diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 20:20:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 20:20:12 -0700 |
commit | f5a8eb632b562bd9c16c389f5db3a5260fba4157 (patch) | |
tree | 82687234d772ff8f72a31e598fe16553885c56c9 /drivers | |
parent | c9297d284126b80c9cfd72c690e0da531c99fc48 (diff) | |
parent | dd3b8c329aa270027fba61a02a12600972dc3983 (diff) | |
download | blackbird-op-linux-f5a8eb632b562bd9c16c389f5db3a5260fba4157.tar.gz blackbird-op-linux-f5a8eb632b562bd9c16c389f5db3a5260fba4157.zip |
Merge tag 'arch-removal' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic
Pul removal of obsolete architecture ports from Arnd Bergmann:
"This removes the entire architecture code for blackfin, cris, frv,
m32r, metag, mn10300, score, and tile, including the associated device
drivers.
I have been working with the (former) maintainers for each one to
ensure that my interpretation was right and the code is definitely
unused in mainline kernels. Many had fond memories of working on the
respective ports to start with and getting them included in upstream,
but also saw no point in keeping the port alive without any users.
In the end, it seems that while the eight architectures are extremely
different, they all suffered the same fate: There was one company in
charge of an SoC line, a CPU microarchitecture and a software
ecosystem, which was more costly than licensing newer off-the-shelf
CPU cores from a third party (typically ARM, MIPS, or RISC-V). It
seems that all the SoC product lines are still around, but have not
used the custom CPU architectures for several years at this point. In
contrast, CPU instruction sets that remain popular and have actively
maintained kernel ports tend to all be used across multiple licensees.
[ See the new nds32 port merged in the previous commit for the next
generation of "one company in charge of an SoC line, a CPU
microarchitecture and a software ecosystem" - Linus ]
The removal came out of a discussion that is now documented at
https://lwn.net/Articles/748074/. Unlike the original plans, I'm not
marking any ports as deprecated but remove them all at once after I
made sure that they are all unused. Some architectures (notably tile,
mn10300, and blackfin) are still being shipped in products with old
kernels, but those products will never be updated to newer kernel
releases.
After this series, we still have a few architectures without mainline
gcc support:
- unicore32 and hexagon both have very outdated gcc releases, but the
maintainers promised to work on providing something newer. At least
in case of hexagon, this will only be llvm, not gcc.
- openrisc, risc-v and nds32 are still in the process of finishing
their support or getting it added to mainline gcc in the first
place. They all have patched gcc-7.3 ports that work to some
degree, but complete upstream support won't happen before gcc-8.1.
Csky posted their first kernel patch set last week, their situation
will be similar
[ Palmer Dabbelt points out that RISC-V support is in mainline gcc
since gcc-7, although gcc-7.3.0 is the recommended minimum - Linus ]"
This really says it all:
2498 files changed, 95 insertions(+), 467668 deletions(-)
* tag 'arch-removal' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic: (74 commits)
MAINTAINERS: UNICORE32: Change email account
staging: iio: remove iio-trig-bfin-timer driver
tty: hvc: remove tile driver
tty: remove bfin_jtag_comm and hvc_bfin_jtag drivers
serial: remove tile uart driver
serial: remove m32r_sio driver
serial: remove blackfin drivers
serial: remove cris/etrax uart drivers
usb: Remove Blackfin references in USB support
usb: isp1362: remove blackfin arch glue
usb: musb: remove blackfin port
usb: host: remove tilegx platform glue
pwm: remove pwm-bfin driver
i2c: remove bfin-twi driver
spi: remove blackfin related host drivers
watchdog: remove bfin_wdt driver
can: remove bfin_can driver
mmc: remove bfin_sdh driver
input: misc: remove blackfin rotary driver
input: keyboard: remove bf54x driver
...
Diffstat (limited to 'drivers')
167 files changed, 43 insertions, 49696 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index a7120d621154..4582fa27cf37 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -549,15 +549,6 @@ config PATA_ATP867X If unsure, say N. -config PATA_BF54X - tristate "Blackfin 54x ATAPI support" - depends on BF542 || BF548 || BF549 - help - This option enables support for the built-in ATAPI controller on - Blackfin 54x family chips. - - If unsure, say N. - config PATA_BK3710 tristate "Palmchip BK3710 PATA support" depends on ARCH_DAVINCI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index f1f5a3fbc777..6dae8c985e8e 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -53,7 +53,6 @@ obj-$(CONFIG_PATA_AMD) += pata_amd.o obj-$(CONFIG_PATA_ARTOP) += pata_artop.o obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o -obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c deleted file mode 100644 index 0e55a8da2748..000000000000 --- a/drivers/ata/pata_bf54x.c +++ /dev/null @@ -1,1703 +0,0 @@ -/* - * File: drivers/ata/pata_bf54x.c - * Author: Sonic Zhang <sonic.zhang@analog.com> - * - * Created: - * Description: PATA Driver for blackfin 54x - * - * Modified: - * Copyright 2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/blkdev.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <scsi/scsi_host.h> -#include <linux/libata.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <asm/dma.h> -#include <asm/portmux.h> - -#define DRV_NAME "pata-bf54x" -#define DRV_VERSION "0.9" - -#define ATA_REG_CTRL 0x0E -#define ATA_REG_ALTSTATUS ATA_REG_CTRL - -/* These are the offset of the controller's registers */ -#define ATAPI_OFFSET_CONTROL 0x00 -#define ATAPI_OFFSET_STATUS 0x04 -#define ATAPI_OFFSET_DEV_ADDR 0x08 -#define ATAPI_OFFSET_DEV_TXBUF 0x0c -#define ATAPI_OFFSET_DEV_RXBUF 0x10 -#define ATAPI_OFFSET_INT_MASK 0x14 -#define ATAPI_OFFSET_INT_STATUS 0x18 -#define ATAPI_OFFSET_XFER_LEN 0x1c -#define ATAPI_OFFSET_LINE_STATUS 0x20 -#define ATAPI_OFFSET_SM_STATE 0x24 -#define ATAPI_OFFSET_TERMINATE 0x28 -#define ATAPI_OFFSET_PIO_TFRCNT 0x2c -#define ATAPI_OFFSET_DMA_TFRCNT 0x30 -#define ATAPI_OFFSET_UMAIN_TFRCNT 0x34 -#define ATAPI_OFFSET_UDMAOUT_TFRCNT 0x38 -#define ATAPI_OFFSET_REG_TIM_0 0x40 -#define ATAPI_OFFSET_PIO_TIM_0 0x44 -#define ATAPI_OFFSET_PIO_TIM_1 0x48 -#define ATAPI_OFFSET_MULTI_TIM_0 0x50 -#define ATAPI_OFFSET_MULTI_TIM_1 0x54 -#define ATAPI_OFFSET_MULTI_TIM_2 0x58 -#define ATAPI_OFFSET_ULTRA_TIM_0 0x60 -#define ATAPI_OFFSET_ULTRA_TIM_1 0x64 -#define ATAPI_OFFSET_ULTRA_TIM_2 0x68 -#define ATAPI_OFFSET_ULTRA_TIM_3 0x6c - - -#define ATAPI_GET_CONTROL(base)\ - bfin_read16(base + ATAPI_OFFSET_CONTROL) -#define ATAPI_SET_CONTROL(base, val)\ - bfin_write16(base + ATAPI_OFFSET_CONTROL, val) -#define ATAPI_GET_STATUS(base)\ - bfin_read16(base + ATAPI_OFFSET_STATUS) -#define ATAPI_GET_DEV_ADDR(base)\ - bfin_read16(base + ATAPI_OFFSET_DEV_ADDR) -#define ATAPI_SET_DEV_ADDR(base, val)\ - bfin_write16(base + ATAPI_OFFSET_DEV_ADDR, val) -#define ATAPI_GET_DEV_TXBUF(base)\ - bfin_read16(base + ATAPI_OFFSET_DEV_TXBUF) -#define ATAPI_SET_DEV_TXBUF(base, val)\ - bfin_write16(base + ATAPI_OFFSET_DEV_TXBUF, val) -#define ATAPI_GET_DEV_RXBUF(base)\ - bfin_read16(base + ATAPI_OFFSET_DEV_RXBUF) -#define ATAPI_SET_DEV_RXBUF(base, val)\ - bfin_write16(base + ATAPI_OFFSET_DEV_RXBUF, val) -#define ATAPI_GET_INT_MASK(base)\ - bfin_read16(base + ATAPI_OFFSET_INT_MASK) -#define ATAPI_SET_INT_MASK(base, val)\ - bfin_write16(base + ATAPI_OFFSET_INT_MASK, val) -#define ATAPI_GET_INT_STATUS(base)\ - bfin_read16(base + ATAPI_OFFSET_INT_STATUS) -#define ATAPI_SET_INT_STATUS(base, val)\ - bfin_write16(base + ATAPI_OFFSET_INT_STATUS, val) -#define ATAPI_GET_XFER_LEN(base)\ - bfin_read16(base + ATAPI_OFFSET_XFER_LEN) -#define ATAPI_SET_XFER_LEN(base, val)\ - bfin_write16(base + ATAPI_OFFSET_XFER_LEN, val) -#define ATAPI_GET_LINE_STATUS(base)\ - bfin_read16(base + ATAPI_OFFSET_LINE_STATUS) -#define ATAPI_GET_SM_STATE(base)\ - bfin_read16(base + ATAPI_OFFSET_SM_STATE) -#define ATAPI_GET_TERMINATE(base)\ - bfin_read16(base + ATAPI_OFFSET_TERMINATE) -#define ATAPI_SET_TERMINATE(base, val)\ - bfin_write16(base + ATAPI_OFFSET_TERMINATE, val) -#define ATAPI_GET_PIO_TFRCNT(base)\ - bfin_read16(base + ATAPI_OFFSET_PIO_TFRCNT) -#define ATAPI_GET_DMA_TFRCNT(base)\ - bfin_read16(base + ATAPI_OFFSET_DMA_TFRCNT) -#define ATAPI_GET_UMAIN_TFRCNT(base)\ - bfin_read16(base + ATAPI_OFFSET_UMAIN_TFRCNT) -#define ATAPI_GET_UDMAOUT_TFRCNT(base)\ - bfin_read16(base + ATAPI_OFFSET_UDMAOUT_TFRCNT) -#define ATAPI_GET_REG_TIM_0(base)\ - bfin_read16(base + ATAPI_OFFSET_REG_TIM_0) -#define ATAPI_SET_REG_TIM_0(base, val)\ - bfin_write16(base + ATAPI_OFFSET_REG_TIM_0, val) -#define ATAPI_GET_PIO_TIM_0(base)\ - bfin_read16(base + ATAPI_OFFSET_PIO_TIM_0) -#define ATAPI_SET_PIO_TIM_0(base, val)\ - bfin_write16(base + ATAPI_OFFSET_PIO_TIM_0, val) -#define ATAPI_GET_PIO_TIM_1(base)\ - bfin_read16(base + ATAPI_OFFSET_PIO_TIM_1) -#define ATAPI_SET_PIO_TIM_1(base, val)\ - bfin_write16(base + ATAPI_OFFSET_PIO_TIM_1, val) -#define ATAPI_GET_MULTI_TIM_0(base)\ - bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_0) -#define ATAPI_SET_MULTI_TIM_0(base, val)\ - bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_0, val) -#define ATAPI_GET_MULTI_TIM_1(base)\ - bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_1) -#define ATAPI_SET_MULTI_TIM_1(base, val)\ - bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_1, val) -#define ATAPI_GET_MULTI_TIM_2(base)\ - bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_2) -#define ATAPI_SET_MULTI_TIM_2(base, val)\ - bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_2, val) -#define ATAPI_GET_ULTRA_TIM_0(base)\ - bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_0) -#define ATAPI_SET_ULTRA_TIM_0(base, val)\ - bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_0, val) -#define ATAPI_GET_ULTRA_TIM_1(base)\ - bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_1) -#define ATAPI_SET_ULTRA_TIM_1(base, val)\ - bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_1, val) -#define ATAPI_GET_ULTRA_TIM_2(base)\ - bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_2) -#define ATAPI_SET_ULTRA_TIM_2(base, val)\ - bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_2, val) -#define ATAPI_GET_ULTRA_TIM_3(base)\ - bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_3) -#define ATAPI_SET_ULTRA_TIM_3(base, val)\ - bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_3, val) - -/** - * PIO Mode - Frequency compatibility - */ -/* mode: 0 1 2 3 4 */ -static const u32 pio_fsclk[] = -{ 33333333, 33333333, 33333333, 33333333, 33333333 }; - -/** - * MDMA Mode - Frequency compatibility - */ -/* mode: 0 1 2 */ -static const u32 mdma_fsclk[] = { 33333333, 33333333, 33333333 }; - -/** - * UDMA Mode - Frequency compatibility - * - * UDMA5 - 100 MB/s - SCLK = 133 MHz - * UDMA4 - 66 MB/s - SCLK >= 80 MHz - * UDMA3 - 44.4 MB/s - SCLK >= 50 MHz - * UDMA2 - 33 MB/s - SCLK >= 40 MHz - */ -/* mode: 0 1 2 3 4 5 */ -static const u32 udma_fsclk[] = -{ 33333333, 33333333, 40000000, 50000000, 80000000, 133333333 }; - -/** - * Register transfer timing table - */ -/* mode: 0 1 2 3 4 */ -/* Cycle Time */ -static const u32 reg_t0min[] = { 600, 383, 330, 180, 120 }; -/* DIOR/DIOW to end cycle */ -static const u32 reg_t2min[] = { 290, 290, 290, 70, 25 }; -/* DIOR/DIOW asserted pulse width */ -static const u32 reg_teocmin[] = { 290, 290, 290, 80, 70 }; - -/** - * PIO timing table - */ -/* mode: 0 1 2 3 4 */ -/* Cycle Time */ -static const u32 pio_t0min[] = { 600, 383, 240, 180, 120 }; -/* Address valid to DIOR/DIORW */ -static const u32 pio_t1min[] = { 70, 50, 30, 30, 25 }; -/* DIOR/DIOW to end cycle */ -static const u32 pio_t2min[] = { 165, 125, 100, 80, 70 }; -/* DIOR/DIOW asserted pulse width */ -static const u32 pio_teocmin[] = { 165, 125, 100, 70, 25 }; -/* DIOW data hold */ -static const u32 pio_t4min[] = { 30, 20, 15, 10, 10 }; - -/* ****************************************************************** - * Multiword DMA timing table - * ****************************************************************** - */ -/* mode: 0 1 2 */ -/* Cycle Time */ -static const u32 mdma_t0min[] = { 480, 150, 120 }; -/* DIOR/DIOW asserted pulse width */ -static const u32 mdma_tdmin[] = { 215, 80, 70 }; -/* DMACK to read data released */ -static const u32 mdma_thmin[] = { 20, 15, 10 }; -/* DIOR/DIOW to DMACK hold */ -static const u32 mdma_tjmin[] = { 20, 5, 5 }; -/* DIOR negated pulse width */ -static const u32 mdma_tkrmin[] = { 50, 50, 25 }; -/* DIOR negated pulse width */ -static const u32 mdma_tkwmin[] = { 215, 50, 25 }; -/* CS[1:0] valid to DIOR/DIOW */ -static const u32 mdma_tmmin[] = { 50, 30, 25 }; -/* DMACK to read data released */ -static const u32 mdma_tzmax[] = { 20, 25, 25 }; - -/** - * Ultra DMA timing table - */ -/* mode: 0 1 2 3 4 5 */ -static const u32 udma_tcycmin[] = { 112, 73, 54, 39, 25, 17 }; -static const u32 udma_tdvsmin[] = { 70, 48, 31, 20, 7, 5 }; -static const u32 udma_tenvmax[] = { 70, 70, 70, 55, 55, 50 }; -static const u32 udma_trpmin[] = { 160, 125, 100, 100, 100, 85 }; -static const u32 udma_tmin[] = { 5, 5, 5, 5, 3, 3 }; - - -static const u32 udma_tmlimin = 20; -static const u32 udma_tzahmin = 20; -static const u32 udma_tenvmin = 20; -static const u32 udma_tackmin = 20; -static const u32 udma_tssmin = 50; - -#define BFIN_MAX_SG_SEGMENTS 4 - -/** - * - * Function: num_clocks_min - * - * Description: - * calculate number of SCLK cycles to meet minimum timing - */ -static unsigned short num_clocks_min(unsigned long tmin, - unsigned long fsclk) -{ - unsigned long tmp ; - unsigned short result; - - tmp = tmin * (fsclk/1000/1000) / 1000; - result = (unsigned short)tmp; - if ((tmp*1000*1000) < (tmin*(fsclk/1000))) { - result++; - } - - return result; -} - -/** - * bfin_set_piomode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set PIO mode for device. - * - * LOCKING: - * None (inherited from caller). - */ - -static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - int mode = adev->pio_mode - XFER_PIO_0; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned int fsclk = get_sclk(); - unsigned short teoc_reg, t2_reg, teoc_pio; - unsigned short t4_reg, t2_pio, t1_reg; - unsigned short n0, n6, t6min = 5; - - /* the most restrictive timing value is t6 and tc, the DIOW - data hold - * If one SCLK pulse is longer than this minimum value then register - * transfers cannot be supported at this frequency. - */ - n6 = num_clocks_min(t6min, fsclk); - if (mode >= 0 && mode <= 4 && n6 >= 1) { - dev_dbg(adev->link->ap->dev, "set piomode: mode=%d, fsclk=%ud\n", mode, fsclk); - /* calculate the timing values for register transfers. */ - while (mode > 0 && pio_fsclk[mode] > fsclk) - mode--; - - /* DIOR/DIOW to end cycle time */ - t2_reg = num_clocks_min(reg_t2min[mode], fsclk); - /* DIOR/DIOW asserted pulse width */ - teoc_reg = num_clocks_min(reg_teocmin[mode], fsclk); - /* Cycle Time */ - n0 = num_clocks_min(reg_t0min[mode], fsclk); - - /* increase t2 until we meed the minimum cycle length */ - if (t2_reg + teoc_reg < n0) - t2_reg = n0 - teoc_reg; - - /* calculate the timing values for pio transfers. */ - - /* DIOR/DIOW to end cycle time */ - t2_pio = num_clocks_min(pio_t2min[mode], fsclk); - /* DIOR/DIOW asserted pulse width */ - teoc_pio = num_clocks_min(pio_teocmin[mode], fsclk); - /* Cycle Time */ - n0 = num_clocks_min(pio_t0min[mode], fsclk); - - /* increase t2 until we meed the minimum cycle length */ - if (t2_pio + teoc_pio < n0) - t2_pio = n0 - teoc_pio; - - /* Address valid to DIOR/DIORW */ - t1_reg = num_clocks_min(pio_t1min[mode], fsclk); - - /* DIOW data hold */ - t4_reg = num_clocks_min(pio_t4min[mode], fsclk); - - ATAPI_SET_REG_TIM_0(base, (teoc_reg<<8 | t2_reg)); - ATAPI_SET_PIO_TIM_0(base, (t4_reg<<12 | t2_pio<<4 | t1_reg)); - ATAPI_SET_PIO_TIM_1(base, teoc_pio); - if (mode > 2) { - ATAPI_SET_CONTROL(base, - ATAPI_GET_CONTROL(base) | IORDY_EN); - } else { - ATAPI_SET_CONTROL(base, - ATAPI_GET_CONTROL(base) & ~IORDY_EN); - } - - /* Disable host ATAPI PIO interrupts */ - ATAPI_SET_INT_MASK(base, ATAPI_GET_INT_MASK(base) - & ~(PIO_DONE_MASK | HOST_TERM_XFER_MASK)); - SSYNC(); - } -} - -/** - * bfin_set_dmamode - Initialize host controller PATA DMA timings - * @ap: Port whose timings we are configuring - * @adev: um - * - * Set UDMA mode for device. - * - * LOCKING: - * None (inherited from caller). - */ - -static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev) -{ - int mode; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned long fsclk = get_sclk(); - unsigned short tenv, tack, tcyc_tdvs, tdvs, tmli, tss, trp, tzah; - unsigned short tm, td, tkr, tkw, teoc, th; - unsigned short n0, nf, tfmin = 5; - unsigned short nmin, tcyc; - - mode = adev->dma_mode - XFER_UDMA_0; - if (mode >= 0 && mode <= 5) { - dev_dbg(adev->link->ap->dev, "set udmamode: mode=%d\n", mode); - /* the most restrictive timing value is t6 and tc, - * the DIOW - data hold. If one SCLK pulse is longer - * than this minimum value then register - * transfers cannot be supported at this frequency. - */ - while (mode > 0 && udma_fsclk[mode] > fsclk) - mode--; - - nmin = num_clocks_min(udma_tmin[mode], fsclk); - if (nmin >= 1) { - /* calculate the timing values for Ultra DMA. */ - tdvs = num_clocks_min(udma_tdvsmin[mode], fsclk); - tcyc = num_clocks_min(udma_tcycmin[mode], fsclk); - tcyc_tdvs = 2; - - /* increase tcyc - tdvs (tcyc_tdvs) until we meed - * the minimum cycle length - */ - if (tdvs + tcyc_tdvs < tcyc) - tcyc_tdvs = tcyc - tdvs; - - /* Mow assign the values required for the timing - * registers - */ - if (tcyc_tdvs < 2) - tcyc_tdvs = 2; - - if (tdvs < 2) - tdvs = 2; - - tack = num_clocks_min(udma_tackmin, fsclk); - tss = num_clocks_min(udma_tssmin, fsclk); - tmli = num_clocks_min(udma_tmlimin, fsclk); - tzah = num_clocks_min(udma_tzahmin, fsclk); - trp = num_clocks_min(udma_trpmin[mode], fsclk); - tenv = num_clocks_min(udma_tenvmin, fsclk); - if (tenv <= udma_tenvmax[mode]) { - ATAPI_SET_ULTRA_TIM_0(base, (tenv<<8 | tack)); - ATAPI_SET_ULTRA_TIM_1(base, - (tcyc_tdvs<<8 | tdvs)); - ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss)); - ATAPI_SET_ULTRA_TIM_3(base, (trp<<8 | tzah)); - } - } - } - - mode = adev->dma_mode - XFER_MW_DMA_0; - if (mode >= 0 && mode <= 2) { - dev_dbg(adev->link->ap->dev, "set mdmamode: mode=%d\n", mode); - /* the most restrictive timing value is tf, the DMACK to - * read data released. If one SCLK pulse is longer than - * this maximum value then the MDMA mode - * cannot be supported at this frequency. - */ - while (mode > 0 && mdma_fsclk[mode] > fsclk) - mode--; - - nf = num_clocks_min(tfmin, fsclk); - if (nf >= 1) { - /* calculate the timing values for Multi-word DMA. */ - - /* DIOR/DIOW asserted pulse width */ - td = num_clocks_min(mdma_tdmin[mode], fsclk); - - /* DIOR negated pulse width */ - tkw = num_clocks_min(mdma_tkwmin[mode], fsclk); - - /* Cycle Time */ - n0 = num_clocks_min(mdma_t0min[mode], fsclk); - - /* increase tk until we meed the minimum cycle length */ - if (tkw + td < n0) - tkw = n0 - td; - - /* DIOR negated pulse width - read */ - tkr = num_clocks_min(mdma_tkrmin[mode], fsclk); - /* CS{1:0] valid to DIOR/DIOW */ - tm = num_clocks_min(mdma_tmmin[mode], fsclk); - /* DIOR/DIOW to DMACK hold */ - teoc = num_clocks_min(mdma_tjmin[mode], fsclk); - /* DIOW Data hold */ - th = num_clocks_min(mdma_thmin[mode], fsclk); - - ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td)); - ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw)); - ATAPI_SET_MULTI_TIM_2(base, (teoc<<8 | th)); - SSYNC(); - } - } - return; -} - -/** - * - * Function: wait_complete - * - * Description: Waits the interrupt from device - * - */ -static inline void wait_complete(void __iomem *base, unsigned short mask) -{ - unsigned short status; - unsigned int i = 0; - -#define PATA_BF54X_WAIT_TIMEOUT 10000 - - for (i = 0; i < PATA_BF54X_WAIT_TIMEOUT; i++) { - status = ATAPI_GET_INT_STATUS(base) & mask; - if (status) - break; - } - - ATAPI_SET_INT_STATUS(base, mask); -} - -/** - * - * Function: write_atapi_register - * - * Description: Writes to ATA Device Resgister - * - */ - -static void write_atapi_register(void __iomem *base, - unsigned long ata_reg, unsigned short value) -{ - /* Program the ATA_DEV_TXBUF register with write data (to be - * written into the device). - */ - ATAPI_SET_DEV_TXBUF(base, value); - - /* Program the ATA_DEV_ADDR register with address of the - * device register (0x01 to 0x0F). - */ - ATAPI_SET_DEV_ADDR(base, ata_reg); - - /* Program the ATA_CTRL register with dir set to write (1) - */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR)); - - /* ensure PIO DMA is not set */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA)); - - /* and start the transfer */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START)); - - /* Wait for the interrupt to indicate the end of the transfer. - * (We need to wait on and clear rhe ATA_DEV_INT interrupt status) - */ - wait_complete(base, PIO_DONE_INT); -} - -/** - * - * Function: read_atapi_register - * - *Description: Reads from ATA Device Resgister - * - */ - -static unsigned short read_atapi_register(void __iomem *base, - unsigned long ata_reg) -{ - /* Program the ATA_DEV_ADDR register with address of the - * device register (0x01 to 0x0F). - */ - ATAPI_SET_DEV_ADDR(base, ata_reg); - - /* Program the ATA_CTRL register with dir set to read (0) and - */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR)); - - /* ensure PIO DMA is not set */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA)); - - /* and start the transfer */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START)); - - /* Wait for the interrupt to indicate the end of the transfer. - * (PIO_DONE interrupt is set and it doesn't seem to matter - * that we don't clear it) - */ - wait_complete(base, PIO_DONE_INT); - - /* Read the ATA_DEV_RXBUF register with write data (to be - * written into the device). - */ - return ATAPI_GET_DEV_RXBUF(base); -} - -/** - * - * Function: write_atapi_register_data - * - * Description: Writes to ATA Device Resgister - * - */ - -static void write_atapi_data(void __iomem *base, - int len, unsigned short *buf) -{ - int i; - - /* Set transfer length to 1 */ - ATAPI_SET_XFER_LEN(base, 1); - - /* Program the ATA_DEV_ADDR register with address of the - * ATA_REG_DATA - */ - ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA); - - /* Program the ATA_CTRL register with dir set to write (1) - */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR)); - - /* ensure PIO DMA is not set */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA)); - - for (i = 0; i < len; i++) { - /* Program the ATA_DEV_TXBUF register with write data (to be - * written into the device). - */ - ATAPI_SET_DEV_TXBUF(base, buf[i]); - - /* and start the transfer */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START)); - - /* Wait for the interrupt to indicate the end of the transfer. - * (We need to wait on and clear rhe ATA_DEV_INT - * interrupt status) - */ - wait_complete(base, PIO_DONE_INT); - } -} - -/** - * - * Function: read_atapi_register_data - * - * Description: Reads from ATA Device Resgister - * - */ - -static void read_atapi_data(void __iomem *base, - int len, unsigned short *buf) -{ - int i; - - /* Set transfer length to 1 */ - ATAPI_SET_XFER_LEN(base, 1); - - /* Program the ATA_DEV_ADDR register with address of the - * ATA_REG_DATA - */ - ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA); - - /* Program the ATA_CTRL register with dir set to read (0) and - */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR)); - - /* ensure PIO DMA is not set */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA)); - - for (i = 0; i < len; i++) { - /* and start the transfer */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START)); - - /* Wait for the interrupt to indicate the end of the transfer. - * (PIO_DONE interrupt is set and it doesn't seem to matter - * that we don't clear it) - */ - wait_complete(base, PIO_DONE_INT); - - /* Read the ATA_DEV_RXBUF register with write data (to be - * written into the device). - */ - buf[i] = ATAPI_GET_DEV_RXBUF(base); - } -} - -/** - * bfin_tf_load - send taskfile registers to host controller - * @ap: Port to which output is sent - * @tf: ATA taskfile register set - * - * Note: Original code is ata_sff_tf_load(). - */ - -static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - write_atapi_register(base, ATA_REG_CTRL, tf->ctl); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - - if (is_addr) { - if (tf->flags & ATA_TFLAG_LBA48) { - write_atapi_register(base, ATA_REG_FEATURE, - tf->hob_feature); - write_atapi_register(base, ATA_REG_NSECT, - tf->hob_nsect); - write_atapi_register(base, ATA_REG_LBAL, tf->hob_lbal); - write_atapi_register(base, ATA_REG_LBAM, tf->hob_lbam); - write_atapi_register(base, ATA_REG_LBAH, tf->hob_lbah); - dev_dbg(ap->dev, "hob: feat 0x%X nsect 0x%X, lba 0x%X " - "0x%X 0x%X\n", - tf->hob_feature, - tf->hob_nsect, - tf->hob_lbal, - tf->hob_lbam, - tf->hob_lbah); - } - - write_atapi_register(base, ATA_REG_FEATURE, tf->feature); - write_atapi_register(base, ATA_REG_NSECT, tf->nsect); - write_atapi_register(base, ATA_REG_LBAL, tf->lbal); - write_atapi_register(base, ATA_REG_LBAM, tf->lbam); - write_atapi_register(base, ATA_REG_LBAH, tf->lbah); - dev_dbg(ap->dev, "feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", - tf->feature, - tf->nsect, - tf->lbal, - tf->lbam, - tf->lbah); - } - - if (tf->flags & ATA_TFLAG_DEVICE) { - write_atapi_register(base, ATA_REG_DEVICE, tf->device); - dev_dbg(ap->dev, "device 0x%X\n", tf->device); - } - - ata_wait_idle(ap); -} - -/** - * bfin_check_status - Read device status reg & clear interrupt - * @ap: port where the device is - * - * Note: Original code is ata_check_status(). - */ - -static u8 bfin_check_status(struct ata_port *ap) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - return read_atapi_register(base, ATA_REG_STATUS); -} - -/** - * bfin_tf_read - input device's ATA taskfile shadow registers - * @ap: Port from which input is read - * @tf: ATA taskfile register set for storing input - * - * Note: Original code is ata_sff_tf_read(). - */ - -static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - tf->command = bfin_check_status(ap); - tf->feature = read_atapi_register(base, ATA_REG_ERR); - tf->nsect = read_atapi_register(base, ATA_REG_NSECT); - tf->lbal = read_atapi_register(base, ATA_REG_LBAL); - tf->lbam = read_atapi_register(base, ATA_REG_LBAM); - tf->lbah = read_atapi_register(base, ATA_REG_LBAH); - tf->device = read_atapi_register(base, ATA_REG_DEVICE); - - if (tf->flags & ATA_TFLAG_LBA48) { - write_atapi_register(base, ATA_REG_CTRL, tf->ctl | ATA_HOB); - tf->hob_feature = read_atapi_register(base, ATA_REG_ERR); - tf->hob_nsect = read_atapi_register(base, ATA_REG_NSECT); - tf->hob_lbal = read_atapi_register(base, ATA_REG_LBAL); - tf->hob_lbam = read_atapi_register(base, ATA_REG_LBAM); - tf->hob_lbah = read_atapi_register(base, ATA_REG_LBAH); - } -} - -/** - * bfin_exec_command - issue ATA command to host controller - * @ap: port to which command is being issued - * @tf: ATA taskfile register set - * - * Note: Original code is ata_sff_exec_command(). - */ - -static void bfin_exec_command(struct ata_port *ap, - const struct ata_taskfile *tf) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command); - - write_atapi_register(base, ATA_REG_CMD, tf->command); - ata_sff_pause(ap); -} - -/** - * bfin_check_altstatus - Read device alternate status reg - * @ap: port where the device is - */ - -static u8 bfin_check_altstatus(struct ata_port *ap) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - return read_atapi_register(base, ATA_REG_ALTSTATUS); -} - -/** - * bfin_dev_select - Select device 0/1 on ATA bus - * @ap: ATA channel to manipulate - * @device: ATA device (numbered from zero) to select - * - * Note: Original code is ata_sff_dev_select(). - */ - -static void bfin_dev_select(struct ata_port *ap, unsigned int device) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - u8 tmp; - - if (device == 0) - tmp = ATA_DEVICE_OBS; - else - tmp = ATA_DEVICE_OBS | ATA_DEV1; - - write_atapi_register(base, ATA_REG_DEVICE, tmp); - ata_sff_pause(ap); -} - -/** - * bfin_set_devctl - Write device control reg - * @ap: port where the device is - * @ctl: value to write - */ - -static void bfin_set_devctl(struct ata_port *ap, u8 ctl) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - write_atapi_register(base, ATA_REG_CTRL, ctl); -} - -/** - * bfin_bmdma_setup - Set up IDE DMA transaction - * @qc: Info associated with this ATA transaction. - * - * Note: Original code is ata_bmdma_setup(). - */ - -static void bfin_bmdma_setup(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct dma_desc_array *dma_desc_cpu = (struct dma_desc_array *)ap->bmdma_prd; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned short config = DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_16 | DMAEN; - struct scatterlist *sg; - unsigned int si; - unsigned int channel; - unsigned int dir; - unsigned int size = 0; - - dev_dbg(qc->ap->dev, "in atapi dma setup\n"); - /* Program the ATA_CTRL register with dir */ - if (qc->tf.flags & ATA_TFLAG_WRITE) { - channel = CH_ATAPI_TX; - dir = DMA_TO_DEVICE; - } else { - channel = CH_ATAPI_RX; - dir = DMA_FROM_DEVICE; - config |= WNR; - } - - dma_map_sg(ap->dev, qc->sg, qc->n_elem, dir); - - /* fill the ATAPI DMA controller */ - for_each_sg(qc->sg, sg, qc->n_elem, si) { - dma_desc_cpu[si].start_addr = sg_dma_address(sg); - dma_desc_cpu[si].cfg = config; - dma_desc_cpu[si].x_count = sg_dma_len(sg) >> 1; - dma_desc_cpu[si].x_modify = 2; - size += sg_dma_len(sg); - } - - /* Set the last descriptor to stop mode */ - dma_desc_cpu[qc->n_elem - 1].cfg &= ~(DMAFLOW | NDSIZE); - - flush_dcache_range((unsigned int)dma_desc_cpu, - (unsigned int)dma_desc_cpu + - qc->n_elem * sizeof(struct dma_desc_array)); - - /* Enable ATA DMA operation*/ - set_dma_curr_desc_addr(channel, (unsigned long *)ap->bmdma_prd_dma); - set_dma_x_count(channel, 0); - set_dma_x_modify(channel, 0); - set_dma_config(channel, config); - - SSYNC(); - - /* Send ATA DMA command */ - bfin_exec_command(ap, &qc->tf); - - if (qc->tf.flags & ATA_TFLAG_WRITE) { - /* set ATA DMA write direction */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) - | XFER_DIR)); - } else { - /* set ATA DMA read direction */ - ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) - & ~XFER_DIR)); - } - - /* Reset all transfer count */ - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST); - - /* Set ATAPI state machine contorl in terminate sequence */ - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM); - - /* Set transfer length to the total size of sg buffers */ - ATAPI_SET_XFER_LEN(base, size >> 1); -} - -/** - * bfin_bmdma_start - Start an IDE DMA transaction - * @qc: Info associated with this ATA transaction. - * - * Note: Original code is ata_bmdma_start(). - */ - -static void bfin_bmdma_start(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - dev_dbg(qc->ap->dev, "in atapi dma start\n"); - - if (!(ap->udma_mask || ap->mwdma_mask)) - return; - - /* start ATAPI transfer*/ - if (ap->udma_mask) - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) - | ULTRA_START); - else - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) - | MULTI_START); -} - -/** - * bfin_bmdma_stop - Stop IDE DMA transfer - * @qc: Command we are ending DMA for - */ - -static void bfin_bmdma_stop(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int dir; - - dev_dbg(qc->ap->dev, "in atapi dma stop\n"); - - if (!(ap->udma_mask || ap->mwdma_mask)) - return; - - /* stop ATAPI DMA controller*/ - if (qc->tf.flags & ATA_TFLAG_WRITE) { - dir = DMA_TO_DEVICE; - disable_dma(CH_ATAPI_TX); - } else { - dir = DMA_FROM_DEVICE; - disable_dma(CH_ATAPI_RX); - } - - dma_unmap_sg(ap->dev, qc->sg, qc->n_elem, dir); -} - -/** - * bfin_devchk - PATA device presence detection - * @ap: ATA channel to examine - * @device: Device to examine (starting at zero) - * - * Note: Original code is ata_devchk(). - */ - -static unsigned int bfin_devchk(struct ata_port *ap, - unsigned int device) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - u8 nsect, lbal; - - bfin_dev_select(ap, device); - - write_atapi_register(base, ATA_REG_NSECT, 0x55); - write_atapi_register(base, ATA_REG_LBAL, 0xaa); - - write_atapi_register(base, ATA_REG_NSECT, 0xaa); - write_atapi_register(base, ATA_REG_LBAL, 0x55); - - write_atapi_register(base, ATA_REG_NSECT, 0x55); - write_atapi_register(base, ATA_REG_LBAL, 0xaa); - - nsect = read_atapi_register(base, ATA_REG_NSECT); - lbal = read_atapi_register(base, ATA_REG_LBAL); - - if ((nsect == 0x55) && (lbal == 0xaa)) - return 1; /* we found a device */ - - return 0; /* nothing found */ -} - -/** - * bfin_bus_post_reset - PATA device post reset - * - * Note: Original code is ata_bus_post_reset(). - */ - -static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned int dev0 = devmask & (1 << 0); - unsigned int dev1 = devmask & (1 << 1); - unsigned long deadline; - - /* if device 0 was found in ata_devchk, wait for its - * BSY bit to clear - */ - if (dev0) - ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); - - /* if device 1 was found in ata_devchk, wait for - * register access, then wait for BSY to clear - */ - deadline = ata_deadline(jiffies, ATA_TMOUT_BOOT); - while (dev1) { - u8 nsect, lbal; - - bfin_dev_select(ap, 1); - nsect = read_atapi_register(base, ATA_REG_NSECT); - lbal = read_atapi_register(base, ATA_REG_LBAL); - if ((nsect == 1) && (lbal == 1)) - break; - if (time_after(jiffies, deadline)) { - dev1 = 0; - break; - } - ata_msleep(ap, 50); /* give drive a breather */ - } - if (dev1) - ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); - - /* is all this really necessary? */ - bfin_dev_select(ap, 0); - if (dev1) - bfin_dev_select(ap, 1); - if (dev0) - bfin_dev_select(ap, 0); -} - -/** - * bfin_bus_softreset - PATA device software reset - * - * Note: Original code is ata_bus_softreset(). - */ - -static unsigned int bfin_bus_softreset(struct ata_port *ap, - unsigned int devmask) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - /* software reset. causes dev0 to be selected */ - write_atapi_register(base, ATA_REG_CTRL, ap->ctl); - udelay(20); - write_atapi_register(base, ATA_REG_CTRL, ap->ctl | ATA_SRST); - udelay(20); - write_atapi_register(base, ATA_REG_CTRL, ap->ctl); - - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - * - * Old drivers/ide uses the 2mS rule and then waits for ready - */ - ata_msleep(ap, 150); - - /* Before we perform post reset processing we want to see if - * the bus shows 0xFF because the odd clown forgets the D7 - * pulldown resistor. - */ - if (bfin_check_status(ap) == 0xFF) - return 0; - - bfin_bus_post_reset(ap, devmask); - - return 0; -} - -/** - * bfin_softreset - reset host port via ATA SRST - * @ap: port to reset - * @classes: resulting classes of attached devices - * - * Note: Original code is ata_sff_softreset(). - */ - -static int bfin_softreset(struct ata_link *link, unsigned int *classes, - unsigned long deadline) -{ - struct ata_port *ap = link->ap; - unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; - unsigned int devmask = 0, err_mask; - u8 err; - - /* determine if device 0/1 are present */ - if (bfin_devchk(ap, 0)) - devmask |= (1 << 0); - if (slave_possible && bfin_devchk(ap, 1)) - devmask |= (1 << 1); - - /* select device 0 again */ - bfin_dev_select(ap, 0); - - /* issue bus reset */ - err_mask = bfin_bus_softreset(ap, devmask); - if (err_mask) { - ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", - err_mask); - return -EIO; - } - - /* determine by signature whether we have ATA or ATAPI devices */ - classes[0] = ata_sff_dev_classify(&ap->link.device[0], - devmask & (1 << 0), &err); - if (slave_possible && err != 0x81) - classes[1] = ata_sff_dev_classify(&ap->link.device[1], - devmask & (1 << 1), &err); - - return 0; -} - -/** - * bfin_bmdma_status - Read IDE DMA status - * @ap: Port associated with this ATA transaction. - */ - -static unsigned char bfin_bmdma_status(struct ata_port *ap) -{ - unsigned char host_stat = 0; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON | ULTRA_XFER_ON)) - host_stat |= ATA_DMA_ACTIVE; - if (ATAPI_GET_INT_STATUS(base) & ATAPI_DEV_INT) - host_stat |= ATA_DMA_INTR; - - dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat); - - return host_stat; -} - -/** - * bfin_data_xfer - Transfer data by PIO - * @qc: queued command - * @buf: data buffer - * @buflen: buffer length - * @write_data: read/write - * - * Note: Original code is ata_sff_data_xfer(). - */ - -static unsigned int bfin_data_xfer(struct ata_queued_cmd *qc, - unsigned char *buf, - unsigned int buflen, int rw) -{ - struct ata_port *ap = qc->dev->link->ap; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - unsigned int words = buflen >> 1; - unsigned short *buf16 = (u16 *)buf; - - /* Transfer multiple of 2 bytes */ - if (rw == READ) - read_atapi_data(base, words, buf16); - else - write_atapi_data(base, words, buf16); - - /* Transfer trailing 1 byte, if any. */ - if (unlikely(buflen & 0x01)) { - unsigned short align_buf[1] = { 0 }; - unsigned char *trailing_buf = buf + buflen - 1; - - if (rw == READ) { - read_atapi_data(base, 1, align_buf); - memcpy(trailing_buf, align_buf, 1); - } else { - memcpy(align_buf, trailing_buf, 1); - write_atapi_data(base, 1, align_buf); - } - words++; - } - - return words << 1; -} - -/** - * bfin_irq_clear - Clear ATAPI interrupt. - * @ap: Port associated with this ATA transaction. - * - * Note: Original code is ata_bmdma_irq_clear(). - */ - -static void bfin_irq_clear(struct ata_port *ap) -{ - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - dev_dbg(ap->dev, "in atapi irq clear\n"); - ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT - | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT - | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT); -} - -/** - * bfin_thaw - Thaw DMA controller port - * @ap: port to thaw - * - * Note: Original code is ata_sff_thaw(). - */ - -void bfin_thaw(struct ata_port *ap) -{ - dev_dbg(ap->dev, "in atapi dma thaw\n"); - bfin_check_status(ap); - ata_sff_irq_on(ap); -} - -/** - * bfin_postreset - standard postreset callback - * @ap: the target ata_port - * @classes: classes of attached devices - * - * Note: Original code is ata_sff_postreset(). - */ - -static void bfin_postreset(struct ata_link *link, unsigned int *classes) -{ - struct ata_port *ap = link->ap; - void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr; - - /* re-enable interrupts */ - ata_sff_irq_on(ap); - - /* is double-select really necessary? */ - if (classes[0] != ATA_DEV_NONE) - bfin_dev_select(ap, 1); - if (classes[1] != ATA_DEV_NONE) - bfin_dev_select(ap, 0); - - /* bail out if no device is present */ - if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { - return; - } - - /* set up device control */ - write_atapi_register(base, ATA_REG_CTRL, ap->ctl); -} - -static void bfin_port_stop(struct ata_port *ap) -{ - dev_dbg(ap->dev, "in atapi port stop\n"); - if (ap->udma_mask != 0 || ap->mwdma_mask != 0) { - dma_free_coherent(ap->dev, - BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), - ap->bmdma_prd, - ap->bmdma_prd_dma); - - free_dma(CH_ATAPI_RX); - free_dma(CH_ATAPI_TX); - } -} - -static int bfin_port_start(struct ata_port *ap) -{ - dev_dbg(ap->dev, "in atapi port start\n"); - if (!(ap->udma_mask || ap->mwdma_mask)) - return 0; - - ap->bmdma_prd = dma_alloc_coherent(ap->dev, - BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), - &ap->bmdma_prd_dma, - GFP_KERNEL); - - if (ap->bmdma_prd == NULL) { - dev_info(ap->dev, "Unable to allocate DMA descriptor array.\n"); - goto out; - } - - if (request_dma(CH_ATAPI_RX, "BFIN ATAPI RX DMA") >= 0) { - if (request_dma(CH_ATAPI_TX, - "BFIN ATAPI TX DMA") >= 0) - return 0; - - free_dma(CH_ATAPI_RX); - dma_free_coherent(ap->dev, - BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array), - ap->bmdma_prd, - ap->bmdma_prd_dma); - } - -out: - ap->udma_mask = 0; - ap->mwdma_mask = 0; - dev_err(ap->dev, "Unable to request ATAPI DMA!" - " Continue in PIO mode.\n"); - - return 0; -} - -static unsigned int bfin_ata_host_intr(struct ata_port *ap, - struct ata_queued_cmd *qc) -{ - struct ata_eh_info *ehi = &ap->link.eh_info; - u8 status, host_stat = 0; - - VPRINTK("ata%u: protocol %d task_state %d\n", - ap->print_id, qc->tf.protocol, ap->hsm_task_state); - - /* Check whether we are expecting interrupt in this state */ - switch (ap->hsm_task_state) { - case HSM_ST_FIRST: - /* Some pre-ATAPI-4 devices assert INTRQ - * at this state when ready to receive CDB. - */ - - /* Check the ATA_DFLAG_CDB_INTR flag is enough here. - * The flag was turned on only for atapi devices. - * No need to check is_atapi_taskfile(&qc->tf) again. - */ - if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - goto idle_irq; - break; - case HSM_ST_LAST: - if (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATAPI_PROT_DMA) { - /* check status of DMA engine */ - host_stat = ap->ops->bmdma_status(ap); - VPRINTK("ata%u: host_stat 0x%X\n", - ap->print_id, host_stat); - - /* if it's not our irq... */ - if (!(host_stat & ATA_DMA_INTR)) - goto idle_irq; - - /* before we do anything else, clear DMA-Start bit */ - ap->ops->bmdma_stop(qc); - - if (unlikely(host_stat & ATA_DMA_ERR)) { - /* error when transferring data to/from memory */ - qc->err_mask |= AC_ERR_HOST_BUS; - ap->hsm_task_state = HSM_ST_ERR; - } - } - break; - case HSM_ST: - break; - default: - goto idle_irq; - } - - /* check altstatus */ - status = ap->ops->sff_check_altstatus(ap); - if (status & ATA_BUSY) - goto busy_ata; - - /* check main status, clearing INTRQ */ - status = ap->ops->sff_check_status(ap); - if (unlikely(status & ATA_BUSY)) - goto busy_ata; - - /* ack bmdma irq events */ - ap->ops->sff_irq_clear(ap); - - ata_sff_hsm_move(ap, qc, status, 0); - - if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || - qc->tf.protocol == ATAPI_PROT_DMA)) - ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); - -busy_ata: - return 1; /* irq handled */ - -idle_irq: - ap->stats.idle_irq++; - -#ifdef ATA_IRQ_TRAP - if ((ap->stats.idle_irq % 1000) == 0) { - ap->ops->irq_ack(ap, 0); /* debug trap */ - ata_port_warn(ap, "irq trap\n"); - return 1; - } -#endif - return 0; /* irq not handled */ -} - -static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance) -{ - struct ata_host *host = dev_instance; - unsigned int i; - unsigned int handled = 0; - unsigned long flags; - - /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ - spin_lock_irqsave(&host->lock, flags); - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) - handled |= bfin_ata_host_intr(ap, qc); - } - - spin_unlock_irqrestore(&host->lock, flags); - - return IRQ_RETVAL(handled); -} - - -static struct scsi_host_template bfin_sht = { - ATA_BASE_SHT(DRV_NAME), - .sg_tablesize = BFIN_MAX_SG_SEGMENTS, - .dma_boundary = ATA_DMA_BOUNDARY, -}; - -static struct ata_port_operations bfin_pata_ops = { - .inherits = &ata_bmdma_port_ops, - - .set_piomode = bfin_set_piomode, - .set_dmamode = bfin_set_dmamode, - - .sff_tf_load = bfin_tf_load, - .sff_tf_read = bfin_tf_read, - .sff_exec_command = bfin_exec_command, - .sff_check_status = bfin_check_status, - .sff_check_altstatus = bfin_check_altstatus, - .sff_dev_select = bfin_dev_select, - .sff_set_devctl = bfin_set_devctl, - - .bmdma_setup = bfin_bmdma_setup, - .bmdma_start = bfin_bmdma_start, - .bmdma_stop = bfin_bmdma_stop, - .bmdma_status = bfin_bmdma_status, - .sff_data_xfer = bfin_data_xfer, - - .qc_prep = ata_noop_qc_prep, - - .thaw = bfin_thaw, - .softreset = bfin_softreset, - .postreset = bfin_postreset, - - .sff_irq_clear = bfin_irq_clear, - - .port_start = bfin_port_start, - .port_stop = bfin_port_stop, -}; - -static struct ata_port_info bfin_port_info[] = { - { - .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = ATA_PIO4, - .mwdma_mask = 0, - .udma_mask = 0, - .port_ops = &bfin_pata_ops, - }, -}; - -/** - * bfin_reset_controller - initialize BF54x ATAPI controller. - */ - -static int bfin_reset_controller(struct ata_host *host) -{ - void __iomem *base = (void __iomem *)host->ports[0]->ioaddr.ctl_addr; - int count; - unsigned short status; - - /* Disable all ATAPI interrupts */ - ATAPI_SET_INT_MASK(base, 0); - SSYNC(); - - /* Assert the RESET signal 25us*/ - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | DEV_RST); - udelay(30); - - /* Negate the RESET signal for 2ms*/ - ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) & ~DEV_RST); - msleep(2); - - /* Wait on Busy flag to clear */ - count = 10000000; - do { - status = read_atapi_register(base, ATA_REG_STATUS); - } while (--count && (status & ATA_BUSY)); - - /* Enable only ATAPI Device interrupt */ - ATAPI_SET_INT_MASK(base, 1); - SSYNC(); - - return (!count); -} - -/** - * atapi_io_port - define atapi peripheral port pins. - */ -static unsigned short atapi_io_port[] = { - P_ATAPI_RESET, - P_ATAPI_DIOR, - P_ATAPI_DIOW, - P_ATAPI_CS0, - P_ATAPI_CS1, - P_ATAPI_DMACK, - P_ATAPI_DMARQ, - P_ATAPI_INTRQ, - P_ATAPI_IORDY, - P_ATAPI_D0A, - P_ATAPI_D1A, - P_ATAPI_D2A, - P_ATAPI_D3A, - P_ATAPI_D4A, - P_ATAPI_D5A, - P_ATAPI_D6A, - P_ATAPI_D7A, - P_ATAPI_D8A, - P_ATAPI_D9A, - P_ATAPI_D10A, - P_ATAPI_D11A, - P_ATAPI_D12A, - P_ATAPI_D13A, - P_ATAPI_D14A, - P_ATAPI_D15A, - P_ATAPI_A0A, - P_ATAPI_A1A, - P_ATAPI_A2A, - 0 -}; - -/** - * bfin_atapi_probe - attach a bfin atapi interface - * @pdev: platform device - * - * Register a bfin atapi interface. - * - * - * Platform devices are expected to contain 2 resources per port: - * - * - I/O Base (IORESOURCE_IO) - * - IRQ (IORESOURCE_IRQ) - * - */ -static int bfin_atapi_probe(struct platform_device *pdev) -{ - int board_idx = 0; - struct resource *res; - struct ata_host *host; - unsigned int fsclk = get_sclk(); - int udma_mode = 5; - const struct ata_port_info *ppi[] = - { &bfin_port_info[board_idx], NULL }; - - /* - * Simple resource validation .. - */ - if (unlikely(pdev->num_resources != 2)) { - dev_err(&pdev->dev, "invalid number of resources\n"); - return -EINVAL; - } - - /* - * Get the register base first - */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) - return -EINVAL; - - while (bfin_port_info[board_idx].udma_mask > 0 && - udma_fsclk[udma_mode] > fsclk) { - udma_mode--; - bfin_port_info[board_idx].udma_mask >>= 1; - } - - /* - * Now that that's out of the way, wire up the port.. - */ - host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1); - if (!host) - return -ENOMEM; - - host->ports[0]->ioaddr.ctl_addr = (void *)res->start; - - if (peripheral_request_list(atapi_io_port, "atapi-io-port")) { - dev_err(&pdev->dev, "Requesting Peripherals failed\n"); - return -EFAULT; - } - - if (bfin_reset_controller(host)) { - peripheral_free_list(atapi_io_port); - dev_err(&pdev->dev, "Fail to reset ATAPI device\n"); - return -EFAULT; - } - - if (ata_host_activate(host, platform_get_irq(pdev, 0), - bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) { - peripheral_free_list(atapi_io_port); - dev_err(&pdev->dev, "Fail to attach ATAPI device\n"); - return -ENODEV; - } - - return 0; -} - -/** - * bfin_atapi_remove - unplug a bfin atapi interface - * @pdev: platform device - * - * A bfin atapi device has been unplugged. Perform the needed - * cleanup. Also called on module unload for any active devices. - */ -static int bfin_atapi_remove(struct platform_device *pdev) -{ - struct ata_host *host = platform_get_drvdata(pdev); - - ata_host_detach(host); - - peripheral_free_list(atapi_io_port); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct ata_host *host = platform_get_drvdata(pdev); - if (host) - return ata_host_suspend(host, state); - else - return 0; -} - -static int bfin_atapi_resume(struct platform_device *pdev) -{ - struct ata_host *host = platform_get_drvdata(pdev); - int ret; - - if (host) { - ret = bfin_reset_controller(host); - if (ret) { - printk(KERN_ERR DRV_NAME ": Error during HW init\n"); - return ret; - } - ata_host_resume(host); - } - - return 0; -} -#else -#define bfin_atapi_suspend NULL -#define bfin_atapi_resume NULL -#endif - -static struct platform_driver bfin_atapi_driver = { - .probe = bfin_atapi_probe, - .remove = bfin_atapi_remove, - .suspend = bfin_atapi_suspend, - .resume = bfin_atapi_resume, - .driver = { - .name = DRV_NAME, - }, -}; - -#define ATAPI_MODE_SIZE 10 -static char bfin_atapi_mode[ATAPI_MODE_SIZE]; - -static int __init bfin_atapi_init(void) -{ - pr_info("register bfin atapi driver\n"); - - switch(bfin_atapi_mode[0]) { - case 'p': - case 'P': - break; - case 'm': - case 'M': - bfin_port_info[0].mwdma_mask = ATA_MWDMA2; - break; - default: - bfin_port_info[0].udma_mask = ATA_UDMA5; - }; - - return platform_driver_register(&bfin_atapi_driver); -} - -static void __exit bfin_atapi_exit(void) -{ - platform_driver_unregister(&bfin_atapi_driver); -} - -module_init(bfin_atapi_init); -module_exit(bfin_atapi_exit); -/* - * ATAPI mode: - * pio/PIO - * udma/UDMA (default) - * mwdma/MWDMA - */ -module_param_string(bfin_atapi_mode, bfin_atapi_mode, ATAPI_MODE_SIZE, 0); - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index c28dca0c613d..40947a796666 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -66,34 +66,6 @@ config TTY_PRINTK If unsure, say N. -config BFIN_OTP - tristate "Blackfin On-Chip OTP Memory Support" - depends on BLACKFIN && (BF51x || BF52x || BF54x) - default y - help - If you say Y here, you will get support for a character device - interface into the One Time Programmable memory pages that are - stored on the Blackfin processor. This will not get you access - to the secure memory pages however. You will need to write your - own secure code and reader for that. - - To compile this driver as a module, choose M here: the module - will be called bfin-otp. - - If unsure, it is safe to say Y. - -config BFIN_OTP_WRITE_ENABLE - bool "Enable writing support of OTP pages" - depends on BFIN_OTP - default n - help - If you say Y here, you will enable support for writing of the - OTP pages. This is dangerous by nature as you can only program - the pages once, so only enable this option when you actually - need it so as to not inadvertently clobber data. - - If unsure, say N. - config PRINTER tristate "Parallel printer support" depends on PARPORT @@ -346,15 +318,6 @@ config EFI_RTC bool "EFI Real Time Clock Services" depends on IA64 -config DS1302 - tristate "DS1302 RTC support" - depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT) - help - If you say Y here and create a character special file /dev/rtc with - major number 121 and minor number 0 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - into your computer. - endif # RTC_LIB config DTLK @@ -575,17 +538,6 @@ config DEVPORT source "drivers/s390/char/Kconfig" -config TILE_SROM - tristate "Character-device access via hypervisor to the Tilera SPI ROM" - depends on TILE - default y - ---help--- - This device provides character-level read-write access - to the SROM, typically via the "0", "1", and "2" devices - in /dev/srom/. The Tilera hypervisor makes the flash - device appear much like a simple EEPROM, and knows - how to partition a single ROM for multiple purposes. - source "drivers/char/xillybus/Kconfig" endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 7dc3abe66464..c97c768cd1dd 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o obj-$(CONFIG_IBM_BSR) += bsr.o obj-$(CONFIG_SGI_MBCS) += mbcs.o -obj-$(CONFIG_BFIN_OTP) += bfin-otp.o obj-$(CONFIG_PRINTER) += lp.o @@ -26,7 +25,6 @@ obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_EFI_RTC) += efirtc.o -obj-$(CONFIG_DS1302) += ds1302.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ ifeq ($(CONFIG_GENERIC_NVRAM),y) obj-$(CONFIG_NVRAM) += generic_nvram.o @@ -57,6 +55,5 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o obj-$(CONFIG_JS_RTC) += js-rtc.o js-rtc-y = rtc.o -obj-$(CONFIG_TILE_SROM) += tile-srom.o obj-$(CONFIG_XILLYBUS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c deleted file mode 100644 index 0584025bb0c2..000000000000 --- a/drivers/char/bfin-otp.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Blackfin On-Chip OTP Memory Interface - * - * Copyright 2007-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/miscdevice.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/types.h> -#include <mtd/mtd-abi.h> - -#include <asm/blackfin.h> -#include <asm/bfrom.h> -#include <linux/uaccess.h> - -#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) -#define stampit() stamp("here i am") -#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) - -#define DRIVER_NAME "bfin-otp" -#define PFX DRIVER_NAME ": " - -static DEFINE_MUTEX(bfin_otp_lock); - -/** - * bfin_otp_read - Read OTP pages - * - * All reads must be in half page chunks (half page == 64 bits). - */ -static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count, loff_t *pos) -{ - ssize_t bytes_done; - u32 page, flags, ret; - u64 content; - - stampit(); - - if (count % sizeof(u64)) - return -EMSGSIZE; - - if (mutex_lock_interruptible(&bfin_otp_lock)) - return -ERESTARTSYS; - - bytes_done = 0; - page = *pos / (sizeof(u64) * 2); - while (bytes_done < count) { - flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF); - stamp("processing page %i (0x%x:%s)", page, flags, - (flags & OTP_UPPER_HALF ? "upper" : "lower")); - ret = bfrom_OtpRead(page, flags, &content); - if (ret & OTP_MASTER_ERROR) { - stamp("error from otp: 0x%x", ret); - bytes_done = -EIO; - break; - } - if (copy_to_user(buff + bytes_done, &content, sizeof(content))) { - bytes_done = -EFAULT; - break; - } - if (flags & OTP_UPPER_HALF) - ++page; - bytes_done += sizeof(content); - *pos += sizeof(content); - } - - mutex_unlock(&bfin_otp_lock); - - return bytes_done; -} - -#ifdef CONFIG_BFIN_OTP_WRITE_ENABLE -static bool allow_writes; - -/** - * bfin_otp_init_timing - setup OTP timing parameters - * - * Required before doing any write operation. Algorithms from HRM. - */ -static u32 bfin_otp_init_timing(void) -{ - u32 tp1, tp2, tp3, timing; - - tp1 = get_sclk() / 1000000; - tp2 = (2 * get_sclk() / 10000000) << 8; - tp3 = (0x1401) << 15; - timing = tp1 | tp2 | tp3; - if (bfrom_OtpCommand(OTP_INIT, timing)) - return 0; - - return timing; -} - -/** - * bfin_otp_deinit_timing - set timings to only allow reads - * - * Should be called after all writes are done. - */ -static void bfin_otp_deinit_timing(u32 timing) -{ - /* mask bits [31:15] so that any attempts to write fail */ - bfrom_OtpCommand(OTP_CLOSE, 0); - bfrom_OtpCommand(OTP_INIT, timing & ~(-1 << 15)); - bfrom_OtpCommand(OTP_CLOSE, 0); -} - -/** - * bfin_otp_write - write OTP pages - * - * All writes must be in half page chunks (half page == 64 bits). - */ -static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos) -{ - ssize_t bytes_done; - u32 timing, page, base_flags, flags, ret; - u64 content; - - if (!allow_writes) - return -EACCES; - - if (count % sizeof(u64)) - return -EMSGSIZE; - - if (mutex_lock_interruptible(&bfin_otp_lock)) - return -ERESTARTSYS; - - stampit(); - - timing = bfin_otp_init_timing(); - if (timing == 0) { - mutex_unlock(&bfin_otp_lock); - return -EIO; - } - - base_flags = OTP_CHECK_FOR_PREV_WRITE; - - bytes_done = 0; - page = *pos / (sizeof(u64) * 2); - while (bytes_done < count) { - flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF); - stamp("processing page %i (0x%x:%s) from %p", page, flags, - (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done); - if (copy_from_user(&content, buff + bytes_done, sizeof(content))) { - bytes_done = -EFAULT; - break; - } - ret = bfrom_OtpWrite(page, flags, &content); - if (ret & OTP_MASTER_ERROR) { - stamp("error from otp: 0x%x", ret); - bytes_done = -EIO; - break; - } - if (flags & OTP_UPPER_HALF) - ++page; - bytes_done += sizeof(content); - *pos += sizeof(content); - } - - bfin_otp_deinit_timing(timing); - - mutex_unlock(&bfin_otp_lock); - - return bytes_done; -} - -static long bfin_otp_ioctl(struct file *filp, unsigned cmd, unsigned long arg) -{ - stampit(); - - switch (cmd) { - case OTPLOCK: { - u32 timing; - int ret = -EIO; - - if (!allow_writes) - return -EACCES; - - if (mutex_lock_interruptible(&bfin_otp_lock)) - return -ERESTARTSYS; - - timing = bfin_otp_init_timing(); - if (timing) { - u32 otp_result = bfrom_OtpWrite(arg, OTP_LOCK, NULL); - stamp("locking page %lu resulted in 0x%x", arg, otp_result); - if (!(otp_result & OTP_MASTER_ERROR)) - ret = 0; - - bfin_otp_deinit_timing(timing); - } - - mutex_unlock(&bfin_otp_lock); - - return ret; - } - - case MEMLOCK: - allow_writes = false; - return 0; - - case MEMUNLOCK: - allow_writes = true; - return 0; - } - - return -EINVAL; -} -#else -# define bfin_otp_write NULL -# define bfin_otp_ioctl NULL -#endif - -static const struct file_operations bfin_otp_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = bfin_otp_ioctl, - .read = bfin_otp_read, - .write = bfin_otp_write, - .llseek = default_llseek, -}; - -static struct miscdevice bfin_otp_misc_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = DRIVER_NAME, - .fops = &bfin_otp_fops, -}; -module_misc_device(bfin_otp_misc_device); - -MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); -MODULE_DESCRIPTION("Blackfin OTP Memory Interface"); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c deleted file mode 100644 index 8e16ad5d6d89..000000000000 --- a/drivers/char/ds1302.c +++ /dev/null @@ -1,357 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*!*************************************************************************** -*! -*! FILE NAME : ds1302.c -*! -*! DESCRIPTION: Implements an interface for the DS1302 RTC -*! -*! Functions exported: ds1302_readreg, ds1302_writereg, ds1302_init, get_rtc_status -*! -*! --------------------------------------------------------------------------- -*! -*! (C) Copyright 1999, 2000, 2001 Axis Communications AB, LUND, SWEDEN -*! -*!***************************************************************************/ - - -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/bcd.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -#include <asm/rtc.h> -#if defined(CONFIG_M32R) -#include <asm/m32r.h> -#endif - -#define RTC_MAJOR_NR 121 /* local major, change later */ - -static DEFINE_MUTEX(rtc_mutex); -static const char ds1302_name[] = "ds1302"; - -/* Send 8 bits. */ -static void -out_byte_rtc(unsigned int reg_addr, unsigned char x) -{ - //RST H - outw(0x0001,(unsigned long)PLD_RTCRSTODT); - //write data - outw(((x<<8)|(reg_addr&0xff)),(unsigned long)PLD_RTCWRDATA); - //WE - outw(0x0002,(unsigned long)PLD_RTCCR); - //wait - while(inw((unsigned long)PLD_RTCCR)); - - //RST L - outw(0x0000,(unsigned long)PLD_RTCRSTODT); - -} - -static unsigned char -in_byte_rtc(unsigned int reg_addr) -{ - unsigned char retval; - - //RST H - outw(0x0001,(unsigned long)PLD_RTCRSTODT); - //write data - outw((reg_addr&0xff),(unsigned long)PLD_RTCRDDATA); - //RE - outw(0x0001,(unsigned long)PLD_RTCCR); - //wait - while(inw((unsigned long)PLD_RTCCR)); - - //read data - retval=(inw((unsigned long)PLD_RTCRDDATA) & 0xff00)>>8; - - //RST L - outw(0x0000,(unsigned long)PLD_RTCRSTODT); - - return retval; -} - -/* Enable writing. */ - -static void -ds1302_wenable(void) -{ - out_byte_rtc(0x8e,0x00); -} - -/* Disable writing. */ - -static void -ds1302_wdisable(void) -{ - out_byte_rtc(0x8e,0x80); -} - - - -/* Read a byte from the selected register in the DS1302. */ - -unsigned char -ds1302_readreg(int reg) -{ - unsigned char x; - - x=in_byte_rtc((0x81 | (reg << 1))); /* read register */ - - return x; -} - -/* Write a byte to the selected register. */ - -void -ds1302_writereg(int reg, unsigned char val) -{ - ds1302_wenable(); - out_byte_rtc((0x80 | (reg << 1)),val); - ds1302_wdisable(); -} - -void -get_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned long flags; - - local_irq_save(flags); - - rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); - rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); - rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); - rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); - rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); - rtc_tm->tm_year = CMOS_READ(RTC_YEAR); - - local_irq_restore(flags); - - rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); - rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); - rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); - rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); - rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); - rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - - if (rtc_tm->tm_year <= 69) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} - -static unsigned char days_in_mo[] = - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ - -static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned long flags; - - switch(cmd) { - case RTC_RD_TIME: /* read the time/date from RTC */ - { - struct rtc_time rtc_tm; - - memset(&rtc_tm, 0, sizeof (struct rtc_time)); - mutex_lock(&rtc_mutex); - get_rtc_time(&rtc_tm); - mutex_unlock(&rtc_mutex); - if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) - return -EFAULT; - return 0; - } - - case RTC_SET_TIME: /* set the RTC */ - { - struct rtc_time rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned int yrs; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) - return -EFAULT; - - yrs = rtc_tm.tm_year + 1900; - mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm.tm_mday; - hrs = rtc_tm.tm_hour; - min = rtc_tm.tm_min; - sec = rtc_tm.tm_sec; - - - if ((yrs < 1970) || (yrs > 2069)) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if (yrs >= 2000) - yrs -= 2000; /* RTC (0, 1, ... 69) */ - else - yrs -= 1900; /* RTC (70, 71, ... 99) */ - - sec = bin2bcd(sec); - min = bin2bcd(min); - hrs = bin2bcd(hrs); - day = bin2bcd(day); - mon = bin2bcd(mon); - yrs = bin2bcd(yrs); - - mutex_lock(&rtc_mutex); - local_irq_save(flags); - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DAY_OF_MONTH); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); - local_irq_restore(flags); - mutex_unlock(&rtc_mutex); - - /* Notice that at this point, the RTC is updated but - * the kernel is still running with the old time. - * You need to set that separately with settimeofday - * or adjtimex. - */ - return 0; - } - - case RTC_SET_CHARGE: /* set the RTC TRICKLE CHARGE register */ - { - int tcs_val; - - if (!capable(CAP_SYS_TIME)) - return -EPERM; - - if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) - return -EFAULT; - - mutex_lock(&rtc_mutex); - tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); - ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); - mutex_unlock(&rtc_mutex); - return 0; - } - default: - return -EINVAL; - } -} - -int -get_rtc_status(char *buf) -{ - char *p; - struct rtc_time tm; - - p = buf; - - get_rtc_time(&tm); - - /* - * There is no way to tell if the luser has the RTC set for local - * time or for Universal Standard Time (GMT). Probably local though. - */ - - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); - - return p - buf; -} - - -/* The various file operations we support. */ - -static const struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = rtc_ioctl, - .llseek = noop_llseek, -}; - -/* Probe for the chip by writing something to its RAM and try reading it back. */ - -#define MAGIC_PATTERN 0x42 - -static int __init -ds1302_probe(void) -{ - int retval, res, baur; - - baur=(boot_cpu_data.bus_clock/(2*1000*1000)); - - printk("%s: Set PLD_RTCBAUR = %d\n", ds1302_name,baur); - - outw(0x0000,(unsigned long)PLD_RTCCR); - outw(0x0000,(unsigned long)PLD_RTCRSTODT); - outw(baur,(unsigned long)PLD_RTCBAUR); - - /* Try to talk to timekeeper. */ - - ds1302_wenable(); - /* write RAM byte 0 */ - /* write something magic */ - out_byte_rtc(0xc0,MAGIC_PATTERN); - - /* read RAM byte 0 */ - if((res = in_byte_rtc(0xc1)) == MAGIC_PATTERN) { - char buf[100]; - ds1302_wdisable(); - printk("%s: RTC found.\n", ds1302_name); - get_rtc_status(buf); - printk(buf); - retval = 1; - } else { - printk("%s: RTC not found.\n", ds1302_name); - retval = 0; - } - - return retval; -} - - -/* Just probe for the RTC and register the device to handle the ioctl needed. */ - -int __init -ds1302_init(void) -{ - if (!ds1302_probe()) { - return -1; - } - return 0; -} - -static int __init ds1302_register(void) -{ - ds1302_init(); - if (register_chrdev(RTC_MAJOR_NR, ds1302_name, &rtc_fops)) { - printk(KERN_INFO "%s: unable to get major %d for rtc\n", - ds1302_name, RTC_MAJOR_NR); - return -1; - } - return 0; -} - -module_init(ds1302_register); diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c deleted file mode 100644 index 3d4cca64b2d4..000000000000 --- a/drivers/char/tile-srom.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright 2011 Tilera Corporation. All Rights Reserved. - * - * 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. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - * - * SPI Flash ROM driver - * - * This source code is derived from code provided in "Linux Device - * Drivers, Third Edition", by Jonathan Corbet, Alessandro Rubini, and - * Greg Kroah-Hartman, published by O'Reilly Media, Inc. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> /* printk() */ -#include <linux/slab.h> /* kmalloc() */ -#include <linux/fs.h> /* everything... */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/proc_fs.h> -#include <linux/fcntl.h> /* O_ACCMODE */ -#include <linux/pagemap.h> -#include <linux/hugetlb.h> -#include <linux/uaccess.h> -#include <linux/platform_device.h> -#include <hv/hypervisor.h> -#include <linux/ioctl.h> -#include <linux/cdev.h> -#include <linux/delay.h> -#include <hv/drv_srom_intf.h> - -/* - * Size of our hypervisor I/O requests. We break up large transfers - * so that we don't spend large uninterrupted spans of time in the - * hypervisor. Erasing an SROM sector takes a significant fraction of - * a second, so if we allowed the user to, say, do one I/O to write the - * entire ROM, we'd get soft lockup timeouts, or worse. - */ -#define SROM_CHUNK_SIZE ((size_t)4096) - -/* - * When hypervisor is busy (e.g. erasing), poll the status periodically. - */ - -/* - * Interval to poll the state in msec - */ -#define SROM_WAIT_TRY_INTERVAL 20 - -/* - * Maximum times to poll the state - */ -#define SROM_MAX_WAIT_TRY_TIMES 1000 - -struct srom_dev { - int hv_devhdl; /* Handle for hypervisor device */ - u32 total_size; /* Size of this device */ - u32 sector_size; /* Size of a sector */ - u32 page_size; /* Size of a page */ - struct mutex lock; /* Allow only one accessor at a time */ -}; - -static int srom_major; /* Dynamic major by default */ -module_param(srom_major, int, 0); -MODULE_AUTHOR("Tilera Corporation"); -MODULE_LICENSE("GPL"); - -static int srom_devs; /* Number of SROM partitions */ -static struct cdev srom_cdev; -static struct platform_device *srom_parent; -static struct class *srom_class; -static struct srom_dev *srom_devices; - -/* - * Handle calling the hypervisor and managing EAGAIN/EBUSY. - */ - -static ssize_t _srom_read(int hv_devhdl, void *buf, - loff_t off, size_t count) -{ - int retval, retries = SROM_MAX_WAIT_TRY_TIMES; - for (;;) { - retval = hv_dev_pread(hv_devhdl, 0, (HV_VirtAddr)buf, - count, off); - if (retval >= 0) - return retval; - if (retval == HV_EAGAIN) - continue; - if (retval == HV_EBUSY && --retries > 0) { - msleep(SROM_WAIT_TRY_INTERVAL); - continue; - } - pr_err("_srom_read: error %d\n", retval); - return -EIO; - } -} - -static ssize_t _srom_write(int hv_devhdl, const void *buf, - loff_t off, size_t count) -{ - int retval, retries = SROM_MAX_WAIT_TRY_TIMES; - for (;;) { - retval = hv_dev_pwrite(hv_devhdl, 0, (HV_VirtAddr)buf, - count, off); - if (retval >= 0) - return retval; - if (retval == HV_EAGAIN) - continue; - if (retval == HV_EBUSY && --retries > 0) { - msleep(SROM_WAIT_TRY_INTERVAL); - continue; - } - pr_err("_srom_write: error %d\n", retval); - return -EIO; - } -} - -/** - * srom_open() - Device open routine. - * @inode: Inode for this device. - * @filp: File for this specific open of the device. - * - * Returns zero, or an error code. - */ -static int srom_open(struct inode *inode, struct file *filp) -{ - filp->private_data = &srom_devices[iminor(inode)]; - return 0; -} - - -/** - * srom_release() - Device release routine. - * @inode: Inode for this device. - * @filp: File for this specific open of the device. - * - * Returns zero, or an error code. - */ -static int srom_release(struct inode *inode, struct file *filp) -{ - struct srom_dev *srom = filp->private_data; - char dummy; - - /* Make sure we've flushed anything written to the ROM. */ - mutex_lock(&srom->lock); - if (srom->hv_devhdl >= 0) - _srom_write(srom->hv_devhdl, &dummy, SROM_FLUSH_OFF, 1); - mutex_unlock(&srom->lock); - - filp->private_data = NULL; - - return 0; -} - - -/** - * srom_read() - Read data from the device. - * @filp: File for this specific open of the device. - * @buf: User's data buffer. - * @count: Number of bytes requested. - * @f_pos: File position. - * - * Returns number of bytes read, or an error code. - */ -static ssize_t srom_read(struct file *filp, char __user *buf, - size_t count, loff_t *f_pos) -{ - int retval = 0; - void *kernbuf; - struct srom_dev *srom = filp->private_data; - - kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL); - if (!kernbuf) - return -ENOMEM; - - if (mutex_lock_interruptible(&srom->lock)) { - retval = -ERESTARTSYS; - kfree(kernbuf); - return retval; - } - - while (count) { - int hv_retval; - int bytes_this_pass = min(count, SROM_CHUNK_SIZE); - - hv_retval = _srom_read(srom->hv_devhdl, kernbuf, - *f_pos, bytes_this_pass); - if (hv_retval <= 0) { - if (retval == 0) - retval = hv_retval; - break; - } - - if (copy_to_user(buf, kernbuf, hv_retval) != 0) { - retval = -EFAULT; - break; - } - - retval += hv_retval; - *f_pos += hv_retval; - buf += hv_retval; - count -= hv_retval; - } - - mutex_unlock(&srom->lock); - kfree(kernbuf); - - return retval; -} - -/** - * srom_write() - Write data to the device. - * @filp: File for this specific open of the device. - * @buf: User's data buffer. - * @count: Number of bytes requested. - * @f_pos: File position. - * - * Returns number of bytes written, or an error code. - */ -static ssize_t srom_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos) -{ - int retval = 0; - void *kernbuf; - struct srom_dev *srom = filp->private_data; - - kernbuf = kmalloc(SROM_CHUNK_SIZE, GFP_KERNEL); - if (!kernbuf) - return -ENOMEM; - - if (mutex_lock_interruptible(&srom->lock)) { - retval = -ERESTARTSYS; - kfree(kernbuf); - return retval; - } - - while (count) { - int hv_retval; - int bytes_this_pass = min(count, SROM_CHUNK_SIZE); - - if (copy_from_user(kernbuf, buf, bytes_this_pass) != 0) { - retval = -EFAULT; - break; - } - - hv_retval = _srom_write(srom->hv_devhdl, kernbuf, - *f_pos, bytes_this_pass); - if (hv_retval <= 0) { - if (retval == 0) - retval = hv_retval; - break; - } - - retval += hv_retval; - *f_pos += hv_retval; - buf += hv_retval; - count -= hv_retval; - } - - mutex_unlock(&srom->lock); - kfree(kernbuf); - - return retval; -} - -/* Provide our own implementation so we can use srom->total_size. */ -loff_t srom_llseek(struct file *file, loff_t offset, int origin) -{ - struct srom_dev *srom = file->private_data; - return fixed_size_llseek(file, offset, origin, srom->total_size); -} - -static ssize_t total_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct srom_dev *srom = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", srom->total_size); -} -static DEVICE_ATTR_RO(total_size); - -static ssize_t sector_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct srom_dev *srom = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", srom->sector_size); -} -static DEVICE_ATTR_RO(sector_size); - -static ssize_t page_size_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct srom_dev *srom = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", srom->page_size); -} -static DEVICE_ATTR_RO(page_size); - -static struct attribute *srom_dev_attrs[] = { - &dev_attr_total_size.attr, - &dev_attr_sector_size.attr, - &dev_attr_page_size.attr, - NULL, -}; -ATTRIBUTE_GROUPS(srom_dev); - -static char *srom_devnode(struct device *dev, umode_t *mode) -{ - if (mode) - *mode = 0644; - return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev)); -} - -/* - * The fops - */ -static const struct file_operations srom_fops = { - .owner = THIS_MODULE, - .llseek = srom_llseek, - .read = srom_read, - .write = srom_write, - .open = srom_open, - .release = srom_release, -}; - -/** - * srom_setup_minor() - Initialize per-minor information. - * @srom: Per-device SROM state. - * @devhdl: Partition device handle. - */ -static int srom_setup_minor(struct srom_dev *srom, int devhdl) -{ - srom->hv_devhdl = devhdl; - mutex_init(&srom->lock); - - if (_srom_read(devhdl, &srom->total_size, - SROM_TOTAL_SIZE_OFF, sizeof(srom->total_size)) < 0) - return -EIO; - if (_srom_read(devhdl, &srom->sector_size, - SROM_SECTOR_SIZE_OFF, sizeof(srom->sector_size)) < 0) - return -EIO; - if (_srom_read(devhdl, &srom->page_size, - SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0) - return -EIO; - - return 0; -} - -/** srom_init() - Initialize the driver's module. */ -static int srom_init(void) -{ - int result, i; - dev_t dev = MKDEV(srom_major, 0); - - /* - * Start with a plausible number of partitions; the krealloc() call - * below will yield about log(srom_devs) additional allocations. - */ - srom_devices = kmalloc(4 * sizeof(struct srom_dev), GFP_KERNEL); - - /* Discover the number of srom partitions. */ - for (i = 0; ; i++) { - int devhdl; - char buf[20]; - struct srom_dev *new_srom_devices = - krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), - GFP_KERNEL); - if (!new_srom_devices) { - result = -ENOMEM; - goto fail_mem; - } - srom_devices = new_srom_devices; - sprintf(buf, "srom/0/%d", i); - devhdl = hv_dev_open((HV_VirtAddr)buf, 0); - if (devhdl < 0) { - if (devhdl != HV_ENODEV) - pr_notice("srom/%d: hv_dev_open failed: %d.\n", - i, devhdl); - break; - } - result = srom_setup_minor(&srom_devices[i], devhdl); - if (result != 0) - goto fail_mem; - } - srom_devs = i; - - /* Bail out early if we have no partitions at all. */ - if (srom_devs == 0) { - result = -ENODEV; - goto fail_mem; - } - - /* Register our major, and accept a dynamic number. */ - if (srom_major) - result = register_chrdev_region(dev, srom_devs, "srom"); - else { - result = alloc_chrdev_region(&dev, 0, srom_devs, "srom"); - srom_major = MAJOR(dev); - } - if (result < 0) - goto fail_mem; - - /* Register a character device. */ - cdev_init(&srom_cdev, &srom_fops); - srom_cdev.owner = THIS_MODULE; - srom_cdev.ops = &srom_fops; - result = cdev_add(&srom_cdev, dev, srom_devs); - if (result < 0) - goto fail_chrdev; - - /* Create a parent device */ - srom_parent = platform_device_register_simple("srom", -1, NULL, 0); - if (IS_ERR(srom_parent)) { - result = PTR_ERR(srom_parent); - goto fail_pdev; - } - - /* Create a sysfs class. */ - srom_class = class_create(THIS_MODULE, "srom"); - if (IS_ERR(srom_class)) { - result = PTR_ERR(srom_class); - goto fail_cdev; - } - srom_class->dev_groups = srom_dev_groups; - srom_class->devnode = srom_devnode; - - /* Create per-partition devices */ - for (i = 0; i < srom_devs; i++) { - struct device *dev = - device_create(srom_class, &srom_parent->dev, - MKDEV(srom_major, i), srom_devices + i, - "%d", i); - result = PTR_ERR_OR_ZERO(dev); - if (result < 0) - goto fail_class; - } - - return 0; - -fail_class: - for (i = 0; i < srom_devs; i++) - device_destroy(srom_class, MKDEV(srom_major, i)); - class_destroy(srom_class); -fail_cdev: - platform_device_unregister(srom_parent); -fail_pdev: - cdev_del(&srom_cdev); -fail_chrdev: - unregister_chrdev_region(dev, srom_devs); -fail_mem: - kfree(srom_devices); - return result; -} - -/** srom_cleanup() - Clean up the driver's module. */ -static void srom_cleanup(void) -{ - int i; - for (i = 0; i < srom_devs; i++) - device_destroy(srom_class, MKDEV(srom_major, i)); - class_destroy(srom_class); - cdev_del(&srom_cdev); - platform_device_unregister(srom_parent); - unregister_chrdev_region(MKDEV(srom_major, 0), srom_devs); - kfree(srom_devices); -} - -module_init(srom_init); -module_exit(srom_cleanup); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 14c9796e37ac..6021a5af21da 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -392,11 +392,6 @@ config ATMEL_ST help Support for the Atmel ST timer. -config CLKSRC_METAG_GENERIC - def_bool y if METAG - help - This option enables support for the Meta per-thread timers. - config CLKSRC_EXYNOS_MCT bool "Exynos multi core timer driver" if COMPILE_TEST depends on ARM || ARM64 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index a79523b22e52..f0cb07637a65 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -61,7 +61,6 @@ obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp804.o -obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o obj-$(CONFIG_KEYSTONE_TIMER) += timer-keystone.o obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c deleted file mode 100644 index 3e5fa2f62d5f..000000000000 --- a/drivers/clocksource/metag_generic.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2005-2013 Imagination Technologies Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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, see <http://www.gnu.org/licenses/>. - * - * - * Support for Meta per-thread timers. - * - * Meta hardware threads have 2 timers. The background timer (TXTIMER) is used - * as a free-running time base (hz clocksource), and the interrupt timer - * (TXTIMERI) is used for the timer interrupt (clock event). Both counters - * traditionally count at approximately 1MHz. - */ - -#include <clocksource/metag_generic.h> -#include <linux/cpu.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/time.h> -#include <linux/init.h> -#include <linux/proc_fs.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> - -#include <asm/clock.h> -#include <asm/hwthread.h> -#include <asm/core_reg.h> -#include <asm/metag_mem.h> -#include <asm/tbx.h> - -#define HARDWARE_FREQ 1000000 /* 1MHz */ -#define HARDWARE_DIV 1 /* divide by 1 = 1MHz clock */ -#define HARDWARE_TO_NS_SHIFT 10 /* convert ticks to ns */ - -static unsigned int hwtimer_freq = HARDWARE_FREQ; -static DEFINE_PER_CPU(struct clock_event_device, local_clockevent); -static DEFINE_PER_CPU(char [11], local_clockevent_name); - -static int metag_timer_set_next_event(unsigned long delta, - struct clock_event_device *dev) -{ - __core_reg_set(TXTIMERI, -delta); - return 0; -} - -static u64 metag_clocksource_read(struct clocksource *cs) -{ - return __core_reg_get(TXTIMER); -} - -static struct clocksource clocksource_metag = { - .name = "META", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = metag_clocksource_read, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t metag_timer_interrupt(int irq, void *dummy) -{ - struct clock_event_device *evt = this_cpu_ptr(&local_clockevent); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction metag_timer_irq = { - .name = "META core timer", - .handler = metag_timer_interrupt, - .flags = IRQF_TIMER | IRQF_IRQPOLL | IRQF_PERCPU, -}; - -unsigned long long sched_clock(void) -{ - unsigned long long ticks = __core_reg_get(TXTIMER); - return ticks << HARDWARE_TO_NS_SHIFT; -} - -static int arch_timer_starting_cpu(unsigned int cpu) -{ - unsigned int txdivtime; - struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); - char *name = per_cpu(local_clockevent_name, cpu); - - txdivtime = __core_reg_get(TXDIVTIME); - - txdivtime &= ~TXDIVTIME_DIV_BITS; - txdivtime |= (HARDWARE_DIV & TXDIVTIME_DIV_BITS); - - __core_reg_set(TXDIVTIME, txdivtime); - - sprintf(name, "META %d", cpu); - clk->name = name; - clk->features = CLOCK_EVT_FEAT_ONESHOT, - - clk->rating = 200, - clk->shift = 12, - clk->irq = tbisig_map(TBID_SIGNUM_TRT), - clk->set_next_event = metag_timer_set_next_event, - - clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift); - clk->max_delta_ns = clockevent_delta2ns(0x7fffffff, clk); - clk->max_delta_ticks = 0x7fffffff; - clk->min_delta_ns = clockevent_delta2ns(0xf, clk); - clk->min_delta_ticks = 0xf; - clk->cpumask = cpumask_of(cpu); - - clockevents_register_device(clk); - - /* - * For all non-boot CPUs we need to synchronize our free - * running clock (TXTIMER) with the boot CPU's clock. - * - * While this won't be accurate, it should be close enough. - */ - if (cpu) { - unsigned int thread0 = cpu_2_hwthread_id[0]; - unsigned long val; - - val = core_reg_read(TXUCT_ID, TXTIMER_REGNUM, thread0); - __core_reg_set(TXTIMER, val); - } - return 0; -} - -int __init metag_generic_timer_init(void) -{ - /* - * On Meta 2 SoCs, the actual frequency of the timer is based on the - * Meta core clock speed divided by an integer, so it is only - * approximately 1MHz. Calculating the real frequency here drastically - * reduces clock skew on these SoCs. - */ -#ifdef CONFIG_METAG_META21 - hwtimer_freq = get_coreclock() / (metag_in32(EXPAND_TIMER_DIV) + 1); -#endif - pr_info("Timer frequency: %u Hz\n", hwtimer_freq); - - clocksource_register_hz(&clocksource_metag, hwtimer_freq); - - setup_irq(tbisig_map(TBID_SIGNUM_TRT), &metag_timer_irq); - - /* Hook cpu boot to configure the CPU's timers */ - return cpuhp_setup_state(CPUHP_AP_METAG_TIMER_STARTING, - "clockevents/metag:starting", - arch_timer_starting_cpu, NULL); -} diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index c60c1e141d9d..b2cbdc016c77 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,10 +100,7 @@ obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o ################################################################################## # Other platform drivers -obj-$(CONFIG_BFIN_CPU_FREQ) += blackfin-cpufreq.o obj-$(CONFIG_BMIPS_CPUFREQ) += bmips-cpufreq.o -obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o -obj-$(CONFIG_ETRAXFS) += cris-etraxfs-cpufreq.o obj-$(CONFIG_IA64_ACPI_CPUFREQ) += ia64-acpi-cpufreq.o obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o obj-$(CONFIG_LOONGSON1_CPUFREQ) += loongson1-cpufreq.o diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c deleted file mode 100644 index 12e97d8a9db0..000000000000 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Blackfin core clock scaling - * - * Copyright 2008-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <asm/blackfin.h> -#include <asm/time.h> -#include <asm/dpmc.h> - - -/* this is the table of CCLK frequencies, in Hz */ -/* .driver_data is the entry in the auxiliary dpm_state_table[] */ -static struct cpufreq_frequency_table bfin_freq_table[] = { - { - .frequency = CPUFREQ_TABLE_END, - .driver_data = 0, - }, - { - .frequency = CPUFREQ_TABLE_END, - .driver_data = 1, - }, - { - .frequency = CPUFREQ_TABLE_END, - .driver_data = 2, - }, - { - .frequency = CPUFREQ_TABLE_END, - .driver_data = 0, - }, -}; - -static struct bfin_dpm_state { - unsigned int csel; /* system clock divider */ - unsigned int tscale; /* change the divider on the core timer interrupt */ -} dpm_state_table[3]; - -#if defined(CONFIG_CYCLES_CLOCKSOURCE) -/* - * normalized to maximum frequency offset for CYCLES, - * used in time-ts cycles clock source, but could be used - * somewhere also. - */ -unsigned long long __bfin_cycles_off; -unsigned int __bfin_cycles_mod; -#endif - -/**************************************************************************/ -static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk) -{ - - unsigned long csel, min_cclk; - int index; - - /* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */ -#if ANOMALY_05000273 || ANOMALY_05000274 || \ - (!(defined(CONFIG_BF54x) || defined(CONFIG_BF60x)) \ - && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE)) - min_cclk = sclk * 2; -#else - min_cclk = sclk; -#endif - -#ifndef CONFIG_BF60x - csel = ((bfin_read_PLL_DIV() & CSEL) >> 4); -#else - csel = bfin_read32(CGU0_DIV) & 0x1F; -#endif - - for (index = 0; (cclk >> index) >= min_cclk && csel <= 3 && index < 3; index++, csel++) { - bfin_freq_table[index].frequency = cclk >> index; -#ifndef CONFIG_BF60x - dpm_state_table[index].csel = csel << 4; /* Shift now into PLL_DIV bitpos */ -#else - dpm_state_table[index].csel = csel; -#endif - dpm_state_table[index].tscale = (TIME_SCALE >> index) - 1; - - pr_debug("cpufreq: freq:%d csel:0x%x tscale:%d\n", - bfin_freq_table[index].frequency, - dpm_state_table[index].csel, - dpm_state_table[index].tscale); - } - return; -} - -static void bfin_adjust_core_timer(void *info) -{ - unsigned int tscale; - unsigned int index = *(unsigned int *)info; - - /* we have to adjust the core timer, because it is using cclk */ - tscale = dpm_state_table[index].tscale; - bfin_write_TSCALE(tscale); - return; -} - -static unsigned int bfin_getfreq_khz(unsigned int cpu) -{ - /* Both CoreA/B have the same core clock */ - return get_cclk() / 1000; -} - -#ifdef CONFIG_BF60x -static int cpu_set_cclk(int cpu, unsigned long new) -{ - struct clk *clk; - int ret; - - clk = clk_get(NULL, "CCLK"); - if (IS_ERR(clk)) - return -ENODEV; - - ret = clk_set_rate(clk, new); - clk_put(clk); - return ret; -} -#endif - -static int bfin_target(struct cpufreq_policy *policy, unsigned int index) -{ -#ifndef CONFIG_BF60x - unsigned int plldiv; -#endif - static unsigned long lpj_ref; - static unsigned int lpj_ref_freq; - unsigned int old_freq, new_freq; - int ret = 0; - -#if defined(CONFIG_CYCLES_CLOCKSOURCE) - cycles_t cycles; -#endif - - old_freq = bfin_getfreq_khz(0); - new_freq = bfin_freq_table[index].frequency; - -#ifndef CONFIG_BF60x - plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel; - bfin_write_PLL_DIV(plldiv); -#else - ret = cpu_set_cclk(policy->cpu, new_freq * 1000); - if (ret != 0) { - WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret); - return ret; - } -#endif - on_each_cpu(bfin_adjust_core_timer, &index, 1); -#if defined(CONFIG_CYCLES_CLOCKSOURCE) - cycles = get_cycles(); - SSYNC(); - cycles += 10; /* ~10 cycles we lose after get_cycles() */ - __bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index); - __bfin_cycles_mod = index; -#endif - if (!lpj_ref_freq) { - lpj_ref = loops_per_jiffy; - lpj_ref_freq = old_freq; - } - if (new_freq != old_freq) { - loops_per_jiffy = cpufreq_scale(lpj_ref, - lpj_ref_freq, new_freq); - } - - return ret; -} - -static int __bfin_cpu_init(struct cpufreq_policy *policy) -{ - - unsigned long cclk, sclk; - - cclk = get_cclk() / 1000; - sclk = get_sclk() / 1000; - - if (policy->cpu == CPUFREQ_CPU) - bfin_init_tables(cclk, sclk); - - policy->cpuinfo.transition_latency = 50000; /* 50us assumed */ - - return cpufreq_table_validate_and_show(policy, bfin_freq_table); -} - -static struct cpufreq_driver bfin_driver = { - .verify = cpufreq_generic_frequency_table_verify, - .target_index = bfin_target, - .get = bfin_getfreq_khz, - .init = __bfin_cpu_init, - .name = "bfin cpufreq", - .attr = cpufreq_generic_attr, -}; - -static int __init bfin_cpu_init(void) -{ - return cpufreq_register_driver(&bfin_driver); -} - -static void __exit bfin_cpu_exit(void) -{ - cpufreq_unregister_driver(&bfin_driver); -} - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("cpufreq driver for Blackfin"); -MODULE_LICENSE("GPL"); - -module_init(bfin_cpu_init); -module_exit(bfin_cpu_exit); diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c deleted file mode 100644 index 455b4fb78cba..000000000000 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/init.h> -#include <linux/module.h> -#include <linux/cpufreq.h> -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/clkgen_defs.h> -#include <hwregs/ddr2_defs.h> - -static int -cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, - void *data); - -static struct notifier_block cris_sdram_freq_notifier_block = { - .notifier_call = cris_sdram_freq_notifier -}; - -static struct cpufreq_frequency_table cris_freq_table[] = { - {0, 0x01, 6000}, - {0, 0x02, 200000}, - {0, 0, CPUFREQ_TABLE_END}, -}; - -static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) -{ - reg_clkgen_rw_clk_ctrl clk_ctrl; - clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); - return clk_ctrl.pll ? 200000 : 6000; -} - -static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) -{ - reg_clkgen_rw_clk_ctrl clk_ctrl; - clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl); - - local_irq_disable(); - - /* Even though we may be SMP they will share the same clock - * so all settings are made on CPU0. */ - if (cris_freq_table[state].frequency == 200000) - clk_ctrl.pll = 1; - else - clk_ctrl.pll = 0; - REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl); - - local_irq_enable(); - - return 0; -} - -static int cris_freq_cpu_init(struct cpufreq_policy *policy) -{ - return cpufreq_generic_init(policy, cris_freq_table, 1000000); -} - -static struct cpufreq_driver cris_freq_driver = { - .get = cris_freq_get_cpu_frequency, - .verify = cpufreq_generic_frequency_table_verify, - .target_index = cris_freq_target, - .init = cris_freq_cpu_init, - .name = "cris_freq", - .attr = cpufreq_generic_attr, -}; - -static int __init cris_freq_init(void) -{ - int ret; - ret = cpufreq_register_driver(&cris_freq_driver); - cpufreq_register_notifier(&cris_sdram_freq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - return ret; -} - -static int -cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - int i; - struct cpufreq_freqs *freqs = data; - if (val == CPUFREQ_PRECHANGE) { - reg_ddr2_rw_cfg cfg = - REG_RD(ddr2, regi_ddr2_ctrl, rw_cfg); - cfg.ref_interval = (freqs->new == 200000 ? 1560 : 46); - - if (freqs->new == 200000) - for (i = 0; i < 50000; i++); - REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing); - } - return 0; -} - - -module_init(cris_freq_init); diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c deleted file mode 100644 index 4c4b5dd685e3..000000000000 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/init.h> -#include <linux/module.h> -#include <linux/cpufreq.h> -#include <hwregs/reg_map.h> -#include <arch/hwregs/reg_rdwr.h> -#include <arch/hwregs/config_defs.h> -#include <arch/hwregs/bif_core_defs.h> - -static int -cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, - void *data); - -static struct notifier_block cris_sdram_freq_notifier_block = { - .notifier_call = cris_sdram_freq_notifier -}; - -static struct cpufreq_frequency_table cris_freq_table[] = { - {0, 0x01, 6000}, - {0, 0x02, 200000}, - {0, 0, CPUFREQ_TABLE_END}, -}; - -static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu) -{ - reg_config_rw_clk_ctrl clk_ctrl; - clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); - return clk_ctrl.pll ? 200000 : 6000; -} - -static int cris_freq_target(struct cpufreq_policy *policy, unsigned int state) -{ - reg_config_rw_clk_ctrl clk_ctrl; - clk_ctrl = REG_RD(config, regi_config, rw_clk_ctrl); - - local_irq_disable(); - - /* Even though we may be SMP they will share the same clock - * so all settings are made on CPU0. */ - if (cris_freq_table[state].frequency == 200000) - clk_ctrl.pll = 1; - else - clk_ctrl.pll = 0; - REG_WR(config, regi_config, rw_clk_ctrl, clk_ctrl); - - local_irq_enable(); - - return 0; -} - -static int cris_freq_cpu_init(struct cpufreq_policy *policy) -{ - return cpufreq_generic_init(policy, cris_freq_table, 1000000); -} - -static struct cpufreq_driver cris_freq_driver = { - .get = cris_freq_get_cpu_frequency, - .verify = cpufreq_generic_frequency_table_verify, - .target_index = cris_freq_target, - .init = cris_freq_cpu_init, - .name = "cris_freq", - .attr = cpufreq_generic_attr, -}; - -static int __init cris_freq_init(void) -{ - int ret; - ret = cpufreq_register_driver(&cris_freq_driver); - cpufreq_register_notifier(&cris_sdram_freq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - return ret; -} - -static int -cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - int i; - struct cpufreq_freqs *freqs = data; - if (val == CPUFREQ_PRECHANGE) { - reg_bif_core_rw_sdram_timing timing = - REG_RD(bif_core, regi_bif_core, rw_sdram_timing); - timing.cpd = (freqs->new == 200000 ? 0 : 1); - - if (freqs->new == 200000) - for (i = 0; i < 50000; i++) ; - REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing); - } - return 0; -} - -module_init(cris_freq_init); diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 3c4017007647..cfcb91056f23 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -317,14 +317,6 @@ config EDAC_CPC925 a companion chip to the PowerPC 970 family of processors. -config EDAC_TILE - tristate "Tilera Memory Controller" - depends on TILE - default y - help - Support for error detection and correction on the - Tilera memory controller. - config EDAC_HIGHBANK_MC tristate "Highbank Memory Controller" depends on ARCH_HIGHBANK diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index b54912eb39af..02b43a7d8c3e 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -64,8 +64,6 @@ obj-$(CONFIG_EDAC_PPC4XX) += ppc4xx_edac.o obj-$(CONFIG_EDAC_AMD8111) += amd8111_edac.o obj-$(CONFIG_EDAC_AMD8131) += amd8131_edac.o -obj-$(CONFIG_EDAC_TILE) += tile_edac.o - obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c deleted file mode 100644 index 8a33a87e67f1..000000000000 --- a/drivers/edac/tile_edac.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2011 Tilera Corporation. All Rights Reserved. - * - * 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. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - * Tilera-specific EDAC driver. - * - * This source code is derived from the following driver: - * - * Cell MIC driver for ECC counting - * - * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. - * <benh@kernel.crashing.org> - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/uaccess.h> -#include <linux/edac.h> -#include <hv/hypervisor.h> -#include <hv/drv_mshim_intf.h> - -#include "edac_module.h" - -#define DRV_NAME "tile-edac" - -/* Number of cs_rows needed per memory controller on TILEPro. */ -#define TILE_EDAC_NR_CSROWS 1 - -/* Number of channels per memory controller on TILEPro. */ -#define TILE_EDAC_NR_CHANS 1 - -/* Granularity of reported error in bytes on TILEPro. */ -#define TILE_EDAC_ERROR_GRAIN 8 - -/* TILE processor has multiple independent memory controllers. */ -struct platform_device *mshim_pdev[TILE_MAX_MSHIMS]; - -struct tile_edac_priv { - int hv_devhdl; /* Hypervisor device handle. */ - int node; /* Memory controller instance #. */ - unsigned int ce_count; /* - * Correctable-error counter - * kept by the driver. - */ -}; - -static void tile_edac_check(struct mem_ctl_info *mci) -{ - struct tile_edac_priv *priv = mci->pvt_info; - struct mshim_mem_error mem_error; - - if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_error, - sizeof(struct mshim_mem_error), MSHIM_MEM_ERROR_OFF) != - sizeof(struct mshim_mem_error)) { - pr_err(DRV_NAME ": MSHIM_MEM_ERROR_OFF pread failure.\n"); - return; - } - - /* Check if the current error count is different from the saved one. */ - if (mem_error.sbe_count != priv->ce_count) { - dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node); - priv->ce_count = mem_error.sbe_count; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, - 0, 0, 0, - 0, 0, -1, - mci->ctl_name, ""); - } -} - -/* - * Initialize the 'csrows' table within the mci control structure with the - * addressing of memory. - */ -static int tile_edac_init_csrows(struct mem_ctl_info *mci) -{ - struct csrow_info *csrow = mci->csrows[0]; - struct tile_edac_priv *priv = mci->pvt_info; - struct mshim_mem_info mem_info; - struct dimm_info *dimm = csrow->channels[0]->dimm; - - if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info, - sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) != - sizeof(struct mshim_mem_info)) { - pr_err(DRV_NAME ": MSHIM_MEM_INFO_OFF pread failure.\n"); - return -1; - } - - if (mem_info.mem_ecc) - dimm->edac_mode = EDAC_SECDED; - else - dimm->edac_mode = EDAC_NONE; - switch (mem_info.mem_type) { - case DDR2: - dimm->mtype = MEM_DDR2; - break; - - case DDR3: - dimm->mtype = MEM_DDR3; - break; - - default: - return -1; - } - - dimm->nr_pages = mem_info.mem_size >> PAGE_SHIFT; - dimm->grain = TILE_EDAC_ERROR_GRAIN; - dimm->dtype = DEV_UNKNOWN; - - return 0; -} - -static int tile_edac_mc_probe(struct platform_device *pdev) -{ - char hv_file[32]; - int hv_devhdl; - struct mem_ctl_info *mci; - struct edac_mc_layer layers[2]; - struct tile_edac_priv *priv; - int rc; - - sprintf(hv_file, "mshim/%d", pdev->id); - hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0); - if (hv_devhdl < 0) - return -EINVAL; - - /* A TILE MC has a single channel and one chip-select row. */ - layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; - layers[0].size = TILE_EDAC_NR_CSROWS; - layers[0].is_virt_csrow = true; - layers[1].type = EDAC_MC_LAYER_CHANNEL; - layers[1].size = TILE_EDAC_NR_CHANS; - layers[1].is_virt_csrow = false; - mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, - sizeof(struct tile_edac_priv)); - if (mci == NULL) - return -ENOMEM; - priv = mci->pvt_info; - priv->node = pdev->id; - priv->hv_devhdl = hv_devhdl; - - mci->pdev = &pdev->dev; - mci->mtype_cap = MEM_FLAG_DDR2; - mci->edac_ctl_cap = EDAC_FLAG_SECDED; - - mci->mod_name = DRV_NAME; -#ifdef __tilegx__ - mci->ctl_name = "TILEGx_Memory_Controller"; -#else - mci->ctl_name = "TILEPro_Memory_Controller"; -#endif - mci->dev_name = dev_name(&pdev->dev); - mci->edac_check = tile_edac_check; - - /* - * Initialize the MC control structure 'csrows' table - * with the mapping and control information. - */ - if (tile_edac_init_csrows(mci)) { - /* No csrows found. */ - mci->edac_cap = EDAC_FLAG_NONE; - } else { - mci->edac_cap = EDAC_FLAG_SECDED; - } - - platform_set_drvdata(pdev, mci); - - /* Register with EDAC core */ - rc = edac_mc_add_mc(mci); - if (rc) { - dev_err(&pdev->dev, "failed to register with EDAC core\n"); - edac_mc_free(mci); - return rc; - } - - return 0; -} - -static int tile_edac_mc_remove(struct platform_device *pdev) -{ - struct mem_ctl_info *mci = platform_get_drvdata(pdev); - - edac_mc_del_mc(&pdev->dev); - if (mci) - edac_mc_free(mci); - return 0; -} - -static struct platform_driver tile_edac_mc_driver = { - .driver = { - .name = DRV_NAME, - }, - .probe = tile_edac_mc_probe, - .remove = tile_edac_mc_remove, -}; - -/* - * Driver init routine. - */ -static int __init tile_edac_init(void) -{ - char hv_file[32]; - struct platform_device *pdev; - int i, err, num = 0; - - /* Only support POLL mode. */ - edac_op_state = EDAC_OPSTATE_POLL; - - err = platform_driver_register(&tile_edac_mc_driver); - if (err) - return err; - - for (i = 0; i < TILE_MAX_MSHIMS; i++) { - /* - * Not all memory controllers are configured such as in the - * case of a simulator. So we register only those mshims - * that are configured by the hypervisor. - */ - sprintf(hv_file, "mshim/%d", i); - if (hv_dev_open((HV_VirtAddr)hv_file, 0) < 0) - continue; - - pdev = platform_device_register_simple(DRV_NAME, i, NULL, 0); - if (IS_ERR(pdev)) - continue; - mshim_pdev[i] = pdev; - num++; - } - - if (num == 0) { - platform_driver_unregister(&tile_edac_mc_driver); - return -ENODEV; - } - return 0; -} - -/* - * Driver cleanup routine. - */ -static void __exit tile_edac_exit(void) -{ - int i; - - for (i = 0; i < TILE_MAX_MSHIMS; i++) { - struct platform_device *pdev = mshim_pdev[i]; - if (!pdev) - continue; - - platform_device_unregister(pdev); - } - platform_driver_unregister(&tile_edac_mc_driver); -} - -module_init(tile_edac_init); -module_exit(tile_edac_exit); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8dbb2280538d..68d812b38be7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -170,15 +170,6 @@ config GPIO_EP93XX depends on ARCH_EP93XX select GPIO_GENERIC -config GPIO_ETRAXFS - bool "Axis ETRAX FS General I/O" - depends on CRIS || COMPILE_TEST - depends on OF_GPIO - select GPIO_GENERIC - select GPIOLIB_IRQCHIP - help - Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. - config GPIO_EXAR tristate "Support for GPIO pins on XR17V352/354/358" depends on SERIAL_8250_EXAR diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index cccb0d40846c..db8c9d4ea2ef 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o -obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o diff --git a/drivers/gpio/gpio-etraxfs.c b/drivers/gpio/gpio-etraxfs.c deleted file mode 100644 index 94db1bf4bfdb..000000000000 --- a/drivers/gpio/gpio-etraxfs.c +++ /dev/null @@ -1,475 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/gpio/driver.h> -#include <linux/of_gpio.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> - -#define ETRAX_FS_rw_pa_dout 0 -#define ETRAX_FS_r_pa_din 4 -#define ETRAX_FS_rw_pa_oe 8 -#define ETRAX_FS_rw_intr_cfg 12 -#define ETRAX_FS_rw_intr_mask 16 -#define ETRAX_FS_rw_ack_intr 20 -#define ETRAX_FS_r_intr 24 -#define ETRAX_FS_r_masked_intr 28 -#define ETRAX_FS_rw_pb_dout 32 -#define ETRAX_FS_r_pb_din 36 -#define ETRAX_FS_rw_pb_oe 40 -#define ETRAX_FS_rw_pc_dout 48 -#define ETRAX_FS_r_pc_din 52 -#define ETRAX_FS_rw_pc_oe 56 -#define ETRAX_FS_rw_pd_dout 64 -#define ETRAX_FS_r_pd_din 68 -#define ETRAX_FS_rw_pd_oe 72 -#define ETRAX_FS_rw_pe_dout 80 -#define ETRAX_FS_r_pe_din 84 -#define ETRAX_FS_rw_pe_oe 88 - -#define ARTPEC3_r_pa_din 0 -#define ARTPEC3_rw_pa_dout 4 -#define ARTPEC3_rw_pa_oe 8 -#define ARTPEC3_r_pb_din 44 -#define ARTPEC3_rw_pb_dout 48 -#define ARTPEC3_rw_pb_oe 52 -#define ARTPEC3_r_pc_din 88 -#define ARTPEC3_rw_pc_dout 92 -#define ARTPEC3_rw_pc_oe 96 -#define ARTPEC3_r_pd_din 116 -#define ARTPEC3_rw_intr_cfg 120 -#define ARTPEC3_rw_intr_pins 124 -#define ARTPEC3_rw_intr_mask 128 -#define ARTPEC3_rw_ack_intr 132 -#define ARTPEC3_r_masked_intr 140 - -#define GIO_CFG_OFF 0 -#define GIO_CFG_HI 1 -#define GIO_CFG_LO 2 -#define GIO_CFG_SET 3 -#define GIO_CFG_POSEDGE 5 -#define GIO_CFG_NEGEDGE 6 -#define GIO_CFG_ANYEDGE 7 - -struct etraxfs_gpio_info; - -struct etraxfs_gpio_block { - raw_spinlock_t lock; - u32 mask; - u32 cfg; - u32 pins; - unsigned int group[8]; - - void __iomem *regs; - const struct etraxfs_gpio_info *info; -}; - -struct etraxfs_gpio_chip { - struct gpio_chip gc; - struct etraxfs_gpio_block *block; -}; - -struct etraxfs_gpio_port { - const char *label; - unsigned int oe; - unsigned int dout; - unsigned int din; - unsigned int ngpio; -}; - -struct etraxfs_gpio_info { - unsigned int num_ports; - const struct etraxfs_gpio_port *ports; - - unsigned int rw_ack_intr; - unsigned int rw_intr_mask; - unsigned int rw_intr_cfg; - unsigned int rw_intr_pins; - unsigned int r_masked_intr; -}; - -static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { - { - .label = "A", - .ngpio = 8, - .oe = ETRAX_FS_rw_pa_oe, - .dout = ETRAX_FS_rw_pa_dout, - .din = ETRAX_FS_r_pa_din, - }, - { - .label = "B", - .ngpio = 18, - .oe = ETRAX_FS_rw_pb_oe, - .dout = ETRAX_FS_rw_pb_dout, - .din = ETRAX_FS_r_pb_din, - }, - { - .label = "C", - .ngpio = 18, - .oe = ETRAX_FS_rw_pc_oe, - .dout = ETRAX_FS_rw_pc_dout, - .din = ETRAX_FS_r_pc_din, - }, - { - .label = "D", - .ngpio = 18, - .oe = ETRAX_FS_rw_pd_oe, - .dout = ETRAX_FS_rw_pd_dout, - .din = ETRAX_FS_r_pd_din, - }, - { - .label = "E", - .ngpio = 18, - .oe = ETRAX_FS_rw_pe_oe, - .dout = ETRAX_FS_rw_pe_dout, - .din = ETRAX_FS_r_pe_din, - }, -}; - -static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = { - .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), - .ports = etraxfs_gpio_etraxfs_ports, - .rw_ack_intr = ETRAX_FS_rw_ack_intr, - .rw_intr_mask = ETRAX_FS_rw_intr_mask, - .rw_intr_cfg = ETRAX_FS_rw_intr_cfg, - .r_masked_intr = ETRAX_FS_r_masked_intr, -}; - -static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = { - { - .label = "A", - .ngpio = 32, - .oe = ARTPEC3_rw_pa_oe, - .dout = ARTPEC3_rw_pa_dout, - .din = ARTPEC3_r_pa_din, - }, - { - .label = "B", - .ngpio = 32, - .oe = ARTPEC3_rw_pb_oe, - .dout = ARTPEC3_rw_pb_dout, - .din = ARTPEC3_r_pb_din, - }, - { - .label = "C", - .ngpio = 16, - .oe = ARTPEC3_rw_pc_oe, - .dout = ARTPEC3_rw_pc_dout, - .din = ARTPEC3_r_pc_din, - }, - { - .label = "D", - .ngpio = 32, - .din = ARTPEC3_r_pd_din, - }, -}; - -static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = { - .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports), - .ports = etraxfs_gpio_artpec3_ports, - .rw_ack_intr = ARTPEC3_rw_ack_intr, - .rw_intr_mask = ARTPEC3_rw_intr_mask, - .rw_intr_cfg = ARTPEC3_rw_intr_cfg, - .r_masked_intr = ARTPEC3_r_masked_intr, - .rw_intr_pins = ARTPEC3_rw_intr_pins, -}; - -static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc) -{ - return gc->label[0] - 'A'; -} - -static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, - const struct of_phandle_args *gpiospec, - u32 *flags) -{ - /* - * Port numbers are A to E, and the properties are integers, so we - * specify them as 0xA - 0xE. - */ - if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2]) - return -EINVAL; - - return of_gpio_simple_xlate(gc, gpiospec, flags); -} - -static const struct of_device_id etraxfs_gpio_of_table[] = { - { - .compatible = "axis,etraxfs-gio", - .data = &etraxfs_gpio_etraxfs, - }, - { - .compatible = "axis,artpec3-gio", - .data = &etraxfs_gpio_artpec3, - }, - {}, -}; - -static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio) -{ - return gpio % 8; -} - -static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip, - unsigned int gpio) -{ - return 4 * etraxfs_gpio_chip_to_port(&chip->gc) + gpio / 8; -} - -static void etraxfs_gpio_irq_ack(struct irq_data *d) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - - writel(BIT(grpirq), block->regs + block->info->rw_ack_intr); -} - -static void etraxfs_gpio_irq_mask(struct irq_data *d) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - - raw_spin_lock(&block->lock); - block->mask &= ~BIT(grpirq); - writel(block->mask, block->regs + block->info->rw_intr_mask); - raw_spin_unlock(&block->lock); -} - -static void etraxfs_gpio_irq_unmask(struct irq_data *d) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - - raw_spin_lock(&block->lock); - block->mask |= BIT(grpirq); - writel(block->mask, block->regs + block->info->rw_intr_mask); - raw_spin_unlock(&block->lock); -} - -static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - u32 cfg; - - switch (type) { - case IRQ_TYPE_EDGE_RISING: - cfg = GIO_CFG_POSEDGE; - break; - case IRQ_TYPE_EDGE_FALLING: - cfg = GIO_CFG_NEGEDGE; - break; - case IRQ_TYPE_EDGE_BOTH: - cfg = GIO_CFG_ANYEDGE; - break; - case IRQ_TYPE_LEVEL_LOW: - cfg = GIO_CFG_LO; - break; - case IRQ_TYPE_LEVEL_HIGH: - cfg = GIO_CFG_HI; - break; - default: - return -EINVAL; - } - - raw_spin_lock(&block->lock); - block->cfg &= ~(0x7 << (grpirq * 3)); - block->cfg |= (cfg << (grpirq * 3)); - writel(block->cfg, block->regs + block->info->rw_intr_cfg); - raw_spin_unlock(&block->lock); - - return 0; -} - -static int etraxfs_gpio_irq_request_resources(struct irq_data *d) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - int ret = -EBUSY; - - raw_spin_lock(&block->lock); - if (block->group[grpirq]) - goto out; - - ret = gpiochip_lock_as_irq(&chip->gc, d->hwirq); - if (ret) - goto out; - - block->group[grpirq] = d->irq; - if (block->info->rw_intr_pins) { - unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq); - - block->pins &= ~(0xf << (grpirq * 4)); - block->pins |= (pin << (grpirq * 4)); - - writel(block->pins, block->regs + block->info->rw_intr_pins); - } - -out: - raw_spin_unlock(&block->lock); - return ret; -} - -static void etraxfs_gpio_irq_release_resources(struct irq_data *d) -{ - struct etraxfs_gpio_chip *chip = - gpiochip_get_data(irq_data_get_irq_chip_data(d)); - struct etraxfs_gpio_block *block = chip->block; - unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); - - raw_spin_lock(&block->lock); - block->group[grpirq] = 0; - gpiochip_unlock_as_irq(&chip->gc, d->hwirq); - raw_spin_unlock(&block->lock); -} - -static struct irq_chip etraxfs_gpio_irq_chip = { - .name = "gpio-etraxfs", - .irq_ack = etraxfs_gpio_irq_ack, - .irq_mask = etraxfs_gpio_irq_mask, - .irq_unmask = etraxfs_gpio_irq_unmask, - .irq_set_type = etraxfs_gpio_irq_set_type, - .irq_request_resources = etraxfs_gpio_irq_request_resources, - .irq_release_resources = etraxfs_gpio_irq_release_resources, -}; - -static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id) -{ - struct etraxfs_gpio_block *block = dev_id; - unsigned long intr = readl(block->regs + block->info->r_masked_intr); - int bit; - - for_each_set_bit(bit, &intr, 8) - generic_handle_irq(block->group[bit]); - - return IRQ_RETVAL(intr & 0xff); -} - -static int etraxfs_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - const struct etraxfs_gpio_info *info; - const struct of_device_id *match; - struct etraxfs_gpio_block *block; - struct etraxfs_gpio_chip *chips; - struct resource *res, *irq; - bool allportsirq = false; - void __iomem *regs; - int ret; - int i; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs = devm_ioremap_resource(dev, res); - if (IS_ERR(regs)) - return PTR_ERR(regs); - - match = of_match_node(etraxfs_gpio_of_table, dev->of_node); - if (!match) - return -EINVAL; - - info = match->data; - - chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL); - if (!chips) - return -ENOMEM; - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) - return -EINVAL; - - block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL); - if (!block) - return -ENOMEM; - - raw_spin_lock_init(&block->lock); - - block->regs = regs; - block->info = info; - - writel(0, block->regs + info->rw_intr_mask); - writel(0, block->regs + info->rw_intr_cfg); - if (info->rw_intr_pins) { - allportsirq = true; - writel(0, block->regs + info->rw_intr_pins); - } - - ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt, - IRQF_SHARED, dev_name(dev), block); - if (ret) { - dev_err(dev, "Unable to request irq %d\n", ret); - return ret; - } - - for (i = 0; i < info->num_ports; i++) { - struct etraxfs_gpio_chip *chip = &chips[i]; - struct gpio_chip *gc = &chip->gc; - const struct etraxfs_gpio_port *port = &info->ports[i]; - unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET; - void __iomem *dat = regs + port->din; - void __iomem *set = regs + port->dout; - void __iomem *dirout = regs + port->oe; - - chip->block = block; - - if (dirout == set) { - dirout = set = NULL; - flags = BGPIOF_NO_OUTPUT; - } - - ret = bgpio_init(gc, dev, 4, - dat, set, NULL, dirout, NULL, - flags); - if (ret) { - dev_err(dev, "Unable to init port %s\n", - port->label); - continue; - } - - gc->ngpio = port->ngpio; - gc->label = port->label; - - gc->of_node = dev->of_node; - gc->of_gpio_n_cells = 3; - gc->of_xlate = etraxfs_gpio_of_xlate; - - ret = gpiochip_add_data(gc, chip); - if (ret) { - dev_err(dev, "Unable to register port %s\n", - gc->label); - continue; - } - - if (i > 0 && !allportsirq) - continue; - - ret = gpiochip_irqchip_add(gc, &etraxfs_gpio_irq_chip, 0, - handle_level_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "Unable to add irqchip to port %s\n", - gc->label); - } - } - - return 0; -} - -static struct platform_driver etraxfs_gpio_driver = { - .driver = { - .name = "etraxfs-gpio", - .of_match_table = of_match_ptr(etraxfs_gpio_of_table), - }, - .probe = etraxfs_gpio_probe, -}; - -builtin_platform_driver(etraxfs_gpio_driver); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e2954fb86d65..4c0895165727 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -445,24 +445,6 @@ config I2C_BRCMSTB If you do not need I2C interface, say N. -config I2C_BLACKFIN_TWI - tristate "Blackfin TWI I2C support" - depends on BLACKFIN - depends on !BF561 && !BF531 && !BF532 && !BF533 - help - This is the I2C bus driver for Blackfin on-chip TWI interface. - - This driver can also be built as a module. If so, the module - will be called i2c-bfin-twi. - -config I2C_BLACKFIN_TWI_CLK_KHZ - int "Blackfin TWI I2C clock (kHz)" - depends on I2C_BLACKFIN_TWI - range 21 400 - default 50 - help - The unit of the TWI clock is kHz. - config I2C_CADENCE tristate "Cadence I2C Controller" depends on ARCH_ZYNQ || ARM64 || XTENSA @@ -637,7 +619,7 @@ config I2C_IBM_IIC config I2C_IMG tristate "Imagination Technologies I2C SCB Controller" - depends on MIPS || METAG || COMPILE_TEST + depends on MIPS || COMPILE_TEST help Say Y here if you want to use the IMG I2C SCB controller, available on the TZ1090 and other IMG SoCs. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2ce8576540a2..9e475a54e36e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AXXIA) += i2c-axxia.o obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o obj-$(CONFIG_I2C_BCM_IPROC) += i2c-bcm-iproc.o -obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c deleted file mode 100644 index ff3343186a82..000000000000 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Blackfin On-Chip Two Wire Interface Driver - * - * Copyright 2005-2007 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/mm.h> -#include <linux/timer.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/delay.h> - -#include <asm/irq.h> -#include <asm/portmux.h> -#include <asm/bfin_twi.h> - -/* SMBus mode*/ -#define TWI_I2C_MODE_STANDARD 1 -#define TWI_I2C_MODE_STANDARDSUB 2 -#define TWI_I2C_MODE_COMBINED 3 -#define TWI_I2C_MODE_REPEAT 4 - -static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, - unsigned short twi_int_status) -{ - unsigned short mast_stat = read_MASTER_STAT(iface); - - if (twi_int_status & XMTSERV) { - if (iface->writeNum <= 0) { - /* start receive immediately after complete sending in - * combine mode. - */ - if (iface->cur_mode == TWI_I2C_MODE_COMBINED) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MDIR); - else if (iface->manual_stop) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | STOP); - else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - if (iface->pmsg[iface->cur_msg + 1].flags & - I2C_M_RD) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | - MDIR); - else - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & - ~MDIR); - } - } - /* Transmit next data */ - while (iface->writeNum > 0 && - (read_FIFO_STAT(iface) & XMTSTAT) != XMT_FULL) { - write_XMT_DATA8(iface, *(iface->transPtr++)); - iface->writeNum--; - } - } - if (twi_int_status & RCVSERV) { - while (iface->readNum > 0 && - (read_FIFO_STAT(iface) & RCVSTAT)) { - /* Receive next data */ - *(iface->transPtr) = read_RCV_DATA8(iface); - if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { - /* Change combine mode into sub mode after - * read first data. - */ - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - /* Get read number from first byte in block - * combine mode. - */ - if (iface->readNum == 1 && iface->manual_stop) - iface->readNum = *iface->transPtr + 1; - } - iface->transPtr++; - iface->readNum--; - } - - if (iface->readNum == 0) { - if (iface->manual_stop) { - /* Temporary workaround to avoid possible bus stall - - * Flush FIFO before issuing the STOP condition - */ - read_RCV_DATA16(iface); - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | STOP); - } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MDIR); - else - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~MDIR); - } - } - } - if (twi_int_status & MERR) { - write_INT_MASK(iface, 0); - write_MASTER_STAT(iface, 0x3e); - write_MASTER_CTL(iface, 0); - iface->result = -EIO; - - if (mast_stat & LOSTARB) - dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); - if (mast_stat & ANAK) - dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); - if (mast_stat & DNAK) - dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); - if (mast_stat & BUFRDERR) - dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); - if (mast_stat & BUFWRERR) - dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); - - /* Faulty slave devices, may drive SDA low after a transfer - * finishes. To release the bus this code generates up to 9 - * extra clocks until SDA is released. - */ - - if (read_MASTER_STAT(iface) & SDASEN) { - int cnt = 9; - do { - write_MASTER_CTL(iface, SCLOVR); - udelay(6); - write_MASTER_CTL(iface, 0); - udelay(6); - } while ((read_MASTER_STAT(iface) & SDASEN) && cnt--); - - write_MASTER_CTL(iface, SDAOVR | SCLOVR); - udelay(6); - write_MASTER_CTL(iface, SDAOVR); - udelay(6); - write_MASTER_CTL(iface, 0); - } - - /* If it is a quick transfer, only address without data, - * not an err, return 1. - */ - if (iface->cur_mode == TWI_I2C_MODE_STANDARD && - iface->transPtr == NULL && - (twi_int_status & MCOMP) && (mast_stat & DNAK)) - iface->result = 1; - - complete(&iface->complete); - return; - } - if (twi_int_status & MCOMP) { - if (twi_int_status & (XMTSERV | RCVSERV) && - (read_MASTER_CTL(iface) & MEN) == 0 && - (iface->cur_mode == TWI_I2C_MODE_REPEAT || - iface->cur_mode == TWI_I2C_MODE_COMBINED)) { - iface->result = -1; - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - } else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { - if (iface->readNum == 0) { - /* set the read number to 1 and ask for manual - * stop in block combine mode - */ - iface->readNum = 1; - iface->manual_stop = 1; - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | (0xff << 6)); - } else { - /* set the readd number in other - * combine mode. - */ - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) & - (~(0xff << 6))) | - (iface->readNum << 6)); - } - /* remove restart bit and enable master receive */ - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~RSTART); - } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - iface->cur_msg++; - iface->transPtr = iface->pmsg[iface->cur_msg].buf; - iface->writeNum = iface->readNum = - iface->pmsg[iface->cur_msg].len; - /* Set Transmit device address */ - write_MASTER_ADDR(iface, - iface->pmsg[iface->cur_msg].addr); - if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD) - iface->read_write = I2C_SMBUS_READ; - else { - iface->read_write = I2C_SMBUS_WRITE; - /* Transmit first data */ - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, - *(iface->transPtr++)); - iface->writeNum--; - } - } - - if (iface->pmsg[iface->cur_msg].len <= 255) { - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) & - (~(0xff << 6))) | - (iface->pmsg[iface->cur_msg].len << 6)); - iface->manual_stop = 0; - } else { - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) | - (0xff << 6))); - iface->manual_stop = 1; - } - /* remove restart bit before last message */ - if (iface->cur_msg + 1 == iface->msg_num) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~RSTART); - } else { - iface->result = 1; - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - } - complete(&iface->complete); - } -} - -/* Interrupt handler */ -static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) -{ - struct bfin_twi_iface *iface = dev_id; - unsigned long flags; - unsigned short twi_int_status; - - spin_lock_irqsave(&iface->lock, flags); - while (1) { - twi_int_status = read_INT_STAT(iface); - if (!twi_int_status) - break; - /* Clear interrupt status */ - write_INT_STAT(iface, twi_int_status); - bfin_twi_handle_interrupt(iface, twi_int_status); - } - spin_unlock_irqrestore(&iface->lock, flags); - return IRQ_HANDLED; -} - -/* - * One i2c master transfer - */ -static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct bfin_twi_iface *iface = adap->algo_data; - struct i2c_msg *pmsg; - int rc = 0; - - if (!(read_CONTROL(iface) & TWI_ENA)) - return -ENXIO; - - if (read_MASTER_STAT(iface) & BUSBUSY) - return -EAGAIN; - - iface->pmsg = msgs; - iface->msg_num = num; - iface->cur_msg = 0; - - pmsg = &msgs[0]; - if (pmsg->flags & I2C_M_TEN) { - dev_err(&adap->dev, "10 bits addr not supported!\n"); - return -EINVAL; - } - - if (iface->msg_num > 1) - iface->cur_mode = TWI_I2C_MODE_REPEAT; - iface->manual_stop = 0; - iface->transPtr = pmsg->buf; - iface->writeNum = iface->readNum = pmsg->len; - iface->result = 0; - init_completion(&(iface->complete)); - /* Set Transmit device address */ - write_MASTER_ADDR(iface, pmsg->addr); - - /* FIFO Initiation. Data in FIFO should be - * discarded before start a new operation. - */ - write_FIFO_CTL(iface, 0x3); - write_FIFO_CTL(iface, 0); - - if (pmsg->flags & I2C_M_RD) - iface->read_write = I2C_SMBUS_READ; - else { - iface->read_write = I2C_SMBUS_WRITE; - /* Transmit first data */ - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, *(iface->transPtr++)); - iface->writeNum--; - } - } - - /* clear int stat */ - write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV); - - /* Interrupt mask . Enable XMT, RCV interrupt */ - write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - - if (pmsg->len <= 255) - write_MASTER_CTL(iface, pmsg->len << 6); - else { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } - - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - (iface->msg_num > 1 ? RSTART : 0) | - ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); - - while (!iface->result) { - if (!wait_for_completion_timeout(&iface->complete, - adap->timeout)) { - iface->result = -1; - dev_err(&adap->dev, "master transfer timeout\n"); - } - } - - if (iface->result == 1) - rc = iface->cur_msg + 1; - else - rc = iface->result; - - return rc; -} - -/* - * Generic i2c master transfer entrypoint - */ -static int bfin_twi_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - return bfin_twi_do_master_xfer(adap, msgs, num); -} - -/* - * One I2C SMBus transfer - */ -int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - struct bfin_twi_iface *iface = adap->algo_data; - int rc = 0; - - if (!(read_CONTROL(iface) & TWI_ENA)) - return -ENXIO; - - if (read_MASTER_STAT(iface) & BUSBUSY) - return -EAGAIN; - - iface->writeNum = 0; - iface->readNum = 0; - - /* Prepare datas & select mode */ - switch (size) { - case I2C_SMBUS_QUICK: - iface->transPtr = NULL; - iface->cur_mode = TWI_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE: - if (data == NULL) - iface->transPtr = NULL; - else { - if (read_write == I2C_SMBUS_READ) - iface->readNum = 1; - else - iface->writeNum = 1; - iface->transPtr = &data->byte; - } - iface->cur_mode = TWI_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 1; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = 1; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = &data->byte; - break; - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 2; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = 2; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = (u8 *)&data->word; - break; - case I2C_SMBUS_PROC_CALL: - iface->writeNum = 2; - iface->readNum = 2; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - iface->transPtr = (u8 *)&data->word; - break; - case I2C_SMBUS_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 0; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = data->block[0] + 1; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = data->block; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = data->block[0]; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = data->block[0]; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = (u8 *)&data->block[1]; - break; - default: - return -1; - } - - iface->result = 0; - iface->manual_stop = 0; - iface->read_write = read_write; - iface->command = command; - init_completion(&(iface->complete)); - - /* FIFO Initiation. Data in FIFO should be discarded before - * start a new operation. - */ - write_FIFO_CTL(iface, 0x3); - write_FIFO_CTL(iface, 0); - - /* clear int stat */ - write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV); - - /* Set Transmit device address */ - write_MASTER_ADDR(iface, addr); - - switch (iface->cur_mode) { - case TWI_I2C_MODE_STANDARDSUB: - write_XMT_DATA8(iface, iface->command); - write_INT_MASK(iface, MCOMP | MERR | - ((iface->read_write == I2C_SMBUS_READ) ? - RCVSERV : XMTSERV)); - - if (iface->writeNum + 1 <= 255) - write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); - else { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); - break; - case TWI_I2C_MODE_COMBINED: - write_XMT_DATA8(iface, iface->command); - write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - - if (iface->writeNum > 0) - write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); - else - write_MASTER_CTL(iface, 0x1 << 6); - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | RSTART | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); - break; - default: - write_MASTER_CTL(iface, 0); - if (size != I2C_SMBUS_QUICK) { - /* Don't access xmit data register when this is a - * read operation. - */ - if (iface->read_write != I2C_SMBUS_READ) { - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, - *(iface->transPtr++)); - if (iface->writeNum <= 255) - write_MASTER_CTL(iface, - iface->writeNum << 6); - else { - write_MASTER_CTL(iface, - 0xff << 6); - iface->manual_stop = 1; - } - iface->writeNum--; - } else { - write_XMT_DATA8(iface, iface->command); - write_MASTER_CTL(iface, 1 << 6); - } - } else { - if (iface->readNum > 0 && iface->readNum <= 255) - write_MASTER_CTL(iface, - iface->readNum << 6); - else if (iface->readNum > 255) { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } else - break; - } - } - write_INT_MASK(iface, MCOMP | MERR | - ((iface->read_write == I2C_SMBUS_READ) ? - RCVSERV : XMTSERV)); - - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); - break; - } - - while (!iface->result) { - if (!wait_for_completion_timeout(&iface->complete, - adap->timeout)) { - iface->result = -1; - dev_err(&adap->dev, "smbus transfer timeout\n"); - } - } - - rc = (iface->result >= 0) ? 0 : -1; - - return rc; -} - -/* - * Generic I2C SMBus transfer entrypoint - */ -int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - return bfin_twi_do_smbus_xfer(adap, addr, flags, - read_write, command, size, data); -} - -/* - * Return what the adapter supports - */ -static u32 bfin_twi_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK; -} - -static const struct i2c_algorithm bfin_twi_algorithm = { - .master_xfer = bfin_twi_master_xfer, - .smbus_xfer = bfin_twi_smbus_xfer, - .functionality = bfin_twi_functionality, -}; - -#ifdef CONFIG_PM_SLEEP -static int i2c_bfin_twi_suspend(struct device *dev) -{ - struct bfin_twi_iface *iface = dev_get_drvdata(dev); - - iface->saved_clkdiv = read_CLKDIV(iface); - iface->saved_control = read_CONTROL(iface); - - free_irq(iface->irq, iface); - - /* Disable TWI */ - write_CONTROL(iface, iface->saved_control & ~TWI_ENA); - - return 0; -} - -static int i2c_bfin_twi_resume(struct device *dev) -{ - struct bfin_twi_iface *iface = dev_get_drvdata(dev); - - int rc = request_irq(iface->irq, bfin_twi_interrupt_entry, - 0, to_platform_device(dev)->name, iface); - if (rc) { - dev_err(dev, "Can't get IRQ %d !\n", iface->irq); - return -ENODEV; - } - - /* Resume TWI interface clock as specified */ - write_CLKDIV(iface, iface->saved_clkdiv); - - /* Resume TWI */ - write_CONTROL(iface, iface->saved_control); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(i2c_bfin_twi_pm, - i2c_bfin_twi_suspend, i2c_bfin_twi_resume); -#define I2C_BFIN_TWI_PM_OPS (&i2c_bfin_twi_pm) -#else -#define I2C_BFIN_TWI_PM_OPS NULL -#endif - -static int i2c_bfin_twi_probe(struct platform_device *pdev) -{ - struct bfin_twi_iface *iface; - struct i2c_adapter *p_adap; - struct resource *res; - int rc; - unsigned int clkhilow; - - iface = devm_kzalloc(&pdev->dev, sizeof(struct bfin_twi_iface), - GFP_KERNEL); - if (!iface) { - dev_err(&pdev->dev, "Cannot allocate memory\n"); - return -ENOMEM; - } - - spin_lock_init(&(iface->lock)); - - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iface->regs_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(iface->regs_base)) { - dev_err(&pdev->dev, "Cannot map IO\n"); - return PTR_ERR(iface->regs_base); - } - - iface->irq = platform_get_irq(pdev, 0); - if (iface->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); - return -ENOENT; - } - - p_adap = &iface->adap; - p_adap->nr = pdev->id; - strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); - p_adap->algo = &bfin_twi_algorithm; - p_adap->algo_data = iface; - p_adap->class = I2C_CLASS_DEPRECATED; - p_adap->dev.parent = &pdev->dev; - p_adap->timeout = 5 * HZ; - p_adap->retries = 3; - - rc = peripheral_request_list( - dev_get_platdata(&pdev->dev), - "i2c-bfin-twi"); - if (rc) { - dev_err(&pdev->dev, "Can't setup pin mux!\n"); - return -EBUSY; - } - - rc = devm_request_irq(&pdev->dev, iface->irq, bfin_twi_interrupt_entry, - 0, pdev->name, iface); - if (rc) { - dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); - rc = -ENODEV; - goto out_error; - } - - /* Set TWI internal clock as 10MHz */ - write_CONTROL(iface, ((get_sclk() / 1000 / 1000 + 5) / 10) & 0x7F); - - /* - * We will not end up with a CLKDIV=0 because no one will specify - * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250) - */ - clkhilow = ((10 * 1000 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) + 1) / 2; - - /* Set Twi interface clock as specified */ - write_CLKDIV(iface, (clkhilow << 8) | clkhilow); - - /* Enable TWI */ - write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); - - rc = i2c_add_numbered_adapter(p_adap); - if (rc < 0) - goto out_error; - - platform_set_drvdata(pdev, iface); - - dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Controller, " - "regs_base@%p\n", iface->regs_base); - - return 0; - -out_error: - peripheral_free_list(dev_get_platdata(&pdev->dev)); - return rc; -} - -static int i2c_bfin_twi_remove(struct platform_device *pdev) -{ - struct bfin_twi_iface *iface = platform_get_drvdata(pdev); - - i2c_del_adapter(&(iface->adap)); - peripheral_free_list(dev_get_platdata(&pdev->dev)); - - return 0; -} - -static struct platform_driver i2c_bfin_twi_driver = { - .probe = i2c_bfin_twi_probe, - .remove = i2c_bfin_twi_remove, - .driver = { - .name = "i2c-bfin-twi", - .pm = I2C_BFIN_TWI_PM_OPS, - }, -}; - -static int __init i2c_bfin_twi_init(void) -{ - return platform_driver_register(&i2c_bfin_twi_driver); -} - -static void __exit i2c_bfin_twi_exit(void) -{ - platform_driver_unregister(&i2c_bfin_twi_driver); -} - -subsys_initcall(i2c_bfin_twi_init); -module_exit(i2c_bfin_twi_exit); - -MODULE_AUTHOR("Bryan Wu, Sonic Zhang"); -MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Controller Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:i2c-bfin-twi"); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index cf1fb3fb5d26..901b8833847f 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -200,7 +200,7 @@ comment "IDE chipset support/bugfixes" config IDE_GENERIC tristate "generic/default IDE chipset support" - depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC + depends on ALPHA || X86 || IA64 || MIPS || ARCH_RPC default ARM && ARCH_RPC help This is the generic IDE driver. This driver attaches to the diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 54d7c4685d23..80c0d69b83ac 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -13,13 +13,10 @@ #include <linux/ide.h> #include <linux/pci_ids.h> -/* FIXME: convert arm and m32r to use ide_platform host driver */ +/* FIXME: convert arm to use ide_platform host driver */ #ifdef CONFIG_ARM #include <asm/irq.h> #endif -#ifdef CONFIG_M32R -#include <asm/m32r.h> -#endif #define DRV_NAME "ide_generic" @@ -35,13 +32,6 @@ static const struct ide_port_info ide_generic_port_info = { #ifdef CONFIG_ARM static const u16 legacy_bases[] = { 0x1f0 }; static const int legacy_irqs[] = { IRQ_HARDDISK }; -#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || \ - defined(CONFIG_PLAT_OPSPUT) -static const u16 legacy_bases[] = { 0x1f0 }; -static const int legacy_irqs[] = { PLD_IRQ_CFIREQ }; -#elif defined(CONFIG_PLAT_MAPPI3) -static const u16 legacy_bases[] = { 0x1f0, 0x170 }; -static const int legacy_irqs[] = { PLD_IRQ_CFIREQ, PLD_IRQ_IDEIREQ }; #elif defined(CONFIG_ALPHA) static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 }; static const int legacy_irqs[] = { 14, 15, 11, 10 }; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index c868a878c84f..eefac7978f93 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -163,7 +163,7 @@ static unsigned int get_time_pit(void) #define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "TSC" -#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) || defined(CONFIG_TILE) +#elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) #define GET_TIME(x) do { x = get_cycles(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "get_cycles" diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4c4ab1ced235..2b469cc47a78 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -157,15 +157,6 @@ config KEYBOARD_QT2160 This driver can also be built as a module. If so, the module will be called qt2160. -config KEYBOARD_BFIN - tristate "Blackfin BF54x keypad support" - depends on (BF54x && !BF544) - help - Say Y here if you want to use the BF54x keypad. - - To compile this driver as a module, choose M here: the - module will be called bf54x-keys. - config KEYBOARD_CLPS711X tristate "CLPS711X Keypad support" depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 526e68294e6e..8fab920afa58 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o -obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c deleted file mode 100644 index 8a07a426f88e..000000000000 --- a/drivers/input/keyboard/bf54x-keys.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * File: drivers/input/keyboard/bf54x-keys.c - * Based on: - * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> - * - * Created: - * Description: keypad driver for Analog Devices Blackfin BF54x Processors - * - * - * Modified: - * Copyright 2007-2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/module.h> - -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <linux/pm.h> -#include <linux/sysctl.h> -#include <linux/proc_fs.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/input.h> - -#include <asm/portmux.h> -#include <mach/bf54x_keys.h> - -#define DRV_NAME "bf54x-keys" -#define TIME_SCALE 100 /* 100 ns */ -#define MAX_MULT (0xFF * TIME_SCALE) -#define MAX_RC 8 /* Max Row/Col */ - -static const u16 per_rows[] = { - P_KEY_ROW7, - P_KEY_ROW6, - P_KEY_ROW5, - P_KEY_ROW4, - P_KEY_ROW3, - P_KEY_ROW2, - P_KEY_ROW1, - P_KEY_ROW0, - 0 -}; - -static const u16 per_cols[] = { - P_KEY_COL7, - P_KEY_COL6, - P_KEY_COL5, - P_KEY_COL4, - P_KEY_COL3, - P_KEY_COL2, - P_KEY_COL1, - P_KEY_COL0, - 0 -}; - -struct bf54x_kpad { - struct input_dev *input; - int irq; - unsigned short lastkey; - unsigned short *keycode; - struct timer_list timer; - unsigned int keyup_test_jiffies; - unsigned short kpad_msel; - unsigned short kpad_prescale; - unsigned short kpad_ctl; -}; - -static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad, - struct input_dev *input, u16 keyident) -{ - u16 i; - - for (i = 0; i < input->keycodemax; i++) - if (bf54x_kpad->keycode[i + input->keycodemax] == keyident) - return bf54x_kpad->keycode[i]; - return -1; -} - -static inline void bfin_keycodecpy(unsigned short *keycode, - const unsigned int *pdata_kc, - unsigned short keymapsize) -{ - unsigned int i; - - for (i = 0; i < keymapsize; i++) { - keycode[i] = pdata_kc[i] & 0xffff; - keycode[i + keymapsize] = pdata_kc[i] >> 16; - } -} - -static inline u16 bfin_kpad_get_prescale(u32 timescale) -{ - u32 sclk = get_sclk(); - - return ((((sclk / 1000) * timescale) / 1024) - 1); -} - -static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad) -{ - return (bfin_read_KPAD_STAT() & KPAD_PRESSED); -} - -static inline void bfin_kpad_clear_irq(void) -{ - bfin_write_KPAD_STAT(0xFFFF); - bfin_write_KPAD_ROWCOL(0xFFFF); -} - -static void bfin_kpad_timer(struct timer_list *t) -{ - struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer); - - if (bfin_kpad_get_keypressed(bf54x_kpad)) { - /* Try again later */ - mod_timer(&bf54x_kpad->timer, - jiffies + bf54x_kpad->keyup_test_jiffies); - return; - } - - input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0); - input_sync(bf54x_kpad->input); - - /* Clear IRQ Status */ - - bfin_kpad_clear_irq(); - enable_irq(bf54x_kpad->irq); -} - -static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) -{ - struct platform_device *pdev = dev_id; - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - struct input_dev *input = bf54x_kpad->input; - int key; - u16 rowcol = bfin_read_KPAD_ROWCOL(); - - key = bfin_kpad_find_key(bf54x_kpad, input, rowcol); - - input_report_key(input, key, 1); - input_sync(input); - - if (bfin_kpad_get_keypressed(bf54x_kpad)) { - disable_irq_nosync(bf54x_kpad->irq); - bf54x_kpad->lastkey = key; - mod_timer(&bf54x_kpad->timer, - jiffies + bf54x_kpad->keyup_test_jiffies); - } else { - input_report_key(input, key, 0); - input_sync(input); - - bfin_kpad_clear_irq(); - } - - return IRQ_HANDLED; -} - -static int bfin_kpad_probe(struct platform_device *pdev) -{ - struct bf54x_kpad *bf54x_kpad; - struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct input_dev *input; - int i, error; - - if (!pdata->rows || !pdata->cols || !pdata->keymap) { - dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); - return -EINVAL; - } - - if (!pdata->keymapsize || - pdata->keymapsize > (pdata->rows * pdata->cols)) { - dev_err(&pdev->dev, "invalid keymapsize\n"); - return -EINVAL; - } - - bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL); - if (!bf54x_kpad) - return -ENOMEM; - - platform_set_drvdata(pdev, bf54x_kpad); - - /* Allocate memory for keymap followed by private LUT */ - bf54x_kpad->keycode = kmalloc(pdata->keymapsize * - sizeof(unsigned short) * 2, GFP_KERNEL); - if (!bf54x_kpad->keycode) { - error = -ENOMEM; - goto out; - } - - if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || - !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { - dev_warn(&pdev->dev, - "invalid platform debounce/columndrive time\n"); - bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ - } else { - bfin_write_KPAD_MSEL( - ((pdata->debounce_time / TIME_SCALE) - & DBON_SCALE) | - (((pdata->coldrive_time / TIME_SCALE) << 8) - & COLDRV_SCALE)); - - } - - if (!pdata->keyup_test_interval) - bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50); - else - bf54x_kpad->keyup_test_jiffies = - msecs_to_jiffies(pdata->keyup_test_interval); - - if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], - DRV_NAME)) { - dev_err(&pdev->dev, "requesting peripherals failed\n"); - error = -EFAULT; - goto out0; - } - - if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], - DRV_NAME)) { - dev_err(&pdev->dev, "requesting peripherals failed\n"); - error = -EFAULT; - goto out1; - } - - bf54x_kpad->irq = platform_get_irq(pdev, 0); - if (bf54x_kpad->irq < 0) { - error = -ENODEV; - goto out2; - } - - error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, - 0, DRV_NAME, pdev); - if (error) { - dev_err(&pdev->dev, "unable to claim irq %d\n", - bf54x_kpad->irq); - goto out2; - } - - input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto out3; - } - - bf54x_kpad->input = input; - - input->name = pdev->name; - input->phys = "bf54x-keys/input0"; - input->dev.parent = &pdev->dev; - - input->id.bustype = BUS_HOST; - input->id.vendor = 0x0001; - input->id.product = 0x0001; - input->id.version = 0x0100; - - input->keycodesize = sizeof(unsigned short); - input->keycodemax = pdata->keymapsize; - input->keycode = bf54x_kpad->keycode; - - bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize); - - /* setup input device */ - __set_bit(EV_KEY, input->evbit); - - if (pdata->repeat) - __set_bit(EV_REP, input->evbit); - - for (i = 0; i < input->keycodemax; i++) - if (bf54x_kpad->keycode[i] <= KEY_MAX) - __set_bit(bf54x_kpad->keycode[i], input->keybit); - __clear_bit(KEY_RESERVED, input->keybit); - - error = input_register_device(input); - if (error) { - dev_err(&pdev->dev, "unable to register input device\n"); - goto out4; - } - - /* Init Keypad Key Up/Release test timer */ - - timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0); - - bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE)); - - bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) | - (((pdata->rows - 1) << 10) & KPAD_ROWEN) | - (2 & KPAD_IRQMODE)); - - bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN); - - device_init_wakeup(&pdev->dev, 1); - - return 0; - -out4: - input_free_device(input); -out3: - free_irq(bf54x_kpad->irq, pdev); -out2: - peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); -out1: - peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); -out0: - kfree(bf54x_kpad->keycode); -out: - kfree(bf54x_kpad); - - return error; -} - -static int bfin_kpad_remove(struct platform_device *pdev) -{ - struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - - del_timer_sync(&bf54x_kpad->timer); - free_irq(bf54x_kpad->irq, pdev); - - input_unregister_device(bf54x_kpad->input); - - peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]); - peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]); - - kfree(bf54x_kpad->keycode); - kfree(bf54x_kpad); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - - bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL(); - bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE(); - bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL(); - - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(bf54x_kpad->irq); - - return 0; -} - -static int bfin_kpad_resume(struct platform_device *pdev) -{ - struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); - - bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel); - bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale); - bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl); - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(bf54x_kpad->irq); - - return 0; -} -#else -# define bfin_kpad_suspend NULL -# define bfin_kpad_resume NULL -#endif - -static struct platform_driver bfin_kpad_device_driver = { - .driver = { - .name = DRV_NAME, - }, - .probe = bfin_kpad_probe, - .remove = bfin_kpad_remove, - .suspend = bfin_kpad_suspend, - .resume = bfin_kpad_resume, -}; -module_platform_driver(bfin_kpad_device_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Keypad driver for BF54x Processors"); -MODULE_ALIAS("platform:bf54x-keys"); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 62a1312a7387..e9770f5e3f77 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -655,15 +655,6 @@ config INPUT_DM355EVM To compile this driver as a module, choose M here: the module will be called dm355evm_keys. -config INPUT_BFIN_ROTARY - tristate "Blackfin Rotary support" - depends on BF54x || BF52x - help - Say Y here if you want to use the Blackfin Rotary. - - To compile this driver as a module, choose M here: the - module will be called bfin-rotary. - config INPUT_WM831X_ON tristate "WM831X ON pin" depends on MFD_WM831X diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index a8f61af865aa..eb9c6c3ec530 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o -obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o obj-$(CONFIG_INPUT_BMA150) += bma150.o obj-$(CONFIG_INPUT_CM109) += cm109.o obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c deleted file mode 100644 index 799ce3d2820e..000000000000 --- a/drivers/input/misc/bfin_rotary.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Rotary counter driver for Analog Devices Blackfin Processors - * - * Copyright 2008-2009 Analog Devices Inc. - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/pm.h> -#include <linux/platform_device.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/platform_data/bfin_rotary.h> - -#include <asm/portmux.h> - -#define CNT_CONFIG_OFF 0 /* CNT Config Offset */ -#define CNT_IMASK_OFF 4 /* CNT Interrupt Mask Offset */ -#define CNT_STATUS_OFF 8 /* CNT Status Offset */ -#define CNT_COMMAND_OFF 12 /* CNT Command Offset */ -#define CNT_DEBOUNCE_OFF 16 /* CNT Debounce Offset */ -#define CNT_COUNTER_OFF 20 /* CNT Counter Offset */ -#define CNT_MAX_OFF 24 /* CNT Maximum Count Offset */ -#define CNT_MIN_OFF 28 /* CNT Minimum Count Offset */ - -struct bfin_rot { - struct input_dev *input; - void __iomem *base; - int irq; - unsigned int up_key; - unsigned int down_key; - unsigned int button_key; - unsigned int rel_code; - - unsigned short mode; - unsigned short debounce; - - unsigned short cnt_config; - unsigned short cnt_imask; - unsigned short cnt_debounce; -}; - -static void report_key_event(struct input_dev *input, int keycode) -{ - /* simulate a press-n-release */ - input_report_key(input, keycode, 1); - input_sync(input); - input_report_key(input, keycode, 0); - input_sync(input); -} - -static void report_rotary_event(struct bfin_rot *rotary, int delta) -{ - struct input_dev *input = rotary->input; - - if (rotary->up_key) { - report_key_event(input, - delta > 0 ? rotary->up_key : rotary->down_key); - } else { - input_report_rel(input, rotary->rel_code, delta); - input_sync(input); - } -} - -static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) -{ - struct bfin_rot *rotary = dev_id; - int delta; - - switch (readw(rotary->base + CNT_STATUS_OFF)) { - - case ICII: - break; - - case UCII: - case DCII: - delta = readl(rotary->base + CNT_COUNTER_OFF); - if (delta) - report_rotary_event(rotary, delta); - break; - - case CZMII: - report_key_event(rotary->input, rotary->button_key); - break; - - default: - break; - } - - writew(W1LCNT_ZERO, rotary->base + CNT_COMMAND_OFF); /* Clear COUNTER */ - writew(-1, rotary->base + CNT_STATUS_OFF); /* Clear STATUS */ - - return IRQ_HANDLED; -} - -static int bfin_rotary_open(struct input_dev *input) -{ - struct bfin_rot *rotary = input_get_drvdata(input); - unsigned short val; - - if (rotary->mode & ROT_DEBE) - writew(rotary->debounce & DPRESCALE, - rotary->base + CNT_DEBOUNCE_OFF); - - writew(rotary->mode & ~CNTE, rotary->base + CNT_CONFIG_OFF); - - val = UCIE | DCIE; - if (rotary->button_key) - val |= CZMIE; - writew(val, rotary->base + CNT_IMASK_OFF); - - writew(rotary->mode | CNTE, rotary->base + CNT_CONFIG_OFF); - - return 0; -} - -static void bfin_rotary_close(struct input_dev *input) -{ - struct bfin_rot *rotary = input_get_drvdata(input); - - writew(0, rotary->base + CNT_CONFIG_OFF); - writew(0, rotary->base + CNT_IMASK_OFF); -} - -static void bfin_rotary_free_action(void *data) -{ - peripheral_free_list(data); -} - -static int bfin_rotary_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - const struct bfin_rotary_platform_data *pdata = dev_get_platdata(dev); - struct bfin_rot *rotary; - struct resource *res; - struct input_dev *input; - int error; - - /* Basic validation */ - if ((pdata->rotary_up_key && !pdata->rotary_down_key) || - (!pdata->rotary_up_key && pdata->rotary_down_key)) { - return -EINVAL; - } - - if (pdata->pin_list) { - error = peripheral_request_list(pdata->pin_list, - dev_name(dev)); - if (error) { - dev_err(dev, "requesting peripherals failed: %d\n", - error); - return error; - } - - error = devm_add_action_or_reset(dev, bfin_rotary_free_action, - pdata->pin_list); - if (error) { - dev_err(dev, "setting cleanup action failed: %d\n", - error); - return error; - } - } - - rotary = devm_kzalloc(dev, sizeof(struct bfin_rot), GFP_KERNEL); - if (!rotary) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rotary->base = devm_ioremap_resource(dev, res); - if (IS_ERR(rotary->base)) - return PTR_ERR(rotary->base); - - input = devm_input_allocate_device(dev); - if (!input) - return -ENOMEM; - - rotary->input = input; - - rotary->up_key = pdata->rotary_up_key; - rotary->down_key = pdata->rotary_down_key; - rotary->button_key = pdata->rotary_button_key; - rotary->rel_code = pdata->rotary_rel_code; - - rotary->mode = pdata->mode; - rotary->debounce = pdata->debounce; - - input->name = pdev->name; - input->phys = "bfin-rotary/input0"; - input->dev.parent = dev; - - input_set_drvdata(input, rotary); - - input->id.bustype = BUS_HOST; - input->id.vendor = 0x0001; - input->id.product = 0x0001; - input->id.version = 0x0100; - - input->open = bfin_rotary_open; - input->close = bfin_rotary_close; - - if (rotary->up_key) { - __set_bit(EV_KEY, input->evbit); - __set_bit(rotary->up_key, input->keybit); - __set_bit(rotary->down_key, input->keybit); - } else { - __set_bit(EV_REL, input->evbit); - __set_bit(rotary->rel_code, input->relbit); - } - - if (rotary->button_key) { - __set_bit(EV_KEY, input->evbit); - __set_bit(rotary->button_key, input->keybit); - } - - /* Quiesce the device before requesting irq */ - bfin_rotary_close(input); - - rotary->irq = platform_get_irq(pdev, 0); - if (rotary->irq < 0) { - dev_err(dev, "No rotary IRQ specified\n"); - return -ENOENT; - } - - error = devm_request_irq(dev, rotary->irq, bfin_rotary_isr, - 0, dev_name(dev), rotary); - if (error) { - dev_err(dev, "unable to claim irq %d; error %d\n", - rotary->irq, error); - return error; - } - - error = input_register_device(input); - if (error) { - dev_err(dev, "unable to register input device (%d)\n", error); - return error; - } - - platform_set_drvdata(pdev, rotary); - device_init_wakeup(dev, 1); - - return 0; -} - -static int __maybe_unused bfin_rotary_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct bfin_rot *rotary = platform_get_drvdata(pdev); - - rotary->cnt_config = readw(rotary->base + CNT_CONFIG_OFF); - rotary->cnt_imask = readw(rotary->base + CNT_IMASK_OFF); - rotary->cnt_debounce = readw(rotary->base + CNT_DEBOUNCE_OFF); - - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(rotary->irq); - - return 0; -} - -static int __maybe_unused bfin_rotary_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct bfin_rot *rotary = platform_get_drvdata(pdev); - - writew(rotary->cnt_debounce, rotary->base + CNT_DEBOUNCE_OFF); - writew(rotary->cnt_imask, rotary->base + CNT_IMASK_OFF); - writew(rotary->cnt_config & ~CNTE, rotary->base + CNT_CONFIG_OFF); - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(rotary->irq); - - if (rotary->cnt_config & CNTE) - writew(rotary->cnt_config, rotary->base + CNT_CONFIG_OFF); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(bfin_rotary_pm_ops, - bfin_rotary_suspend, bfin_rotary_resume); - -static struct platform_driver bfin_rotary_device_driver = { - .probe = bfin_rotary_probe, - .driver = { - .name = "bfin-rotary", - .pm = &bfin_rotary_pm_ops, - }, -}; -module_platform_driver(bfin_rotary_device_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); -MODULE_ALIAS("platform:bfin-rotary"); diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index de7cf483e1b7..110de02bb215 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -15,8 +15,6 @@ obj-$(CONFIG_IRQ_MXS) += irq-mxs.o obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o -obj-$(CONFIG_METAG) += irq-metag-ext.o -obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o obj-$(CONFIG_OMPIC) += irq-ompic.o obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c deleted file mode 100644 index e67483161f0f..000000000000 --- a/drivers/irqchip/irq-metag-ext.c +++ /dev/null @@ -1,871 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Meta External interrupt code. - * - * Copyright (C) 2005-2012 Imagination Technologies Ltd. - * - * External interrupts on Meta are configured at two-levels, in the CPU core and - * in the external trigger block. Interrupts from SoC peripherals are - * multiplexed onto a single Meta CPU "trigger" - traditionally it has always - * been trigger 2 (TR2). For info on how de-multiplexing happens check out - * meta_intc_irq_demux(). - */ - -#include <linux/interrupt.h> -#include <linux/irqchip/metag-ext.h> -#include <linux/irqdomain.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/slab.h> -#include <linux/syscore_ops.h> - -#include <asm/irq.h> -#include <asm/hwthread.h> - -#define HWSTAT_STRIDE 8 -#define HWVEC_BLK_STRIDE 0x1000 - -/** - * struct meta_intc_priv - private meta external interrupt data - * @nr_banks: Number of interrupt banks - * @domain: IRQ domain for all banks of external IRQs - * @unmasked: Record of unmasked IRQs - * @levels_altered: Record of altered level bits - */ -struct meta_intc_priv { - unsigned int nr_banks; - struct irq_domain *domain; - - unsigned long unmasked[4]; - -#ifdef CONFIG_METAG_SUSPEND_MEM - unsigned long levels_altered[4]; -#endif -}; - -/* Private data for the one and only external interrupt controller */ -static struct meta_intc_priv meta_intc_priv; - -/** - * meta_intc_offset() - Get the offset into the bank of a hardware IRQ number - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Bit offset into the IRQ's bank registers - */ -static unsigned int meta_intc_offset(irq_hw_number_t hw) -{ - return hw & 0x1f; -} - -/** - * meta_intc_bank() - Get the bank number of a hardware IRQ number - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Bank number indicating which register the IRQ's bits are - */ -static unsigned int meta_intc_bank(irq_hw_number_t hw) -{ - return hw >> 5; -} - -/** - * meta_intc_stat_addr() - Get the address of a HWSTATEXT register - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Address of a HWSTATEXT register containing the status bit for - * the specified hardware IRQ number - */ -static void __iomem *meta_intc_stat_addr(irq_hw_number_t hw) -{ - return (void __iomem *)(HWSTATEXT + - HWSTAT_STRIDE * meta_intc_bank(hw)); -} - -/** - * meta_intc_level_addr() - Get the address of a HWLEVELEXT register - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Address of a HWLEVELEXT register containing the sense bit for - * the specified hardware IRQ number - */ -static void __iomem *meta_intc_level_addr(irq_hw_number_t hw) -{ - return (void __iomem *)(HWLEVELEXT + - HWSTAT_STRIDE * meta_intc_bank(hw)); -} - -/** - * meta_intc_mask_addr() - Get the address of a HWMASKEXT register - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Address of a HWMASKEXT register containing the mask bit for the - * specified hardware IRQ number - */ -static void __iomem *meta_intc_mask_addr(irq_hw_number_t hw) -{ - return (void __iomem *)(HWMASKEXT + - HWSTAT_STRIDE * meta_intc_bank(hw)); -} - -/** - * meta_intc_vec_addr() - Get the vector address of a hardware interrupt - * @hw: Hardware IRQ number (within external trigger block) - * - * Returns: Address of a HWVECEXT register controlling the core trigger to - * vector the IRQ onto - */ -static inline void __iomem *meta_intc_vec_addr(irq_hw_number_t hw) -{ - return (void __iomem *)(HWVEC0EXT + - HWVEC_BLK_STRIDE * meta_intc_bank(hw) + - HWVECnEXT_STRIDE * meta_intc_offset(hw)); -} - -/** - * meta_intc_startup_irq() - set up an external irq - * @data: data for the external irq to start up - * - * Multiplex interrupts for irq onto TR2. Clear any pending interrupts and - * unmask irq, both using the appropriate callbacks. - */ -static unsigned int meta_intc_startup_irq(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - void __iomem *vec_addr = meta_intc_vec_addr(hw); - int thread = hard_processor_id(); - - /* Perform any necessary acking. */ - if (data->chip->irq_ack) - data->chip->irq_ack(data); - - /* Wire up this interrupt to the core with HWVECxEXT. */ - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); - - /* Perform any necessary unmasking. */ - data->chip->irq_unmask(data); - - return 0; -} - -/** - * meta_intc_shutdown_irq() - turn off an external irq - * @data: data for the external irq to turn off - * - * Mask irq using the appropriate callback and stop muxing it onto TR2. - */ -static void meta_intc_shutdown_irq(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - void __iomem *vec_addr = meta_intc_vec_addr(hw); - - /* Mask the IRQ */ - data->chip->irq_mask(data); - - /* - * Disable the IRQ at the core by removing the interrupt from - * the HW vector mapping. - */ - metag_out32(0, vec_addr); -} - -/** - * meta_intc_ack_irq() - acknowledge an external irq - * @data: data for the external irq to ack - * - * Clear down an edge interrupt in the status register. - */ -static void meta_intc_ack_irq(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *stat_addr = meta_intc_stat_addr(hw); - - /* Ack the int, if it is still 'on'. - * NOTE - this only works for edge triggered interrupts. - */ - if (metag_in32(stat_addr) & bit) - metag_out32(bit, stat_addr); -} - -/** - * record_irq_is_masked() - record the IRQ masked so it doesn't get handled - * @data: data for the external irq to record - * - * This should get called whenever an external IRQ is masked (by whichever - * callback is used). It records the IRQ masked so that it doesn't get handled - * if it still shows up in the status register. - */ -static void record_irq_is_masked(struct irq_data *data) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - irq_hw_number_t hw = data->hwirq; - - clear_bit(meta_intc_offset(hw), &priv->unmasked[meta_intc_bank(hw)]); -} - -/** - * record_irq_is_unmasked() - record the IRQ unmasked so it can be handled - * @data: data for the external irq to record - * - * This should get called whenever an external IRQ is unmasked (by whichever - * callback is used). It records the IRQ unmasked so that it gets handled if it - * shows up in the status register. - */ -static void record_irq_is_unmasked(struct irq_data *data) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - irq_hw_number_t hw = data->hwirq; - - set_bit(meta_intc_offset(hw), &priv->unmasked[meta_intc_bank(hw)]); -} - -/* - * For use by wrapper IRQ drivers - */ - -/** - * meta_intc_mask_irq_simple() - minimal mask used by wrapper IRQ drivers - * @data: data for the external irq being masked - * - * This should be called by any wrapper IRQ driver mask functions. it doesn't do - * any masking but records the IRQ as masked so that the core code knows the - * mask has taken place. It is the callers responsibility to ensure that the IRQ - * won't trigger an interrupt to the core. - */ -void meta_intc_mask_irq_simple(struct irq_data *data) -{ - record_irq_is_masked(data); -} - -/** - * meta_intc_unmask_irq_simple() - minimal unmask used by wrapper IRQ drivers - * @data: data for the external irq being unmasked - * - * This should be called by any wrapper IRQ driver unmask functions. it doesn't - * do any unmasking but records the IRQ as unmasked so that the core code knows - * the unmask has taken place. It is the callers responsibility to ensure that - * the IRQ can now trigger an interrupt to the core. - */ -void meta_intc_unmask_irq_simple(struct irq_data *data) -{ - record_irq_is_unmasked(data); -} - - -/** - * meta_intc_mask_irq() - mask an external irq using HWMASKEXT - * @data: data for the external irq to mask - * - * This is a default implementation of a mask function which makes use of the - * HWMASKEXT registers available in newer versions. - * - * Earlier versions without these registers should use SoC level IRQ masking - * which call the meta_intc_*_simple() functions above, or if that isn't - * available should use the fallback meta_intc_*_nomask() functions below. - */ -static void meta_intc_mask_irq(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *mask_addr = meta_intc_mask_addr(hw); - unsigned long flags; - - record_irq_is_masked(data); - - /* update the interrupt mask */ - __global_lock2(flags); - metag_out32(metag_in32(mask_addr) & ~bit, mask_addr); - __global_unlock2(flags); -} - -/** - * meta_intc_unmask_irq() - unmask an external irq using HWMASKEXT - * @data: data for the external irq to unmask - * - * This is a default implementation of an unmask function which makes use of the - * HWMASKEXT registers available on new versions. It should be paired with - * meta_intc_mask_irq() above. - */ -static void meta_intc_unmask_irq(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *mask_addr = meta_intc_mask_addr(hw); - unsigned long flags; - - record_irq_is_unmasked(data); - - /* update the interrupt mask */ - __global_lock2(flags); - metag_out32(metag_in32(mask_addr) | bit, mask_addr); - __global_unlock2(flags); -} - -/** - * meta_intc_mask_irq_nomask() - mask an external irq by unvectoring - * @data: data for the external irq to mask - * - * This is the version of the mask function for older versions which don't have - * HWMASKEXT registers, or a SoC level means of masking IRQs. Instead the IRQ is - * unvectored from the core and retriggered if necessary later. - */ -static void meta_intc_mask_irq_nomask(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - void __iomem *vec_addr = meta_intc_vec_addr(hw); - - record_irq_is_masked(data); - - /* there is no interrupt mask, so unvector the interrupt */ - metag_out32(0, vec_addr); -} - -/** - * meta_intc_unmask_edge_irq_nomask() - unmask an edge irq by revectoring - * @data: data for the external irq to unmask - * - * This is the version of the unmask function for older versions which don't - * have HWMASKEXT registers, or a SoC level means of masking IRQs. Instead the - * IRQ is revectored back to the core and retriggered if necessary. - * - * The retriggering done by this function is specific to edge interrupts. - */ -static void meta_intc_unmask_edge_irq_nomask(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *stat_addr = meta_intc_stat_addr(hw); - void __iomem *vec_addr = meta_intc_vec_addr(hw); - unsigned int thread = hard_processor_id(); - - record_irq_is_unmasked(data); - - /* there is no interrupt mask, so revector the interrupt */ - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); - - /* - * Re-trigger interrupt - * - * Writing a 1 toggles, and a 0->1 transition triggers. We only - * retrigger if the status bit is already set, which means we - * need to clear it first. Retriggering is fundamentally racy - * because if the interrupt fires again after we clear it we - * could end up clearing it again and the interrupt handler - * thinking it hasn't fired. Therefore we need to keep trying to - * retrigger until the bit is set. - */ - if (metag_in32(stat_addr) & bit) { - metag_out32(bit, stat_addr); - while (!(metag_in32(stat_addr) & bit)) - metag_out32(bit, stat_addr); - } -} - -/** - * meta_intc_unmask_level_irq_nomask() - unmask a level irq by revectoring - * @data: data for the external irq to unmask - * - * This is the version of the unmask function for older versions which don't - * have HWMASKEXT registers, or a SoC level means of masking IRQs. Instead the - * IRQ is revectored back to the core and retriggered if necessary. - * - * The retriggering done by this function is specific to level interrupts. - */ -static void meta_intc_unmask_level_irq_nomask(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *stat_addr = meta_intc_stat_addr(hw); - void __iomem *vec_addr = meta_intc_vec_addr(hw); - unsigned int thread = hard_processor_id(); - - record_irq_is_unmasked(data); - - /* there is no interrupt mask, so revector the interrupt */ - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); - - /* Re-trigger interrupt */ - /* Writing a 1 triggers interrupt */ - if (metag_in32(stat_addr) & bit) - metag_out32(bit, stat_addr); -} - -/** - * meta_intc_irq_set_type() - set the type of an external irq - * @data: data for the external irq to set the type of - * @flow_type: new irq flow type - * - * Set the flow type of an external interrupt. This updates the irq chip and irq - * handler depending on whether the irq is edge or level sensitive (the polarity - * is ignored), and also sets up the bit in HWLEVELEXT so the hardware knows - * when to trigger. - */ -static int meta_intc_irq_set_type(struct irq_data *data, unsigned int flow_type) -{ -#ifdef CONFIG_METAG_SUSPEND_MEM - struct meta_intc_priv *priv = &meta_intc_priv; -#endif - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *level_addr = meta_intc_level_addr(hw); - unsigned long flags; - unsigned int level; - - /* update the chip/handler */ - if (flow_type & IRQ_TYPE_LEVEL_MASK) - irq_set_chip_handler_name_locked(data, &meta_intc_level_chip, - handle_level_irq, NULL); - else - irq_set_chip_handler_name_locked(data, &meta_intc_edge_chip, - handle_edge_irq, NULL); - - /* and clear/set the bit in HWLEVELEXT */ - __global_lock2(flags); - level = metag_in32(level_addr); - if (flow_type & IRQ_TYPE_LEVEL_MASK) - level |= bit; - else - level &= ~bit; - metag_out32(level, level_addr); -#ifdef CONFIG_METAG_SUSPEND_MEM - priv->levels_altered[meta_intc_bank(hw)] |= bit; -#endif - __global_unlock2(flags); - - return 0; -} - -/** - * meta_intc_irq_demux() - external irq de-multiplexer - * @desc: the interrupt description structure for this irq - * - * The cpu receives an interrupt on TR2 when a SoC interrupt has occurred. It is - * this function's job to demux this irq and figure out exactly which external - * irq needs servicing. - * - * Whilst using TR2 to detect external interrupts is a software convention it is - * (hopefully) unlikely to change. - */ -static void meta_intc_irq_demux(struct irq_desc *desc) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - irq_hw_number_t hw; - unsigned int bank, irq_no, status; - void __iomem *stat_addr = meta_intc_stat_addr(0); - - /* - * Locate which interrupt has caused our handler to run. - */ - for (bank = 0; bank < priv->nr_banks; ++bank) { - /* Which interrupts are currently pending in this bank? */ -recalculate: - status = metag_in32(stat_addr) & priv->unmasked[bank]; - - for (hw = bank*32; status; status >>= 1, ++hw) { - if (status & 0x1) { - /* - * Map the hardware IRQ number to a virtual - * Linux IRQ number. - */ - irq_no = irq_linear_revmap(priv->domain, hw); - - /* - * Only fire off external interrupts that are - * registered to be handled by the kernel. - * Other external interrupts are probably being - * handled by other Meta hardware threads. - */ - generic_handle_irq(irq_no); - - /* - * The handler may have re-enabled interrupts - * which could have caused a nested invocation - * of this code and make the copy of the - * status register we are using invalid. - */ - goto recalculate; - } - } - stat_addr += HWSTAT_STRIDE; - } -} - -#ifdef CONFIG_SMP -/** - * meta_intc_set_affinity() - set the affinity for an interrupt - * @data: data for the external irq to set the affinity of - * @cpumask: cpu mask representing cpus which can handle the interrupt - * @force: whether to force (ignored) - * - * Revector the specified external irq onto a specific cpu's TR2 trigger, so - * that that cpu tends to be the one who handles it. - */ -static int meta_intc_set_affinity(struct irq_data *data, - const struct cpumask *cpumask, bool force) -{ - irq_hw_number_t hw = data->hwirq; - void __iomem *vec_addr = meta_intc_vec_addr(hw); - unsigned int cpu, thread; - - /* - * Wire up this interrupt from HWVECxEXT to the Meta core. - * - * Note that we can't wire up HWVECxEXT to interrupt more than - * one cpu (the interrupt code doesn't support it), so we just - * pick the first cpu we find in 'cpumask'. - */ - cpu = cpumask_any_and(cpumask, cpu_online_mask); - thread = cpu_2_hwthread_id[cpu]; - - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); - - irq_data_update_effective_affinity(data, cpumask_of(cpu)); - - return 0; -} -#else -#define meta_intc_set_affinity NULL -#endif - -#ifdef CONFIG_PM_SLEEP -#define META_INTC_CHIP_FLAGS (IRQCHIP_MASK_ON_SUSPEND \ - | IRQCHIP_SKIP_SET_WAKE) -#else -#define META_INTC_CHIP_FLAGS 0 -#endif - -/* public edge/level irq chips which SoCs can override */ - -struct irq_chip meta_intc_edge_chip = { - .irq_startup = meta_intc_startup_irq, - .irq_shutdown = meta_intc_shutdown_irq, - .irq_ack = meta_intc_ack_irq, - .irq_mask = meta_intc_mask_irq, - .irq_unmask = meta_intc_unmask_irq, - .irq_set_type = meta_intc_irq_set_type, - .irq_set_affinity = meta_intc_set_affinity, - .flags = META_INTC_CHIP_FLAGS, -}; - -struct irq_chip meta_intc_level_chip = { - .irq_startup = meta_intc_startup_irq, - .irq_shutdown = meta_intc_shutdown_irq, - .irq_set_type = meta_intc_irq_set_type, - .irq_mask = meta_intc_mask_irq, - .irq_unmask = meta_intc_unmask_irq, - .irq_set_affinity = meta_intc_set_affinity, - .flags = META_INTC_CHIP_FLAGS, -}; - -/** - * meta_intc_map() - map an external irq - * @d: irq domain of external trigger block - * @irq: virtual irq number - * @hw: hardware irq number within external trigger block - * - * This sets up a virtual irq for a specified hardware interrupt. The irq chip - * and handler is configured, using the HWLEVELEXT registers to determine - * edge/level flow type. These registers will have been set when the irq type is - * set (or set to a default at init time). - */ -static int meta_intc_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - unsigned int bit = 1 << meta_intc_offset(hw); - void __iomem *level_addr = meta_intc_level_addr(hw); - - /* Go by the current sense in the HWLEVELEXT register */ - if (metag_in32(level_addr) & bit) - irq_set_chip_and_handler(irq, &meta_intc_level_chip, - handle_level_irq); - else - irq_set_chip_and_handler(irq, &meta_intc_edge_chip, - handle_edge_irq); - - irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); - return 0; -} - -static const struct irq_domain_ops meta_intc_domain_ops = { - .map = meta_intc_map, - .xlate = irq_domain_xlate_twocell, -}; - -#ifdef CONFIG_METAG_SUSPEND_MEM - -/** - * struct meta_intc_context - suspend context - * @levels: State of HWLEVELEXT registers - * @masks: State of HWMASKEXT registers - * @vectors: State of HWVECEXT registers - * @txvecint: State of TxVECINT registers - * - * This structure stores the IRQ state across suspend. - */ -struct meta_intc_context { - u32 levels[4]; - u32 masks[4]; - u8 vectors[4*32]; - - u8 txvecint[4][4]; -}; - -/* suspend context */ -static struct meta_intc_context *meta_intc_context; - -/** - * meta_intc_suspend() - store irq state - * - * To avoid interfering with other threads we only save the IRQ state of IRQs in - * use by Linux. - */ -static int meta_intc_suspend(void) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - int i, j; - irq_hw_number_t hw; - unsigned int bank; - unsigned long flags; - struct meta_intc_context *context; - void __iomem *level_addr, *mask_addr, *vec_addr; - u32 mask, bit; - - context = kzalloc(sizeof(*context), GFP_ATOMIC); - if (!context) - return -ENOMEM; - - hw = 0; - level_addr = meta_intc_level_addr(0); - mask_addr = meta_intc_mask_addr(0); - for (bank = 0; bank < priv->nr_banks; ++bank) { - vec_addr = meta_intc_vec_addr(hw); - - /* create mask of interrupts in use */ - mask = 0; - for (bit = 1; bit; bit <<= 1) { - i = irq_linear_revmap(priv->domain, hw); - /* save mapped irqs which are enabled or have actions */ - if (i && (!irqd_irq_disabled(irq_get_irq_data(i)) || - irq_has_action(i))) { - mask |= bit; - - /* save trigger vector */ - context->vectors[hw] = metag_in32(vec_addr); - } - - ++hw; - vec_addr += HWVECnEXT_STRIDE; - } - - /* save level state if any IRQ levels altered */ - if (priv->levels_altered[bank]) - context->levels[bank] = metag_in32(level_addr); - /* save mask state if any IRQs in use */ - if (mask) - context->masks[bank] = metag_in32(mask_addr); - - level_addr += HWSTAT_STRIDE; - mask_addr += HWSTAT_STRIDE; - } - - /* save trigger matrixing */ - __global_lock2(flags); - for (i = 0; i < 4; ++i) - for (j = 0; j < 4; ++j) - context->txvecint[i][j] = metag_in32(T0VECINT_BHALT + - TnVECINT_STRIDE*i + - 8*j); - __global_unlock2(flags); - - meta_intc_context = context; - return 0; -} - -/** - * meta_intc_resume() - restore saved irq state - * - * Restore the saved IRQ state and drop it. - */ -static void meta_intc_resume(void) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - int i, j; - irq_hw_number_t hw; - unsigned int bank; - unsigned long flags; - struct meta_intc_context *context = meta_intc_context; - void __iomem *level_addr, *mask_addr, *vec_addr; - u32 mask, bit, tmp; - - meta_intc_context = NULL; - - hw = 0; - level_addr = meta_intc_level_addr(0); - mask_addr = meta_intc_mask_addr(0); - for (bank = 0; bank < priv->nr_banks; ++bank) { - vec_addr = meta_intc_vec_addr(hw); - - /* create mask of interrupts in use */ - mask = 0; - for (bit = 1; bit; bit <<= 1) { - i = irq_linear_revmap(priv->domain, hw); - /* restore mapped irqs, enabled or with actions */ - if (i && (!irqd_irq_disabled(irq_get_irq_data(i)) || - irq_has_action(i))) { - mask |= bit; - - /* restore trigger vector */ - metag_out32(context->vectors[hw], vec_addr); - } - - ++hw; - vec_addr += HWVECnEXT_STRIDE; - } - - if (mask) { - /* restore mask state */ - __global_lock2(flags); - tmp = metag_in32(mask_addr); - tmp = (tmp & ~mask) | (context->masks[bank] & mask); - metag_out32(tmp, mask_addr); - __global_unlock2(flags); - } - - mask = priv->levels_altered[bank]; - if (mask) { - /* restore level state */ - __global_lock2(flags); - tmp = metag_in32(level_addr); - tmp = (tmp & ~mask) | (context->levels[bank] & mask); - metag_out32(tmp, level_addr); - __global_unlock2(flags); - } - - level_addr += HWSTAT_STRIDE; - mask_addr += HWSTAT_STRIDE; - } - - /* restore trigger matrixing */ - __global_lock2(flags); - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - metag_out32(context->txvecint[i][j], - T0VECINT_BHALT + - TnVECINT_STRIDE*i + - 8*j); - } - } - __global_unlock2(flags); - - kfree(context); -} - -static struct syscore_ops meta_intc_syscore_ops = { - .suspend = meta_intc_suspend, - .resume = meta_intc_resume, -}; - -static void __init meta_intc_init_syscore_ops(struct meta_intc_priv *priv) -{ - register_syscore_ops(&meta_intc_syscore_ops); -} -#else -#define meta_intc_init_syscore_ops(priv) do {} while (0) -#endif - -/** - * meta_intc_init_cpu() - register with a Meta cpu - * @priv: private interrupt controller data - * @cpu: the CPU to register on - * - * Configure @cpu's TR2 irq so that we can demux external irqs. - */ -static void __init meta_intc_init_cpu(struct meta_intc_priv *priv, int cpu) -{ - unsigned int thread = cpu_2_hwthread_id[cpu]; - unsigned int signum = TBID_SIGNUM_TR2(thread); - int irq = tbisig_map(signum); - - /* Register the multiplexed IRQ handler */ - irq_set_chained_handler(irq, meta_intc_irq_demux); - irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); -} - -/** - * meta_intc_no_mask() - indicate lack of HWMASKEXT registers - * - * Called from SoC code (or init code below) to dynamically indicate the lack of - * HWMASKEXT registers (for example depending on some SoC revision register). - * This alters the irq mask and unmask callbacks to use the fallback - * unvectoring/retriggering technique instead of using HWMASKEXT registers. - */ -void __init meta_intc_no_mask(void) -{ - meta_intc_edge_chip.irq_mask = meta_intc_mask_irq_nomask; - meta_intc_edge_chip.irq_unmask = meta_intc_unmask_edge_irq_nomask; - meta_intc_level_chip.irq_mask = meta_intc_mask_irq_nomask; - meta_intc_level_chip.irq_unmask = meta_intc_unmask_level_irq_nomask; -} - -/** - * init_external_IRQ() - initialise the external irq controller - * - * Set up the external irq controller using device tree properties. This is - * called from init_IRQ(). - */ -int __init init_external_IRQ(void) -{ - struct meta_intc_priv *priv = &meta_intc_priv; - struct device_node *node; - int ret, cpu; - u32 val; - bool no_masks = false; - - node = of_find_compatible_node(NULL, NULL, "img,meta-intc"); - if (!node) - return -ENOENT; - - /* Get number of banks */ - ret = of_property_read_u32(node, "num-banks", &val); - if (ret) { - pr_err("meta-intc: No num-banks property found\n"); - return ret; - } - if (val < 1 || val > 4) { - pr_err("meta-intc: num-banks (%u) out of range\n", val); - return -EINVAL; - } - priv->nr_banks = val; - - /* Are any mask registers present? */ - if (of_get_property(node, "no-mask", NULL)) - no_masks = true; - - /* No HWMASKEXT registers present? */ - if (no_masks) - meta_intc_no_mask(); - - /* Set up an IRQ domain */ - /* - * This is a legacy IRQ domain for now until all the platform setup code - * has been converted to devicetree. - */ - priv->domain = irq_domain_add_linear(node, priv->nr_banks*32, - &meta_intc_domain_ops, priv); - if (unlikely(!priv->domain)) { - pr_err("meta-intc: cannot add IRQ domain\n"); - return -ENOMEM; - } - - /* Setup TR2 for all cpus. */ - for_each_possible_cpu(cpu) - meta_intc_init_cpu(priv, cpu); - - /* Set up system suspend/resume callbacks */ - meta_intc_init_syscore_ops(priv); - - pr_info("meta-intc: External IRQ controller initialised (%u IRQs)\n", - priv->nr_banks*32); - - return 0; -} diff --git a/drivers/irqchip/irq-metag.c b/drivers/irqchip/irq-metag.c deleted file mode 100644 index 857b946747eb..000000000000 --- a/drivers/irqchip/irq-metag.c +++ /dev/null @@ -1,343 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Meta internal (HWSTATMETA) interrupt code. - * - * Copyright (C) 2011-2012 Imagination Technologies Ltd. - * - * This code is based on the code in SoC/common/irq.c and SoC/comet/irq.c - * The code base could be generalised/merged as a lot of the functionality is - * similar. Until this is done, we try to keep the code simple here. - */ - -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irqdomain.h> - -#include <asm/irq.h> -#include <asm/hwthread.h> - -#define PERF0VECINT 0x04820580 -#define PERF1VECINT 0x04820588 -#define PERF0TRIG_OFFSET 16 -#define PERF1TRIG_OFFSET 17 - -/** - * struct metag_internal_irq_priv - private meta internal interrupt data - * @domain: IRQ domain for all internal Meta IRQs (HWSTATMETA) - * @unmasked: Record of unmasked IRQs - */ -struct metag_internal_irq_priv { - struct irq_domain *domain; - - unsigned long unmasked; -}; - -/* Private data for the one and only internal interrupt controller */ -static struct metag_internal_irq_priv metag_internal_irq_priv; - -static unsigned int metag_internal_irq_startup(struct irq_data *data); -static void metag_internal_irq_shutdown(struct irq_data *data); -static void metag_internal_irq_ack(struct irq_data *data); -static void metag_internal_irq_mask(struct irq_data *data); -static void metag_internal_irq_unmask(struct irq_data *data); -#ifdef CONFIG_SMP -static int metag_internal_irq_set_affinity(struct irq_data *data, - const struct cpumask *cpumask, bool force); -#endif - -static struct irq_chip internal_irq_edge_chip = { - .name = "HWSTATMETA-IRQ", - .irq_startup = metag_internal_irq_startup, - .irq_shutdown = metag_internal_irq_shutdown, - .irq_ack = metag_internal_irq_ack, - .irq_mask = metag_internal_irq_mask, - .irq_unmask = metag_internal_irq_unmask, -#ifdef CONFIG_SMP - .irq_set_affinity = metag_internal_irq_set_affinity, -#endif -}; - -/* - * metag_hwvec_addr - get the address of *VECINT regs of irq - * - * This function is a table of supported triggers on HWSTATMETA - * Could do with a structure, but better keep it simple. Changes - * in this code should be rare. - */ -static inline void __iomem *metag_hwvec_addr(irq_hw_number_t hw) -{ - void __iomem *addr; - - switch (hw) { - case PERF0TRIG_OFFSET: - addr = (void __iomem *)PERF0VECINT; - break; - case PERF1TRIG_OFFSET: - addr = (void __iomem *)PERF1VECINT; - break; - default: - addr = NULL; - break; - } - return addr; -} - -/* - * metag_internal_startup - setup an internal irq - * @irq: the irq to startup - * - * Multiplex interrupts for @irq onto TR1. Clear any pending - * interrupts. - */ -static unsigned int metag_internal_irq_startup(struct irq_data *data) -{ - /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */ - metag_internal_irq_ack(data); - - /* Enable the interrupt by unmasking it */ - metag_internal_irq_unmask(data); - - return 0; -} - -/* - * metag_internal_irq_shutdown - turn off the irq - * @irq: the irq number to turn off - * - * Mask @irq and clear any pending interrupts. - * Stop muxing @irq onto TR1. - */ -static void metag_internal_irq_shutdown(struct irq_data *data) -{ - /* Disable the IRQ at the core by masking it. */ - metag_internal_irq_mask(data); - - /* Clear (toggle) the bit in HWSTATMETA for our interrupt. */ - metag_internal_irq_ack(data); -} - -/* - * metag_internal_irq_ack - acknowledge irq - * @irq: the irq to ack - */ -static void metag_internal_irq_ack(struct irq_data *data) -{ - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << hw; - - if (metag_in32(HWSTATMETA) & bit) - metag_out32(bit, HWSTATMETA); -} - -/** - * metag_internal_irq_mask() - mask an internal irq by unvectoring - * @data: data for the internal irq to mask - * - * HWSTATMETA has no mask register. Instead the IRQ is unvectored from the core - * and retriggered if necessary later. - */ -static void metag_internal_irq_mask(struct irq_data *data) -{ - struct metag_internal_irq_priv *priv = &metag_internal_irq_priv; - irq_hw_number_t hw = data->hwirq; - void __iomem *vec_addr = metag_hwvec_addr(hw); - - clear_bit(hw, &priv->unmasked); - - /* there is no interrupt mask, so unvector the interrupt */ - metag_out32(0, vec_addr); -} - -/** - * meta_intc_unmask_edge_irq_nomask() - unmask an edge irq by revectoring - * @data: data for the internal irq to unmask - * - * HWSTATMETA has no mask register. Instead the IRQ is revectored back to the - * core and retriggered if necessary. - */ -static void metag_internal_irq_unmask(struct irq_data *data) -{ - struct metag_internal_irq_priv *priv = &metag_internal_irq_priv; - irq_hw_number_t hw = data->hwirq; - unsigned int bit = 1 << hw; - void __iomem *vec_addr = metag_hwvec_addr(hw); - unsigned int thread = hard_processor_id(); - - set_bit(hw, &priv->unmasked); - - /* there is no interrupt mask, so revector the interrupt */ - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), vec_addr); - - /* - * Re-trigger interrupt - * - * Writing a 1 toggles, and a 0->1 transition triggers. We only - * retrigger if the status bit is already set, which means we - * need to clear it first. Retriggering is fundamentally racy - * because if the interrupt fires again after we clear it we - * could end up clearing it again and the interrupt handler - * thinking it hasn't fired. Therefore we need to keep trying to - * retrigger until the bit is set. - */ - if (metag_in32(HWSTATMETA) & bit) { - metag_out32(bit, HWSTATMETA); - while (!(metag_in32(HWSTATMETA) & bit)) - metag_out32(bit, HWSTATMETA); - } -} - -#ifdef CONFIG_SMP -/* - * metag_internal_irq_set_affinity - set the affinity for an interrupt - */ -static int metag_internal_irq_set_affinity(struct irq_data *data, - const struct cpumask *cpumask, bool force) -{ - unsigned int cpu, thread; - irq_hw_number_t hw = data->hwirq; - /* - * Wire up this interrupt from *VECINT to the Meta core. - * - * Note that we can't wire up *VECINT to interrupt more than - * one cpu (the interrupt code doesn't support it), so we just - * pick the first cpu we find in 'cpumask'. - */ - cpu = cpumask_any_and(cpumask, cpu_online_mask); - thread = cpu_2_hwthread_id[cpu]; - - metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR1(thread)), - metag_hwvec_addr(hw)); - - return 0; -} -#endif - -/* - * metag_internal_irq_demux - irq de-multiplexer - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * - * The cpu receives an interrupt on TR1 when an interrupt has - * occurred. It is this function's job to demux this irq and - * figure out exactly which trigger needs servicing. - */ -static void metag_internal_irq_demux(struct irq_desc *desc) -{ - struct metag_internal_irq_priv *priv = irq_desc_get_handler_data(desc); - irq_hw_number_t hw; - unsigned int irq_no; - u32 status; - -recalculate: - status = metag_in32(HWSTATMETA) & priv->unmasked; - - for (hw = 0; status != 0; status >>= 1, ++hw) { - if (status & 0x1) { - /* - * Map the hardware IRQ number to a virtual Linux IRQ - * number. - */ - irq_no = irq_linear_revmap(priv->domain, hw); - - /* - * Only fire off interrupts that are - * registered to be handled by the kernel. - * Other interrupts are probably being - * handled by other Meta hardware threads. - */ - generic_handle_irq(irq_no); - - /* - * The handler may have re-enabled interrupts - * which could have caused a nested invocation - * of this code and make the copy of the - * status register we are using invalid. - */ - goto recalculate; - } - } -} - -/** - * internal_irq_map() - Map an internal meta IRQ to a virtual IRQ number. - * @hw: Number of the internal IRQ. Must be in range. - * - * Returns: The virtual IRQ number of the Meta internal IRQ specified by - * @hw. - */ -int internal_irq_map(unsigned int hw) -{ - struct metag_internal_irq_priv *priv = &metag_internal_irq_priv; - if (!priv->domain) - return -ENODEV; - return irq_create_mapping(priv->domain, hw); -} - -/** - * metag_internal_irq_init_cpu - regsister with the Meta cpu - * @cpu: the CPU to register on - * - * Configure @cpu's TR1 irq so that we can demux irqs. - */ -static void metag_internal_irq_init_cpu(struct metag_internal_irq_priv *priv, - int cpu) -{ - unsigned int thread = cpu_2_hwthread_id[cpu]; - unsigned int signum = TBID_SIGNUM_TR1(thread); - int irq = tbisig_map(signum); - - /* Register the multiplexed IRQ handler */ - irq_set_chained_handler_and_data(irq, metag_internal_irq_demux, priv); - irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); -} - -/** - * metag_internal_intc_map() - map an internal irq - * @d: irq domain of internal trigger block - * @irq: virtual irq number - * @hw: hardware irq number within internal trigger block - * - * This sets up a virtual irq for a specified hardware interrupt. The irq chip - * and handler is configured. - */ -static int metag_internal_intc_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hw) -{ - /* only register interrupt if it is mapped */ - if (!metag_hwvec_addr(hw)) - return -EINVAL; - - irq_set_chip_and_handler(irq, &internal_irq_edge_chip, - handle_edge_irq); - return 0; -} - -static const struct irq_domain_ops metag_internal_intc_domain_ops = { - .map = metag_internal_intc_map, -}; - -/** - * metag_internal_irq_register - register internal IRQs - * - * Register the irq chip and handler function for all internal IRQs - */ -int __init init_internal_IRQ(void) -{ - struct metag_internal_irq_priv *priv = &metag_internal_irq_priv; - unsigned int cpu; - - /* Set up an IRQ domain */ - priv->domain = irq_domain_add_linear(NULL, 32, - &metag_internal_intc_domain_ops, - priv); - if (unlikely(!priv->domain)) { - pr_err("meta-internal-intc: cannot add IRQ domain\n"); - return -ENOMEM; - } - - /* Setup TR1 for all cpus. */ - for_each_possible_cpu(cpu) - metag_internal_irq_init_cpu(priv, cpu); - - return 0; -}; diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index eb83d94ab4fe..38cfc8baae19 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -109,7 +109,7 @@ config HISAX_16_3 config HISAX_TELESPCI bool "Teles PCI" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || (XTENSA && !CPU_LITTLE_ENDIAN))) help This enables HiSax support for the Teles PCI. See <file:Documentation/isdn/README.HiSax> on how to configure it. @@ -237,7 +237,7 @@ config HISAX_MIC config HISAX_NETJET bool "NETjet card" - depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE)) + depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE)) depends on VIRT_TO_BUS help This enables HiSax support for the NetJet from Traverse @@ -249,7 +249,7 @@ config HISAX_NETJET config HISAX_NETJET_U bool "NETspider U card" - depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE)) + depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || (XTENSA && !CPU_LITTLE_ENDIAN) || MICROBLAZE)) depends on VIRT_TO_BUS help This enables HiSax support for the Netspider U interface ISDN card @@ -318,7 +318,7 @@ config HISAX_GAZEL config HISAX_HFC_PCI bool "HFC PCI-Bus cards" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) + depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || (XTENSA && !CPU_LITTLE_ENDIAN))) help This enables HiSax support for the HFC-S PCI 2BDS0 based cards. @@ -343,7 +343,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) + depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || (XTENSA && !CPU_LITTLE_ENDIAN))) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 614fbef08ddc..6df9ec377482 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -31,8 +31,6 @@ source "drivers/media/platform/davinci/Kconfig" source "drivers/media/platform/omap/Kconfig" -source "drivers/media/platform/blackfin/Kconfig" - config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on MEDIA_CAMERA_SUPPORT @@ -54,26 +52,6 @@ config VIDEO_VIU Say Y here if you want to enable VIU device on MPC5121e Rev2+. In doubt, say N. -config VIDEO_M32R_AR - tristate "AR devices" - depends on VIDEO_V4L2 - depends on M32R || COMPILE_TEST - ---help--- - This is a video4linux driver for the Renesas AR (Artificial Retina) - camera module. - -config VIDEO_M32R_AR_M64278 - tristate "AR device with color module M64278(VGA)" - depends on PLAT_M32700UT - select VIDEO_M32R_AR - ---help--- - This is a video4linux driver for the Renesas AR (Artificial - Retina) with M64278E-800 camera module. - This module supports VGA(640x480 pixels) resolutions. - - To compile this driver as a module, choose M here: the - module will be called arv. - config VIDEO_MUX tristate "Video Multiplexer" select MULTIPLEXER diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 7f3080437be6..db96a3cb18dd 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -3,8 +3,6 @@ # Makefile for the video capture/playback device drivers. # -obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o - obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/ obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/ @@ -53,8 +51,6 @@ obj-$(CONFIG_VIDEO_TEGRA_HDMI_CEC) += tegra-cec/ obj-y += stm32/ -obj-y += blackfin/ - obj-y += davinci/ obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o diff --git a/drivers/media/platform/arv.c b/drivers/media/platform/arv.c deleted file mode 100644 index 1e865fea803c..000000000000 --- a/drivers/media/platform/arv.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Colour AR M64278(VGA) driver for Video4Linux - * - * Copyright (C) 2003 Takeo Takahashi <takahashi.takeo@renesas.com> - * - * 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. - * - * Some code is taken from AR driver sample program for M3T-M32700UT. - * - * AR driver sample (M32R SDK): - * Copyright (c) 2003 RENESAS TECHNOROGY CORPORATION - * AND RENESAS SOLUTIONS CORPORATION - * All Rights Reserved. - * - * 2003-09-01: Support w3cam by Takeo Takahashi - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-fh.h> -#include <linux/mutex.h> - -#include <linux/uaccess.h> -#include <asm/m32r.h> -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#if 0 -#define DEBUG(n, args...) printk(KERN_INFO args) -#define CHECK_LOST 1 -#else -#define DEBUG(n, args...) -#define CHECK_LOST 0 -#endif - -/* - * USE_INT is always 0, interrupt mode is not available - * on linux due to lack of speed - */ -#define USE_INT 0 /* Don't modify */ - -#define VERSION "0.0.5" - -#define ar_inl(addr) inl((unsigned long)(addr)) -#define ar_outl(val, addr) outl((unsigned long)(val), (unsigned long)(addr)) - -extern struct cpuinfo_m32r boot_cpu_data; - -/* - * CCD pixel size - * Note that M32700UT does not support CIF mode, but QVGA is - * supported by M32700UT hardware using VGA mode of AR LSI. - * - * Supported: VGA (Normal mode, Interlace mode) - * QVGA (Always Interlace mode of VGA) - * - */ -#define AR_WIDTH_VGA 640 -#define AR_HEIGHT_VGA 480 -#define AR_WIDTH_QVGA 320 -#define AR_HEIGHT_QVGA 240 -#define MIN_AR_WIDTH AR_WIDTH_QVGA -#define MIN_AR_HEIGHT AR_HEIGHT_QVGA -#define MAX_AR_WIDTH AR_WIDTH_VGA -#define MAX_AR_HEIGHT AR_HEIGHT_VGA - -/* bits & bytes per pixel */ -#define AR_BITS_PER_PIXEL 16 -#define AR_BYTES_PER_PIXEL (AR_BITS_PER_PIXEL / 8) - -/* line buffer size */ -#define AR_LINE_BYTES_VGA (AR_WIDTH_VGA * AR_BYTES_PER_PIXEL) -#define AR_LINE_BYTES_QVGA (AR_WIDTH_QVGA * AR_BYTES_PER_PIXEL) -#define MAX_AR_LINE_BYTES AR_LINE_BYTES_VGA - -/* frame size & type */ -#define AR_FRAME_BYTES_VGA \ - (AR_WIDTH_VGA * AR_HEIGHT_VGA * AR_BYTES_PER_PIXEL) -#define AR_FRAME_BYTES_QVGA \ - (AR_WIDTH_QVGA * AR_HEIGHT_QVGA * AR_BYTES_PER_PIXEL) -#define MAX_AR_FRAME_BYTES \ - (MAX_AR_WIDTH * MAX_AR_HEIGHT * AR_BYTES_PER_PIXEL) - -#define AR_MAX_FRAME 15 - -/* capture size */ -#define AR_SIZE_VGA 0 -#define AR_SIZE_QVGA 1 - -/* capture mode */ -#define AR_MODE_INTERLACE 0 -#define AR_MODE_NORMAL 1 - -struct ar { - struct v4l2_device v4l2_dev; - struct video_device vdev; - int start_capture; /* duaring capture in INT. mode. */ -#if USE_INT - unsigned char *line_buff; /* DMA line buffer */ -#endif - unsigned char *frame[MAX_AR_HEIGHT]; /* frame data */ - short size; /* capture size */ - short mode; /* capture mode */ - int width, height; - int frame_bytes, line_bytes; - wait_queue_head_t wait; - struct mutex lock; -}; - -static struct ar ardev; - -static int video_nr = -1; /* video device number (first free) */ -static unsigned char yuv[MAX_AR_FRAME_BYTES]; - -/* module parameters */ -/* default frequency */ -#define DEFAULT_FREQ 50 /* 50 or 75 (MHz) is available as BCLK */ -static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */ -static int vga; /* default mode(0:QVGA mode, other:VGA mode) */ -static int vga_interlace; /* 0 is normal mode for, else interlace mode */ -module_param(freq, int, 0); -module_param(vga, int, 0); -module_param(vga_interlace, int, 0); - -static void wait_for_vsync(void) -{ - while (ar_inl(ARVCR0) & ARVCR0_VDS) /* wait for VSYNC */ - cpu_relax(); - while (!(ar_inl(ARVCR0) & ARVCR0_VDS)) /* wait for VSYNC */ - cpu_relax(); -} - -static void wait_acknowledge(void) -{ - int i; - - for (i = 0; i < 1000; i++) - cpu_relax(); - while (ar_inl(PLDI2CSTS) & PLDI2CSTS_NOACK) - cpu_relax(); -} - -/******************************************************************* - * I2C functions - *******************************************************************/ -static void iic(int n, unsigned long addr, unsigned long data1, unsigned long data2, - unsigned long data3) -{ - int i; - - /* Slave Address */ - ar_outl(addr, PLDI2CDATA); - wait_for_vsync(); - - /* Start */ - ar_outl(1, PLDI2CCND); - wait_acknowledge(); - - /* Transfer data 1 */ - ar_outl(data1, PLDI2CDATA); - wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); - wait_acknowledge(); - - /* Transfer data 2 */ - ar_outl(data2, PLDI2CDATA); - wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); - wait_acknowledge(); - - if (n == 3) { - /* Transfer data 3 */ - ar_outl(data3, PLDI2CDATA); - wait_for_vsync(); - ar_outl(PLDI2CSTEN_STEN, PLDI2CSTEN); - wait_acknowledge(); - } - - /* Stop */ - for (i = 0; i < 100; i++) - cpu_relax(); - ar_outl(2, PLDI2CCND); - ar_outl(2, PLDI2CCND); - - while (ar_inl(PLDI2CSTS) & PLDI2CSTS_BB) - cpu_relax(); -} - - -static void init_iic(void) -{ - DEBUG(1, "init_iic:\n"); - - /* - * ICU Setting (iic) - */ - /* I2C Setting */ - ar_outl(0x0, PLDI2CCR); /* I2CCR Disable */ - ar_outl(0x0300, PLDI2CMOD); /* I2CMOD ACK/8b-data/7b-addr/auto */ - ar_outl(0x1, PLDI2CACK); /* I2CACK ACK */ - - /* I2C CLK */ - /* 50MH-100k */ - if (freq == 75) - ar_outl(369, PLDI2CFREQ); /* BCLK = 75MHz */ - else if (freq == 50) - ar_outl(244, PLDI2CFREQ); /* BCLK = 50MHz */ - else - ar_outl(244, PLDI2CFREQ); /* default: BCLK = 50MHz */ - ar_outl(0x1, PLDI2CCR); /* I2CCR Enable */ -} - -/************************************************************************** - * - * Video4Linux Interface functions - * - **************************************************************************/ - -static inline void disable_dma(void) -{ - ar_outl(0x8000, M32R_DMAEN_PORTL); /* disable DMA0 */ -} - -static inline void enable_dma(void) -{ - ar_outl(0x8080, M32R_DMAEN_PORTL); /* enable DMA0 */ -} - -static inline void clear_dma_status(void) -{ - ar_outl(0x8000, M32R_DMAEDET_PORTL); /* clear status */ -} - -static void wait_for_vertical_sync(struct ar *ar, int exp_line) -{ -#if CHECK_LOST - int tmout = 10000; /* FIXME */ - int l; - - /* - * check HCOUNT because we cannot check vertical sync. - */ - for (; tmout >= 0; tmout--) { - l = ar_inl(ARVHCOUNT); - if (l == exp_line) - break; - } - if (tmout < 0) - v4l2_err(&ar->v4l2_dev, "lost %d -> %d\n", exp_line, l); -#else - while (ar_inl(ARVHCOUNT) != exp_line) - cpu_relax(); -#endif -} - -static ssize_t ar_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - struct ar *ar = video_drvdata(file); - long ret = ar->frame_bytes; /* return read bytes */ - unsigned long arvcr1 = 0; - unsigned long flags; - unsigned char *p; - int h, w; - unsigned char *py, *pu, *pv; -#if !USE_INT - int l; -#endif - - DEBUG(1, "ar_read()\n"); - - if (ar->size == AR_SIZE_QVGA) - arvcr1 |= ARVCR1_QVGA; - if (ar->mode == AR_MODE_NORMAL) - arvcr1 |= ARVCR1_NORMAL; - - mutex_lock(&ar->lock); - -#if USE_INT - local_irq_save(flags); - disable_dma(); - ar_outl(0xa1871300, M32R_DMA0CR0_PORTL); - ar_outl(0x01000000, M32R_DMA0CR1_PORTL); - - /* set AR FIFO address as source(BSEL5) */ - ar_outl(ARDATA32, M32R_DMA0CSA_PORTL); - ar_outl(ARDATA32, M32R_DMA0RSA_PORTL); - ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL); /* destination addr. */ - ar_outl(ar->line_buff, M32R_DMA0RDA_PORTL); /* reload address */ - ar_outl(ar->line_bytes, M32R_DMA0CBCUT_PORTL); /* byte count (bytes) */ - ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); /* reload count (bytes) */ - - /* - * Okay, kick AR LSI to invoke an interrupt - */ - ar->start_capture = -1; - ar_outl(arvcr1 | ARVCR1_HIEN, ARVCR1); - local_irq_restore(flags); - /* .... AR interrupts .... */ - wait_event_interruptible(ar->wait, ar->start_capture == 0); - if (signal_pending(current)) { - printk(KERN_ERR "arv: interrupted while get frame data.\n"); - ret = -EINTR; - goto out_up; - } -#else /* ! USE_INT */ - /* polling */ - ar_outl(arvcr1, ARVCR1); - disable_dma(); - ar_outl(0x8000, M32R_DMAEDET_PORTL); - ar_outl(0xa0861300, M32R_DMA0CR0_PORTL); - ar_outl(0x01000000, M32R_DMA0CR1_PORTL); - ar_outl(ARDATA32, M32R_DMA0CSA_PORTL); - ar_outl(ARDATA32, M32R_DMA0RSA_PORTL); - ar_outl(ar->line_bytes, M32R_DMA0CBCUT_PORTL); - ar_outl(ar->line_bytes, M32R_DMA0RBCUT_PORTL); - - local_irq_save(flags); - while (ar_inl(ARVHCOUNT) != 0) /* wait for 0 */ - cpu_relax(); - if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { - for (h = 0; h < ar->height; h++) { - wait_for_vertical_sync(ar, h); - if (h < (AR_HEIGHT_VGA/2)) - l = h << 1; - else - l = (((h - (AR_HEIGHT_VGA/2)) << 1) + 1); - ar_outl(virt_to_phys(ar->frame[l]), M32R_DMA0CDA_PORTL); - enable_dma(); - while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000)) - cpu_relax(); - disable_dma(); - clear_dma_status(); - ar_outl(0xa0861300, M32R_DMA0CR0_PORTL); - } - } else { - for (h = 0; h < ar->height; h++) { - wait_for_vertical_sync(ar, h); - ar_outl(virt_to_phys(ar->frame[h]), M32R_DMA0CDA_PORTL); - enable_dma(); - while (!(ar_inl(M32R_DMAEDET_PORTL) & 0x8000)) - cpu_relax(); - disable_dma(); - clear_dma_status(); - ar_outl(0xa0861300, M32R_DMA0CR0_PORTL); - } - } - local_irq_restore(flags); -#endif /* ! USE_INT */ - - /* - * convert YUV422 to YUV422P - * +--------------------+ - * | Y0,Y1,... | - * | ..............Yn | - * +--------------------+ - * | U0,U1,........Un | - * +--------------------+ - * | V0,V1,........Vn | - * +--------------------+ - */ - py = yuv; - pu = py + (ar->frame_bytes / 2); - pv = pu + (ar->frame_bytes / 4); - for (h = 0; h < ar->height; h++) { - p = ar->frame[h]; - for (w = 0; w < ar->line_bytes; w += 4) { - *py++ = *p++; - *pu++ = *p++; - *py++ = *p++; - *pv++ = *p++; - } - } - if (copy_to_user(buf, yuv, ar->frame_bytes)) { - v4l2_err(&ar->v4l2_dev, "failed while copy_to_user yuv.\n"); - ret = -EFAULT; - goto out_up; - } - DEBUG(1, "ret = %d\n", ret); -out_up: - mutex_unlock(&ar->lock); - return ret; -} - -static int ar_querycap(struct file *file, void *priv, - struct v4l2_capability *vcap) -{ - struct ar *ar = video_drvdata(file); - - strlcpy(vcap->driver, ar->vdev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, "Colour AR VGA", sizeof(vcap->card)); - strlcpy(vcap->bus_info, "Platform", sizeof(vcap->bus_info)); - vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; - vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int ar_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - if (vin->index > 0) - return -EINVAL; - strlcpy(vin->name, "Camera", sizeof(vin->name)); - vin->type = V4L2_INPUT_TYPE_CAMERA; - vin->audioset = 0; - vin->tuner = 0; - vin->std = V4L2_STD_ALL; - vin->status = 0; - return 0; -} - -static int ar_g_input(struct file *file, void *fh, unsigned int *inp) -{ - *inp = 0; - return 0; -} - -static int ar_s_input(struct file *file, void *fh, unsigned int inp) -{ - return inp ? -EINVAL : 0; -} - -static int ar_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ar *ar = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - pix->width = ar->width; - pix->height = ar->height; - pix->pixelformat = V4L2_PIX_FMT_YUV422P; - pix->field = (ar->mode == AR_MODE_NORMAL) ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED; - pix->bytesperline = ar->width; - pix->sizeimage = 2 * ar->width * ar->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - return 0; -} - -static int ar_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ar *ar = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - - if (pix->height <= AR_HEIGHT_QVGA || pix->width <= AR_WIDTH_QVGA) { - pix->height = AR_HEIGHT_QVGA; - pix->width = AR_WIDTH_QVGA; - pix->field = V4L2_FIELD_INTERLACED; - } else { - pix->height = AR_HEIGHT_VGA; - pix->width = AR_WIDTH_VGA; - pix->field = vga_interlace ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; - } - pix->pixelformat = V4L2_PIX_FMT_YUV422P; - pix->bytesperline = ar->width; - pix->sizeimage = 2 * ar->width * ar->height; - /* Just a guess */ - pix->colorspace = V4L2_COLORSPACE_SMPTE170M; - return 0; -} - -static int ar_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ar *ar = video_drvdata(file); - struct v4l2_pix_format *pix = &fmt->fmt.pix; - int ret = ar_try_fmt_vid_cap(file, fh, fmt); - - if (ret) - return ret; - mutex_lock(&ar->lock); - ar->width = pix->width; - ar->height = pix->height; - if (ar->width == AR_WIDTH_VGA) { - ar->size = AR_SIZE_VGA; - ar->frame_bytes = AR_FRAME_BYTES_VGA; - ar->line_bytes = AR_LINE_BYTES_VGA; - if (vga_interlace) - ar->mode = AR_MODE_INTERLACE; - else - ar->mode = AR_MODE_NORMAL; - } else { - ar->size = AR_SIZE_QVGA; - ar->frame_bytes = AR_FRAME_BYTES_QVGA; - ar->line_bytes = AR_LINE_BYTES_QVGA; - ar->mode = AR_MODE_INTERLACE; - } - /* Ok we figured out what to use from our wide choice */ - mutex_unlock(&ar->lock); - return 0; -} - -static int ar_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "YUV 4:2:2 Planar", V4L2_PIX_FMT_YUV422P, - { 0, 0, 0, 0 } - }, - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 0) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -#if USE_INT -/* - * Interrupt handler - */ -static void ar_interrupt(int irq, void *dev) -{ - struct ar *ar = dev; - unsigned int line_count; - unsigned int line_number; - unsigned int arvcr1; - - line_count = ar_inl(ARVHCOUNT); /* line number */ - if (ar->mode == AR_MODE_INTERLACE && ar->size == AR_SIZE_VGA) { - /* operations for interlace mode */ - if (line_count < (AR_HEIGHT_VGA / 2)) /* even line */ - line_number = (line_count << 1); - else /* odd line */ - line_number = - (((line_count - (AR_HEIGHT_VGA / 2)) << 1) + 1); - } else { - line_number = line_count; - } - - if (line_number == 0) { - /* - * It is an interrupt for line 0. - * we have to start capture. - */ - disable_dma(); -#if 0 - ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL); /* needless? */ -#endif - memcpy(ar->frame[0], ar->line_buff, ar->line_bytes); -#if 0 - ar_outl(0xa1861300, M32R_DMA0CR0_PORTL); -#endif - enable_dma(); - ar->start_capture = 1; /* during capture */ - return; - } - - if (ar->start_capture == 1 && line_number <= (ar->height - 1)) { - disable_dma(); - memcpy(ar->frame[line_number], ar->line_buff, ar->line_bytes); - - /* - * if captured all line of a frame, disable AR interrupt - * and wake a process up. - */ - if (line_number == (ar->height - 1)) { /* end of line */ - - ar->start_capture = 0; - - /* disable AR interrupt request */ - arvcr1 = ar_inl(ARVCR1); - arvcr1 &= ~ARVCR1_HIEN; /* clear int. flag */ - ar_outl(arvcr1, ARVCR1); /* disable */ - wake_up_interruptible(&ar->wait); - } else { -#if 0 - ar_outl(ar->line_buff, M32R_DMA0CDA_PORTL); - ar_outl(0xa1861300, M32R_DMA0CR0_PORTL); -#endif - enable_dma(); - } - } -} -#endif - -/* - * ar_initialize() - * ar_initialize() is called by video_register_device() and - * initializes AR LSI and peripherals. - * - * -1 is returned in all failures. - * 0 is returned in success. - * - */ -static int ar_initialize(struct ar *ar) -{ - unsigned long cr = 0; - int i, found = 0; - - DEBUG(1, "ar_initialize:\n"); - - /* - * initialize AR LSI - */ - ar_outl(0, ARVCR0); /* assert reset of AR LSI */ - for (i = 0; i < 0x18; i++) /* wait for over 10 cycles @ 27MHz */ - cpu_relax(); - ar_outl(ARVCR0_RST, ARVCR0); /* negate reset of AR LSI (enable) */ - for (i = 0; i < 0x40d; i++) /* wait for over 420 cycles @ 27MHz */ - cpu_relax(); - - /* AR uses INT3 of CPU as interrupt pin. */ - ar_outl(ARINTSEL_INT3, ARINTSEL); - - if (ar->size == AR_SIZE_QVGA) - cr |= ARVCR1_QVGA; - if (ar->mode == AR_MODE_NORMAL) - cr |= ARVCR1_NORMAL; - ar_outl(cr, ARVCR1); - - /* - * Initialize IIC so that CPU can communicate with AR LSI, - * and send boot commands to AR LSI. - */ - init_iic(); - - for (i = 0; i < 0x100000; i++) { /* > 0xa1d10, 56ms */ - if ((ar_inl(ARVCR0) & ARVCR0_VDS)) { /* VSYNC */ - found = 1; - break; - } - } - - if (found == 0) - return -ENODEV; - - v4l2_info(&ar->v4l2_dev, "Initializing "); - - iic(2, 0x78, 0x11, 0x01, 0x00); /* start */ - iic(3, 0x78, 0x12, 0x00, 0x06); - iic(3, 0x78, 0x12, 0x12, 0x30); - iic(3, 0x78, 0x12, 0x15, 0x58); - iic(3, 0x78, 0x12, 0x17, 0x30); - printk(KERN_CONT "."); - iic(3, 0x78, 0x12, 0x1a, 0x97); - iic(3, 0x78, 0x12, 0x1b, 0xff); - iic(3, 0x78, 0x12, 0x1c, 0xff); - iic(3, 0x78, 0x12, 0x26, 0x10); - iic(3, 0x78, 0x12, 0x27, 0x00); - printk(KERN_CONT "."); - iic(2, 0x78, 0x34, 0x02, 0x00); - iic(2, 0x78, 0x7a, 0x10, 0x00); - iic(2, 0x78, 0x80, 0x39, 0x00); - iic(2, 0x78, 0x81, 0xe6, 0x00); - iic(2, 0x78, 0x8d, 0x00, 0x00); - printk(KERN_CONT "."); - iic(2, 0x78, 0x8e, 0x0c, 0x00); - iic(2, 0x78, 0x8f, 0x00, 0x00); -#if 0 - iic(2, 0x78, 0x90, 0x00, 0x00); /* AWB on=1 off=0 */ -#endif - iic(2, 0x78, 0x93, 0x01, 0x00); - iic(2, 0x78, 0x94, 0xcd, 0x00); - iic(2, 0x78, 0x95, 0x00, 0x00); - printk(KERN_CONT "."); - iic(2, 0x78, 0x96, 0xa0, 0x00); - iic(2, 0x78, 0x97, 0x00, 0x00); - iic(2, 0x78, 0x98, 0x60, 0x00); - iic(2, 0x78, 0x99, 0x01, 0x00); - iic(2, 0x78, 0x9a, 0x19, 0x00); - printk(KERN_CONT "."); - iic(2, 0x78, 0x9b, 0x02, 0x00); - iic(2, 0x78, 0x9c, 0xe8, 0x00); - iic(2, 0x78, 0x9d, 0x02, 0x00); - iic(2, 0x78, 0x9e, 0x2e, 0x00); - iic(2, 0x78, 0xb8, 0x78, 0x00); - iic(2, 0x78, 0xba, 0x05, 0x00); -#if 0 - iic(2, 0x78, 0x83, 0x8c, 0x00); /* brightness */ -#endif - printk(KERN_CONT "."); - - /* color correction */ - iic(3, 0x78, 0x49, 0x00, 0x95); /* a */ - iic(3, 0x78, 0x49, 0x01, 0x96); /* b */ - iic(3, 0x78, 0x49, 0x03, 0x85); /* c */ - iic(3, 0x78, 0x49, 0x04, 0x97); /* d */ - iic(3, 0x78, 0x49, 0x02, 0x7e); /* e(Lo) */ - iic(3, 0x78, 0x49, 0x05, 0xa4); /* f(Lo) */ - iic(3, 0x78, 0x49, 0x06, 0x04); /* e(Hi) */ - iic(3, 0x78, 0x49, 0x07, 0x04); /* e(Hi) */ - iic(2, 0x78, 0x48, 0x01, 0x00); /* on=1 off=0 */ - - printk(KERN_CONT "."); - iic(2, 0x78, 0x11, 0x00, 0x00); /* end */ - printk(KERN_CONT " done\n"); - return 0; -} - - -/**************************************************************************** - * - * Video4Linux Module functions - * - ****************************************************************************/ - -static const struct v4l2_file_operations ar_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = v4l2_fh_release, - .read = ar_read, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops ar_ioctl_ops = { - .vidioc_querycap = ar_querycap, - .vidioc_g_input = ar_g_input, - .vidioc_s_input = ar_s_input, - .vidioc_enum_input = ar_enum_input, - .vidioc_enum_fmt_vid_cap = ar_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = ar_g_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = ar_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = ar_try_fmt_vid_cap, -}; - -#define ALIGN4(x) ((((int)(x)) & 0x3) == 0) - -static int __init ar_init(void) -{ - struct ar *ar; - struct v4l2_device *v4l2_dev; - int ret; - int i; - - ar = &ardev; - v4l2_dev = &ar->v4l2_dev; - strlcpy(v4l2_dev->name, "arv", sizeof(v4l2_dev->name)); - v4l2_info(v4l2_dev, "Colour AR VGA driver %s\n", VERSION); - - ret = v4l2_device_register(NULL, v4l2_dev); - if (ret < 0) { - v4l2_err(v4l2_dev, "Could not register v4l2_device\n"); - return ret; - } - ret = -EIO; - -#if USE_INT - /* allocate a DMA buffer for 1 line. */ - ar->line_buff = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL | GFP_DMA); - if (ar->line_buff == NULL || !ALIGN4(ar->line_buff)) { - v4l2_err(v4l2_dev, "buffer allocation failed for DMA.\n"); - ret = -ENOMEM; - goto out_end; - } -#endif - /* allocate buffers for a frame */ - for (i = 0; i < MAX_AR_HEIGHT; i++) { - ar->frame[i] = kmalloc(MAX_AR_LINE_BYTES, GFP_KERNEL); - if (ar->frame[i] == NULL || !ALIGN4(ar->frame[i])) { - v4l2_err(v4l2_dev, "buffer allocation failed for frame.\n"); - ret = -ENOMEM; - goto out_line_buff; - } - } - - strlcpy(ar->vdev.name, "Colour AR VGA", sizeof(ar->vdev.name)); - ar->vdev.v4l2_dev = v4l2_dev; - ar->vdev.fops = &ar_fops; - ar->vdev.ioctl_ops = &ar_ioctl_ops; - ar->vdev.release = video_device_release_empty; - video_set_drvdata(&ar->vdev, ar); - - if (vga) { - ar->width = AR_WIDTH_VGA; - ar->height = AR_HEIGHT_VGA; - ar->size = AR_SIZE_VGA; - ar->frame_bytes = AR_FRAME_BYTES_VGA; - ar->line_bytes = AR_LINE_BYTES_VGA; - if (vga_interlace) - ar->mode = AR_MODE_INTERLACE; - else - ar->mode = AR_MODE_NORMAL; - } else { - ar->width = AR_WIDTH_QVGA; - ar->height = AR_HEIGHT_QVGA; - ar->size = AR_SIZE_QVGA; - ar->frame_bytes = AR_FRAME_BYTES_QVGA; - ar->line_bytes = AR_LINE_BYTES_QVGA; - ar->mode = AR_MODE_INTERLACE; - } - mutex_init(&ar->lock); - init_waitqueue_head(&ar->wait); - -#if USE_INT - if (request_irq(M32R_IRQ_INT3, ar_interrupt, 0, "arv", ar)) { - v4l2_err("request_irq(%d) failed.\n", M32R_IRQ_INT3); - ret = -EIO; - goto out_irq; - } -#endif - - if (ar_initialize(ar) != 0) { - v4l2_err(v4l2_dev, "M64278 not found.\n"); - ret = -ENODEV; - goto out_dev; - } - - /* - * ok, we can initialize h/w according to parameters, - * so register video device as a frame grabber type. - * device is named "video[0-64]". - * video_register_device() initializes h/w using ar_initialize(). - */ - if (video_register_device(&ar->vdev, VFL_TYPE_GRABBER, video_nr) != 0) { - /* return -1, -ENFILE(full) or others */ - v4l2_err(v4l2_dev, "register video (Colour AR) failed.\n"); - ret = -ENODEV; - goto out_dev; - } - - v4l2_info(v4l2_dev, "%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n", - video_device_node_name(&ar->vdev), M32R_IRQ_INT3, freq); - - return 0; - -out_dev: -#if USE_INT - free_irq(M32R_IRQ_INT3, ar); - -out_irq: -#endif - for (i = 0; i < MAX_AR_HEIGHT; i++) - kfree(ar->frame[i]); - -out_line_buff: -#if USE_INT - kfree(ar->line_buff); - -out_end: -#endif - v4l2_device_unregister(&ar->v4l2_dev); - return ret; -} - - -static int __init ar_init_module(void) -{ - freq = (boot_cpu_data.bus_clock / 1000000); - printk(KERN_INFO "arv: Bus clock %d\n", freq); - if (freq != 50 && freq != 75) - freq = DEFAULT_FREQ; - return ar_init(); -} - -static void __exit ar_cleanup_module(void) -{ - struct ar *ar; - int i; - - ar = &ardev; - video_unregister_device(&ar->vdev); -#if USE_INT - free_irq(M32R_IRQ_INT3, ar); -#endif - for (i = 0; i < MAX_AR_HEIGHT; i++) - kfree(ar->frame[i]); -#if USE_INT - kfree(ar->line_buff); -#endif - v4l2_device_unregister(&ar->v4l2_dev); -} - -module_init(ar_init_module); -module_exit(ar_cleanup_module); - -MODULE_AUTHOR("Takeo Takahashi <takahashi.takeo@renesas.com>"); -MODULE_DESCRIPTION("Colour AR M64278(VGA) for Video4Linux"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(VERSION); diff --git a/drivers/media/platform/blackfin/Kconfig b/drivers/media/platform/blackfin/Kconfig deleted file mode 100644 index 68fa90151b8f..000000000000 --- a/drivers/media/platform/blackfin/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config VIDEO_BLACKFIN_CAPTURE - tristate "Blackfin Video Capture Driver" - depends on VIDEO_V4L2 && BLACKFIN && I2C - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - help - V4L2 bridge driver for Blackfin video capture device. - Choose PPI or EPPI as its interface. - - To compile this driver as a module, choose M here: the - module will be called bfin_capture. - -config VIDEO_BLACKFIN_PPI - tristate - depends on VIDEO_BLACKFIN_CAPTURE - default VIDEO_BLACKFIN_CAPTURE diff --git a/drivers/media/platform/blackfin/Makefile b/drivers/media/platform/blackfin/Makefile deleted file mode 100644 index 30421bc23080..000000000000 --- a/drivers/media/platform/blackfin/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_VIDEO_BLACKFIN_CAPTURE) += bfin_capture.o -obj-$(CONFIG_VIDEO_BLACKFIN_PPI) += ppi.o diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c deleted file mode 100644 index 41f179117fb0..000000000000 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - * Analog Devices video capture driver - * - * Copyright (c) 2011 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include <linux/completion.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/time.h> -#include <linux/types.h> - -#include <media/v4l2-common.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/videobuf2-dma-contig.h> - -#include <asm/dma.h> - -#include <media/blackfin/bfin_capture.h> -#include <media/blackfin/ppi.h> - -#define CAPTURE_DRV_NAME "bfin_capture" - -struct bcap_format { - char *desc; - u32 pixelformat; - u32 mbus_code; - int bpp; /* bits per pixel */ - int dlen; /* data length for ppi in bits */ -}; - -struct bcap_buffer { - struct vb2_v4l2_buffer vb; - struct list_head list; -}; - -struct bcap_device { - /* capture device instance */ - struct v4l2_device v4l2_dev; - /* v4l2 control handler */ - struct v4l2_ctrl_handler ctrl_handler; - /* device node data */ - struct video_device video_dev; - /* sub device instance */ - struct v4l2_subdev *sd; - /* capture config */ - struct bfin_capture_config *cfg; - /* ppi interface */ - struct ppi_if *ppi; - /* current input */ - unsigned int cur_input; - /* current selected standard */ - v4l2_std_id std; - /* current selected dv_timings */ - struct v4l2_dv_timings dv_timings; - /* used to store pixel format */ - struct v4l2_pix_format fmt; - /* bits per pixel*/ - int bpp; - /* data length for ppi in bits */ - int dlen; - /* used to store sensor supported format */ - struct bcap_format *sensor_formats; - /* number of sensor formats array */ - int num_sensor_formats; - /* pointing to current video buffer */ - struct bcap_buffer *cur_frm; - /* buffer queue used in videobuf2 */ - struct vb2_queue buffer_queue; - /* queue of filled frames */ - struct list_head dma_queue; - /* used in videobuf2 callback */ - spinlock_t lock; - /* used to access capture device */ - struct mutex mutex; - /* used to wait ppi to complete one transfer */ - struct completion comp; - /* prepare to stop */ - bool stop; - /* vb2 buffer sequence counter */ - unsigned sequence; -}; - -static const struct bcap_format bcap_formats[] = { - { - .desc = "YCbCr 4:2:2 Interleaved UYVY", - .pixelformat = V4L2_PIX_FMT_UYVY, - .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8, - .bpp = 16, - .dlen = 8, - }, - { - .desc = "YCbCr 4:2:2 Interleaved YUYV", - .pixelformat = V4L2_PIX_FMT_YUYV, - .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, - .bpp = 16, - .dlen = 8, - }, - { - .desc = "YCbCr 4:2:2 Interleaved UYVY", - .pixelformat = V4L2_PIX_FMT_UYVY, - .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, - .bpp = 16, - .dlen = 16, - }, - { - .desc = "RGB 565", - .pixelformat = V4L2_PIX_FMT_RGB565, - .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, - .bpp = 16, - .dlen = 8, - }, - { - .desc = "RGB 444", - .pixelformat = V4L2_PIX_FMT_RGB444, - .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, - .bpp = 16, - .dlen = 8, - }, - -}; -#define BCAP_MAX_FMTS ARRAY_SIZE(bcap_formats) - -static irqreturn_t bcap_isr(int irq, void *dev_id); - -static struct bcap_buffer *to_bcap_vb(struct vb2_v4l2_buffer *vb) -{ - return container_of(vb, struct bcap_buffer, vb); -} - -static int bcap_init_sensor_formats(struct bcap_device *bcap_dev) -{ - struct v4l2_subdev_mbus_code_enum code = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct bcap_format *sf; - unsigned int num_formats = 0; - int i, j; - - while (!v4l2_subdev_call(bcap_dev->sd, pad, - enum_mbus_code, NULL, &code)) { - num_formats++; - code.index++; - } - if (!num_formats) - return -ENXIO; - - sf = kcalloc(num_formats, sizeof(*sf), GFP_KERNEL); - if (!sf) - return -ENOMEM; - - for (i = 0; i < num_formats; i++) { - code.index = i; - v4l2_subdev_call(bcap_dev->sd, pad, - enum_mbus_code, NULL, &code); - for (j = 0; j < BCAP_MAX_FMTS; j++) - if (code.code == bcap_formats[j].mbus_code) - break; - if (j == BCAP_MAX_FMTS) { - /* we don't allow this sensor working with our bridge */ - kfree(sf); - return -EINVAL; - } - sf[i] = bcap_formats[j]; - } - bcap_dev->sensor_formats = sf; - bcap_dev->num_sensor_formats = num_formats; - return 0; -} - -static void bcap_free_sensor_formats(struct bcap_device *bcap_dev) -{ - bcap_dev->num_sensor_formats = 0; - kfree(bcap_dev->sensor_formats); - bcap_dev->sensor_formats = NULL; -} - -static int bcap_queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_devs[]) -{ - struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); - - if (vq->num_buffers + *nbuffers < 2) - *nbuffers = 2; - - if (*nplanes) - return sizes[0] < bcap_dev->fmt.sizeimage ? -EINVAL : 0; - - *nplanes = 1; - sizes[0] = bcap_dev->fmt.sizeimage; - - return 0; -} - -static int bcap_buffer_prepare(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); - unsigned long size = bcap_dev->fmt.sizeimage; - - if (vb2_plane_size(vb, 0) < size) { - v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n", - vb2_plane_size(vb, 0), size); - return -EINVAL; - } - vb2_set_plane_payload(vb, 0, size); - - vbuf->field = bcap_dev->fmt.field; - - return 0; -} - -static void bcap_buffer_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); - struct bcap_buffer *buf = to_bcap_vb(vbuf); - unsigned long flags; - - spin_lock_irqsave(&bcap_dev->lock, flags); - list_add_tail(&buf->list, &bcap_dev->dma_queue); - spin_unlock_irqrestore(&bcap_dev->lock, flags); -} - -static void bcap_buffer_cleanup(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue); - struct bcap_buffer *buf = to_bcap_vb(vbuf); - unsigned long flags; - - spin_lock_irqsave(&bcap_dev->lock, flags); - list_del_init(&buf->list); - spin_unlock_irqrestore(&bcap_dev->lock, flags); -} - -static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); - struct ppi_if *ppi = bcap_dev->ppi; - struct bcap_buffer *buf, *tmp; - struct ppi_params params; - dma_addr_t addr; - int ret; - - /* enable streamon on the sub device */ - ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1); - if (ret && (ret != -ENOIOCTLCMD)) { - v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n"); - goto err; - } - - /* set ppi params */ - params.width = bcap_dev->fmt.width; - params.height = bcap_dev->fmt.height; - params.bpp = bcap_dev->bpp; - params.dlen = bcap_dev->dlen; - params.ppi_control = bcap_dev->cfg->ppi_control; - params.int_mask = bcap_dev->cfg->int_mask; - if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities - & V4L2_IN_CAP_DV_TIMINGS) { - struct v4l2_bt_timings *bt = &bcap_dev->dv_timings.bt; - - params.hdelay = bt->hsync + bt->hbackporch; - params.vdelay = bt->vsync + bt->vbackporch; - params.line = V4L2_DV_BT_FRAME_WIDTH(bt); - params.frame = V4L2_DV_BT_FRAME_HEIGHT(bt); - } else if (bcap_dev->cfg->inputs[bcap_dev->cur_input].capabilities - & V4L2_IN_CAP_STD) { - params.hdelay = 0; - params.vdelay = 0; - if (bcap_dev->std & V4L2_STD_525_60) { - params.line = 858; - params.frame = 525; - } else { - params.line = 864; - params.frame = 625; - } - } else { - params.hdelay = 0; - params.vdelay = 0; - params.line = params.width + bcap_dev->cfg->blank_pixels; - params.frame = params.height; - } - ret = ppi->ops->set_params(ppi, ¶ms); - if (ret < 0) { - v4l2_err(&bcap_dev->v4l2_dev, - "Error in setting ppi params\n"); - goto err; - } - - /* attach ppi DMA irq handler */ - ret = ppi->ops->attach_irq(ppi, bcap_isr); - if (ret < 0) { - v4l2_err(&bcap_dev->v4l2_dev, - "Error in attaching interrupt handler\n"); - goto err; - } - - bcap_dev->sequence = 0; - - reinit_completion(&bcap_dev->comp); - bcap_dev->stop = false; - - /* get the next frame from the dma queue */ - bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, - struct bcap_buffer, list); - /* remove buffer from the dma queue */ - list_del_init(&bcap_dev->cur_frm->list); - addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb.vb2_buf, - 0); - /* update DMA address */ - ppi->ops->update_addr(ppi, (unsigned long)addr); - /* enable ppi */ - ppi->ops->start(ppi); - - return 0; - -err: - list_for_each_entry_safe(buf, tmp, &bcap_dev->dma_queue, list) { - list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); - } - - return ret; -} - -static void bcap_stop_streaming(struct vb2_queue *vq) -{ - struct bcap_device *bcap_dev = vb2_get_drv_priv(vq); - struct ppi_if *ppi = bcap_dev->ppi; - int ret; - - bcap_dev->stop = true; - wait_for_completion(&bcap_dev->comp); - ppi->ops->stop(ppi); - ppi->ops->detach_irq(ppi); - ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 0); - if (ret && (ret != -ENOIOCTLCMD)) - v4l2_err(&bcap_dev->v4l2_dev, - "stream off failed in subdev\n"); - - /* release all active buffers */ - if (bcap_dev->cur_frm) - vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - - while (!list_empty(&bcap_dev->dma_queue)) { - bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, - struct bcap_buffer, list); - list_del_init(&bcap_dev->cur_frm->list); - vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf, - VB2_BUF_STATE_ERROR); - } -} - -static const struct vb2_ops bcap_video_qops = { - .queue_setup = bcap_queue_setup, - .buf_prepare = bcap_buffer_prepare, - .buf_cleanup = bcap_buffer_cleanup, - .buf_queue = bcap_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .start_streaming = bcap_start_streaming, - .stop_streaming = bcap_stop_streaming, -}; - -static irqreturn_t bcap_isr(int irq, void *dev_id) -{ - struct ppi_if *ppi = dev_id; - struct bcap_device *bcap_dev = ppi->priv; - struct vb2_v4l2_buffer *vbuf = &bcap_dev->cur_frm->vb; - struct vb2_buffer *vb = &vbuf->vb2_buf; - dma_addr_t addr; - - spin_lock(&bcap_dev->lock); - - if (!list_empty(&bcap_dev->dma_queue)) { - vb->timestamp = ktime_get_ns(); - if (ppi->err) { - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); - ppi->err = false; - } else { - vbuf->sequence = bcap_dev->sequence++; - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); - } - bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next, - struct bcap_buffer, list); - list_del_init(&bcap_dev->cur_frm->list); - } else { - /* clear error flag, we will get a new frame */ - if (ppi->err) - ppi->err = false; - } - - ppi->ops->stop(ppi); - - if (bcap_dev->stop) { - complete(&bcap_dev->comp); - } else { - addr = vb2_dma_contig_plane_dma_addr( - &bcap_dev->cur_frm->vb.vb2_buf, 0); - ppi->ops->update_addr(ppi, (unsigned long)addr); - ppi->ops->start(ppi); - } - - spin_unlock(&bcap_dev->lock); - - return IRQ_HANDLED; -} - -static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_STD)) - return -ENODATA; - - return v4l2_subdev_call(bcap_dev->sd, video, querystd, std); -} - -static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_STD)) - return -ENODATA; - - *std = bcap_dev->std; - return 0; -} - -static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - int ret; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_STD)) - return -ENODATA; - - if (vb2_is_busy(&bcap_dev->buffer_queue)) - return -EBUSY; - - ret = v4l2_subdev_call(bcap_dev->sd, video, s_std, std); - if (ret < 0) - return ret; - - bcap_dev->std = std; - return 0; -} - -static int bcap_enum_dv_timings(struct file *file, void *priv, - struct v4l2_enum_dv_timings *timings) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS)) - return -ENODATA; - - timings->pad = 0; - - return v4l2_subdev_call(bcap_dev->sd, pad, - enum_dv_timings, timings); -} - -static int bcap_query_dv_timings(struct file *file, void *priv, - struct v4l2_dv_timings *timings) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS)) - return -ENODATA; - - return v4l2_subdev_call(bcap_dev->sd, video, - query_dv_timings, timings); -} - -static int bcap_g_dv_timings(struct file *file, void *priv, - struct v4l2_dv_timings *timings) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS)) - return -ENODATA; - - *timings = bcap_dev->dv_timings; - return 0; -} - -static int bcap_s_dv_timings(struct file *file, void *priv, - struct v4l2_dv_timings *timings) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_input input; - int ret; - - input = bcap_dev->cfg->inputs[bcap_dev->cur_input]; - if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS)) - return -ENODATA; - - if (vb2_is_busy(&bcap_dev->buffer_queue)) - return -EBUSY; - - ret = v4l2_subdev_call(bcap_dev->sd, video, s_dv_timings, timings); - if (ret < 0) - return ret; - - bcap_dev->dv_timings = *timings; - return 0; -} - -static int bcap_enum_input(struct file *file, void *priv, - struct v4l2_input *input) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct bfin_capture_config *config = bcap_dev->cfg; - int ret; - u32 status; - - if (input->index >= config->num_inputs) - return -EINVAL; - - *input = config->inputs[input->index]; - /* get input status */ - ret = v4l2_subdev_call(bcap_dev->sd, video, g_input_status, &status); - if (!ret) - input->status = status; - return 0; -} - -static int bcap_g_input(struct file *file, void *priv, unsigned int *index) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - *index = bcap_dev->cur_input; - return 0; -} - -static int bcap_s_input(struct file *file, void *priv, unsigned int index) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct bfin_capture_config *config = bcap_dev->cfg; - struct bcap_route *route; - int ret; - - if (vb2_is_busy(&bcap_dev->buffer_queue)) - return -EBUSY; - - if (index >= config->num_inputs) - return -EINVAL; - - route = &config->routes[index]; - ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, - route->input, route->output, 0); - if ((ret < 0) && (ret != -ENOIOCTLCMD)) { - v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); - return ret; - } - bcap_dev->cur_input = index; - /* if this route has specific config, update ppi control */ - if (route->ppi_control) - config->ppi_control = route->ppi_control; - return 0; -} - -static int bcap_try_format(struct bcap_device *bcap, - struct v4l2_pix_format *pixfmt, - struct bcap_format *bcap_fmt) -{ - struct bcap_format *sf = bcap->sensor_formats; - struct bcap_format *fmt = NULL; - struct v4l2_subdev_pad_config pad_cfg; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_TRY, - }; - int ret, i; - - for (i = 0; i < bcap->num_sensor_formats; i++) { - fmt = &sf[i]; - if (pixfmt->pixelformat == fmt->pixelformat) - break; - } - if (i == bcap->num_sensor_formats) - fmt = &sf[0]; - - v4l2_fill_mbus_format(&format.format, pixfmt, fmt->mbus_code); - ret = v4l2_subdev_call(bcap->sd, pad, set_fmt, &pad_cfg, - &format); - if (ret < 0) - return ret; - v4l2_fill_pix_format(pixfmt, &format.format); - if (bcap_fmt) { - for (i = 0; i < bcap->num_sensor_formats; i++) { - fmt = &sf[i]; - if (format.format.code == fmt->mbus_code) - break; - } - *bcap_fmt = *fmt; - } - pixfmt->bytesperline = pixfmt->width * fmt->bpp / 8; - pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; - return 0; -} - -static int bcap_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *fmt) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct bcap_format *sf = bcap_dev->sensor_formats; - - if (fmt->index >= bcap_dev->num_sensor_formats) - return -EINVAL; - - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strlcpy(fmt->description, - sf[fmt->index].desc, - sizeof(fmt->description)); - fmt->pixelformat = sf[fmt->index].pixelformat; - return 0; -} - -static int bcap_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - return bcap_try_format(bcap_dev, pixfmt, NULL); -} - -static int bcap_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - fmt->fmt.pix = bcap_dev->fmt; - return 0; -} - -static int bcap_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *fmt) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct bcap_format bcap_fmt; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - int ret; - - if (vb2_is_busy(&bcap_dev->buffer_queue)) - return -EBUSY; - - /* see if format works */ - ret = bcap_try_format(bcap_dev, pixfmt, &bcap_fmt); - if (ret < 0) - return ret; - - v4l2_fill_mbus_format(&format.format, pixfmt, bcap_fmt.mbus_code); - ret = v4l2_subdev_call(bcap_dev->sd, pad, set_fmt, NULL, &format); - if (ret < 0) - return ret; - bcap_dev->fmt = *pixfmt; - bcap_dev->bpp = bcap_fmt.bpp; - bcap_dev->dlen = bcap_fmt.dlen; - return 0; -} - -static int bcap_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, "Blackfin Platform", sizeof(cap->bus_info)); - strlcpy(cap->card, bcap_dev->cfg->card_name, sizeof(cap->card)); - return 0; -} - -static int bcap_g_parm(struct file *file, void *fh, - struct v4l2_streamparm *a) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return v4l2_subdev_call(bcap_dev->sd, video, g_parm, a); -} - -static int bcap_s_parm(struct file *file, void *fh, - struct v4l2_streamparm *a) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); -} - -static int bcap_log_status(struct file *file, void *priv) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - /* status for sub devices */ - v4l2_device_call_all(&bcap_dev->v4l2_dev, 0, core, log_status); - return 0; -} - -static const struct v4l2_ioctl_ops bcap_ioctl_ops = { - .vidioc_querycap = bcap_querycap, - .vidioc_g_fmt_vid_cap = bcap_g_fmt_vid_cap, - .vidioc_enum_fmt_vid_cap = bcap_enum_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = bcap_s_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = bcap_try_fmt_vid_cap, - .vidioc_enum_input = bcap_enum_input, - .vidioc_g_input = bcap_g_input, - .vidioc_s_input = bcap_s_input, - .vidioc_querystd = bcap_querystd, - .vidioc_s_std = bcap_s_std, - .vidioc_g_std = bcap_g_std, - .vidioc_s_dv_timings = bcap_s_dv_timings, - .vidioc_g_dv_timings = bcap_g_dv_timings, - .vidioc_query_dv_timings = bcap_query_dv_timings, - .vidioc_enum_dv_timings = bcap_enum_dv_timings, - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_expbuf = vb2_ioctl_expbuf, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - .vidioc_g_parm = bcap_g_parm, - .vidioc_s_parm = bcap_s_parm, - .vidioc_log_status = bcap_log_status, -}; - -static const struct v4l2_file_operations bcap_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .unlocked_ioctl = video_ioctl2, - .mmap = vb2_fop_mmap, -#ifndef CONFIG_MMU - .get_unmapped_area = vb2_fop_get_unmapped_area, -#endif - .poll = vb2_fop_poll -}; - -static int bcap_probe(struct platform_device *pdev) -{ - struct bcap_device *bcap_dev; - struct video_device *vfd; - struct i2c_adapter *i2c_adap; - struct bfin_capture_config *config; - struct vb2_queue *q; - struct bcap_route *route; - int ret; - - config = pdev->dev.platform_data; - if (!config || !config->num_inputs) { - v4l2_err(pdev->dev.driver, "Unable to get board config\n"); - return -ENODEV; - } - - bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL); - if (!bcap_dev) - return -ENOMEM; - - bcap_dev->cfg = config; - - bcap_dev->ppi = ppi_create_instance(pdev, config->ppi_info); - if (!bcap_dev->ppi) { - v4l2_err(pdev->dev.driver, "Unable to create ppi\n"); - ret = -ENODEV; - goto err_free_dev; - } - bcap_dev->ppi->priv = bcap_dev; - - vfd = &bcap_dev->video_dev; - /* initialize field of video device */ - vfd->release = video_device_release_empty; - vfd->fops = &bcap_fops; - vfd->ioctl_ops = &bcap_ioctl_ops; - vfd->tvnorms = 0; - vfd->v4l2_dev = &bcap_dev->v4l2_dev; - strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name)); - - ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev); - if (ret) { - v4l2_err(pdev->dev.driver, - "Unable to register v4l2 device\n"); - goto err_free_ppi; - } - v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n"); - - bcap_dev->v4l2_dev.ctrl_handler = &bcap_dev->ctrl_handler; - ret = v4l2_ctrl_handler_init(&bcap_dev->ctrl_handler, 0); - if (ret) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to init control handler\n"); - goto err_unreg_v4l2; - } - - spin_lock_init(&bcap_dev->lock); - /* initialize queue */ - q = &bcap_dev->buffer_queue; - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_DMABUF; - q->drv_priv = bcap_dev; - q->buf_struct_size = sizeof(struct bcap_buffer); - q->ops = &bcap_video_qops; - q->mem_ops = &vb2_dma_contig_memops; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &bcap_dev->mutex; - q->min_buffers_needed = 1; - q->dev = &pdev->dev; - - ret = vb2_queue_init(q); - if (ret) - goto err_free_handler; - - mutex_init(&bcap_dev->mutex); - init_completion(&bcap_dev->comp); - - /* init video dma queues */ - INIT_LIST_HEAD(&bcap_dev->dma_queue); - - vfd->lock = &bcap_dev->mutex; - vfd->queue = q; - - /* register video device */ - ret = video_register_device(&bcap_dev->video_dev, VFL_TYPE_GRABBER, -1); - if (ret) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to register video device\n"); - goto err_free_handler; - } - video_set_drvdata(&bcap_dev->video_dev, bcap_dev); - v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n", - video_device_node_name(vfd)); - - /* load up the subdevice */ - i2c_adap = i2c_get_adapter(config->i2c_adapter_id); - if (!i2c_adap) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to find i2c adapter\n"); - ret = -ENODEV; - goto err_unreg_vdev; - - } - bcap_dev->sd = v4l2_i2c_new_subdev_board(&bcap_dev->v4l2_dev, - i2c_adap, - &config->board_info, - NULL); - if (bcap_dev->sd) { - int i; - - /* update tvnorms from the sub devices */ - for (i = 0; i < config->num_inputs; i++) - vfd->tvnorms |= config->inputs[i].std; - } else { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to register sub device\n"); - ret = -ENODEV; - goto err_unreg_vdev; - } - - v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n"); - - /* - * explicitly set input, otherwise some boards - * may not work at the state as we expected - */ - route = &config->routes[0]; - ret = v4l2_subdev_call(bcap_dev->sd, video, s_routing, - route->input, route->output, 0); - if ((ret < 0) && (ret != -ENOIOCTLCMD)) { - v4l2_err(&bcap_dev->v4l2_dev, "Failed to set input\n"); - goto err_unreg_vdev; - } - bcap_dev->cur_input = 0; - /* if this route has specific config, update ppi control */ - if (route->ppi_control) - config->ppi_control = route->ppi_control; - - /* now we can probe the default state */ - if (config->inputs[0].capabilities & V4L2_IN_CAP_STD) { - v4l2_std_id std; - ret = v4l2_subdev_call(bcap_dev->sd, video, g_std, &std); - if (ret) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to get std\n"); - goto err_unreg_vdev; - } - bcap_dev->std = std; - } - if (config->inputs[0].capabilities & V4L2_IN_CAP_DV_TIMINGS) { - struct v4l2_dv_timings dv_timings; - ret = v4l2_subdev_call(bcap_dev->sd, video, - g_dv_timings, &dv_timings); - if (ret) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to get dv timings\n"); - goto err_unreg_vdev; - } - bcap_dev->dv_timings = dv_timings; - } - ret = bcap_init_sensor_formats(bcap_dev); - if (ret) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to create sensor formats table\n"); - goto err_unreg_vdev; - } - return 0; -err_unreg_vdev: - video_unregister_device(&bcap_dev->video_dev); -err_free_handler: - v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); -err_unreg_v4l2: - v4l2_device_unregister(&bcap_dev->v4l2_dev); -err_free_ppi: - ppi_delete_instance(bcap_dev->ppi); -err_free_dev: - kfree(bcap_dev); - return ret; -} - -static int bcap_remove(struct platform_device *pdev) -{ - struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); - struct bcap_device *bcap_dev = container_of(v4l2_dev, - struct bcap_device, v4l2_dev); - - bcap_free_sensor_formats(bcap_dev); - video_unregister_device(&bcap_dev->video_dev); - v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler); - v4l2_device_unregister(v4l2_dev); - ppi_delete_instance(bcap_dev->ppi); - kfree(bcap_dev); - return 0; -} - -static struct platform_driver bcap_driver = { - .driver = { - .name = CAPTURE_DRV_NAME, - }, - .probe = bcap_probe, - .remove = bcap_remove, -}; -module_platform_driver(bcap_driver); - -MODULE_DESCRIPTION("Analog Devices blackfin video capture driver"); -MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c deleted file mode 100644 index d3dc765c1609..000000000000 --- a/drivers/media/platform/blackfin/ppi.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * ppi.c Analog Devices Parallel Peripheral Interface driver - * - * Copyright (c) 2011 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> - -#include <asm/bfin_ppi.h> -#include <asm/blackfin.h> -#include <asm/cacheflush.h> -#include <asm/dma.h> -#include <asm/portmux.h> - -#include <media/blackfin/ppi.h> - -static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler); -static void ppi_detach_irq(struct ppi_if *ppi); -static int ppi_start(struct ppi_if *ppi); -static int ppi_stop(struct ppi_if *ppi); -static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params); -static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr); - -static const struct ppi_ops ppi_ops = { - .attach_irq = ppi_attach_irq, - .detach_irq = ppi_detach_irq, - .start = ppi_start, - .stop = ppi_stop, - .set_params = ppi_set_params, - .update_addr = ppi_update_addr, -}; - -static irqreturn_t ppi_irq_err(int irq, void *dev_id) -{ - struct ppi_if *ppi = dev_id; - const struct ppi_info *info = ppi->info; - - switch (info->type) { - case PPI_TYPE_PPI: - { - struct bfin_ppi_regs *reg = info->base; - unsigned short status; - - /* register on bf561 is cleared when read - * others are W1C - */ - status = bfin_read16(®->status); - if (status & 0x3000) - ppi->err = true; - bfin_write16(®->status, 0xff00); - break; - } - case PPI_TYPE_EPPI: - { - struct bfin_eppi_regs *reg = info->base; - unsigned short status; - - status = bfin_read16(®->status); - if (status & 0x2) - ppi->err = true; - bfin_write16(®->status, 0xffff); - break; - } - case PPI_TYPE_EPPI3: - { - struct bfin_eppi3_regs *reg = info->base; - unsigned long stat; - - stat = bfin_read32(®->stat); - if (stat & 0x2) - ppi->err = true; - bfin_write32(®->stat, 0xc0ff); - break; - } - default: - break; - } - - return IRQ_HANDLED; -} - -static int ppi_attach_irq(struct ppi_if *ppi, irq_handler_t handler) -{ - const struct ppi_info *info = ppi->info; - int ret; - - ret = request_dma(info->dma_ch, "PPI_DMA"); - - if (ret) { - pr_err("Unable to allocate DMA channel for PPI\n"); - return ret; - } - set_dma_callback(info->dma_ch, handler, ppi); - - if (ppi->err_int) { - ret = request_irq(info->irq_err, ppi_irq_err, 0, "PPI ERROR", ppi); - if (ret) { - pr_err("Unable to allocate IRQ for PPI\n"); - free_dma(info->dma_ch); - } - } - return ret; -} - -static void ppi_detach_irq(struct ppi_if *ppi) -{ - const struct ppi_info *info = ppi->info; - - if (ppi->err_int) - free_irq(info->irq_err, ppi); - free_dma(info->dma_ch); -} - -static int ppi_start(struct ppi_if *ppi) -{ - const struct ppi_info *info = ppi->info; - - /* enable DMA */ - enable_dma(info->dma_ch); - - /* enable PPI */ - ppi->ppi_control |= PORT_EN; - switch (info->type) { - case PPI_TYPE_PPI: - { - struct bfin_ppi_regs *reg = info->base; - bfin_write16(®->control, ppi->ppi_control); - break; - } - case PPI_TYPE_EPPI: - { - struct bfin_eppi_regs *reg = info->base; - bfin_write32(®->control, ppi->ppi_control); - break; - } - case PPI_TYPE_EPPI3: - { - struct bfin_eppi3_regs *reg = info->base; - bfin_write32(®->ctl, ppi->ppi_control); - break; - } - default: - return -EINVAL; - } - - SSYNC(); - return 0; -} - -static int ppi_stop(struct ppi_if *ppi) -{ - const struct ppi_info *info = ppi->info; - - /* disable PPI */ - ppi->ppi_control &= ~PORT_EN; - switch (info->type) { - case PPI_TYPE_PPI: - { - struct bfin_ppi_regs *reg = info->base; - bfin_write16(®->control, ppi->ppi_control); - break; - } - case PPI_TYPE_EPPI: - { - struct bfin_eppi_regs *reg = info->base; - bfin_write32(®->control, ppi->ppi_control); - break; - } - case PPI_TYPE_EPPI3: - { - struct bfin_eppi3_regs *reg = info->base; - bfin_write32(®->ctl, ppi->ppi_control); - break; - } - default: - return -EINVAL; - } - - /* disable DMA */ - clear_dma_irqstat(info->dma_ch); - disable_dma(info->dma_ch); - - SSYNC(); - return 0; -} - -static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) -{ - const struct ppi_info *info = ppi->info; - int dma32 = 0; - int dma_config, bytes_per_line; - int hcount, hdelay, samples_per_line; - -#ifdef CONFIG_PINCTRL - static const char * const pin_state[] = {"8bit", "16bit", "24bit"}; - struct pinctrl *pctrl; - struct pinctrl_state *pstate; - - if (params->dlen > 24 || params->dlen <= 0) - return -EINVAL; - pctrl = devm_pinctrl_get(ppi->dev); - if (IS_ERR(pctrl)) - return PTR_ERR(pctrl); - pstate = pinctrl_lookup_state(pctrl, - pin_state[(params->dlen + 7) / 8 - 1]); - if (pinctrl_select_state(pctrl, pstate)) - return -EINVAL; -#endif - - bytes_per_line = params->width * params->bpp / 8; - /* convert parameters unit from pixels to samples */ - hcount = params->width * params->bpp / params->dlen; - hdelay = params->hdelay * params->bpp / params->dlen; - samples_per_line = params->line * params->bpp / params->dlen; - if (params->int_mask == 0xFFFFFFFF) - ppi->err_int = false; - else - ppi->err_int = true; - - dma_config = (DMA_FLOW_STOP | RESTART | DMA2D | DI_EN_Y); - ppi->ppi_control = params->ppi_control & ~PORT_EN; - if (!(ppi->ppi_control & PORT_DIR)) - dma_config |= WNR; - switch (info->type) { - case PPI_TYPE_PPI: - { - struct bfin_ppi_regs *reg = info->base; - - if (params->ppi_control & DMA32) - dma32 = 1; - - bfin_write16(®->control, ppi->ppi_control); - bfin_write16(®->count, samples_per_line - 1); - bfin_write16(®->frame, params->frame); - break; - } - case PPI_TYPE_EPPI: - { - struct bfin_eppi_regs *reg = info->base; - - if ((params->ppi_control & PACK_EN) - || (params->ppi_control & 0x38000) > DLEN_16) - dma32 = 1; - - bfin_write32(®->control, ppi->ppi_control); - bfin_write16(®->line, samples_per_line); - bfin_write16(®->frame, params->frame); - bfin_write16(®->hdelay, hdelay); - bfin_write16(®->vdelay, params->vdelay); - bfin_write16(®->hcount, hcount); - bfin_write16(®->vcount, params->height); - break; - } - case PPI_TYPE_EPPI3: - { - struct bfin_eppi3_regs *reg = info->base; - - if ((params->ppi_control & PACK_EN) - || (params->ppi_control & 0x70000) > DLEN_16) - dma32 = 1; - - bfin_write32(®->ctl, ppi->ppi_control); - bfin_write32(®->line, samples_per_line); - bfin_write32(®->frame, params->frame); - bfin_write32(®->hdly, hdelay); - bfin_write32(®->vdly, params->vdelay); - bfin_write32(®->hcnt, hcount); - bfin_write32(®->vcnt, params->height); - if (params->int_mask) - bfin_write32(®->imsk, params->int_mask & 0xFF); - if (ppi->ppi_control & PORT_DIR) { - u32 hsync_width, vsync_width, vsync_period; - - hsync_width = params->hsync - * params->bpp / params->dlen; - vsync_width = params->vsync * samples_per_line; - vsync_period = samples_per_line * params->frame; - bfin_write32(®->fs1_wlhb, hsync_width); - bfin_write32(®->fs1_paspl, samples_per_line); - bfin_write32(®->fs2_wlvb, vsync_width); - bfin_write32(®->fs2_palpf, vsync_period); - } - break; - } - default: - return -EINVAL; - } - - if (dma32) { - dma_config |= WDSIZE_32 | PSIZE_32; - set_dma_x_count(info->dma_ch, bytes_per_line >> 2); - set_dma_x_modify(info->dma_ch, 4); - set_dma_y_modify(info->dma_ch, 4); - } else { - dma_config |= WDSIZE_16 | PSIZE_16; - set_dma_x_count(info->dma_ch, bytes_per_line >> 1); - set_dma_x_modify(info->dma_ch, 2); - set_dma_y_modify(info->dma_ch, 2); - } - set_dma_y_count(info->dma_ch, params->height); - set_dma_config(info->dma_ch, dma_config); - - SSYNC(); - return 0; -} - -static void ppi_update_addr(struct ppi_if *ppi, unsigned long addr) -{ - set_dma_start_addr(ppi->info->dma_ch, addr); -} - -struct ppi_if *ppi_create_instance(struct platform_device *pdev, - const struct ppi_info *info) -{ - struct ppi_if *ppi; - - if (!info || !info->pin_req) - return NULL; - -#ifndef CONFIG_PINCTRL - if (peripheral_request_list(info->pin_req, KBUILD_MODNAME)) { - dev_err(&pdev->dev, "request peripheral failed\n"); - return NULL; - } -#endif - - ppi = kzalloc(sizeof(*ppi), GFP_KERNEL); - if (!ppi) { - peripheral_free_list(info->pin_req); - return NULL; - } - ppi->ops = &ppi_ops; - ppi->info = info; - ppi->dev = &pdev->dev; - - pr_info("ppi probe success\n"); - return ppi; -} -EXPORT_SYMBOL(ppi_create_instance); - -void ppi_delete_instance(struct ppi_if *ppi) -{ - peripheral_free_list(ppi->info->pin_req); - kfree(ppi); -} -EXPORT_SYMBOL(ppi_delete_instance); - -MODULE_DESCRIPTION("Analog Devices PPI driver"); -MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig index a896d3c83a1c..d2c6617d468e 100644 --- a/drivers/media/rc/img-ir/Kconfig +++ b/drivers/media/rc/img-ir/Kconfig @@ -1,7 +1,7 @@ config IR_IMG tristate "ImgTec IR Decoder" depends on RC_CORE - depends on METAG || MIPS || COMPILE_TEST + depends on MIPS || COMPILE_TEST select IR_IMG_HW if !IR_IMG_RAW help Say Y or M here if you want to use the ImgTec infrared decoder diff --git a/drivers/misc/echo/echo.c b/drivers/misc/echo/echo.c index 9597e9523cac..8a5adc0d2e88 100644 --- a/drivers/misc/echo/echo.c +++ b/drivers/misc/echo/echo.c @@ -115,78 +115,6 @@ /* adapting coeffs using the traditional stochastic descent (N)LMS algorithm */ -#ifdef __bfin__ -static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) -{ - int i; - int offset1; - int offset2; - int factor; - int exp; - int16_t *phist; - int n; - - if (shift > 0) - factor = clean << shift; - else - factor = clean >> -shift; - - /* Update the FIR taps */ - - offset2 = ec->curr_pos; - offset1 = ec->taps - offset2; - phist = &ec->fir_state_bg.history[offset2]; - - /* st: and en: help us locate the assembler in echo.s */ - - /* asm("st:"); */ - n = ec->taps; - for (i = 0; i < n; i++) { - exp = *phist++ * factor; - ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15); - } - /* asm("en:"); */ - - /* Note the asm for the inner loop above generated by Blackfin gcc - 4.1.1 is pretty good (note even parallel instructions used): - - R0 = W [P0++] (X); - R0 *= R2; - R0 = R0 + R3 (NS) || - R1 = W [P1] (X) || - nop; - R0 >>>= 15; - R0 = R0 + R1; - W [P1++] = R0; - - A block based update algorithm would be much faster but the - above can't be improved on much. Every instruction saved in - the loop above is 2 MIPs/ch! The for loop above is where the - Blackfin spends most of it's time - about 17 MIPs/ch measured - with speedtest.c with 256 taps (32ms). Write-back and - Write-through cache gave about the same performance. - */ -} - -/* - IDEAS for further optimisation of lms_adapt_bg(): - - 1/ The rounding is quite costly. Could we keep as 32 bit coeffs - then make filter pluck the MS 16-bits of the coeffs when filtering? - However this would lower potential optimisation of filter, as I - think the dual-MAC architecture requires packed 16 bit coeffs. - - 2/ Block based update would be more efficient, as per comments above, - could use dual MAC architecture. - - 3/ Look for same sample Blackfin LMS code, see if we can get dual-MAC - packing. - - 4/ Execute the whole e/c in a block of say 20ms rather than sample - by sample. Processing a few samples every ms is inefficient. -*/ - -#else static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) { int i; @@ -215,7 +143,6 @@ static inline void lms_adapt_bg(struct oslec_state *ec, int clean, int shift) ec->fir_taps16[1][i] += (int16_t) ((exp + (1 << 14)) >> 15); } } -#endif static inline int top_bit(unsigned int bits) { diff --git a/drivers/misc/echo/fir.h b/drivers/misc/echo/fir.h index 7b9fabf1fea5..4e0f365f0577 100644 --- a/drivers/misc/echo/fir.h +++ b/drivers/misc/echo/fir.h @@ -27,14 +27,6 @@ #define _FIR_H_ /* - Blackfin NOTES & IDEAS: - - A simple dot product function is used to implement the filter. This performs - just one MAC/cycle which is inefficient but was easy to implement as a first - pass. The current Blackfin code also uses an unrolled form of the filter - history to avoid 0 length hardware loop issues. This is wasteful of - memory. - Ideas for improvement: 1/ Rewrite filter for dual MAC inner loop. The issue here is handling @@ -94,21 +86,13 @@ static inline const int16_t *fir16_create(struct fir16_state_t *fir, fir->taps = taps; fir->curr_pos = taps - 1; fir->coeffs = coeffs; -#if defined(__bfin__) - fir->history = kcalloc(2 * taps, sizeof(int16_t), GFP_KERNEL); -#else fir->history = kcalloc(taps, sizeof(int16_t), GFP_KERNEL); -#endif return fir->history; } static inline void fir16_flush(struct fir16_state_t *fir) { -#if defined(__bfin__) - memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t)); -#else memset(fir->history, 0, fir->taps * sizeof(int16_t)); -#endif } static inline void fir16_free(struct fir16_state_t *fir) @@ -116,42 +100,9 @@ static inline void fir16_free(struct fir16_state_t *fir) kfree(fir->history); } -#ifdef __bfin__ -static inline int32_t dot_asm(short *x, short *y, int len) -{ - int dot; - - len--; - - __asm__("I0 = %1;\n\t" - "I1 = %2;\n\t" - "A0 = 0;\n\t" - "R0.L = W[I0++] || R1.L = W[I1++];\n\t" - "LOOP dot%= LC0 = %3;\n\t" - "LOOP_BEGIN dot%=;\n\t" - "A0 += R0.L * R1.L (IS) || R0.L = W[I0++] || R1.L = W[I1++];\n\t" - "LOOP_END dot%=;\n\t" - "A0 += R0.L*R1.L (IS);\n\t" - "R0 = A0;\n\t" - "%0 = R0;\n\t" - : "=&d"(dot) - : "a"(x), "a"(y), "a"(len) - : "I0", "I1", "A1", "A0", "R0", "R1" - ); - - return dot; -} -#endif - static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample) { int32_t y; -#if defined(__bfin__) - fir->history[fir->curr_pos] = sample; - fir->history[fir->curr_pos + fir->taps] = sample; - y = dot_asm((int16_t *) fir->coeffs, &fir->history[fir->curr_pos], - fir->taps); -#else int i; int offset1; int offset2; @@ -165,7 +116,6 @@ static inline int16_t fir16(struct fir16_state_t *fir, int16_t sample) y += fir->coeffs[i] * fir->history[i - offset1]; for (; i >= 0; i--) y += fir->coeffs[i] * fir->history[i + offset2]; -#endif if (fir->curr_pos <= 0) fir->curr_pos = fir->taps; fir->curr_pos--; diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 620c2d90a646..b4fd5d48dd35 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -646,25 +646,6 @@ config MMC_VIA_SDMMC If unsure, say N. -config SDH_BFIN - tristate "Blackfin Secure Digital Host support" - depends on (BF54x && !BF544) || (BF51x && !BF512) - help - If you say yes here you will get support for the Blackfin on-chip - Secure Digital Host interface. This includes support for MMC and - SD cards. - - To compile this driver as a module, choose M here: the - module will be called bfin_sdh. - - If unsure, say N. - -config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND - bool "Blackfin EZkit Missing SDH_CMD Pull Up Resistor Workaround" - depends on SDH_BFIN - help - If you say yes here SD-Cards may work on the EZkit. - config MMC_CAVIUM_OCTEON tristate "Cavium OCTEON SD/MMC Card Interface support" depends on CAVIUM_OCTEON_SOC diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 84cd1388abc3..f563cc0b7f93 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -43,7 +43,6 @@ obj-$(CONFIG_MMC_SDHI_SYS_DMAC) += renesas_sdhi_sys_dmac.o obj-$(CONFIG_MMC_SDHI_INTERNAL_DMAC) += renesas_sdhi_internal_dmac.o obj-$(CONFIG_MMC_CB710) += cb710-mmc.o obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o -obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o octeon-mmc-objs := cavium.o cavium-octeon.o obj-$(CONFIG_MMC_CAVIUM_OCTEON) += octeon-mmc.o thunderx-mmc-objs := cavium.o cavium-thunderx.o diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c deleted file mode 100644 index 526231e38583..000000000000 --- a/drivers/mmc/host/bfin_sdh.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * bfin_sdh.c - Analog Devices Blackfin SDH Controller - * - * Copyright (C) 2007-2009 Analog Device Inc. - * - * Licensed under the GPL-2 or later. - */ - -#define DRIVER_NAME "bfin-sdh" - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> -#include <linux/mmc/host.h> -#include <linux/proc_fs.h> -#include <linux/gfp.h> - -#include <asm/cacheflush.h> -#include <asm/dma.h> -#include <asm/portmux.h> -#include <asm/bfin_sdh.h> - -#if defined(CONFIG_BF51x) || defined(__ADSPBF60x__) -#define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL -#define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL -#define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT -#define bfin_write_SDH_COMMAND bfin_write_RSI_COMMAND -#define bfin_write_SDH_DATA_TIMER bfin_write_RSI_DATA_TIMER -#define bfin_read_SDH_RESPONSE0 bfin_read_RSI_RESPONSE0 -#define bfin_read_SDH_RESPONSE1 bfin_read_RSI_RESPONSE1 -#define bfin_read_SDH_RESPONSE2 bfin_read_RSI_RESPONSE2 -#define bfin_read_SDH_RESPONSE3 bfin_read_RSI_RESPONSE3 -#define bfin_write_SDH_DATA_LGTH bfin_write_RSI_DATA_LGTH -#define bfin_read_SDH_DATA_CTL bfin_read_RSI_DATA_CTL -#define bfin_write_SDH_DATA_CTL bfin_write_RSI_DATA_CTL -#define bfin_read_SDH_DATA_CNT bfin_read_RSI_DATA_CNT -#define bfin_write_SDH_STATUS_CLR bfin_write_RSI_STATUS_CLR -#define bfin_read_SDH_E_STATUS bfin_read_RSI_E_STATUS -#define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS -#define bfin_read_SDH_STATUS bfin_read_RSI_STATUS -#define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 -#define bfin_write_SDH_E_MASK bfin_write_RSI_E_MASK -#define bfin_read_SDH_CFG bfin_read_RSI_CFG -#define bfin_write_SDH_CFG bfin_write_RSI_CFG -# if defined(__ADSPBF60x__) -# define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ -# define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ -# else -# define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL -# define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL -# endif -#endif - -struct sdh_host { - struct mmc_host *mmc; - spinlock_t lock; - struct resource *res; - void __iomem *base; - int irq; - int stat_irq; - int dma_ch; - int dma_dir; - struct dma_desc_array *sg_cpu; - dma_addr_t sg_dma; - int dma_len; - - unsigned long sclk; - unsigned int imask; - unsigned int power_mode; - unsigned int clk_div; - - struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; -}; - -static struct bfin_sd_host *get_sdh_data(struct platform_device *pdev) -{ - return pdev->dev.platform_data; -} - -static void sdh_stop_clock(struct sdh_host *host) -{ - bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() & ~CLK_E); - SSYNC(); -} - -static void sdh_enable_stat_irq(struct sdh_host *host, unsigned int mask) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->imask |= mask; - bfin_write_SDH_MASK0(mask); - SSYNC(); - spin_unlock_irqrestore(&host->lock, flags); -} - -static void sdh_disable_stat_irq(struct sdh_host *host, unsigned int mask) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->imask &= ~mask; - bfin_write_SDH_MASK0(host->imask); - SSYNC(); - spin_unlock_irqrestore(&host->lock, flags); -} - -static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) -{ - unsigned int length; - unsigned int data_ctl; - unsigned int dma_cfg; - unsigned int cycle_ns, timeout; - - dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags); - host->data = data; - data_ctl = 0; - dma_cfg = 0; - - length = data->blksz * data->blocks; - bfin_write_SDH_DATA_LGTH(length); - - if (data->flags & MMC_DATA_READ) - data_ctl |= DTX_DIR; - /* Only supports power-of-2 block size */ - if (data->blksz & (data->blksz - 1)) - return -EINVAL; -#ifndef RSI_BLKSZ - data_ctl |= ((ffs(data->blksz) - 1) << 4); -#else - bfin_write_SDH_BLK_SIZE(data->blksz); -#endif - - bfin_write_SDH_DATA_CTL(data_ctl); - /* the time of a host clock period in ns */ - cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1))); - timeout = data->timeout_ns / cycle_ns; - timeout += data->timeout_clks; - bfin_write_SDH_DATA_TIMER(timeout); - SSYNC(); - - if (data->flags & MMC_DATA_READ) { - host->dma_dir = DMA_FROM_DEVICE; - dma_cfg |= WNR; - } else - host->dma_dir = DMA_TO_DEVICE; - - sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); - host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN; -# ifdef RSI_BLKSZ - dma_cfg |= PSIZE_32 | NDSIZE_3; -# else - dma_cfg |= NDSIZE_5; -# endif - { - struct scatterlist *sg; - int i; - for_each_sg(data->sg, sg, host->dma_len, i) { - host->sg_cpu[i].start_addr = sg_dma_address(sg); - host->sg_cpu[i].cfg = dma_cfg; - host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; - host->sg_cpu[i].x_modify = 4; - dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " - "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", - i, host->sg_cpu[i].start_addr, - host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, - host->sg_cpu[i].x_modify); - } - } - flush_dcache_range((unsigned int)host->sg_cpu, - (unsigned int)host->sg_cpu + - host->dma_len * sizeof(struct dma_desc_array)); - /* Set the last descriptor to stop mode */ - host->sg_cpu[host->dma_len - 1].cfg &= ~(DMAFLOW | NDSIZE); - host->sg_cpu[host->dma_len - 1].cfg |= DI_EN; - - set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); - set_dma_x_count(host->dma_ch, 0); - set_dma_x_modify(host->dma_ch, 0); - SSYNC(); - set_dma_config(host->dma_ch, dma_cfg); -#elif defined(CONFIG_BF51x) - /* RSI DMA doesn't work in array mode */ - dma_cfg |= WDSIZE_32 | DMAEN; - set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); - set_dma_x_count(host->dma_ch, length / 4); - set_dma_x_modify(host->dma_ch, 4); - SSYNC(); - set_dma_config(host->dma_ch, dma_cfg); -#endif - bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); - - SSYNC(); - - dev_dbg(mmc_dev(host->mmc), "%s exit\n", __func__); - return 0; -} - -static void sdh_start_cmd(struct sdh_host *host, struct mmc_command *cmd) -{ - unsigned int sdh_cmd; - unsigned int stat_mask; - - dev_dbg(mmc_dev(host->mmc), "%s enter cmd: 0x%p\n", __func__, cmd); - WARN_ON(host->cmd != NULL); - host->cmd = cmd; - - sdh_cmd = 0; - stat_mask = 0; - - sdh_cmd |= cmd->opcode; - - if (cmd->flags & MMC_RSP_PRESENT) { - sdh_cmd |= CMD_RSP; - stat_mask |= CMD_RESP_END; - } else { - stat_mask |= CMD_SENT; - } - - if (cmd->flags & MMC_RSP_136) - sdh_cmd |= CMD_L_RSP; - - stat_mask |= CMD_CRC_FAIL | CMD_TIME_OUT; - - sdh_enable_stat_irq(host, stat_mask); - - bfin_write_SDH_ARGUMENT(cmd->arg); - bfin_write_SDH_COMMAND(sdh_cmd | CMD_E); - bfin_write_SDH_CLK_CTL(bfin_read_SDH_CLK_CTL() | CLK_E); - SSYNC(); -} - -static void sdh_finish_request(struct sdh_host *host, struct mmc_request *mrq) -{ - dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); - host->mrq = NULL; - host->cmd = NULL; - host->data = NULL; - mmc_request_done(host->mmc, mrq); -} - -static int sdh_cmd_done(struct sdh_host *host, unsigned int stat) -{ - struct mmc_command *cmd = host->cmd; - int ret = 0; - - dev_dbg(mmc_dev(host->mmc), "%s enter cmd: %p\n", __func__, cmd); - if (!cmd) - return 0; - - host->cmd = NULL; - - if (cmd->flags & MMC_RSP_PRESENT) { - cmd->resp[0] = bfin_read_SDH_RESPONSE0(); - if (cmd->flags & MMC_RSP_136) { - cmd->resp[1] = bfin_read_SDH_RESPONSE1(); - cmd->resp[2] = bfin_read_SDH_RESPONSE2(); - cmd->resp[3] = bfin_read_SDH_RESPONSE3(); - } - } - if (stat & CMD_TIME_OUT) - cmd->error = -ETIMEDOUT; - else if (stat & CMD_CRC_FAIL && cmd->flags & MMC_RSP_CRC) - cmd->error = -EILSEQ; - - sdh_disable_stat_irq(host, (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)); - - if (host->data && !cmd->error) { - if (host->data->flags & MMC_DATA_WRITE) { - ret = sdh_setup_data(host, host->data); - if (ret) - return 0; - } - - sdh_enable_stat_irq(host, DAT_END | RX_OVERRUN | TX_UNDERRUN | DAT_TIME_OUT); - } else - sdh_finish_request(host, host->mrq); - - return 1; -} - -static int sdh_data_done(struct sdh_host *host, unsigned int stat) -{ - struct mmc_data *data = host->data; - - dev_dbg(mmc_dev(host->mmc), "%s enter stat: 0x%x\n", __func__, stat); - if (!data) - return 0; - - disable_dma(host->dma_ch); - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - host->dma_dir); - - if (stat & DAT_TIME_OUT) - data->error = -ETIMEDOUT; - else if (stat & DAT_CRC_FAIL) - data->error = -EILSEQ; - else if (stat & (RX_OVERRUN | TX_UNDERRUN)) - data->error = -EIO; - - if (!data->error) - data->bytes_xfered = data->blocks * data->blksz; - else - data->bytes_xfered = 0; - - bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ - DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); - bfin_write_SDH_DATA_CTL(0); - SSYNC(); - - host->data = NULL; - if (host->mrq->stop) { - sdh_stop_clock(host); - sdh_start_cmd(host, host->mrq->stop); - } else { - sdh_finish_request(host, host->mrq); - } - - return 1; -} - -static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct sdh_host *host = mmc_priv(mmc); - int ret = 0; - - dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); - WARN_ON(host->mrq != NULL); - - spin_lock(&host->lock); - host->mrq = mrq; - host->data = mrq->data; - - if (mrq->data && mrq->data->flags & MMC_DATA_READ) { - ret = sdh_setup_data(host, mrq->data); - if (ret) - goto data_err; - } - - sdh_start_cmd(host, mrq->cmd); -data_err: - spin_unlock(&host->lock); -} - -static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct sdh_host *host; - u16 clk_ctl = 0; -#ifndef RSI_BLKSZ - u16 pwr_ctl = 0; -#endif - u16 cfg; - host = mmc_priv(mmc); - - spin_lock(&host->lock); - - cfg = bfin_read_SDH_CFG(); - cfg |= MWE; - switch (ios->bus_width) { - case MMC_BUS_WIDTH_4: -#ifndef RSI_BLKSZ - cfg &= ~PD_SDDAT3; -#endif - cfg |= PUP_SDDAT3; - /* Enable 4 bit SDIO */ - cfg |= SD4E; - clk_ctl |= WIDE_BUS_4; - break; - case MMC_BUS_WIDTH_8: -#ifndef RSI_BLKSZ - cfg &= ~PD_SDDAT3; -#endif - cfg |= PUP_SDDAT3; - /* Disable 4 bit SDIO */ - cfg &= ~SD4E; - clk_ctl |= BYTE_BUS_8; - break; - default: - cfg &= ~PUP_SDDAT3; - /* Disable 4 bit SDIO */ - cfg &= ~SD4E; - } - bfin_write_SDH_CFG(cfg); - - host->power_mode = ios->power_mode; -#ifndef RSI_BLKSZ - if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { - pwr_ctl |= ROD_CTL; -# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND - pwr_ctl |= SD_CMD_OD; -# endif - } - - if (ios->power_mode != MMC_POWER_OFF) - pwr_ctl |= PWR_ON; - else - pwr_ctl &= ~PWR_ON; - - bfin_write_SDH_PWR_CTL(pwr_ctl); -#else -# ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND - if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - cfg |= SD_CMD_OD; - else - cfg &= ~SD_CMD_OD; -# endif - - if (ios->power_mode != MMC_POWER_OFF) - cfg |= PWR_ON; - else - cfg &= ~PWR_ON; - - bfin_write_SDH_CFG(cfg); -#endif - SSYNC(); - - if (ios->power_mode == MMC_POWER_ON && ios->clock) { - unsigned char clk_div; - clk_div = (get_sclk() / ios->clock - 1) / 2; - clk_div = min_t(unsigned char, clk_div, 0xFF); - clk_ctl |= clk_div; - clk_ctl |= CLK_E; - host->clk_div = clk_div; - bfin_write_SDH_CLK_CTL(clk_ctl); - } else - sdh_stop_clock(host); - - /* set up sdh interrupt mask*/ - if (ios->power_mode == MMC_POWER_ON) - bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | - RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END | - CMD_TIME_OUT | CMD_CRC_FAIL); - else - bfin_write_SDH_MASK0(0); - SSYNC(); - - spin_unlock(&host->lock); - - dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", - host->clk_div, - host->clk_div ? get_sclk() / (2 * (host->clk_div + 1)) : 0, - ios->clock); -} - -static const struct mmc_host_ops sdh_ops = { - .request = sdh_request, - .set_ios = sdh_set_ios, -}; - -static irqreturn_t sdh_dma_irq(int irq, void *devid) -{ - struct sdh_host *host = devid; - - dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__, - get_dma_curr_irqstat(host->dma_ch)); - clear_dma_irqstat(host->dma_ch); - SSYNC(); - - return IRQ_HANDLED; -} - -static irqreturn_t sdh_stat_irq(int irq, void *devid) -{ - struct sdh_host *host = devid; - unsigned int status; - int handled = 0; - - dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); - - spin_lock(&host->lock); - - status = bfin_read_SDH_E_STATUS(); - if (status & SD_CARD_DET) { - mmc_detect_change(host->mmc, 0); - bfin_write_SDH_E_STATUS(SD_CARD_DET); - } - status = bfin_read_SDH_STATUS(); - if (status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT | CMD_CRC_FAIL)) { - handled |= sdh_cmd_done(host, status); - bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT | \ - CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT); - SSYNC(); - } - - status = bfin_read_SDH_STATUS(); - if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) - handled |= sdh_data_done(host, status); - - spin_unlock(&host->lock); - - dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); - - return IRQ_RETVAL(handled); -} - -static void sdh_reset(void) -{ -#if defined(CONFIG_BF54x) - /* Secure Digital Host shares DMA with Nand controller */ - bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); -#endif - - bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); - SSYNC(); - - /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and - * mmc stack will do the detection. - */ - bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); - SSYNC(); -} - -static int sdh_probe(struct platform_device *pdev) -{ - struct mmc_host *mmc; - struct sdh_host *host; - struct bfin_sd_host *drv_data = get_sdh_data(pdev); - int ret; - - if (!drv_data) { - dev_err(&pdev->dev, "missing platform driver data\n"); - ret = -EINVAL; - goto out; - } - - mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev); - if (!mmc) { - ret = -ENOMEM; - goto out; - } - - mmc->ops = &sdh_ops; -#if defined(CONFIG_BF51x) - mmc->max_segs = 1; -#else - mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array); -#endif -#ifdef RSI_BLKSZ - mmc->max_seg_size = -1; -#else - mmc->max_seg_size = 1 << 16; -#endif - mmc->max_blk_size = 1 << 11; - mmc->max_blk_count = 1 << 11; - mmc->max_req_size = PAGE_SIZE; - mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; - mmc->f_max = get_sclk(); - mmc->f_min = mmc->f_max >> 9; - mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; - host = mmc_priv(mmc); - host->mmc = mmc; - host->sclk = get_sclk(); - - spin_lock_init(&host->lock); - host->irq = drv_data->irq_int0; - host->dma_ch = drv_data->dma_chan; - - ret = request_dma(host->dma_ch, DRIVER_NAME "DMA"); - if (ret) { - dev_err(&pdev->dev, "unable to request DMA channel\n"); - goto out1; - } - - ret = set_dma_callback(host->dma_ch, sdh_dma_irq, host); - if (ret) { - dev_err(&pdev->dev, "unable to request DMA irq\n"); - goto out2; - } - - host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL); - if (host->sg_cpu == NULL) { - ret = -ENOMEM; - goto out2; - } - - platform_set_drvdata(pdev, mmc); - - ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); - if (ret) { - dev_err(&pdev->dev, "unable to request status irq\n"); - goto out3; - } - - ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME); - if (ret) { - dev_err(&pdev->dev, "unable to request peripheral pins\n"); - goto out4; - } - - sdh_reset(); - - mmc_add_host(mmc); - return 0; - -out4: - free_irq(host->irq, host); -out3: - mmc_remove_host(mmc); - dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); -out2: - free_dma(host->dma_ch); -out1: - mmc_free_host(mmc); - out: - return ret; -} - -static int sdh_remove(struct platform_device *pdev) -{ - struct mmc_host *mmc = platform_get_drvdata(pdev); - - if (mmc) { - struct sdh_host *host = mmc_priv(mmc); - - mmc_remove_host(mmc); - - sdh_stop_clock(host); - free_irq(host->irq, host); - free_dma(host->dma_ch); - dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); - - mmc_free_host(mmc); - } - - return 0; -} - -#ifdef CONFIG_PM -static int sdh_suspend(struct platform_device *dev, pm_message_t state) -{ - struct bfin_sd_host *drv_data = get_sdh_data(dev); - - peripheral_free_list(drv_data->pin_req); - - return 0; -} - -static int sdh_resume(struct platform_device *dev) -{ - struct bfin_sd_host *drv_data = get_sdh_data(dev); - int ret = 0; - - ret = peripheral_request_list(drv_data->pin_req, DRIVER_NAME); - if (ret) { - dev_err(&dev->dev, "unable to request peripheral pins\n"); - return ret; - } - - sdh_reset(); - return ret; -} -#else -# define sdh_suspend NULL -# define sdh_resume NULL -#endif - -static struct platform_driver sdh_driver = { - .probe = sdh_probe, - .remove = sdh_remove, - .suspend = sdh_suspend, - .resume = sdh_resume, - .driver = { - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(sdh_driver); - -MODULE_DESCRIPTION("Blackfin Secure Digital Host Driver"); -MODULE_AUTHOR("Cliff Cai, Roy Huang"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 04c3b747812c..91e67e375dd4 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_ARCNET) += arcnet/ obj-$(CONFIG_DEV_APPLETALK) += appletalk/ obj-$(CONFIG_CAIF) += caif/ obj-$(CONFIG_CAN) += can/ -obj-$(CONFIG_ETRAX_ETHERNET) += cris/ obj-$(CONFIG_NET_DSA) += dsa/ obj-$(CONFIG_ETHERNET) += ethernet/ obj-$(CONFIG_FDDI) += fddi/ diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index ac4ff394bc56..2cb75988b328 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -88,15 +88,6 @@ config CAN_AT91 This is a driver for the SoC CAN controller in Atmel's AT91SAM9263 and AT91SAM9X5 processors. -config CAN_BFIN - depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x - tristate "Analog Devices Blackfin on-chip CAN" - ---help--- - Driver for the Analog Devices Blackfin on-chip CAN controllers - - To compile this driver as a module, choose M here: the - module will be called bfin_can. - config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" depends on ARM || PPC diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 02b8ed794564..44922bf29b6a 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -19,7 +19,6 @@ obj-y += usb/ obj-y += softing/ obj-$(CONFIG_CAN_AT91) += at91_can.o -obj-$(CONFIG_CAN_BFIN) += bfin_can.o obj-$(CONFIG_CAN_CC770) += cc770/ obj-$(CONFIG_CAN_C_CAN) += c_can/ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c deleted file mode 100644 index 1deb8ff90a89..000000000000 --- a/drivers/net/can/bfin_can.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Blackfin On-Chip CAN Driver - * - * Copyright 2004-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/bitops.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/platform_device.h> - -#include <linux/can/dev.h> -#include <linux/can/error.h> - -#include <asm/portmux.h> - -#define DRV_NAME "bfin_can" -#define BFIN_CAN_TIMEOUT 100 -#define TX_ECHO_SKB_MAX 1 - -/* transmit and receive channels */ -#define TRANSMIT_CHL 24 -#define RECEIVE_STD_CHL 0 -#define RECEIVE_EXT_CHL 4 -#define RECEIVE_RTR_CHL 8 -#define RECEIVE_EXT_RTR_CHL 12 -#define MAX_CHL_NUMBER 32 - -/* All Blackfin system MMRs are padded to 32bits even if the register - * itself is only 16bits. So use a helper macro to streamline this - */ -#define __BFP(m) u16 m; u16 __pad_##m - -/* bfin can registers layout */ -struct bfin_can_mask_regs { - __BFP(aml); - __BFP(amh); -}; - -struct bfin_can_channel_regs { - /* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */ - u16 data[8]; - __BFP(dlc); - __BFP(tsv); - __BFP(id0); - __BFP(id1); -}; - -struct bfin_can_regs { - /* global control and status registers */ - __BFP(mc1); /* offset 0x00 */ - __BFP(md1); /* offset 0x04 */ - __BFP(trs1); /* offset 0x08 */ - __BFP(trr1); /* offset 0x0c */ - __BFP(ta1); /* offset 0x10 */ - __BFP(aa1); /* offset 0x14 */ - __BFP(rmp1); /* offset 0x18 */ - __BFP(rml1); /* offset 0x1c */ - __BFP(mbtif1); /* offset 0x20 */ - __BFP(mbrif1); /* offset 0x24 */ - __BFP(mbim1); /* offset 0x28 */ - __BFP(rfh1); /* offset 0x2c */ - __BFP(opss1); /* offset 0x30 */ - u32 __pad1[3]; - __BFP(mc2); /* offset 0x40 */ - __BFP(md2); /* offset 0x44 */ - __BFP(trs2); /* offset 0x48 */ - __BFP(trr2); /* offset 0x4c */ - __BFP(ta2); /* offset 0x50 */ - __BFP(aa2); /* offset 0x54 */ - __BFP(rmp2); /* offset 0x58 */ - __BFP(rml2); /* offset 0x5c */ - __BFP(mbtif2); /* offset 0x60 */ - __BFP(mbrif2); /* offset 0x64 */ - __BFP(mbim2); /* offset 0x68 */ - __BFP(rfh2); /* offset 0x6c */ - __BFP(opss2); /* offset 0x70 */ - u32 __pad2[3]; - __BFP(clock); /* offset 0x80 */ - __BFP(timing); /* offset 0x84 */ - __BFP(debug); /* offset 0x88 */ - __BFP(status); /* offset 0x8c */ - __BFP(cec); /* offset 0x90 */ - __BFP(gis); /* offset 0x94 */ - __BFP(gim); /* offset 0x98 */ - __BFP(gif); /* offset 0x9c */ - __BFP(control); /* offset 0xa0 */ - __BFP(intr); /* offset 0xa4 */ - __BFP(version); /* offset 0xa8 */ - __BFP(mbtd); /* offset 0xac */ - __BFP(ewr); /* offset 0xb0 */ - __BFP(esr); /* offset 0xb4 */ - u32 __pad3[2]; - __BFP(ucreg); /* offset 0xc0 */ - __BFP(uccnt); /* offset 0xc4 */ - __BFP(ucrc); /* offset 0xc8 */ - __BFP(uccnf); /* offset 0xcc */ - u32 __pad4[1]; - __BFP(version2); /* offset 0xd4 */ - u32 __pad5[10]; - - /* channel(mailbox) mask and message registers */ - struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */ - struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */ -}; - -#undef __BFP - -#define SRS 0x0001 /* Software Reset */ -#define SER 0x0008 /* Stuff Error */ -#define BOIM 0x0008 /* Enable Bus Off Interrupt */ -#define CCR 0x0080 /* CAN Configuration Mode Request */ -#define CCA 0x0080 /* Configuration Mode Acknowledge */ -#define SAM 0x0080 /* Sampling */ -#define AME 0x8000 /* Acceptance Mask Enable */ -#define RMLIM 0x0080 /* Enable RX Message Lost Interrupt */ -#define RMLIS 0x0080 /* RX Message Lost IRQ Status */ -#define RTR 0x4000 /* Remote Frame Transmission Request */ -#define BOIS 0x0008 /* Bus Off IRQ Status */ -#define IDE 0x2000 /* Identifier Extension */ -#define EPIS 0x0004 /* Error-Passive Mode IRQ Status */ -#define EPIM 0x0004 /* Enable Error-Passive Mode Interrupt */ -#define EWTIS 0x0001 /* TX Error Count IRQ Status */ -#define EWRIS 0x0002 /* RX Error Count IRQ Status */ -#define BEF 0x0040 /* Bit Error Flag */ -#define FER 0x0080 /* Form Error Flag */ -#define SMR 0x0020 /* Sleep Mode Request */ -#define SMACK 0x0008 /* Sleep Mode Acknowledge */ - -/* - * bfin can private data - */ -struct bfin_can_priv { - struct can_priv can; /* must be the first member */ - struct net_device *dev; - void __iomem *membase; - int rx_irq; - int tx_irq; - int err_irq; - unsigned short *pin_list; -}; - -/* - * bfin can timing parameters - */ -static const struct can_bittiming_const bfin_can_bittiming_const = { - .name = DRV_NAME, - .tseg1_min = 1, - .tseg1_max = 16, - .tseg2_min = 1, - .tseg2_max = 8, - .sjw_max = 4, - /* - * Although the BRP field can be set to any value, it is recommended - * that the value be greater than or equal to 4, as restrictions - * apply to the bit timing configuration when BRP is less than 4. - */ - .brp_min = 4, - .brp_max = 1024, - .brp_inc = 1, -}; - -static int bfin_can_set_bittiming(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - struct can_bittiming *bt = &priv->can.bittiming; - u16 clk, timing; - - clk = bt->brp - 1; - timing = ((bt->sjw - 1) << 8) | (bt->prop_seg + bt->phase_seg1 - 1) | - ((bt->phase_seg2 - 1) << 4); - - /* - * If the SAM bit is set, the input signal is oversampled three times - * at the SCLK rate. - */ - if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - timing |= SAM; - - writew(clk, ®->clock); - writew(timing, ®->timing); - - netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing); - - return 0; -} - -static void bfin_can_set_reset_mode(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - int timeout = BFIN_CAN_TIMEOUT; - int i; - - /* disable interrupts */ - writew(0, ®->mbim1); - writew(0, ®->mbim2); - writew(0, ®->gim); - - /* reset can and enter configuration mode */ - writew(SRS | CCR, ®->control); - writew(CCR, ®->control); - while (!(readw(®->control) & CCA)) { - udelay(10); - if (--timeout == 0) { - netdev_err(dev, "fail to enter configuration mode\n"); - BUG(); - } - } - - /* - * All mailbox configurations are marked as inactive - * by writing to CAN Mailbox Configuration Registers 1 and 2 - * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled - */ - writew(0, ®->mc1); - writew(0, ®->mc2); - - /* Set Mailbox Direction */ - writew(0xFFFF, ®->md1); /* mailbox 1-16 are RX */ - writew(0, ®->md2); /* mailbox 17-32 are TX */ - - /* RECEIVE_STD_CHL */ - for (i = 0; i < 2; i++) { - writew(0, ®->chl[RECEIVE_STD_CHL + i].id0); - writew(AME, ®->chl[RECEIVE_STD_CHL + i].id1); - writew(0, ®->chl[RECEIVE_STD_CHL + i].dlc); - writew(0x1FFF, ®->msk[RECEIVE_STD_CHL + i].amh); - writew(0xFFFF, ®->msk[RECEIVE_STD_CHL + i].aml); - } - - /* RECEIVE_EXT_CHL */ - for (i = 0; i < 2; i++) { - writew(0, ®->chl[RECEIVE_EXT_CHL + i].id0); - writew(AME | IDE, ®->chl[RECEIVE_EXT_CHL + i].id1); - writew(0, ®->chl[RECEIVE_EXT_CHL + i].dlc); - writew(0x1FFF, ®->msk[RECEIVE_EXT_CHL + i].amh); - writew(0xFFFF, ®->msk[RECEIVE_EXT_CHL + i].aml); - } - - writew(BIT(TRANSMIT_CHL - 16), ®->mc2); - writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), ®->mc1); - - priv->can.state = CAN_STATE_STOPPED; -} - -static void bfin_can_set_normal_mode(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - int timeout = BFIN_CAN_TIMEOUT; - - /* - * leave configuration mode - */ - writew(readw(®->control) & ~CCR, ®->control); - - while (readw(®->status) & CCA) { - udelay(10); - if (--timeout == 0) { - netdev_err(dev, "fail to leave configuration mode\n"); - BUG(); - } - } - - /* - * clear _All_ tx and rx interrupts - */ - writew(0xFFFF, ®->mbtif1); - writew(0xFFFF, ®->mbtif2); - writew(0xFFFF, ®->mbrif1); - writew(0xFFFF, ®->mbrif2); - - /* - * clear global interrupt status register - */ - writew(0x7FF, ®->gis); /* overwrites with '1' */ - - /* - * Initialize Interrupts - * - set bits in the mailbox interrupt mask register - * - global interrupt mask - */ - writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), ®->mbim1); - writew(BIT(TRANSMIT_CHL - 16), ®->mbim2); - - writew(EPIM | BOIM | RMLIM, ®->gim); -} - -static void bfin_can_start(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - - /* enter reset mode */ - if (priv->can.state != CAN_STATE_STOPPED) - bfin_can_set_reset_mode(dev); - - /* leave reset mode */ - bfin_can_set_normal_mode(dev); -} - -static int bfin_can_set_mode(struct net_device *dev, enum can_mode mode) -{ - switch (mode) { - case CAN_MODE_START: - bfin_can_start(dev); - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - break; - - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int bfin_can_get_berr_counter(const struct net_device *dev, - struct can_berr_counter *bec) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - - u16 cec = readw(®->cec); - - bec->txerr = cec >> 8; - bec->rxerr = cec; - - return 0; -} - -static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - struct can_frame *cf = (struct can_frame *)skb->data; - u8 dlc = cf->can_dlc; - canid_t id = cf->can_id; - u8 *data = cf->data; - u16 val; - int i; - - if (can_dropped_invalid_skb(dev, skb)) - return NETDEV_TX_OK; - - netif_stop_queue(dev); - - /* fill id */ - if (id & CAN_EFF_FLAG) { - writew(id, ®->chl[TRANSMIT_CHL].id0); - val = ((id & 0x1FFF0000) >> 16) | IDE; - } else - val = (id << 2); - if (id & CAN_RTR_FLAG) - val |= RTR; - writew(val | AME, ®->chl[TRANSMIT_CHL].id1); - - /* fill payload */ - for (i = 0; i < 8; i += 2) { - val = ((7 - i) < dlc ? (data[7 - i]) : 0) + - ((6 - i) < dlc ? (data[6 - i] << 8) : 0); - writew(val, ®->chl[TRANSMIT_CHL].data[i]); - } - - /* fill data length code */ - writew(dlc, ®->chl[TRANSMIT_CHL].dlc); - - can_put_echo_skb(skb, dev, 0); - - /* set transmit request */ - writew(BIT(TRANSMIT_CHL - 16), ®->trs2); - - return 0; -} - -static void bfin_can_rx(struct net_device *dev, u16 isrc) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; - struct bfin_can_regs __iomem *reg = priv->membase; - struct can_frame *cf; - struct sk_buff *skb; - int obj; - int i; - u16 val; - - skb = alloc_can_skb(dev, &cf); - if (skb == NULL) - return; - - /* get id */ - if (isrc & BIT(RECEIVE_EXT_CHL)) { - /* extended frame format (EFF) */ - cf->can_id = ((readw(®->chl[RECEIVE_EXT_CHL].id1) - & 0x1FFF) << 16) - + readw(®->chl[RECEIVE_EXT_CHL].id0); - cf->can_id |= CAN_EFF_FLAG; - obj = RECEIVE_EXT_CHL; - } else { - /* standard frame format (SFF) */ - cf->can_id = (readw(®->chl[RECEIVE_STD_CHL].id1) - & 0x1ffc) >> 2; - obj = RECEIVE_STD_CHL; - } - if (readw(®->chl[obj].id1) & RTR) - cf->can_id |= CAN_RTR_FLAG; - - /* get data length code */ - cf->can_dlc = get_can_dlc(readw(®->chl[obj].dlc) & 0xF); - - /* get payload */ - for (i = 0; i < 8; i += 2) { - val = readw(®->chl[obj].data[i]); - cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0; - cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0; - } - - stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; - netif_rx(skb); -} - -static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - struct net_device_stats *stats = &dev->stats; - struct can_frame *cf; - struct sk_buff *skb; - enum can_state state = priv->can.state; - - skb = alloc_can_err_skb(dev, &cf); - if (skb == NULL) - return -ENOMEM; - - if (isrc & RMLIS) { - /* data overrun interrupt */ - netdev_dbg(dev, "data overrun interrupt\n"); - cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; - stats->rx_over_errors++; - stats->rx_errors++; - } - - if (isrc & BOIS) { - netdev_dbg(dev, "bus-off mode interrupt\n"); - state = CAN_STATE_BUS_OFF; - cf->can_id |= CAN_ERR_BUSOFF; - priv->can.can_stats.bus_off++; - can_bus_off(dev); - } - - if (isrc & EPIS) { - /* error passive interrupt */ - netdev_dbg(dev, "error passive interrupt\n"); - state = CAN_STATE_ERROR_PASSIVE; - } - - if ((isrc & EWTIS) || (isrc & EWRIS)) { - netdev_dbg(dev, "Error Warning Transmit/Receive Interrupt\n"); - state = CAN_STATE_ERROR_WARNING; - } - - if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || - state == CAN_STATE_ERROR_PASSIVE)) { - u16 cec = readw(®->cec); - u8 rxerr = cec; - u8 txerr = cec >> 8; - - cf->can_id |= CAN_ERR_CRTL; - if (state == CAN_STATE_ERROR_WARNING) { - priv->can.can_stats.error_warning++; - cf->data[1] = (txerr > rxerr) ? - CAN_ERR_CRTL_TX_WARNING : - CAN_ERR_CRTL_RX_WARNING; - } else { - priv->can.can_stats.error_passive++; - cf->data[1] = (txerr > rxerr) ? - CAN_ERR_CRTL_TX_PASSIVE : - CAN_ERR_CRTL_RX_PASSIVE; - } - } - - if (status) { - priv->can.can_stats.bus_error++; - - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - - if (status & BEF) - cf->data[2] |= CAN_ERR_PROT_BIT; - else if (status & FER) - cf->data[2] |= CAN_ERR_PROT_FORM; - else if (status & SER) - cf->data[2] |= CAN_ERR_PROT_STUFF; - } - - priv->can.state = state; - - stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; - netif_rx(skb); - - return 0; -} - -static irqreturn_t bfin_can_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - struct net_device_stats *stats = &dev->stats; - u16 status, isrc; - - if ((irq == priv->tx_irq) && readw(®->mbtif2)) { - /* transmission complete interrupt */ - writew(0xFFFF, ®->mbtif2); - stats->tx_packets++; - stats->tx_bytes += readw(®->chl[TRANSMIT_CHL].dlc); - can_get_echo_skb(dev, 0); - netif_wake_queue(dev); - } else if ((irq == priv->rx_irq) && readw(®->mbrif1)) { - /* receive interrupt */ - isrc = readw(®->mbrif1); - writew(0xFFFF, ®->mbrif1); - bfin_can_rx(dev, isrc); - } else if ((irq == priv->err_irq) && readw(®->gis)) { - /* error interrupt */ - isrc = readw(®->gis); - status = readw(®->esr); - writew(0x7FF, ®->gis); - bfin_can_err(dev, isrc, status); - } else { - return IRQ_NONE; - } - - return IRQ_HANDLED; -} - -static int bfin_can_open(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - int err; - - /* set chip into reset mode */ - bfin_can_set_reset_mode(dev); - - /* common open */ - err = open_candev(dev); - if (err) - goto exit_open; - - /* register interrupt handler */ - err = request_irq(priv->rx_irq, &bfin_can_interrupt, 0, - "bfin-can-rx", dev); - if (err) - goto exit_rx_irq; - err = request_irq(priv->tx_irq, &bfin_can_interrupt, 0, - "bfin-can-tx", dev); - if (err) - goto exit_tx_irq; - err = request_irq(priv->err_irq, &bfin_can_interrupt, 0, - "bfin-can-err", dev); - if (err) - goto exit_err_irq; - - bfin_can_start(dev); - - netif_start_queue(dev); - - return 0; - -exit_err_irq: - free_irq(priv->tx_irq, dev); -exit_tx_irq: - free_irq(priv->rx_irq, dev); -exit_rx_irq: - close_candev(dev); -exit_open: - return err; -} - -static int bfin_can_close(struct net_device *dev) -{ - struct bfin_can_priv *priv = netdev_priv(dev); - - netif_stop_queue(dev); - bfin_can_set_reset_mode(dev); - - close_candev(dev); - - free_irq(priv->rx_irq, dev); - free_irq(priv->tx_irq, dev); - free_irq(priv->err_irq, dev); - - return 0; -} - -static struct net_device *alloc_bfin_candev(void) -{ - struct net_device *dev; - struct bfin_can_priv *priv; - - dev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX); - if (!dev) - return NULL; - - priv = netdev_priv(dev); - - priv->dev = dev; - priv->can.bittiming_const = &bfin_can_bittiming_const; - priv->can.do_set_bittiming = bfin_can_set_bittiming; - priv->can.do_set_mode = bfin_can_set_mode; - priv->can.do_get_berr_counter = bfin_can_get_berr_counter; - priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; - - return dev; -} - -static const struct net_device_ops bfin_can_netdev_ops = { - .ndo_open = bfin_can_open, - .ndo_stop = bfin_can_close, - .ndo_start_xmit = bfin_can_start_xmit, - .ndo_change_mtu = can_change_mtu, -}; - -static int bfin_can_probe(struct platform_device *pdev) -{ - int err; - struct net_device *dev; - struct bfin_can_priv *priv; - struct resource *res_mem, *rx_irq, *tx_irq, *err_irq; - unsigned short *pdata; - - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "No platform data provided!\n"); - err = -EINVAL; - goto exit; - } - - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - tx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - err_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 2); - if (!res_mem || !rx_irq || !tx_irq || !err_irq) { - err = -EINVAL; - goto exit; - } - - /* request peripheral pins */ - err = peripheral_request_list(pdata, dev_name(&pdev->dev)); - if (err) - goto exit; - - dev = alloc_bfin_candev(); - if (!dev) { - err = -ENOMEM; - goto exit_peri_pin_free; - } - - priv = netdev_priv(dev); - - priv->membase = devm_ioremap_resource(&pdev->dev, res_mem); - if (IS_ERR(priv->membase)) { - err = PTR_ERR(priv->membase); - goto exit_peri_pin_free; - } - - priv->rx_irq = rx_irq->start; - priv->tx_irq = tx_irq->start; - priv->err_irq = err_irq->start; - priv->pin_list = pdata; - priv->can.clock.freq = get_sclk(); - - platform_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - dev->flags |= IFF_ECHO; /* we support local echo */ - dev->netdev_ops = &bfin_can_netdev_ops; - - bfin_can_set_reset_mode(dev); - - err = register_candev(dev); - if (err) { - dev_err(&pdev->dev, "registering failed (err=%d)\n", err); - goto exit_candev_free; - } - - dev_info(&pdev->dev, - "%s device registered" - "(®_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n", - DRV_NAME, priv->membase, priv->rx_irq, - priv->tx_irq, priv->err_irq, priv->can.clock.freq); - return 0; - -exit_candev_free: - free_candev(dev); -exit_peri_pin_free: - peripheral_free_list(pdata); -exit: - return err; -} - -static int bfin_can_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct bfin_can_priv *priv = netdev_priv(dev); - - bfin_can_set_reset_mode(dev); - - unregister_candev(dev); - - peripheral_free_list(priv->pin_list); - - free_candev(dev); - return 0; -} - -#ifdef CONFIG_PM -static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - int timeout = BFIN_CAN_TIMEOUT; - - if (netif_running(dev)) { - /* enter sleep mode */ - writew(readw(®->control) | SMR, ®->control); - while (!(readw(®->intr) & SMACK)) { - udelay(10); - if (--timeout == 0) { - netdev_err(dev, "fail to enter sleep mode\n"); - BUG(); - } - } - } - - return 0; -} - -static int bfin_can_resume(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct bfin_can_priv *priv = netdev_priv(dev); - struct bfin_can_regs __iomem *reg = priv->membase; - - if (netif_running(dev)) { - /* leave sleep mode */ - writew(0, ®->intr); - } - - return 0; -} -#else -#define bfin_can_suspend NULL -#define bfin_can_resume NULL -#endif /* CONFIG_PM */ - -static struct platform_driver bfin_can_driver = { - .probe = bfin_can_probe, - .remove = bfin_can_remove, - .suspend = bfin_can_suspend, - .resume = bfin_can_resume, - .driver = { - .name = DRV_NAME, - }, -}; - -module_platform_driver(bfin_can_driver); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/net/cris/Makefile b/drivers/net/cris/Makefile deleted file mode 100644 index b4e8932227b6..000000000000 --- a/drivers/net/cris/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ETRAX_ARCH_V10) += eth_v10.o diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c deleted file mode 100644 index 8b1a859f5140..000000000000 --- a/drivers/net/cris/eth_v10.c +++ /dev/null @@ -1,1742 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * e100net.c: A network driver for the ETRAX 100LX network controller. - * - * Copyright (c) 1998-2002 Axis Communications AB. - * - * The outline of this driver comes from skeleton.c. - * - */ - -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/ptrace.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/string.h> -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/bitops.h> - -#include <linux/if.h> -#include <linux/mii.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/ethtool.h> - -#include <arch/svinto.h>/* DMA and register descriptions */ -#include <asm/io.h> /* CRIS_LED_* I/O functions */ -#include <asm/irq.h> -#include <asm/dma.h> -#include <asm/ethernet.h> -#include <asm/cache.h> -#include <arch/io_interface_mux.h> - -//#define ETHDEBUG -#define D(x) - -/* - * The name of the card. Is used for messages and in the requests for - * io regions, irqs and dma channels - */ - -static const char* cardname = "ETRAX 100LX built-in ethernet controller"; - -/* A default ethernet address. Highlevel SW will set the real one later */ - -static struct sockaddr default_mac = { - 0, - { 0x00, 0x40, 0x8C, 0xCD, 0x00, 0x00 } -}; - -/* Information that need to be kept for each board. */ -struct net_local { - struct mii_if_info mii_if; - - /* Tx control lock. This protects the transmit buffer ring - * state along with the "tx full" state of the driver. This - * means all netif_queue flow control actions are protected - * by this lock as well. - */ - spinlock_t lock; - - spinlock_t led_lock; /* Protect LED state */ - spinlock_t transceiver_lock; /* Protect transceiver state. */ -}; - -typedef struct etrax_eth_descr -{ - etrax_dma_descr descr; - struct sk_buff* skb; -} etrax_eth_descr; - -/* Some transceivers requires special handling */ -struct transceiver_ops -{ - unsigned int oui; - void (*check_speed)(struct net_device* dev); - void (*check_duplex)(struct net_device* dev); -}; - -/* Duplex settings */ -enum duplex -{ - half, - full, - autoneg -}; - -/* Dma descriptors etc. */ - -#define MAX_MEDIA_DATA_SIZE 1522 - -#define MIN_PACKET_LEN 46 -#define ETHER_HEAD_LEN 14 - -/* -** MDIO constants. -*/ -#define MDIO_START 0x1 -#define MDIO_READ 0x2 -#define MDIO_WRITE 0x1 -#define MDIO_PREAMBLE 0xfffffffful - -/* Broadcom specific */ -#define MDIO_AUX_CTRL_STATUS_REG 0x18 -#define MDIO_BC_FULL_DUPLEX_IND 0x1 -#define MDIO_BC_SPEED 0x2 - -/* TDK specific */ -#define MDIO_TDK_DIAGNOSTIC_REG 18 -#define MDIO_TDK_DIAGNOSTIC_RATE 0x400 -#define MDIO_TDK_DIAGNOSTIC_DPLX 0x800 - -/*Intel LXT972A specific*/ -#define MDIO_INT_STATUS_REG_2 0x0011 -#define MDIO_INT_FULL_DUPLEX_IND (1 << 9) -#define MDIO_INT_SPEED (1 << 14) - -/* Network flash constants */ -#define NET_FLASH_TIME (HZ/50) /* 20 ms */ -#define NET_FLASH_PAUSE (HZ/100) /* 10 ms */ -#define NET_LINK_UP_CHECK_INTERVAL (2*HZ) /* 2 s */ -#define NET_DUPLEX_CHECK_INTERVAL (2*HZ) /* 2 s */ - -#define NO_NETWORK_ACTIVITY 0 -#define NETWORK_ACTIVITY 1 - -#define NBR_OF_RX_DESC 32 -#define NBR_OF_TX_DESC 16 - -/* Large packets are sent directly to upper layers while small packets are */ -/* copied (to reduce memory waste). The following constant decides the breakpoint */ -#define RX_COPYBREAK 256 - -/* Due to a chip bug we need to flush the cache when descriptors are returned */ -/* to the DMA. To decrease performance impact we return descriptors in chunks. */ -/* The following constant determines the number of descriptors to return. */ -#define RX_QUEUE_THRESHOLD NBR_OF_RX_DESC/2 - -#define GET_BIT(bit,val) (((val) >> (bit)) & 0x01) - -/* Define some macros to access ETRAX 100 registers */ -#define SETF(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_FIELD_(reg##_, field##_, val) -#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val) - -static etrax_eth_descr *myNextRxDesc; /* Points to the next descriptor to - to be processed */ -static etrax_eth_descr *myLastRxDesc; /* The last processed descriptor */ - -static etrax_eth_descr RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned(32))); - -static etrax_eth_descr* myFirstTxDesc; /* First packet not yet sent */ -static etrax_eth_descr* myLastTxDesc; /* End of send queue */ -static etrax_eth_descr* myNextTxDesc; /* Next descriptor to use */ -static etrax_eth_descr TxDescList[NBR_OF_TX_DESC] __attribute__ ((aligned(32))); - -static unsigned int network_rec_config_shadow = 0; - -static unsigned int network_tr_ctrl_shadow = 0; - -/* Timers */ -static void e100_check_speed(struct timer_list *unused); -static void e100_clear_network_leds(struct timer_list *unused); -static void e100_check_duplex(struct timer_list *unused); -static DEFINE_TIMER(speed_timer, e100_check_speed); -static DEFINE_TIMER(clear_led_timer, e100_clear_network_leds); -static DEFINE_TIMER(duplex_timer, e100_check_duplex); -static struct net_device *timer_dev; - -/* Network speed indication. */ -static int current_speed; /* Speed read from transceiver */ -static int current_speed_selection; /* Speed selected by user */ -static unsigned long led_next_time; -static int led_active; -static int rx_queue_len; - -/* Duplex */ -static int full_duplex; -static enum duplex current_duplex; - -/* Index to functions, as function prototypes. */ - -static int etrax_ethernet_init(void); - -static int e100_open(struct net_device *dev); -static int e100_set_mac_address(struct net_device *dev, void *addr); -static int e100_send_packet(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t e100rxtx_interrupt(int irq, void *dev_id); -static irqreturn_t e100nw_interrupt(int irq, void *dev_id); -static void e100_rx(struct net_device *dev); -static int e100_close(struct net_device *dev); -static int e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int e100_set_config(struct net_device* dev, struct ifmap* map); -static void e100_tx_timeout(struct net_device *dev); -static struct net_device_stats *e100_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void e100_hardware_send_packet(struct net_local* np, char *buf, int length); -static void update_rx_stats(struct net_device_stats *); -static void update_tx_stats(struct net_device_stats *); -static int e100_probe_transceiver(struct net_device* dev); - -static void e100_set_speed(struct net_device* dev, unsigned long speed); -static void e100_set_duplex(struct net_device* dev, enum duplex); -static void e100_negotiate(struct net_device* dev); - -static int e100_get_mdio_reg(struct net_device *dev, int phy_id, int location); -static void e100_set_mdio_reg(struct net_device *dev, int phy_id, int location, int value); - -static void e100_send_mdio_cmd(unsigned short cmd, int write_cmd); -static void e100_send_mdio_bit(unsigned char bit); -static unsigned char e100_receive_mdio_bit(void); -static void e100_reset_transceiver(struct net_device* net); - -static void e100_set_network_leds(int active); - -static const struct ethtool_ops e100_ethtool_ops; -#if defined(CONFIG_ETRAX_NO_PHY) -static void dummy_check_speed(struct net_device* dev); -static void dummy_check_duplex(struct net_device* dev); -#else -static void broadcom_check_speed(struct net_device* dev); -static void broadcom_check_duplex(struct net_device* dev); -static void tdk_check_speed(struct net_device* dev); -static void tdk_check_duplex(struct net_device* dev); -static void intel_check_speed(struct net_device* dev); -static void intel_check_duplex(struct net_device* dev); -static void generic_check_speed(struct net_device* dev); -static void generic_check_duplex(struct net_device* dev); -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER -static void e100_netpoll(struct net_device* dev); -#endif - -static int autoneg_normal = 1; - -struct transceiver_ops transceivers[] = -{ -#if defined(CONFIG_ETRAX_NO_PHY) - {0x0000, dummy_check_speed, dummy_check_duplex} /* Dummy */ -#else - {0x1018, broadcom_check_speed, broadcom_check_duplex}, /* Broadcom */ - {0xC039, tdk_check_speed, tdk_check_duplex}, /* TDK 2120 */ - {0x039C, tdk_check_speed, tdk_check_duplex}, /* TDK 2120C */ - {0x04de, intel_check_speed, intel_check_duplex}, /* Intel LXT972A*/ - {0x0000, generic_check_speed, generic_check_duplex} /* Generic, must be last */ -#endif -}; - -struct transceiver_ops* transceiver = &transceivers[0]; - -static const struct net_device_ops e100_netdev_ops = { - .ndo_open = e100_open, - .ndo_stop = e100_close, - .ndo_start_xmit = e100_send_packet, - .ndo_tx_timeout = e100_tx_timeout, - .ndo_get_stats = e100_get_stats, - .ndo_set_rx_mode = set_multicast_list, - .ndo_do_ioctl = e100_ioctl, - .ndo_set_mac_address = e100_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_config = e100_set_config, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e100_netpoll, -#endif -}; - -#define tx_done(dev) (*R_DMA_CH0_CMD == 0) - -/* - * Check for a network adaptor of this type, and return '0' if one exists. - * If dev->base_addr == 0, probe all likely locations. - * If dev->base_addr == 1, always return failure. - * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). - */ - -static int __init -etrax_ethernet_init(void) -{ - struct net_device *dev; - struct net_local* np; - int i, err; - - printk(KERN_INFO - "ETRAX 100LX 10/100MBit ethernet v2.0 (c) 1998-2007 Axis Communications AB\n"); - - if (cris_request_io_interface(if_eth, cardname)) { - printk(KERN_CRIT "etrax_ethernet_init failed to get IO interface\n"); - return -EBUSY; - } - - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) - return -ENOMEM; - - np = netdev_priv(dev); - - /* we do our own locking */ - dev->features |= NETIF_F_LLTX; - - dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */ - - /* now setup our etrax specific stuff */ - - dev->irq = NETWORK_DMA_RX_IRQ_NBR; /* we really use DMATX as well... */ - dev->dma = NETWORK_RX_DMA_NBR; - - /* fill in our handlers so the network layer can talk to us in the future */ - - dev->ethtool_ops = &e100_ethtool_ops; - dev->netdev_ops = &e100_netdev_ops; - - spin_lock_init(&np->lock); - spin_lock_init(&np->led_lock); - spin_lock_init(&np->transceiver_lock); - - /* Initialise the list of Etrax DMA-descriptors */ - - /* Initialise receive descriptors */ - - for (i = 0; i < NBR_OF_RX_DESC; i++) { - /* Allocate two extra cachelines to make sure that buffer used - * by DMA does not share cacheline with any other data (to - * avoid cache bug) - */ - RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); - if (!RxDescList[i].skb) - return -ENOMEM; - RxDescList[i].descr.ctrl = 0; - RxDescList[i].descr.sw_len = MAX_MEDIA_DATA_SIZE; - RxDescList[i].descr.next = virt_to_phys(&RxDescList[i + 1]); - RxDescList[i].descr.buf = L1_CACHE_ALIGN(virt_to_phys(RxDescList[i].skb->data)); - RxDescList[i].descr.status = 0; - RxDescList[i].descr.hw_len = 0; - prepare_rx_descriptor(&RxDescList[i].descr); - } - - RxDescList[NBR_OF_RX_DESC - 1].descr.ctrl = d_eol; - RxDescList[NBR_OF_RX_DESC - 1].descr.next = virt_to_phys(&RxDescList[0]); - rx_queue_len = 0; - - /* Initialize transmit descriptors */ - for (i = 0; i < NBR_OF_TX_DESC; i++) { - TxDescList[i].descr.ctrl = 0; - TxDescList[i].descr.sw_len = 0; - TxDescList[i].descr.next = virt_to_phys(&TxDescList[i + 1].descr); - TxDescList[i].descr.buf = 0; - TxDescList[i].descr.status = 0; - TxDescList[i].descr.hw_len = 0; - TxDescList[i].skb = 0; - } - - TxDescList[NBR_OF_TX_DESC - 1].descr.ctrl = d_eol; - TxDescList[NBR_OF_TX_DESC - 1].descr.next = virt_to_phys(&TxDescList[0].descr); - - /* Initialise initial pointers */ - - myNextRxDesc = &RxDescList[0]; - myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; - myFirstTxDesc = &TxDescList[0]; - myNextTxDesc = &TxDescList[0]; - myLastTxDesc = &TxDescList[NBR_OF_TX_DESC - 1]; - - /* Register device */ - err = register_netdev(dev); - if (err) { - free_netdev(dev); - return err; - } - - /* set the default MAC address */ - - e100_set_mac_address(dev, &default_mac); - - /* Initialize speed indicator stuff. */ - - current_speed = 10; - current_speed_selection = 0; /* Auto */ - speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; - - full_duplex = 0; - current_duplex = autoneg; - duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL; - - timer_dev = dev; - - /* Initialize mii interface */ - np->mii_if.phy_id_mask = 0x1f; - np->mii_if.reg_num_mask = 0x1f; - np->mii_if.dev = dev; - np->mii_if.mdio_read = e100_get_mdio_reg; - np->mii_if.mdio_write = e100_set_mdio_reg; - - /* Initialize group address registers to make sure that no */ - /* unwanted addresses are matched */ - *R_NETWORK_GA_0 = 0x00000000; - *R_NETWORK_GA_1 = 0x00000000; - - /* Initialize next time the led can flash */ - led_next_time = jiffies; - return 0; -} -device_initcall(etrax_ethernet_init) - -/* set MAC address of the interface. called from the core after a - * SIOCSIFADDR ioctl, and from the bootup above. - */ - -static int -e100_set_mac_address(struct net_device *dev, void *p) -{ - struct net_local *np = netdev_priv(dev); - struct sockaddr *addr = p; - - spin_lock(&np->lock); /* preemption protection */ - - /* remember it */ - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* Write it to the hardware. - * Note the way the address is wrapped: - * *R_NETWORK_SA_0 = a0_0 | (a0_1 << 8) | (a0_2 << 16) | (a0_3 << 24); - * *R_NETWORK_SA_1 = a0_4 | (a0_5 << 8); - */ - - *R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) | - (dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24); - *R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8); - *R_NETWORK_SA_2 = 0; - - /* show it in the log as well */ - - printk(KERN_INFO "%s: changed MAC to %pM\n", dev->name, dev->dev_addr); - - spin_unlock(&np->lock); - - return 0; -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * sometime after booting when the 'ifconfig' program is run. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is non-reboot way to recover if something goes wrong. - */ - -static int -e100_open(struct net_device *dev) -{ - unsigned long flags; - - /* enable the MDIO output pin */ - - *R_NETWORK_MGM_CTRL = IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable); - - *R_IRQ_MASK0_CLR = - IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) | - IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) | - IO_STATE(R_IRQ_MASK0_CLR, excessive_col, clr); - - /* clear dma0 and 1 eop and descr irq masks */ - *R_IRQ_MASK2_CLR = - IO_STATE(R_IRQ_MASK2_CLR, dma0_descr, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_descr, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr); - - /* Reset and wait for the DMA channels */ - - RESET_DMA(NETWORK_TX_DMA_NBR); - RESET_DMA(NETWORK_RX_DMA_NBR); - WAIT_DMA(NETWORK_TX_DMA_NBR); - WAIT_DMA(NETWORK_RX_DMA_NBR); - - /* Initialise the etrax network controller */ - - /* allocate the irq corresponding to the receiving DMA */ - - if (request_irq(NETWORK_DMA_RX_IRQ_NBR, e100rxtx_interrupt, 0, cardname, - (void *)dev)) { - goto grace_exit0; - } - - /* allocate the irq corresponding to the transmitting DMA */ - - if (request_irq(NETWORK_DMA_TX_IRQ_NBR, e100rxtx_interrupt, 0, - cardname, (void *)dev)) { - goto grace_exit1; - } - - /* allocate the irq corresponding to the network errors etc */ - - if (request_irq(NETWORK_STATUS_IRQ_NBR, e100nw_interrupt, 0, - cardname, (void *)dev)) { - goto grace_exit2; - } - - /* - * Always allocate the DMA channels after the IRQ, - * and clean up on failure. - */ - - if (cris_request_dma(NETWORK_TX_DMA_NBR, - cardname, - DMA_VERBOSE_ON_ERROR, - dma_eth)) { - goto grace_exit3; - } - - if (cris_request_dma(NETWORK_RX_DMA_NBR, - cardname, - DMA_VERBOSE_ON_ERROR, - dma_eth)) { - goto grace_exit4; - } - - /* give the HW an idea of what MAC address we want */ - - *R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) | - (dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24); - *R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8); - *R_NETWORK_SA_2 = 0; - -#if 0 - /* use promiscuous mode for testing */ - *R_NETWORK_GA_0 = 0xffffffff; - *R_NETWORK_GA_1 = 0xffffffff; - - *R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */ -#else - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, max_size, size1522); - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, broadcast, receive); - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, ma0, enable); - SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; -#endif - - *R_NETWORK_GEN_CONFIG = - IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | - IO_STATE(R_NETWORK_GEN_CONFIG, enable, on); - - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, delay, none); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cancel, dont); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, cd, enable); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, retry, enable); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, pad, enable); - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, crc, enable); - *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; - - local_irq_save(flags); - - /* enable the irq's for ethernet DMA */ - - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) | - IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set); - - *R_IRQ_MASK0_SET = - IO_STATE(R_IRQ_MASK0_SET, overrun, set) | - IO_STATE(R_IRQ_MASK0_SET, underrun, set) | - IO_STATE(R_IRQ_MASK0_SET, excessive_col, set); - - /* make sure the irqs are cleared */ - - *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - *R_DMA_CH1_CLR_INTR = IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do); - - /* make sure the rec and transmit error counters are cleared */ - - (void)*R_REC_COUNTERS; /* dummy read */ - (void)*R_TR_COUNTERS; /* dummy read */ - - /* start the receiving DMA channel so we can receive packets from now on */ - - *R_DMA_CH1_FIRST = virt_to_phys(myNextRxDesc); - *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, start); - - /* Set up transmit DMA channel so it can be restarted later */ - - *R_DMA_CH0_FIRST = 0; - *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc); - netif_start_queue(dev); - - local_irq_restore(flags); - - /* Probe for transceiver */ - if (e100_probe_transceiver(dev)) - goto grace_exit5; - - /* Start duplex/speed timers */ - add_timer(&speed_timer); - add_timer(&duplex_timer); - - /* We are now ready to accept transmit requeusts from - * the queueing layer of the networking. - */ - netif_carrier_on(dev); - - return 0; - -grace_exit5: - cris_free_dma(NETWORK_RX_DMA_NBR, cardname); -grace_exit4: - cris_free_dma(NETWORK_TX_DMA_NBR, cardname); -grace_exit3: - free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); -grace_exit2: - free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev); -grace_exit1: - free_irq(NETWORK_DMA_RX_IRQ_NBR, (void *)dev); -grace_exit0: - return -EAGAIN; -} - -#if defined(CONFIG_ETRAX_NO_PHY) -static void -dummy_check_speed(struct net_device* dev) -{ - current_speed = 100; -} -#else -static void -generic_check_speed(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); - if ((data & ADVERTISE_100FULL) || - (data & ADVERTISE_100HALF)) - current_speed = 100; - else - current_speed = 10; -} - -static void -tdk_check_speed(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_TDK_DIAGNOSTIC_REG); - current_speed = (data & MDIO_TDK_DIAGNOSTIC_RATE ? 100 : 10); -} - -static void -broadcom_check_speed(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_AUX_CTRL_STATUS_REG); - current_speed = (data & MDIO_BC_SPEED ? 100 : 10); -} - -static void -intel_check_speed(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_INT_STATUS_REG_2); - current_speed = (data & MDIO_INT_SPEED ? 100 : 10); -} -#endif -static void -e100_check_speed(struct timer_list *unused) -{ - struct net_device* dev = timer_dev; - struct net_local *np = netdev_priv(dev); - static int led_initiated = 0; - unsigned long data; - int old_speed = current_speed; - - spin_lock(&np->transceiver_lock); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMSR); - if (!(data & BMSR_LSTATUS)) { - current_speed = 0; - } else { - transceiver->check_speed(dev); - } - - spin_lock(&np->led_lock); - if ((old_speed != current_speed) || !led_initiated) { - led_initiated = 1; - e100_set_network_leds(NO_NETWORK_ACTIVITY); - if (current_speed) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - } - spin_unlock(&np->led_lock); - - /* Reinitialize the timer. */ - speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL; - add_timer(&speed_timer); - - spin_unlock(&np->transceiver_lock); -} - -static void -e100_negotiate(struct net_device* dev) -{ - struct net_local *np = netdev_priv(dev); - unsigned short data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MII_ADVERTISE); - - /* Discard old speed and duplex settings */ - data &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_10HALF | ADVERTISE_10FULL); - - switch (current_speed_selection) { - case 10: - if (current_duplex == full) - data |= ADVERTISE_10FULL; - else if (current_duplex == half) - data |= ADVERTISE_10HALF; - else - data |= ADVERTISE_10HALF | ADVERTISE_10FULL; - break; - - case 100: - if (current_duplex == full) - data |= ADVERTISE_100FULL; - else if (current_duplex == half) - data |= ADVERTISE_100HALF; - else - data |= ADVERTISE_100HALF | ADVERTISE_100FULL; - break; - - case 0: /* Auto */ - if (current_duplex == full) - data |= ADVERTISE_100FULL | ADVERTISE_10FULL; - else if (current_duplex == half) - data |= ADVERTISE_100HALF | ADVERTISE_10HALF; - else - data |= ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL; - break; - - default: /* assume autoneg speed and duplex */ - data |= ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL; - break; - } - - e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE, data); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); - if (autoneg_normal) { - /* Renegotiate with link partner */ - data |= BMCR_ANENABLE | BMCR_ANRESTART; - } else { - /* Don't negotiate speed or duplex */ - data &= ~(BMCR_ANENABLE | BMCR_ANRESTART); - - /* Set speed and duplex static */ - if (current_speed_selection == 10) - data &= ~BMCR_SPEED100; - else - data |= BMCR_SPEED100; - - if (current_duplex != full) - data &= ~BMCR_FULLDPLX; - else - data |= BMCR_FULLDPLX; - } - e100_set_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR, data); -} - -static void -e100_set_speed(struct net_device* dev, unsigned long speed) -{ - struct net_local *np = netdev_priv(dev); - - spin_lock(&np->transceiver_lock); - if (speed != current_speed_selection) { - current_speed_selection = speed; - e100_negotiate(dev); - } - spin_unlock(&np->transceiver_lock); -} - -static void -e100_check_duplex(struct timer_list *unused) -{ - struct net_device *dev = timer_dev; - struct net_local *np = netdev_priv(dev); - int old_duplex; - - spin_lock(&np->transceiver_lock); - old_duplex = full_duplex; - transceiver->check_duplex(dev); - if (old_duplex != full_duplex) { - /* Duplex changed */ - SETF(network_rec_config_shadow, R_NETWORK_REC_CONFIG, duplex, full_duplex); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } - - /* Reinitialize the timer. */ - duplex_timer.expires = jiffies + NET_DUPLEX_CHECK_INTERVAL; - add_timer(&duplex_timer); - np->mii_if.full_duplex = full_duplex; - spin_unlock(&np->transceiver_lock); -} -#if defined(CONFIG_ETRAX_NO_PHY) -static void -dummy_check_duplex(struct net_device* dev) -{ - full_duplex = 1; -} -#else -static void -generic_check_duplex(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_ADVERTISE); - if ((data & ADVERTISE_10FULL) || - (data & ADVERTISE_100FULL)) - full_duplex = 1; - else - full_duplex = 0; -} - -static void -tdk_check_duplex(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_TDK_DIAGNOSTIC_REG); - full_duplex = (data & MDIO_TDK_DIAGNOSTIC_DPLX) ? 1 : 0; -} - -static void -broadcom_check_duplex(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_AUX_CTRL_STATUS_REG); - full_duplex = (data & MDIO_BC_FULL_DUPLEX_IND) ? 1 : 0; -} - -static void -intel_check_duplex(struct net_device* dev) -{ - unsigned long data; - struct net_local *np = netdev_priv(dev); - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, - MDIO_INT_STATUS_REG_2); - full_duplex = (data & MDIO_INT_FULL_DUPLEX_IND) ? 1 : 0; -} -#endif -static void -e100_set_duplex(struct net_device* dev, enum duplex new_duplex) -{ - struct net_local *np = netdev_priv(dev); - - spin_lock(&np->transceiver_lock); - if (new_duplex != current_duplex) { - current_duplex = new_duplex; - e100_negotiate(dev); - } - spin_unlock(&np->transceiver_lock); -} - -static int -e100_probe_transceiver(struct net_device* dev) -{ - int ret = 0; - -#if !defined(CONFIG_ETRAX_NO_PHY) - unsigned int phyid_high; - unsigned int phyid_low; - unsigned int oui; - struct transceiver_ops* ops = NULL; - struct net_local *np = netdev_priv(dev); - - spin_lock(&np->transceiver_lock); - - /* Probe MDIO physical address */ - for (np->mii_if.phy_id = 0; np->mii_if.phy_id <= 31; - np->mii_if.phy_id++) { - if (e100_get_mdio_reg(dev, - np->mii_if.phy_id, MII_BMSR) != 0xffff) - break; - } - if (np->mii_if.phy_id == 32) { - ret = -ENODEV; - goto out; - } - - /* Get manufacturer */ - phyid_high = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID1); - phyid_low = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_PHYSID2); - oui = (phyid_high << 6) | (phyid_low >> 10); - - for (ops = &transceivers[0]; ops->oui; ops++) { - if (ops->oui == oui) - break; - } - transceiver = ops; -out: - spin_unlock(&np->transceiver_lock); -#endif - return ret; -} - -static int -e100_get_mdio_reg(struct net_device *dev, int phy_id, int location) -{ - unsigned short cmd; /* Data to be sent on MDIO port */ - int data; /* Data read from MDIO */ - int bitCounter; - - /* Start of frame, OP Code, Physical Address, Register Address */ - cmd = (MDIO_START << 14) | (MDIO_READ << 12) | (phy_id << 7) | - (location << 2); - - e100_send_mdio_cmd(cmd, 0); - - data = 0; - - /* Data... */ - for (bitCounter=15; bitCounter>=0 ; bitCounter--) { - data |= (e100_receive_mdio_bit() << bitCounter); - } - - return data; -} - -static void -e100_set_mdio_reg(struct net_device *dev, int phy_id, int location, int value) -{ - int bitCounter; - unsigned short cmd; - - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (phy_id << 7) | - (location << 2); - - e100_send_mdio_cmd(cmd, 1); - - /* Data... */ - for (bitCounter=15; bitCounter>=0 ; bitCounter--) { - e100_send_mdio_bit(GET_BIT(bitCounter, value)); - } - -} - -static void -e100_send_mdio_cmd(unsigned short cmd, int write_cmd) -{ - int bitCounter; - unsigned char data = 0x2; - - /* Preamble */ - for (bitCounter = 31; bitCounter>= 0; bitCounter--) - e100_send_mdio_bit(GET_BIT(bitCounter, MDIO_PREAMBLE)); - - for (bitCounter = 15; bitCounter >= 2; bitCounter--) - e100_send_mdio_bit(GET_BIT(bitCounter, cmd)); - - /* Turnaround */ - for (bitCounter = 1; bitCounter >= 0 ; bitCounter--) - if (write_cmd) - e100_send_mdio_bit(GET_BIT(bitCounter, data)); - else - e100_receive_mdio_bit(); -} - -static void -e100_send_mdio_bit(unsigned char bit) -{ - *R_NETWORK_MGM_CTRL = - IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable) | - IO_FIELD(R_NETWORK_MGM_CTRL, mdio, bit); - udelay(1); - *R_NETWORK_MGM_CTRL = - IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable) | - IO_MASK(R_NETWORK_MGM_CTRL, mdck) | - IO_FIELD(R_NETWORK_MGM_CTRL, mdio, bit); - udelay(1); -} - -static unsigned char -e100_receive_mdio_bit(void) -{ - unsigned char bit; - *R_NETWORK_MGM_CTRL = 0; - bit = IO_EXTRACT(R_NETWORK_STAT, mdio, *R_NETWORK_STAT); - udelay(1); - *R_NETWORK_MGM_CTRL = IO_MASK(R_NETWORK_MGM_CTRL, mdck); - udelay(1); - return bit; -} - -static void -e100_reset_transceiver(struct net_device* dev) -{ - struct net_local *np = netdev_priv(dev); - unsigned short cmd; - unsigned short data; - int bitCounter; - - data = e100_get_mdio_reg(dev, np->mii_if.phy_id, MII_BMCR); - - cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (np->mii_if.phy_id << 7) | (MII_BMCR << 2); - - e100_send_mdio_cmd(cmd, 1); - - data |= 0x8000; - - for (bitCounter = 15; bitCounter >= 0 ; bitCounter--) { - e100_send_mdio_bit(GET_BIT(bitCounter, data)); - } -} - -/* Called by upper layers if they decide it took too long to complete - * sending a packet - we need to reset and stuff. - */ - -static void -e100_tx_timeout(struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&np->lock, flags); - - printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, - tx_done(dev) ? "IRQ problem" : "network cable problem"); - - /* remember we got an error */ - - dev->stats.tx_errors++; - - /* reset the TX DMA in case it has hung on something */ - - RESET_DMA(NETWORK_TX_DMA_NBR); - WAIT_DMA(NETWORK_TX_DMA_NBR); - - /* Reset the transceiver. */ - - e100_reset_transceiver(dev); - - /* and get rid of the packets that never got an interrupt */ - while (myFirstTxDesc != myNextTxDesc) { - dev_kfree_skb(myFirstTxDesc->skb); - myFirstTxDesc->skb = 0; - myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); - } - - /* Set up transmit DMA channel so it can be restarted later */ - *R_DMA_CH0_FIRST = 0; - *R_DMA_CH0_DESCR = virt_to_phys(myLastTxDesc); - - /* tell the upper layers we're ok again */ - - netif_wake_queue(dev); - spin_unlock_irqrestore(&np->lock, flags); -} - - -/* This will only be invoked if the driver is _not_ in XOFF state. - * What this means is that we need not check it, and that this - * invariant will hold if we make sure that the netif_*_queue() - * calls are done at the proper times. - */ - -static int -e100_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - unsigned char *buf = skb->data; - unsigned long flags; - -#ifdef ETHDEBUG - printk("send packet len %d\n", length); -#endif - spin_lock_irqsave(&np->lock, flags); /* protect from tx_interrupt and ourself */ - - myNextTxDesc->skb = skb; - - netif_trans_update(dev); /* NETIF_F_LLTX driver :( */ - - e100_hardware_send_packet(np, buf, skb->len); - - myNextTxDesc = phys_to_virt(myNextTxDesc->descr.next); - - /* Stop queue if full */ - if (myNextTxDesc == myFirstTxDesc) { - netif_stop_queue(dev); - } - - spin_unlock_irqrestore(&np->lock, flags); - - return NETDEV_TX_OK; -} - -/* - * The typical workload of the driver: - * Handle the network interface interrupts. - */ - -static irqreturn_t -e100rxtx_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *)dev_id; - unsigned long irqbits; - - /* - * Note that both rx and tx interrupts are blocked at this point, - * regardless of which got us here. - */ - - irqbits = *R_IRQ_MASK2_RD; - - /* Handle received packets */ - if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma1_eop, active)) { - /* acknowledge the eop interrupt */ - - *R_DMA_CH1_CLR_INTR = IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do); - - /* check if one or more complete packets were indeed received */ - - while ((*R_DMA_CH1_FIRST != virt_to_phys(myNextRxDesc)) && - (myNextRxDesc != myLastRxDesc)) { - /* Take out the buffer and give it to the OS, then - * allocate a new buffer to put a packet in. - */ - e100_rx(dev); - dev->stats.rx_packets++; - /* restart/continue on the channel, for safety */ - *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, restart); - /* clear dma channel 1 eop/descr irq bits */ - *R_DMA_CH1_CLR_INTR = - IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) | - IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do); - - /* now, we might have gotten another packet - so we have to loop back and check if so */ - } - } - - /* Report any packets that have been sent */ - while (virt_to_phys(myFirstTxDesc) != *R_DMA_CH0_FIRST && - (netif_queue_stopped(dev) || myFirstTxDesc != myNextTxDesc)) { - dev->stats.tx_bytes += myFirstTxDesc->skb->len; - dev->stats.tx_packets++; - - /* dma is ready with the transmission of the data in tx_skb, so now - we can release the skb memory */ - dev_kfree_skb_irq(myFirstTxDesc->skb); - myFirstTxDesc->skb = 0; - myFirstTxDesc = phys_to_virt(myFirstTxDesc->descr.next); - /* Wake up queue. */ - netif_wake_queue(dev); - } - - if (irqbits & IO_STATE(R_IRQ_MASK2_RD, dma0_eop, active)) { - /* acknowledge the eop interrupt. */ - *R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do); - } - - return IRQ_HANDLED; -} - -static irqreturn_t -e100nw_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *)dev_id; - unsigned long irqbits = *R_IRQ_MASK0_RD; - - /* check for underrun irq */ - if (irqbits & IO_STATE(R_IRQ_MASK0_RD, underrun, active)) { - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); - *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); - dev->stats.tx_errors++; - D(printk("ethernet receiver underrun!\n")); - } - - /* check for overrun irq */ - if (irqbits & IO_STATE(R_IRQ_MASK0_RD, overrun, active)) { - update_rx_stats(&dev->stats); /* this will ack the irq */ - D(printk("ethernet receiver overrun!\n")); - } - /* check for excessive collision irq */ - if (irqbits & IO_STATE(R_IRQ_MASK0_RD, excessive_col, active)) { - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, clr); - *R_NETWORK_TR_CTRL = network_tr_ctrl_shadow; - SETS(network_tr_ctrl_shadow, R_NETWORK_TR_CTRL, clr_error, nop); - dev->stats.tx_errors++; - D(printk("ethernet excessive collisions!\n")); - } - return IRQ_HANDLED; -} - -/* We have a good packet(s), get it/them out of the buffers. */ -static void -e100_rx(struct net_device *dev) -{ - struct sk_buff *skb; - int length = 0; - struct net_local *np = netdev_priv(dev); - unsigned char *skb_data_ptr; -#ifdef ETHDEBUG - int i; -#endif - etrax_eth_descr *prevRxDesc; /* The descriptor right before myNextRxDesc */ - spin_lock(&np->led_lock); - if (!led_active && time_after(jiffies, led_next_time)) { - /* light the network leds depending on the current speed. */ - e100_set_network_leds(NETWORK_ACTIVITY); - - /* Set the earliest time we may clear the LED */ - led_next_time = jiffies + NET_FLASH_TIME; - led_active = 1; - mod_timer(&clear_led_timer, jiffies + HZ/10); - } - spin_unlock(&np->led_lock); - - length = myNextRxDesc->descr.hw_len - 4; - dev->stats.rx_bytes += length; - -#ifdef ETHDEBUG - printk("Got a packet of length %d:\n", length); - /* dump the first bytes in the packet */ - skb_data_ptr = (unsigned char *)phys_to_virt(myNextRxDesc->descr.buf); - for (i = 0; i < 8; i++) { - printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8, - skb_data_ptr[0],skb_data_ptr[1],skb_data_ptr[2],skb_data_ptr[3], - skb_data_ptr[4],skb_data_ptr[5],skb_data_ptr[6],skb_data_ptr[7]); - skb_data_ptr += 8; - } -#endif - - if (length < RX_COPYBREAK) { - /* Small packet, copy data */ - skb = dev_alloc_skb(length - ETHER_HEAD_LEN); - if (!skb) { - dev->stats.rx_errors++; - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - goto update_nextrxdesc; - } - - skb_put(skb, length - ETHER_HEAD_LEN); /* allocate room for the packet body */ - skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */ - -#ifdef ETHDEBUG - printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n", - skb->head, skb->data, skb_tail_pointer(skb), - skb_end_pointer(skb)); - printk("copying packet to 0x%x.\n", skb_data_ptr); -#endif - - memcpy(skb_data_ptr, phys_to_virt(myNextRxDesc->descr.buf), length); - } - else { - /* Large packet, send directly to upper layers and allocate new - * memory (aligned to cache line boundary to avoid bug). - * Before sending the skb to upper layers we must make sure - * that skb->data points to the aligned start of the packet. - */ - int align; - struct sk_buff *new_skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); - if (!new_skb) { - dev->stats.rx_errors++; - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - goto update_nextrxdesc; - } - skb = myNextRxDesc->skb; - align = (int)phys_to_virt(myNextRxDesc->descr.buf) - (int)skb->data; - skb_put(skb, length + align); - skb_pull(skb, align); /* Remove alignment bytes */ - myNextRxDesc->skb = new_skb; - myNextRxDesc->descr.buf = L1_CACHE_ALIGN(virt_to_phys(myNextRxDesc->skb->data)); - } - - skb->protocol = eth_type_trans(skb, dev); - - /* Send the packet to the upper layers */ - netif_rx(skb); - - update_nextrxdesc: - /* Prepare for next packet */ - myNextRxDesc->descr.status = 0; - prevRxDesc = myNextRxDesc; - myNextRxDesc = phys_to_virt(myNextRxDesc->descr.next); - - rx_queue_len++; - - /* Check if descriptors should be returned */ - if (rx_queue_len == RX_QUEUE_THRESHOLD) { - flush_etrax_cache(); - prevRxDesc->descr.ctrl |= d_eol; - myLastRxDesc->descr.ctrl &= ~d_eol; - myLastRxDesc = prevRxDesc; - rx_queue_len = 0; - } -} - -/* The inverse routine to net_open(). */ -static int -e100_close(struct net_device *dev) -{ - printk(KERN_INFO "Closing %s.\n", dev->name); - - netif_stop_queue(dev); - - *R_IRQ_MASK0_CLR = - IO_STATE(R_IRQ_MASK0_CLR, overrun, clr) | - IO_STATE(R_IRQ_MASK0_CLR, underrun, clr) | - IO_STATE(R_IRQ_MASK0_CLR, excessive_col, clr); - - *R_IRQ_MASK2_CLR = - IO_STATE(R_IRQ_MASK2_CLR, dma0_descr, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma0_eop, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_descr, clr) | - IO_STATE(R_IRQ_MASK2_CLR, dma1_eop, clr); - - /* Stop the receiver and the transmitter */ - - RESET_DMA(NETWORK_TX_DMA_NBR); - RESET_DMA(NETWORK_RX_DMA_NBR); - - /* Flush the Tx and disable Rx here. */ - - free_irq(NETWORK_DMA_RX_IRQ_NBR, (void *)dev); - free_irq(NETWORK_DMA_TX_IRQ_NBR, (void *)dev); - free_irq(NETWORK_STATUS_IRQ_NBR, (void *)dev); - - cris_free_dma(NETWORK_TX_DMA_NBR, cardname); - cris_free_dma(NETWORK_RX_DMA_NBR, cardname); - - /* Update the statistics here. */ - - update_rx_stats(&dev->stats); - update_tx_stats(&dev->stats); - - /* Stop speed/duplex timers */ - del_timer(&speed_timer); - del_timer(&duplex_timer); - - return 0; -} - -static int -e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct mii_ioctl_data *data = if_mii(ifr); - struct net_local *np = netdev_priv(dev); - int rc = 0; - int old_autoneg; - - spin_lock(&np->lock); /* Preempt protection */ - switch (cmd) { - /* The ioctls below should be considered obsolete but are */ - /* still present for compatibility with old scripts/apps */ - case SET_ETH_SPEED_10: /* 10 Mbps */ - e100_set_speed(dev, 10); - break; - case SET_ETH_SPEED_100: /* 100 Mbps */ - e100_set_speed(dev, 100); - break; - case SET_ETH_SPEED_AUTO: /* Auto-negotiate speed */ - e100_set_speed(dev, 0); - break; - case SET_ETH_DUPLEX_HALF: /* Half duplex */ - e100_set_duplex(dev, half); - break; - case SET_ETH_DUPLEX_FULL: /* Full duplex */ - e100_set_duplex(dev, full); - break; - case SET_ETH_DUPLEX_AUTO: /* Auto-negotiate duplex */ - e100_set_duplex(dev, autoneg); - break; - case SET_ETH_AUTONEG: - old_autoneg = autoneg_normal; - autoneg_normal = *(int*)data; - if (autoneg_normal != old_autoneg) - e100_negotiate(dev); - break; - default: - rc = generic_mii_ioctl(&np->mii_if, if_mii(ifr), - cmd, NULL); - break; - } - spin_unlock(&np->lock); - return rc; -} - -static int e100_get_link_ksettings(struct net_device *dev, - struct ethtool_link_ksettings *cmd) -{ - struct net_local *np = netdev_priv(dev); - u32 supported; - - spin_lock_irq(&np->lock); - mii_ethtool_get_link_ksettings(&np->mii_if, cmd); - spin_unlock_irq(&np->lock); - - /* The PHY may support 1000baseT, but the Etrax100 does not. */ - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - - supported &= ~(SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full); - - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - - return 0; -} - -static int e100_set_link_ksettings(struct net_device *dev, - const struct ethtool_link_ksettings *ecmd) -{ - if (ecmd->base.autoneg == AUTONEG_ENABLE) { - e100_set_duplex(dev, autoneg); - e100_set_speed(dev, 0); - } else { - e100_set_duplex(dev, ecmd->base.duplex == DUPLEX_HALF ? - half : full); - e100_set_speed(dev, ecmd->base.speed == SPEED_10 ? 10 : 100); - } - - return 0; -} - -static void e100_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, "ETRAX 100LX", sizeof(info->driver)); - strlcpy(info->version, "$Revision: 1.31 $", sizeof(info->version)); - strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); - strlcpy(info->bus_info, "N/A", sizeof(info->bus_info)); -} - -static int e100_nway_reset(struct net_device *dev) -{ - if (current_duplex == autoneg && current_speed_selection == 0) - e100_negotiate(dev); - return 0; -} - -static const struct ethtool_ops e100_ethtool_ops = { - .get_drvinfo = e100_get_drvinfo, - .nway_reset = e100_nway_reset, - .get_link = ethtool_op_get_link, - .get_link_ksettings = e100_get_link_ksettings, - .set_link_ksettings = e100_set_link_ksettings, -}; - -static int -e100_set_config(struct net_device *dev, struct ifmap *map) -{ - struct net_local *np = netdev_priv(dev); - - spin_lock(&np->lock); /* Preempt protection */ - - switch(map->port) { - case IF_PORT_UNKNOWN: - /* Use autoneg */ - e100_set_speed(dev, 0); - e100_set_duplex(dev, autoneg); - break; - case IF_PORT_10BASET: - e100_set_speed(dev, 10); - e100_set_duplex(dev, autoneg); - break; - case IF_PORT_100BASET: - case IF_PORT_100BASETX: - e100_set_speed(dev, 100); - e100_set_duplex(dev, autoneg); - break; - case IF_PORT_100BASEFX: - case IF_PORT_10BASE2: - case IF_PORT_AUI: - spin_unlock(&np->lock); - return -EOPNOTSUPP; - default: - printk(KERN_ERR "%s: Invalid media selected", dev->name); - spin_unlock(&np->lock); - return -EINVAL; - } - spin_unlock(&np->lock); - return 0; -} - -static void -update_rx_stats(struct net_device_stats *es) -{ - unsigned long r = *R_REC_COUNTERS; - /* update stats relevant to reception errors */ - es->rx_fifo_errors += IO_EXTRACT(R_REC_COUNTERS, congestion, r); - es->rx_crc_errors += IO_EXTRACT(R_REC_COUNTERS, crc_error, r); - es->rx_frame_errors += IO_EXTRACT(R_REC_COUNTERS, alignment_error, r); - es->rx_length_errors += IO_EXTRACT(R_REC_COUNTERS, oversize, r); -} - -static void -update_tx_stats(struct net_device_stats *es) -{ - unsigned long r = *R_TR_COUNTERS; - /* update stats relevant to transmission errors */ - es->collisions += - IO_EXTRACT(R_TR_COUNTERS, single_col, r) + - IO_EXTRACT(R_TR_COUNTERS, multiple_col, r); -} - -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static struct net_device_stats * -e100_get_stats(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&lp->lock, flags); - - update_rx_stats(&dev->stats); - update_tx_stats(&dev->stats); - - spin_unlock_irqrestore(&lp->lock, flags); - return &dev->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - * num_addrs == -1 Promiscuous mode, receive all packets - * num_addrs == 0 Normal mode, clear multicast list - * num_addrs > 0 Multicast mode, receive normal and MC packets, - * and do best-effort filtering. - */ -static void -set_multicast_list(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int num_addr = netdev_mc_count(dev); - unsigned long int lo_bits; - unsigned long int hi_bits; - - spin_lock(&lp->lock); - if (dev->flags & IFF_PROMISC) { - /* promiscuous mode */ - lo_bits = 0xfffffffful; - hi_bits = 0xfffffffful; - - /* Enable individual receive */ - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, receive); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } else if (dev->flags & IFF_ALLMULTI) { - /* enable all multicasts */ - lo_bits = 0xfffffffful; - hi_bits = 0xfffffffful; - - /* Disable individual receive */ - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } else if (num_addr == 0) { - /* Normal, clear the mc list */ - lo_bits = 0x00000000ul; - hi_bits = 0x00000000ul; - - /* Disable individual receive */ - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } else { - /* MC mode, receive normal and MC packets */ - char hash_ix; - struct netdev_hw_addr *ha; - char *baddr; - - lo_bits = 0x00000000ul; - hi_bits = 0x00000000ul; - netdev_for_each_mc_addr(ha, dev) { - /* Calculate the hash index for the GA registers */ - - hash_ix = 0; - baddr = ha->addr; - hash_ix ^= (*baddr) & 0x3f; - hash_ix ^= ((*baddr) >> 6) & 0x03; - ++baddr; - hash_ix ^= ((*baddr) << 2) & 0x03c; - hash_ix ^= ((*baddr) >> 4) & 0xf; - ++baddr; - hash_ix ^= ((*baddr) << 4) & 0x30; - hash_ix ^= ((*baddr) >> 2) & 0x3f; - ++baddr; - hash_ix ^= (*baddr) & 0x3f; - hash_ix ^= ((*baddr) >> 6) & 0x03; - ++baddr; - hash_ix ^= ((*baddr) << 2) & 0x03c; - hash_ix ^= ((*baddr) >> 4) & 0xf; - ++baddr; - hash_ix ^= ((*baddr) << 4) & 0x30; - hash_ix ^= ((*baddr) >> 2) & 0x3f; - - hash_ix &= 0x3f; - - if (hash_ix >= 32) { - hi_bits |= (1 << (hash_ix-32)); - } else { - lo_bits |= (1 << hash_ix); - } - } - /* Disable individual receive */ - SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard); - *R_NETWORK_REC_CONFIG = network_rec_config_shadow; - } - *R_NETWORK_GA_0 = lo_bits; - *R_NETWORK_GA_1 = hi_bits; - spin_unlock(&lp->lock); -} - -void -e100_hardware_send_packet(struct net_local *np, char *buf, int length) -{ - D(printk("e100 send pack, buf 0x%x len %d\n", buf, length)); - - spin_lock(&np->led_lock); - if (!led_active && time_after(jiffies, led_next_time)) { - /* light the network leds depending on the current speed. */ - e100_set_network_leds(NETWORK_ACTIVITY); - - /* Set the earliest time we may clear the LED */ - led_next_time = jiffies + NET_FLASH_TIME; - led_active = 1; - mod_timer(&clear_led_timer, jiffies + HZ/10); - } - spin_unlock(&np->led_lock); - - /* configure the tx dma descriptor */ - myNextTxDesc->descr.sw_len = length; - myNextTxDesc->descr.ctrl = d_eop | d_eol | d_wait; - myNextTxDesc->descr.buf = virt_to_phys(buf); - - /* Move end of list */ - myLastTxDesc->descr.ctrl &= ~d_eol; - myLastTxDesc = myNextTxDesc; - - /* Restart DMA channel */ - *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, restart); -} - -static void -e100_clear_network_leds(struct timer_list *unused) -{ - struct net_device *dev = timer_dev; - struct net_local *np = netdev_priv(dev); - - spin_lock(&np->led_lock); - - if (led_active && time_after(jiffies, led_next_time)) { - e100_set_network_leds(NO_NETWORK_ACTIVITY); - - /* Set the earliest time we may set the LED */ - led_next_time = jiffies + NET_FLASH_PAUSE; - led_active = 0; - } - - spin_unlock(&np->led_lock); -} - -static void -e100_set_network_leds(int active) -{ -#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK) - int light_leds = (active == NO_NETWORK_ACTIVITY); -#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY) - int light_leds = (active == NETWORK_ACTIVITY); -#else -#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY" -#endif - - if (!current_speed) { - /* Make LED red, link is down */ - CRIS_LED_NETWORK_SET(CRIS_LED_OFF); - } else if (light_leds) { - if (current_speed == 10) { - CRIS_LED_NETWORK_SET(CRIS_LED_ORANGE); - } else { - CRIS_LED_NETWORK_SET(CRIS_LED_GREEN); - } - } else { - CRIS_LED_NETWORK_SET(CRIS_LED_OFF); - } -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void -e100_netpoll(struct net_device* netdev) -{ - e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev); -} -#endif - - -static int __init -e100_boot_setup(char* str) -{ - struct sockaddr sa = {0}; - int i; - - /* Parse the colon separated Ethernet station address */ - for (i = 0; i < ETH_ALEN; i++) { - unsigned int tmp; - if (sscanf(str + 3*i, "%2x", &tmp) != 1) { - printk(KERN_WARNING "Malformed station address"); - return 0; - } - sa.sa_data[i] = (char)tmp; - } - - default_mac = sa; - return 1; -} - -__setup("etrax100_eth=", e100_boot_setup); diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig index fdc673484add..9fee7c83ef9f 100644 --- a/drivers/net/ethernet/8390/Kconfig +++ b/drivers/net/ethernet/8390/Kconfig @@ -87,8 +87,7 @@ config MCF8390 config NE2000 tristate "NE2000/NE1000 support" - depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX || \ - ATARI_ETHERNEC) + depends on (ISA || (Q40 && m) || MACH_TX49XX || ATARI_ETHERNEC) select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y here. diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index 66f47987e2a2..4e05953c4fbc 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -99,7 +99,7 @@ MODULE_LICENSE("GPL"); that the ne2k probe is the last 8390 based probe to take place (as it is at boot) and so the probe will get confused by any other 8390 cards. ISA device autoprobes on a running machine are not recommended anyway. */ -#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R)) +#if !defined(MODULE) && defined(CONFIG_ISA) /* Do we need a portlist for the ISA auto-probe ? */ #define NEEDS_PORTLIST #endif @@ -164,12 +164,7 @@ bad_clone_list[] __initdata = { #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -#if defined(CONFIG_PLAT_MAPPI) -# define DCR_VAL 0x4b -#elif defined(CONFIG_PLAT_OAKS32R) || \ - defined(CONFIG_MACH_TX49XX) -# define DCR_VAL 0x48 /* 8-bit mode */ -#elif defined(CONFIG_ATARI) /* 8-bit mode on Atari, normal on Q40 */ +#if defined(CONFIG_ATARI) /* 8-bit mode on Atari, normal on Q40 */ # define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49) #else # define DCR_VAL 0x49 @@ -422,12 +417,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) stop_page = NE1SM_STOP_PG; } -#if defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R) - neX000 = ((SA_prom[14] == 0x57 && SA_prom[15] == 0x57) - || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42)); -#else neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); -#endif ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00); @@ -508,18 +498,9 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr) dev->base_addr = ioaddr; -#ifdef CONFIG_PLAT_MAPPI - outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, - ioaddr + E8390_CMD); /* 0x61 */ - for (i = 0; i < ETH_ALEN; i++) { - dev->dev_addr[i] = SA_prom[i] - = inb_p(ioaddr + EN1_PHYS_SHIFT(i)); - } -#else for (i = 0; i < ETH_ALEN; i++) { dev->dev_addr[i] = SA_prom[i]; } -#endif pr_cont("%pM\n", dev->dev_addr); diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index b6cf4b6962f5..074d760a568b 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -34,7 +34,6 @@ source "drivers/net/ethernet/arc/Kconfig" source "drivers/net/ethernet/atheros/Kconfig" source "drivers/net/ethernet/aurora/Kconfig" source "drivers/net/ethernet/cadence/Kconfig" -source "drivers/net/ethernet/adi/Kconfig" source "drivers/net/ethernet/broadcom/Kconfig" source "drivers/net/ethernet/brocade/Kconfig" source "drivers/net/ethernet/calxeda/Kconfig" @@ -176,7 +175,6 @@ source "drivers/net/ethernet/stmicro/Kconfig" source "drivers/net/ethernet/sun/Kconfig" source "drivers/net/ethernet/tehuti/Kconfig" source "drivers/net/ethernet/ti/Kconfig" -source "drivers/net/ethernet/tile/Kconfig" source "drivers/net/ethernet/toshiba/Kconfig" source "drivers/net/ethernet/tundra/Kconfig" source "drivers/net/ethernet/via/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 3cdf01e96e0b..135dae67d671 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_NET_VENDOR_ARC) += arc/ obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ obj-$(CONFIG_NET_VENDOR_AURORA) += aurora/ obj-$(CONFIG_NET_CADENCE) += cadence/ -obj-$(CONFIG_NET_BFIN) += adi/ obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/ obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/ obj-$(CONFIG_NET_CALXEDA_XGMAC) += calxeda/ @@ -88,7 +87,6 @@ obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/ obj-$(CONFIG_NET_VENDOR_SUN) += sun/ obj-$(CONFIG_NET_VENDOR_TEHUTI) += tehuti/ obj-$(CONFIG_NET_VENDOR_TI) += ti/ -obj-$(CONFIG_TILE_NET) += tile/ obj-$(CONFIG_NET_VENDOR_TOSHIBA) += toshiba/ obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/ obj-$(CONFIG_NET_VENDOR_VIA) += via/ diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig deleted file mode 100644 index 98cc8f535021..000000000000 --- a/drivers/net/ethernet/adi/Kconfig +++ /dev/null @@ -1,66 +0,0 @@ -# -# Blackfin device configuration -# - -config NET_BFIN - bool "Blackfin devices" - depends on BF516 || BF518 || BF526 || BF527 || BF536 || BF537 - ---help--- - If you have a network (Ethernet) card belonging to this class, say Y. - - If unsure, say Y. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the remaining Blackfin card questions. If you say Y, you will be - asked for your specific card in the following questions. - -if NET_BFIN - -config BFIN_MAC - tristate "Blackfin on-chip MAC support" - depends on (BF516 || BF518 || BF526 || BF527 || BF536 || BF537) - select CRC32 - select MII - select PHYLIB - select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE - ---help--- - This is the driver for Blackfin on-chip mac device. Say Y if you want - it compiled into the kernel. This driver is also available as a - module ( = code which can be inserted in and removed from the running - kernel whenever you want). The module will be called bfin_mac. - -config BFIN_MAC_USE_L1 - bool "Use L1 memory for rx/tx packets" - depends on BFIN_MAC && (BF527 || BF537) - default y - ---help--- - To get maximum network performance, you should use L1 memory as rx/tx - buffers. Say N here if you want to reserve L1 memory for other uses. - -config BFIN_TX_DESC_NUM - int "Number of transmit buffer packets" - depends on BFIN_MAC - range 6 10 if BFIN_MAC_USE_L1 - range 10 100 - default "10" - ---help--- - Set the number of buffer packets used in driver. - -config BFIN_RX_DESC_NUM - int "Number of receive buffer packets" - depends on BFIN_MAC - range 20 64 - default "20" - ---help--- - Set the number of buffer packets used in driver. - -config BFIN_MAC_USE_HWSTAMP - bool "Use IEEE 1588 hwstamp" - depends on BFIN_MAC && BF518 - imply PTP_1588_CLOCK - default y - ---help--- - To support the IEEE 1588 Precision Time Protocol (PTP), select y here - -endif # NET_BFIN diff --git a/drivers/net/ethernet/adi/Makefile b/drivers/net/ethernet/adi/Makefile deleted file mode 100644 index b1fbe195d0e8..000000000000 --- a/drivers/net/ethernet/adi/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the Blackfin device drivers. -# - -obj-$(CONFIG_BFIN_MAC) += bfin_mac.o diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c deleted file mode 100644 index 7120f2b9c6ef..000000000000 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ /dev/null @@ -1,1881 +0,0 @@ -/* - * Blackfin On-Chip MAC Driver - * - * Copyright 2004-2010 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#define DRV_VERSION "1.1" -#define DRV_DESC "Blackfin on-chip Ethernet MAC driver" - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/timer.h> -#include <linux/errno.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/crc32.h> -#include <linux/device.h> -#include <linux/spinlock.h> -#include <linux/mii.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/skbuff.h> -#include <linux/platform_device.h> - -#include <asm/dma.h> -#include <linux/dma-mapping.h> - -#include <asm/div64.h> -#include <asm/dpmc.h> -#include <asm/blackfin.h> -#include <asm/cacheflush.h> -#include <asm/portmux.h> -#include <mach/pll.h> - -#include "bfin_mac.h" - -MODULE_AUTHOR("Bryan Wu, Luke Yang"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_ALIAS("platform:bfin_mac"); - -#if defined(CONFIG_BFIN_MAC_USE_L1) -# define bfin_mac_alloc(dma_handle, size, num) l1_data_sram_zalloc(size*num) -# define bfin_mac_free(dma_handle, ptr, num) l1_data_sram_free(ptr) -#else -# define bfin_mac_alloc(dma_handle, size, num) \ - dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL) -# define bfin_mac_free(dma_handle, ptr, num) \ - dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle) -#endif - -#define PKT_BUF_SZ 1580 - -#define MAX_TIMEOUT_CNT 500 - -/* pointers to maintain transmit list */ -static struct net_dma_desc_tx *tx_list_head; -static struct net_dma_desc_tx *tx_list_tail; -static struct net_dma_desc_rx *rx_list_head; -static struct net_dma_desc_rx *rx_list_tail; -static struct net_dma_desc_rx *current_rx_ptr; -static struct net_dma_desc_tx *current_tx_ptr; -static struct net_dma_desc_tx *tx_desc; -static struct net_dma_desc_rx *rx_desc; - -static void desc_list_free(void) -{ - struct net_dma_desc_rx *r; - struct net_dma_desc_tx *t; - int i; -#if !defined(CONFIG_BFIN_MAC_USE_L1) - dma_addr_t dma_handle = 0; -#endif - - if (tx_desc) { - t = tx_list_head; - for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { - if (t) { - if (t->skb) { - dev_kfree_skb(t->skb); - t->skb = NULL; - } - t = t->next; - } - } - bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM); - } - - if (rx_desc) { - r = rx_list_head; - for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { - if (r) { - if (r->skb) { - dev_kfree_skb(r->skb); - r->skb = NULL; - } - r = r->next; - } - } - bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM); - } -} - -static int desc_list_init(struct net_device *dev) -{ - int i; - struct sk_buff *new_skb; -#if !defined(CONFIG_BFIN_MAC_USE_L1) - /* - * This dma_handle is useless in Blackfin dma_alloc_coherent(). - * The real dma handler is the return value of dma_alloc_coherent(). - */ - dma_addr_t dma_handle; -#endif - - tx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_tx), - CONFIG_BFIN_TX_DESC_NUM); - if (tx_desc == NULL) - goto init_error; - - rx_desc = bfin_mac_alloc(&dma_handle, - sizeof(struct net_dma_desc_rx), - CONFIG_BFIN_RX_DESC_NUM); - if (rx_desc == NULL) - goto init_error; - - /* init tx_list */ - tx_list_head = tx_list_tail = tx_desc; - - for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { - struct net_dma_desc_tx *t = tx_desc + i; - struct dma_descriptor *a = &(t->desc_a); - struct dma_descriptor *b = &(t->desc_b); - - /* - * disable DMA - * read from memory WNR = 0 - * wordsize is 32 bits - * 6 half words is desc size - * large desc flow - */ - a->config = WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; - a->start_addr = (unsigned long)t->packet; - a->x_count = 0; - a->next_dma_desc = b; - - /* - * enabled DMA - * write to memory WNR = 1 - * wordsize is 32 bits - * disable interrupt - * 6 half words is desc size - * large desc flow - */ - b->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; - b->start_addr = (unsigned long)(&(t->status)); - b->x_count = 0; - - t->skb = NULL; - tx_list_tail->desc_b.next_dma_desc = a; - tx_list_tail->next = t; - tx_list_tail = t; - } - tx_list_tail->next = tx_list_head; /* tx_list is a circle */ - tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a); - current_tx_ptr = tx_list_head; - - /* init rx_list */ - rx_list_head = rx_list_tail = rx_desc; - - for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { - struct net_dma_desc_rx *r = rx_desc + i; - struct dma_descriptor *a = &(r->desc_a); - struct dma_descriptor *b = &(r->desc_b); - - /* allocate a new skb for next time receive */ - new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); - if (!new_skb) - goto init_error; - - skb_reserve(new_skb, NET_IP_ALIGN); - /* Invalidate the data cache of skb->data range when it is write back - * cache. It will prevent overwriting the new data from DMA - */ - blackfin_dcache_invalidate_range((unsigned long)new_skb->head, - (unsigned long)new_skb->end); - r->skb = new_skb; - - /* - * enabled DMA - * write to memory WNR = 1 - * wordsize is 32 bits - * disable interrupt - * 6 half words is desc size - * large desc flow - */ - a->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; - /* since RXDWA is enabled */ - a->start_addr = (unsigned long)new_skb->data - 2; - a->x_count = 0; - a->next_dma_desc = b; - - /* - * enabled DMA - * write to memory WNR = 1 - * wordsize is 32 bits - * enable interrupt - * 6 half words is desc size - * large desc flow - */ - b->config = DMAEN | WNR | WDSIZE_32 | DI_EN | - NDSIZE_6 | DMAFLOW_LARGE; - b->start_addr = (unsigned long)(&(r->status)); - b->x_count = 0; - - rx_list_tail->desc_b.next_dma_desc = a; - rx_list_tail->next = r; - rx_list_tail = r; - } - rx_list_tail->next = rx_list_head; /* rx_list is a circle */ - rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a); - current_rx_ptr = rx_list_head; - - return 0; - -init_error: - desc_list_free(); - pr_err("kmalloc failed\n"); - return -ENOMEM; -} - - -/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ - -/* - * MII operations - */ -/* Wait until the previous MDC/MDIO transaction has completed */ -static int bfin_mdio_poll(void) -{ - int timeout_cnt = MAX_TIMEOUT_CNT; - - /* poll the STABUSY bit */ - while ((bfin_read_EMAC_STAADD()) & STABUSY) { - udelay(1); - if (timeout_cnt-- < 0) { - pr_err("wait MDC/MDIO transaction to complete timeout\n"); - return -ETIMEDOUT; - } - } - - return 0; -} - -/* Read an off-chip register in a PHY through the MDC/MDIO port */ -static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) -{ - int ret; - - ret = bfin_mdio_poll(); - if (ret) - return ret; - - /* read mode */ - bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | - SET_REGAD((u16) regnum) | - STABUSY); - - ret = bfin_mdio_poll(); - if (ret) - return ret; - - return (int) bfin_read_EMAC_STADAT(); -} - -/* Write an off-chip register in a PHY through the MDC/MDIO port */ -static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, - u16 value) -{ - int ret; - - ret = bfin_mdio_poll(); - if (ret) - return ret; - - bfin_write_EMAC_STADAT((u32) value); - - /* write mode */ - bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) | - SET_REGAD((u16) regnum) | - STAOP | - STABUSY); - - return bfin_mdio_poll(); -} - -static void bfin_mac_adjust_link(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - struct phy_device *phydev = dev->phydev; - unsigned long flags; - int new_state = 0; - - spin_lock_irqsave(&lp->lock, flags); - if (phydev->link) { - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != lp->old_duplex) { - u32 opmode = bfin_read_EMAC_OPMODE(); - new_state = 1; - - if (phydev->duplex) - opmode |= FDMODE; - else - opmode &= ~(FDMODE); - - bfin_write_EMAC_OPMODE(opmode); - lp->old_duplex = phydev->duplex; - } - - if (phydev->speed != lp->old_speed) { - if (phydev->interface == PHY_INTERFACE_MODE_RMII) { - u32 opmode = bfin_read_EMAC_OPMODE(); - switch (phydev->speed) { - case 10: - opmode |= RMII_10; - break; - case 100: - opmode &= ~RMII_10; - break; - default: - netdev_warn(dev, - "Ack! Speed (%d) is not 10/100!\n", - phydev->speed); - break; - } - bfin_write_EMAC_OPMODE(opmode); - } - - new_state = 1; - lp->old_speed = phydev->speed; - } - - if (!lp->old_link) { - new_state = 1; - lp->old_link = 1; - } - } else if (lp->old_link) { - new_state = 1; - lp->old_link = 0; - lp->old_speed = 0; - lp->old_duplex = -1; - } - - if (new_state) { - u32 opmode = bfin_read_EMAC_OPMODE(); - phy_print_status(phydev); - pr_debug("EMAC_OPMODE = 0x%08x\n", opmode); - } - - spin_unlock_irqrestore(&lp->lock, flags); -} - -/* MDC = 2.5 MHz */ -#define MDC_CLK 2500000 - -static int mii_probe(struct net_device *dev, int phy_mode) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - struct phy_device *phydev; - unsigned short sysctl; - u32 sclk, mdc_div; - - /* Enable PHY output early */ - if (!(bfin_read_VR_CTL() & CLKBUFOE)) - bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); - - sclk = get_sclk(); - mdc_div = ((sclk / MDC_CLK) / 2) - 1; - - sysctl = bfin_read_EMAC_SYSCTL(); - sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div); - bfin_write_EMAC_SYSCTL(sysctl); - - phydev = phy_find_first(lp->mii_bus); - if (!phydev) { - netdev_err(dev, "no phy device found\n"); - return -ENODEV; - } - - if (phy_mode != PHY_INTERFACE_MODE_RMII && - phy_mode != PHY_INTERFACE_MODE_MII) { - netdev_err(dev, "invalid phy interface mode\n"); - return -EINVAL; - } - - phydev = phy_connect(dev, phydev_name(phydev), - &bfin_mac_adjust_link, phy_mode); - - if (IS_ERR(phydev)) { - netdev_err(dev, "could not attach PHY\n"); - return PTR_ERR(phydev); - } - - /* mask with MAC supported features */ - phydev->supported &= (SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_Autoneg - | SUPPORTED_Pause | SUPPORTED_Asym_Pause - | SUPPORTED_MII - | SUPPORTED_TP); - - phydev->advertising = phydev->supported; - - lp->old_link = 0; - lp->old_speed = 0; - lp->old_duplex = -1; - - phy_attached_print(phydev, "mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n", - MDC_CLK, mdc_div, sclk / 1000000); - - return 0; -} - -/* - * Ethtool support - */ - -/* - * interrupt routine for magic packet wakeup - */ -static irqreturn_t bfin_mac_wake_interrupt(int irq, void *dev_id) -{ - return IRQ_HANDLED; -} - -static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); - strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info)); -} - -static void bfin_mac_ethtool_getwol(struct net_device *dev, - struct ethtool_wolinfo *wolinfo) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - - wolinfo->supported = WAKE_MAGIC; - wolinfo->wolopts = lp->wol; -} - -static int bfin_mac_ethtool_setwol(struct net_device *dev, - struct ethtool_wolinfo *wolinfo) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - int rc; - - if (wolinfo->wolopts & (WAKE_MAGICSECURE | - WAKE_UCAST | - WAKE_MCAST | - WAKE_BCAST | - WAKE_ARP)) - return -EOPNOTSUPP; - - lp->wol = wolinfo->wolopts; - - if (lp->wol && !lp->irq_wake_requested) { - /* register wake irq handler */ - rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt, - 0, "EMAC_WAKE", dev); - if (rc) - return rc; - lp->irq_wake_requested = true; - } - - if (!lp->wol && lp->irq_wake_requested) { - free_irq(IRQ_MAC_WAKEDET, dev); - lp->irq_wake_requested = false; - } - - /* Make sure the PHY driver doesn't suspend */ - device_init_wakeup(&dev->dev, lp->wol); - - return 0; -} - -#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP -static int bfin_mac_ethtool_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - - info->so_timestamping = - SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; - info->phc_index = lp->phc_index; - info->tx_types = - (1 << HWTSTAMP_TX_OFF) | - (1 << HWTSTAMP_TX_ON); - info->rx_filters = - (1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT); - return 0; -} -#endif - -static const struct ethtool_ops bfin_mac_ethtool_ops = { - .get_link = ethtool_op_get_link, - .get_drvinfo = bfin_mac_ethtool_getdrvinfo, - .get_wol = bfin_mac_ethtool_getwol, - .set_wol = bfin_mac_ethtool_setwol, -#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP - .get_ts_info = bfin_mac_ethtool_get_ts_info, -#endif - .get_link_ksettings = phy_ethtool_get_link_ksettings, - .set_link_ksettings = phy_ethtool_set_link_ksettings, -}; - -/**************************************************************************/ -static void setup_system_regs(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - int i; - unsigned short sysctl; - - /* - * Odd word alignment for Receive Frame DMA word - * Configure checksum support and rcve frame word alignment - */ - sysctl = bfin_read_EMAC_SYSCTL(); - /* - * check if interrupt is requested for any PHY, - * enable PHY interrupt only if needed - */ - for (i = 0; i < PHY_MAX_ADDR; ++i) - if (lp->mii_bus->irq[i] != PHY_POLL) - break; - if (i < PHY_MAX_ADDR) - sysctl |= PHYIE; - sysctl |= RXDWA; -#if defined(BFIN_MAC_CSUM_OFFLOAD) - sysctl |= RXCKS; -#else - sysctl &= ~RXCKS; -#endif - bfin_write_EMAC_SYSCTL(sysctl); - - bfin_write_EMAC_MMC_CTL(RSTC | CROLL); - - /* Set vlan regs to let 1522 bytes long packets pass through */ - bfin_write_EMAC_VLAN1(lp->vlan1_mask); - bfin_write_EMAC_VLAN2(lp->vlan2_mask); - - /* Initialize the TX DMA channel registers */ - bfin_write_DMA2_X_COUNT(0); - bfin_write_DMA2_X_MODIFY(4); - bfin_write_DMA2_Y_COUNT(0); - bfin_write_DMA2_Y_MODIFY(0); - - /* Initialize the RX DMA channel registers */ - bfin_write_DMA1_X_COUNT(0); - bfin_write_DMA1_X_MODIFY(4); - bfin_write_DMA1_Y_COUNT(0); - bfin_write_DMA1_Y_MODIFY(0); -} - -static void setup_mac_addr(u8 *mac_addr) -{ - u32 addr_low = le32_to_cpu(*(__le32 *) & mac_addr[0]); - u16 addr_hi = le16_to_cpu(*(__le16 *) & mac_addr[4]); - - /* this depends on a little-endian machine */ - bfin_write_EMAC_ADDRLO(addr_low); - bfin_write_EMAC_ADDRHI(addr_hi); -} - -static int bfin_mac_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - setup_mac_addr(dev->dev_addr); - return 0; -} - -#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP -#define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE) - -static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result) -{ - u32 ipn = 1000000000UL / input_clk; - u32 ppn = 1; - unsigned int shift = 0; - - while (ppn <= ipn) { - ppn <<= 1; - shift++; - } - *shift_result = shift; - return 1000000000UL / ppn; -} - -static int bfin_mac_hwtstamp_set(struct net_device *netdev, - struct ifreq *ifr) -{ - struct hwtstamp_config config; - struct bfin_mac_local *lp = netdev_priv(netdev); - u16 ptpctl; - u32 ptpfv1, ptpfv2, ptpfv3, ptpfoff; - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - pr_debug("%s config flag:0x%x, tx_type:0x%x, rx_filter:0x%x\n", - __func__, config.flags, config.tx_type, config.rx_filter); - - /* reserved for future extensions */ - if (config.flags) - return -EINVAL; - - if ((config.tx_type != HWTSTAMP_TX_OFF) && - (config.tx_type != HWTSTAMP_TX_ON)) - return -ERANGE; - - ptpctl = bfin_read_EMAC_PTP_CTL(); - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - /* - * Dont allow any timestamping - */ - ptpfv3 = 0xFFFFFFFF; - bfin_write_EMAC_PTP_FV3(ptpfv3); - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - /* - * Clear the five comparison mask bits (bits[12:8]) in EMAC_PTP_CTL) - * to enable all the field matches. - */ - ptpctl &= ~0x1F00; - bfin_write_EMAC_PTP_CTL(ptpctl); - /* - * Keep the default values of the EMAC_PTP_FOFF register. - */ - ptpfoff = 0x4A24170C; - bfin_write_EMAC_PTP_FOFF(ptpfoff); - /* - * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 - * registers. - */ - ptpfv1 = 0x11040800; - bfin_write_EMAC_PTP_FV1(ptpfv1); - ptpfv2 = 0x0140013F; - bfin_write_EMAC_PTP_FV2(ptpfv2); - /* - * The default value (0xFFFC) allows the timestamping of both - * received Sync messages and Delay_Req messages. - */ - ptpfv3 = 0xFFFFFFFC; - bfin_write_EMAC_PTP_FV3(ptpfv3); - - config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - /* Clear all five comparison mask bits (bits[12:8]) in the - * EMAC_PTP_CTL register to enable all the field matches. - */ - ptpctl &= ~0x1F00; - bfin_write_EMAC_PTP_CTL(ptpctl); - /* - * Keep the default values of the EMAC_PTP_FOFF register, except set - * the PTPCOF field to 0x2A. - */ - ptpfoff = 0x2A24170C; - bfin_write_EMAC_PTP_FOFF(ptpfoff); - /* - * Keep the default values of the EMAC_PTP_FV1 and EMAC_PTP_FV2 - * registers. - */ - ptpfv1 = 0x11040800; - bfin_write_EMAC_PTP_FV1(ptpfv1); - ptpfv2 = 0x0140013F; - bfin_write_EMAC_PTP_FV2(ptpfv2); - /* - * To allow the timestamping of Pdelay_Req and Pdelay_Resp, set - * the value to 0xFFF0. - */ - ptpfv3 = 0xFFFFFFF0; - bfin_write_EMAC_PTP_FV3(ptpfv3); - - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - /* - * Clear bits 8 and 12 of the EMAC_PTP_CTL register to enable only the - * EFTM and PTPCM field comparison. - */ - ptpctl &= ~0x1100; - bfin_write_EMAC_PTP_CTL(ptpctl); - /* - * Keep the default values of all the fields of the EMAC_PTP_FOFF - * register, except set the PTPCOF field to 0x0E. - */ - ptpfoff = 0x0E24170C; - bfin_write_EMAC_PTP_FOFF(ptpfoff); - /* - * Program bits [15:0] of the EMAC_PTP_FV1 register to 0x88F7, which - * corresponds to PTP messages on the MAC layer. - */ - ptpfv1 = 0x110488F7; - bfin_write_EMAC_PTP_FV1(ptpfv1); - ptpfv2 = 0x0140013F; - bfin_write_EMAC_PTP_FV2(ptpfv2); - /* - * To allow the timestamping of Pdelay_Req and Pdelay_Resp - * messages, set the value to 0xFFF0. - */ - ptpfv3 = 0xFFFFFFF0; - bfin_write_EMAC_PTP_FV3(ptpfv3); - - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; - break; - default: - return -ERANGE; - } - - if (config.tx_type == HWTSTAMP_TX_OFF && - bfin_mac_hwtstamp_is_none(config.rx_filter)) { - ptpctl &= ~PTP_EN; - bfin_write_EMAC_PTP_CTL(ptpctl); - - SSYNC(); - } else { - ptpctl |= PTP_EN; - bfin_write_EMAC_PTP_CTL(ptpctl); - - /* - * clear any existing timestamp - */ - bfin_read_EMAC_PTP_RXSNAPLO(); - bfin_read_EMAC_PTP_RXSNAPHI(); - - bfin_read_EMAC_PTP_TXSNAPLO(); - bfin_read_EMAC_PTP_TXSNAPHI(); - - SSYNC(); - } - - lp->stamp_cfg = config; - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; -} - -static int bfin_mac_hwtstamp_get(struct net_device *netdev, - struct ifreq *ifr) -{ - struct bfin_mac_local *lp = netdev_priv(netdev); - - return copy_to_user(ifr->ifr_data, &lp->stamp_cfg, - sizeof(lp->stamp_cfg)) ? - -EFAULT : 0; -} - -static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) -{ - struct bfin_mac_local *lp = netdev_priv(netdev); - - if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { - int timeout_cnt = MAX_TIMEOUT_CNT; - - /* When doing time stamping, keep the connection to the socket - * a while longer - */ - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - - /* - * The timestamping is done at the EMAC module's MII/RMII interface - * when the module sees the Start of Frame of an event message packet. This - * interface is the closest possible place to the physical Ethernet transmission - * medium, providing the best timing accuracy. - */ - while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) - udelay(1); - if (timeout_cnt == 0) - netdev_err(netdev, "timestamp the TX packet failed\n"); - else { - struct skb_shared_hwtstamps shhwtstamps; - u64 ns; - u64 regval; - - regval = bfin_read_EMAC_PTP_TXSNAPLO(); - regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; - memset(&shhwtstamps, 0, sizeof(shhwtstamps)); - ns = regval << lp->shift; - shhwtstamps.hwtstamp = ns_to_ktime(ns); - skb_tstamp_tx(skb, &shhwtstamps); - } - } -} - -static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) -{ - struct bfin_mac_local *lp = netdev_priv(netdev); - u32 valid; - u64 regval, ns; - struct skb_shared_hwtstamps *shhwtstamps; - - if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter)) - return; - - valid = bfin_read_EMAC_PTP_ISTAT() & RXEL; - if (!valid) - return; - - shhwtstamps = skb_hwtstamps(skb); - - regval = bfin_read_EMAC_PTP_RXSNAPLO(); - regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; - ns = regval << lp->shift; - memset(shhwtstamps, 0, sizeof(*shhwtstamps)); - shhwtstamps->hwtstamp = ns_to_ktime(ns); -} - -static void bfin_mac_hwtstamp_init(struct net_device *netdev) -{ - struct bfin_mac_local *lp = netdev_priv(netdev); - u64 addend, ppb; - u32 input_clk, phc_clk; - - /* Initialize hardware timer */ - input_clk = get_sclk(); - phc_clk = bfin_select_phc_clock(input_clk, &lp->shift); - addend = phc_clk * (1ULL << 32); - do_div(addend, input_clk); - bfin_write_EMAC_PTP_ADDEND((u32)addend); - - lp->addend = addend; - ppb = 1000000000ULL * input_clk; - do_div(ppb, phc_clk); - lp->max_ppb = ppb - 1000000000ULL - 1ULL; - - /* Initialize hwstamp config */ - lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; - lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; -} - -static u64 bfin_ptp_time_read(struct bfin_mac_local *lp) -{ - u64 ns; - u32 lo, hi; - - lo = bfin_read_EMAC_PTP_TIMELO(); - hi = bfin_read_EMAC_PTP_TIMEHI(); - - ns = ((u64) hi) << 32; - ns |= lo; - ns <<= lp->shift; - - return ns; -} - -static void bfin_ptp_time_write(struct bfin_mac_local *lp, u64 ns) -{ - u32 hi, lo; - - ns >>= lp->shift; - hi = ns >> 32; - lo = ns & 0xffffffff; - - bfin_write_EMAC_PTP_TIMELO(lo); - bfin_write_EMAC_PTP_TIMEHI(hi); -} - -/* PTP Hardware Clock operations */ - -static int bfin_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - u64 adj; - u32 diff, addend; - int neg_adj = 0; - struct bfin_mac_local *lp = - container_of(ptp, struct bfin_mac_local, caps); - - if (ppb < 0) { - neg_adj = 1; - ppb = -ppb; - } - addend = lp->addend; - adj = addend; - adj *= ppb; - diff = div_u64(adj, 1000000000ULL); - - addend = neg_adj ? addend - diff : addend + diff; - - bfin_write_EMAC_PTP_ADDEND(addend); - - return 0; -} - -static int bfin_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - s64 now; - unsigned long flags; - struct bfin_mac_local *lp = - container_of(ptp, struct bfin_mac_local, caps); - - spin_lock_irqsave(&lp->phc_lock, flags); - - now = bfin_ptp_time_read(lp); - now += delta; - bfin_ptp_time_write(lp, now); - - spin_unlock_irqrestore(&lp->phc_lock, flags); - - return 0; -} - -static int bfin_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) -{ - u64 ns; - unsigned long flags; - struct bfin_mac_local *lp = - container_of(ptp, struct bfin_mac_local, caps); - - spin_lock_irqsave(&lp->phc_lock, flags); - - ns = bfin_ptp_time_read(lp); - - spin_unlock_irqrestore(&lp->phc_lock, flags); - - *ts = ns_to_timespec64(ns); - - return 0; -} - -static int bfin_ptp_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) -{ - u64 ns; - unsigned long flags; - struct bfin_mac_local *lp = - container_of(ptp, struct bfin_mac_local, caps); - - ns = timespec64_to_ns(ts); - - spin_lock_irqsave(&lp->phc_lock, flags); - - bfin_ptp_time_write(lp, ns); - - spin_unlock_irqrestore(&lp->phc_lock, flags); - - return 0; -} - -static int bfin_ptp_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) -{ - return -EOPNOTSUPP; -} - -static const struct ptp_clock_info bfin_ptp_caps = { - .owner = THIS_MODULE, - .name = "BF518 clock", - .max_adj = 0, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .n_pins = 0, - .pps = 0, - .adjfreq = bfin_ptp_adjfreq, - .adjtime = bfin_ptp_adjtime, - .gettime64 = bfin_ptp_gettime, - .settime64 = bfin_ptp_settime, - .enable = bfin_ptp_enable, -}; - -static int bfin_phc_init(struct net_device *netdev, struct device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(netdev); - - lp->caps = bfin_ptp_caps; - lp->caps.max_adj = lp->max_ppb; - lp->clock = ptp_clock_register(&lp->caps, dev); - if (IS_ERR(lp->clock)) - return PTR_ERR(lp->clock); - - lp->phc_index = ptp_clock_index(lp->clock); - spin_lock_init(&lp->phc_lock); - - return 0; -} - -static void bfin_phc_release(struct bfin_mac_local *lp) -{ - ptp_clock_unregister(lp->clock); -} - -#else -# define bfin_mac_hwtstamp_is_none(cfg) 0 -# define bfin_mac_hwtstamp_init(dev) -# define bfin_mac_hwtstamp_set(dev, ifr) (-EOPNOTSUPP) -# define bfin_mac_hwtstamp_get(dev, ifr) (-EOPNOTSUPP) -# define bfin_rx_hwtstamp(dev, skb) -# define bfin_tx_hwtstamp(dev, skb) -# define bfin_phc_init(netdev, dev) 0 -# define bfin_phc_release(lp) -#endif - -static inline void _tx_reclaim_skb(void) -{ - do { - tx_list_head->desc_a.config &= ~DMAEN; - tx_list_head->status.status_word = 0; - if (tx_list_head->skb) { - dev_consume_skb_any(tx_list_head->skb); - tx_list_head->skb = NULL; - } - tx_list_head = tx_list_head->next; - - } while (tx_list_head->status.status_word != 0); -} - -static void tx_reclaim_skb(struct bfin_mac_local *lp) -{ - int timeout_cnt = MAX_TIMEOUT_CNT; - - if (tx_list_head->status.status_word != 0) - _tx_reclaim_skb(); - - if (current_tx_ptr->next == tx_list_head) { - while (tx_list_head->status.status_word == 0) { - /* slow down polling to avoid too many queue stop. */ - udelay(10); - /* reclaim skb if DMA is not running. */ - if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) - break; - if (timeout_cnt-- < 0) - break; - } - - if (timeout_cnt >= 0) - _tx_reclaim_skb(); - else - netif_stop_queue(lp->ndev); - } - - if (current_tx_ptr->next != tx_list_head && - netif_queue_stopped(lp->ndev)) - netif_wake_queue(lp->ndev); - - if (tx_list_head != current_tx_ptr) { - /* shorten the timer interval if tx queue is stopped */ - if (netif_queue_stopped(lp->ndev)) - lp->tx_reclaim_timer.expires = - jiffies + (TX_RECLAIM_JIFFIES >> 4); - else - lp->tx_reclaim_timer.expires = - jiffies + TX_RECLAIM_JIFFIES; - - mod_timer(&lp->tx_reclaim_timer, - lp->tx_reclaim_timer.expires); - } - - return; -} - -static void tx_reclaim_skb_timeout(struct timer_list *t) -{ - struct bfin_mac_local *lp = from_timer(lp, t, tx_reclaim_timer); - - tx_reclaim_skb(lp); -} - -static int bfin_mac_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - u16 *data; - u32 data_align = (unsigned long)(skb->data) & 0x3; - - current_tx_ptr->skb = skb; - - if (data_align == 0x2) { - /* move skb->data to current_tx_ptr payload */ - data = (u16 *)(skb->data) - 1; - *data = (u16)(skb->len); - /* - * When transmitting an Ethernet packet, the PTP_TSYNC module requires - * a DMA_Length_Word field associated with the packet. The lower 12 bits - * of this field are the length of the packet payload in bytes and the higher - * 4 bits are the timestamping enable field. - */ - if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) - *data |= 0x1000; - - current_tx_ptr->desc_a.start_addr = (u32)data; - /* this is important! */ - blackfin_dcache_flush_range((u32)data, - (u32)((u8 *)data + skb->len + 4)); - } else { - *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); - /* enable timestamping for the sent packet */ - if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) - *((u16 *)(current_tx_ptr->packet)) |= 0x1000; - memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, - skb->len); - current_tx_ptr->desc_a.start_addr = - (u32)current_tx_ptr->packet; - blackfin_dcache_flush_range( - (u32)current_tx_ptr->packet, - (u32)(current_tx_ptr->packet + skb->len + 2)); - } - - /* make sure the internal data buffers in the core are drained - * so that the DMA descriptors are completely written when the - * DMA engine goes to fetch them below - */ - SSYNC(); - - /* always clear status buffer before start tx dma */ - current_tx_ptr->status.status_word = 0; - - /* enable this packet's dma */ - current_tx_ptr->desc_a.config |= DMAEN; - - /* tx dma is running, just return */ - if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN) - goto out; - - /* tx dma is not running */ - bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a)); - /* dma enabled, read from memory, size is 6 */ - bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config); - /* Turn on the EMAC tx */ - bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); - -out: - bfin_tx_hwtstamp(dev, skb); - - current_tx_ptr = current_tx_ptr->next; - dev->stats.tx_packets++; - dev->stats.tx_bytes += (skb->len); - - tx_reclaim_skb(lp); - - return NETDEV_TX_OK; -} - -#define IP_HEADER_OFF 0 -#define RX_ERROR_MASK (RX_LONG | RX_ALIGN | RX_CRC | RX_LEN | \ - RX_FRAG | RX_ADDR | RX_DMAO | RX_PHY | RX_LATE | RX_RANGE) - -static void bfin_mac_rx(struct bfin_mac_local *lp) -{ - struct net_device *dev = lp->ndev; - struct sk_buff *skb, *new_skb; - unsigned short len; -#if defined(BFIN_MAC_CSUM_OFFLOAD) - unsigned int i; - unsigned char fcs[ETH_FCS_LEN + 1]; -#endif - - /* check if frame status word reports an error condition - * we which case we simply drop the packet - */ - if (current_rx_ptr->status.status_word & RX_ERROR_MASK) { - netdev_notice(dev, "rx: receive error - packet dropped\n"); - dev->stats.rx_dropped++; - goto out; - } - - /* allocate a new skb for next time receive */ - skb = current_rx_ptr->skb; - - new_skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN); - if (!new_skb) { - dev->stats.rx_dropped++; - goto out; - } - /* reserve 2 bytes for RXDWA padding */ - skb_reserve(new_skb, NET_IP_ALIGN); - /* Invalidate the data cache of skb->data range when it is write back - * cache. It will prevent overwriting the new data from DMA - */ - blackfin_dcache_invalidate_range((unsigned long)new_skb->head, - (unsigned long)new_skb->end); - - current_rx_ptr->skb = new_skb; - current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; - - len = (unsigned short)(current_rx_ptr->status.status_word & RX_FRLEN); - /* Deduce Ethernet FCS length from Ethernet payload length */ - len -= ETH_FCS_LEN; - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, dev); - - bfin_rx_hwtstamp(dev, skb); - -#if defined(BFIN_MAC_CSUM_OFFLOAD) - /* Checksum offloading only works for IPv4 packets with the standard IP header - * length of 20 bytes, because the blackfin MAC checksum calculation is - * based on that assumption. We must NOT use the calculated checksum if our - * IP version or header break that assumption. - */ - if (skb->data[IP_HEADER_OFF] == 0x45) { - skb->csum = current_rx_ptr->status.ip_payload_csum; - /* - * Deduce Ethernet FCS from hardware generated IP payload checksum. - * IP checksum is based on 16-bit one's complement algorithm. - * To deduce a value from checksum is equal to add its inversion. - * If the IP payload len is odd, the inversed FCS should also - * begin from odd address and leave first byte zero. - */ - if (skb->len % 2) { - fcs[0] = 0; - for (i = 0; i < ETH_FCS_LEN; i++) - fcs[i + 1] = ~skb->data[skb->len + i]; - skb->csum = csum_partial(fcs, ETH_FCS_LEN + 1, skb->csum); - } else { - for (i = 0; i < ETH_FCS_LEN; i++) - fcs[i] = ~skb->data[skb->len + i]; - skb->csum = csum_partial(fcs, ETH_FCS_LEN, skb->csum); - } - skb->ip_summed = CHECKSUM_COMPLETE; - } -#endif - - napi_gro_receive(&lp->napi, skb); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; -out: - current_rx_ptr->status.status_word = 0x00000000; - current_rx_ptr = current_rx_ptr->next; -} - -static int bfin_mac_poll(struct napi_struct *napi, int budget) -{ - int i = 0; - struct bfin_mac_local *lp = container_of(napi, - struct bfin_mac_local, - napi); - - while (current_rx_ptr->status.status_word != 0 && i < budget) { - bfin_mac_rx(lp); - i++; - } - - if (i < budget) { - napi_complete_done(napi, i); - if (test_and_clear_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags)) - enable_irq(IRQ_MAC_RX); - } - - return i; -} - -/* interrupt routine to handle rx and error signal */ -static irqreturn_t bfin_mac_interrupt(int irq, void *dev_id) -{ - struct bfin_mac_local *lp = netdev_priv(dev_id); - u32 status; - - status = bfin_read_DMA1_IRQ_STATUS(); - - bfin_write_DMA1_IRQ_STATUS(status | DMA_DONE | DMA_ERR); - if (status & DMA_DONE) { - disable_irq_nosync(IRQ_MAC_RX); - set_bit(BFIN_MAC_RX_IRQ_DISABLED, &lp->flags); - napi_schedule(&lp->napi); - } - - return IRQ_HANDLED; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void bfin_mac_poll_controller(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - - bfin_mac_interrupt(IRQ_MAC_RX, dev); - tx_reclaim_skb(lp); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static void bfin_mac_disable(void) -{ - unsigned int opmode; - - opmode = bfin_read_EMAC_OPMODE(); - opmode &= (~RE); - opmode &= (~TE); - /* Turn off the EMAC */ - bfin_write_EMAC_OPMODE(opmode); -} - -/* - * Enable Interrupts, Receive, and Transmit - */ -static int bfin_mac_enable(struct phy_device *phydev) -{ - int ret; - u32 opmode; - - pr_debug("%s\n", __func__); - - /* Set RX DMA */ - bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a)); - bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config); - - /* Wait MII done */ - ret = bfin_mdio_poll(); - if (ret) - return ret; - - /* We enable only RX here */ - /* ASTP : Enable Automatic Pad Stripping - PR : Promiscuous Mode for test - PSF : Receive frames with total length less than 64 bytes. - FDMODE : Full Duplex Mode - LB : Internal Loopback for test - RE : Receiver Enable */ - opmode = bfin_read_EMAC_OPMODE(); - if (opmode & FDMODE) - opmode |= PSF; - else - opmode |= DRO | DC | PSF; - opmode |= RE; - - if (phydev->interface == PHY_INTERFACE_MODE_RMII) { - opmode |= RMII; /* For Now only 100MBit are supported */ -#if defined(CONFIG_BF537) || defined(CONFIG_BF536) - if (__SILICON_REVISION__ < 3) { - /* - * This isn't publicly documented (fun times!), but in - * silicon <=0.2, the RX and TX pins are clocked together. - * So in order to recv, we must enable the transmit side - * as well. This will cause a spurious TX interrupt too, - * but we can easily consume that. - */ - opmode |= TE; - } -#endif - } - - /* Turn on the EMAC rx */ - bfin_write_EMAC_OPMODE(opmode); - - return 0; -} - -/* Our watchdog timed out. Called by the networking layer */ -static void bfin_mac_timeout(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - - pr_debug("%s: %s\n", dev->name, __func__); - - bfin_mac_disable(); - - del_timer(&lp->tx_reclaim_timer); - - /* reset tx queue and free skb */ - while (tx_list_head != current_tx_ptr) { - tx_list_head->desc_a.config &= ~DMAEN; - tx_list_head->status.status_word = 0; - if (tx_list_head->skb) { - dev_kfree_skb(tx_list_head->skb); - tx_list_head->skb = NULL; - } - tx_list_head = tx_list_head->next; - } - - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - - bfin_mac_enable(dev->phydev); - - /* We can accept TX packets again */ - netif_trans_update(dev); /* prevent tx timeout */ -} - -static void bfin_mac_multicast_hash(struct net_device *dev) -{ - u32 emac_hashhi, emac_hashlo; - struct netdev_hw_addr *ha; - u32 crc; - - emac_hashhi = emac_hashlo = 0; - - netdev_for_each_mc_addr(ha, dev) { - crc = ether_crc(ETH_ALEN, ha->addr); - crc >>= 26; - - if (crc & 0x20) - emac_hashhi |= 1 << (crc & 0x1f); - else - emac_hashlo |= 1 << (crc & 0x1f); - } - - bfin_write_EMAC_HASHHI(emac_hashhi); - bfin_write_EMAC_HASHLO(emac_hashlo); -} - -/* - * This routine will, depending on the values passed to it, - * either make it accept multicast packets, go into - * promiscuous mode (for TCPDUMP and cousins) or accept - * a select set of multicast packets - */ -static void bfin_mac_set_multicast_list(struct net_device *dev) -{ - u32 sysctl; - - if (dev->flags & IFF_PROMISC) { - netdev_info(dev, "set promisc mode\n"); - sysctl = bfin_read_EMAC_OPMODE(); - sysctl |= PR; - bfin_write_EMAC_OPMODE(sysctl); - } else if (dev->flags & IFF_ALLMULTI) { - /* accept all multicast */ - sysctl = bfin_read_EMAC_OPMODE(); - sysctl |= PAM; - bfin_write_EMAC_OPMODE(sysctl); - } else if (!netdev_mc_empty(dev)) { - /* set up multicast hash table */ - sysctl = bfin_read_EMAC_OPMODE(); - sysctl |= HM; - bfin_write_EMAC_OPMODE(sysctl); - bfin_mac_multicast_hash(dev); - } else { - /* clear promisc or multicast mode */ - sysctl = bfin_read_EMAC_OPMODE(); - sysctl &= ~(RAF | PAM); - bfin_write_EMAC_OPMODE(sysctl); - } -} - -static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - if (!netif_running(netdev)) - return -EINVAL; - - switch (cmd) { - case SIOCSHWTSTAMP: - return bfin_mac_hwtstamp_set(netdev, ifr); - case SIOCGHWTSTAMP: - return bfin_mac_hwtstamp_get(netdev, ifr); - default: - if (netdev->phydev) - return phy_mii_ioctl(netdev->phydev, ifr, cmd); - else - return -EOPNOTSUPP; - } -} - -/* - * this puts the device in an inactive state - */ -static void bfin_mac_shutdown(struct net_device *dev) -{ - /* Turn off the EMAC */ - bfin_write_EMAC_OPMODE(0x00000000); - /* Turn off the EMAC RX DMA */ - bfin_write_DMA1_CONFIG(0x0000); - bfin_write_DMA2_CONFIG(0x0000); -} - -/* - * Open and Initialize the interface - * - * Set up everything, reset the card, etc.. - */ -static int bfin_mac_open(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - int ret; - pr_debug("%s: %s\n", dev->name, __func__); - - /* - * Check that the address is valid. If its not, refuse - * to bring the device up. The user must specify an - * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx - */ - if (!is_valid_ether_addr(dev->dev_addr)) { - netdev_warn(dev, "no valid ethernet hw addr\n"); - return -EINVAL; - } - - /* initial rx and tx list */ - ret = desc_list_init(dev); - if (ret) - return ret; - - phy_start(dev->phydev); - setup_system_regs(dev); - setup_mac_addr(dev->dev_addr); - - bfin_mac_disable(); - ret = bfin_mac_enable(dev->phydev); - if (ret) - return ret; - pr_debug("hardware init finished\n"); - - napi_enable(&lp->napi); - netif_start_queue(dev); - netif_carrier_on(dev); - - return 0; -} - -/* - * this makes the board clean up everything that it can - * and not talk to the outside world. Caused by - * an 'ifconfig ethX down' - */ -static int bfin_mac_close(struct net_device *dev) -{ - struct bfin_mac_local *lp = netdev_priv(dev); - pr_debug("%s: %s\n", dev->name, __func__); - - netif_stop_queue(dev); - napi_disable(&lp->napi); - netif_carrier_off(dev); - - phy_stop(dev->phydev); - phy_write(dev->phydev, MII_BMCR, BMCR_PDOWN); - - /* clear everything */ - bfin_mac_shutdown(dev); - - /* free the rx/tx buffers */ - desc_list_free(); - - return 0; -} - -static const struct net_device_ops bfin_mac_netdev_ops = { - .ndo_open = bfin_mac_open, - .ndo_stop = bfin_mac_close, - .ndo_start_xmit = bfin_mac_hard_start_xmit, - .ndo_set_mac_address = bfin_mac_set_mac_address, - .ndo_tx_timeout = bfin_mac_timeout, - .ndo_set_rx_mode = bfin_mac_set_multicast_list, - .ndo_do_ioctl = bfin_mac_ioctl, - .ndo_validate_addr = eth_validate_addr, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = bfin_mac_poll_controller, -#endif -}; - -static int bfin_mac_probe(struct platform_device *pdev) -{ - struct net_device *ndev; - struct bfin_mac_local *lp; - struct platform_device *pd; - struct bfin_mii_bus_platform_data *mii_bus_data; - int rc; - - ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); - if (!ndev) - return -ENOMEM; - - SET_NETDEV_DEV(ndev, &pdev->dev); - platform_set_drvdata(pdev, ndev); - lp = netdev_priv(ndev); - lp->ndev = ndev; - - /* Grab the MAC address in the MAC */ - *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); - *(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI()); - - /* probe mac */ - /*todo: how to probe? which is revision_register */ - bfin_write_EMAC_ADDRLO(0x12345678); - if (bfin_read_EMAC_ADDRLO() != 0x12345678) { - dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n"); - rc = -ENODEV; - goto out_err_probe_mac; - } - - - /* - * Is it valid? (Did bootloader initialize it?) - * Grab the MAC from the board somehow - * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c - */ - if (!is_valid_ether_addr(ndev->dev_addr)) { - if (bfin_get_ether_addr(ndev->dev_addr) || - !is_valid_ether_addr(ndev->dev_addr)) { - /* Still not valid, get a random one */ - netdev_warn(ndev, "Setting Ethernet MAC to a random one\n"); - eth_hw_addr_random(ndev); - } - } - - setup_mac_addr(ndev->dev_addr); - - if (!dev_get_platdata(&pdev->dev)) { - dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n"); - rc = -ENODEV; - goto out_err_probe_mac; - } - pd = dev_get_platdata(&pdev->dev); - lp->mii_bus = platform_get_drvdata(pd); - if (!lp->mii_bus) { - dev_err(&pdev->dev, "Cannot get mii_bus!\n"); - rc = -ENODEV; - goto out_err_probe_mac; - } - lp->mii_bus->priv = ndev; - mii_bus_data = dev_get_platdata(&pd->dev); - - rc = mii_probe(ndev, mii_bus_data->phy_mode); - if (rc) { - dev_err(&pdev->dev, "MII Probe failed!\n"); - goto out_err_mii_probe; - } - - lp->vlan1_mask = ETH_P_8021Q | mii_bus_data->vlan1_mask; - lp->vlan2_mask = ETH_P_8021Q | mii_bus_data->vlan2_mask; - - ndev->netdev_ops = &bfin_mac_netdev_ops; - ndev->ethtool_ops = &bfin_mac_ethtool_ops; - - timer_setup(&lp->tx_reclaim_timer, tx_reclaim_skb_timeout, 0); - - lp->flags = 0; - netif_napi_add(ndev, &lp->napi, bfin_mac_poll, CONFIG_BFIN_RX_DESC_NUM); - - spin_lock_init(&lp->lock); - - /* now, enable interrupts */ - /* register irq handler */ - rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, - 0, "EMAC_RX", ndev); - if (rc) { - dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); - rc = -EBUSY; - goto out_err_request_irq; - } - - rc = register_netdev(ndev); - if (rc) { - dev_err(&pdev->dev, "Cannot register net device!\n"); - goto out_err_reg_ndev; - } - - bfin_mac_hwtstamp_init(ndev); - rc = bfin_phc_init(ndev, &pdev->dev); - if (rc) { - dev_err(&pdev->dev, "Cannot register PHC device!\n"); - goto out_err_phc; - } - - /* now, print out the card info, in a short format.. */ - netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION); - - return 0; - -out_err_phc: -out_err_reg_ndev: - free_irq(IRQ_MAC_RX, ndev); -out_err_request_irq: - netif_napi_del(&lp->napi); -out_err_mii_probe: - mdiobus_unregister(lp->mii_bus); - mdiobus_free(lp->mii_bus); -out_err_probe_mac: - free_netdev(ndev); - - return rc; -} - -static int bfin_mac_remove(struct platform_device *pdev) -{ - struct net_device *ndev = platform_get_drvdata(pdev); - struct bfin_mac_local *lp = netdev_priv(ndev); - - bfin_phc_release(lp); - - lp->mii_bus->priv = NULL; - - unregister_netdev(ndev); - - netif_napi_del(&lp->napi); - - free_irq(IRQ_MAC_RX, ndev); - - free_netdev(ndev); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - struct net_device *net_dev = platform_get_drvdata(pdev); - struct bfin_mac_local *lp = netdev_priv(net_dev); - - if (lp->wol) { - bfin_write_EMAC_OPMODE((bfin_read_EMAC_OPMODE() & ~TE) | RE); - bfin_write_EMAC_WKUP_CTL(MPKE); - enable_irq_wake(IRQ_MAC_WAKEDET); - } else { - if (netif_running(net_dev)) - bfin_mac_close(net_dev); - } - - return 0; -} - -static int bfin_mac_resume(struct platform_device *pdev) -{ - struct net_device *net_dev = platform_get_drvdata(pdev); - struct bfin_mac_local *lp = netdev_priv(net_dev); - - if (lp->wol) { - bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); - bfin_write_EMAC_WKUP_CTL(0); - disable_irq_wake(IRQ_MAC_WAKEDET); - } else { - if (netif_running(net_dev)) - bfin_mac_open(net_dev); - } - - return 0; -} -#else -#define bfin_mac_suspend NULL -#define bfin_mac_resume NULL -#endif /* CONFIG_PM */ - -static int bfin_mii_bus_probe(struct platform_device *pdev) -{ - struct mii_bus *miibus; - struct bfin_mii_bus_platform_data *mii_bus_pd; - const unsigned short *pin_req; - int rc, i; - - mii_bus_pd = dev_get_platdata(&pdev->dev); - if (!mii_bus_pd) { - dev_err(&pdev->dev, "No peripherals in platform data!\n"); - return -EINVAL; - } - - /* - * We are setting up a network card, - * so set the GPIO pins to Ethernet mode - */ - pin_req = mii_bus_pd->mac_peripherals; - rc = peripheral_request_list(pin_req, KBUILD_MODNAME); - if (rc) { - dev_err(&pdev->dev, "Requesting peripherals failed!\n"); - return rc; - } - - rc = -ENOMEM; - miibus = mdiobus_alloc(); - if (miibus == NULL) - goto out_err_alloc; - miibus->read = bfin_mdiobus_read; - miibus->write = bfin_mdiobus_write; - - miibus->parent = &pdev->dev; - miibus->name = "bfin_mii_bus"; - miibus->phy_mask = mii_bus_pd->phy_mask; - - snprintf(miibus->id, MII_BUS_ID_SIZE, "%s-%x", - pdev->name, pdev->id); - - rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR); - if (rc != mii_bus_pd->phydev_number) - dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n", - mii_bus_pd->phydev_number); - for (i = 0; i < rc; ++i) { - unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr; - if (phyaddr < PHY_MAX_ADDR) - miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq; - else - dev_err(&pdev->dev, - "Invalid PHY address %i for phydev %i\n", - phyaddr, i); - } - - rc = mdiobus_register(miibus); - if (rc) { - dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); - goto out_err_irq_alloc; - } - - platform_set_drvdata(pdev, miibus); - return 0; - -out_err_irq_alloc: - mdiobus_free(miibus); -out_err_alloc: - peripheral_free_list(pin_req); - - return rc; -} - -static int bfin_mii_bus_remove(struct platform_device *pdev) -{ - struct mii_bus *miibus = platform_get_drvdata(pdev); - struct bfin_mii_bus_platform_data *mii_bus_pd = - dev_get_platdata(&pdev->dev); - - mdiobus_unregister(miibus); - mdiobus_free(miibus); - peripheral_free_list(mii_bus_pd->mac_peripherals); - - return 0; -} - -static struct platform_driver bfin_mii_bus_driver = { - .probe = bfin_mii_bus_probe, - .remove = bfin_mii_bus_remove, - .driver = { - .name = "bfin_mii_bus", - }, -}; - -static struct platform_driver bfin_mac_driver = { - .probe = bfin_mac_probe, - .remove = bfin_mac_remove, - .resume = bfin_mac_resume, - .suspend = bfin_mac_suspend, - .driver = { - .name = KBUILD_MODNAME, - }, -}; - -static struct platform_driver * const drivers[] = { - &bfin_mii_bus_driver, - &bfin_mac_driver, -}; - -static int __init bfin_mac_init(void) -{ - return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); -} - -module_init(bfin_mac_init); - -static void __exit bfin_mac_cleanup(void) -{ - platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); -} - -module_exit(bfin_mac_cleanup); - diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h deleted file mode 100644 index 4ad5b9be3f84..000000000000 --- a/drivers/net/ethernet/adi/bfin_mac.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Blackfin On-Chip MAC Driver - * - * Copyright 2004-2007 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ -#ifndef _BFIN_MAC_H_ -#define _BFIN_MAC_H_ - -#include <linux/net_tstamp.h> -#include <linux/ptp_clock_kernel.h> -#include <linux/timer.h> -#include <linux/etherdevice.h> -#include <linux/bfin_mac.h> - -/* - * Disable hardware checksum for bug #5600 if writeback cache is - * enabled. Otherwize, corrupted RX packet will be sent up stack - * without error mark. - */ -#ifndef CONFIG_BFIN_EXTMEM_WRITEBACK -#define BFIN_MAC_CSUM_OFFLOAD -#endif - -#define TX_RECLAIM_JIFFIES (HZ / 5) -#define BFIN_MAC_RX_IRQ_DISABLED 1 - -struct dma_descriptor { - struct dma_descriptor *next_dma_desc; - unsigned long start_addr; - unsigned short config; - unsigned short x_count; -}; - -struct status_area_rx { -#if defined(BFIN_MAC_CSUM_OFFLOAD) - unsigned short ip_hdr_csum; /* ip header checksum */ - /* ip payload(udp or tcp or others) checksum */ - unsigned short ip_payload_csum; -#endif - unsigned long status_word; /* the frame status word */ -}; - -struct status_area_tx { - unsigned long status_word; /* the frame status word */ -}; - -/* use two descriptors for a packet */ -struct net_dma_desc_rx { - struct net_dma_desc_rx *next; - struct sk_buff *skb; - struct dma_descriptor desc_a; - struct dma_descriptor desc_b; - struct status_area_rx status; -}; - -/* use two descriptors for a packet */ -struct net_dma_desc_tx { - struct net_dma_desc_tx *next; - struct sk_buff *skb; - struct dma_descriptor desc_a; - struct dma_descriptor desc_b; - unsigned char packet[1560]; - struct status_area_tx status; -}; - -struct bfin_mac_local { - spinlock_t lock; - - int wol; /* Wake On Lan */ - int irq_wake_requested; - struct timer_list tx_reclaim_timer; - struct net_device *ndev; - struct napi_struct napi; - unsigned long flags; - - /* Data for EMAC_VLAN1 regs */ - u16 vlan1_mask, vlan2_mask; - - /* MII and PHY stuffs */ - int old_link; /* used by bf537_adjust_link */ - int old_speed; - int old_duplex; - - struct mii_bus *mii_bus; - -#if defined(CONFIG_BFIN_MAC_USE_HWSTAMP) - u32 addend; - unsigned int shift; - s32 max_ppb; - struct hwtstamp_config stamp_cfg; - struct ptp_clock_info caps; - struct ptp_clock *clock; - int phc_index; - spinlock_t phc_lock; /* protects time lo/hi registers */ -#endif -}; - -int bfin_get_ether_addr(char *addr); - -#endif diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig index 7ec2d74f94d3..680a6d983f37 100644 --- a/drivers/net/ethernet/davicom/Kconfig +++ b/drivers/net/ethernet/davicom/Kconfig @@ -4,7 +4,7 @@ config DM9000 tristate "DM9000 support" - depends on ARM || BLACKFIN || MIPS || COLDFIRE || NIOS2 + depends on ARM || MIPS || COLDFIRE || NIOS2 select CRC32 select MII ---help--- diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index 4c2f612e4414..358820282ef0 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -5,8 +5,8 @@ config NET_VENDOR_SMSC bool "SMC (SMSC)/Western Digital devices" default y - depends on ARM || ARM64 || ATARI_ETHERNAT || BLACKFIN || COLDFIRE || \ - ISA || M32R || MAC || MIPS || MN10300 || NIOS2 || PCI || \ + depends on ARM || ARM64 || ATARI_ETHERNAT || COLDFIRE || \ + ISA || MAC || MIPS || NIOS2 || PCI || \ PCMCIA || SUPERH || XTENSA || H8300 ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -37,8 +37,8 @@ config SMC91X select CRC32 select MII depends on !OF || GPIOLIB - depends on ARM || ARM64 || ATARI_ETHERNAT || BLACKFIN || COLDFIRE || \ - M32R || MIPS || MN10300 || NIOS2 || SUPERH || XTENSA || H8300 + depends on ARM || ARM64 || ATARI_ETHERNAT || COLDFIRE || \ + MIPS || NIOS2 || SUPERH || XTENSA || H8300 ---help--- This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it @@ -77,7 +77,7 @@ config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 select MII - depends on (ARM || SUPERH || MN10300) + depends on (ARM || SUPERH) ---help--- This is a driver for SMSC's LAN911x series of Ethernet chipsets including the new LAN9115, LAN9116, LAN9117, and LAN9118. diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 08b17adf0a65..b337ee97e0c0 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -144,32 +144,6 @@ static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg, #define SMC_IRQ_FLAGS (0) -#elif defined(CONFIG_M32R) - -#define SMC_CAN_USE_8BIT 0 -#define SMC_CAN_USE_16BIT 1 -#define SMC_CAN_USE_32BIT 0 - -#define SMC_inb(a, r) inb(((u32)a) + (r)) -#define SMC_inw(a, r) inw(((u32)a) + (r)) -#define SMC_outb(v, a, r) outb(v, ((u32)a) + (r)) -#define SMC_outw(lp, v, a, r) outw(v, ((u32)a) + (r)) -#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) -#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) - -#define SMC_IRQ_FLAGS (0) - -#define RPC_LSA_DEFAULT RPC_LED_TX_RX -#define RPC_LSB_DEFAULT RPC_LED_100_10 - -#elif defined(CONFIG_MN10300) - -/* - * MN10300/AM33 configuration - */ - -#include <unit/smc91111.h> - #elif defined(CONFIG_ATARI) #define SMC_CAN_USE_8BIT 1 diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig deleted file mode 100644 index bdfeaf3d4fce..000000000000 --- a/drivers/net/ethernet/tile/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -# -# Tilera network device configuration -# - -config TILE_NET - tristate "Tilera GBE/XGBE network driver support" - depends on TILE - default y - select CRC32 - select TILE_GXIO_MPIPE if TILEGX - select HIGH_RES_TIMERS if TILEGX - imply PTP_1588_CLOCK if TILEGX - ---help--- - This is a standard Linux network device driver for the - on-chip Tilera Gigabit Ethernet and XAUI interfaces. - - To compile this driver as a module, choose M here: the module - will be called tile_net. diff --git a/drivers/net/ethernet/tile/Makefile b/drivers/net/ethernet/tile/Makefile deleted file mode 100644 index 3d0ae1f07fc9..000000000000 --- a/drivers/net/ethernet/tile/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the TILE on-chip networking support. -# - -obj-$(CONFIG_TILE_NET) += tile_net.o -ifdef CONFIG_TILEGX -tile_net-y := tilegx.o -else -tile_net-y := tilepro.o -endif diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c deleted file mode 100644 index b3e5816a4678..000000000000 --- a/drivers/net/ethernet/tile/tilegx.c +++ /dev/null @@ -1,2279 +0,0 @@ -/* - * Copyright 2012 Tilera Corporation. All Rights Reserved. - * - * 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. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/moduleparam.h> -#include <linux/sched.h> -#include <linux/kernel.h> /* printk() */ -#include <linux/slab.h> /* kmalloc() */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/irq.h> -#include <linux/netdevice.h> /* struct device, and other headers */ -#include <linux/etherdevice.h> /* eth_type_trans */ -#include <linux/skbuff.h> -#include <linux/ioctl.h> -#include <linux/cdev.h> -#include <linux/hugetlb.h> -#include <linux/in6.h> -#include <linux/timer.h> -#include <linux/hrtimer.h> -#include <linux/ktime.h> -#include <linux/io.h> -#include <linux/ctype.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/tcp.h> -#include <linux/net_tstamp.h> -#include <linux/ptp_clock_kernel.h> -#include <linux/sched/isolation.h> - -#include <asm/checksum.h> -#include <asm/homecache.h> -#include <gxio/mpipe.h> -#include <arch/sim.h> - -/* Default transmit lockup timeout period, in jiffies. */ -#define TILE_NET_TIMEOUT (5 * HZ) - -/* The maximum number of distinct channels (idesc.channel is 5 bits). */ -#define TILE_NET_CHANNELS 32 - -/* Maximum number of idescs to handle per "poll". */ -#define TILE_NET_BATCH 128 - -/* Maximum number of packets to handle per "poll". */ -#define TILE_NET_WEIGHT 64 - -/* Maximum Jumbo Packet MTU */ -#define TILE_JUMBO_MAX_MTU 9000 - -/* Number of entries in each iqueue. */ -#define IQUEUE_ENTRIES 512 - -/* Number of entries in each equeue. */ -#define EQUEUE_ENTRIES 2048 - -/* Total header bytes per equeue slot. Must be big enough for 2 bytes - * of NET_IP_ALIGN alignment, plus 14 bytes (?) of L2 header, plus up to - * 60 bytes of actual TCP header. We round up to align to cache lines. - */ -#define HEADER_BYTES 128 - -/* Maximum completions per cpu per device (must be a power of two). - * ISSUE: What is the right number here? If this is too small, then - * egress might block waiting for free space in a completions array. - * ISSUE: At the least, allocate these only for initialized echannels. - */ -#define TILE_NET_MAX_COMPS 64 - -#define MAX_FRAGS (MAX_SKB_FRAGS + 1) - -/* The "kinds" of buffer stacks (small/large/jumbo). */ -#define MAX_KINDS 3 - -/* Size of completions data to allocate. - * ISSUE: Probably more than needed since we don't use all the channels. - */ -#define COMPS_SIZE (TILE_NET_CHANNELS * sizeof(struct tile_net_comps)) - -/* Size of NotifRing data to allocate. */ -#define NOTIF_RING_SIZE (IQUEUE_ENTRIES * sizeof(gxio_mpipe_idesc_t)) - -/* Timeout to wake the per-device TX timer after we stop the queue. - * We don't want the timeout too short (adds overhead, and might end - * up causing stop/wake/stop/wake cycles) or too long (affects performance). - * For the 10 Gb NIC, 30 usec means roughly 30+ 1500-byte packets. - */ -#define TX_TIMER_DELAY_USEC 30 - -/* Timeout to wake the per-cpu egress timer to free completions. */ -#define EGRESS_TIMER_DELAY_USEC 1000 - -MODULE_AUTHOR("Tilera Corporation"); -MODULE_LICENSE("GPL"); - -/* A "packet fragment" (a chunk of memory). */ -struct frag { - void *buf; - size_t length; -}; - -/* A single completion. */ -struct tile_net_comp { - /* The "complete_count" when the completion will be complete. */ - s64 when; - /* The buffer to be freed when the completion is complete. */ - struct sk_buff *skb; -}; - -/* The completions for a given cpu and echannel. */ -struct tile_net_comps { - /* The completions. */ - struct tile_net_comp comp_queue[TILE_NET_MAX_COMPS]; - /* The number of completions used. */ - unsigned long comp_next; - /* The number of completions freed. */ - unsigned long comp_last; -}; - -/* The transmit wake timer for a given cpu and echannel. */ -struct tile_net_tx_wake { - int tx_queue_idx; - struct hrtimer timer; - struct net_device *dev; -}; - -/* Info for a specific cpu. */ -struct tile_net_info { - /* Our cpu. */ - int my_cpu; - /* A timer for handling egress completions. */ - struct hrtimer egress_timer; - /* True if "egress_timer" is scheduled. */ - bool egress_timer_scheduled; - struct info_mpipe { - /* Packet queue. */ - gxio_mpipe_iqueue_t iqueue; - /* The NAPI struct. */ - struct napi_struct napi; - /* Number of buffers (by kind) which must still be provided. */ - unsigned int num_needed_buffers[MAX_KINDS]; - /* instance id. */ - int instance; - /* True if iqueue is valid. */ - bool has_iqueue; - /* NAPI flags. */ - bool napi_added; - bool napi_enabled; - /* Comps for each egress channel. */ - struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS]; - /* Transmit wake timer for each egress channel. */ - struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS]; - } mpipe[NR_MPIPE_MAX]; -}; - -/* Info for egress on a particular egress channel. */ -struct tile_net_egress { - /* The "equeue". */ - gxio_mpipe_equeue_t *equeue; - /* The headers for TSO. */ - unsigned char *headers; -}; - -/* Info for a specific device. */ -struct tile_net_priv { - /* Our network device. */ - struct net_device *dev; - /* The primary link. */ - gxio_mpipe_link_t link; - /* The primary channel, if open, else -1. */ - int channel; - /* The "loopify" egress link, if needed. */ - gxio_mpipe_link_t loopify_link; - /* The "loopify" egress channel, if open, else -1. */ - int loopify_channel; - /* The egress channel (channel or loopify_channel). */ - int echannel; - /* mPIPE instance, 0 or 1. */ - int instance; - /* The timestamp config. */ - struct hwtstamp_config stamp_cfg; -}; - -static struct mpipe_data { - /* The ingress irq. */ - int ingress_irq; - - /* The "context" for all devices. */ - gxio_mpipe_context_t context; - - /* Egress info, indexed by "priv->echannel" - * (lazily created as needed). - */ - struct tile_net_egress - egress_for_echannel[TILE_NET_CHANNELS]; - - /* Devices currently associated with each channel. - * NOTE: The array entry can become NULL after ifconfig down, but - * we do not free the underlying net_device structures, so it is - * safe to use a pointer after reading it from this array. - */ - struct net_device - *tile_net_devs_for_channel[TILE_NET_CHANNELS]; - - /* The actual memory allocated for the buffer stacks. */ - void *buffer_stack_vas[MAX_KINDS]; - - /* The amount of memory allocated for each buffer stack. */ - size_t buffer_stack_bytes[MAX_KINDS]; - - /* The first buffer stack index - * (small = +0, large = +1, jumbo = +2). - */ - int first_buffer_stack; - - /* The buckets. */ - int first_bucket; - int num_buckets; - - /* PTP-specific data. */ - struct ptp_clock *ptp_clock; - struct ptp_clock_info caps; - - /* Lock for ptp accessors. */ - struct mutex ptp_lock; - -} mpipe_data[NR_MPIPE_MAX] = { - [0 ... (NR_MPIPE_MAX - 1)] { - .ingress_irq = -1, - .first_buffer_stack = -1, - .first_bucket = -1, - .num_buckets = 1 - } -}; - -/* A mutex for "tile_net_devs_for_channel". */ -static DEFINE_MUTEX(tile_net_devs_for_channel_mutex); - -/* The per-cpu info. */ -static DEFINE_PER_CPU(struct tile_net_info, per_cpu_info); - - -/* The buffer size enums for each buffer stack. - * See arch/tile/include/gxio/mpipe.h for the set of possible values. - * We avoid the "10384" size because it can induce "false chaining" - * on "cut-through" jumbo packets. - */ -static gxio_mpipe_buffer_size_enum_t buffer_size_enums[MAX_KINDS] = { - GXIO_MPIPE_BUFFER_SIZE_128, - GXIO_MPIPE_BUFFER_SIZE_1664, - GXIO_MPIPE_BUFFER_SIZE_16384 -}; - -/* Text value of tile_net.cpus if passed as a module parameter. */ -static char *network_cpus_string; - -/* The actual cpus in "network_cpus". */ -static struct cpumask network_cpus_map; - -/* If "tile_net.loopify=LINK" was specified, this is "LINK". */ -static char *loopify_link_name; - -/* If "tile_net.custom" was specified, this is true. */ -static bool custom_flag; - -/* If "tile_net.jumbo=NUM" was specified, this is "NUM". */ -static uint jumbo_num; - -/* Obtain mpipe instance from struct tile_net_priv given struct net_device. */ -static inline int mpipe_instance(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - return priv->instance; -} - -/* The "tile_net.cpus" argument specifies the cpus that are dedicated - * to handle ingress packets. - * - * The parameter should be in the form "tile_net.cpus=m-n[,x-y]", where - * m, n, x, y are integer numbers that represent the cpus that can be - * neither a dedicated cpu nor a dataplane cpu. - */ -static bool network_cpus_init(void) -{ - int rc; - - if (network_cpus_string == NULL) - return false; - - rc = cpulist_parse_crop(network_cpus_string, &network_cpus_map); - if (rc != 0) { - pr_warn("tile_net.cpus=%s: malformed cpu list\n", - network_cpus_string); - return false; - } - - /* Remove dedicated cpus. */ - cpumask_and(&network_cpus_map, &network_cpus_map, cpu_possible_mask); - - if (cpumask_empty(&network_cpus_map)) { - pr_warn("Ignoring empty tile_net.cpus='%s'.\n", - network_cpus_string); - return false; - } - - pr_info("Linux network CPUs: %*pbl\n", - cpumask_pr_args(&network_cpus_map)); - return true; -} - -module_param_named(cpus, network_cpus_string, charp, 0444); -MODULE_PARM_DESC(cpus, "cpulist of cores that handle network interrupts"); - -/* The "tile_net.loopify=LINK" argument causes the named device to - * actually use "loop0" for ingress, and "loop1" for egress. This - * allows an app to sit between the actual link and linux, passing - * (some) packets along to linux, and forwarding (some) packets sent - * out by linux. - */ -module_param_named(loopify, loopify_link_name, charp, 0444); -MODULE_PARM_DESC(loopify, "name the device to use loop0/1 for ingress/egress"); - -/* The "tile_net.custom" argument causes us to ignore the "conventional" - * classifier metadata, in particular, the "l2_offset". - */ -module_param_named(custom, custom_flag, bool, 0444); -MODULE_PARM_DESC(custom, "indicates a (heavily) customized classifier"); - -/* The "tile_net.jumbo" argument causes us to support "jumbo" packets, - * and to allocate the given number of "jumbo" buffers. - */ -module_param_named(jumbo, jumbo_num, uint, 0444); -MODULE_PARM_DESC(jumbo, "the number of buffers to support jumbo packets"); - -/* Atomically update a statistics field. - * Note that on TILE-Gx, this operation is fire-and-forget on the - * issuing core (single-cycle dispatch) and takes only a few cycles - * longer than a regular store when the request reaches the home cache. - * No expensive bus management overhead is required. - */ -static void tile_net_stats_add(unsigned long value, unsigned long *field) -{ - BUILD_BUG_ON(sizeof(atomic_long_t) != sizeof(unsigned long)); - atomic_long_add(value, (atomic_long_t *)field); -} - -/* Allocate and push a buffer. */ -static bool tile_net_provide_buffer(int instance, int kind) -{ - struct mpipe_data *md = &mpipe_data[instance]; - gxio_mpipe_buffer_size_enum_t bse = buffer_size_enums[kind]; - size_t bs = gxio_mpipe_buffer_size_enum_to_buffer_size(bse); - const unsigned long buffer_alignment = 128; - struct sk_buff *skb; - int len; - - len = sizeof(struct sk_buff **) + buffer_alignment + bs; - skb = dev_alloc_skb(len); - if (skb == NULL) - return false; - - /* Make room for a back-pointer to 'skb' and guarantee alignment. */ - skb_reserve(skb, sizeof(struct sk_buff **)); - skb_reserve(skb, -(long)skb->data & (buffer_alignment - 1)); - - /* Save a back-pointer to 'skb'. */ - *(struct sk_buff **)(skb->data - sizeof(struct sk_buff **)) = skb; - - /* Make sure "skb" and the back-pointer have been flushed. */ - wmb(); - - gxio_mpipe_push_buffer(&md->context, md->first_buffer_stack + kind, - (void *)va_to_tile_io_addr(skb->data)); - - return true; -} - -/* Convert a raw mpipe buffer to its matching skb pointer. */ -static struct sk_buff *mpipe_buf_to_skb(void *va) -{ - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - /* Paranoia. */ - if (skb->data != va) { - /* Panic here since there's a reasonable chance - * that corrupt buffers means generic memory - * corruption, with unpredictable system effects. - */ - panic("Corrupt linux buffer! va=%p, skb=%p, skb->data=%p", - va, skb, skb->data); - } - - return skb; -} - -static void tile_net_pop_all_buffers(int instance, int stack) -{ - struct mpipe_data *md = &mpipe_data[instance]; - - for (;;) { - tile_io_addr_t addr = - (tile_io_addr_t)gxio_mpipe_pop_buffer(&md->context, - stack); - if (addr == 0) - break; - dev_kfree_skb_irq(mpipe_buf_to_skb(tile_io_addr_to_va(addr))); - } -} - -/* Provide linux buffers to mPIPE. */ -static void tile_net_provide_needed_buffers(void) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - int instance, kind; - for (instance = 0; instance < NR_MPIPE_MAX && - info->mpipe[instance].has_iqueue; instance++) { - for (kind = 0; kind < MAX_KINDS; kind++) { - while (info->mpipe[instance].num_needed_buffers[kind] - != 0) { - if (!tile_net_provide_buffer(instance, kind)) { - pr_notice("Tile %d still needs" - " some buffers\n", - info->my_cpu); - return; - } - info->mpipe[instance]. - num_needed_buffers[kind]--; - } - } - } -} - -/* Get RX timestamp, and store it in the skb. */ -static void tile_rx_timestamp(struct tile_net_priv *priv, struct sk_buff *skb, - gxio_mpipe_idesc_t *idesc) -{ - if (unlikely(priv->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)) { - struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); - memset(shhwtstamps, 0, sizeof(*shhwtstamps)); - shhwtstamps->hwtstamp = ktime_set(idesc->time_stamp_sec, - idesc->time_stamp_ns); - } -} - -/* Get TX timestamp, and store it in the skb. */ -static void tile_tx_timestamp(struct sk_buff *skb, int instance) -{ - struct skb_shared_info *shtx = skb_shinfo(skb); - if (unlikely((shtx->tx_flags & SKBTX_HW_TSTAMP) != 0)) { - struct mpipe_data *md = &mpipe_data[instance]; - struct skb_shared_hwtstamps shhwtstamps; - struct timespec64 ts; - - shtx->tx_flags |= SKBTX_IN_PROGRESS; - gxio_mpipe_get_timestamp(&md->context, &ts); - memset(&shhwtstamps, 0, sizeof(shhwtstamps)); - shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec); - skb_tstamp_tx(skb, &shhwtstamps); - } -} - -/* Use ioctl() to enable or disable TX or RX timestamping. */ -static int tile_hwtstamp_set(struct net_device *dev, struct ifreq *rq) -{ - struct hwtstamp_config config; - struct tile_net_priv *priv = netdev_priv(dev); - - if (copy_from_user(&config, rq->ifr_data, sizeof(config))) - return -EFAULT; - - if (config.flags) /* reserved for future extensions */ - return -EINVAL; - - switch (config.tx_type) { - case HWTSTAMP_TX_OFF: - case HWTSTAMP_TX_ON: - break; - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - break; - case HWTSTAMP_FILTER_ALL: - case HWTSTAMP_FILTER_SOME: - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_NTP_ALL: - config.rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - if (copy_to_user(rq->ifr_data, &config, sizeof(config))) - return -EFAULT; - - priv->stamp_cfg = config; - return 0; -} - -static int tile_hwtstamp_get(struct net_device *dev, struct ifreq *rq) -{ - struct tile_net_priv *priv = netdev_priv(dev); - - if (copy_to_user(rq->ifr_data, &priv->stamp_cfg, - sizeof(priv->stamp_cfg))) - return -EFAULT; - - return 0; -} - -static inline bool filter_packet(struct net_device *dev, void *buf) -{ - /* Filter packets received before we're up. */ - if (dev == NULL || !(dev->flags & IFF_UP)) - return true; - - /* Filter out packets that aren't for us. */ - if (!(dev->flags & IFF_PROMISC) && - !is_multicast_ether_addr(buf) && - !ether_addr_equal(dev->dev_addr, buf)) - return true; - - return false; -} - -static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, - gxio_mpipe_idesc_t *idesc, unsigned long len) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - int instance = priv->instance; - - /* Encode the actual packet length. */ - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, dev); - - /* Acknowledge "good" hardware checksums. */ - if (idesc->cs && idesc->csum_seed_val == 0xFFFF) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - /* Get RX timestamp from idesc. */ - tile_rx_timestamp(priv, skb, idesc); - - napi_gro_receive(&info->mpipe[instance].napi, skb); - - /* Update stats. */ - tile_net_stats_add(1, &dev->stats.rx_packets); - tile_net_stats_add(len, &dev->stats.rx_bytes); - - /* Need a new buffer. */ - if (idesc->size == buffer_size_enums[0]) - info->mpipe[instance].num_needed_buffers[0]++; - else if (idesc->size == buffer_size_enums[1]) - info->mpipe[instance].num_needed_buffers[1]++; - else - info->mpipe[instance].num_needed_buffers[2]++; -} - -/* Handle a packet. Return true if "processed", false if "filtered". */ -static bool tile_net_handle_packet(int instance, gxio_mpipe_idesc_t *idesc) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - struct mpipe_data *md = &mpipe_data[instance]; - struct net_device *dev = md->tile_net_devs_for_channel[idesc->channel]; - uint8_t l2_offset; - void *va; - void *buf; - unsigned long len; - bool filter; - - /* Drop packets for which no buffer was available (which can - * happen under heavy load), or for which the me/tr/ce flags - * are set (which can happen for jumbo cut-through packets, - * or with a customized classifier). - */ - if (idesc->be || idesc->me || idesc->tr || idesc->ce) { - if (dev) - tile_net_stats_add(1, &dev->stats.rx_errors); - goto drop; - } - - /* Get the "l2_offset", if allowed. */ - l2_offset = custom_flag ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc); - - /* Get the VA (including NET_IP_ALIGN bytes of "headroom"). */ - va = tile_io_addr_to_va((unsigned long)idesc->va); - - /* Get the actual packet start/length. */ - buf = va + l2_offset; - len = idesc->l2_size - l2_offset; - - /* Point "va" at the raw buffer. */ - va -= NET_IP_ALIGN; - - filter = filter_packet(dev, buf); - if (filter) { - if (dev) - tile_net_stats_add(1, &dev->stats.rx_dropped); -drop: - gxio_mpipe_iqueue_drop(&info->mpipe[instance].iqueue, idesc); - } else { - struct sk_buff *skb = mpipe_buf_to_skb(va); - - /* Skip headroom, and any custom header. */ - skb_reserve(skb, NET_IP_ALIGN + l2_offset); - - tile_net_receive_skb(dev, skb, idesc, len); - } - - gxio_mpipe_iqueue_consume(&info->mpipe[instance].iqueue, idesc); - return !filter; -} - -/* Handle some packets for the current CPU. - * - * This function handles up to TILE_NET_BATCH idescs per call. - * - * ISSUE: Since we do not provide new buffers until this function is - * complete, we must initially provide enough buffers for each network - * cpu to fill its iqueue and also its batched idescs. - * - * ISSUE: The "rotting packet" race condition occurs if a packet - * arrives after the queue appears to be empty, and before the - * hypervisor interrupt is re-enabled. - */ -static int tile_net_poll(struct napi_struct *napi, int budget) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - unsigned int work = 0; - gxio_mpipe_idesc_t *idesc; - int instance, i, n; - struct mpipe_data *md; - struct info_mpipe *info_mpipe = - container_of(napi, struct info_mpipe, napi); - - if (budget <= 0) - goto done; - - instance = info_mpipe->instance; - while ((n = gxio_mpipe_iqueue_try_peek( - &info_mpipe->iqueue, - &idesc)) > 0) { - for (i = 0; i < n; i++) { - if (i == TILE_NET_BATCH) - goto done; - if (tile_net_handle_packet(instance, - idesc + i)) { - if (++work >= budget) - goto done; - } - } - } - - /* There are no packets left. */ - napi_complete_done(&info_mpipe->napi, work); - - md = &mpipe_data[instance]; - /* Re-enable hypervisor interrupts. */ - gxio_mpipe_enable_notif_ring_interrupt( - &md->context, info->mpipe[instance].iqueue.ring); - - /* HACK: Avoid the "rotting packet" problem. */ - if (gxio_mpipe_iqueue_try_peek(&info_mpipe->iqueue, &idesc) > 0) - napi_schedule(&info_mpipe->napi); - - /* ISSUE: Handle completions? */ - -done: - tile_net_provide_needed_buffers(); - - return work; -} - -/* Handle an ingress interrupt from an instance on the current cpu. */ -static irqreturn_t tile_net_handle_ingress_irq(int irq, void *id) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - napi_schedule(&info->mpipe[(uint64_t)id].napi); - return IRQ_HANDLED; -} - -/* Free some completions. This must be called with interrupts blocked. */ -static int tile_net_free_comps(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - int limit, bool force_update) -{ - int n = 0; - while (comps->comp_last < comps->comp_next) { - unsigned int cid = comps->comp_last % TILE_NET_MAX_COMPS; - struct tile_net_comp *comp = &comps->comp_queue[cid]; - if (!gxio_mpipe_equeue_is_complete(equeue, comp->when, - force_update || n == 0)) - break; - dev_kfree_skb_irq(comp->skb); - comps->comp_last++; - if (++n == limit) - break; - } - return n; -} - -/* Add a completion. This must be called with interrupts blocked. - * tile_net_equeue_try_reserve() will have ensured a free completion entry. - */ -static void add_comp(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - uint64_t when, struct sk_buff *skb) -{ - int cid = comps->comp_next % TILE_NET_MAX_COMPS; - comps->comp_queue[cid].when = when; - comps->comp_queue[cid].skb = skb; - comps->comp_next++; -} - -static void tile_net_schedule_tx_wake_timer(struct net_device *dev, - int tx_queue_idx) -{ - struct tile_net_info *info = &per_cpu(per_cpu_info, tx_queue_idx); - struct tile_net_priv *priv = netdev_priv(dev); - int instance = priv->instance; - struct tile_net_tx_wake *tx_wake = - &info->mpipe[instance].tx_wake[priv->echannel]; - - hrtimer_start(&tx_wake->timer, - TX_TIMER_DELAY_USEC * 1000UL, - HRTIMER_MODE_REL_PINNED); -} - -static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t) -{ - struct tile_net_tx_wake *tx_wake = - container_of(t, struct tile_net_tx_wake, timer); - netif_wake_subqueue(tx_wake->dev, tx_wake->tx_queue_idx); - return HRTIMER_NORESTART; -} - -/* Make sure the egress timer is scheduled. */ -static void tile_net_schedule_egress_timer(void) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - - if (!info->egress_timer_scheduled) { - hrtimer_start(&info->egress_timer, - EGRESS_TIMER_DELAY_USEC * 1000UL, - HRTIMER_MODE_REL_PINNED); - info->egress_timer_scheduled = true; - } -} - -/* The "function" for "info->egress_timer". - * - * This timer will reschedule itself as long as there are any pending - * completions expected for this tile. - */ -static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - unsigned long irqflags; - bool pending = false; - int i, instance; - - local_irq_save(irqflags); - - /* The timer is no longer scheduled. */ - info->egress_timer_scheduled = false; - - /* Free all possible comps for this tile. */ - for (instance = 0; instance < NR_MPIPE_MAX && - info->mpipe[instance].has_iqueue; instance++) { - for (i = 0; i < TILE_NET_CHANNELS; i++) { - struct tile_net_egress *egress = - &mpipe_data[instance].egress_for_echannel[i]; - struct tile_net_comps *comps = - info->mpipe[instance].comps_for_echannel[i]; - if (!egress || comps->comp_last >= comps->comp_next) - continue; - tile_net_free_comps(egress->equeue, comps, -1, true); - pending = pending || - (comps->comp_last < comps->comp_next); - } - } - - /* Reschedule timer if needed. */ - if (pending) - tile_net_schedule_egress_timer(); - - local_irq_restore(irqflags); - - return HRTIMER_NORESTART; -} - -/* PTP clock operations. */ - -static int ptp_mpipe_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - int ret = 0; - struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); - mutex_lock(&md->ptp_lock); - if (gxio_mpipe_adjust_timestamp_freq(&md->context, ppb)) - ret = -EINVAL; - mutex_unlock(&md->ptp_lock); - return ret; -} - -static int ptp_mpipe_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - int ret = 0; - struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); - mutex_lock(&md->ptp_lock); - if (gxio_mpipe_adjust_timestamp(&md->context, delta)) - ret = -EBUSY; - mutex_unlock(&md->ptp_lock); - return ret; -} - -static int ptp_mpipe_gettime(struct ptp_clock_info *ptp, - struct timespec64 *ts) -{ - int ret = 0; - struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); - mutex_lock(&md->ptp_lock); - if (gxio_mpipe_get_timestamp(&md->context, ts)) - ret = -EBUSY; - mutex_unlock(&md->ptp_lock); - return ret; -} - -static int ptp_mpipe_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) -{ - int ret = 0; - struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); - mutex_lock(&md->ptp_lock); - if (gxio_mpipe_set_timestamp(&md->context, ts)) - ret = -EBUSY; - mutex_unlock(&md->ptp_lock); - return ret; -} - -static int ptp_mpipe_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *request, int on) -{ - return -EOPNOTSUPP; -} - -static const struct ptp_clock_info ptp_mpipe_caps = { - .owner = THIS_MODULE, - .name = "mPIPE clock", - .max_adj = 999999999, - .n_ext_ts = 0, - .n_pins = 0, - .pps = 0, - .adjfreq = ptp_mpipe_adjfreq, - .adjtime = ptp_mpipe_adjtime, - .gettime64 = ptp_mpipe_gettime, - .settime64 = ptp_mpipe_settime, - .enable = ptp_mpipe_enable, -}; - -/* Sync mPIPE's timestamp up with Linux system time and register PTP clock. */ -static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md) -{ - struct timespec64 ts; - - ktime_get_ts64(&ts); - gxio_mpipe_set_timestamp(&md->context, &ts); - - mutex_init(&md->ptp_lock); - md->caps = ptp_mpipe_caps; - md->ptp_clock = ptp_clock_register(&md->caps, NULL); - if (IS_ERR(md->ptp_clock)) - netdev_err(dev, "ptp_clock_register failed %ld\n", - PTR_ERR(md->ptp_clock)); -} - -/* Initialize PTP fields in a new device. */ -static void init_ptp_dev(struct tile_net_priv *priv) -{ - priv->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; - priv->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; -} - -/* Helper functions for "tile_net_update()". */ -static void enable_ingress_irq(void *irq) -{ - enable_percpu_irq((long)irq, 0); -} - -static void disable_ingress_irq(void *irq) -{ - disable_percpu_irq((long)irq); -} - -/* Helper function for tile_net_open() and tile_net_stop(). - * Always called under tile_net_devs_for_channel_mutex. - */ -static int tile_net_update(struct net_device *dev) -{ - static gxio_mpipe_rules_t rules; /* too big to fit on the stack */ - bool saw_channel = false; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - int channel; - int rc; - int cpu; - - saw_channel = false; - gxio_mpipe_rules_init(&rules, &md->context); - - for (channel = 0; channel < TILE_NET_CHANNELS; channel++) { - if (md->tile_net_devs_for_channel[channel] == NULL) - continue; - if (!saw_channel) { - saw_channel = true; - gxio_mpipe_rules_begin(&rules, md->first_bucket, - md->num_buckets, NULL); - gxio_mpipe_rules_set_headroom(&rules, NET_IP_ALIGN); - } - gxio_mpipe_rules_add_channel(&rules, channel); - } - - /* NOTE: This can fail if there is no classifier. - * ISSUE: Can anything else cause it to fail? - */ - rc = gxio_mpipe_rules_commit(&rules); - if (rc != 0) { - netdev_warn(dev, "gxio_mpipe_rules_commit: mpipe[%d] %d\n", - instance, rc); - return -EIO; - } - - /* Update all cpus, sequentially (to protect "netif_napi_add()"). - * We use on_each_cpu to handle the IPI mask or unmask. - */ - if (!saw_channel) - on_each_cpu(disable_ingress_irq, - (void *)(long)(md->ingress_irq), 1); - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - - if (!info->mpipe[instance].has_iqueue) - continue; - if (saw_channel) { - if (!info->mpipe[instance].napi_added) { - netif_napi_add(dev, &info->mpipe[instance].napi, - tile_net_poll, TILE_NET_WEIGHT); - info->mpipe[instance].napi_added = true; - } - if (!info->mpipe[instance].napi_enabled) { - napi_enable(&info->mpipe[instance].napi); - info->mpipe[instance].napi_enabled = true; - } - } else { - if (info->mpipe[instance].napi_enabled) { - napi_disable(&info->mpipe[instance].napi); - info->mpipe[instance].napi_enabled = false; - } - /* FIXME: Drain the iqueue. */ - } - } - if (saw_channel) - on_each_cpu(enable_ingress_irq, - (void *)(long)(md->ingress_irq), 1); - - /* HACK: Allow packets to flow in the simulator. */ - if (saw_channel) - sim_enable_mpipe_links(instance, -1); - - return 0; -} - -/* Initialize a buffer stack. */ -static int create_buffer_stack(struct net_device *dev, - int kind, size_t num_buffers) -{ - pte_t hash_pte = pte_set_home((pte_t) { 0 }, PAGE_HOME_HASH); - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - size_t needed = gxio_mpipe_calc_buffer_stack_bytes(num_buffers); - int stack_idx = md->first_buffer_stack + kind; - void *va; - int i, rc; - - /* Round up to 64KB and then use alloc_pages() so we get the - * required 64KB alignment. - */ - md->buffer_stack_bytes[kind] = - ALIGN(needed, 64 * 1024); - - va = alloc_pages_exact(md->buffer_stack_bytes[kind], GFP_KERNEL); - if (va == NULL) { - netdev_err(dev, - "Could not alloc %zd bytes for buffer stack %d\n", - md->buffer_stack_bytes[kind], kind); - return -ENOMEM; - } - - /* Initialize the buffer stack. */ - rc = gxio_mpipe_init_buffer_stack(&md->context, stack_idx, - buffer_size_enums[kind], va, - md->buffer_stack_bytes[kind], 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_buffer_stack: mpipe[%d] %d\n", - instance, rc); - free_pages_exact(va, md->buffer_stack_bytes[kind]); - return rc; - } - - md->buffer_stack_vas[kind] = va; - - rc = gxio_mpipe_register_client_memory(&md->context, stack_idx, - hash_pte, 0); - if (rc != 0) { - netdev_err(dev, - "gxio_mpipe_register_client_memory: mpipe[%d] %d\n", - instance, rc); - return rc; - } - - /* Provide initial buffers. */ - for (i = 0; i < num_buffers; i++) { - if (!tile_net_provide_buffer(instance, kind)) { - netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); - return -ENOMEM; - } - } - - return 0; -} - -/* Allocate and initialize mpipe buffer stacks, and register them in - * the mPIPE TLBs, for small, large, and (possibly) jumbo packet sizes. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_buffer_stacks(struct net_device *dev, - int network_cpus_count) -{ - int num_kinds = MAX_KINDS - (jumbo_num == 0); - size_t num_buffers; - int rc; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - - /* Allocate the buffer stacks. */ - rc = gxio_mpipe_alloc_buffer_stacks(&md->context, num_kinds, 0, 0); - if (rc < 0) { - netdev_err(dev, - "gxio_mpipe_alloc_buffer_stacks: mpipe[%d] %d\n", - instance, rc); - return rc; - } - md->first_buffer_stack = rc; - - /* Enough small/large buffers to (normally) avoid buffer errors. */ - num_buffers = - network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH); - - /* Allocate the small memory stack. */ - if (rc >= 0) - rc = create_buffer_stack(dev, 0, num_buffers); - - /* Allocate the large buffer stack. */ - if (rc >= 0) - rc = create_buffer_stack(dev, 1, num_buffers); - - /* Allocate the jumbo buffer stack if needed. */ - if (rc >= 0 && jumbo_num != 0) - rc = create_buffer_stack(dev, 2, jumbo_num); - - return rc; -} - -/* Allocate per-cpu resources (memory for completions and idescs). - * This routine supports tile_net_init_mpipe(), below. - */ -static int alloc_percpu_mpipe_resources(struct net_device *dev, - int cpu, int ring) -{ - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - int order, i, rc; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - struct page *page; - void *addr; - - /* Allocate the "comps". */ - order = get_order(COMPS_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, "Failed to alloc %zd bytes comps memory\n", - COMPS_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - memset(addr, 0, COMPS_SIZE); - for (i = 0; i < TILE_NET_CHANNELS; i++) - info->mpipe[instance].comps_for_echannel[i] = - addr + i * sizeof(struct tile_net_comps); - - /* If this is a network cpu, create an iqueue. */ - if (cpumask_test_cpu(cpu, &network_cpus_map)) { - order = get_order(NOTIF_RING_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, - "Failed to alloc %zd bytes iqueue memory\n", - NOTIF_RING_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - rc = gxio_mpipe_iqueue_init(&info->mpipe[instance].iqueue, - &md->context, ring++, addr, - NOTIF_RING_SIZE, 0); - if (rc < 0) { - netdev_err(dev, - "gxio_mpipe_iqueue_init failed: %d\n", rc); - return rc; - } - info->mpipe[instance].has_iqueue = true; - } - - return ring; -} - -/* Initialize NotifGroup and buckets. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_notif_group_and_buckets(struct net_device *dev, - int ring, int network_cpus_count) -{ - int group, rc; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - - /* Allocate one NotifGroup. */ - rc = gxio_mpipe_alloc_notif_groups(&md->context, 1, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_groups: mpipe[%d] %d\n", - instance, rc); - return rc; - } - group = rc; - - /* Initialize global num_buckets value. */ - if (network_cpus_count > 4) - md->num_buckets = 256; - else if (network_cpus_count > 1) - md->num_buckets = 16; - - /* Allocate some buckets, and set global first_bucket value. */ - rc = gxio_mpipe_alloc_buckets(&md->context, md->num_buckets, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_buckets: mpipe[%d] %d\n", - instance, rc); - return rc; - } - md->first_bucket = rc; - - /* Init group and buckets. */ - rc = gxio_mpipe_init_notif_group_and_buckets( - &md->context, group, ring, network_cpus_count, - md->first_bucket, md->num_buckets, - GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_notif_group_and_buckets: " - "mpipe[%d] %d\n", instance, rc); - return rc; - } - - return 0; -} - -/* Create an irq and register it, then activate the irq and request - * interrupts on all cores. Note that "ingress_irq" being initialized - * is how we know not to call tile_net_init_mpipe() again. - * This routine supports tile_net_init_mpipe(), below. - */ -static int tile_net_setup_interrupts(struct net_device *dev) -{ - int cpu, rc, irq; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - - irq = md->ingress_irq; - if (irq < 0) { - irq = irq_alloc_hwirq(-1); - if (!irq) { - netdev_err(dev, - "create_irq failed: mpipe[%d] %d\n", - instance, irq); - return irq; - } - tile_irq_activate(irq, TILE_IRQ_PERCPU); - - rc = request_irq(irq, tile_net_handle_ingress_irq, - 0, "tile_net", (void *)((uint64_t)instance)); - - if (rc != 0) { - netdev_err(dev, "request_irq failed: mpipe[%d] %d\n", - instance, rc); - irq_free_hwirq(irq); - return rc; - } - md->ingress_irq = irq; - } - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - if (info->mpipe[instance].has_iqueue) { - gxio_mpipe_request_notif_ring_interrupt(&md->context, - cpu_x(cpu), cpu_y(cpu), KERNEL_PL, irq, - info->mpipe[instance].iqueue.ring); - } - } - - return 0; -} - -/* Undo any state set up partially by a failed call to tile_net_init_mpipe. */ -static void tile_net_init_mpipe_fail(int instance) -{ - int kind, cpu; - struct mpipe_data *md = &mpipe_data[instance]; - - /* Do cleanups that require the mpipe context first. */ - for (kind = 0; kind < MAX_KINDS; kind++) { - if (md->buffer_stack_vas[kind] != NULL) { - tile_net_pop_all_buffers(instance, - md->first_buffer_stack + - kind); - } - } - - /* Destroy mpipe context so the hardware no longer owns any memory. */ - gxio_mpipe_destroy(&md->context); - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - free_pages( - (unsigned long)( - info->mpipe[instance].comps_for_echannel[0]), - get_order(COMPS_SIZE)); - info->mpipe[instance].comps_for_echannel[0] = NULL; - free_pages((unsigned long)(info->mpipe[instance].iqueue.idescs), - get_order(NOTIF_RING_SIZE)); - info->mpipe[instance].iqueue.idescs = NULL; - } - - for (kind = 0; kind < MAX_KINDS; kind++) { - if (md->buffer_stack_vas[kind] != NULL) { - free_pages_exact(md->buffer_stack_vas[kind], - md->buffer_stack_bytes[kind]); - md->buffer_stack_vas[kind] = NULL; - } - } - - md->first_buffer_stack = -1; - md->first_bucket = -1; -} - -/* The first time any tilegx network device is opened, we initialize - * the global mpipe state. If this step fails, we fail to open the - * device, but if it succeeds, we never need to do it again, and since - * tile_net can't be unloaded, we never undo it. - * - * Note that some resources in this path (buffer stack indices, - * bindings from init_buffer_stack, etc.) are hypervisor resources - * that are freed implicitly by gxio_mpipe_destroy(). - */ -static int tile_net_init_mpipe(struct net_device *dev) -{ - int rc; - int cpu; - int first_ring, ring; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - int network_cpus_count = cpumask_weight(&network_cpus_map); - - if (!hash_default) { - netdev_err(dev, "Networking requires hash_default!\n"); - return -EIO; - } - - rc = gxio_mpipe_init(&md->context, instance); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init: mpipe[%d] %d\n", - instance, rc); - return -EIO; - } - - /* Set up the buffer stacks. */ - rc = init_buffer_stacks(dev, network_cpus_count); - if (rc != 0) - goto fail; - - /* Allocate one NotifRing for each network cpu. */ - rc = gxio_mpipe_alloc_notif_rings(&md->context, - network_cpus_count, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_rings failed %d\n", - rc); - goto fail; - } - - /* Init NotifRings per-cpu. */ - first_ring = rc; - ring = first_ring; - for_each_online_cpu(cpu) { - rc = alloc_percpu_mpipe_resources(dev, cpu, ring); - if (rc < 0) - goto fail; - ring = rc; - } - - /* Initialize NotifGroup and buckets. */ - rc = init_notif_group_and_buckets(dev, first_ring, network_cpus_count); - if (rc != 0) - goto fail; - - /* Create and enable interrupts. */ - rc = tile_net_setup_interrupts(dev); - if (rc != 0) - goto fail; - - /* Register PTP clock and set mPIPE timestamp, if configured. */ - register_ptp_clock(dev, md); - - return 0; - -fail: - tile_net_init_mpipe_fail(instance); - return rc; -} - -/* Create persistent egress info for a given egress channel. - * Note that this may be shared between, say, "gbe0" and "xgbe0". - * ISSUE: Defer header allocation until TSO is actually needed? - */ -static int tile_net_init_egress(struct net_device *dev, int echannel) -{ - static int ering = -1; - struct page *headers_page, *edescs_page, *equeue_page; - gxio_mpipe_edesc_t *edescs; - gxio_mpipe_equeue_t *equeue; - unsigned char *headers; - int headers_order, edescs_order, equeue_order; - size_t edescs_size; - int rc = -ENOMEM; - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - - /* Only initialize once. */ - if (md->egress_for_echannel[echannel].equeue != NULL) - return 0; - - /* Allocate memory for the "headers". */ - headers_order = get_order(EQUEUE_ENTRIES * HEADER_BYTES); - headers_page = alloc_pages(GFP_KERNEL, headers_order); - if (headers_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for TSO headers.\n", - PAGE_SIZE << headers_order); - goto fail; - } - headers = pfn_to_kaddr(page_to_pfn(headers_page)); - - /* Allocate memory for the "edescs". */ - edescs_size = EQUEUE_ENTRIES * sizeof(*edescs); - edescs_order = get_order(edescs_size); - edescs_page = alloc_pages(GFP_KERNEL, edescs_order); - if (edescs_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for eDMA ring.\n", - edescs_size); - goto fail_headers; - } - edescs = pfn_to_kaddr(page_to_pfn(edescs_page)); - - /* Allocate memory for the "equeue". */ - equeue_order = get_order(sizeof(*equeue)); - equeue_page = alloc_pages(GFP_KERNEL, equeue_order); - if (equeue_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for equeue info.\n", - PAGE_SIZE << equeue_order); - goto fail_edescs; - } - equeue = pfn_to_kaddr(page_to_pfn(equeue_page)); - - /* Allocate an edma ring (using a one entry "free list"). */ - if (ering < 0) { - rc = gxio_mpipe_alloc_edma_rings(&md->context, 1, 0, 0); - if (rc < 0) { - netdev_warn(dev, "gxio_mpipe_alloc_edma_rings: " - "mpipe[%d] %d\n", instance, rc); - goto fail_equeue; - } - ering = rc; - } - - /* Initialize the equeue. */ - rc = gxio_mpipe_equeue_init(equeue, &md->context, ering, echannel, - edescs, edescs_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_equeue_init: mpipe[%d] %d\n", - instance, rc); - goto fail_equeue; - } - - /* Don't reuse the ering later. */ - ering = -1; - - if (jumbo_num != 0) { - /* Make sure "jumbo" packets can be egressed safely. */ - if (gxio_mpipe_equeue_set_snf_size(equeue, 10368) < 0) { - /* ISSUE: There is no "gxio_mpipe_equeue_destroy()". */ - netdev_warn(dev, "Jumbo packets may not be egressed" - " properly on channel %d\n", echannel); - } - } - - /* Done. */ - md->egress_for_echannel[echannel].equeue = equeue; - md->egress_for_echannel[echannel].headers = headers; - return 0; - -fail_equeue: - __free_pages(equeue_page, equeue_order); - -fail_edescs: - __free_pages(edescs_page, edescs_order); - -fail_headers: - __free_pages(headers_page, headers_order); - -fail: - return rc; -} - -/* Return channel number for a newly-opened link. */ -static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link, - const char *link_name) -{ - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - int rc = gxio_mpipe_link_open(link, &md->context, link_name, 0); - if (rc < 0) { - netdev_err(dev, "Failed to open '%s', mpipe[%d], %d\n", - link_name, instance, rc); - return rc; - } - if (jumbo_num != 0) { - u32 attr = GXIO_MPIPE_LINK_RECEIVE_JUMBO; - rc = gxio_mpipe_link_set_attr(link, attr, 1); - if (rc != 0) { - netdev_err(dev, - "Cannot receive jumbo packets on '%s'\n", - link_name); - gxio_mpipe_link_close(link); - return rc; - } - } - rc = gxio_mpipe_link_channel(link); - if (rc < 0 || rc >= TILE_NET_CHANNELS) { - netdev_err(dev, "gxio_mpipe_link_channel bad value: %d\n", rc); - gxio_mpipe_link_close(link); - return -EINVAL; - } - return rc; -} - -/* Help the kernel activate the given network interface. */ -static int tile_net_open(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu, rc, instance; - - mutex_lock(&tile_net_devs_for_channel_mutex); - - /* Get the instance info. */ - rc = gxio_mpipe_link_instance(dev->name); - if (rc < 0 || rc >= NR_MPIPE_MAX) { - mutex_unlock(&tile_net_devs_for_channel_mutex); - return -EIO; - } - - priv->instance = rc; - instance = rc; - if (!mpipe_data[rc].context.mmio_fast_base) { - /* Do one-time initialization per instance the first time - * any device is opened. - */ - rc = tile_net_init_mpipe(dev); - if (rc != 0) - goto fail; - } - - /* Determine if this is the "loopify" device. */ - if (unlikely((loopify_link_name != NULL) && - !strcmp(dev->name, loopify_link_name))) { - rc = tile_net_link_open(dev, &priv->link, "loop0"); - if (rc < 0) - goto fail; - priv->channel = rc; - rc = tile_net_link_open(dev, &priv->loopify_link, "loop1"); - if (rc < 0) - goto fail; - priv->loopify_channel = rc; - priv->echannel = rc; - } else { - rc = tile_net_link_open(dev, &priv->link, dev->name); - if (rc < 0) - goto fail; - priv->channel = rc; - priv->echannel = rc; - } - - /* Initialize egress info (if needed). Once ever, per echannel. */ - rc = tile_net_init_egress(dev, priv->echannel); - if (rc != 0) - goto fail; - - mpipe_data[instance].tile_net_devs_for_channel[priv->channel] = dev; - - rc = tile_net_update(dev); - if (rc != 0) - goto fail; - - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Initialize the transmit wake timer for this device for each cpu. */ - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->mpipe[instance].tx_wake[priv->echannel]; - - hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - tx_wake->tx_queue_idx = cpu; - tx_wake->timer.function = tile_net_handle_tx_wake_timer; - tx_wake->dev = dev; - } - - for_each_online_cpu(cpu) - netif_start_subqueue(dev, cpu); - netif_carrier_on(dev); - return 0; - -fail: - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - mpipe_data[instance].tile_net_devs_for_channel[priv->channel] = NULL; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Don't return raw gxio error codes to generic Linux. */ - return (rc > -512) ? rc : -EIO; -} - -/* Help the kernel deactivate the given network interface. */ -static int tile_net_stop(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu; - int instance = priv->instance; - struct mpipe_data *md = &mpipe_data[instance]; - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->mpipe[instance].tx_wake[priv->echannel]; - - hrtimer_cancel(&tx_wake->timer); - netif_stop_subqueue(dev, cpu); - } - - mutex_lock(&tile_net_devs_for_channel_mutex); - md->tile_net_devs_for_channel[priv->channel] = NULL; - (void)tile_net_update(dev); - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - return 0; -} - -/* Determine the VA for a fragment. */ -static inline void *tile_net_frag_buf(skb_frag_t *f) -{ - unsigned long pfn = page_to_pfn(skb_frag_page(f)); - return pfn_to_kaddr(pfn) + f->page_offset; -} - -/* Acquire a completion entry and an egress slot, or if we can't, - * stop the queue and schedule the tx_wake timer. - */ -static s64 tile_net_equeue_try_reserve(struct net_device *dev, - int tx_queue_idx, - struct tile_net_comps *comps, - gxio_mpipe_equeue_t *equeue, - int num_edescs) -{ - /* Try to acquire a completion entry. */ - if (comps->comp_next - comps->comp_last < TILE_NET_MAX_COMPS - 1 || - tile_net_free_comps(equeue, comps, 32, false) != 0) { - - /* Try to acquire an egress slot. */ - s64 slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - - /* Freeing some completions gives the equeue time to drain. */ - tile_net_free_comps(equeue, comps, TILE_NET_MAX_COMPS, false); - - slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - } - - /* Still nothing; give up and stop the queue for a short while. */ - netif_stop_subqueue(dev, tx_queue_idx); - tile_net_schedule_tx_wake_timer(dev, tx_queue_idx); - return -1; -} - -/* Determine how many edesc's are needed for TSO. - * - * Sometimes, if "sendfile()" requires copying, we will be called with - * "data" containing the header and payload, with "frags" being empty. - * Sometimes, for example when using NFS over TCP, a single segment can - * span 3 fragments. This requires special care. - */ -static int tso_count_edescs(struct sk_buff *skb) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; - unsigned int p_len = sh->gso_size; - long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int num_edescs = 0; - int segment; - - for (segment = 0; segment < sh->gso_segs; segment++) { - - unsigned int p_used = 0; - - /* One edesc for header and for each piece of the payload. */ - for (num_edescs++; p_used < p_len; num_edescs++) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - } - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - return num_edescs; -} - -/* Prepare modified copies of the skbuff headers. */ -static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, - s64 slot) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - struct iphdr *ih; - struct ipv6hdr *ih6; - struct tcphdr *th; - unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; - unsigned char *data = skb->data; - unsigned int ih_off, th_off, p_len; - unsigned int isum_seed, tsum_seed, seq; - unsigned int uninitialized_var(id); - int is_ipv6; - long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int segment; - - /* Locate original headers and compute various lengths. */ - is_ipv6 = skb_is_gso_v6(skb); - if (is_ipv6) { - ih6 = ipv6_hdr(skb); - ih_off = skb_network_offset(skb); - } else { - ih = ip_hdr(skb); - ih_off = skb_network_offset(skb); - isum_seed = ((0xFFFF - ih->check) + - (0xFFFF - ih->tot_len) + - (0xFFFF - ih->id)); - id = ntohs(ih->id); - } - - th = tcp_hdr(skb); - th_off = skb_transport_offset(skb); - p_len = sh->gso_size; - - tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); - seq = ntohl(th->seq); - - /* Prepare all the headers. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - unsigned char *buf; - unsigned int p_used = 0; - - /* Copy to the header memory for this segment. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - memcpy(buf, data, sh_len); - - /* Update copied ip header. */ - if (is_ipv6) { - ih6 = (struct ipv6hdr *)(buf + ih_off); - ih6->payload_len = htons(sh_len + p_len - ih_off - - sizeof(*ih6)); - } else { - ih = (struct iphdr *)(buf + ih_off); - ih->tot_len = htons(sh_len + p_len - ih_off); - ih->id = htons(id++); - ih->check = csum_long(isum_seed + ih->tot_len + - ih->id) ^ 0xffff; - } - - /* Update copied tcp header. */ - th = (struct tcphdr *)(buf + th_off); - th->seq = htonl(seq); - th->check = csum_long(tsum_seed + htons(sh_len + p_len)); - if (segment != sh->gso_segs - 1) { - th->fin = 0; - th->psh = 0; - } - - /* Skip past the header. */ - slot++; - - /* Skip past the payload. */ - while (p_used < p_len) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - slot++; - } - - seq += p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Flush the headers so they are ready for hardware DMA. */ - wmb(); -} - -/* Pass all the data to mpipe for egress. */ -static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, - struct sk_buff *skb, unsigned char *headers, s64 slot) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - int instance = mpipe_instance(dev); - struct mpipe_data *md = &mpipe_data[instance]; - unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->len - sh_len; - unsigned int p_len = sh->gso_size; - gxio_mpipe_edesc_t edesc_head = { { 0 } }; - gxio_mpipe_edesc_t edesc_body = { { 0 } }; - long f_id = -1; /* id of the current fragment */ - long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ - long f_used = 0; /* bytes used from the current fragment */ - void *f_data = skb->data + sh_len; - long n; /* size of the current piece of payload */ - unsigned long tx_packets = 0, tx_bytes = 0; - unsigned int csum_start; - int segment; - - /* Prepare to egress the headers: set up header edesc. */ - csum_start = skb_checksum_start_offset(skb); - edesc_head.csum = 1; - edesc_head.csum_start = csum_start; - edesc_head.csum_dest = csum_start + skb->csum_offset; - edesc_head.xfer_size = sh_len; - - /* This is only used to specify the TLB. */ - edesc_head.stack_idx = md->first_buffer_stack; - edesc_body.stack_idx = md->first_buffer_stack; - - /* Egress all the edescs. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - unsigned char *buf; - unsigned int p_used = 0; - - /* Egress the header. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - edesc_head.va = va_to_tile_io_addr(buf); - gxio_mpipe_equeue_put_at(equeue, edesc_head, slot); - slot++; - - /* Egress the payload. */ - while (p_used < p_len) { - void *va; - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = skb_frag_size(&sh->frags[f_id]); - f_data = tile_net_frag_buf(&sh->frags[f_id]); - f_used = 0; - } - - va = f_data + f_used; - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(va); - edesc_body.xfer_size = n; - edesc_body.bound = !(p_used < p_len); - gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); - slot++; - } - - tx_packets++; - tx_bytes += sh_len + p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Update stats. */ - tile_net_stats_add(tx_packets, &dev->stats.tx_packets); - tile_net_stats_add(tx_bytes, &dev->stats.tx_bytes); -} - -/* Do "TSO" handling for egress. - * - * Normally drivers set NETIF_F_TSO only to support hardware TSO; - * otherwise the stack uses scatter-gather to implement GSO in software. - * On our testing, enabling GSO support (via NETIF_F_SG) drops network - * performance down to around 7.5 Gbps on the 10G interfaces, although - * also dropping cpu utilization way down, to under 8%. But - * implementing "TSO" in the driver brings performance back up to line - * rate, while dropping cpu usage even further, to less than 4%. In - * practice, profiling of GSO shows that skb_segment() is what causes - * the performance overheads; we benefit in the driver from using - * preallocated memory to duplicate the TCP/IP headers. - */ -static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - int channel = priv->echannel; - int instance = priv->instance; - struct mpipe_data *md = &mpipe_data[instance]; - struct tile_net_egress *egress = &md->egress_for_echannel[channel]; - struct tile_net_comps *comps = - info->mpipe[instance].comps_for_echannel[channel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - unsigned long irqflags; - int num_edescs; - s64 slot; - - /* Determine how many mpipe edesc's are needed. */ - num_edescs = tso_count_edescs(skb); - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, skb->queue_mapping, comps, - equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - /* Set up copies of header data properly. */ - tso_headers_prepare(skb, egress->headers, slot); - - /* Actually pass the data to the network hardware. */ - tso_egress(dev, equeue, skb, egress->headers, slot); - - /* Add a completion record. */ - add_comp(equeue, comps, slot + num_edescs - 1, skb); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Analyze the body and frags for a transmit request. */ -static unsigned int tile_net_tx_frags(struct frag *frags, - struct sk_buff *skb, - void *b_data, unsigned int b_len) -{ - unsigned int i, n = 0; - - struct skb_shared_info *sh = skb_shinfo(skb); - - if (b_len != 0) { - frags[n].buf = b_data; - frags[n++].length = b_len; - } - - for (i = 0; i < sh->nr_frags; i++) { - skb_frag_t *f = &sh->frags[i]; - frags[n].buf = tile_net_frag_buf(f); - frags[n++].length = skb_frag_size(f); - } - - return n; -} - -/* Help the kernel transmit a packet. */ -static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - int instance = priv->instance; - struct mpipe_data *md = &mpipe_data[instance]; - struct tile_net_egress *egress = - &md->egress_for_echannel[priv->echannel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - struct tile_net_comps *comps = - info->mpipe[instance].comps_for_echannel[priv->echannel]; - unsigned int len = skb->len; - unsigned char *data = skb->data; - unsigned int num_edescs; - struct frag frags[MAX_FRAGS]; - gxio_mpipe_edesc_t edescs[MAX_FRAGS]; - unsigned long irqflags; - gxio_mpipe_edesc_t edesc = { { 0 } }; - unsigned int i; - s64 slot; - - if (skb_is_gso(skb)) - return tile_net_tx_tso(skb, dev); - - num_edescs = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); - - /* This is only used to specify the TLB. */ - edesc.stack_idx = md->first_buffer_stack; - - /* Prepare the edescs. */ - for (i = 0; i < num_edescs; i++) { - edesc.xfer_size = frags[i].length; - edesc.va = va_to_tile_io_addr(frags[i].buf); - edescs[i] = edesc; - } - - /* Mark the final edesc. */ - edescs[num_edescs - 1].bound = 1; - - /* Add checksum info to the initial edesc, if needed. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - unsigned int csum_start = skb_checksum_start_offset(skb); - edescs[0].csum = 1; - edescs[0].csum_start = csum_start; - edescs[0].csum_dest = csum_start + skb->csum_offset; - } - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, skb->queue_mapping, comps, - equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - for (i = 0; i < num_edescs; i++) - gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); - - /* Store TX timestamp if needed. */ - tile_tx_timestamp(skb, instance); - - /* Add a completion record. */ - add_comp(equeue, comps, slot - 1, skb); - - /* NOTE: Use ETH_ZLEN for short packets (e.g. 42 < 60). */ - tile_net_stats_add(1, &dev->stats.tx_packets); - tile_net_stats_add(max_t(unsigned int, len, ETH_ZLEN), - &dev->stats.tx_bytes); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Return subqueue id on this core (one per core). */ -static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv, select_queue_fallback_t fallback) -{ - return smp_processor_id(); -} - -/* Deal with a transmit timeout. */ -static void tile_net_tx_timeout(struct net_device *dev) -{ - int cpu; - - for_each_online_cpu(cpu) - netif_wake_subqueue(dev, cpu); -} - -/* Ioctl commands. */ -static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - if (cmd == SIOCSHWTSTAMP) - return tile_hwtstamp_set(dev, rq); - if (cmd == SIOCGHWTSTAMP) - return tile_hwtstamp_get(dev, rq); - - return -EOPNOTSUPP; -} - -/* Change the Ethernet address of the NIC. - * - * The hypervisor driver does not support changing MAC address. However, - * the hardware does not do anything with the MAC address, so the address - * which gets used on outgoing packets, and which is accepted on incoming - * packets, is completely up to us. - * - * Returns 0 on success, negative on failure. - */ -static int tile_net_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void tile_net_netpoll(struct net_device *dev) -{ - int instance = mpipe_instance(dev); - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - struct mpipe_data *md = &mpipe_data[instance]; - - disable_percpu_irq(md->ingress_irq); - napi_schedule(&info->mpipe[instance].napi); - enable_percpu_irq(md->ingress_irq, 0); -} -#endif - -static const struct net_device_ops tile_net_ops = { - .ndo_open = tile_net_open, - .ndo_stop = tile_net_stop, - .ndo_start_xmit = tile_net_tx, - .ndo_select_queue = tile_net_select_queue, - .ndo_do_ioctl = tile_net_ioctl, - .ndo_tx_timeout = tile_net_tx_timeout, - .ndo_set_mac_address = tile_net_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tile_net_netpoll, -#endif -}; - -/* The setup function. - * - * This uses ether_setup() to assign various fields in dev, including - * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. - */ -static void tile_net_setup(struct net_device *dev) -{ - netdev_features_t features = 0; - - ether_setup(dev); - dev->netdev_ops = &tile_net_ops; - dev->watchdog_timeo = TILE_NET_TIMEOUT; - - /* MTU range: 68 - 1500 or 9000 */ - dev->mtu = ETH_DATA_LEN; - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = jumbo_num ? TILE_JUMBO_MAX_MTU : ETH_DATA_LEN; - - features |= NETIF_F_HW_CSUM; - features |= NETIF_F_SG; - features |= NETIF_F_TSO; - features |= NETIF_F_TSO6; - - dev->hw_features |= features; - dev->vlan_features |= features; - dev->features |= features; -} - -/* Allocate the device structure, register the device, and obtain the - * MAC address from the hypervisor. - */ -static void tile_net_dev_init(const char *name, const uint8_t *mac) -{ - int ret; - struct net_device *dev; - struct tile_net_priv *priv; - - /* HACK: Ignore "loop" links. */ - if (strncmp(name, "loop", 4) == 0) - return; - - /* Allocate the device structure. Normally, "name" is a - * template, instantiated by register_netdev(), but not for us. - */ - dev = alloc_netdev_mqs(sizeof(*priv), name, NET_NAME_UNKNOWN, - tile_net_setup, NR_CPUS, 1); - if (!dev) { - pr_err("alloc_netdev_mqs(%s) failed\n", name); - return; - } - - /* Initialize "priv". */ - priv = netdev_priv(dev); - priv->dev = dev; - priv->channel = -1; - priv->loopify_channel = -1; - priv->echannel = -1; - init_ptp_dev(priv); - - /* Get the MAC address and set it in the device struct; this must - * be done before the device is opened. If the MAC is all zeroes, - * we use a random address, since we're probably on the simulator. - */ - if (!is_zero_ether_addr(mac)) - ether_addr_copy(dev->dev_addr, mac); - else - eth_hw_addr_random(dev); - - /* Register the network device. */ - ret = register_netdev(dev); - if (ret) { - netdev_err(dev, "register_netdev failed %d\n", ret); - free_netdev(dev); - return; - } -} - -/* Per-cpu module initialization. */ -static void tile_net_init_module_percpu(void *unused) -{ - struct tile_net_info *info = this_cpu_ptr(&per_cpu_info); - int my_cpu = smp_processor_id(); - int instance; - - for (instance = 0; instance < NR_MPIPE_MAX; instance++) { - info->mpipe[instance].has_iqueue = false; - info->mpipe[instance].instance = instance; - } - info->my_cpu = my_cpu; - - /* Initialize the egress timer. */ - hrtimer_init(&info->egress_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - info->egress_timer.function = tile_net_handle_egress_timer; -} - -/* Module initialization. */ -static int __init tile_net_init_module(void) -{ - int i; - char name[GXIO_MPIPE_LINK_NAME_LEN]; - uint8_t mac[6]; - - pr_info("Tilera Network Driver\n"); - - BUILD_BUG_ON(NR_MPIPE_MAX != 2); - - mutex_init(&tile_net_devs_for_channel_mutex); - - /* Initialize each CPU. */ - on_each_cpu(tile_net_init_module_percpu, NULL, 1); - - /* Find out what devices we have, and initialize them. */ - for (i = 0; gxio_mpipe_link_enumerate_mac(i, name, mac) >= 0; i++) - tile_net_dev_init(name, mac); - - if (!network_cpus_init()) - cpumask_and(&network_cpus_map, - housekeeping_cpumask(HK_FLAG_MISC), cpu_online_mask); - - return 0; -} - -module_init(tile_net_init_module); diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c deleted file mode 100644 index 56d06282fbde..000000000000 --- a/drivers/net/ethernet/tile/tilepro.c +++ /dev/null @@ -1,2397 +0,0 @@ -/* - * Copyright 2011 Tilera Corporation. All Rights Reserved. - * - * 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. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/moduleparam.h> -#include <linux/sched.h> -#include <linux/kernel.h> /* printk() */ -#include <linux/slab.h> /* kmalloc() */ -#include <linux/errno.h> /* error codes */ -#include <linux/types.h> /* size_t */ -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/netdevice.h> /* struct device, and other headers */ -#include <linux/etherdevice.h> /* eth_type_trans */ -#include <linux/skbuff.h> -#include <linux/ioctl.h> -#include <linux/cdev.h> -#include <linux/hugetlb.h> -#include <linux/in6.h> -#include <linux/timer.h> -#include <linux/io.h> -#include <linux/u64_stats_sync.h> -#include <asm/checksum.h> -#include <asm/homecache.h> - -#include <hv/drv_xgbe_intf.h> -#include <hv/drv_xgbe_impl.h> -#include <hv/hypervisor.h> -#include <hv/netio_intf.h> - -/* For TSO */ -#include <linux/ip.h> -#include <linux/tcp.h> - - -/* - * First, "tile_net_init_module()" initializes all four "devices" which - * can be used by linux. - * - * Then, "ifconfig DEVICE up" calls "tile_net_open()", which analyzes - * the network cpus, then uses "tile_net_open_aux()" to initialize - * LIPP/LEPP, and then uses "tile_net_open_inner()" to register all - * the tiles, provide buffers to LIPP, allow ingress to start, and - * turn on hypervisor interrupt handling (and NAPI) on all tiles. - * - * If registration fails due to the link being down, then "retry_work" - * is used to keep calling "tile_net_open_inner()" until it succeeds. - * - * If "ifconfig DEVICE down" is called, it uses "tile_net_stop()" to - * stop egress, drain the LIPP buffers, unregister all the tiles, stop - * LIPP/LEPP, and wipe the LEPP queue. - * - * We start out with the ingress interrupt enabled on each CPU. When - * this interrupt fires, we disable it, and call "napi_schedule()". - * This will cause "tile_net_poll()" to be called, which will pull - * packets from the netio queue, filtering them out, or passing them - * to "netif_receive_skb()". If our budget is exhausted, we will - * return, knowing we will be called again later. Otherwise, we - * reenable the ingress interrupt, and call "napi_complete()". - * - * HACK: Since disabling the ingress interrupt is not reliable, we - * ignore the interrupt if the global "active" flag is false. - * - * - * NOTE: The use of "native_driver" ensures that EPP exists, and that - * we are using "LIPP" and "LEPP". - * - * NOTE: Failing to free completions for an arbitrarily long time - * (which is defined to be illegal) does in fact cause bizarre - * problems. The "egress_timer" helps prevent this from happening. - */ - - -/* HACK: Allow use of "jumbo" packets. */ -/* This should be 1500 if "jumbo" is not set in LIPP. */ -/* This should be at most 10226 (10240 - 14) if "jumbo" is set in LIPP. */ -/* ISSUE: This has not been thoroughly tested (except at 1500). */ -#define TILE_NET_MTU ETH_DATA_LEN - -/* HACK: Define this to verify incoming packets. */ -/* #define TILE_NET_VERIFY_INGRESS */ - -/* Use 3000 to enable the Linux Traffic Control (QoS) layer, else 0. */ -#define TILE_NET_TX_QUEUE_LEN 0 - -/* Define to dump packets (prints out the whole packet on tx and rx). */ -/* #define TILE_NET_DUMP_PACKETS */ - -/* Define to enable debug spew (all PDEBUG's are enabled). */ -/* #define TILE_NET_DEBUG */ - - -/* Define to activate paranoia checks. */ -/* #define TILE_NET_PARANOIA */ - -/* Default transmit lockup timeout period, in jiffies. */ -#define TILE_NET_TIMEOUT (5 * HZ) - -/* Default retry interval for bringing up the NetIO interface, in jiffies. */ -#define TILE_NET_RETRY_INTERVAL (5 * HZ) - -/* Number of ports (xgbe0, xgbe1, gbe0, gbe1). */ -#define TILE_NET_DEVS 4 - - - -/* Paranoia. */ -#if NET_IP_ALIGN != LIPP_PACKET_PADDING -#error "NET_IP_ALIGN must match LIPP_PACKET_PADDING." -#endif - - -/* Debug print. */ -#ifdef TILE_NET_DEBUG -#define PDEBUG(fmt, args...) net_printk(fmt, ## args) -#else -#define PDEBUG(fmt, args...) -#endif - - -MODULE_AUTHOR("Tilera"); -MODULE_LICENSE("GPL"); - - -/* - * Queue of incoming packets for a specific cpu and device. - * - * Includes a pointer to the "system" data, and the actual "user" data. - */ -struct tile_netio_queue { - netio_queue_impl_t *__system_part; - netio_queue_user_impl_t __user_part; - -}; - - -/* - * Statistics counters for a specific cpu and device. - */ -struct tile_net_stats_t { - struct u64_stats_sync syncp; - u64 rx_packets; /* total packets received */ - u64 tx_packets; /* total packets transmitted */ - u64 rx_bytes; /* total bytes received */ - u64 tx_bytes; /* total bytes transmitted */ - u64 rx_errors; /* packets truncated or marked bad by hw */ - u64 rx_dropped; /* packets not for us or intf not up */ -}; - - -/* - * Info for a specific cpu and device. - * - * ISSUE: There is a "dev" pointer in "napi" as well. - */ -struct tile_net_cpu { - /* The NAPI struct. */ - struct napi_struct napi; - /* Packet queue. */ - struct tile_netio_queue queue; - /* Statistics. */ - struct tile_net_stats_t stats; - /* True iff NAPI is enabled. */ - bool napi_enabled; - /* True if this tile has successfully registered with the IPP. */ - bool registered; - /* True if the link was down last time we tried to register. */ - bool link_down; - /* True if "egress_timer" is scheduled. */ - bool egress_timer_scheduled; - /* Number of small sk_buffs which must still be provided. */ - unsigned int num_needed_small_buffers; - /* Number of large sk_buffs which must still be provided. */ - unsigned int num_needed_large_buffers; - /* A timer for handling egress completions. */ - struct timer_list egress_timer; -}; - - -/* - * Info for a specific device. - */ -struct tile_net_priv { - /* Our network device. */ - struct net_device *dev; - /* Pages making up the egress queue. */ - struct page *eq_pages; - /* Address of the actual egress queue. */ - lepp_queue_t *eq; - /* Protects "eq". */ - spinlock_t eq_lock; - /* The hypervisor handle for this interface. */ - int hv_devhdl; - /* The intr bit mask that IDs this device. */ - u32 intr_id; - /* True iff "tile_net_open_aux()" has succeeded. */ - bool partly_opened; - /* True iff the device is "active". */ - bool active; - /* Effective network cpus. */ - struct cpumask network_cpus_map; - /* Number of network cpus. */ - int network_cpus_count; - /* Credits per network cpu. */ - int network_cpus_credits; - /* For NetIO bringup retries. */ - struct delayed_work retry_work; - /* Quick access to per cpu data. */ - struct tile_net_cpu *cpu[NR_CPUS]; -}; - -/* Log2 of the number of small pages needed for the egress queue. */ -#define EQ_ORDER get_order(sizeof(lepp_queue_t)) -/* Size of the egress queue's pages. */ -#define EQ_SIZE (1 << (PAGE_SHIFT + EQ_ORDER)) - -/* - * The actual devices (xgbe0, xgbe1, gbe0, gbe1). - */ -static struct net_device *tile_net_devs[TILE_NET_DEVS]; - -/* - * The "tile_net_cpu" structures for each device. - */ -static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe0); -static DEFINE_PER_CPU(struct tile_net_cpu, hv_xgbe1); -static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe0); -static DEFINE_PER_CPU(struct tile_net_cpu, hv_gbe1); - - -/* - * True if "network_cpus" was specified. - */ -static bool network_cpus_used; - -/* - * The actual cpus in "network_cpus". - */ -static struct cpumask network_cpus_map; - - - -#ifdef TILE_NET_DEBUG -/* - * printk with extra stuff. - * - * We print the CPU we're running in brackets. - */ -static void net_printk(char *fmt, ...) -{ - int i; - int len; - va_list args; - static char buf[256]; - - len = sprintf(buf, "tile_net[%2.2d]: ", smp_processor_id()); - va_start(args, fmt); - i = vscnprintf(buf + len, sizeof(buf) - len - 1, fmt, args); - va_end(args); - buf[255] = '\0'; - pr_notice(buf); -} -#endif - - -#ifdef TILE_NET_DUMP_PACKETS -/* - * Dump a packet. - */ -static void dump_packet(unsigned char *data, unsigned long length, char *s) -{ - int my_cpu = smp_processor_id(); - - unsigned long i; - char buf[128]; - - static unsigned int count; - - pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n", - data, length, s, count++); - - pr_info("\n"); - - for (i = 0; i < length; i++) { - if ((i & 0xf) == 0) - sprintf(buf, "[%02d] %8.8lx:", my_cpu, i); - sprintf(buf + strlen(buf), " %2.2x", data[i]); - if ((i & 0xf) == 0xf || i == length - 1) { - strcat(buf, "\n"); - pr_info("%s", buf); - } - } -} -#endif - - -/* - * Provide support for the __netio_fastio1() swint - * (see <hv/drv_xgbe_intf.h> for how it is used). - * - * The fastio swint2 call may clobber all the caller-saved registers. - * It rarely clobbers memory, but we allow for the possibility in - * the signature just to be on the safe side. - * - * Also, gcc doesn't seem to allow an input operand to be - * clobbered, so we fake it with dummy outputs. - * - * This function can't be static because of the way it is declared - * in the netio header. - */ -inline int __netio_fastio1(u32 fastio_index, u32 arg0) -{ - long result, clobber_r1, clobber_r10; - asm volatile("swint2" - : "=R00" (result), - "=R01" (clobber_r1), "=R10" (clobber_r10) - : "R10" (fastio_index), "R01" (arg0) - : "memory", "r2", "r3", "r4", - "r5", "r6", "r7", "r8", "r9", - "r11", "r12", "r13", "r14", - "r15", "r16", "r17", "r18", "r19", - "r20", "r21", "r22", "r23", "r24", - "r25", "r26", "r27", "r28", "r29"); - return result; -} - - -static void tile_net_return_credit(struct tile_net_cpu *info) -{ - struct tile_netio_queue *queue = &info->queue; - netio_queue_user_impl_t *qup = &queue->__user_part; - - /* Return four credits after every fourth packet. */ - if (--qup->__receive_credit_remaining == 0) { - u32 interval = qup->__receive_credit_interval; - qup->__receive_credit_remaining = interval; - __netio_fastio_return_credits(qup->__fastio_index, interval); - } -} - - - -/* - * Provide a linux buffer to LIPP. - */ -static void tile_net_provide_linux_buffer(struct tile_net_cpu *info, - void *va, bool small) -{ - struct tile_netio_queue *queue = &info->queue; - - /* Convert "va" and "small" to "linux_buffer_t". */ - unsigned int buffer = ((unsigned int)(__pa(va) >> 7) << 1) + small; - - __netio_fastio_free_buffer(queue->__user_part.__fastio_index, buffer); -} - - -/* - * Provide a linux buffer for LIPP. - * - * Note that the ACTUAL allocation for each buffer is a "struct sk_buff", - * plus a chunk of memory that includes not only the requested bytes, but - * also NET_SKB_PAD bytes of initial padding, and a "struct skb_shared_info". - * - * Note that "struct skb_shared_info" is 88 bytes with 64K pages and - * 268 bytes with 4K pages (since the frags[] array needs 18 entries). - * - * Without jumbo packets, the maximum packet size will be 1536 bytes, - * and we use 2 bytes (NET_IP_ALIGN) of padding. ISSUE: If we told - * the hardware to clip at 1518 bytes instead of 1536 bytes, then we - * could save an entire cache line, but in practice, we don't need it. - * - * Since CPAs are 38 bits, and we can only encode the high 31 bits in - * a "linux_buffer_t", the low 7 bits must be zero, and thus, we must - * align the actual "va" mod 128. - * - * We assume that the underlying "head" will be aligned mod 64. Note - * that in practice, we have seen "head" NOT aligned mod 128 even when - * using 2048 byte allocations, which is surprising. - * - * If "head" WAS always aligned mod 128, we could change LIPP to - * assume that the low SIX bits are zero, and the 7th bit is one, that - * is, align the actual "va" mod 128 plus 64, which would be "free". - * - * For now, the actual "head" pointer points at NET_SKB_PAD bytes of - * padding, plus 28 or 92 bytes of extra padding, plus the sk_buff - * pointer, plus the NET_IP_ALIGN padding, plus 126 or 1536 bytes for - * the actual packet, plus 62 bytes of empty padding, plus some - * padding and the "struct skb_shared_info". - * - * With 64K pages, a large buffer thus needs 32+92+4+2+1536+62+88 - * bytes, or 1816 bytes, which fits comfortably into 2048 bytes. - * - * With 64K pages, a small buffer thus needs 32+92+4+2+126+88 - * bytes, or 344 bytes, which means we are wasting 64+ bytes, and - * could presumably increase the size of small buffers. - * - * With 4K pages, a large buffer thus needs 32+92+4+2+1536+62+268 - * bytes, or 1996 bytes, which fits comfortably into 2048 bytes. - * - * With 4K pages, a small buffer thus needs 32+92+4+2+126+268 - * bytes, or 524 bytes, which is annoyingly wasteful. - * - * Maybe we should increase LIPP_SMALL_PACKET_SIZE to 192? - * - * ISSUE: Maybe we should increase "NET_SKB_PAD" to 64? - */ -static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info, - bool small) -{ -#if TILE_NET_MTU <= 1536 - /* Without "jumbo", 2 + 1536 should be sufficient. */ - unsigned int large_size = NET_IP_ALIGN + 1536; -#else - /* ISSUE: This has not been tested. */ - unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100; -#endif - - /* Avoid "false sharing" with last cache line. */ - /* ISSUE: This is already done by "netdev_alloc_skb()". */ - unsigned int len = - (((small ? LIPP_SMALL_PACKET_SIZE : large_size) + - CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE()); - - unsigned int padding = 128 - NET_SKB_PAD; - unsigned int align; - - struct sk_buff *skb; - void *va; - - struct sk_buff **skb_ptr; - - /* Request 96 extra bytes for alignment purposes. */ - skb = netdev_alloc_skb(info->napi.dev, len + padding); - if (skb == NULL) - return false; - - /* Skip 32 or 96 bytes to align "data" mod 128. */ - align = -(long)skb->data & (128 - 1); - BUG_ON(align > padding); - skb_reserve(skb, align); - - /* This address is given to IPP. */ - va = skb->data; - - /* Buffers must not span a huge page. */ - BUG_ON(((((long)va & ~HPAGE_MASK) + len) & HPAGE_MASK) != 0); - -#ifdef TILE_NET_PARANOIA -#if CHIP_HAS_CBOX_HOME_MAP() - if (hash_default) { - HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va); - if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3) - panic("Non-HFH ingress buffer! VA=%p Mode=%d PTE=%llx", - va, hv_pte_get_mode(pte), hv_pte_val(pte)); - } -#endif -#endif - - /* Invalidate the packet buffer. */ - if (!hash_default) - __inv_buffer(va, len); - - /* Skip two bytes to satisfy LIPP assumptions. */ - /* Note that this aligns IP on a 16 byte boundary. */ - /* ISSUE: Do this when the packet arrives? */ - skb_reserve(skb, NET_IP_ALIGN); - - /* Save a back-pointer to 'skb'. */ - skb_ptr = va - sizeof(*skb_ptr); - *skb_ptr = skb; - - /* Make sure "skb_ptr" has been flushed. */ - __insn_mf(); - - /* Provide the new buffer. */ - tile_net_provide_linux_buffer(info, va, small); - - return true; -} - - -/* - * Provide linux buffers for LIPP. - */ -static void tile_net_provide_needed_buffers(struct tile_net_cpu *info) -{ - while (info->num_needed_small_buffers != 0) { - if (!tile_net_provide_needed_buffer(info, true)) - goto oops; - info->num_needed_small_buffers--; - } - - while (info->num_needed_large_buffers != 0) { - if (!tile_net_provide_needed_buffer(info, false)) - goto oops; - info->num_needed_large_buffers--; - } - - return; - -oops: - - /* Add a description to the page allocation failure dump. */ - pr_notice("Could not provide a linux buffer to LIPP.\n"); -} - - -/* - * Grab some LEPP completions, and store them in "comps", of size - * "comps_size", and return the number of completions which were - * stored, so the caller can free them. - */ -static unsigned int tile_net_lepp_grab_comps(lepp_queue_t *eq, - struct sk_buff *comps[], - unsigned int comps_size, - unsigned int min_size) -{ - unsigned int n = 0; - - unsigned int comp_head = eq->comp_head; - unsigned int comp_busy = eq->comp_busy; - - while (comp_head != comp_busy && n < comps_size) { - comps[n++] = eq->comps[comp_head]; - LEPP_QINC(comp_head); - } - - if (n < min_size) - return 0; - - eq->comp_head = comp_head; - - return n; -} - - -/* - * Free some comps, and return true iff there are still some pending. - */ -static bool tile_net_lepp_free_comps(struct net_device *dev, bool all) -{ - struct tile_net_priv *priv = netdev_priv(dev); - - lepp_queue_t *eq = priv->eq; - - struct sk_buff *olds[64]; - unsigned int wanted = 64; - unsigned int i, n; - bool pending; - - spin_lock(&priv->eq_lock); - - if (all) - eq->comp_busy = eq->comp_tail; - - n = tile_net_lepp_grab_comps(eq, olds, wanted, 0); - - pending = (eq->comp_head != eq->comp_tail); - - spin_unlock(&priv->eq_lock); - - for (i = 0; i < n; i++) - kfree_skb(olds[i]); - - return pending; -} - - -/* - * Make sure the egress timer is scheduled. - * - * Note that we use "schedule if not scheduled" logic instead of the more - * obvious "reschedule" logic, because "reschedule" is fairly expensive. - */ -static void tile_net_schedule_egress_timer(struct tile_net_cpu *info) -{ - if (!info->egress_timer_scheduled) { - mod_timer(&info->egress_timer, jiffies + 1); - info->egress_timer_scheduled = true; - } -} - - -/* - * The "function" for "info->egress_timer". - * - * This timer will reschedule itself as long as there are any pending - * completions expected (on behalf of any tile). - * - * ISSUE: Realistically, will the timer ever stop scheduling itself? - * - * ISSUE: This timer is almost never actually needed, so just use a global - * timer that can run on any tile. - * - * ISSUE: Maybe instead track number of expected completions, and free - * only that many, resetting to zero if "pending" is ever false. - */ -static void tile_net_handle_egress_timer(struct timer_list *t) -{ - struct tile_net_cpu *info = from_timer(info, t, egress_timer); - struct net_device *dev = info->napi.dev; - - /* The timer is no longer scheduled. */ - info->egress_timer_scheduled = false; - - /* Free comps, and reschedule timer if more are pending. */ - if (tile_net_lepp_free_comps(dev, false)) - tile_net_schedule_egress_timer(info); -} - - -static void tile_net_discard_aux(struct tile_net_cpu *info, int index) -{ - struct tile_netio_queue *queue = &info->queue; - netio_queue_impl_t *qsp = queue->__system_part; - netio_queue_user_impl_t *qup = &queue->__user_part; - - int index2_aux = index + sizeof(netio_pkt_t); - int index2 = - ((index2_aux == - qsp->__packet_receive_queue.__last_packet_plus_one) ? - 0 : index2_aux); - - netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index); - - /* Extract the "linux_buffer_t". */ - unsigned int buffer = pkt->__packet.word; - - /* Convert "linux_buffer_t" to "va". */ - void *va = __va((phys_addr_t)(buffer >> 1) << 7); - - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - kfree_skb(skb); - - /* Consume this packet. */ - qup->__packet_receive_read = index2; -} - - -/* - * Like "tile_net_poll()", but just discard packets. - */ -static void tile_net_discard_packets(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - struct tile_netio_queue *queue = &info->queue; - netio_queue_impl_t *qsp = queue->__system_part; - netio_queue_user_impl_t *qup = &queue->__user_part; - - while (qup->__packet_receive_read != - qsp->__packet_receive_queue.__packet_write) { - int index = qup->__packet_receive_read; - tile_net_discard_aux(info, index); - } -} - - -/* - * Handle the next packet. Return true if "processed", false if "filtered". - */ -static bool tile_net_poll_aux(struct tile_net_cpu *info, int index) -{ - struct net_device *dev = info->napi.dev; - - struct tile_netio_queue *queue = &info->queue; - netio_queue_impl_t *qsp = queue->__system_part; - netio_queue_user_impl_t *qup = &queue->__user_part; - struct tile_net_stats_t *stats = &info->stats; - - int filter; - - int index2_aux = index + sizeof(netio_pkt_t); - int index2 = - ((index2_aux == - qsp->__packet_receive_queue.__last_packet_plus_one) ? - 0 : index2_aux); - - netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index); - - netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt); - netio_pkt_status_t pkt_status = NETIO_PKT_STATUS_M(metadata, pkt); - - /* Extract the packet size. FIXME: Shouldn't the second line */ - /* get subtracted? Mostly moot, since it should be "zero". */ - unsigned long len = - (NETIO_PKT_CUSTOM_LENGTH(pkt) + - NET_IP_ALIGN - NETIO_PACKET_PADDING); - - /* Extract the "linux_buffer_t". */ - unsigned int buffer = pkt->__packet.word; - - /* Extract "small" (vs "large"). */ - bool small = ((buffer & 1) != 0); - - /* Convert "linux_buffer_t" to "va". */ - void *va = __va((phys_addr_t)(buffer >> 1) << 7); - - /* Extract the packet data pointer. */ - /* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */ - unsigned char *buf = va + NET_IP_ALIGN; - - /* Invalidate the packet buffer. */ - if (!hash_default) - __inv_buffer(buf, len); - -#ifdef TILE_NET_DUMP_PACKETS - dump_packet(buf, len, "rx"); -#endif /* TILE_NET_DUMP_PACKETS */ - -#ifdef TILE_NET_VERIFY_INGRESS - if (pkt_status == NETIO_PKT_STATUS_OVERSIZE && len >= 64) { - dump_packet(buf, len, "rx"); - panic("Unexpected OVERSIZE."); - } -#endif - - filter = 0; - - if (pkt_status == NETIO_PKT_STATUS_BAD) { - /* Handle CRC error and hardware truncation. */ - filter = 2; - } else if (!(dev->flags & IFF_UP)) { - /* Filter packets received before we're up. */ - filter = 1; - } else if (NETIO_PKT_ETHERTYPE_RECOGNIZED_M(metadata, pkt) && - pkt_status == NETIO_PKT_STATUS_UNDERSIZE) { - /* Filter "truncated" packets. */ - filter = 2; - } else if (!(dev->flags & IFF_PROMISC)) { - if (!is_multicast_ether_addr(buf)) { - /* Filter packets not for our address. */ - const u8 *mine = dev->dev_addr; - filter = !ether_addr_equal(mine, buf); - } - } - - u64_stats_update_begin(&stats->syncp); - - if (filter != 0) { - - if (filter == 1) - stats->rx_dropped++; - else - stats->rx_errors++; - - tile_net_provide_linux_buffer(info, va, small); - - } else { - - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - /* Paranoia. */ - if (skb->data != buf) - panic("Corrupt linux buffer from LIPP! " - "VA=%p, skb=%p, skb->data=%p\n", - va, skb, skb->data); - - /* Encode the actual packet length. */ - skb_put(skb, len); - - /* NOTE: This call also sets "skb->dev = dev". */ - skb->protocol = eth_type_trans(skb, dev); - - /* Avoid recomputing "good" TCP/UDP checksums. */ - if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - netif_receive_skb(skb); - - stats->rx_packets++; - stats->rx_bytes += len; - } - - u64_stats_update_end(&stats->syncp); - - /* ISSUE: It would be nice to defer this until the packet has */ - /* actually been processed. */ - tile_net_return_credit(info); - - /* Consume this packet. */ - qup->__packet_receive_read = index2; - - return !filter; -} - - -/* - * Handle some packets for the given device on the current CPU. - * - * If "tile_net_stop()" is called on some other tile while this - * function is running, we will return, hopefully before that - * other tile asks us to call "napi_disable()". - * - * The "rotting packet" race condition occurs if a packet arrives - * during the extremely narrow window between the queue appearing to - * be empty, and the ingress interrupt being re-enabled. This happens - * a LOT under heavy network load. - */ -static int tile_net_poll(struct napi_struct *napi, int budget) -{ - struct net_device *dev = napi->dev; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - struct tile_netio_queue *queue = &info->queue; - netio_queue_impl_t *qsp = queue->__system_part; - netio_queue_user_impl_t *qup = &queue->__user_part; - - unsigned int work = 0; - - if (budget <= 0) - goto done; - - while (priv->active) { - int index = qup->__packet_receive_read; - if (index == qsp->__packet_receive_queue.__packet_write) - break; - - if (tile_net_poll_aux(info, index)) { - if (++work >= budget) - goto done; - } - } - - napi_complete_done(&info->napi, work); - - if (!priv->active) - goto done; - - /* Re-enable the ingress interrupt. */ - enable_percpu_irq(priv->intr_id, 0); - - /* HACK: Avoid the "rotting packet" problem (see above). */ - if (qup->__packet_receive_read != - qsp->__packet_receive_queue.__packet_write) { - /* ISSUE: Sometimes this returns zero, presumably */ - /* because an interrupt was handled for this tile. */ - (void)napi_reschedule(&info->napi); - } - -done: - - if (priv->active) - tile_net_provide_needed_buffers(info); - - return work; -} - - -/* - * Handle an ingress interrupt for the given device on the current cpu. - * - * ISSUE: Sometimes this gets called after "disable_percpu_irq()" has - * been called! This is probably due to "pending hypervisor downcalls". - * - * ISSUE: Is there any race condition between the "napi_schedule()" here - * and the "napi_complete()" call above? - */ -static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - - /* Disable the ingress interrupt. */ - disable_percpu_irq(priv->intr_id); - - /* Ignore unwanted interrupts. */ - if (!priv->active) - return IRQ_HANDLED; - - /* ISSUE: Sometimes "info->napi_enabled" is false here. */ - - napi_schedule(&info->napi); - - return IRQ_HANDLED; -} - - -/* - * One time initialization per interface. - */ -static int tile_net_open_aux(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - - int ret; - int dummy; - unsigned int epp_lotar; - - /* - * Find out where EPP memory should be homed. - */ - ret = hv_dev_pread(priv->hv_devhdl, 0, - (HV_VirtAddr)&epp_lotar, sizeof(epp_lotar), - NETIO_EPP_SHM_OFF); - if (ret < 0) { - pr_err("could not read epp_shm_queue lotar.\n"); - return -EIO; - } - - /* - * Home the page on the EPP. - */ - { - int epp_home = hv_lotar_to_cpu(epp_lotar); - homecache_change_page_home(priv->eq_pages, EQ_ORDER, epp_home); - } - - /* - * Register the EPP shared memory queue. - */ - { - netio_ipp_address_t ea = { - .va = 0, - .pa = __pa(priv->eq), - .pte = hv_pte(0), - .size = EQ_SIZE, - }; - ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar); - ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3); - ret = hv_dev_pwrite(priv->hv_devhdl, 0, - (HV_VirtAddr)&ea, - sizeof(ea), - NETIO_EPP_SHM_OFF); - if (ret < 0) - return -EIO; - } - - /* - * Start LIPP/LEPP. - */ - if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, - sizeof(dummy), NETIO_IPP_START_SHIM_OFF) < 0) { - pr_warn("Failed to start LIPP/LEPP\n"); - return -EIO; - } - - return 0; -} - - -/* - * Register with hypervisor on the current CPU. - * - * Strangely, this function does important things even if it "fails", - * which is especially common if the link is not up yet. Hopefully - * these things are all "harmless" if done twice! - */ -static void tile_net_register(void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info; - - struct tile_netio_queue *queue; - - /* Only network cpus can receive packets. */ - int queue_id = - cpumask_test_cpu(my_cpu, &priv->network_cpus_map) ? 0 : 255; - - netio_input_config_t config = { - .flags = 0, - .num_receive_packets = priv->network_cpus_credits, - .queue_id = queue_id - }; - - int ret = 0; - netio_queue_impl_t *queuep; - - PDEBUG("tile_net_register(queue_id %d)\n", queue_id); - - if (!strcmp(dev->name, "xgbe0")) - info = this_cpu_ptr(&hv_xgbe0); - else if (!strcmp(dev->name, "xgbe1")) - info = this_cpu_ptr(&hv_xgbe1); - else if (!strcmp(dev->name, "gbe0")) - info = this_cpu_ptr(&hv_gbe0); - else if (!strcmp(dev->name, "gbe1")) - info = this_cpu_ptr(&hv_gbe1); - else - BUG(); - - /* Initialize the egress timer. */ - timer_setup(&info->egress_timer, tile_net_handle_egress_timer, - TIMER_PINNED); - - u64_stats_init(&info->stats.syncp); - - priv->cpu[my_cpu] = info; - - /* - * Register ourselves with LIPP. This does a lot of stuff, - * including invoking the LIPP registration code. - */ - ret = hv_dev_pwrite(priv->hv_devhdl, 0, - (HV_VirtAddr)&config, - sizeof(netio_input_config_t), - NETIO_IPP_INPUT_REGISTER_OFF); - PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n", - ret); - if (ret < 0) { - if (ret != NETIO_LINK_DOWN) { - printk(KERN_DEBUG "hv_dev_pwrite " - "NETIO_IPP_INPUT_REGISTER_OFF failure %d\n", - ret); - } - info->link_down = (ret == NETIO_LINK_DOWN); - return; - } - - /* - * Get the pointer to our queue's system part. - */ - - ret = hv_dev_pread(priv->hv_devhdl, 0, - (HV_VirtAddr)&queuep, - sizeof(netio_queue_impl_t *), - NETIO_IPP_INPUT_REGISTER_OFF); - PDEBUG("hv_dev_pread(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n", - ret); - PDEBUG("queuep %p\n", queuep); - if (ret <= 0) { - /* ISSUE: Shouldn't this be a fatal error? */ - pr_err("hv_dev_pread NETIO_IPP_INPUT_REGISTER_OFF failure\n"); - return; - } - - queue = &info->queue; - - queue->__system_part = queuep; - - memset(&queue->__user_part, 0, sizeof(netio_queue_user_impl_t)); - - /* This is traditionally "config.num_receive_packets / 2". */ - queue->__user_part.__receive_credit_interval = 4; - queue->__user_part.__receive_credit_remaining = - queue->__user_part.__receive_credit_interval; - - /* - * Get a fastio index from the hypervisor. - * ISSUE: Shouldn't this check the result? - */ - ret = hv_dev_pread(priv->hv_devhdl, 0, - (HV_VirtAddr)&queue->__user_part.__fastio_index, - sizeof(queue->__user_part.__fastio_index), - NETIO_IPP_GET_FASTIO_OFF); - PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret); - - /* Now we are registered. */ - info->registered = true; -} - - -/* - * Deregister with hypervisor on the current CPU. - * - * This simply discards all our credits, so no more packets will be - * delivered to this tile. There may still be packets in our queue. - * - * Also, disable the ingress interrupt. - */ -static void tile_net_deregister(void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - - /* Disable the ingress interrupt. */ - disable_percpu_irq(priv->intr_id); - - /* Do nothing else if not registered. */ - if (info == NULL || !info->registered) - return; - - { - struct tile_netio_queue *queue = &info->queue; - netio_queue_user_impl_t *qup = &queue->__user_part; - - /* Discard all our credits. */ - __netio_fastio_return_credits(qup->__fastio_index, -1); - } -} - - -/* - * Unregister with hypervisor on the current CPU. - * - * Also, disable the ingress interrupt. - */ -static void tile_net_unregister(void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - - int ret; - int dummy = 0; - - /* Disable the ingress interrupt. */ - disable_percpu_irq(priv->intr_id); - - /* Do nothing else if not registered. */ - if (info == NULL || !info->registered) - return; - - /* Unregister ourselves with LIPP/LEPP. */ - ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, - sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF); - if (ret < 0) - panic("Failed to unregister with LIPP/LEPP!\n"); - - /* Discard all packets still in our NetIO queue. */ - tile_net_discard_packets(dev); - - /* Reset state. */ - info->num_needed_small_buffers = 0; - info->num_needed_large_buffers = 0; - - /* Cancel egress timer. */ - del_timer(&info->egress_timer); - info->egress_timer_scheduled = false; -} - - -/* - * Helper function for "tile_net_stop()". - * - * Also used to handle registration failure in "tile_net_open_inner()", - * when the various extra steps in "tile_net_stop()" are not necessary. - */ -static void tile_net_stop_aux(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int i; - - int dummy = 0; - - /* - * Unregister all tiles, so LIPP will stop delivering packets. - * Also, delete all the "napi" objects (sequentially, to protect - * "dev->napi_list"). - */ - on_each_cpu(tile_net_unregister, (void *)dev, 1); - for_each_online_cpu(i) { - struct tile_net_cpu *info = priv->cpu[i]; - if (info != NULL && info->registered) { - netif_napi_del(&info->napi); - info->registered = false; - } - } - - /* Stop LIPP/LEPP. */ - if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, - sizeof(dummy), NETIO_IPP_STOP_SHIM_OFF) < 0) - panic("Failed to stop LIPP/LEPP!\n"); - - priv->partly_opened = false; -} - - -/* - * Disable NAPI for the given device on the current cpu. - */ -static void tile_net_stop_disable(void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - - /* Disable NAPI if needed. */ - if (info != NULL && info->napi_enabled) { - napi_disable(&info->napi); - info->napi_enabled = false; - } -} - - -/* - * Enable NAPI and the ingress interrupt for the given device - * on the current cpu. - * - * ISSUE: Only do this for "network cpus"? - */ -static void tile_net_open_enable(void *dev_ptr) -{ - struct net_device *dev = (struct net_device *)dev_ptr; - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - - /* Enable NAPI. */ - napi_enable(&info->napi); - info->napi_enabled = true; - - /* Enable the ingress interrupt. */ - enable_percpu_irq(priv->intr_id, 0); -} - - -/* - * tile_net_open_inner does most of the work of bringing up the interface. - * It's called from tile_net_open(), and also from tile_net_retry_open(). - * The return value is 0 if the interface was brought up, < 0 if - * tile_net_open() should return the return value as an error, and > 0 if - * tile_net_open() should return success and schedule a work item to - * periodically retry the bringup. - */ -static int tile_net_open_inner(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info; - struct tile_netio_queue *queue; - int result = 0; - int i; - int dummy = 0; - - /* - * First try to register just on the local CPU, and handle any - * semi-expected "link down" failure specially. Note that we - * do NOT call "tile_net_stop_aux()", unlike below. - */ - tile_net_register(dev); - info = priv->cpu[my_cpu]; - if (!info->registered) { - if (info->link_down) - return 1; - return -EAGAIN; - } - - /* - * Now register everywhere else. If any registration fails, - * even for "link down" (which might not be possible), we - * clean up using "tile_net_stop_aux()". Also, add all the - * "napi" objects (sequentially, to protect "dev->napi_list"). - * ISSUE: Only use "netif_napi_add()" for "network cpus"? - */ - smp_call_function(tile_net_register, (void *)dev, 1); - for_each_online_cpu(i) { - struct tile_net_cpu *info = priv->cpu[i]; - if (info->registered) - netif_napi_add(dev, &info->napi, tile_net_poll, 64); - else - result = -EAGAIN; - } - if (result != 0) { - tile_net_stop_aux(dev); - return result; - } - - queue = &info->queue; - - if (priv->intr_id == 0) { - unsigned int irq; - - /* - * Acquire the irq allocated by the hypervisor. Every - * queue gets the same irq. The "__intr_id" field is - * "1 << irq", so we use "__ffs()" to extract "irq". - */ - priv->intr_id = queue->__system_part->__intr_id; - BUG_ON(priv->intr_id == 0); - irq = __ffs(priv->intr_id); - - /* - * Register the ingress interrupt handler for this - * device, permanently. - * - * We used to call "free_irq()" in "tile_net_stop()", - * and then re-register the handler here every time, - * but that caused DNP errors in "handle_IRQ_event()" - * because "desc->action" was NULL. See bug 9143. - */ - tile_irq_activate(irq, TILE_IRQ_PERCPU); - BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt, - 0, dev->name, (void *)dev) != 0); - } - - { - /* Allocate initial buffers. */ - - int max_buffers = - priv->network_cpus_count * priv->network_cpus_credits; - - info->num_needed_small_buffers = - min(LIPP_SMALL_BUFFERS, max_buffers); - - info->num_needed_large_buffers = - min(LIPP_LARGE_BUFFERS, max_buffers); - - tile_net_provide_needed_buffers(info); - - if (info->num_needed_small_buffers != 0 || - info->num_needed_large_buffers != 0) - panic("Insufficient memory for buffer stack!"); - } - - /* We are about to be active. */ - priv->active = true; - - /* Make sure "active" is visible to all tiles. */ - mb(); - - /* On each tile, enable NAPI and the ingress interrupt. */ - on_each_cpu(tile_net_open_enable, (void *)dev, 1); - - /* Start LIPP/LEPP and activate "ingress" at the shim. */ - if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy, - sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0) - panic("Failed to activate the LIPP Shim!\n"); - - /* Start our transmit queue. */ - netif_start_queue(dev); - - return 0; -} - - -/* - * Called periodically to retry bringing up the NetIO interface, - * if it doesn't come up cleanly during tile_net_open(). - */ -static void tile_net_open_retry(struct work_struct *w) -{ - struct delayed_work *dw = to_delayed_work(w); - - struct tile_net_priv *priv = - container_of(dw, struct tile_net_priv, retry_work); - - /* - * Try to bring the NetIO interface up. If it fails, reschedule - * ourselves to try again later; otherwise, tell Linux we now have - * a working link. ISSUE: What if the return value is negative? - */ - if (tile_net_open_inner(priv->dev) != 0) - schedule_delayed_work(&priv->retry_work, - TILE_NET_RETRY_INTERVAL); - else - netif_carrier_on(priv->dev); -} - - -/* - * Called when a network interface is made active. - * - * Returns 0 on success, negative value on failure. - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS (if needed), the watchdog timer - * is started, and the stack is notified that the interface is ready. - * - * If the actual link is not available yet, then we tell Linux that - * we have no carrier, and we keep checking until the link comes up. - */ -static int tile_net_open(struct net_device *dev) -{ - int ret = 0; - struct tile_net_priv *priv = netdev_priv(dev); - - /* - * We rely on priv->partly_opened to tell us if this is the - * first time this interface is being brought up. If it is - * set, the IPP was already initialized and should not be - * initialized again. - */ - if (!priv->partly_opened) { - - int count; - int credits; - - /* Initialize LIPP/LEPP, and start the Shim. */ - ret = tile_net_open_aux(dev); - if (ret < 0) { - pr_err("tile_net_open_aux failed: %d\n", ret); - return ret; - } - - /* Analyze the network cpus. */ - - if (network_cpus_used) - cpumask_copy(&priv->network_cpus_map, - &network_cpus_map); - else - cpumask_copy(&priv->network_cpus_map, cpu_online_mask); - - - count = cpumask_weight(&priv->network_cpus_map); - - /* Limit credits to available buffers, and apply min. */ - credits = max(16, (LIPP_LARGE_BUFFERS / count) & ~1); - - /* Apply "GBE" max limit. */ - /* ISSUE: Use higher limit for XGBE? */ - credits = min(NETIO_MAX_RECEIVE_PKTS, credits); - - priv->network_cpus_count = count; - priv->network_cpus_credits = credits; - -#ifdef TILE_NET_DEBUG - pr_info("Using %d network cpus, with %d credits each\n", - priv->network_cpus_count, priv->network_cpus_credits); -#endif - - priv->partly_opened = true; - - } else { - /* FIXME: Is this possible? */ - /* printk("Already partly opened.\n"); */ - } - - /* - * Attempt to bring up the link. - */ - ret = tile_net_open_inner(dev); - if (ret <= 0) { - if (ret == 0) - netif_carrier_on(dev); - return ret; - } - - /* - * We were unable to bring up the NetIO interface, but we want to - * try again in a little bit. Tell Linux that we have no carrier - * so it doesn't try to use the interface before the link comes up - * and then remember to try again later. - */ - netif_carrier_off(dev); - schedule_delayed_work(&priv->retry_work, TILE_NET_RETRY_INTERVAL); - - return 0; -} - - -static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv) -{ - int n = 0; - - /* Drain all the LIPP buffers. */ - while (true) { - unsigned int buffer; - - /* NOTE: This should never fail. */ - if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer, - sizeof(buffer), NETIO_IPP_DRAIN_OFF) < 0) - break; - - /* Stop when done. */ - if (buffer == 0) - break; - - { - /* Convert "linux_buffer_t" to "va". */ - void *va = __va((phys_addr_t)(buffer >> 1) << 7); - - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - kfree_skb(skb); - } - - n++; - } - - return n; -} - - -/* - * Disables a network interface. - * - * Returns 0, this is not allowed to fail. - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - * - * ISSUE: How closely does "netif_running(dev)" mirror "priv->active"? - * - * Before we are called by "__dev_close()", "netif_running()" will - * have been cleared, so no NEW calls to "tile_net_poll()" will be - * made by "netpoll_poll_dev()". - * - * Often, this can cause some tiles to still have packets in their - * queues, so we must call "tile_net_discard_packets()" later. - * - * Note that some other tile may still be INSIDE "tile_net_poll()", - * and in fact, many will be, if there is heavy network load. - * - * Calling "on_each_cpu(tile_net_stop_disable, (void *)dev, 1)" when - * any tile is still "napi_schedule()"'d will induce a horrible crash - * when "msleep()" is called. This includes tiles which are inside - * "tile_net_poll()" which have not yet called "napi_complete()". - * - * So, we must first try to wait long enough for other tiles to finish - * with any current "tile_net_poll()" call, and, hopefully, to clear - * the "scheduled" flag. ISSUE: It is unclear what happens to tiles - * which have called "napi_schedule()" but which had not yet tried to - * call "tile_net_poll()", or which exhausted their budget inside - * "tile_net_poll()" just before this function was called. - */ -static int tile_net_stop(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - - PDEBUG("tile_net_stop()\n"); - - /* Start discarding packets. */ - priv->active = false; - - /* Make sure "active" is visible to all tiles. */ - mb(); - - /* - * On each tile, make sure no NEW packets get delivered, and - * disable the ingress interrupt. - * - * Note that the ingress interrupt can fire AFTER this, - * presumably due to packets which were recently delivered, - * but it will have no effect. - */ - on_each_cpu(tile_net_deregister, (void *)dev, 1); - - /* Optimistically drain LIPP buffers. */ - (void)tile_net_drain_lipp_buffers(priv); - - /* ISSUE: Only needed if not yet fully open. */ - cancel_delayed_work_sync(&priv->retry_work); - - /* Can't transmit any more. */ - netif_stop_queue(dev); - - /* Disable NAPI on each tile. */ - on_each_cpu(tile_net_stop_disable, (void *)dev, 1); - - /* - * Drain any remaining LIPP buffers. NOTE: This "printk()" - * has never been observed, but in theory it could happen. - */ - if (tile_net_drain_lipp_buffers(priv) != 0) - printk("Had to drain some extra LIPP buffers!\n"); - - /* Stop LIPP/LEPP. */ - tile_net_stop_aux(dev); - - /* - * ISSUE: It appears that, in practice anyway, by the time we - * get here, there are no pending completions, but just in case, - * we free (all of) them anyway. - */ - while (tile_net_lepp_free_comps(dev, true)) - /* loop */; - - /* Wipe the EPP queue, and wait till the stores hit the EPP. */ - memset(priv->eq, 0, sizeof(lepp_queue_t)); - mb(); - - return 0; -} - - -/* - * Prepare the "frags" info for the resulting LEPP command. - * - * If needed, flush the memory used by the frags. - */ -static unsigned int tile_net_tx_frags(lepp_frag_t *frags, - struct sk_buff *skb, - void *b_data, unsigned int b_len) -{ - unsigned int i, n = 0; - - struct skb_shared_info *sh = skb_shinfo(skb); - - phys_addr_t cpa; - - if (b_len != 0) { - - if (!hash_default) - finv_buffer_remote(b_data, b_len, 0); - - cpa = __pa(b_data); - frags[n].cpa_lo = cpa; - frags[n].cpa_hi = cpa >> 32; - frags[n].length = b_len; - frags[n].hash_for_home = hash_default; - n++; - } - - for (i = 0; i < sh->nr_frags; i++) { - - skb_frag_t *f = &sh->frags[i]; - unsigned long pfn = page_to_pfn(skb_frag_page(f)); - - /* FIXME: Compute "hash_for_home" properly. */ - /* ISSUE: The hypervisor checks CHIP_HAS_REV1_DMA_PACKETS(). */ - int hash_for_home = hash_default; - - /* FIXME: Hmmm. */ - if (!hash_default) { - void *va = pfn_to_kaddr(pfn) + f->page_offset; - BUG_ON(PageHighMem(skb_frag_page(f))); - finv_buffer_remote(va, skb_frag_size(f), 0); - } - - cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset; - frags[n].cpa_lo = cpa; - frags[n].cpa_hi = cpa >> 32; - frags[n].length = skb_frag_size(f); - frags[n].hash_for_home = hash_for_home; - n++; - } - - return n; -} - - -/* - * This function takes "skb", consisting of a header template and a - * payload, and hands it to LEPP, to emit as one or more segments, - * each consisting of a possibly modified header, plus a piece of the - * payload, via a process known as "tcp segmentation offload". - * - * Usually, "data" will contain the header template, of size "sh_len", - * and "sh->frags" will contain "skb->data_len" bytes of payload, and - * there will be "sh->gso_segs" segments. - * - * Sometimes, if "sendfile()" requires copying, we will be called with - * "data" containing the header and payload, with "frags" being empty. - * - * Sometimes, for example when using NFS over TCP, a single segment can - * span 3 fragments, which must be handled carefully in LEPP. - * - * See "emulate_large_send_offload()" for some reference code, which - * does not handle checksumming. - * - * ISSUE: How do we make sure that high memory DMA does not migrate? - */ -static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - struct tile_net_stats_t *stats = &info->stats; - - struct skb_shared_info *sh = skb_shinfo(skb); - - unsigned char *data = skb->data; - - /* The ip header follows the ethernet header. */ - struct iphdr *ih = ip_hdr(skb); - unsigned int ih_len = ih->ihl * 4; - - /* Note that "nh == ih", by definition. */ - unsigned char *nh = skb_network_header(skb); - unsigned int eh_len = nh - data; - - /* The tcp header follows the ip header. */ - struct tcphdr *th = (struct tcphdr *)(nh + ih_len); - unsigned int th_len = th->doff * 4; - - /* The total number of header bytes. */ - /* NOTE: This may be less than skb_headlen(skb). */ - unsigned int sh_len = eh_len + ih_len + th_len; - - /* The number of payload bytes at "skb->data + sh_len". */ - /* This is non-zero for sendfile() without HIGHDMA. */ - unsigned int b_len = skb_headlen(skb) - sh_len; - - /* The total number of payload bytes. */ - unsigned int d_len = b_len + skb->data_len; - - /* The maximum payload size. */ - unsigned int p_len = sh->gso_size; - - /* The total number of segments. */ - unsigned int num_segs = sh->gso_segs; - - /* The temporary copy of the command. */ - u32 cmd_body[(LEPP_MAX_CMD_SIZE + 3) / 4]; - lepp_tso_cmd_t *cmd = (lepp_tso_cmd_t *)cmd_body; - - /* Analyze the "frags". */ - unsigned int num_frags = - tile_net_tx_frags(cmd->frags, skb, data + sh_len, b_len); - - /* The size of the command, including frags and header. */ - size_t cmd_size = LEPP_TSO_CMD_SIZE(num_frags, sh_len); - - /* The command header. */ - lepp_tso_cmd_t cmd_init = { - .tso = true, - .header_size = sh_len, - .ip_offset = eh_len, - .tcp_offset = eh_len + ih_len, - .payload_size = p_len, - .num_frags = num_frags, - }; - - unsigned long irqflags; - - lepp_queue_t *eq = priv->eq; - - struct sk_buff *olds[8]; - unsigned int wanted = 8; - unsigned int i, nolds = 0; - - unsigned int cmd_head, cmd_tail, cmd_next; - unsigned int comp_tail; - - - /* Paranoia. */ - BUG_ON(skb->protocol != htons(ETH_P_IP)); - BUG_ON(ih->protocol != IPPROTO_TCP); - BUG_ON(skb->ip_summed != CHECKSUM_PARTIAL); - BUG_ON(num_frags > LEPP_MAX_FRAGS); - /*--BUG_ON(num_segs != (d_len + (p_len - 1)) / p_len); */ - BUG_ON(num_segs <= 1); - - - /* Finish preparing the command. */ - - /* Copy the command header. */ - *cmd = cmd_init; - - /* Copy the "header". */ - memcpy(&cmd->frags[num_frags], data, sh_len); - - - /* Prefetch and wait, to minimize time spent holding the spinlock. */ - prefetch_L1(&eq->comp_tail); - prefetch_L1(&eq->cmd_tail); - mb(); - - - /* Enqueue the command. */ - - spin_lock_irqsave(&priv->eq_lock, irqflags); - - /* Handle completions if needed to make room. */ - /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */ - if (lepp_num_free_comp_slots(eq) == 0) { - nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); - if (nolds == 0) { -busy: - spin_unlock_irqrestore(&priv->eq_lock, irqflags); - return NETDEV_TX_BUSY; - } - } - - cmd_head = eq->cmd_head; - cmd_tail = eq->cmd_tail; - - /* Prepare to advance, detecting full queue. */ - /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */ - cmd_next = cmd_tail + cmd_size; - if (cmd_tail < cmd_head && cmd_next >= cmd_head) - goto busy; - if (cmd_next > LEPP_CMD_LIMIT) { - cmd_next = 0; - if (cmd_next == cmd_head) - goto busy; - } - - /* Copy the command. */ - memcpy(&eq->cmds[cmd_tail], cmd, cmd_size); - - /* Advance. */ - cmd_tail = cmd_next; - - /* Record "skb" for eventual freeing. */ - comp_tail = eq->comp_tail; - eq->comps[comp_tail] = skb; - LEPP_QINC(comp_tail); - eq->comp_tail = comp_tail; - - /* Flush before allowing LEPP to handle the command. */ - /* ISSUE: Is this the optimal location for the flush? */ - __insn_mf(); - - eq->cmd_tail = cmd_tail; - - /* NOTE: Using "4" here is more efficient than "0" or "2", */ - /* and, strangely, more efficient than pre-checking the number */ - /* of available completions, and comparing it to 4. */ - if (nolds == 0) - nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4); - - spin_unlock_irqrestore(&priv->eq_lock, irqflags); - - /* Handle completions. */ - for (i = 0; i < nolds; i++) - dev_consume_skb_any(olds[i]); - - /* Update stats. */ - u64_stats_update_begin(&stats->syncp); - stats->tx_packets += num_segs; - stats->tx_bytes += (num_segs * sh_len) + d_len; - u64_stats_update_end(&stats->syncp); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(info); - - return NETDEV_TX_OK; -} - - -/* - * Transmit a packet (called by the kernel via "hard_start_xmit" hook). - */ -static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int my_cpu = smp_processor_id(); - struct tile_net_cpu *info = priv->cpu[my_cpu]; - struct tile_net_stats_t *stats = &info->stats; - - unsigned long irqflags; - - struct skb_shared_info *sh = skb_shinfo(skb); - - unsigned int len = skb->len; - unsigned char *data = skb->data; - - unsigned int csum_start = skb_checksum_start_offset(skb); - - lepp_frag_t frags[1 + MAX_SKB_FRAGS]; - - unsigned int num_frags; - - lepp_queue_t *eq = priv->eq; - - struct sk_buff *olds[8]; - unsigned int wanted = 8; - unsigned int i, nolds = 0; - - unsigned int cmd_size = sizeof(lepp_cmd_t); - - unsigned int cmd_head, cmd_tail, cmd_next; - unsigned int comp_tail; - - lepp_cmd_t cmds[1 + MAX_SKB_FRAGS]; - - - /* - * This is paranoia, since we think that if the link doesn't come - * up, telling Linux we have no carrier will keep it from trying - * to transmit. If it does, though, we can't execute this routine, - * since data structures we depend on aren't set up yet. - */ - if (!info->registered) - return NETDEV_TX_BUSY; - - - /* Save the timestamp. */ - netif_trans_update(dev); - - -#ifdef TILE_NET_PARANOIA -#if CHIP_HAS_CBOX_HOME_MAP() - if (hash_default) { - HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data); - if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3) - panic("Non-HFH egress buffer! VA=%p Mode=%d PTE=%llx", - data, hv_pte_get_mode(pte), hv_pte_val(pte)); - } -#endif -#endif - - -#ifdef TILE_NET_DUMP_PACKETS - /* ISSUE: Does not dump the "frags". */ - dump_packet(data, skb_headlen(skb), "tx"); -#endif /* TILE_NET_DUMP_PACKETS */ - - - if (sh->gso_size != 0) - return tile_net_tx_tso(skb, dev); - - - /* Prepare the commands. */ - - num_frags = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); - - for (i = 0; i < num_frags; i++) { - - bool final = (i == num_frags - 1); - - lepp_cmd_t cmd = { - .cpa_lo = frags[i].cpa_lo, - .cpa_hi = frags[i].cpa_hi, - .length = frags[i].length, - .hash_for_home = frags[i].hash_for_home, - .send_completion = final, - .end_of_packet = final - }; - - if (i == 0 && skb->ip_summed == CHECKSUM_PARTIAL) { - cmd.compute_checksum = 1; - cmd.checksum_data.bits.start_byte = csum_start; - cmd.checksum_data.bits.count = len - csum_start; - cmd.checksum_data.bits.destination_byte = - csum_start + skb->csum_offset; - } - - cmds[i] = cmd; - } - - - /* Prefetch and wait, to minimize time spent holding the spinlock. */ - prefetch_L1(&eq->comp_tail); - prefetch_L1(&eq->cmd_tail); - mb(); - - - /* Enqueue the commands. */ - - spin_lock_irqsave(&priv->eq_lock, irqflags); - - /* Handle completions if needed to make room. */ - /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */ - if (lepp_num_free_comp_slots(eq) == 0) { - nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0); - if (nolds == 0) { -busy: - spin_unlock_irqrestore(&priv->eq_lock, irqflags); - return NETDEV_TX_BUSY; - } - } - - cmd_head = eq->cmd_head; - cmd_tail = eq->cmd_tail; - - /* Copy the commands, or fail. */ - /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */ - for (i = 0; i < num_frags; i++) { - - /* Prepare to advance, detecting full queue. */ - cmd_next = cmd_tail + cmd_size; - if (cmd_tail < cmd_head && cmd_next >= cmd_head) - goto busy; - if (cmd_next > LEPP_CMD_LIMIT) { - cmd_next = 0; - if (cmd_next == cmd_head) - goto busy; - } - - /* Copy the command. */ - *(lepp_cmd_t *)&eq->cmds[cmd_tail] = cmds[i]; - - /* Advance. */ - cmd_tail = cmd_next; - } - - /* Record "skb" for eventual freeing. */ - comp_tail = eq->comp_tail; - eq->comps[comp_tail] = skb; - LEPP_QINC(comp_tail); - eq->comp_tail = comp_tail; - - /* Flush before allowing LEPP to handle the command. */ - /* ISSUE: Is this the optimal location for the flush? */ - __insn_mf(); - - eq->cmd_tail = cmd_tail; - - /* NOTE: Using "4" here is more efficient than "0" or "2", */ - /* and, strangely, more efficient than pre-checking the number */ - /* of available completions, and comparing it to 4. */ - if (nolds == 0) - nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4); - - spin_unlock_irqrestore(&priv->eq_lock, irqflags); - - /* Handle completions. */ - for (i = 0; i < nolds; i++) - dev_consume_skb_any(olds[i]); - - /* HACK: Track "expanded" size for short packets (e.g. 42 < 60). */ - u64_stats_update_begin(&stats->syncp); - stats->tx_packets++; - stats->tx_bytes += ((len >= ETH_ZLEN) ? len : ETH_ZLEN); - u64_stats_update_end(&stats->syncp); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(info); - - return NETDEV_TX_OK; -} - - -/* - * Deal with a transmit timeout. - */ -static void tile_net_tx_timeout(struct net_device *dev) -{ - PDEBUG("tile_net_tx_timeout()\n"); - PDEBUG("Transmit timeout at %ld, latency %ld\n", jiffies, - jiffies - dev_trans_start(dev)); - - /* XXX: ISSUE: This doesn't seem useful for us. */ - netif_wake_queue(dev); -} - - -/* - * Ioctl commands. - */ -static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - return -EOPNOTSUPP; -} - - -/* - * Get System Network Statistics. - * - * Returns the address of the device statistics structure. - */ -static void tile_net_get_stats64(struct net_device *dev, - struct rtnl_link_stats64 *stats) -{ - struct tile_net_priv *priv = netdev_priv(dev); - u64 rx_packets = 0, tx_packets = 0; - u64 rx_bytes = 0, tx_bytes = 0; - u64 rx_errors = 0, rx_dropped = 0; - int i; - - for_each_online_cpu(i) { - struct tile_net_stats_t *cpu_stats; - u64 trx_packets, ttx_packets, trx_bytes, ttx_bytes; - u64 trx_errors, trx_dropped; - unsigned int start; - - if (priv->cpu[i] == NULL) - continue; - cpu_stats = &priv->cpu[i]->stats; - - do { - start = u64_stats_fetch_begin_irq(&cpu_stats->syncp); - trx_packets = cpu_stats->rx_packets; - ttx_packets = cpu_stats->tx_packets; - trx_bytes = cpu_stats->rx_bytes; - ttx_bytes = cpu_stats->tx_bytes; - trx_errors = cpu_stats->rx_errors; - trx_dropped = cpu_stats->rx_dropped; - } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start)); - - rx_packets += trx_packets; - tx_packets += ttx_packets; - rx_bytes += trx_bytes; - tx_bytes += ttx_bytes; - rx_errors += trx_errors; - rx_dropped += trx_dropped; - } - - stats->rx_packets = rx_packets; - stats->tx_packets = tx_packets; - stats->rx_bytes = rx_bytes; - stats->tx_bytes = tx_bytes; - stats->rx_errors = rx_errors; - stats->rx_dropped = rx_dropped; -} - -/* - * Change the Ethernet Address of the NIC. - * - * The hypervisor driver does not support changing MAC address. However, - * the IPP does not do anything with the MAC address, so the address which - * gets used on outgoing packets, and which is accepted on incoming packets, - * is completely up to the NetIO program or kernel driver which is actually - * handling them. - * - * Returns 0 on success, negative on failure. - */ -static int tile_net_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - /* ISSUE: Note that "dev_addr" is now a pointer. */ - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - return 0; -} - - -/* - * Obtain the MAC address from the hypervisor. - * This must be done before opening the device. - */ -static int tile_net_get_mac(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - - char hv_dev_name[32]; - int len; - - __netio_getset_offset_t offset = { .word = NETIO_IPP_PARAM_OFF }; - - int ret; - - /* For example, "xgbe0". */ - strcpy(hv_dev_name, dev->name); - len = strlen(hv_dev_name); - - /* For example, "xgbe/0". */ - hv_dev_name[len] = hv_dev_name[len - 1]; - hv_dev_name[len - 1] = '/'; - len++; - - /* For example, "xgbe/0/native_hash". */ - strcpy(hv_dev_name + len, hash_default ? "/native_hash" : "/native"); - - /* Get the hypervisor handle for this device. */ - priv->hv_devhdl = hv_dev_open((HV_VirtAddr)hv_dev_name, 0); - PDEBUG("hv_dev_open(%s) returned %d %p\n", - hv_dev_name, priv->hv_devhdl, &priv->hv_devhdl); - if (priv->hv_devhdl < 0) { - if (priv->hv_devhdl == HV_ENODEV) - printk(KERN_DEBUG "Ignoring unconfigured device %s\n", - hv_dev_name); - else - printk(KERN_DEBUG "hv_dev_open(%s) returned %d\n", - hv_dev_name, priv->hv_devhdl); - return -1; - } - - /* - * Read the hardware address from the hypervisor. - * ISSUE: Note that "dev_addr" is now a pointer. - */ - offset.bits.class = NETIO_PARAM; - offset.bits.addr = NETIO_PARAM_MAC; - ret = hv_dev_pread(priv->hv_devhdl, 0, - (HV_VirtAddr)dev->dev_addr, dev->addr_len, - offset.word); - PDEBUG("hv_dev_pread(NETIO_PARAM_MAC) returned %d\n", ret); - if (ret <= 0) { - printk(KERN_DEBUG "hv_dev_pread(NETIO_PARAM_MAC) %s failed\n", - dev->name); - /* - * Since the device is configured by the hypervisor but we - * can't get its MAC address, we are most likely running - * the simulator, so let's generate a random MAC address. - */ - eth_hw_addr_random(dev); - } - - return 0; -} - - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void tile_net_netpoll(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - disable_percpu_irq(priv->intr_id); - tile_net_handle_ingress_interrupt(priv->intr_id, dev); - enable_percpu_irq(priv->intr_id, 0); -} -#endif - - -static const struct net_device_ops tile_net_ops = { - .ndo_open = tile_net_open, - .ndo_stop = tile_net_stop, - .ndo_start_xmit = tile_net_tx, - .ndo_do_ioctl = tile_net_ioctl, - .ndo_get_stats64 = tile_net_get_stats64, - .ndo_tx_timeout = tile_net_tx_timeout, - .ndo_set_mac_address = tile_net_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tile_net_netpoll, -#endif -}; - - -/* - * The setup function. - * - * This uses ether_setup() to assign various fields in dev, including - * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. - */ -static void tile_net_setup(struct net_device *dev) -{ - netdev_features_t features = 0; - - ether_setup(dev); - dev->netdev_ops = &tile_net_ops; - dev->watchdog_timeo = TILE_NET_TIMEOUT; - dev->tx_queue_len = TILE_NET_TX_QUEUE_LEN; - - /* MTU range: 68 - 1500 */ - dev->mtu = TILE_NET_MTU; - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = TILE_NET_MTU; - - features |= NETIF_F_HW_CSUM; - features |= NETIF_F_SG; - - /* We support TSO iff the HV supports sufficient frags. */ - if (LEPP_MAX_FRAGS >= 1 + MAX_SKB_FRAGS) - features |= NETIF_F_TSO; - - /* We can't support HIGHDMA without hash_default, since we need - * to be able to finv() with a VA if we don't have hash_default. - */ - if (hash_default) - features |= NETIF_F_HIGHDMA; - - dev->hw_features |= features; - dev->vlan_features |= features; - dev->features |= features; -} - - -/* - * Allocate the device structure, register the device, and obtain the - * MAC address from the hypervisor. - */ -static struct net_device *tile_net_dev_init(const char *name) -{ - int ret; - struct net_device *dev; - struct tile_net_priv *priv; - - /* - * Allocate the device structure. This allocates "priv", calls - * tile_net_setup(), and saves "name". Normally, "name" is a - * template, instantiated by register_netdev(), but not for us. - */ - dev = alloc_netdev(sizeof(*priv), name, NET_NAME_UNKNOWN, - tile_net_setup); - if (!dev) { - pr_err("alloc_netdev(%s) failed\n", name); - return NULL; - } - - priv = netdev_priv(dev); - - /* Initialize "priv". */ - - memset(priv, 0, sizeof(*priv)); - - /* Save "dev" for "tile_net_open_retry()". */ - priv->dev = dev; - - INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry); - - spin_lock_init(&priv->eq_lock); - - /* Allocate "eq". */ - priv->eq_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, EQ_ORDER); - if (!priv->eq_pages) { - free_netdev(dev); - return NULL; - } - priv->eq = page_address(priv->eq_pages); - - /* Register the network device. */ - ret = register_netdev(dev); - if (ret) { - pr_err("register_netdev %s failed %d\n", dev->name, ret); - __free_pages(priv->eq_pages, EQ_ORDER); - free_netdev(dev); - return NULL; - } - - /* Get the MAC address. */ - ret = tile_net_get_mac(dev); - if (ret < 0) { - unregister_netdev(dev); - __free_pages(priv->eq_pages, EQ_ORDER); - free_netdev(dev); - return NULL; - } - - return dev; -} - - -/* - * Module cleanup. - * - * FIXME: If compiled as a module, this module cannot be "unloaded", - * because the "ingress interrupt handler" is registered permanently. - */ -static void tile_net_cleanup(void) -{ - int i; - - for (i = 0; i < TILE_NET_DEVS; i++) { - if (tile_net_devs[i]) { - struct net_device *dev = tile_net_devs[i]; - struct tile_net_priv *priv = netdev_priv(dev); - unregister_netdev(dev); - finv_buffer_remote(priv->eq, EQ_SIZE, 0); - __free_pages(priv->eq_pages, EQ_ORDER); - free_netdev(dev); - } - } -} - - -/* - * Module initialization. - */ -static int tile_net_init_module(void) -{ - pr_info("Tilera Network Driver\n"); - - tile_net_devs[0] = tile_net_dev_init("xgbe0"); - tile_net_devs[1] = tile_net_dev_init("xgbe1"); - tile_net_devs[2] = tile_net_dev_init("gbe0"); - tile_net_devs[3] = tile_net_dev_init("gbe1"); - - return 0; -} - - -module_init(tile_net_init_module); -module_exit(tile_net_cleanup); - - -#ifndef MODULE - -/* - * The "network_cpus" boot argument specifies the cpus that are dedicated - * to handle ingress packets. - * - * The parameter should be in the form "network_cpus=m-n[,x-y]", where - * m, n, x, y are integer numbers that represent the cpus that can be - * neither a dedicated cpu nor a dataplane cpu. - */ -static int __init network_cpus_setup(char *str) -{ - int rc = cpulist_parse_crop(str, &network_cpus_map); - if (rc != 0) { - pr_warn("network_cpus=%s: malformed cpu list\n", str); - } else { - - /* Remove dedicated cpus. */ - cpumask_and(&network_cpus_map, &network_cpus_map, - cpu_possible_mask); - - - if (cpumask_empty(&network_cpus_map)) { - pr_warn("Ignoring network_cpus='%s'\n", str); - } else { - pr_info("Linux network CPUs: %*pbl\n", - cpumask_pr_args(&network_cpus_map)); - network_cpus_used = true; - } - } - - return 0; -} -__setup("network_cpus=", network_cpus_setup); - -#endif diff --git a/drivers/net/wireless/cisco/Kconfig b/drivers/net/wireless/cisco/Kconfig index b22567dff893..8ed0b154bb33 100644 --- a/drivers/net/wireless/cisco/Kconfig +++ b/drivers/net/wireless/cisco/Kconfig @@ -33,7 +33,7 @@ config AIRO config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" - depends on CFG80211 && PCMCIA && (BROKEN || !M32R) + depends on CFG80211 && PCMCIA select WIRELESS_EXT select WEXT_SPY select WEXT_PRIV diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index c3ba14f6444e..36db2098ee18 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2320,25 +2320,6 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, quirk_unhide_mch_dev6); -#ifdef CONFIG_TILEPRO -/* - * The Tilera TILEmpower tilepro platform needs to set the link speed - * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed - * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe - * capability register of the PEX8624 PCIe switch. The switch - * supports link speed auto negotiation, but falsely sets - * the link speed to 5GT/s. - */ -static void quirk_tile_plx_gen1(struct pci_dev *dev) -{ - if (tile_plx_gen1) { - pci_write_config_dword(dev, 0x98, 0x1); - mdelay(50); - } -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); -#endif /* CONFIG_TILEPRO */ - #ifdef CONFIG_PCI_MSI /* Some chipsets do not support MSI. We cannot easily rely on setting * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d3c378b4db6c..cbbe4a285b48 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -232,25 +232,6 @@ config PCMCIA_PROBE bool default y if ISA && !ARCH_SA1100 && !PARISC -config M32R_PCC - bool "M32R PCMCIA I/F" - depends on M32R && CHIP_M32700 && PCMCIA - help - Say Y here to use the M32R PCMCIA controller. - -config M32R_CFC - bool "M32R CF I/F Controller" - depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT) - help - Say Y here to use the M32R CompactFlash controller. - -config M32R_CFC_NUM - int "M32R CF I/F number" - depends on M32R_CFC - default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT - help - Set the number of M32R CF slots. - config PCMCIA_VRC4171 tristate "NEC VRC4171 Card Controllers support" depends on CPU_VR41XX && ISA && PCMCIA @@ -266,13 +247,6 @@ config OMAP_CF Say Y here to support the CompactFlash controller on OMAP. Note that this doesn't support "True IDE" mode. -config BFIN_CFPCMCIA - tristate "Blackfin CompactFlash PCMCIA Driver" - depends on PCMCIA && BLACKFIN - help - Say Y here to support the CompactFlash PCMCIA driver for Blackfin. - - config AT91_CF tristate "AT91 CompactFlash Controller" depends on PCI diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index e7dae16b9a43..f1f89ddb1bfd 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -28,13 +28,10 @@ obj-$(CONFIG_PCMCIA_SOC_COMMON) += soc_common.o obj-$(CONFIG_PCMCIA_SA11XX_BASE) += sa11xx_base.o obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o -obj-$(CONFIG_M32R_PCC) += m32r_pcc.o -obj-$(CONFIG_M32R_CFC) += m32r_cfc.o obj-$(CONFIG_PCMCIA_BCM63XX) += bcm63xx_pcmcia.o obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o obj-$(CONFIG_OMAP_CF) += omap_cf.o -obj-$(CONFIG_BFIN_CFPCMCIA) += bfin_cf_pcmcia.o obj-$(CONFIG_AT91_CF) += at91_cf.o obj-$(CONFIG_ELECTRA_CF) += electra_cf.o obj-$(CONFIG_PCMCIA_ALCHEMY_DEVBOARD) += db1xxx_ss.o diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c deleted file mode 100644 index 00a296d431ba..000000000000 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * file: drivers/pcmcia/bfin_cf.c - * - * based on: drivers/pcmcia/omap_cf.c - * omap_cf.c -- OMAP 16xx CompactFlash controller driver - * - * Copyright (c) 2005 David Brownell - * Copyright (c) 2006-2008 Michael Hennerich Analog Devices Inc. - * - * bugs: enter bugs at http://blackfin.uclinux.org/ - * - * 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, 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; see the file copying. - * if not, write to the free software foundation, - * 59 temple place - suite 330, boston, ma 02111-1307, usa. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/platform_device.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/gpio.h> - -#include <pcmcia/ss.h> -#include <pcmcia/cisreg.h> - -#define SZ_1K 0x00000400 -#define SZ_8K 0x00002000 -#define SZ_2K (2 * SZ_1K) - -#define POLL_INTERVAL (2 * HZ) - -#define CF_ATASEL_ENA 0x20311802 /* Inverts RESET */ -#define CF_ATASEL_DIS 0x20311800 - -#define bfin_cf_present(pfx) (gpio_get_value(pfx)) - -/*--------------------------------------------------------------------------*/ - -static const char driver_name[] = "bfin_cf_pcmcia"; - -struct bfin_cf_socket { - struct pcmcia_socket socket; - - struct timer_list timer; - unsigned present:1; - unsigned active:1; - - struct platform_device *pdev; - unsigned long phys_cf_io; - unsigned long phys_cf_attr; - u_int irq; - u_short cd_pfx; -}; - -/*--------------------------------------------------------------------------*/ -static int bfin_cf_reset(void) -{ - outw(0, CF_ATASEL_ENA); - mdelay(200); - outw(0, CF_ATASEL_DIS); - - return 0; -} - -static int bfin_cf_ss_init(struct pcmcia_socket *s) -{ - return 0; -} - -/* the timer is primarily to kick this socket's pccardd */ -static void bfin_cf_timer(struct timer_list *t) -{ - struct bfin_cf_socket *cf = from_timer(cf, t, timer); - unsigned short present = bfin_cf_present(cf->cd_pfx); - - if (present != cf->present) { - cf->present = present; - dev_dbg(&cf->pdev->dev, ": card %s\n", - present ? "present" : "gone"); - pcmcia_parse_events(&cf->socket, SS_DETECT); - } - - if (cf->active) - mod_timer(&cf->timer, jiffies + POLL_INTERVAL); -} - -static int bfin_cf_get_status(struct pcmcia_socket *s, u_int *sp) -{ - struct bfin_cf_socket *cf; - - if (!sp) - return -EINVAL; - - cf = container_of(s, struct bfin_cf_socket, socket); - - if (bfin_cf_present(cf->cd_pfx)) { - *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; - s->pcmcia_irq = 0; - s->pci_irq = cf->irq; - - } else - *sp = 0; - return 0; -} - -static int -bfin_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) -{ - - struct bfin_cf_socket *cf; - cf = container_of(sock, struct bfin_cf_socket, socket); - - switch (s->Vcc) { - case 0: - case 33: - break; - case 50: - break; - default: - return -EINVAL; - } - - if (s->flags & SS_RESET) { - disable_irq(cf->irq); - bfin_cf_reset(); - enable_irq(cf->irq); - } - - dev_dbg(&cf->pdev->dev, ": Vcc %d, io_irq %d, flags %04x csc %04x\n", - s->Vcc, s->io_irq, s->flags, s->csc_mask); - - return 0; -} - -static int bfin_cf_ss_suspend(struct pcmcia_socket *s) -{ - return bfin_cf_set_socket(s, &dead_socket); -} - -/* regions are 2K each: mem, attrib, io (and reserved-for-ide) */ - -static int bfin_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) -{ - struct bfin_cf_socket *cf; - - cf = container_of(s, struct bfin_cf_socket, socket); - io->flags &= MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT; - io->start = cf->phys_cf_io; - io->stop = io->start + SZ_2K - 1; - return 0; -} - -static int -bfin_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map) -{ - struct bfin_cf_socket *cf; - - if (map->card_start) - return -EINVAL; - cf = container_of(s, struct bfin_cf_socket, socket); - map->static_start = cf->phys_cf_io; - map->flags &= MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT; - if (map->flags & MAP_ATTRIB) - map->static_start = cf->phys_cf_attr; - - return 0; -} - -static struct pccard_operations bfin_cf_ops = { - .init = bfin_cf_ss_init, - .suspend = bfin_cf_ss_suspend, - .get_status = bfin_cf_get_status, - .set_socket = bfin_cf_set_socket, - .set_io_map = bfin_cf_set_io_map, - .set_mem_map = bfin_cf_set_mem_map, -}; - -/*--------------------------------------------------------------------------*/ - -static int bfin_cf_probe(struct platform_device *pdev) -{ - struct bfin_cf_socket *cf; - struct resource *io_mem, *attr_mem; - int irq; - unsigned short cd_pfx; - int status = 0; - - dev_info(&pdev->dev, "Blackfin CompactFlash/PCMCIA Socket Driver\n"); - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -EINVAL; - - cd_pfx = platform_get_irq(pdev, 1); /*Card Detect GPIO PIN */ - - if (gpio_request(cd_pfx, "pcmcia: CD")) { - dev_err(&pdev->dev, - "Failed ro request Card Detect GPIO_%d\n", - cd_pfx); - return -EBUSY; - } - gpio_direction_input(cd_pfx); - - cf = kzalloc(sizeof *cf, GFP_KERNEL); - if (!cf) { - gpio_free(cd_pfx); - return -ENOMEM; - } - - cf->cd_pfx = cd_pfx; - - timer_setup(&cf->timer, bfin_cf_timer, 0); - - cf->pdev = pdev; - platform_set_drvdata(pdev, cf); - - cf->irq = irq; - cf->socket.pci_irq = irq; - - irq_set_irq_type(irq, IRQF_TRIGGER_LOW); - - io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - - if (!io_mem || !attr_mem) - goto fail0; - - cf->phys_cf_io = io_mem->start; - cf->phys_cf_attr = attr_mem->start; - - /* pcmcia layer only remaps "real" memory */ - cf->socket.io_offset = (unsigned long) - ioremap(cf->phys_cf_io, SZ_2K); - - if (!cf->socket.io_offset) - goto fail0; - - dev_err(&pdev->dev, ": on irq %d\n", irq); - - dev_dbg(&pdev->dev, ": %s\n", - bfin_cf_present(cf->cd_pfx) ? "present" : "(not present)"); - - cf->socket.owner = THIS_MODULE; - cf->socket.dev.parent = &pdev->dev; - cf->socket.ops = &bfin_cf_ops; - cf->socket.resource_ops = &pccard_static_ops; - cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP - | SS_CAP_MEM_ALIGN; - cf->socket.map_size = SZ_2K; - - status = pcmcia_register_socket(&cf->socket); - if (status < 0) - goto fail2; - - cf->active = 1; - mod_timer(&cf->timer, jiffies + POLL_INTERVAL); - return 0; - -fail2: - iounmap((void __iomem *)cf->socket.io_offset); - release_mem_region(cf->phys_cf_io, SZ_8K); - -fail0: - gpio_free(cf->cd_pfx); - kfree(cf); - platform_set_drvdata(pdev, NULL); - - return status; -} - -static int bfin_cf_remove(struct platform_device *pdev) -{ - struct bfin_cf_socket *cf = platform_get_drvdata(pdev); - - gpio_free(cf->cd_pfx); - cf->active = 0; - pcmcia_unregister_socket(&cf->socket); - del_timer_sync(&cf->timer); - iounmap((void __iomem *)cf->socket.io_offset); - release_mem_region(cf->phys_cf_io, SZ_8K); - platform_set_drvdata(pdev, NULL); - kfree(cf); - return 0; -} - -static struct platform_driver bfin_cf_driver = { - .driver = { - .name = driver_name, - }, - .probe = bfin_cf_probe, - .remove = bfin_cf_remove, -}; - -module_platform_driver(bfin_cf_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c deleted file mode 100644 index 9a4940e56e2f..000000000000 --- a/drivers/pcmcia/m32r_cfc.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * drivers/pcmcia/m32r_cfc.c - * - * Device driver for the CFC functionality of M32R. - * - * Copyright (c) 2001, 2002, 2003, 2004 - * Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/bitops.h> -#include <asm/irq.h> -#include <asm/io.h> - -#include <pcmcia/ss.h> - -#undef MAX_IO_WIN /* FIXME */ -#define MAX_IO_WIN 1 -#undef MAX_WIN /* FIXME */ -#define MAX_WIN 1 - -#include "m32r_cfc.h" - -/* Poll status interval -- 0 means default to interrupt */ -static int poll_interval = 0; - -typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t; - -typedef struct pcc_socket { - u_short type, flags; - struct pcmcia_socket socket; - unsigned int number; - unsigned int ioaddr; - u_long mapaddr; - u_long base; /* PCC register base */ - u_char cs_irq1, cs_irq2, intr; - pccard_io_map io_map[MAX_IO_WIN]; - pccard_mem_map mem_map[MAX_WIN]; - u_char io_win; - u_char mem_win; - pcc_as_t current_space; - u_char last_iodbex; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; -#endif -} pcc_socket_t; - -static int pcc_sockets = 0; -static pcc_socket_t socket[M32R_MAX_PCC] = { - { 0, }, /* ... */ -}; - -/*====================================================================*/ - -static unsigned int pcc_get(u_short, unsigned int); -static void pcc_set(u_short, unsigned int , unsigned int ); - -static DEFINE_SPINLOCK(pcc_lock); - -#if !defined(CONFIG_PLAT_USRV) -static inline u_long pcc_port2addr(unsigned long port, int size) { - u_long addr = 0; - u_long odd; - - if (size == 1) { /* byte access */ - odd = (port&1) << 11; - port -= port & 1; - addr = CFC_IO_MAPBASE_BYTE - CFC_IOPORT_BASE + odd + port; - } else if (size == 2) - addr = CFC_IO_MAPBASE_WORD - CFC_IOPORT_BASE + port; - - return addr; -} -#else /* CONFIG_PLAT_USRV */ -static inline u_long pcc_port2addr(unsigned long port, int size) { - u_long odd; - u_long addr = ((port - CFC_IOPORT_BASE) & 0xf000) << 8; - - if (size == 1) { /* byte access */ - odd = port & 1; - port -= odd; - odd <<= 11; - addr = (addr | CFC_IO_MAPBASE_BYTE) + odd + (port & 0xfff); - } else if (size == 2) /* word access */ - addr = (addr | CFC_IO_MAPBASE_WORD) + (port & 0xfff); - - return addr; -} -#endif /* CONFIG_PLAT_USRV */ - -void pcc_ioread_byte(int sock, unsigned long port, void *buf, size_t size, - size_t nmemb, int flag) -{ - u_long addr; - unsigned char *bp = (unsigned char *)buf; - unsigned long flags; - - pr_debug("m32r_cfc: pcc_ioread_byte: sock=%d, port=%#lx, buf=%p, " - "size=%u, nmemb=%d, flag=%d\n", - sock, port, buf, size, nmemb, flag); - - addr = pcc_port2addr(port, 1); - if (!addr) { - printk("m32r_cfc:ioread_byte null port :%#lx\n",port); - return; - } - pr_debug("m32r_cfc: pcc_ioread_byte: addr=%#lx\n", addr); - - spin_lock_irqsave(&pcc_lock, flags); - /* read Byte */ - while (nmemb--) - *bp++ = readb(addr); - spin_unlock_irqrestore(&pcc_lock, flags); -} - -void pcc_ioread_word(int sock, unsigned long port, void *buf, size_t size, - size_t nmemb, int flag) -{ - u_long addr; - unsigned short *bp = (unsigned short *)buf; - unsigned long flags; - - pr_debug("m32r_cfc: pcc_ioread_word: sock=%d, port=%#lx, " - "buf=%p, size=%u, nmemb=%d, flag=%d\n", - sock, port, buf, size, nmemb, flag); - - if (size != 2) - printk("m32r_cfc: ioread_word :illigal size %u : %#lx\n", size, - port); - if (size == 9) - printk("m32r_cfc: ioread_word :insw \n"); - - addr = pcc_port2addr(port, 2); - if (!addr) { - printk("m32r_cfc:ioread_word null port :%#lx\n",port); - return; - } - pr_debug("m32r_cfc: pcc_ioread_word: addr=%#lx\n", addr); - - spin_lock_irqsave(&pcc_lock, flags); - /* read Word */ - while (nmemb--) - *bp++ = readw(addr); - spin_unlock_irqrestore(&pcc_lock, flags); -} - -void pcc_iowrite_byte(int sock, unsigned long port, void *buf, size_t size, - size_t nmemb, int flag) -{ - u_long addr; - unsigned char *bp = (unsigned char *)buf; - unsigned long flags; - - pr_debug("m32r_cfc: pcc_iowrite_byte: sock=%d, port=%#lx, " - "buf=%p, size=%u, nmemb=%d, flag=%d\n", - sock, port, buf, size, nmemb, flag); - - /* write Byte */ - addr = pcc_port2addr(port, 1); - if (!addr) { - printk("m32r_cfc:iowrite_byte null port:%#lx\n",port); - return; - } - pr_debug("m32r_cfc: pcc_iowrite_byte: addr=%#lx\n", addr); - - spin_lock_irqsave(&pcc_lock, flags); - while (nmemb--) - writeb(*bp++, addr); - spin_unlock_irqrestore(&pcc_lock, flags); -} - -void pcc_iowrite_word(int sock, unsigned long port, void *buf, size_t size, - size_t nmemb, int flag) -{ - u_long addr; - unsigned short *bp = (unsigned short *)buf; - unsigned long flags; - - pr_debug("m32r_cfc: pcc_iowrite_word: sock=%d, port=%#lx, " - "buf=%p, size=%u, nmemb=%d, flag=%d\n", - sock, port, buf, size, nmemb, flag); - - if(size != 2) - printk("m32r_cfc: iowrite_word :illigal size %u : %#lx\n", - size, port); - if(size == 9) - printk("m32r_cfc: iowrite_word :outsw \n"); - - addr = pcc_port2addr(port, 2); - if (!addr) { - printk("m32r_cfc:iowrite_word null addr :%#lx\n",port); - return; - } -#if 1 - if (addr & 1) { - printk("m32r_cfc:iowrite_word port addr (%#lx):%#lx\n", port, - addr); - return; - } -#endif - pr_debug("m32r_cfc: pcc_iowrite_word: addr=%#lx\n", addr); - - spin_lock_irqsave(&pcc_lock, flags); - while (nmemb--) - writew(*bp++, addr); - spin_unlock_irqrestore(&pcc_lock, flags); -} - -/*====================================================================*/ - -#define IS_REGISTERED 0x2000 -#define IS_ALIVE 0x8000 - -typedef struct pcc_t { - char *name; - u_short flags; -} pcc_t; - -static pcc_t pcc[] = { -#if !defined(CONFIG_PLAT_USRV) - { "m32r_cfc", 0 }, { "", 0 }, -#else /* CONFIG_PLAT_USRV */ - { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, - { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "", 0 }, -#endif /* CONFIG_PLAT_USRV */ -}; - -static irqreturn_t pcc_interrupt(int, void *); - -/*====================================================================*/ - -static struct timer_list poll_timer; - -static unsigned int pcc_get(u_short sock, unsigned int reg) -{ - unsigned int val = inw(reg); - pr_debug("m32r_cfc: pcc_get: reg(0x%08x)=0x%04x\n", reg, val); - return val; -} - - -static void pcc_set(u_short sock, unsigned int reg, unsigned int data) -{ - outw(data, reg); - pr_debug("m32r_cfc: pcc_set: reg(0x%08x)=0x%04x\n", reg, data); -} - -/*====================================================================== - - See if a card is present, powered up, in IO mode, and already - bound to a (non PC Card) Linux driver. We leave these alone. - - We make an exception for cards that seem to be serial devices. - -======================================================================*/ - -static int __init is_alive(u_short sock) -{ - unsigned int stat; - - pr_debug("m32r_cfc: is_alive:\n"); - - printk("CF: "); - stat = pcc_get(sock, (unsigned int)PLD_CFSTS); - if (!stat) - printk("No "); - printk("Card is detected at socket %d : stat = 0x%08x\n", sock, stat); - pr_debug("m32r_cfc: is_alive: sock stat is 0x%04x\n", stat); - - return 0; -} - -static void add_pcc_socket(ulong base, int irq, ulong mapaddr, - unsigned int ioaddr) -{ - pcc_socket_t *t = &socket[pcc_sockets]; - - pr_debug("m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, " - "mapaddr=%#lx, ioaddr=%08x\n", - base, irq, mapaddr, ioaddr); - - /* add sockets */ - t->ioaddr = ioaddr; - t->mapaddr = mapaddr; -#if !defined(CONFIG_PLAT_USRV) - t->base = 0; - t->flags = 0; - t->cs_irq1 = irq; // insert irq - t->cs_irq2 = irq + 1; // eject irq -#else /* CONFIG_PLAT_USRV */ - t->base = base; - t->flags = 0; - t->cs_irq1 = 0; // insert irq - t->cs_irq2 = 0; // eject irq -#endif /* CONFIG_PLAT_USRV */ - - if (is_alive(pcc_sockets)) - t->flags |= IS_ALIVE; - - /* add pcc */ -#if !defined(CONFIG_PLAT_USRV) - request_region((unsigned int)PLD_CFRSTCR, 0x20, "m32r_cfc"); -#else /* CONFIG_PLAT_USRV */ - { - unsigned int reg_base; - - reg_base = (unsigned int)PLD_CFRSTCR; - reg_base |= pcc_sockets << 8; - request_region(reg_base, 0x20, "m32r_cfc"); - } -#endif /* CONFIG_PLAT_USRV */ - printk(KERN_INFO " %s ", pcc[pcc_sockets].name); - printk("pcc at 0x%08lx\n", t->base); - - /* Update socket interrupt information, capabilities */ - t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP); - t->socket.map_size = M32R_PCC_MAPSIZE; - t->socket.io_offset = ioaddr; /* use for io access offset */ - t->socket.irq_mask = 0; -#if !defined(CONFIG_PLAT_USRV) - t->socket.pci_irq = PLD_IRQ_CFIREQ ; /* card interrupt */ -#else /* CONFIG_PLAT_USRV */ - t->socket.pci_irq = PLD_IRQ_CF0 + pcc_sockets; -#endif /* CONFIG_PLAT_USRV */ - -#ifndef CONFIG_PLAT_USRV - /* insert interrupt */ - request_irq(irq, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt); -#ifndef CONFIG_PLAT_MAPPI3 - /* eject interrupt */ - request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt); -#endif - pr_debug("m32r_cfc: enable CFMSK, RDYSEL\n"); - pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01); -#endif /* CONFIG_PLAT_USRV */ -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) - pcc_set(pcc_sockets, (unsigned int)PLD_CFCR1, 0x0200); -#endif - pcc_sockets++; - - return; -} - - -/*====================================================================*/ - -static irqreturn_t pcc_interrupt(int irq, void *dev) -{ - int i; - u_int events = 0; - int handled = 0; - - pr_debug("m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev); - for (i = 0; i < pcc_sockets; i++) { - if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq) - continue; - - handled = 1; - pr_debug("m32r_cfc: pcc_interrupt: socket %d irq 0x%02x ", - i, irq); - events |= SS_DETECT; /* insert or eject */ - if (events) - pcmcia_parse_events(&socket[i].socket, events); - } - pr_debug("m32r_cfc: pcc_interrupt: done\n"); - - return IRQ_RETVAL(handled); -} /* pcc_interrupt */ - -static void pcc_interrupt_wrapper(struct timer_list *unused) -{ - pr_debug("m32r_cfc: pcc_interrupt_wrapper:\n"); - pcc_interrupt(0, NULL); - poll_timer.expires = jiffies + poll_interval; - add_timer(&poll_timer); -} - -/*====================================================================*/ - -static int _pcc_get_status(u_short sock, u_int *value) -{ - u_int status; - - pr_debug("m32r_cfc: _pcc_get_status:\n"); - status = pcc_get(sock, (unsigned int)PLD_CFSTS); - *value = (status) ? SS_DETECT : 0; - pr_debug("m32r_cfc: _pcc_get_status: status=0x%08x\n", status); - -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) - if ( status ) { - /* enable CF power */ - status = inw((unsigned int)PLD_CPCR); - if (!(status & PLD_CPCR_CF)) { - pr_debug("m32r_cfc: _pcc_get_status: " - "power on (CPCR=0x%08x)\n", status); - status |= PLD_CPCR_CF; - outw(status, (unsigned int)PLD_CPCR); - udelay(100); - } - *value |= SS_POWERON; - - pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);/* enable buffer */ - udelay(100); - - *value |= SS_READY; /* always ready */ - *value |= SS_3VCARD; - } else { - /* disable CF power */ - status = inw((unsigned int)PLD_CPCR); - status &= ~PLD_CPCR_CF; - outw(status, (unsigned int)PLD_CPCR); - udelay(100); - pr_debug("m32r_cfc: _pcc_get_status: " - "power off (CPCR=0x%08x)\n", status); - } -#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) - if ( status ) { - status = pcc_get(sock, (unsigned int)PLD_CPCR); - if (status == 0) { /* power off */ - pcc_set(sock, (unsigned int)PLD_CPCR, 1); - pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */ - udelay(50); - } - *value |= SS_POWERON; - - pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); - udelay(50); - pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101); - udelay(25); /* for IDE reset */ - pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100); - mdelay(2); /* for IDE reset */ - - *value |= SS_READY; - *value |= SS_3VCARD; - } else { - /* disable CF power */ - pcc_set(sock, (unsigned int)PLD_CPCR, 0); - udelay(100); - pr_debug("m32r_cfc: _pcc_get_status: " - "power off (CPCR=0x%08x)\n", status); - } -#else -#error no platform configuration -#endif - pr_debug("m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n", - sock, *value); - return 0; -} /* _get_status */ - -/*====================================================================*/ - -static int _pcc_set_socket(u_short sock, socket_state_t *state) -{ - pr_debug("m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " - "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags, - state->Vcc, state->Vpp, state->io_irq, state->csc_mask); - -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) - if (state->Vcc) { - if ((state->Vcc != 50) && (state->Vcc != 33)) - return -EINVAL; - /* accept 5V and 3.3V */ - } -#endif - if (state->flags & SS_RESET) { - pr_debug(":RESET\n"); - pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101); - }else{ - pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100); - } - if (state->flags & SS_OUTPUT_ENA){ - pr_debug(":OUTPUT_ENA\n"); - /* bit clear */ - pcc_set(sock,(unsigned int)PLD_CFBUFCR,0); - } else { - pcc_set(sock,(unsigned int)PLD_CFBUFCR,1); - } - - if(state->flags & SS_IOCARD){ - pr_debug(":IOCARD"); - } - if (state->flags & SS_PWR_AUTO) { - pr_debug(":PWR_AUTO"); - } - if (state->csc_mask & SS_DETECT) - pr_debug(":csc-SS_DETECT"); - if (state->flags & SS_IOCARD) { - if (state->csc_mask & SS_STSCHG) - pr_debug(":STSCHG"); - } else { - if (state->csc_mask & SS_BATDEAD) - pr_debug(":BATDEAD"); - if (state->csc_mask & SS_BATWARN) - pr_debug(":BATWARN"); - if (state->csc_mask & SS_READY) - pr_debug(":READY"); - } - pr_debug("\n"); - return 0; -} /* _set_socket */ - -/*====================================================================*/ - -static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io) -{ - u_char map; - - pr_debug("m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#llx-%#llx)\n", sock, io->map, io->flags, - io->speed, (unsigned long long)io->start, - (unsigned long long)io->stop); - map = io->map; - - return 0; -} /* _set_io_map */ - -/*====================================================================*/ - -static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem) -{ - - u_char map = mem->map; - u_long addr; - pcc_socket_t *t = &socket[sock]; - - pr_debug("m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#llx, %#x)\n", sock, map, mem->flags, - mem->speed, (unsigned long long)mem->static_start, - mem->card_start); - - /* - * sanity check - */ - if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){ - return -EINVAL; - } - - /* - * de-activate - */ - if ((mem->flags & MAP_ACTIVE) == 0) { - t->current_space = as_none; - return 0; - } - - /* - * Set mode - */ - if (mem->flags & MAP_ATTRIB) { - t->current_space = as_attr; - } else { - t->current_space = as_comm; - } - - /* - * Set address - */ - addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK); - mem->static_start = addr + mem->card_start; - - return 0; - -} /* _set_mem_map */ - -#if 0 /* driver model ordering issue */ -/*====================================================================== - - Routines for accessing socket information and register dumps via - /proc/bus/pccard/... - -======================================================================*/ - -static ssize_t show_info(struct class_device *class_dev, char *buf) -{ - pcc_socket_t *s = container_of(class_dev, struct pcc_socket, - socket.dev); - - return sprintf(buf, "type: %s\nbase addr: 0x%08lx\n", - pcc[s->type].name, s->base); -} - -static ssize_t show_exca(struct class_device *class_dev, char *buf) -{ - /* FIXME */ - - return 0; -} - -static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL); -static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL); -#endif - -/*====================================================================*/ - -/* this is horribly ugly... proper locking needs to be done here at - * some time... */ -#define LOCKED(x) do { \ - int retval; \ - unsigned long flags; \ - spin_lock_irqsave(&pcc_lock, flags); \ - retval = x; \ - spin_unlock_irqrestore(&pcc_lock, flags); \ - return retval; \ -} while (0) - - -static int pcc_get_status(struct pcmcia_socket *s, u_int *value) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) { - dev_dbg(&s->dev, "pcc_get_status: sock(%d) -EINVAL\n", sock); - *value = 0; - return -EINVAL; - } - dev_dbg(&s->dev, "pcc_get_status: sock(%d)\n", sock); - LOCKED(_pcc_get_status(sock, value)); -} - -static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) { - dev_dbg(&s->dev, "pcc_set_socket: sock(%d) -EINVAL\n", sock); - return -EINVAL; - } - dev_dbg(&s->dev, "pcc_set_socket: sock(%d)\n", sock); - LOCKED(_pcc_set_socket(sock, state)); -} - -static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) { - dev_dbg(&s->dev, "pcc_set_io_map: sock(%d) -EINVAL\n", sock); - return -EINVAL; - } - dev_dbg(&s->dev, "pcc_set_io_map: sock(%d)\n", sock); - LOCKED(_pcc_set_io_map(sock, io)); -} - -static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) { - dev_dbg(&s->dev, "pcc_set_mem_map: sock(%d) -EINVAL\n", sock); - return -EINVAL; - } - dev_dbg(&s->dev, "pcc_set_mem_map: sock(%d)\n", sock); - LOCKED(_pcc_set_mem_map(sock, mem)); -} - -static int pcc_init(struct pcmcia_socket *s) -{ - dev_dbg(&s->dev, "pcc_init()\n"); - return 0; -} - -static struct pccard_operations pcc_operations = { - .init = pcc_init, - .get_status = pcc_get_status, - .set_socket = pcc_set_socket, - .set_io_map = pcc_set_io_map, - .set_mem_map = pcc_set_mem_map, -}; - - -/*====================================================================*/ - -static struct platform_driver pcc_driver = { - .driver = { - .name = "cfc", - }, -}; - -static struct platform_device pcc_device = { - .name = "cfc", - .id = 0, -}; - -/*====================================================================*/ - -static int __init init_m32r_pcc(void) -{ - int i, ret; - - ret = platform_driver_register(&pcc_driver); - if (ret) - return ret; - - ret = platform_device_register(&pcc_device); - if (ret){ - platform_driver_unregister(&pcc_driver); - return ret; - } - -#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) - pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f); - pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200); -#endif - - pcc_sockets = 0; - -#if !defined(CONFIG_PLAT_USRV) - add_pcc_socket(M32R_PCC0_BASE, PLD_IRQ_CFC_INSERT, CFC_ATTR_MAPBASE, - CFC_IOPORT_BASE); -#else /* CONFIG_PLAT_USRV */ - { - ulong base, mapaddr; - unsigned int ioaddr; - - for (i = 0 ; i < M32R_MAX_PCC ; i++) { - base = (ulong)PLD_CFRSTCR; - base = base | (i << 8); - ioaddr = (i + 1) << 12; - mapaddr = CFC_ATTR_MAPBASE | (i << 20); - add_pcc_socket(base, 0, mapaddr, ioaddr); - } - } -#endif /* CONFIG_PLAT_USRV */ - - if (pcc_sockets == 0) { - printk("socket is not found.\n"); - platform_device_unregister(&pcc_device); - platform_driver_unregister(&pcc_driver); - return -ENODEV; - } - - /* Set up interrupt handler(s) */ - - for (i = 0 ; i < pcc_sockets ; i++) { - socket[i].socket.dev.parent = &pcc_device.dev; - socket[i].socket.ops = &pcc_operations; - socket[i].socket.resource_ops = &pccard_static_ops; - socket[i].socket.owner = THIS_MODULE; - socket[i].number = i; - ret = pcmcia_register_socket(&socket[i].socket); - if (!ret) - socket[i].flags |= IS_REGISTERED; - } - - /* Finally, schedule a polling interrupt */ - if (poll_interval != 0) { - timer_setup(&poll_timer, pcc_interrupt_wrapper, 0); - poll_timer.expires = jiffies + poll_interval; - add_timer(&poll_timer); - } - - return 0; -} /* init_m32r_pcc */ - -static void __exit exit_m32r_pcc(void) -{ - int i; - - for (i = 0; i < pcc_sockets; i++) - if (socket[i].flags & IS_REGISTERED) - pcmcia_unregister_socket(&socket[i].socket); - - platform_device_unregister(&pcc_device); - if (poll_interval != 0) - del_timer_sync(&poll_timer); - - platform_driver_unregister(&pcc_driver); -} /* exit_m32r_pcc */ - -module_init(init_m32r_pcc); -module_exit(exit_m32r_pcc); -MODULE_LICENSE("Dual MPL/GPL"); -/*====================================================================*/ diff --git a/drivers/pcmcia/m32r_cfc.h b/drivers/pcmcia/m32r_cfc.h deleted file mode 100644 index 05fec98617d0..000000000000 --- a/drivers/pcmcia/m32r_cfc.h +++ /dev/null @@ -1,88 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2001 by Hiroyuki Kondo - */ - -#if !defined(CONFIG_M32R_CFC_NUM) -#define M32R_MAX_PCC 2 -#else -#define M32R_MAX_PCC CONFIG_M32R_CFC_NUM -#endif - -/* - * M32R PC Card Controller - */ -#define M32R_PCC0_BASE 0x00ef7000 -#define M32R_PCC1_BASE 0x00ef7020 - -/* - * Register offsets - */ -#define PCCR 0x00 -#define PCADR 0x04 -#define PCMOD 0x08 -#define PCIRC 0x0c -#define PCCSIGCR 0x10 -#define PCATCR 0x14 - -/* - * PCCR - */ -#define PCCR_PCEN (1UL<<(31-31)) - -/* - * PCIRC - */ -#define PCIRC_BWERR (1UL<<(31-7)) -#define PCIRC_CDIN1 (1UL<<(31-14)) -#define PCIRC_CDIN2 (1UL<<(31-15)) -#define PCIRC_BEIEN (1UL<<(31-23)) -#define PCIRC_CIIEN (1UL<<(31-30)) -#define PCIRC_COIEN (1UL<<(31-31)) - -/* - * PCCSIGCR - */ -#define PCCSIGCR_SEN (1UL<<(31-3)) -#define PCCSIGCR_VEN (1UL<<(31-7)) -#define PCCSIGCR_CRST (1UL<<(31-15)) -#define PCCSIGCR_COCR (1UL<<(31-31)) - -/* - * - */ -#define PCMOD_AS_ATTRIB (1UL<<(31-19)) -#define PCMOD_AS_IO (1UL<<(31-18)) - -#define PCMOD_CBSZ (1UL<<(31-23)) /* set for 8bit */ - -#define PCMOD_DBEX (1UL<<(31-31)) /* set for excahnge */ - -/* - * M32R PCC Map addr - */ - -#define M32R_PCC0_MAPBASE 0x14000000 -#define M32R_PCC1_MAPBASE 0x16000000 - -#define M32R_PCC_MAPMAX 0x02000000 - -#define M32R_PCC_MAPSIZE 0x00001000 /* XXX */ -#define M32R_PCC_MAPMASK (~(M32R_PCC_MAPMAX-1)) - -#define CFC_IOPORT_BASE 0x1000 - -#if defined(CONFIG_PLAT_MAPPI3) -#define CFC_ATTR_MAPBASE 0x14014000 -#define CFC_IO_MAPBASE_BYTE 0xb4012000 -#define CFC_IO_MAPBASE_WORD 0xb4002000 -#elif !defined(CONFIG_PLAT_USRV) -#define CFC_ATTR_MAPBASE 0x0c014000 -#define CFC_IO_MAPBASE_BYTE 0xac012000 -#define CFC_IO_MAPBASE_WORD 0xac002000 -#else -#define CFC_ATTR_MAPBASE 0x04014000 -#define CFC_IO_MAPBASE_BYTE 0xa4012000 -#define CFC_IO_MAPBASE_WORD 0xa4002000 -#endif /* CONFIG_PLAT_USRV */ - diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c deleted file mode 100644 index c2239a7e383a..000000000000 --- a/drivers/pcmcia/m32r_pcc.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * drivers/pcmcia/m32r_pcc.c - * - * Device driver for the PCMCIA functionality of M32R. - * - * Copyright (c) 2001, 2002, 2003, 2004 - * Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/string.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/bitops.h> -#include <asm/irq.h> -#include <asm/io.h> -#include <asm/addrspace.h> - -#include <pcmcia/ss.h> - -/* XXX: should be moved into asm/irq.h */ -#define PCC0_IRQ 24 -#define PCC1_IRQ 25 - -#include "m32r_pcc.h" - -#define CHAOS_PCC_DEBUG -#ifdef CHAOS_PCC_DEBUG - static volatile u_short dummy_readbuf; -#endif - -#define PCC_DEBUG_DBEX - - -/* Poll status interval -- 0 means default to interrupt */ -static int poll_interval = 0; - -typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t; - -typedef struct pcc_socket { - u_short type, flags; - struct pcmcia_socket socket; - unsigned int number; - unsigned int ioaddr; - u_long mapaddr; - u_long base; /* PCC register base */ - u_char cs_irq, intr; - pccard_io_map io_map[MAX_IO_WIN]; - pccard_mem_map mem_map[MAX_WIN]; - u_char io_win; - u_char mem_win; - pcc_as_t current_space; - u_char last_iodbex; -#ifdef CHAOS_PCC_DEBUG - u_char last_iosize; -#endif -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; -#endif -} pcc_socket_t; - -static int pcc_sockets = 0; -static pcc_socket_t socket[M32R_MAX_PCC] = { - { 0, }, /* ... */ -}; - -/*====================================================================*/ - -static unsigned int pcc_get(u_short, unsigned int); -static void pcc_set(u_short, unsigned int , unsigned int ); - -static DEFINE_SPINLOCK(pcc_lock); - -void pcc_iorw(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int wr, int flag) -{ - u_long addr; - u_long flags; - int need_ex; -#ifdef PCC_DEBUG_DBEX - int _dbex; -#endif - pcc_socket_t *t = &socket[sock]; -#ifdef CHAOS_PCC_DEBUG - int map_changed = 0; -#endif - - /* Need lock ? */ - spin_lock_irqsave(&pcc_lock, flags); - - /* - * Check if need dbex - */ - need_ex = (size > 1 && flag == 0) ? PCMOD_DBEX : 0; -#ifdef PCC_DEBUG_DBEX - _dbex = need_ex; - need_ex = 0; -#endif - - /* - * calculate access address - */ - addr = t->mapaddr + port - t->ioaddr + KSEG1; /* XXX */ - - /* - * Check current mapping - */ - if (t->current_space != as_io || t->last_iodbex != need_ex) { - - u_long cbsz; - - /* - * Disable first - */ - pcc_set(sock, PCCR, 0); - - /* - * Set mode and io address - */ - cbsz = (t->flags & MAP_16BIT) ? 0 : PCMOD_CBSZ; - pcc_set(sock, PCMOD, PCMOD_AS_IO | cbsz | need_ex); - pcc_set(sock, PCADR, addr & 0x1ff00000); - - /* - * Enable and read it - */ - pcc_set(sock, PCCR, 1); - -#ifdef CHAOS_PCC_DEBUG -#if 0 - map_changed = (t->current_space == as_attr && size == 2); /* XXX */ -#else - map_changed = 1; -#endif -#endif - t->current_space = as_io; - } - - /* - * access to IO space - */ - if (size == 1) { - /* Byte */ - unsigned char *bp = (unsigned char *)buf; - -#ifdef CHAOS_DEBUG - if (map_changed) { - dummy_readbuf = readb(addr); - } -#endif - if (wr) { - /* write Byte */ - while (nmemb--) { - writeb(*bp++, addr); - } - } else { - /* read Byte */ - while (nmemb--) { - *bp++ = readb(addr); - } - } - } else { - /* Word */ - unsigned short *bp = (unsigned short *)buf; - -#ifdef CHAOS_PCC_DEBUG - if (map_changed) { - dummy_readbuf = readw(addr); - } -#endif - if (wr) { - /* write Word */ - while (nmemb--) { -#ifdef PCC_DEBUG_DBEX - if (_dbex) { - unsigned char *cp = (unsigned char *)bp; - unsigned short tmp; - tmp = cp[1] << 8 | cp[0]; - writew(tmp, addr); - bp++; - } else -#endif - writew(*bp++, addr); - } - } else { - /* read Word */ - while (nmemb--) { -#ifdef PCC_DEBUG_DBEX - if (_dbex) { - unsigned char *cp = (unsigned char *)bp; - unsigned short tmp; - tmp = readw(addr); - cp[0] = tmp & 0xff; - cp[1] = (tmp >> 8) & 0xff; - bp++; - } else -#endif - *bp++ = readw(addr); - } - } - } - -#if 1 - /* addr is no longer used */ - if ((addr = pcc_get(sock, PCIRC)) & PCIRC_BWERR) { - printk("m32r_pcc: BWERR detected : port 0x%04lx : iosize %dbit\n", - port, size * 8); - pcc_set(sock, PCIRC, addr); - } -#endif - /* - * save state - */ - t->last_iosize = size; - t->last_iodbex = need_ex; - - /* Need lock ? */ - - spin_unlock_irqrestore(&pcc_lock,flags); - - return; -} - -void pcc_ioread(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) { - pcc_iorw(sock, port, buf, size, nmemb, 0, flag); -} - -void pcc_iowrite(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) { - pcc_iorw(sock, port, buf, size, nmemb, 1, flag); -} - -/*====================================================================*/ - -#define IS_REGISTERED 0x2000 -#define IS_ALIVE 0x8000 - -typedef struct pcc_t { - char *name; - u_short flags; -} pcc_t; - -static pcc_t pcc[] = { - { "xnux2", 0 }, { "xnux2", 0 }, -}; - -static irqreturn_t pcc_interrupt(int, void *); - -/*====================================================================*/ - -static struct timer_list poll_timer; - -static unsigned int pcc_get(u_short sock, unsigned int reg) -{ - return inl(socket[sock].base + reg); -} - - -static void pcc_set(u_short sock, unsigned int reg, unsigned int data) -{ - outl(data, socket[sock].base + reg); -} - -/*====================================================================== - - See if a card is present, powered up, in IO mode, and already - bound to a (non PC Card) Linux driver. We leave these alone. - - We make an exception for cards that seem to be serial devices. - -======================================================================*/ - -static int __init is_alive(u_short sock) -{ - unsigned int stat; - unsigned int f; - - stat = pcc_get(sock, PCIRC); - f = (stat & (PCIRC_CDIN1 | PCIRC_CDIN2)) >> 16; - if(!f){ - printk("m32r_pcc: No Card is detected at socket %d : stat = 0x%08x\n",stat,sock); - return 0; - } - if(f!=3) - printk("m32r_pcc: Insertion fail (%.8x) at socket %d\n",stat,sock); - else - printk("m32r_pcc: Card is Inserted at socket %d(%.8x)\n",sock,stat); - return 0; -} - -static int add_pcc_socket(ulong base, int irq, ulong mapaddr, - unsigned int ioaddr) -{ - pcc_socket_t *t = &socket[pcc_sockets]; - int err; - - /* add sockets */ - t->ioaddr = ioaddr; - t->mapaddr = mapaddr; - t->base = base; -#ifdef CHAOS_PCC_DEBUG - t->flags = MAP_16BIT; -#else - t->flags = 0; -#endif - if (is_alive(pcc_sockets)) - t->flags |= IS_ALIVE; - - /* add pcc */ - if (t->base > 0) { - request_region(t->base, 0x20, "m32r-pcc"); - } - - printk(KERN_INFO " %s ", pcc[pcc_sockets].name); - printk("pcc at 0x%08lx\n", t->base); - - /* Update socket interrupt information, capabilities */ - t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP); - t->socket.map_size = M32R_PCC_MAPSIZE; - t->socket.io_offset = ioaddr; /* use for io access offset */ - t->socket.irq_mask = 0; - t->socket.pci_irq = 2 + pcc_sockets; /* XXX */ - - err = request_irq(irq, pcc_interrupt, 0, "m32r-pcc", pcc_interrupt); - if (err) { - if (t->base > 0) - release_region(t->base, 0x20); - return err; - } - - pcc_sockets++; - - return 0; -} - - -/*====================================================================*/ - -static irqreturn_t pcc_interrupt(int irq, void *dev) -{ - int i, j, irc; - u_int events, active; - int handled = 0; - - pr_debug("m32r_pcc: pcc_interrupt(%d)\n", irq); - - for (j = 0; j < 20; j++) { - active = 0; - for (i = 0; i < pcc_sockets; i++) { - if ((socket[i].cs_irq != irq) && - (socket[i].socket.pci_irq != irq)) - continue; - handled = 1; - irc = pcc_get(i, PCIRC); - irc >>=16; - pr_debug("m32r_pcc: interrupt: socket %d pcirc 0x%02x ", - i, irc); - if (!irc) - continue; - - events = (irc) ? SS_DETECT : 0; - events |= (pcc_get(i,PCCR) & PCCR_PCEN) ? SS_READY : 0; - pr_debug("m32r_pcc: event 0x%02x\n", events); - - if (events) - pcmcia_parse_events(&socket[i].socket, events); - - active |= events; - active = 0; - } - if (!active) break; - } - if (j == 20) - printk(KERN_NOTICE "m32r-pcc: infinite loop in interrupt handler\n"); - - pr_debug("m32r_pcc: interrupt done\n"); - - return IRQ_RETVAL(handled); -} /* pcc_interrupt */ - -static void pcc_interrupt_wrapper(struct timer_list *unused) -{ - pcc_interrupt(0, NULL); - poll_timer.expires = jiffies + poll_interval; - add_timer(&poll_timer); -} - -/*====================================================================*/ - -static int _pcc_get_status(u_short sock, u_int *value) -{ - u_int status; - - status = pcc_get(sock,PCIRC); - *value = ((status & PCIRC_CDIN1) && (status & PCIRC_CDIN2)) - ? SS_DETECT : 0; - - status = pcc_get(sock,PCCR); - -#if 0 - *value |= (status & PCCR_PCEN) ? SS_READY : 0; -#else - *value |= SS_READY; /* XXX: always */ -#endif - - status = pcc_get(sock,PCCSIGCR); - *value |= (status & PCCSIGCR_VEN) ? SS_POWERON : 0; - - pr_debug("m32r_pcc: GetStatus(%d) = %#4.4x\n", sock, *value); - return 0; -} /* _get_status */ - -/*====================================================================*/ - -static int _pcc_set_socket(u_short sock, socket_state_t *state) -{ - u_long reg = 0; - - pr_debug("m32r_pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " - "io_irq %d, csc_mask %#2.2x)", sock, state->flags, - state->Vcc, state->Vpp, state->io_irq, state->csc_mask); - - if (state->Vcc) { - /* - * 5V only - */ - if (state->Vcc == 50) { - reg |= PCCSIGCR_VEN; - } else { - return -EINVAL; - } - } - - if (state->flags & SS_RESET) { - pr_debug("m32r_pcc: :RESET\n"); - reg |= PCCSIGCR_CRST; - } - if (state->flags & SS_OUTPUT_ENA){ - pr_debug("m32r_pcc: :OUTPUT_ENA\n"); - /* bit clear */ - } else { - reg |= PCCSIGCR_SEN; - } - - pcc_set(sock,PCCSIGCR,reg); - - if(state->flags & SS_IOCARD){ - pr_debug("m32r_pcc: :IOCARD"); - } - if (state->flags & SS_PWR_AUTO) { - pr_debug("m32r_pcc: :PWR_AUTO"); - } - if (state->csc_mask & SS_DETECT) - pr_debug("m32r_pcc: :csc-SS_DETECT"); - if (state->flags & SS_IOCARD) { - if (state->csc_mask & SS_STSCHG) - pr_debug("m32r_pcc: :STSCHG"); - } else { - if (state->csc_mask & SS_BATDEAD) - pr_debug("m32r_pcc: :BATDEAD"); - if (state->csc_mask & SS_BATWARN) - pr_debug("m32r_pcc: :BATWARN"); - if (state->csc_mask & SS_READY) - pr_debug("m32r_pcc: :READY"); - } - pr_debug("m32r_pcc: \n"); - return 0; -} /* _set_socket */ - -/*====================================================================*/ - -static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io) -{ - u_char map; - - pr_debug("m32r_pcc: SetIOMap(%d, %d, %#2.2x, %d ns, " - "%#llx-%#llx)\n", sock, io->map, io->flags, - io->speed, (unsigned long long)io->start, - (unsigned long long)io->stop); - map = io->map; - - return 0; -} /* _set_io_map */ - -/*====================================================================*/ - -static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem) -{ - - u_char map = mem->map; - u_long mode; - u_long addr; - pcc_socket_t *t = &socket[sock]; -#ifdef CHAOS_PCC_DEBUG -#if 0 - pcc_as_t last = t->current_space; -#endif -#endif - - pr_debug("m32r_pcc: SetMemMap(%d, %d, %#2.2x, %d ns, " - "%#llx, %#x)\n", sock, map, mem->flags, - mem->speed, (unsigned long long)mem->static_start, - mem->card_start); - - /* - * sanity check - */ - if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){ - return -EINVAL; - } - - /* - * de-activate - */ - if ((mem->flags & MAP_ACTIVE) == 0) { - t->current_space = as_none; - return 0; - } - - /* - * Disable first - */ - pcc_set(sock, PCCR, 0); - - /* - * Set mode - */ - if (mem->flags & MAP_ATTRIB) { - mode = PCMOD_AS_ATTRIB | PCMOD_CBSZ; - t->current_space = as_attr; - } else { - mode = 0; /* common memory */ - t->current_space = as_comm; - } - pcc_set(sock, PCMOD, mode); - - /* - * Set address - */ - addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK); - pcc_set(sock, PCADR, addr); - - mem->static_start = addr + mem->card_start; - - /* - * Enable again - */ - pcc_set(sock, PCCR, 1); - -#ifdef CHAOS_PCC_DEBUG -#if 0 - if (last != as_attr) { -#else - if (1) { -#endif - dummy_readbuf = *(u_char *)(addr + KSEG1); - } -#endif - - return 0; - -} /* _set_mem_map */ - -#if 0 /* driver model ordering issue */ -/*====================================================================== - - Routines for accessing socket information and register dumps via - /proc/bus/pccard/... - -======================================================================*/ - -static ssize_t show_info(struct class_device *class_dev, char *buf) -{ - pcc_socket_t *s = container_of(class_dev, struct pcc_socket, - socket.dev); - - return sprintf(buf, "type: %s\nbase addr: 0x%08lx\n", - pcc[s->type].name, s->base); -} - -static ssize_t show_exca(struct class_device *class_dev, char *buf) -{ - /* FIXME */ - - return 0; -} - -static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL); -static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL); -#endif - -/*====================================================================*/ - -/* this is horribly ugly... proper locking needs to be done here at - * some time... */ -#define LOCKED(x) do { \ - int retval; \ - unsigned long flags; \ - spin_lock_irqsave(&pcc_lock, flags); \ - retval = x; \ - spin_unlock_irqrestore(&pcc_lock, flags); \ - return retval; \ -} while (0) - - -static int pcc_get_status(struct pcmcia_socket *s, u_int *value) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) { - *value = 0; - return -EINVAL; - } - LOCKED(_pcc_get_status(sock, value)); -} - -static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - - LOCKED(_pcc_set_socket(sock, state)); -} - -static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - LOCKED(_pcc_set_io_map(sock, io)); -} - -static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) -{ - unsigned int sock = container_of(s, struct pcc_socket, socket)->number; - - if (socket[sock].flags & IS_ALIVE) - return -EINVAL; - LOCKED(_pcc_set_mem_map(sock, mem)); -} - -static int pcc_init(struct pcmcia_socket *s) -{ - pr_debug("m32r_pcc: init call\n"); - return 0; -} - -static struct pccard_operations pcc_operations = { - .init = pcc_init, - .get_status = pcc_get_status, - .set_socket = pcc_set_socket, - .set_io_map = pcc_set_io_map, - .set_mem_map = pcc_set_mem_map, -}; - -/*====================================================================*/ - -static struct platform_driver pcc_driver = { - .driver = { - .name = "pcc", - }, -}; - -static struct platform_device pcc_device = { - .name = "pcc", - .id = 0, -}; - -/*====================================================================*/ - -static int __init init_m32r_pcc(void) -{ - int i, ret; - - ret = platform_driver_register(&pcc_driver); - if (ret) - return ret; - - ret = platform_device_register(&pcc_device); - if (ret) - goto unreg_driv; - - printk(KERN_INFO "m32r PCC probe:\n"); - - pcc_sockets = 0; - - ret = add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE, - 0x1000); - if (ret) - goto unreg_dev; - -#ifdef CONFIG_M32RPCC_SLOT2 - ret = add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE, - 0x2000); - if (ret) - goto unreg_dev; -#endif - - if (pcc_sockets == 0) { - printk("socket is not found.\n"); - ret = -ENODEV; - goto unreg_dev; - } - - /* Set up interrupt handler(s) */ - - for (i = 0 ; i < pcc_sockets ; i++) { - socket[i].socket.dev.parent = &pcc_device.dev; - socket[i].socket.ops = &pcc_operations; - socket[i].socket.resource_ops = &pccard_static_ops; - socket[i].socket.owner = THIS_MODULE; - socket[i].number = i; - ret = pcmcia_register_socket(&socket[i].socket); - if (!ret) - socket[i].flags |= IS_REGISTERED; - } - - /* Finally, schedule a polling interrupt */ - if (poll_interval != 0) { - timer_setup(&poll_timer, pcc_interrupt_wrapper, 0); - poll_timer.expires = jiffies + poll_interval; - add_timer(&poll_timer); - } - - return 0; - -unreg_dev: - platform_device_unregister(&pcc_device); -unreg_driv: - platform_driver_unregister(&pcc_driver); - return ret; -} /* init_m32r_pcc */ - -static void __exit exit_m32r_pcc(void) -{ - int i; - - for (i = 0; i < pcc_sockets; i++) - if (socket[i].flags & IS_REGISTERED) - pcmcia_unregister_socket(&socket[i].socket); - - platform_device_unregister(&pcc_device); - if (poll_interval != 0) - del_timer_sync(&poll_timer); - - platform_driver_unregister(&pcc_driver); -} /* exit_m32r_pcc */ - -module_init(init_m32r_pcc); -module_exit(exit_m32r_pcc); -MODULE_LICENSE("Dual MPL/GPL"); -/*====================================================================*/ diff --git a/drivers/pcmcia/m32r_pcc.h b/drivers/pcmcia/m32r_pcc.h deleted file mode 100644 index d99ad3864ff3..000000000000 --- a/drivers/pcmcia/m32r_pcc.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2001 by Hiroyuki Kondo - */ - -#define M32R_MAX_PCC 2 - -/* - * M32R PC Card Controller - */ -#define M32R_PCC0_BASE 0x00ef7000 -#define M32R_PCC1_BASE 0x00ef7020 - -/* - * Register offsets - */ -#define PCCR 0x00 -#define PCADR 0x04 -#define PCMOD 0x08 -#define PCIRC 0x0c -#define PCCSIGCR 0x10 -#define PCATCR 0x14 - -/* - * PCCR - */ -#define PCCR_PCEN (1UL<<(31-31)) - -/* - * PCIRC - */ -#define PCIRC_BWERR (1UL<<(31-7)) -#define PCIRC_CDIN1 (1UL<<(31-14)) -#define PCIRC_CDIN2 (1UL<<(31-15)) -#define PCIRC_BEIEN (1UL<<(31-23)) -#define PCIRC_CIIEN (1UL<<(31-30)) -#define PCIRC_COIEN (1UL<<(31-31)) - -/* - * PCCSIGCR - */ -#define PCCSIGCR_SEN (1UL<<(31-3)) -#define PCCSIGCR_VEN (1UL<<(31-7)) -#define PCCSIGCR_CRST (1UL<<(31-15)) -#define PCCSIGCR_COCR (1UL<<(31-31)) - -/* - * - */ -#define PCMOD_AS_ATTRIB (1UL<<(31-19)) -#define PCMOD_AS_IO (1UL<<(31-18)) - -#define PCMOD_CBSZ (1UL<<(31-23)) /* set for 8bit */ - -#define PCMOD_DBEX (1UL<<(31-31)) /* set for excahnge */ - -/* - * M32R PCC Map addr - */ -#define M32R_PCC0_MAPBASE 0x14000000 -#define M32R_PCC1_MAPBASE 0x16000000 - -#define M32R_PCC_MAPMAX 0x02000000 - -#define M32R_PCC_MAPSIZE 0x00001000 /* XXX */ -#define M32R_PCC_MAPMASK (~(M32R_PCC_MAPMAX-1)) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 0f254b35c378..008073570a38 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -30,17 +30,6 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. -config PINCTRL_ADI2 - bool "ADI pin controller driver" - depends on (BF54x || BF60x) - depends on !GPIO_ADI - select PINMUX - select IRQ_DOMAIN - help - This is the pin controller and gpio driver for ADI BF54x, BF60x and - future processors. This option is selected automatically when specific - machine and arch are selected to build. - config PINCTRL_ARTPEC6 bool "Axis ARTPEC-6 pin controller driver" depends on MACH_ARTPEC6 @@ -77,14 +66,6 @@ config PINCTRL_AXP209 selected. Say yes to enable pinctrl and GPIO support for the AXP209 PMIC -config PINCTRL_BF54x - def_bool y if BF54x - select PINCTRL_ADI2 - -config PINCTRL_BF60x - def_bool y if BF60x - select PINCTRL_ADI2 - config PINCTRL_AT91 bool "AT91 pinctrl driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index d3692633e9ed..92a40bdb6273 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -8,12 +8,9 @@ obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o -obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o -obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o -obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o diff --git a/drivers/pinctrl/pinctrl-adi2-bf54x.c b/drivers/pinctrl/pinctrl-adi2-bf54x.c deleted file mode 100644 index 008a29e92e56..000000000000 --- a/drivers/pinctrl/pinctrl-adi2-bf54x.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Pinctrl Driver for ADI GPIO2 controller - * - * Copyright 2007-2013 Analog Devices Inc. - * - * Licensed under the GPLv2 or later - */ - -#include <asm/portmux.h> -#include "pinctrl-adi2.h" - -static const struct pinctrl_pin_desc adi_pads[] = { - PINCTRL_PIN(0, "PA0"), - PINCTRL_PIN(1, "PA1"), - PINCTRL_PIN(2, "PA2"), - PINCTRL_PIN(3, "PG3"), - PINCTRL_PIN(4, "PA4"), - PINCTRL_PIN(5, "PA5"), - PINCTRL_PIN(6, "PA6"), - PINCTRL_PIN(7, "PA7"), - PINCTRL_PIN(8, "PA8"), - PINCTRL_PIN(9, "PA9"), - PINCTRL_PIN(10, "PA10"), - PINCTRL_PIN(11, "PA11"), - PINCTRL_PIN(12, "PA12"), - PINCTRL_PIN(13, "PA13"), - PINCTRL_PIN(14, "PA14"), - PINCTRL_PIN(15, "PA15"), - PINCTRL_PIN(16, "PB0"), - PINCTRL_PIN(17, "PB1"), - PINCTRL_PIN(18, "PB2"), - PINCTRL_PIN(19, "PB3"), - PINCTRL_PIN(20, "PB4"), - PINCTRL_PIN(21, "PB5"), - PINCTRL_PIN(22, "PB6"), - PINCTRL_PIN(23, "PB7"), - PINCTRL_PIN(24, "PB8"), - PINCTRL_PIN(25, "PB9"), - PINCTRL_PIN(26, "PB10"), - PINCTRL_PIN(27, "PB11"), - PINCTRL_PIN(28, "PB12"), - PINCTRL_PIN(29, "PB13"), - PINCTRL_PIN(30, "PB14"), - PINCTRL_PIN(32, "PC0"), - PINCTRL_PIN(33, "PC1"), - PINCTRL_PIN(34, "PC2"), - PINCTRL_PIN(35, "PC3"), - PINCTRL_PIN(36, "PC4"), - PINCTRL_PIN(37, "PC5"), - PINCTRL_PIN(38, "PC6"), - PINCTRL_PIN(39, "PC7"), - PINCTRL_PIN(40, "PC8"), - PINCTRL_PIN(41, "PC9"), - PINCTRL_PIN(42, "PC10"), - PINCTRL_PIN(43, "PC11"), - PINCTRL_PIN(44, "PC12"), - PINCTRL_PIN(45, "PC13"), - PINCTRL_PIN(48, "PD0"), - PINCTRL_PIN(49, "PD1"), - PINCTRL_PIN(50, "PD2"), - PINCTRL_PIN(51, "PD3"), - PINCTRL_PIN(52, "PD4"), - PINCTRL_PIN(53, "PD5"), - PINCTRL_PIN(54, "PD6"), - PINCTRL_PIN(55, "PD7"), - PINCTRL_PIN(56, "PD8"), - PINCTRL_PIN(57, "PD9"), - PINCTRL_PIN(58, "PD10"), - PINCTRL_PIN(59, "PD11"), - PINCTRL_PIN(60, "PD12"), - PINCTRL_PIN(61, "PD13"), - PINCTRL_PIN(62, "PD14"), - PINCTRL_PIN(63, "PD15"), - PINCTRL_PIN(64, "PE0"), - PINCTRL_PIN(65, "PE1"), - PINCTRL_PIN(66, "PE2"), - PINCTRL_PIN(67, "PE3"), - PINCTRL_PIN(68, "PE4"), - PINCTRL_PIN(69, "PE5"), - PINCTRL_PIN(70, "PE6"), - PINCTRL_PIN(71, "PE7"), - PINCTRL_PIN(72, "PE8"), - PINCTRL_PIN(73, "PE9"), - PINCTRL_PIN(74, "PE10"), - PINCTRL_PIN(75, "PE11"), - PINCTRL_PIN(76, "PE12"), - PINCTRL_PIN(77, "PE13"), - PINCTRL_PIN(78, "PE14"), - PINCTRL_PIN(79, "PE15"), - PINCTRL_PIN(80, "PF0"), - PINCTRL_PIN(81, "PF1"), - PINCTRL_PIN(82, "PF2"), - PINCTRL_PIN(83, "PF3"), - PINCTRL_PIN(84, "PF4"), - PINCTRL_PIN(85, "PF5"), - PINCTRL_PIN(86, "PF6"), - PINCTRL_PIN(87, "PF7"), - PINCTRL_PIN(88, "PF8"), - PINCTRL_PIN(89, "PF9"), - PINCTRL_PIN(90, "PF10"), - PINCTRL_PIN(91, "PF11"), - PINCTRL_PIN(92, "PF12"), - PINCTRL_PIN(93, "PF13"), - PINCTRL_PIN(94, "PF14"), - PINCTRL_PIN(95, "PF15"), - PINCTRL_PIN(96, "PG0"), - PINCTRL_PIN(97, "PG1"), - PINCTRL_PIN(98, "PG2"), - PINCTRL_PIN(99, "PG3"), - PINCTRL_PIN(100, "PG4"), - PINCTRL_PIN(101, "PG5"), - PINCTRL_PIN(102, "PG6"), - PINCTRL_PIN(103, "PG7"), - PINCTRL_PIN(104, "PG8"), - PINCTRL_PIN(105, "PG9"), - PINCTRL_PIN(106, "PG10"), - PINCTRL_PIN(107, "PG11"), - PINCTRL_PIN(108, "PG12"), - PINCTRL_PIN(109, "PG13"), - PINCTRL_PIN(110, "PG14"), - PINCTRL_PIN(111, "PG15"), - PINCTRL_PIN(112, "PH0"), - PINCTRL_PIN(113, "PH1"), - PINCTRL_PIN(114, "PH2"), - PINCTRL_PIN(115, "PH3"), - PINCTRL_PIN(116, "PH4"), - PINCTRL_PIN(117, "PH5"), - PINCTRL_PIN(118, "PH6"), - PINCTRL_PIN(119, "PH7"), - PINCTRL_PIN(120, "PH8"), - PINCTRL_PIN(121, "PH9"), - PINCTRL_PIN(122, "PH10"), - PINCTRL_PIN(123, "PH11"), - PINCTRL_PIN(124, "PH12"), - PINCTRL_PIN(125, "PH13"), - PINCTRL_PIN(128, "PI0"), - PINCTRL_PIN(129, "PI1"), - PINCTRL_PIN(130, "PI2"), - PINCTRL_PIN(131, "PI3"), - PINCTRL_PIN(132, "PI4"), - PINCTRL_PIN(133, "PI5"), - PINCTRL_PIN(134, "PI6"), - PINCTRL_PIN(135, "PI7"), - PINCTRL_PIN(136, "PI8"), - PINCTRL_PIN(137, "PI9"), - PINCTRL_PIN(138, "PI10"), - PINCTRL_PIN(139, "PI11"), - PINCTRL_PIN(140, "PI12"), - PINCTRL_PIN(141, "PI13"), - PINCTRL_PIN(142, "PI14"), - PINCTRL_PIN(143, "PI15"), - PINCTRL_PIN(144, "PJ0"), - PINCTRL_PIN(145, "PJ1"), - PINCTRL_PIN(146, "PJ2"), - PINCTRL_PIN(147, "PJ3"), - PINCTRL_PIN(148, "PJ4"), - PINCTRL_PIN(149, "PJ5"), - PINCTRL_PIN(150, "PJ6"), - PINCTRL_PIN(151, "PJ7"), - PINCTRL_PIN(152, "PJ8"), - PINCTRL_PIN(153, "PJ9"), - PINCTRL_PIN(154, "PJ10"), - PINCTRL_PIN(155, "PJ11"), - PINCTRL_PIN(156, "PJ12"), - PINCTRL_PIN(157, "PJ13"), -}; - -static const unsigned uart0_pins[] = { - GPIO_PE7, GPIO_PE8, -}; - -static const unsigned uart1_pins[] = { - GPIO_PH0, GPIO_PH1, -}; - -static const unsigned uart1_ctsrts_pins[] = { - GPIO_PE9, GPIO_PE10, -}; - -static const unsigned uart2_pins[] = { - GPIO_PB4, GPIO_PB5, -}; - -static const unsigned uart3_pins[] = { - GPIO_PB6, GPIO_PB7, -}; - -static const unsigned uart3_ctsrts_pins[] = { - GPIO_PB2, GPIO_PB3, -}; - -static const unsigned rsi0_pins[] = { - GPIO_PC8, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, GPIO_PC13, -}; - -static const unsigned spi0_pins[] = { - GPIO_PE0, GPIO_PE1, GPIO_PE2, -}; - -static const unsigned spi1_pins[] = { - GPIO_PG8, GPIO_PG9, GPIO_PG10, -}; - -static const unsigned twi0_pins[] = { - GPIO_PE14, GPIO_PE15, -}; - -static const unsigned twi1_pins[] = { - GPIO_PB0, GPIO_PB1, -}; - -static const unsigned rotary_pins[] = { - GPIO_PH4, GPIO_PH3, GPIO_PH5, -}; - -static const unsigned can0_pins[] = { - GPIO_PG13, GPIO_PG12, -}; - -static const unsigned can1_pins[] = { - GPIO_PG14, GPIO_PG15, -}; - -static const unsigned smc0_pins[] = { - GPIO_PH8, GPIO_PH9, GPIO_PH10, GPIO_PH11, GPIO_PH12, GPIO_PH13, - GPIO_PI0, GPIO_PI1, GPIO_PI2, GPIO_PI3, GPIO_PI4, GPIO_PI5, GPIO_PI6, - GPIO_PI7, GPIO_PI8, GPIO_PI9, GPIO_PI10, GPIO_PI11, - GPIO_PI12, GPIO_PI13, GPIO_PI14, GPIO_PI15, -}; - -static const unsigned sport0_pins[] = { - GPIO_PC0, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC6, GPIO_PC7, -}; - -static const unsigned sport1_pins[] = { - GPIO_PD0, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD6, GPIO_PD7, -}; - -static const unsigned sport2_pins[] = { - GPIO_PA0, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA6, GPIO_PA7, -}; - -static const unsigned sport3_pins[] = { - GPIO_PA8, GPIO_PA10, GPIO_PA11, GPIO_PA12, GPIO_PA14, GPIO_PA15, -}; - -static const unsigned ppi0_8b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF13, GPIO_PG0, GPIO_PG1, GPIO_PG2, -}; - -static const unsigned ppi0_16b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, - GPIO_PF13, GPIO_PF14, GPIO_PF15, - GPIO_PG0, GPIO_PG1, GPIO_PG2, -}; - -static const unsigned ppi0_24b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, - GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PD0, GPIO_PD1, GPIO_PD2, - GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PG3, GPIO_PG4, - GPIO_PG0, GPIO_PG1, GPIO_PG2, -}; - -static const unsigned ppi1_8b_pins[] = { - GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6, - GPIO_PD7, GPIO_PE11, GPIO_PE12, GPIO_PE13, -}; - -static const unsigned ppi1_16b_pins[] = { - GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6, - GPIO_PD7, GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12, - GPIO_PD13, GPIO_PD14, GPIO_PD15, - GPIO_PE11, GPIO_PE12, GPIO_PE13, -}; - -static const unsigned ppi2_8b_pins[] = { - GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12, - GPIO_PD13, GPIO_PD14, GPIO_PD15, - GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3, -}; - -static const unsigned atapi_pins[] = { - GPIO_PH2, GPIO_PJ3, GPIO_PJ4, GPIO_PJ5, GPIO_PJ6, - GPIO_PJ7, GPIO_PJ8, GPIO_PJ9, GPIO_PJ10, -}; - -static const unsigned atapi_alter_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, - GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PG2, GPIO_PG3, GPIO_PG4, -}; - -static const unsigned nfc0_pins[] = { - GPIO_PJ1, GPIO_PJ2, -}; - -static const unsigned keys_4x4_pins[] = { - GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, - GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15, -}; - -static const unsigned keys_8x8_pins[] = { - GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, - GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15, - GPIO_PE0, GPIO_PE1, GPIO_PE2, GPIO_PE3, - GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, -}; - -static const unsigned short uart0_mux[] = { - P_UART0_TX, P_UART0_RX, - 0 -}; - -static const unsigned short uart1_mux[] = { - P_UART1_TX, P_UART1_RX, - 0 -}; - -static const unsigned short uart1_ctsrts_mux[] = { - P_UART1_RTS, P_UART1_CTS, - 0 -}; - -static const unsigned short uart2_mux[] = { - P_UART2_TX, P_UART2_RX, - 0 -}; - -static const unsigned short uart3_mux[] = { - P_UART3_TX, P_UART3_RX, - 0 -}; - -static const unsigned short uart3_ctsrts_mux[] = { - P_UART3_RTS, P_UART3_CTS, - 0 -}; - -static const unsigned short rsi0_mux[] = { - P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD, - 0 -}; - -static const unsigned short spi0_mux[] = { - P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0 -}; - -static const unsigned short spi1_mux[] = { - P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0 -}; - -static const unsigned short twi0_mux[] = { - P_TWI0_SCL, P_TWI0_SDA, 0 -}; - -static const unsigned short twi1_mux[] = { - P_TWI1_SCL, P_TWI1_SDA, 0 -}; - -static const unsigned short rotary_mux[] = { - P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0 -}; - -static const unsigned short sport0_mux[] = { - P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, - P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0 -}; - -static const unsigned short sport1_mux[] = { - P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, - P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0 -}; - -static const unsigned short sport2_mux[] = { - P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS, - P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0 -}; - -static const unsigned short sport3_mux[] = { - P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS, - P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0 -}; - -static const unsigned short can0_mux[] = { - P_CAN0_RX, P_CAN0_TX, 0 -}; - -static const unsigned short can1_mux[] = { - P_CAN1_RX, P_CAN1_TX, 0 -}; - -static const unsigned short smc0_mux[] = { - P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12, - P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21, - P_A22, P_A23, P_A24, P_A25, P_NOR_CLK, 0, -}; - -static const unsigned short ppi0_8b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi0_16b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi0_24b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, - P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19, - P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi1_8b_mux[] = { - P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, - P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, - P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, - 0, -}; - -static const unsigned short ppi1_16b_mux[] = { - P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, - P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, - P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11, - P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15, - P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, - 0, -}; - -static const unsigned short ppi2_8b_mux[] = { - P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, - P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, - P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, - 0, -}; - -static const unsigned short atapi_mux[] = { - P_ATAPI_RESET, P_ATAPI_DIOR, P_ATAPI_DIOW, P_ATAPI_CS0, P_ATAPI_CS1, - P_ATAPI_DMACK, P_ATAPI_DMARQ, P_ATAPI_INTRQ, P_ATAPI_IORDY, -}; - -static const unsigned short atapi_alter_mux[] = { - P_ATAPI_D0A, P_ATAPI_D1A, P_ATAPI_D2A, P_ATAPI_D3A, P_ATAPI_D4A, - P_ATAPI_D5A, P_ATAPI_D6A, P_ATAPI_D7A, P_ATAPI_D8A, P_ATAPI_D9A, - P_ATAPI_D10A, P_ATAPI_D11A, P_ATAPI_D12A, P_ATAPI_D13A, P_ATAPI_D14A, - P_ATAPI_D15A, P_ATAPI_A0A, P_ATAPI_A1A, P_ATAPI_A2A, - 0 -}; - -static const unsigned short nfc0_mux[] = { - P_NAND_CE, P_NAND_RB, - 0 -}; - -static const unsigned short keys_4x4_mux[] = { - P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0, - P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0, - 0 -}; - -static const unsigned short keys_8x8_mux[] = { - P_KEY_ROW7, P_KEY_ROW6, P_KEY_ROW5, P_KEY_ROW4, - P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0, - P_KEY_COL7, P_KEY_COL6, P_KEY_COL5, P_KEY_COL4, - P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0, - 0 -}; - -static const struct adi_pin_group adi_pin_groups[] = { - ADI_PIN_GROUP("uart0grp", uart0_pins, uart0_mux), - ADI_PIN_GROUP("uart1grp", uart1_pins, uart1_mux), - ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins, uart1_ctsrts_mux), - ADI_PIN_GROUP("uart2grp", uart2_pins, uart2_mux), - ADI_PIN_GROUP("uart3grp", uart3_pins, uart3_mux), - ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins, uart3_ctsrts_mux), - ADI_PIN_GROUP("rsi0grp", rsi0_pins, rsi0_mux), - ADI_PIN_GROUP("spi0grp", spi0_pins, spi0_mux), - ADI_PIN_GROUP("spi1grp", spi1_pins, spi1_mux), - ADI_PIN_GROUP("twi0grp", twi0_pins, twi0_mux), - ADI_PIN_GROUP("twi1grp", twi1_pins, twi1_mux), - ADI_PIN_GROUP("rotarygrp", rotary_pins, rotary_mux), - ADI_PIN_GROUP("can0grp", can0_pins, can0_mux), - ADI_PIN_GROUP("can1grp", can1_pins, can1_mux), - ADI_PIN_GROUP("smc0grp", smc0_pins, smc0_mux), - ADI_PIN_GROUP("sport0grp", sport0_pins, sport0_mux), - ADI_PIN_GROUP("sport1grp", sport1_pins, sport1_mux), - ADI_PIN_GROUP("sport2grp", sport2_pins, sport2_mux), - ADI_PIN_GROUP("sport3grp", sport3_pins, sport3_mux), - ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins, ppi0_8b_mux), - ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins, ppi0_16b_mux), - ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins, ppi0_24b_mux), - ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins, ppi1_8b_mux), - ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins, ppi1_16b_mux), - ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins, ppi2_8b_mux), - ADI_PIN_GROUP("atapigrp", atapi_pins, atapi_mux), - ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins, atapi_alter_mux), - ADI_PIN_GROUP("nfc0grp", nfc0_pins, nfc0_mux), - ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins, keys_4x4_mux), - ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins, keys_8x8_mux), -}; - -static const char * const uart0grp[] = { "uart0grp" }; -static const char * const uart1grp[] = { "uart1grp" }; -static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" }; -static const char * const uart2grp[] = { "uart2grp" }; -static const char * const uart3grp[] = { "uart3grp" }; -static const char * const uart3ctsrtsgrp[] = { "uart3ctsrtsgrp" }; -static const char * const rsi0grp[] = { "rsi0grp" }; -static const char * const spi0grp[] = { "spi0grp" }; -static const char * const spi1grp[] = { "spi1grp" }; -static const char * const twi0grp[] = { "twi0grp" }; -static const char * const twi1grp[] = { "twi1grp" }; -static const char * const rotarygrp[] = { "rotarygrp" }; -static const char * const can0grp[] = { "can0grp" }; -static const char * const can1grp[] = { "can1grp" }; -static const char * const smc0grp[] = { "smc0grp" }; -static const char * const sport0grp[] = { "sport0grp" }; -static const char * const sport1grp[] = { "sport1grp" }; -static const char * const sport2grp[] = { "sport2grp" }; -static const char * const sport3grp[] = { "sport3grp" }; -static const char * const ppi0grp[] = { "ppi0_8bgrp", - "ppi0_16bgrp", - "ppi0_24bgrp" }; -static const char * const ppi1grp[] = { "ppi1_8bgrp", - "ppi1_16bgrp" }; -static const char * const ppi2grp[] = { "ppi2_8bgrp" }; -static const char * const atapigrp[] = { "atapigrp" }; -static const char * const atapialtergrp[] = { "atapialtergrp" }; -static const char * const nfc0grp[] = { "nfc0grp" }; -static const char * const keysgrp[] = { "keys_4x4grp", - "keys_8x8grp" }; - -static const struct adi_pmx_func adi_pmx_functions[] = { - ADI_PMX_FUNCTION("uart0", uart0grp), - ADI_PMX_FUNCTION("uart1", uart1grp), - ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp), - ADI_PMX_FUNCTION("uart2", uart2grp), - ADI_PMX_FUNCTION("uart3", uart3grp), - ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp), - ADI_PMX_FUNCTION("rsi0", rsi0grp), - ADI_PMX_FUNCTION("spi0", spi0grp), - ADI_PMX_FUNCTION("spi1", spi1grp), - ADI_PMX_FUNCTION("twi0", twi0grp), - ADI_PMX_FUNCTION("twi1", twi1grp), - ADI_PMX_FUNCTION("rotary", rotarygrp), - ADI_PMX_FUNCTION("can0", can0grp), - ADI_PMX_FUNCTION("can1", can1grp), - ADI_PMX_FUNCTION("smc0", smc0grp), - ADI_PMX_FUNCTION("sport0", sport0grp), - ADI_PMX_FUNCTION("sport1", sport1grp), - ADI_PMX_FUNCTION("sport2", sport2grp), - ADI_PMX_FUNCTION("sport3", sport3grp), - ADI_PMX_FUNCTION("ppi0", ppi0grp), - ADI_PMX_FUNCTION("ppi1", ppi1grp), - ADI_PMX_FUNCTION("ppi2", ppi2grp), - ADI_PMX_FUNCTION("atapi", atapigrp), - ADI_PMX_FUNCTION("atapi_alter", atapialtergrp), - ADI_PMX_FUNCTION("nfc0", nfc0grp), - ADI_PMX_FUNCTION("keys", keysgrp), -}; - -static const struct adi_pinctrl_soc_data adi_bf54x_soc = { - .functions = adi_pmx_functions, - .nfunctions = ARRAY_SIZE(adi_pmx_functions), - .groups = adi_pin_groups, - .ngroups = ARRAY_SIZE(adi_pin_groups), - .pins = adi_pads, - .npins = ARRAY_SIZE(adi_pads), -}; - -void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc) -{ - *soc = &adi_bf54x_soc; -} diff --git a/drivers/pinctrl/pinctrl-adi2-bf60x.c b/drivers/pinctrl/pinctrl-adi2-bf60x.c deleted file mode 100644 index fcfa00821f12..000000000000 --- a/drivers/pinctrl/pinctrl-adi2-bf60x.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Pinctrl Driver for ADI GPIO2 controller - * - * Copyright 2007-2013 Analog Devices Inc. - * - * Licensed under the GPLv2 or later - */ - -#include <asm/portmux.h> -#include "pinctrl-adi2.h" - -static const struct pinctrl_pin_desc adi_pads[] = { - PINCTRL_PIN(0, "PA0"), - PINCTRL_PIN(1, "PA1"), - PINCTRL_PIN(2, "PA2"), - PINCTRL_PIN(3, "PG3"), - PINCTRL_PIN(4, "PA4"), - PINCTRL_PIN(5, "PA5"), - PINCTRL_PIN(6, "PA6"), - PINCTRL_PIN(7, "PA7"), - PINCTRL_PIN(8, "PA8"), - PINCTRL_PIN(9, "PA9"), - PINCTRL_PIN(10, "PA10"), - PINCTRL_PIN(11, "PA11"), - PINCTRL_PIN(12, "PA12"), - PINCTRL_PIN(13, "PA13"), - PINCTRL_PIN(14, "PA14"), - PINCTRL_PIN(15, "PA15"), - PINCTRL_PIN(16, "PB0"), - PINCTRL_PIN(17, "PB1"), - PINCTRL_PIN(18, "PB2"), - PINCTRL_PIN(19, "PB3"), - PINCTRL_PIN(20, "PB4"), - PINCTRL_PIN(21, "PB5"), - PINCTRL_PIN(22, "PB6"), - PINCTRL_PIN(23, "PB7"), - PINCTRL_PIN(24, "PB8"), - PINCTRL_PIN(25, "PB9"), - PINCTRL_PIN(26, "PB10"), - PINCTRL_PIN(27, "PB11"), - PINCTRL_PIN(28, "PB12"), - PINCTRL_PIN(29, "PB13"), - PINCTRL_PIN(30, "PB14"), - PINCTRL_PIN(31, "PB15"), - PINCTRL_PIN(32, "PC0"), - PINCTRL_PIN(33, "PC1"), - PINCTRL_PIN(34, "PC2"), - PINCTRL_PIN(35, "PC3"), - PINCTRL_PIN(36, "PC4"), - PINCTRL_PIN(37, "PC5"), - PINCTRL_PIN(38, "PC6"), - PINCTRL_PIN(39, "PC7"), - PINCTRL_PIN(40, "PC8"), - PINCTRL_PIN(41, "PC9"), - PINCTRL_PIN(42, "PC10"), - PINCTRL_PIN(43, "PC11"), - PINCTRL_PIN(44, "PC12"), - PINCTRL_PIN(45, "PC13"), - PINCTRL_PIN(46, "PC14"), - PINCTRL_PIN(47, "PC15"), - PINCTRL_PIN(48, "PD0"), - PINCTRL_PIN(49, "PD1"), - PINCTRL_PIN(50, "PD2"), - PINCTRL_PIN(51, "PD3"), - PINCTRL_PIN(52, "PD4"), - PINCTRL_PIN(53, "PD5"), - PINCTRL_PIN(54, "PD6"), - PINCTRL_PIN(55, "PD7"), - PINCTRL_PIN(56, "PD8"), - PINCTRL_PIN(57, "PD9"), - PINCTRL_PIN(58, "PD10"), - PINCTRL_PIN(59, "PD11"), - PINCTRL_PIN(60, "PD12"), - PINCTRL_PIN(61, "PD13"), - PINCTRL_PIN(62, "PD14"), - PINCTRL_PIN(63, "PD15"), - PINCTRL_PIN(64, "PE0"), - PINCTRL_PIN(65, "PE1"), - PINCTRL_PIN(66, "PE2"), - PINCTRL_PIN(67, "PE3"), - PINCTRL_PIN(68, "PE4"), - PINCTRL_PIN(69, "PE5"), - PINCTRL_PIN(70, "PE6"), - PINCTRL_PIN(71, "PE7"), - PINCTRL_PIN(72, "PE8"), - PINCTRL_PIN(73, "PE9"), - PINCTRL_PIN(74, "PE10"), - PINCTRL_PIN(75, "PE11"), - PINCTRL_PIN(76, "PE12"), - PINCTRL_PIN(77, "PE13"), - PINCTRL_PIN(78, "PE14"), - PINCTRL_PIN(79, "PE15"), - PINCTRL_PIN(80, "PF0"), - PINCTRL_PIN(81, "PF1"), - PINCTRL_PIN(82, "PF2"), - PINCTRL_PIN(83, "PF3"), - PINCTRL_PIN(84, "PF4"), - PINCTRL_PIN(85, "PF5"), - PINCTRL_PIN(86, "PF6"), - PINCTRL_PIN(87, "PF7"), - PINCTRL_PIN(88, "PF8"), - PINCTRL_PIN(89, "PF9"), - PINCTRL_PIN(90, "PF10"), - PINCTRL_PIN(91, "PF11"), - PINCTRL_PIN(92, "PF12"), - PINCTRL_PIN(93, "PF13"), - PINCTRL_PIN(94, "PF14"), - PINCTRL_PIN(95, "PF15"), - PINCTRL_PIN(96, "PG0"), - PINCTRL_PIN(97, "PG1"), - PINCTRL_PIN(98, "PG2"), - PINCTRL_PIN(99, "PG3"), - PINCTRL_PIN(100, "PG4"), - PINCTRL_PIN(101, "PG5"), - PINCTRL_PIN(102, "PG6"), - PINCTRL_PIN(103, "PG7"), - PINCTRL_PIN(104, "PG8"), - PINCTRL_PIN(105, "PG9"), - PINCTRL_PIN(106, "PG10"), - PINCTRL_PIN(107, "PG11"), - PINCTRL_PIN(108, "PG12"), - PINCTRL_PIN(109, "PG13"), - PINCTRL_PIN(110, "PG14"), - PINCTRL_PIN(111, "PG15"), -}; - -static const unsigned uart0_pins[] = { - GPIO_PD7, GPIO_PD8, -}; - -static const unsigned uart0_ctsrts_pins[] = { - GPIO_PD9, GPIO_PD10, -}; - -static const unsigned uart1_pins[] = { - GPIO_PG15, GPIO_PG14, -}; - -static const unsigned uart1_ctsrts_pins[] = { - GPIO_PG10, GPIO_PG13, -}; - -static const unsigned rsi0_pins[] = { - GPIO_PG3, GPIO_PG2, GPIO_PG0, GPIO_PE15, GPIO_PG5, GPIO_PG6, -}; - -static const unsigned eth0_pins[] = { - GPIO_PC6, GPIO_PC7, GPIO_PC2, GPIO_PC0, GPIO_PC3, GPIO_PC1, - GPIO_PB13, GPIO_PD6, GPIO_PC5, GPIO_PC4, GPIO_PB14, GPIO_PB15, -}; - -static const unsigned eth1_pins[] = { - GPIO_PE10, GPIO_PE11, GPIO_PG3, GPIO_PG0, GPIO_PG2, GPIO_PE15, - GPIO_PG5, GPIO_PE12, GPIO_PE13, GPIO_PE14, GPIO_PG6, GPIO_PC9, -}; - -static const unsigned spi0_pins[] = { - GPIO_PD4, GPIO_PD2, GPIO_PD3, -}; - -static const unsigned spi1_pins[] = { - GPIO_PD5, GPIO_PD14, GPIO_PD13, -}; - -static const unsigned twi0_pins[] = { -}; - -static const unsigned twi1_pins[] = { -}; - -static const unsigned rotary_pins[] = { - GPIO_PG7, GPIO_PG11, GPIO_PG12, -}; - -static const unsigned can0_pins[] = { - GPIO_PG1, GPIO_PG4, -}; - -static const unsigned smc0_pins[] = { - GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, - GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PB2, GPIO_PA10, GPIO_PA11, - GPIO_PB3, GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB6, - GPIO_PB7, GPIO_PB8, GPIO_PB10, GPIO_PB11, GPIO_PB0, -}; - -static const unsigned sport0_pins[] = { - GPIO_PB5, GPIO_PB4, GPIO_PB9, GPIO_PB8, GPIO_PB7, GPIO_PB11, -}; - -static const unsigned sport1_pins[] = { - GPIO_PE2, GPIO_PE5, GPIO_PD15, GPIO_PE4, GPIO_PE3, GPIO_PE1, -}; - -static const unsigned sport2_pins[] = { - GPIO_PG4, GPIO_PG1, GPIO_PG9, GPIO_PG10, GPIO_PG7, GPIO_PB12, -}; - -static const unsigned ppi0_8b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF13, GPIO_PF14, GPIO_PF15, - GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9, -}; - -static const unsigned ppi0_16b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, - GPIO_PF13, GPIO_PF14, GPIO_PF15, - GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9, -}; - -static const unsigned ppi0_24b_pins[] = { - GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6, - GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12, - GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PE0, GPIO_PE1, GPIO_PE2, - GPIO_PE3, GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, GPIO_PE8, - GPIO_PE9, GPIO_PD12, GPIO_PD15, -}; - -static const unsigned ppi1_8b_pins[] = { - GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6, - GPIO_PC7, GPIO_PC8, GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6, -}; - -static const unsigned ppi1_16b_pins[] = { - GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6, - GPIO_PC7, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, - GPIO_PC13, GPIO_PC14, GPIO_PC15, - GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6, -}; - -static const unsigned ppi2_8b_pins[] = { - GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, - GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3, -}; - -static const unsigned ppi2_16b_pins[] = { - GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6, - GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, GPIO_PA12, - GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB0, GPIO_PB1, GPIO_PB2, -}; - -static const unsigned lp0_pins[] = { - GPIO_PB0, GPIO_PB1, GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, - GPIO_PA4, GPIO_PA5, GPIO_PA6, GPIO_PA7, -}; - -static const unsigned lp1_pins[] = { - GPIO_PB3, GPIO_PB2, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, - GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, -}; - -static const unsigned lp2_pins[] = { - GPIO_PE6, GPIO_PE7, GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, - GPIO_PF4, GPIO_PF5, GPIO_PF6, GPIO_PF7, -}; - -static const unsigned lp3_pins[] = { - GPIO_PE9, GPIO_PE8, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, - GPIO_PF12, GPIO_PF13, GPIO_PF14, GPIO_PF15, -}; - -static const unsigned short uart0_mux[] = { - P_UART0_TX, P_UART0_RX, - 0 -}; - -static const unsigned short uart0_ctsrts_mux[] = { - P_UART0_RTS, P_UART0_CTS, - 0 -}; - -static const unsigned short uart1_mux[] = { - P_UART1_TX, P_UART1_RX, - 0 -}; - -static const unsigned short uart1_ctsrts_mux[] = { - P_UART1_RTS, P_UART1_CTS, - 0 -}; - -static const unsigned short rsi0_mux[] = { - P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, - P_RSI_CMD, P_RSI_CLK, 0 -}; - -static const unsigned short eth0_mux[] = P_RMII0; -static const unsigned short eth1_mux[] = P_RMII1; - -static const unsigned short spi0_mux[] = { - P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0 -}; - -static const unsigned short spi1_mux[] = { - P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0 -}; - -static const unsigned short twi0_mux[] = { - P_TWI0_SCL, P_TWI0_SDA, 0 -}; - -static const unsigned short twi1_mux[] = { - P_TWI1_SCL, P_TWI1_SDA, 0 -}; - -static const unsigned short rotary_mux[] = { - P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0 -}; - -static const unsigned short sport0_mux[] = { - P_SPORT0_ACLK, P_SPORT0_AFS, P_SPORT0_AD0, P_SPORT0_BCLK, - P_SPORT0_BFS, P_SPORT0_BD0, 0, -}; - -static const unsigned short sport1_mux[] = { - P_SPORT1_ACLK, P_SPORT1_AFS, P_SPORT1_AD0, P_SPORT1_BCLK, - P_SPORT1_BFS, P_SPORT1_BD0, 0, -}; - -static const unsigned short sport2_mux[] = { - P_SPORT2_ACLK, P_SPORT2_AFS, P_SPORT2_AD0, P_SPORT2_BCLK, - P_SPORT2_BFS, P_SPORT2_BD0, 0, -}; - -static const unsigned short can0_mux[] = { - P_CAN0_RX, P_CAN0_TX, 0 -}; - -static const unsigned short smc0_mux[] = { - P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12, - P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21, - P_A22, P_A23, P_A24, P_A25, P_NORCK, 0, -}; - -static const unsigned short ppi0_8b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi0_16b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi0_24b_mux[] = { - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, - P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19, - P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - 0, -}; - -static const unsigned short ppi1_8b_mux[] = { - P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, - P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, - P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, - 0, -}; - -static const unsigned short ppi1_16b_mux[] = { - P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3, - P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7, - P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11, - P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15, - P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2, - 0, -}; - -static const unsigned short ppi2_8b_mux[] = { - P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, - P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, - P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, - 0, -}; - -static const unsigned short ppi2_16b_mux[] = { - P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3, - P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7, - P_PPI2_D8, P_PPI2_D9, P_PPI2_D10, P_PPI2_D11, - P_PPI2_D12, P_PPI2_D13, P_PPI2_D14, P_PPI2_D15, - P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2, - 0, -}; - -static const unsigned short lp0_mux[] = { - P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2, - P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7, - 0 -}; - -static const unsigned short lp1_mux[] = { - P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2, - P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7, - 0 -}; - -static const unsigned short lp2_mux[] = { - P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2, - P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7, - 0 -}; - -static const unsigned short lp3_mux[] = { - P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2, - P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7, - 0 -}; - -static const struct adi_pin_group adi_pin_groups[] = { - ADI_PIN_GROUP("uart0grp", uart0_pins, uart0_mux), - ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins, uart0_ctsrts_mux), - ADI_PIN_GROUP("uart1grp", uart1_pins, uart1_mux), - ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins, uart1_ctsrts_mux), - ADI_PIN_GROUP("rsi0grp", rsi0_pins, rsi0_mux), - ADI_PIN_GROUP("eth0grp", eth0_pins, eth0_mux), - ADI_PIN_GROUP("eth1grp", eth1_pins, eth1_mux), - ADI_PIN_GROUP("spi0grp", spi0_pins, spi0_mux), - ADI_PIN_GROUP("spi1grp", spi1_pins, spi1_mux), - ADI_PIN_GROUP("twi0grp", twi0_pins, twi0_mux), - ADI_PIN_GROUP("twi1grp", twi1_pins, twi1_mux), - ADI_PIN_GROUP("rotarygrp", rotary_pins, rotary_mux), - ADI_PIN_GROUP("can0grp", can0_pins, can0_mux), - ADI_PIN_GROUP("smc0grp", smc0_pins, smc0_mux), - ADI_PIN_GROUP("sport0grp", sport0_pins, sport0_mux), - ADI_PIN_GROUP("sport1grp", sport1_pins, sport1_mux), - ADI_PIN_GROUP("sport2grp", sport2_pins, sport2_mux), - ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins, ppi0_8b_mux), - ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins, ppi0_16b_mux), - ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins, ppi0_24b_mux), - ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins, ppi1_8b_mux), - ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins, ppi1_16b_mux), - ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins, ppi2_8b_mux), - ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins, ppi2_16b_mux), - ADI_PIN_GROUP("lp0grp", lp0_pins, lp0_mux), - ADI_PIN_GROUP("lp1grp", lp1_pins, lp1_mux), - ADI_PIN_GROUP("lp2grp", lp2_pins, lp2_mux), - ADI_PIN_GROUP("lp3grp", lp3_pins, lp3_mux), -}; - -static const char * const uart0grp[] = { "uart0grp" }; -static const char * const uart0ctsrtsgrp[] = { "uart0ctsrtsgrp" }; -static const char * const uart1grp[] = { "uart1grp" }; -static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" }; -static const char * const rsi0grp[] = { "rsi0grp" }; -static const char * const eth0grp[] = { "eth0grp" }; -static const char * const eth1grp[] = { "eth1grp" }; -static const char * const spi0grp[] = { "spi0grp" }; -static const char * const spi1grp[] = { "spi1grp" }; -static const char * const twi0grp[] = { "twi0grp" }; -static const char * const twi1grp[] = { "twi1grp" }; -static const char * const rotarygrp[] = { "rotarygrp" }; -static const char * const can0grp[] = { "can0grp" }; -static const char * const smc0grp[] = { "smc0grp" }; -static const char * const sport0grp[] = { "sport0grp" }; -static const char * const sport1grp[] = { "sport1grp" }; -static const char * const sport2grp[] = { "sport2grp" }; -static const char * const ppi0grp[] = { "ppi0_8bgrp", - "ppi0_16bgrp", - "ppi0_24bgrp" }; -static const char * const ppi1grp[] = { "ppi1_8bgrp", - "ppi1_16bgrp" }; -static const char * const ppi2grp[] = { "ppi2_8bgrp", - "ppi2_16bgrp" }; -static const char * const lp0grp[] = { "lp0grp" }; -static const char * const lp1grp[] = { "lp1grp" }; -static const char * const lp2grp[] = { "lp2grp" }; -static const char * const lp3grp[] = { "lp3grp" }; - -static const struct adi_pmx_func adi_pmx_functions[] = { - ADI_PMX_FUNCTION("uart0", uart0grp), - ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp), - ADI_PMX_FUNCTION("uart1", uart1grp), - ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp), - ADI_PMX_FUNCTION("rsi0", rsi0grp), - ADI_PMX_FUNCTION("eth0", eth0grp), - ADI_PMX_FUNCTION("eth1", eth1grp), - ADI_PMX_FUNCTION("spi0", spi0grp), - ADI_PMX_FUNCTION("spi1", spi1grp), - ADI_PMX_FUNCTION("twi0", twi0grp), - ADI_PMX_FUNCTION("twi1", twi1grp), - ADI_PMX_FUNCTION("rotary", rotarygrp), - ADI_PMX_FUNCTION("can0", can0grp), - ADI_PMX_FUNCTION("smc0", smc0grp), - ADI_PMX_FUNCTION("sport0", sport0grp), - ADI_PMX_FUNCTION("sport1", sport1grp), - ADI_PMX_FUNCTION("sport2", sport2grp), - ADI_PMX_FUNCTION("ppi0", ppi0grp), - ADI_PMX_FUNCTION("ppi1", ppi1grp), - ADI_PMX_FUNCTION("ppi2", ppi2grp), - ADI_PMX_FUNCTION("lp0", lp0grp), - ADI_PMX_FUNCTION("lp1", lp1grp), - ADI_PMX_FUNCTION("lp2", lp2grp), - ADI_PMX_FUNCTION("lp3", lp3grp), -}; - -static const struct adi_pinctrl_soc_data adi_bf60x_soc = { - .functions = adi_pmx_functions, - .nfunctions = ARRAY_SIZE(adi_pmx_functions), - .groups = adi_pin_groups, - .ngroups = ARRAY_SIZE(adi_pin_groups), - .pins = adi_pads, - .npins = ARRAY_SIZE(adi_pads), -}; - -void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc) -{ - *soc = &adi_bf60x_soc; -} diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c deleted file mode 100644 index 094a451db2a2..000000000000 --- a/drivers/pinctrl/pinctrl-adi2.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* - * Pinctrl Driver for ADI GPIO2 controller - * - * Copyright 2007-2013 Analog Devices Inc. - * - * Licensed under the GPLv2 or later - */ - -#include <linux/bitops.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/err.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/irq.h> -#include <linux/platform_data/pinctrl-adi2.h> -#include <linux/irqdomain.h> -#include <linux/irqchip/chained_irq.h> -#include <linux/pinctrl/pinctrl.h> -#include <linux/pinctrl/pinmux.h> -#include <linux/pinctrl/consumer.h> -#include <linux/pinctrl/machine.h> -#include <linux/syscore_ops.h> -#include <linux/gpio.h> -#include <asm/portmux.h> -#include "pinctrl-adi2.h" -#include "core.h" - -/* -According to the BF54x HRM, pint means "pin interrupt". -http://www.analog.com/static/imported-files/processor_manuals/ADSP-BF54x_hwr_rev1.2.pdf - -ADSP-BF54x processor Blackfin processors have four SIC interrupt chan- -nels dedicated to pin interrupt purposes. These channels are managed by -four hardware blocks, called PINT0, PINT1, PINT2, and PINT3. Every PINTx -block can sense to up to 32 pins. While PINT0 and PINT1 can sense the -pins of port A and port B, PINT2 and PINT3 manage all the pins from port -C to port J as shown in Figure 9-2. - -n BF54x HRM: -The ten GPIO ports are subdivided into 8-bit half ports, resulting in lower and -upper half 8-bit units. The PINTx_ASSIGN registers control the 8-bit multi- -plexers shown in Figure 9-3. Lower half units of eight pins can be -forwarded to either byte 0 or byte 2 of either associated PINTx block. -Upper half units can be forwarded to either byte 1 or byte 3 of the pin -interrupt blocks, without further restrictions. - -All MMR registers in the pin interrupt module are 32 bits wide. To simply the -mapping logic, this driver only maps a 16-bit gpio port to the upper or lower -16 bits of a PINTx block. You can find the Figure 9-3 on page 583. - -Each IRQ domain is binding to a GPIO bank device. 2 GPIO bank devices can map -to one PINT device. Two in "struct gpio_pint" are used to ease the PINT -interrupt handler. - -The GPIO bank mapping to the lower 16 bits of the PINT device set its IRQ -domain pointer in domain[0]. The IRQ domain pointer of the other bank is set -to domain[1]. PINT interrupt handler adi_gpio_handle_pint_irq() finds out -the current domain pointer according to whether the interrupt request mask -is in lower 16 bits (domain[0]) or upper 16bits (domain[1]). - -A PINT device is not part of a GPIO port device in Blackfin. Multiple GPIO -port devices can be mapped to the same PINT device. - -*/ - -static LIST_HEAD(adi_pint_list); -static LIST_HEAD(adi_gpio_port_list); - -#define DRIVER_NAME "pinctrl-adi2" - -#define PINT_HI_OFFSET 16 - -/** - * struct gpio_port_saved - GPIO port registers that should be saved between - * power suspend and resume operations. - * - * @fer: PORTx_FER register - * @data: PORTx_DATA register - * @dir: PORTx_DIR register - * @inen: PORTx_INEN register - * @mux: PORTx_MUX register - */ -struct gpio_port_saved { - u16 fer; - u16 data; - u16 dir; - u16 inen; - u32 mux; -}; - -/* - * struct gpio_pint_saved - PINT registers saved in PM operations - * - * @assign: ASSIGN register - * @edge_set: EDGE_SET register - * @invert_set: INVERT_SET register - */ -struct gpio_pint_saved { - u32 assign; - u32 edge_set; - u32 invert_set; -}; - -/** - * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO - * banks can be mapped into one Pin interrupt controller. - * - * @node: All gpio_pint instances are added to a global list. - * @base: PINT device register base address - * @irq: IRQ of the PINT device, it is the parent IRQ of all - * GPIO IRQs mapping to this device. - * @domain: [0] irq domain of the gpio port, whose hardware interrupts are - * mapping to the low 16-bit of the pint registers. - * [1] irq domain of the gpio port, whose hardware interrupts are - * mapping to the high 16-bit of the pint registers. - * @regs: address pointer to the PINT device - * @map_count: No more than 2 GPIO banks can be mapped to this PINT device. - * @lock: This lock make sure the irq_chip operations to one PINT device - * for different GPIO interrrupts are atomic. - * @pint_map_port: Set up the mapping between one PINT device and - * multiple GPIO banks. - */ -struct gpio_pint { - struct list_head node; - void __iomem *base; - int irq; - struct irq_domain *domain[2]; - struct gpio_pint_regs *regs; - struct gpio_pint_saved saved_data; - int map_count; - spinlock_t lock; - - int (*pint_map_port)(struct gpio_pint *pint, bool assign, - u8 map, struct irq_domain *domain); -}; - -/** - * ADI pin controller - * - * @dev: a pointer back to containing device - * @pctl: the pinctrl device - * @soc: SoC data for this specific chip - */ -struct adi_pinctrl { - struct device *dev; - struct pinctrl_dev *pctl; - const struct adi_pinctrl_soc_data *soc; -}; - -/** - * struct gpio_port - GPIO bank device. Multiple ADI GPIO banks can be mapped - * into one pin interrupt controller. - * - * @node: All gpio_port instances are added to a list. - * @base: GPIO bank device register base address - * @irq_base: base IRQ of the GPIO bank device - * @width: PIN number of the GPIO bank device - * @regs: address pointer to the GPIO bank device - * @saved_data: registers that should be saved between PM operations. - * @dev: device structure of this GPIO bank - * @pint: GPIO PINT device that this GPIO bank mapped to - * @pint_map: GIOP bank mapping code in PINT device - * @pint_assign: The 32-bit PINT registers can be divided into 2 parts. A - * GPIO bank can be mapped into either low 16 bits[0] or high 16 - * bits[1] of each PINT register. - * @lock: This lock make sure the irq_chip operations to one PINT device - * for different GPIO interrrupts are atomic. - * @chip: abstract a GPIO controller - * @domain: The irq domain owned by the GPIO port. - * @rsvmap: Reservation map array for each pin in the GPIO bank - */ -struct gpio_port { - struct list_head node; - void __iomem *base; - int irq_base; - unsigned int width; - struct gpio_port_t *regs; - struct gpio_port_saved saved_data; - struct device *dev; - - struct gpio_pint *pint; - u8 pint_map; - bool pint_assign; - - spinlock_t lock; - struct gpio_chip chip; - struct irq_domain *domain; -}; - -static inline u8 pin_to_offset(struct pinctrl_gpio_range *range, unsigned pin) -{ - return pin - range->pin_base; -} - -static inline u32 hwirq_to_pintbit(struct gpio_port *port, int hwirq) -{ - return port->pint_assign ? BIT(hwirq) << PINT_HI_OFFSET : BIT(hwirq); -} - -static struct gpio_pint *find_gpio_pint(unsigned id) -{ - struct gpio_pint *pint; - int i = 0; - - list_for_each_entry(pint, &adi_pint_list, node) { - if (id == i) - return pint; - i++; - } - - return NULL; -} - -static inline void port_setup(struct gpio_port *port, unsigned offset, - bool use_for_gpio) -{ - struct gpio_port_t *regs = port->regs; - - if (use_for_gpio) - writew(readw(®s->port_fer) & ~BIT(offset), - ®s->port_fer); - else - writew(readw(®s->port_fer) | BIT(offset), ®s->port_fer); -} - -static inline void portmux_setup(struct gpio_port *port, unsigned offset, - unsigned short function) -{ - struct gpio_port_t *regs = port->regs; - u32 pmux; - - pmux = readl(®s->port_mux); - - /* The function field of each pin has 2 consecutive bits in - * the mux register. - */ - pmux &= ~(0x3 << (2 * offset)); - pmux |= (function & 0x3) << (2 * offset); - - writel(pmux, ®s->port_mux); -} - -static inline u16 get_portmux(struct gpio_port *port, unsigned offset) -{ - struct gpio_port_t *regs = port->regs; - u32 pmux = readl(®s->port_mux); - - /* The function field of each pin has 2 consecutive bits in - * the mux register. - */ - return pmux >> (2 * offset) & 0x3; -} - -static void adi_gpio_ack_irq(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs = port->pint->regs; - unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (readl(®s->invert_set) & pintbit) - writel(pintbit, ®s->invert_clear); - else - writel(pintbit, ®s->invert_set); - } - - writel(pintbit, ®s->request); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void adi_gpio_mask_ack_irq(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs = port->pint->regs; - unsigned pintbit = hwirq_to_pintbit(port, d->hwirq); - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) { - if (readl(®s->invert_set) & pintbit) - writel(pintbit, ®s->invert_clear); - else - writel(pintbit, ®s->invert_set); - } - - writel(pintbit, ®s->request); - writel(pintbit, ®s->mask_clear); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void adi_gpio_mask_irq(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs = port->pint->regs; - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void adi_gpio_unmask_irq(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs = port->pint->regs; - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); -} - -static unsigned int adi_gpio_irq_startup(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs; - - if (!port) { - pr_err("GPIO IRQ %d :Not exist\n", d->irq); - /* FIXME: negative return code will be ignored */ - return -ENODEV; - } - - regs = port->pint->regs; - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - port_setup(port, d->hwirq, true); - writew(BIT(d->hwirq), &port->regs->dir_clear); - writew(readw(&port->regs->inen) | BIT(d->hwirq), &port->regs->inen); - - writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_set); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); - - return 0; -} - -static void adi_gpio_irq_shutdown(struct irq_data *d) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *regs = port->pint->regs; - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - writel(hwirq_to_pintbit(port, d->hwirq), ®s->mask_clear); - - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); -} - -static int adi_gpio_irq_type(struct irq_data *d, unsigned int type) -{ - unsigned long flags; - struct gpio_port *port = irq_data_get_irq_chip_data(d); - struct gpio_pint_regs *pint_regs; - unsigned pintmask; - unsigned int irq = d->irq; - int ret = 0; - char buf[16]; - - if (!port) { - pr_err("GPIO IRQ %d :Not exist\n", d->irq); - return -ENODEV; - } - - pint_regs = port->pint->regs; - - pintmask = hwirq_to_pintbit(port, d->hwirq); - - spin_lock_irqsave(&port->lock, flags); - spin_lock(&port->pint->lock); - - /* In case of interrupt autodetect, set irq type to edge sensitive. */ - if (type == IRQ_TYPE_PROBE) - type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | - IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { - snprintf(buf, 16, "gpio-irq%u", irq); - port_setup(port, d->hwirq, true); - } else - goto out; - - /* The GPIO interrupt is triggered only when its input value - * transfer from 0 to 1. So, invert the input value if the - * irq type is low or falling - */ - if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) - writel(pintmask, &pint_regs->invert_set); - else - writel(pintmask, &pint_regs->invert_clear); - - /* In edge sensitive case, if the input value of the requested irq - * is already 1, invert it. - */ - if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { - if (gpio_get_value(port->chip.base + d->hwirq)) - writel(pintmask, &pint_regs->invert_set); - else - writel(pintmask, &pint_regs->invert_clear); - } - - if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { - writel(pintmask, &pint_regs->edge_set); - irq_set_handler_locked(d, handle_edge_irq); - } else { - writel(pintmask, &pint_regs->edge_clear); - irq_set_handler_locked(d, handle_level_irq); - } - -out: - spin_unlock(&port->pint->lock); - spin_unlock_irqrestore(&port->lock, flags); - - return ret; -} - -#ifdef CONFIG_PM -static int adi_gpio_set_wake(struct irq_data *d, unsigned int state) -{ - struct gpio_port *port = irq_data_get_irq_chip_data(d); - - if (!port || !port->pint || port->pint->irq != d->irq) - return -EINVAL; - -#ifndef SEC_GCTL - adi_internal_set_wake(port->pint->irq, state); -#endif - - return 0; -} - -static int adi_pint_suspend(void) -{ - struct gpio_pint *pint; - - list_for_each_entry(pint, &adi_pint_list, node) { - writel(0xffffffff, &pint->regs->mask_clear); - pint->saved_data.assign = readl(&pint->regs->assign); - pint->saved_data.edge_set = readl(&pint->regs->edge_set); - pint->saved_data.invert_set = readl(&pint->regs->invert_set); - } - - return 0; -} - -static void adi_pint_resume(void) -{ - struct gpio_pint *pint; - - list_for_each_entry(pint, &adi_pint_list, node) { - writel(pint->saved_data.assign, &pint->regs->assign); - writel(pint->saved_data.edge_set, &pint->regs->edge_set); - writel(pint->saved_data.invert_set, &pint->regs->invert_set); - } -} - -static int adi_gpio_suspend(void) -{ - struct gpio_port *port; - - list_for_each_entry(port, &adi_gpio_port_list, node) { - port->saved_data.fer = readw(&port->regs->port_fer); - port->saved_data.mux = readl(&port->regs->port_mux); - port->saved_data.data = readw(&port->regs->data); - port->saved_data.inen = readw(&port->regs->inen); - port->saved_data.dir = readw(&port->regs->dir_set); - } - - return adi_pint_suspend(); -} - -static void adi_gpio_resume(void) -{ - struct gpio_port *port; - - adi_pint_resume(); - - list_for_each_entry(port, &adi_gpio_port_list, node) { - writel(port->saved_data.mux, &port->regs->port_mux); - writew(port->saved_data.fer, &port->regs->port_fer); - writew(port->saved_data.inen, &port->regs->inen); - writew(port->saved_data.data & port->saved_data.dir, - &port->regs->data_set); - writew(port->saved_data.dir, &port->regs->dir_set); - } - -} - -static struct syscore_ops gpio_pm_syscore_ops = { - .suspend = adi_gpio_suspend, - .resume = adi_gpio_resume, -}; -#else /* CONFIG_PM */ -#define adi_gpio_set_wake NULL -#endif /* CONFIG_PM */ - -#ifdef CONFIG_IRQ_PREFLOW_FASTEOI -static inline void preflow_handler(struct irq_desc *desc) -{ - if (desc->preflow_handler) - desc->preflow_handler(&desc->irq_data); -} -#else -static inline void preflow_handler(struct irq_desc *desc) { } -#endif - -static void adi_gpio_handle_pint_irq(struct irq_desc *desc) -{ - u32 request; - u32 level_mask, hwirq; - bool umask = false; - struct gpio_pint *pint = irq_desc_get_handler_data(desc); - struct irq_chip *chip = irq_desc_get_chip(desc); - struct gpio_pint_regs *regs = pint->regs; - struct irq_domain *domain; - - preflow_handler(desc); - chained_irq_enter(chip, desc); - - request = readl(®s->request); - level_mask = readl(®s->edge_set) & request; - - hwirq = 0; - domain = pint->domain[0]; - while (request) { - /* domain pointer need to be changed only once at IRQ 16 when - * we go through IRQ requests from bit 0 to bit 31. - */ - if (hwirq == PINT_HI_OFFSET) - domain = pint->domain[1]; - - if (request & 1) { - if (level_mask & BIT(hwirq)) { - umask = true; - chained_irq_exit(chip, desc); - } - generic_handle_irq(irq_find_mapping(domain, - hwirq % PINT_HI_OFFSET)); - } - - hwirq++; - request >>= 1; - } - - if (!umask) - chained_irq_exit(chip, desc); -} - -static struct irq_chip adi_gpio_irqchip = { - .name = "GPIO", - .irq_ack = adi_gpio_ack_irq, - .irq_mask = adi_gpio_mask_irq, - .irq_mask_ack = adi_gpio_mask_ack_irq, - .irq_unmask = adi_gpio_unmask_irq, - .irq_disable = adi_gpio_mask_irq, - .irq_enable = adi_gpio_unmask_irq, - .irq_set_type = adi_gpio_irq_type, - .irq_startup = adi_gpio_irq_startup, - .irq_shutdown = adi_gpio_irq_shutdown, - .irq_set_wake = adi_gpio_set_wake, -}; - -static int adi_get_groups_count(struct pinctrl_dev *pctldev) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - return pinctrl->soc->ngroups; -} - -static const char *adi_get_group_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - return pinctrl->soc->groups[selector].name; -} - -static int adi_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, - const unsigned **pins, - unsigned *num_pins) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - *pins = pinctrl->soc->groups[selector].pins; - *num_pins = pinctrl->soc->groups[selector].num; - return 0; -} - -static const struct pinctrl_ops adi_pctrl_ops = { - .get_groups_count = adi_get_groups_count, - .get_group_name = adi_get_group_name, - .get_group_pins = adi_get_group_pins, -}; - -static int adi_pinmux_set(struct pinctrl_dev *pctldev, unsigned func_id, - unsigned group_id) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - struct gpio_port *port; - struct pinctrl_gpio_range *range; - unsigned long flags; - unsigned short *mux, pin; - - mux = (unsigned short *)pinctrl->soc->groups[group_id].mux; - - while (*mux) { - pin = P_IDENT(*mux); - - range = pinctrl_find_gpio_range_from_pin(pctldev, pin); - if (range == NULL) /* should not happen */ - return -ENODEV; - - port = gpiochip_get_data(range->gc); - - spin_lock_irqsave(&port->lock, flags); - - portmux_setup(port, pin_to_offset(range, pin), - P_FUNCT2MUX(*mux)); - port_setup(port, pin_to_offset(range, pin), false); - mux++; - - spin_unlock_irqrestore(&port->lock, flags); - } - - return 0; -} - -static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - return pinctrl->soc->nfunctions; -} - -static const char *adi_pinmux_get_func_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - return pinctrl->soc->functions[selector].name; -} - -static int adi_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector, - const char * const **groups, - unsigned * const num_groups) -{ - struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev); - - *groups = pinctrl->soc->functions[selector].groups; - *num_groups = pinctrl->soc->functions[selector].num_groups; - return 0; -} - -static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, unsigned pin) -{ - struct gpio_port *port; - unsigned long flags; - u8 offset; - - port = gpiochip_get_data(range->gc); - offset = pin_to_offset(range, pin); - - spin_lock_irqsave(&port->lock, flags); - - port_setup(port, offset, true); - - spin_unlock_irqrestore(&port->lock, flags); - - return 0; -} - -static const struct pinmux_ops adi_pinmux_ops = { - .set_mux = adi_pinmux_set, - .get_functions_count = adi_pinmux_get_funcs_count, - .get_function_name = adi_pinmux_get_func_name, - .get_function_groups = adi_pinmux_get_groups, - .gpio_request_enable = adi_pinmux_request_gpio, - .strict = true, -}; - - -static struct pinctrl_desc adi_pinmux_desc = { - .name = DRIVER_NAME, - .pctlops = &adi_pctrl_ops, - .pmxops = &adi_pinmux_ops, - .owner = THIS_MODULE, -}; - -static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_port *port; - unsigned long flags; - - port = gpiochip_get_data(chip); - - spin_lock_irqsave(&port->lock, flags); - - writew(BIT(offset), &port->regs->dir_clear); - writew(readw(&port->regs->inen) | BIT(offset), &port->regs->inen); - - spin_unlock_irqrestore(&port->lock, flags); - - return 0; -} - -static void adi_gpio_set_value(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct gpio_port *port = gpiochip_get_data(chip); - struct gpio_port_t *regs = port->regs; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - - if (value) - writew(BIT(offset), ®s->data_set); - else - writew(BIT(offset), ®s->data_clear); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static int adi_gpio_direction_output(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct gpio_port *port = gpiochip_get_data(chip); - struct gpio_port_t *regs = port->regs; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - - writew(readw(®s->inen) & ~BIT(offset), ®s->inen); - if (value) - writew(BIT(offset), ®s->data_set); - else - writew(BIT(offset), ®s->data_clear); - writew(BIT(offset), ®s->dir_set); - - spin_unlock_irqrestore(&port->lock, flags); - - return 0; -} - -static int adi_gpio_get_value(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_port *port = gpiochip_get_data(chip); - struct gpio_port_t *regs = port->regs; - unsigned long flags; - int ret; - - spin_lock_irqsave(&port->lock, flags); - - ret = !!(readw(®s->data) & BIT(offset)); - - spin_unlock_irqrestore(&port->lock, flags); - - return ret; -} - -static int adi_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct gpio_port *port = gpiochip_get_data(chip); - - if (port->irq_base >= 0) - return irq_find_mapping(port->domain, offset); - else - return irq_create_mapping(port->domain, offset); -} - -static int adi_pint_map_port(struct gpio_pint *pint, bool assign, u8 map, - struct irq_domain *domain) -{ - struct gpio_pint_regs *regs = pint->regs; - u32 map_mask; - - if (pint->map_count > 1) - return -EINVAL; - - pint->map_count++; - - /* The map_mask of each gpio port is a 16-bit duplicate - * of the 8-bit map. It can be set to either high 16 bits or low - * 16 bits of the pint assignment register. - */ - map_mask = (map << 8) | map; - if (assign) { - map_mask <<= PINT_HI_OFFSET; - writel((readl(®s->assign) & 0xFFFF) | map_mask, - ®s->assign); - } else - writel((readl(®s->assign) & 0xFFFF0000) | map_mask, - ®s->assign); - - pint->domain[assign] = domain; - - return 0; -} - -static int adi_gpio_pint_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct gpio_pint *pint = devm_kzalloc(dev, sizeof(*pint), GFP_KERNEL); - - if (!pint) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pint->base = devm_ioremap_resource(dev, res); - if (IS_ERR(pint->base)) - return PTR_ERR(pint->base); - - pint->regs = (struct gpio_pint_regs *)pint->base; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "Invalid IRQ resource\n"); - return -ENODEV; - } - - spin_lock_init(&pint->lock); - - pint->irq = res->start; - pint->pint_map_port = adi_pint_map_port; - platform_set_drvdata(pdev, pint); - - irq_set_chained_handler_and_data(pint->irq, adi_gpio_handle_pint_irq, - pint); - - list_add_tail(&pint->node, &adi_pint_list); - - return 0; -} - -static int adi_gpio_pint_remove(struct platform_device *pdev) -{ - struct gpio_pint *pint = platform_get_drvdata(pdev); - - list_del(&pint->node); - irq_set_handler(pint->irq, handle_simple_irq); - - return 0; -} - -static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq, - irq_hw_number_t hwirq) -{ - struct gpio_port *port = d->host_data; - - if (!port) - return -EINVAL; - - irq_set_chip_data(irq, port); - irq_set_chip_and_handler(irq, &adi_gpio_irqchip, - handle_level_irq); - - return 0; -} - -static const struct irq_domain_ops adi_gpio_irq_domain_ops = { - .map = adi_gpio_irq_map, - .xlate = irq_domain_xlate_onecell, -}; - -static int adi_gpio_init_int(struct gpio_port *port) -{ - struct device_node *node = port->dev->of_node; - struct gpio_pint *pint = port->pint; - int ret; - - port->domain = irq_domain_add_linear(node, port->width, - &adi_gpio_irq_domain_ops, port); - if (!port->domain) { - dev_err(port->dev, "Failed to create irqdomain\n"); - return -ENOSYS; - } - - /* According to BF54x and BF60x HRM, pin interrupt devices are not - * part of the GPIO port device. in GPIO interrupt mode, the GPIO - * pins of multiple port devices can be routed into one pin interrupt - * device. The mapping can be configured by setting pint assignment - * register with the mapping value of different GPIO port. This is - * done via function pint_map_port(). - */ - ret = pint->pint_map_port(port->pint, port->pint_assign, - port->pint_map, port->domain); - if (ret) - return ret; - - if (port->irq_base >= 0) { - ret = irq_create_strict_mappings(port->domain, port->irq_base, - 0, port->width); - if (ret) { - dev_err(port->dev, "Couldn't associate to domain\n"); - return ret; - } - } - - return 0; -} - -#define DEVNAME_SIZE 16 - -static int adi_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - const struct adi_pinctrl_gpio_platform_data *pdata; - struct resource *res; - struct gpio_port *port; - char pinctrl_devname[DEVNAME_SIZE]; - static int gpio; - int ret = 0; - - pdata = dev->platform_data; - if (!pdata) - return -EINVAL; - - port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); - if (!port) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - port->base = devm_ioremap_resource(dev, res); - if (IS_ERR(port->base)) - return PTR_ERR(port->base); - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) - port->irq_base = -1; - else - port->irq_base = res->start; - - port->width = pdata->port_width; - port->dev = dev; - port->regs = (struct gpio_port_t *)port->base; - port->pint_assign = pdata->pint_assign; - port->pint_map = pdata->pint_map; - - port->pint = find_gpio_pint(pdata->pint_id); - if (port->pint) { - ret = adi_gpio_init_int(port); - if (ret) - return ret; - } - - spin_lock_init(&port->lock); - - platform_set_drvdata(pdev, port); - - port->chip.label = "adi-gpio"; - port->chip.direction_input = adi_gpio_direction_input; - port->chip.get = adi_gpio_get_value; - port->chip.direction_output = adi_gpio_direction_output; - port->chip.set = adi_gpio_set_value; - port->chip.request = gpiochip_generic_request, - port->chip.free = gpiochip_generic_free, - port->chip.to_irq = adi_gpio_to_irq; - if (pdata->port_gpio_base > 0) - port->chip.base = pdata->port_gpio_base; - else - port->chip.base = gpio; - port->chip.ngpio = port->width; - gpio = port->chip.base + port->width; - - ret = gpiochip_add_data(&port->chip, port); - if (ret) { - dev_err(&pdev->dev, "Fail to add GPIO chip.\n"); - goto out_remove_domain; - } - - /* Add gpio pin range */ - snprintf(pinctrl_devname, DEVNAME_SIZE, "pinctrl-adi2.%d", - pdata->pinctrl_id); - pinctrl_devname[DEVNAME_SIZE - 1] = 0; - ret = gpiochip_add_pin_range(&port->chip, pinctrl_devname, - 0, pdata->port_pin_base, port->width); - if (ret) { - dev_err(&pdev->dev, "Fail to add pin range to %s.\n", - pinctrl_devname); - goto out_remove_gpiochip; - } - - list_add_tail(&port->node, &adi_gpio_port_list); - - return 0; - -out_remove_gpiochip: - gpiochip_remove(&port->chip); -out_remove_domain: - if (port->pint) - irq_domain_remove(port->domain); - - return ret; -} - -static int adi_gpio_remove(struct platform_device *pdev) -{ - struct gpio_port *port = platform_get_drvdata(pdev); - u8 offset; - - list_del(&port->node); - gpiochip_remove(&port->chip); - if (port->pint) { - for (offset = 0; offset < port->width; offset++) - irq_dispose_mapping(irq_find_mapping(port->domain, - offset)); - irq_domain_remove(port->domain); - } - - return 0; -} - -static int adi_pinctrl_probe(struct platform_device *pdev) -{ - struct adi_pinctrl *pinctrl; - - pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL); - if (!pinctrl) - return -ENOMEM; - - pinctrl->dev = &pdev->dev; - - adi_pinctrl_soc_init(&pinctrl->soc); - - adi_pinmux_desc.pins = pinctrl->soc->pins; - adi_pinmux_desc.npins = pinctrl->soc->npins; - - /* Now register the pin controller and all pins it handles */ - pinctrl->pctl = devm_pinctrl_register(&pdev->dev, &adi_pinmux_desc, - pinctrl); - if (IS_ERR(pinctrl->pctl)) { - dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n"); - return PTR_ERR(pinctrl->pctl); - } - - platform_set_drvdata(pdev, pinctrl); - - return 0; -} - -static struct platform_driver adi_pinctrl_driver = { - .probe = adi_pinctrl_probe, - .driver = { - .name = DRIVER_NAME, - }, -}; - -static struct platform_driver adi_gpio_pint_driver = { - .probe = adi_gpio_pint_probe, - .remove = adi_gpio_pint_remove, - .driver = { - .name = "adi-gpio-pint", - }, -}; - -static struct platform_driver adi_gpio_driver = { - .probe = adi_gpio_probe, - .remove = adi_gpio_remove, - .driver = { - .name = "adi-gpio", - }, -}; - -static struct platform_driver * const drivers[] = { - &adi_pinctrl_driver, - &adi_gpio_pint_driver, - &adi_gpio_driver, -}; - -static int __init adi_pinctrl_setup(void) -{ - int ret; - - ret = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); - if (ret) - return ret; - -#ifdef CONFIG_PM - register_syscore_ops(&gpio_pm_syscore_ops); -#endif - return 0; -} -arch_initcall(adi_pinctrl_setup); - -MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); -MODULE_DESCRIPTION("ADI gpio2 pin control driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-adi2.h b/drivers/pinctrl/pinctrl-adi2.h deleted file mode 100644 index 3ca29738213f..000000000000 --- a/drivers/pinctrl/pinctrl-adi2.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Pinctrl Driver for ADI GPIO2 controller - * - * Copyright 2007-2013 Analog Devices Inc. - * - * Licensed under the GPLv2 or later - */ - -#ifndef PINCTRL_PINCTRL_ADI2_H -#define PINCTRL_PINCTRL_ADI2_H - -#include <linux/pinctrl/pinctrl.h> - - /** - * struct adi_pin_group - describes a pin group - * @name: the name of this pin group - * @pins: an array of pins - * @num: the number of pins in this array - */ -struct adi_pin_group { - const char *name; - const unsigned *pins; - const unsigned num; - const unsigned short *mux; -}; - -#define ADI_PIN_GROUP(n, p, m) \ - { \ - .name = n, \ - .pins = p, \ - .num = ARRAY_SIZE(p), \ - .mux = m, \ - } - - /** - * struct adi_pmx_func - describes function mux setting of pin groups - * @name: the name of this function mux setting - * @groups: an array of pin groups - * @num_groups: the number of pin groups in this array - * @mux: the function mux setting array, end by zero - */ -struct adi_pmx_func { - const char *name; - const char * const *groups; - const unsigned num_groups; -}; - -#define ADI_PMX_FUNCTION(n, g) \ - { \ - .name = n, \ - .groups = g, \ - .num_groups = ARRAY_SIZE(g), \ - } - -/** - * struct adi_pinctrl_soc_data - ADI pin controller per-SoC configuration - * @functions: The functions supported on this SoC. - * @nfunction: The number of entries in @functions. - * @groups: An array describing all pin groups the pin SoC supports. - * @ngroups: The number of entries in @groups. - * @pins: An array describing all pins the pin controller affects. - * @npins: The number of entries in @pins. - */ -struct adi_pinctrl_soc_data { - const struct adi_pmx_func *functions; - int nfunctions; - const struct adi_pin_group *groups; - int ngroups; - const struct pinctrl_pin_desc *pins; - int npins; -}; - -void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc); - -#endif /* PINCTRL_PINCTRL_ADI2_H */ diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 763ee50ea57d..38d49dbbf9b7 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -43,7 +43,7 @@ config PWM_AB8500 config PWM_ATMEL tristate "Atmel PWM support" - depends on ARCH_AT91 || AVR32 + depends on ARCH_AT91 help Generic PWM framework driver for Atmel SoC. @@ -113,15 +113,6 @@ config PWM_BERLIN To compile this driver as a module, choose M here: the module will be called pwm-berlin. -config PWM_BFIN - tristate "Blackfin PWM support" - depends on BFIN_GPTIMERS - help - Generic PWM framework driver for Blackfin. - - To compile this driver as a module, choose M here: the module - will be called pwm-bfin. - config PWM_BRCMSTB tristate "Broadcom STB PWM support" depends on ARCH_BRCMSTB || BMIPS_GENERIC diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 0258a745f30c..9c676a0dadf5 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o -obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o obj-$(CONFIG_PWM_CRC) += pwm-crc.o diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c deleted file mode 100644 index a9a88137f2cb..000000000000 --- a/drivers/pwm/pwm-bfin.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Blackfin Pulse Width Modulation (PWM) core - * - * Copyright (c) 2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pwm.h> -#include <linux/slab.h> - -#include <asm/gptimers.h> -#include <asm/portmux.h> - -struct bfin_pwm_chip { - struct pwm_chip chip; -}; - -struct bfin_pwm { - unsigned short pin; -}; - -static const unsigned short pwm_to_gptimer_per[] = { - P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5, - P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11, -}; - -static int bfin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bfin_pwm *priv; - int ret; - - if (pwm->hwpwm >= ARRAY_SIZE(pwm_to_gptimer_per)) - return -EINVAL; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->pin = pwm_to_gptimer_per[pwm->hwpwm]; - - ret = peripheral_request(priv->pin, NULL); - if (ret) { - kfree(priv); - return ret; - } - - pwm_set_chip_data(pwm, priv); - - return 0; -} - -static void bfin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bfin_pwm *priv = pwm_get_chip_data(pwm); - - if (priv) { - peripheral_free(priv->pin); - kfree(priv); - } -} - -static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) -{ - struct bfin_pwm *priv = pwm_get_chip_data(pwm); - unsigned long period, duty; - unsigned long long val; - - val = (unsigned long long)get_sclk() * period_ns; - do_div(val, NSEC_PER_SEC); - period = val; - - val = (unsigned long long)period * duty_ns; - do_div(val, period_ns); - duty = period - val; - - if (duty >= period) - duty = period - 1; - - set_gptimer_config(priv->pin, TIMER_MODE_PWM | TIMER_PERIOD_CNT); - set_gptimer_pwidth(priv->pin, duty); - set_gptimer_period(priv->pin, period); - - return 0; -} - -static int bfin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bfin_pwm *priv = pwm_get_chip_data(pwm); - - enable_gptimer(priv->pin); - - return 0; -} - -static void bfin_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -{ - struct bfin_pwm *priv = pwm_get_chip_data(pwm); - - disable_gptimer(priv->pin); -} - -static const struct pwm_ops bfin_pwm_ops = { - .request = bfin_pwm_request, - .free = bfin_pwm_free, - .config = bfin_pwm_config, - .enable = bfin_pwm_enable, - .disable = bfin_pwm_disable, - .owner = THIS_MODULE, -}; - -static int bfin_pwm_probe(struct platform_device *pdev) -{ - struct bfin_pwm_chip *pwm; - int ret; - - pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); - if (!pwm) - return -ENOMEM; - - platform_set_drvdata(pdev, pwm); - - pwm->chip.dev = &pdev->dev; - pwm->chip.ops = &bfin_pwm_ops; - pwm->chip.base = -1; - pwm->chip.npwm = 12; - - ret = pwmchip_add(&pwm->chip); - if (ret < 0) { - dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); - return ret; - } - - return 0; -} - -static int bfin_pwm_remove(struct platform_device *pdev) -{ - struct bfin_pwm_chip *pwm = platform_get_drvdata(pdev); - - return pwmchip_remove(&pwm->chip); -} - -static struct platform_driver bfin_pwm_driver = { - .driver = { - .name = "bfin-pwm", - }, - .probe = bfin_pwm_probe, - .remove = bfin_pwm_remove, -}; - -module_platform_driver(bfin_pwm_driver); - -MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8ab5f0a5d323..319e3c8976d5 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -868,7 +868,7 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" - depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 + depends on X86 || ARM || PPC || MIPS || SPARC64 default y if X86 select RTC_MC146818_LIB help @@ -1434,16 +1434,6 @@ config RTC_DRV_AU1XXX This driver can also be built as a module. If so, the module will be called rtc-au1xxx. -config RTC_DRV_BFIN - tristate "Blackfin On-Chip RTC" - depends on BLACKFIN && !BF561 - help - If you say yes here you will get support for the - Blackfin On-Chip Real Time Clock. - - This driver can also be built as a module. If so, the module - will be called rtc-bfin. - config RTC_DRV_RS5C313 tristate "Ricoh RS5C313" depends on SH_LANDISK @@ -1656,13 +1646,6 @@ config RTC_DRV_TEGRA This drive can also be built as a module. If so, the module will be called rtc-tegra. -config RTC_DRV_TILE - tristate "Tilera hypervisor RTC support" - depends on TILE - help - Enable support for the Linux driver side of the Tilera - hypervisor's real-time clock interface. - config RTC_DRV_PUV3 tristate "PKUnity v3 RTC support" depends on ARCH_PUV3 diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 4fbf87e45a7c..ee0206becd9f 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o -obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o obj-$(CONFIG_RTC_DRV_BRCMSTB) += rtc-brcmstb-waketimer.o obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o @@ -162,7 +161,6 @@ obj-$(CONFIG_RTC_DRV_SUN6I) += rtc-sun6i.o obj-$(CONFIG_RTC_DRV_SUNXI) += rtc-sunxi.o obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o -obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o obj-$(CONFIG_RTC_DRV_TPS80031) += rtc-tps80031.o diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c deleted file mode 100644 index 15344b7c07c5..000000000000 --- a/drivers/rtc/rtc-bfin.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Blackfin On-Chip Real Time Clock Driver - * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x - * - * Copyright 2004-2010 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -/* The biggest issue we deal with in this driver is that register writes are - * synced to the RTC frequency of 1Hz. So if you write to a register and - * attempt to write again before the first write has completed, the new write - * is simply discarded. This can easily be troublesome if userspace disables - * one event (say periodic) and then right after enables an event (say alarm). - * Since all events are maintained in the same interrupt mask register, if - * we wrote to it to disable the first event and then wrote to it again to - * enable the second event, that second event would not be enabled as the - * write would be discarded and things quickly fall apart. - * - * To keep this delay from significantly degrading performance (we, in theory, - * would have to sleep for up to 1 second every time we wanted to write a - * register), we only check the write pending status before we start to issue - * a new write. We bank on the idea that it doesn't matter when the sync - * happens so long as we don't attempt another write before it does. The only - * time userspace would take this penalty is when they try and do multiple - * operations right after another ... but in this case, they need to take the - * sync penalty, so we should be OK. - * - * Also note that the RTC_ISTAT register does not suffer this penalty; its - * writes to clear status registers complete immediately. - */ - -/* It may seem odd that there is no SWCNT code in here (which would be exposed - * via the periodic interrupt event, or PIE). Since the Blackfin RTC peripheral - * runs in units of seconds (N/HZ) but the Linux framework runs in units of HZ - * (2^N HZ), there is no point in keeping code that only provides 1 HZ PIEs. - * The same exact behavior can be accomplished by using the update interrupt - * event (UIE). Maybe down the line the RTC peripheral will suck less in which - * case we can re-introduce PIE support. - */ - -#include <linux/bcd.h> -#include <linux/completion.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/rtc.h> -#include <linux/seq_file.h> -#include <linux/slab.h> - -#include <asm/blackfin.h> - -#define dev_dbg_stamp(dev) dev_dbg(dev, "%s:%i: here i am\n", __func__, __LINE__) - -struct bfin_rtc { - struct rtc_device *rtc_dev; - struct rtc_time rtc_alarm; - u16 rtc_wrote_regs; -}; - -/* Bit values for the ISTAT / ICTL registers */ -#define RTC_ISTAT_WRITE_COMPLETE 0x8000 -#define RTC_ISTAT_WRITE_PENDING 0x4000 -#define RTC_ISTAT_ALARM_DAY 0x0040 -#define RTC_ISTAT_24HR 0x0020 -#define RTC_ISTAT_HOUR 0x0010 -#define RTC_ISTAT_MIN 0x0008 -#define RTC_ISTAT_SEC 0x0004 -#define RTC_ISTAT_ALARM 0x0002 -#define RTC_ISTAT_STOPWATCH 0x0001 - -/* Shift values for RTC_STAT register */ -#define DAY_BITS_OFF 17 -#define HOUR_BITS_OFF 12 -#define MIN_BITS_OFF 6 -#define SEC_BITS_OFF 0 - -/* Some helper functions to convert between the common RTC notion of time - * and the internal Blackfin notion that is encoded in 32bits. - */ -static inline u32 rtc_time_to_bfin(unsigned long now) -{ - u32 sec = (now % 60); - u32 min = (now % (60 * 60)) / 60; - u32 hour = (now % (60 * 60 * 24)) / (60 * 60); - u32 days = (now / (60 * 60 * 24)); - return (sec << SEC_BITS_OFF) + - (min << MIN_BITS_OFF) + - (hour << HOUR_BITS_OFF) + - (days << DAY_BITS_OFF); -} -static inline unsigned long rtc_bfin_to_time(u32 rtc_bfin) -{ - return (((rtc_bfin >> SEC_BITS_OFF) & 0x003F)) + - (((rtc_bfin >> MIN_BITS_OFF) & 0x003F) * 60) + - (((rtc_bfin >> HOUR_BITS_OFF) & 0x001F) * 60 * 60) + - (((rtc_bfin >> DAY_BITS_OFF) & 0x7FFF) * 60 * 60 * 24); -} -static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) -{ - rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); -} - -/** - * bfin_rtc_sync_pending - make sure pending writes have complete - * - * Wait for the previous write to a RTC register to complete. - * Unfortunately, we can't sleep here as that introduces a race condition when - * turning on interrupt events. Consider this: - * - process sets alarm - * - process enables alarm - * - process sleeps while waiting for rtc write to sync - * - interrupt fires while process is sleeping - * - interrupt acks the event by writing to ISTAT - * - interrupt sets the WRITE PENDING bit - * - interrupt handler finishes - * - process wakes up, sees WRITE PENDING bit set, goes to sleep - * - interrupt fires while process is sleeping - * If anyone can point out the obvious solution here, i'm listening :). This - * shouldn't be an issue on an SMP or preempt system as this function should - * only be called with the rtc lock held. - * - * Other options: - * - disable PREN so the sync happens at 32.768kHZ ... but this changes the - * inc rate for all RTC registers from 1HZ to 32.768kHZ ... - * - use the write complete IRQ - */ -/* -static void bfin_rtc_sync_pending_polled(void) -{ - while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) - if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) - break; - bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); -} -*/ -static DECLARE_COMPLETION(bfin_write_complete); -static void bfin_rtc_sync_pending(struct device *dev) -{ - dev_dbg_stamp(dev); - while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) - wait_for_completion_timeout(&bfin_write_complete, HZ * 5); - dev_dbg_stamp(dev); -} - -/** - * bfin_rtc_reset - set RTC to sane/known state - * - * Initialize the RTC. Enable pre-scaler to scale RTC clock - * to 1Hz and clear interrupt/status registers. - */ -static void bfin_rtc_reset(struct device *dev, u16 rtc_ictl) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - dev_dbg_stamp(dev); - bfin_rtc_sync_pending(dev); - bfin_write_RTC_PREN(0x1); - bfin_write_RTC_ICTL(rtc_ictl); - bfin_write_RTC_ALARM(0); - bfin_write_RTC_ISTAT(0xFFFF); - rtc->rtc_wrote_regs = 0; -} - -/** - * bfin_rtc_interrupt - handle interrupt from RTC - * - * Since we handle all RTC events here, we have to make sure the requested - * interrupt is enabled (in RTC_ICTL) as the event status register (RTC_ISTAT) - * always gets updated regardless of the interrupt being enabled. So when one - * even we care about (e.g. stopwatch) goes off, we don't want to turn around - * and say that other events have happened as well (e.g. second). We do not - * have to worry about pending writes to the RTC_ICTL register as interrupts - * only fire if they are enabled in the RTC_ICTL register. - */ -static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) -{ - struct device *dev = dev_id; - struct bfin_rtc *rtc = dev_get_drvdata(dev); - unsigned long events = 0; - bool write_complete = false; - u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits; - - dev_dbg_stamp(dev); - - rtc_istat = bfin_read_RTC_ISTAT(); - rtc_ictl = bfin_read_RTC_ICTL(); - rtc_istat_clear = 0; - - bits = RTC_ISTAT_WRITE_COMPLETE; - if (rtc_istat & bits) { - rtc_istat_clear |= bits; - write_complete = true; - complete(&bfin_write_complete); - } - - bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); - if (rtc_ictl & bits) { - if (rtc_istat & bits) { - rtc_istat_clear |= bits; - events |= RTC_AF | RTC_IRQF; - } - } - - bits = RTC_ISTAT_SEC; - if (rtc_ictl & bits) { - if (rtc_istat & bits) { - rtc_istat_clear |= bits; - events |= RTC_UF | RTC_IRQF; - } - } - - if (events) - rtc_update_irq(rtc->rtc_dev, 1, events); - - if (write_complete || events) { - bfin_write_RTC_ISTAT(rtc_istat_clear); - return IRQ_HANDLED; - } else - return IRQ_NONE; -} - -static void bfin_rtc_int_set(u16 rtc_int) -{ - bfin_write_RTC_ISTAT(rtc_int); - bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); -} -static void bfin_rtc_int_clear(u16 rtc_int) -{ - bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); -} -static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) -{ - /* Blackfin has different bits for whether the alarm is - * more than 24 hours away. - */ - bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); -} - -static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - - dev_dbg_stamp(dev); - if (enabled) - bfin_rtc_int_set_alarm(rtc); - else - bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); - - return 0; -} - -static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - - dev_dbg_stamp(dev); - - if (rtc->rtc_wrote_regs & 0x1) - bfin_rtc_sync_pending(dev); - - rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); - - return 0; -} - -static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - int ret; - unsigned long now; - - dev_dbg_stamp(dev); - - ret = rtc_tm_to_time(tm, &now); - if (ret == 0) { - if (rtc->rtc_wrote_regs & 0x1) - bfin_rtc_sync_pending(dev); - bfin_write_RTC_STAT(rtc_time_to_bfin(now)); - rtc->rtc_wrote_regs = 0x1; - } - - return ret; -} - -static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - dev_dbg_stamp(dev); - alrm->time = rtc->rtc_alarm; - bfin_rtc_sync_pending(dev); - alrm->enabled = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); - return 0; -} - -static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - unsigned long rtc_alarm; - - dev_dbg_stamp(dev); - - if (rtc_tm_to_time(&alrm->time, &rtc_alarm)) - return -EINVAL; - - rtc->rtc_alarm = alrm->time; - - bfin_rtc_sync_pending(dev); - bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); - if (alrm->enabled) - bfin_rtc_int_set_alarm(rtc); - - return 0; -} - -static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) -{ -#define yesno(x) ((x) ? "yes" : "no") - u16 ictl = bfin_read_RTC_ICTL(); - dev_dbg_stamp(dev); - seq_printf(seq, - "alarm_IRQ\t: %s\n" - "wkalarm_IRQ\t: %s\n" - "seconds_IRQ\t: %s\n", - yesno(ictl & RTC_ISTAT_ALARM), - yesno(ictl & RTC_ISTAT_ALARM_DAY), - yesno(ictl & RTC_ISTAT_SEC)); - return 0; -#undef yesno -} - -static const struct rtc_class_ops bfin_rtc_ops = { - .read_time = bfin_rtc_read_time, - .set_time = bfin_rtc_set_time, - .read_alarm = bfin_rtc_read_alarm, - .set_alarm = bfin_rtc_set_alarm, - .proc = bfin_rtc_proc, - .alarm_irq_enable = bfin_rtc_alarm_irq_enable, -}; - -static int bfin_rtc_probe(struct platform_device *pdev) -{ - struct bfin_rtc *rtc; - struct device *dev = &pdev->dev; - int ret; - unsigned long timeout = jiffies + HZ; - - dev_dbg_stamp(dev); - - /* Allocate memory for our RTC struct */ - rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); - if (unlikely(!rtc)) - return -ENOMEM; - platform_set_drvdata(pdev, rtc); - device_init_wakeup(dev, 1); - - /* Register our RTC with the RTC framework */ - rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops, - THIS_MODULE); - if (IS_ERR(rtc->rtc_dev)) - return PTR_ERR(rtc->rtc_dev); - - /* Grab the IRQ and init the hardware */ - ret = devm_request_irq(dev, IRQ_RTC, bfin_rtc_interrupt, 0, - pdev->name, dev); - if (unlikely(ret)) - dev_err(&pdev->dev, - "unable to request IRQ; alarm won't work, " - "and writes will be delayed\n"); - - /* sometimes the bootloader touched things, but the write complete was not - * enabled, so let's just do a quick timeout here since the IRQ will not fire ... - */ - while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) - if (time_after(jiffies, timeout)) - break; - bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); - bfin_write_RTC_SWCNT(0); - - return 0; -} - -static int bfin_rtc_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - - bfin_rtc_reset(dev, 0); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int bfin_rtc_suspend(struct device *dev) -{ - dev_dbg_stamp(dev); - - if (device_may_wakeup(dev)) { - enable_irq_wake(IRQ_RTC); - bfin_rtc_sync_pending(dev); - } else - bfin_rtc_int_clear(0); - - return 0; -} - -static int bfin_rtc_resume(struct device *dev) -{ - dev_dbg_stamp(dev); - - if (device_may_wakeup(dev)) - disable_irq_wake(IRQ_RTC); - - /* - * Since only some of the RTC bits are maintained externally in the - * Vbat domain, we need to wait for the RTC MMRs to be synced into - * the core after waking up. This happens every RTC 1HZ. Once that - * has happened, we can go ahead and re-enable the important write - * complete interrupt event. - */ - while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) - continue; - bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(bfin_rtc_pm_ops, bfin_rtc_suspend, bfin_rtc_resume); - -static struct platform_driver bfin_rtc_driver = { - .driver = { - .name = "rtc-bfin", - .pm = &bfin_rtc_pm_ops, - }, - .probe = bfin_rtc_probe, - .remove = bfin_rtc_remove, -}; - -module_platform_driver(bfin_rtc_driver); - -MODULE_DESCRIPTION("Blackfin On-Chip Real Time Clock Driver"); -MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:rtc-bfin"); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 9dca53df3584..f7c0f72abb56 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -711,7 +711,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) address_space = 64; #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \ || defined(__sparc__) || defined(__mips__) \ - || defined(__powerpc__) || defined(CONFIG_MN10300) + || defined(__powerpc__) address_space = 128; #else #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. diff --git a/drivers/rtc/rtc-tile.c b/drivers/rtc/rtc-tile.c deleted file mode 100644 index 0b60867d8390..000000000000 --- a/drivers/rtc/rtc-tile.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2011 Tilera Corporation. All Rights Reserved. - * - * 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. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - * - * Tilera-specific RTC driver. - */ - -#include <linux/module.h> -#include <linux/device.h> -#include <linux/rtc.h> -#include <linux/platform_device.h> - -/* Platform device pointer. */ -static struct platform_device *tile_rtc_platform_device; - -/* - * RTC read routine. Gets time info from RTC chip via hypervisor syscall. - */ -static int read_rtc_time(struct device *dev, struct rtc_time *tm) -{ - HV_RTCTime hvtm = hv_get_rtc(); - - tm->tm_sec = hvtm.tm_sec; - tm->tm_min = hvtm.tm_min; - tm->tm_hour = hvtm.tm_hour; - tm->tm_mday = hvtm.tm_mday; - tm->tm_mon = hvtm.tm_mon; - tm->tm_year = hvtm.tm_year; - tm->tm_wday = 0; - tm->tm_yday = 0; - tm->tm_isdst = 0; - - if (rtc_valid_tm(tm) < 0) - dev_warn(dev, "Read invalid date/time from RTC\n"); - - return 0; -} - -/* - * RTC write routine. Sends time info to hypervisor via syscall, to be - * written to RTC chip. - */ -static int set_rtc_time(struct device *dev, struct rtc_time *tm) -{ - HV_RTCTime hvtm; - - hvtm.tm_sec = tm->tm_sec; - hvtm.tm_min = tm->tm_min; - hvtm.tm_hour = tm->tm_hour; - hvtm.tm_mday = tm->tm_mday; - hvtm.tm_mon = tm->tm_mon; - hvtm.tm_year = tm->tm_year; - - hv_set_rtc(hvtm); - - return 0; -} - -/* - * RTC read/write ops. - */ -static const struct rtc_class_ops tile_rtc_ops = { - .read_time = read_rtc_time, - .set_time = set_rtc_time, -}; - -/* - * Device probe routine. - */ -static int tile_rtc_probe(struct platform_device *dev) -{ - struct rtc_device *rtc; - - rtc = devm_rtc_device_register(&dev->dev, "tile", - &tile_rtc_ops, THIS_MODULE); - - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - - platform_set_drvdata(dev, rtc); - - return 0; -} - -static struct platform_driver tile_rtc_platform_driver = { - .driver = { - .name = "rtc-tile", - }, - .probe = tile_rtc_probe, -}; - -/* - * Driver init routine. - */ -static int __init tile_rtc_driver_init(void) -{ - int err; - - err = platform_driver_register(&tile_rtc_platform_driver); - if (err) - return err; - - tile_rtc_platform_device = platform_device_alloc("rtc-tile", 0); - if (tile_rtc_platform_device == NULL) { - err = -ENOMEM; - goto exit_driver_unregister; - } - - err = platform_device_add(tile_rtc_platform_device); - if (err) - goto exit_device_put; - - return 0; - -exit_device_put: - platform_device_put(tile_rtc_platform_device); - -exit_driver_unregister: - platform_driver_unregister(&tile_rtc_platform_driver); - return err; -} - -/* - * Driver cleanup routine. - */ -static void __exit tile_rtc_driver_exit(void) -{ - platform_device_unregister(tile_rtc_platform_device); - platform_driver_unregister(&tile_rtc_platform_driver); -} - -module_init(tile_rtc_driver_init); -module_exit(tile_rtc_driver_exit); - -MODULE_DESCRIPTION("Tilera-specific Real Time Clock Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:rtc-tile"); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 603783976b81..2d4146ce2f1b 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -72,10 +72,10 @@ config SPI_ARMADA_3700 config SPI_ATMEL tristate "Atmel SPI Controller" depends on HAS_DMA - depends on (ARCH_AT91 || AVR32 || COMPILE_TEST) + depends on ARCH_AT91 || COMPILE_TEST help This selects a driver for the Atmel SPI Controller, present on - many AT32 (AVR32) and AT91 (ARM) chips. + many AT91 ARM chips. config SPI_AU1550 tristate "Au1550/Au1200/Au1300 SPI Controller" @@ -115,25 +115,6 @@ config SPI_BCM2835AUX "universal SPI master", and the regular SPI controller. This driver is for the universal/auxiliary SPI controller. -config SPI_BFIN5XX - tristate "SPI controller driver for ADI Blackfin5xx" - depends on BLACKFIN && !BF60x - help - This is the SPI controller master driver for Blackfin 5xx processor. - -config SPI_ADI_V3 - tristate "SPI controller v3 for ADI" - depends on BF60x - help - This is the SPI controller v3 master driver - found on Blackfin 60x processor. - -config SPI_BFIN_SPORT - tristate "SPI bus via Blackfin SPORT" - depends on BLACKFIN - help - Enable support for a SPI bus via the Blackfin SPORT peripheral. - config SPI_BCM53XX tristate "Broadcom BCM53xx SPI controller" depends on ARCH_BCM_5301X diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 34c5f2832ddf..b935f10eb961 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -24,9 +24,6 @@ obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o obj-$(CONFIG_SPI_BCM_QSPI) += spi-iproc-qspi.o spi-brcmstb-qspi.o spi-bcm-qspi.o -obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o -obj-$(CONFIG_SPI_ADI_V3) += spi-adi-v3.o -obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o diff --git a/drivers/spi/spi-adi-v3.c b/drivers/spi/spi-adi-v3.c deleted file mode 100644 index a16b25dcd1e6..000000000000 --- a/drivers/spi/spi-adi-v3.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * Analog Devices SPI3 controller driver - * - * Copyright (c) 2014 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/errno.h> -#include <linux/gpio.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/spi/spi.h> -#include <linux/spi/adi_spi3.h> -#include <linux/types.h> - -#include <asm/dma.h> -#include <asm/portmux.h> - -enum adi_spi_state { - START_STATE, - RUNNING_STATE, - DONE_STATE, - ERROR_STATE -}; - -struct adi_spi_master; - -struct adi_spi_transfer_ops { - void (*write) (struct adi_spi_master *); - void (*read) (struct adi_spi_master *); - void (*duplex) (struct adi_spi_master *); -}; - -/* runtime info for spi master */ -struct adi_spi_master { - /* SPI framework hookup */ - struct spi_master *master; - - /* Regs base of SPI controller */ - struct adi_spi_regs __iomem *regs; - - /* Pin request list */ - u16 *pin_req; - - /* Message Transfer pump */ - struct tasklet_struct pump_transfers; - - /* Current message transfer state info */ - struct spi_message *cur_msg; - struct spi_transfer *cur_transfer; - struct adi_spi_device *cur_chip; - unsigned transfer_len; - - /* transfer buffer */ - void *tx; - void *tx_end; - void *rx; - void *rx_end; - - /* dma info */ - unsigned int tx_dma; - unsigned int rx_dma; - dma_addr_t tx_dma_addr; - dma_addr_t rx_dma_addr; - unsigned long dummy_buffer; /* used in unidirectional transfer */ - unsigned long tx_dma_size; - unsigned long rx_dma_size; - int tx_num; - int rx_num; - - /* store register value for suspend/resume */ - u32 control; - u32 ssel; - - unsigned long sclk; - enum adi_spi_state state; - - const struct adi_spi_transfer_ops *ops; -}; - -struct adi_spi_device { - u32 control; - u32 clock; - u32 ssel; - - u8 cs; - u16 cs_chg_udelay; /* Some devices require > 255usec delay */ - u32 cs_gpio; - u32 tx_dummy_val; /* tx value for rx only transfer */ - bool enable_dma; - const struct adi_spi_transfer_ops *ops; -}; - -static void adi_spi_enable(struct adi_spi_master *drv_data) -{ - u32 ctl; - - ctl = ioread32(&drv_data->regs->control); - ctl |= SPI_CTL_EN; - iowrite32(ctl, &drv_data->regs->control); -} - -static void adi_spi_disable(struct adi_spi_master *drv_data) -{ - u32 ctl; - - ctl = ioread32(&drv_data->regs->control); - ctl &= ~SPI_CTL_EN; - iowrite32(ctl, &drv_data->regs->control); -} - -/* Caculate the SPI_CLOCK register value based on input HZ */ -static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz) -{ - u32 spi_clock = sclk / speed_hz; - - if (spi_clock) - spi_clock--; - return spi_clock; -} - -static int adi_spi_flush(struct adi_spi_master *drv_data) -{ - unsigned long limit = loops_per_jiffy << 1; - - /* wait for stop and clear stat */ - while (!(ioread32(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit) - cpu_relax(); - - iowrite32(0xFFFFFFFF, &drv_data->regs->status); - - return limit; -} - -/* Chip select operation functions for cs_change flag */ -static void adi_spi_cs_active(struct adi_spi_master *drv_data, struct adi_spi_device *chip) -{ - if (likely(chip->cs < MAX_CTRL_CS)) { - u32 reg; - reg = ioread32(&drv_data->regs->ssel); - reg &= ~chip->ssel; - iowrite32(reg, &drv_data->regs->ssel); - } else { - gpio_set_value(chip->cs_gpio, 0); - } -} - -static void adi_spi_cs_deactive(struct adi_spi_master *drv_data, - struct adi_spi_device *chip) -{ - if (likely(chip->cs < MAX_CTRL_CS)) { - u32 reg; - reg = ioread32(&drv_data->regs->ssel); - reg |= chip->ssel; - iowrite32(reg, &drv_data->regs->ssel); - } else { - gpio_set_value(chip->cs_gpio, 1); - } - - /* Move delay here for consistency */ - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); -} - -/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ -static inline void adi_spi_cs_enable(struct adi_spi_master *drv_data, - struct adi_spi_device *chip) -{ - if (chip->cs < MAX_CTRL_CS) { - u32 reg; - reg = ioread32(&drv_data->regs->ssel); - reg |= chip->ssel >> 8; - iowrite32(reg, &drv_data->regs->ssel); - } -} - -static inline void adi_spi_cs_disable(struct adi_spi_master *drv_data, - struct adi_spi_device *chip) -{ - if (chip->cs < MAX_CTRL_CS) { - u32 reg; - reg = ioread32(&drv_data->regs->ssel); - reg &= ~(chip->ssel >> 8); - iowrite32(reg, &drv_data->regs->ssel); - } -} - -/* stop controller and re-config current chip*/ -static void adi_spi_restore_state(struct adi_spi_master *drv_data) -{ - struct adi_spi_device *chip = drv_data->cur_chip; - - /* Clear status and disable clock */ - iowrite32(0xFFFFFFFF, &drv_data->regs->status); - iowrite32(0x0, &drv_data->regs->rx_control); - iowrite32(0x0, &drv_data->regs->tx_control); - adi_spi_disable(drv_data); - - /* Load the registers */ - iowrite32(chip->control, &drv_data->regs->control); - iowrite32(chip->clock, &drv_data->regs->clock); - - adi_spi_enable(drv_data); - drv_data->tx_num = drv_data->rx_num = 0; - /* we always choose tx transfer initiate */ - iowrite32(SPI_RXCTL_REN, &drv_data->regs->rx_control); - iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &drv_data->regs->tx_control); - adi_spi_cs_active(drv_data, chip); -} - -/* discard invalid rx data and empty rfifo */ -static inline void dummy_read(struct adi_spi_master *drv_data) -{ - while (!(ioread32(&drv_data->regs->status) & SPI_STAT_RFE)) - ioread32(&drv_data->regs->rfifo); -} - -static void adi_spi_u8_write(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->tx < drv_data->tx_end) { - iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo); - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - ioread32(&drv_data->regs->rfifo); - } -} - -static void adi_spi_u8_read(struct adi_spi_master *drv_data) -{ - u32 tx_val = drv_data->cur_chip->tx_dummy_val; - - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(tx_val, &drv_data->regs->tfifo); - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo); - } -} - -static void adi_spi_u8_duplex(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(*(u8 *)(drv_data->tx++), &drv_data->regs->tfifo); - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u8 *)(drv_data->rx++) = ioread32(&drv_data->regs->rfifo); - } -} - -static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u8 = { - .write = adi_spi_u8_write, - .read = adi_spi_u8_read, - .duplex = adi_spi_u8_duplex, -}; - -static void adi_spi_u16_write(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->tx < drv_data->tx_end) { - iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo); - drv_data->tx += 2; - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - ioread32(&drv_data->regs->rfifo); - } -} - -static void adi_spi_u16_read(struct adi_spi_master *drv_data) -{ - u32 tx_val = drv_data->cur_chip->tx_dummy_val; - - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(tx_val, &drv_data->regs->tfifo); - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo); - drv_data->rx += 2; - } -} - -static void adi_spi_u16_duplex(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(*(u16 *)drv_data->tx, &drv_data->regs->tfifo); - drv_data->tx += 2; - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u16 *)drv_data->rx = ioread32(&drv_data->regs->rfifo); - drv_data->rx += 2; - } -} - -static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u16 = { - .write = adi_spi_u16_write, - .read = adi_spi_u16_read, - .duplex = adi_spi_u16_duplex, -}; - -static void adi_spi_u32_write(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->tx < drv_data->tx_end) { - iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo); - drv_data->tx += 4; - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - ioread32(&drv_data->regs->rfifo); - } -} - -static void adi_spi_u32_read(struct adi_spi_master *drv_data) -{ - u32 tx_val = drv_data->cur_chip->tx_dummy_val; - - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(tx_val, &drv_data->regs->tfifo); - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo); - drv_data->rx += 4; - } -} - -static void adi_spi_u32_duplex(struct adi_spi_master *drv_data) -{ - dummy_read(drv_data); - while (drv_data->rx < drv_data->rx_end) { - iowrite32(*(u32 *)drv_data->tx, &drv_data->regs->tfifo); - drv_data->tx += 4; - while (ioread32(&drv_data->regs->status) & SPI_STAT_RFE) - cpu_relax(); - *(u32 *)drv_data->rx = ioread32(&drv_data->regs->rfifo); - drv_data->rx += 4; - } -} - -static const struct adi_spi_transfer_ops adi_spi_transfer_ops_u32 = { - .write = adi_spi_u32_write, - .read = adi_spi_u32_read, - .duplex = adi_spi_u32_duplex, -}; - - -/* test if there is more transfer to be done */ -static void adi_spi_next_transfer(struct adi_spi_master *drv) -{ - struct spi_message *msg = drv->cur_msg; - struct spi_transfer *t = drv->cur_transfer; - - /* Move to next transfer */ - if (t->transfer_list.next != &msg->transfers) { - drv->cur_transfer = list_entry(t->transfer_list.next, - struct spi_transfer, transfer_list); - drv->state = RUNNING_STATE; - } else { - drv->state = DONE_STATE; - drv->cur_transfer = NULL; - } -} - -static void adi_spi_giveback(struct adi_spi_master *drv_data) -{ - struct adi_spi_device *chip = drv_data->cur_chip; - - adi_spi_cs_deactive(drv_data, chip); - spi_finalize_current_message(drv_data->master); -} - -static int adi_spi_setup_transfer(struct adi_spi_master *drv) -{ - struct spi_transfer *t = drv->cur_transfer; - u32 cr, cr_width; - - if (t->tx_buf) { - drv->tx = (void *)t->tx_buf; - drv->tx_end = drv->tx + t->len; - } else { - drv->tx = NULL; - } - - if (t->rx_buf) { - drv->rx = t->rx_buf; - drv->rx_end = drv->rx + t->len; - } else { - drv->rx = NULL; - } - - drv->transfer_len = t->len; - - /* bits per word setup */ - switch (t->bits_per_word) { - case 8: - cr_width = SPI_CTL_SIZE08; - drv->ops = &adi_spi_transfer_ops_u8; - break; - case 16: - cr_width = SPI_CTL_SIZE16; - drv->ops = &adi_spi_transfer_ops_u16; - break; - case 32: - cr_width = SPI_CTL_SIZE32; - drv->ops = &adi_spi_transfer_ops_u32; - break; - default: - return -EINVAL; - } - cr = ioread32(&drv->regs->control) & ~SPI_CTL_SIZE; - cr |= cr_width; - iowrite32(cr, &drv->regs->control); - - /* speed setup */ - iowrite32(hz_to_spi_clock(drv->sclk, t->speed_hz), &drv->regs->clock); - return 0; -} - -static int adi_spi_dma_xfer(struct adi_spi_master *drv_data) -{ - struct spi_transfer *t = drv_data->cur_transfer; - struct spi_message *msg = drv_data->cur_msg; - struct adi_spi_device *chip = drv_data->cur_chip; - u32 dma_config; - unsigned long word_count, word_size; - void *tx_buf, *rx_buf; - - switch (t->bits_per_word) { - case 8: - dma_config = WDSIZE_8 | PSIZE_8; - word_count = drv_data->transfer_len; - word_size = 1; - break; - case 16: - dma_config = WDSIZE_16 | PSIZE_16; - word_count = drv_data->transfer_len / 2; - word_size = 2; - break; - default: - dma_config = WDSIZE_32 | PSIZE_32; - word_count = drv_data->transfer_len / 4; - word_size = 4; - break; - } - - if (!drv_data->rx) { - tx_buf = drv_data->tx; - rx_buf = &drv_data->dummy_buffer; - drv_data->tx_dma_size = drv_data->transfer_len; - drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer); - set_dma_x_modify(drv_data->tx_dma, word_size); - set_dma_x_modify(drv_data->rx_dma, 0); - } else if (!drv_data->tx) { - drv_data->dummy_buffer = chip->tx_dummy_val; - tx_buf = &drv_data->dummy_buffer; - rx_buf = drv_data->rx; - drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer); - drv_data->rx_dma_size = drv_data->transfer_len; - set_dma_x_modify(drv_data->tx_dma, 0); - set_dma_x_modify(drv_data->rx_dma, word_size); - } else { - tx_buf = drv_data->tx; - rx_buf = drv_data->rx; - drv_data->tx_dma_size = drv_data->rx_dma_size - = drv_data->transfer_len; - set_dma_x_modify(drv_data->tx_dma, word_size); - set_dma_x_modify(drv_data->rx_dma, word_size); - } - - drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev, - (void *)tx_buf, - drv_data->tx_dma_size, - DMA_TO_DEVICE); - if (dma_mapping_error(&msg->spi->dev, - drv_data->tx_dma_addr)) - return -ENOMEM; - - drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev, - (void *)rx_buf, - drv_data->rx_dma_size, - DMA_FROM_DEVICE); - if (dma_mapping_error(&msg->spi->dev, - drv_data->rx_dma_addr)) { - dma_unmap_single(&msg->spi->dev, - drv_data->tx_dma_addr, - drv_data->tx_dma_size, - DMA_TO_DEVICE); - return -ENOMEM; - } - - dummy_read(drv_data); - set_dma_x_count(drv_data->tx_dma, word_count); - set_dma_x_count(drv_data->rx_dma, word_count); - set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr); - set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr); - dma_config |= DMAFLOW_STOP | RESTART | DI_EN; - set_dma_config(drv_data->tx_dma, dma_config); - set_dma_config(drv_data->rx_dma, dma_config | WNR); - enable_dma(drv_data->tx_dma); - enable_dma(drv_data->rx_dma); - - iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RDR_NE, - &drv_data->regs->rx_control); - iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF, - &drv_data->regs->tx_control); - - return 0; -} - -static int adi_spi_pio_xfer(struct adi_spi_master *drv_data) -{ - struct spi_message *msg = drv_data->cur_msg; - - if (!drv_data->rx) { - /* write only half duplex */ - drv_data->ops->write(drv_data); - if (drv_data->tx != drv_data->tx_end) - return -EIO; - } else if (!drv_data->tx) { - /* read only half duplex */ - drv_data->ops->read(drv_data); - if (drv_data->rx != drv_data->rx_end) - return -EIO; - } else { - /* full duplex mode */ - drv_data->ops->duplex(drv_data); - if (drv_data->tx != drv_data->tx_end) - return -EIO; - } - - if (!adi_spi_flush(drv_data)) - return -EIO; - msg->actual_length += drv_data->transfer_len; - tasklet_schedule(&drv_data->pump_transfers); - return 0; -} - -static void adi_spi_pump_transfers(unsigned long data) -{ - struct adi_spi_master *drv_data = (struct adi_spi_master *)data; - struct spi_message *msg = NULL; - struct spi_transfer *t = NULL; - struct adi_spi_device *chip = NULL; - int ret; - - /* Get current state information */ - msg = drv_data->cur_msg; - t = drv_data->cur_transfer; - chip = drv_data->cur_chip; - - /* Handle for abort */ - if (drv_data->state == ERROR_STATE) { - msg->status = -EIO; - adi_spi_giveback(drv_data); - return; - } - - if (drv_data->state == RUNNING_STATE) { - if (t->delay_usecs) - udelay(t->delay_usecs); - if (t->cs_change) - adi_spi_cs_deactive(drv_data, chip); - adi_spi_next_transfer(drv_data); - t = drv_data->cur_transfer; - } - /* Handle end of message */ - if (drv_data->state == DONE_STATE) { - msg->status = 0; - adi_spi_giveback(drv_data); - return; - } - - if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) { - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - return; - } - - ret = adi_spi_setup_transfer(drv_data); - if (ret) { - msg->status = ret; - adi_spi_giveback(drv_data); - } - - iowrite32(0xFFFFFFFF, &drv_data->regs->status); - adi_spi_cs_active(drv_data, chip); - drv_data->state = RUNNING_STATE; - - if (chip->enable_dma) - ret = adi_spi_dma_xfer(drv_data); - else - ret = adi_spi_pio_xfer(drv_data); - if (ret) { - msg->status = ret; - adi_spi_giveback(drv_data); - } -} - -static int adi_spi_transfer_one_message(struct spi_master *master, - struct spi_message *m) -{ - struct adi_spi_master *drv_data = spi_master_get_devdata(master); - - drv_data->cur_msg = m; - drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); - adi_spi_restore_state(drv_data); - - drv_data->state = START_STATE; - drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, - struct spi_transfer, transfer_list); - - tasklet_schedule(&drv_data->pump_transfers); - return 0; -} - -#define MAX_SPI_SSEL 7 - -static const u16 ssel[][MAX_SPI_SSEL] = { - {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, - P_SPI0_SSEL4, P_SPI0_SSEL5, - P_SPI0_SSEL6, P_SPI0_SSEL7}, - - {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, - P_SPI1_SSEL4, P_SPI1_SSEL5, - P_SPI1_SSEL6, P_SPI1_SSEL7}, - - {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, - P_SPI2_SSEL4, P_SPI2_SSEL5, - P_SPI2_SSEL6, P_SPI2_SSEL7}, -}; - -static int adi_spi_setup(struct spi_device *spi) -{ - struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master); - struct adi_spi_device *chip = spi_get_ctldata(spi); - u32 ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; - int ret = -EINVAL; - - if (!chip) { - struct adi_spi3_chip *chip_info = spi->controller_data; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - if (chip_info) { - if (chip_info->control & ~ctl_reg) { - dev_err(&spi->dev, - "do not set bits that the SPI framework manages\n"); - goto error; - } - chip->control = chip_info->control; - chip->cs_chg_udelay = chip_info->cs_chg_udelay; - chip->tx_dummy_val = chip_info->tx_dummy_val; - chip->enable_dma = chip_info->enable_dma; - } - chip->cs = spi->chip_select; - - if (chip->cs < MAX_CTRL_CS) { - chip->ssel = (1 << chip->cs) << 8; - ret = peripheral_request(ssel[spi->master->bus_num] - [chip->cs-1], dev_name(&spi->dev)); - if (ret) { - dev_err(&spi->dev, "peripheral_request() error\n"); - goto error; - } - } else { - chip->cs_gpio = chip->cs - MAX_CTRL_CS; - ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH, - dev_name(&spi->dev)); - if (ret) { - dev_err(&spi->dev, "gpio_request_one() error\n"); - goto error; - } - } - spi_set_ctldata(spi, chip); - } - - /* force a default base state */ - chip->control &= ctl_reg; - - if (spi->mode & SPI_CPOL) - chip->control |= SPI_CTL_CPOL; - if (spi->mode & SPI_CPHA) - chip->control |= SPI_CTL_CPHA; - if (spi->mode & SPI_LSB_FIRST) - chip->control |= SPI_CTL_LSBF; - chip->control |= SPI_CTL_MSTR; - /* we choose software to controll cs */ - chip->control &= ~SPI_CTL_ASSEL; - - chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); - - adi_spi_cs_enable(drv_data, chip); - adi_spi_cs_deactive(drv_data, chip); - - return 0; -error: - if (chip) { - kfree(chip); - spi_set_ctldata(spi, NULL); - } - - return ret; -} - -static void adi_spi_cleanup(struct spi_device *spi) -{ - struct adi_spi_device *chip = spi_get_ctldata(spi); - struct adi_spi_master *drv_data = spi_master_get_devdata(spi->master); - - if (!chip) - return; - - if (chip->cs < MAX_CTRL_CS) { - peripheral_free(ssel[spi->master->bus_num] - [chip->cs-1]); - adi_spi_cs_disable(drv_data, chip); - } else { - gpio_free(chip->cs_gpio); - } - - kfree(chip); - spi_set_ctldata(spi, NULL); -} - -static irqreturn_t adi_spi_tx_dma_isr(int irq, void *dev_id) -{ - struct adi_spi_master *drv_data = dev_id; - u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); - u32 tx_ctl; - - clear_dma_irqstat(drv_data->tx_dma); - if (dma_stat & DMA_DONE) { - drv_data->tx_num++; - } else { - dev_err(&drv_data->master->dev, - "spi tx dma error: %d\n", dma_stat); - if (drv_data->tx) - drv_data->state = ERROR_STATE; - } - tx_ctl = ioread32(&drv_data->regs->tx_control); - tx_ctl &= ~SPI_TXCTL_TDR_NF; - iowrite32(tx_ctl, &drv_data->regs->tx_control); - return IRQ_HANDLED; -} - -static irqreturn_t adi_spi_rx_dma_isr(int irq, void *dev_id) -{ - struct adi_spi_master *drv_data = dev_id; - struct spi_message *msg = drv_data->cur_msg; - u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); - - clear_dma_irqstat(drv_data->rx_dma); - if (dma_stat & DMA_DONE) { - drv_data->rx_num++; - /* we may fail on tx dma */ - if (drv_data->state != ERROR_STATE) - msg->actual_length += drv_data->transfer_len; - } else { - drv_data->state = ERROR_STATE; - dev_err(&drv_data->master->dev, - "spi rx dma error: %d\n", dma_stat); - } - iowrite32(0, &drv_data->regs->tx_control); - iowrite32(0, &drv_data->regs->rx_control); - if (drv_data->rx_num != drv_data->tx_num) - dev_dbg(&drv_data->master->dev, - "dma interrupt missing: tx=%d,rx=%d\n", - drv_data->tx_num, drv_data->rx_num); - tasklet_schedule(&drv_data->pump_transfers); - return IRQ_HANDLED; -} - -static int adi_spi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct adi_spi3_master *info = dev_get_platdata(dev); - struct spi_master *master; - struct adi_spi_master *drv_data; - struct resource *mem, *res; - unsigned int tx_dma, rx_dma; - struct clk *sclk; - int ret; - - if (!info) { - dev_err(dev, "platform data missing!\n"); - return -ENODEV; - } - - sclk = devm_clk_get(dev, "spi"); - if (IS_ERR(sclk)) { - dev_err(dev, "can not get spi clock\n"); - return PTR_ERR(sclk); - } - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(dev, "can not get tx dma resource\n"); - return -ENXIO; - } - tx_dma = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(dev, "can not get rx dma resource\n"); - return -ENXIO; - } - rx_dma = res->start; - - /* allocate master with space for drv_data */ - master = spi_alloc_master(dev, sizeof(*drv_data)); - if (!master) { - dev_err(dev, "can not alloc spi_master\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, master); - - /* the mode bits supported by this driver */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - - master->bus_num = pdev->id; - master->num_chipselect = info->num_chipselect; - master->cleanup = adi_spi_cleanup; - master->setup = adi_spi_setup; - master->transfer_one_message = adi_spi_transfer_one_message; - master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | - SPI_BPW_MASK(8); - - drv_data = spi_master_get_devdata(master); - drv_data->master = master; - drv_data->tx_dma = tx_dma; - drv_data->rx_dma = rx_dma; - drv_data->pin_req = info->pin_req; - drv_data->sclk = clk_get_rate(sclk); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drv_data->regs = devm_ioremap_resource(dev, mem); - if (IS_ERR(drv_data->regs)) { - ret = PTR_ERR(drv_data->regs); - goto err_put_master; - } - - /* request tx and rx dma */ - ret = request_dma(tx_dma, "SPI_TX_DMA"); - if (ret) { - dev_err(dev, "can not request SPI TX DMA channel\n"); - goto err_put_master; - } - set_dma_callback(tx_dma, adi_spi_tx_dma_isr, drv_data); - - ret = request_dma(rx_dma, "SPI_RX_DMA"); - if (ret) { - dev_err(dev, "can not request SPI RX DMA channel\n"); - goto err_free_tx_dma; - } - set_dma_callback(drv_data->rx_dma, adi_spi_rx_dma_isr, drv_data); - - /* request CLK, MOSI and MISO */ - ret = peripheral_request_list(drv_data->pin_req, "adi-spi3"); - if (ret < 0) { - dev_err(dev, "can not request spi pins\n"); - goto err_free_rx_dma; - } - - iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control); - iowrite32(0x0000FE00, &drv_data->regs->ssel); - iowrite32(0x0, &drv_data->regs->delay); - - tasklet_init(&drv_data->pump_transfers, - adi_spi_pump_transfers, (unsigned long)drv_data); - /* register with the SPI framework */ - ret = devm_spi_register_master(dev, master); - if (ret) { - dev_err(dev, "can not register spi master\n"); - goto err_free_peripheral; - } - - return ret; - -err_free_peripheral: - peripheral_free_list(drv_data->pin_req); -err_free_rx_dma: - free_dma(rx_dma); -err_free_tx_dma: - free_dma(tx_dma); -err_put_master: - spi_master_put(master); - - return ret; -} - -static int adi_spi_remove(struct platform_device *pdev) -{ - struct spi_master *master = platform_get_drvdata(pdev); - struct adi_spi_master *drv_data = spi_master_get_devdata(master); - - adi_spi_disable(drv_data); - peripheral_free_list(drv_data->pin_req); - free_dma(drv_data->rx_dma); - free_dma(drv_data->tx_dma); - return 0; -} - -#ifdef CONFIG_PM -static int adi_spi_suspend(struct device *dev) -{ - struct spi_master *master = dev_get_drvdata(dev); - struct adi_spi_master *drv_data = spi_master_get_devdata(master); - - spi_master_suspend(master); - - drv_data->control = ioread32(&drv_data->regs->control); - drv_data->ssel = ioread32(&drv_data->regs->ssel); - - iowrite32(SPI_CTL_MSTR | SPI_CTL_CPHA, &drv_data->regs->control); - iowrite32(0x0000FE00, &drv_data->regs->ssel); - dma_disable_irq(drv_data->rx_dma); - dma_disable_irq(drv_data->tx_dma); - - return 0; -} - -static int adi_spi_resume(struct device *dev) -{ - struct spi_master *master = dev_get_drvdata(dev); - struct adi_spi_master *drv_data = spi_master_get_devdata(master); - int ret = 0; - - /* bootrom may modify spi and dma status when resume in spi boot mode */ - disable_dma(drv_data->rx_dma); - - dma_enable_irq(drv_data->rx_dma); - dma_enable_irq(drv_data->tx_dma); - iowrite32(drv_data->control, &drv_data->regs->control); - iowrite32(drv_data->ssel, &drv_data->regs->ssel); - - ret = spi_master_resume(master); - if (ret) { - free_dma(drv_data->rx_dma); - free_dma(drv_data->tx_dma); - } - - return ret; -} -#endif -static const struct dev_pm_ops adi_spi_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(adi_spi_suspend, adi_spi_resume) -}; - -MODULE_ALIAS("platform:adi-spi3"); -static struct platform_driver adi_spi_driver = { - .driver = { - .name = "adi-spi3", - .pm = &adi_spi_pm_ops, - }, - .remove = adi_spi_remove, -}; - -module_platform_driver_probe(adi_spi_driver, adi_spi_probe); - -MODULE_DESCRIPTION("Analog Devices SPI3 controller driver"); -MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c deleted file mode 100644 index 01d0ba9c5942..000000000000 --- a/drivers/spi/spi-bfin-sport.c +++ /dev/null @@ -1,919 +0,0 @@ -/* - * SPI bus via the Blackfin SPORT peripheral - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Copyright 2009-2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/gpio.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/irq.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/spi/spi.h> -#include <linux/workqueue.h> - -#include <asm/portmux.h> -#include <asm/bfin5xx_spi.h> -#include <asm/blackfin.h> -#include <asm/bfin_sport.h> -#include <asm/cacheflush.h> - -#define DRV_NAME "bfin-sport-spi" -#define DRV_DESC "SPI bus via the Blackfin SPORT" - -MODULE_AUTHOR("Cliff Cai"); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:bfin-sport-spi"); - -enum bfin_sport_spi_state { - START_STATE, - RUNNING_STATE, - DONE_STATE, - ERROR_STATE, -}; - -struct bfin_sport_spi_master_data; - -struct bfin_sport_transfer_ops { - void (*write) (struct bfin_sport_spi_master_data *); - void (*read) (struct bfin_sport_spi_master_data *); - void (*duplex) (struct bfin_sport_spi_master_data *); -}; - -struct bfin_sport_spi_master_data { - /* Driver model hookup */ - struct device *dev; - - /* SPI framework hookup */ - struct spi_master *master; - - /* Regs base of SPI controller */ - struct sport_register __iomem *regs; - int err_irq; - - /* Pin request list */ - u16 *pin_req; - - struct work_struct pump_messages; - spinlock_t lock; - struct list_head queue; - int busy; - bool run; - - /* Message Transfer pump */ - struct tasklet_struct pump_transfers; - - /* Current message transfer state info */ - enum bfin_sport_spi_state state; - struct spi_message *cur_msg; - struct spi_transfer *cur_transfer; - struct bfin_sport_spi_slave_data *cur_chip; - union { - void *tx; - u8 *tx8; - u16 *tx16; - }; - void *tx_end; - union { - void *rx; - u8 *rx8; - u16 *rx16; - }; - void *rx_end; - - int cs_change; - struct bfin_sport_transfer_ops *ops; -}; - -struct bfin_sport_spi_slave_data { - u16 ctl_reg; - u16 baud; - u16 cs_chg_udelay; /* Some devices require > 255usec delay */ - u32 cs_gpio; - u16 idle_tx_val; - struct bfin_sport_transfer_ops *ops; -}; - -static void -bfin_sport_spi_enable(struct bfin_sport_spi_master_data *drv_data) -{ - bfin_write_or(&drv_data->regs->tcr1, TSPEN); - bfin_write_or(&drv_data->regs->rcr1, TSPEN); - SSYNC(); -} - -static void -bfin_sport_spi_disable(struct bfin_sport_spi_master_data *drv_data) -{ - bfin_write_and(&drv_data->regs->tcr1, ~TSPEN); - bfin_write_and(&drv_data->regs->rcr1, ~TSPEN); - SSYNC(); -} - -/* Caculate the SPI_BAUD register value based on input HZ */ -static u16 -bfin_sport_hz_to_spi_baud(u32 speed_hz) -{ - u_long clk, sclk = get_sclk(); - int div = (sclk / (2 * speed_hz)) - 1; - - if (div < 0) - div = 0; - - clk = sclk / (2 * (div + 1)); - - if (clk > speed_hz) - div++; - - return div; -} - -/* Chip select operation functions for cs_change flag */ -static void -bfin_sport_spi_cs_active(struct bfin_sport_spi_slave_data *chip) -{ - gpio_direction_output(chip->cs_gpio, 0); -} - -static void -bfin_sport_spi_cs_deactive(struct bfin_sport_spi_slave_data *chip) -{ - gpio_direction_output(chip->cs_gpio, 1); - /* Move delay here for consistency */ - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); -} - -static void -bfin_sport_spi_stat_poll_complete(struct bfin_sport_spi_master_data *drv_data) -{ - unsigned long timeout = jiffies + HZ; - while (!(bfin_read(&drv_data->regs->stat) & RXNE)) { - if (!time_before(jiffies, timeout)) - break; - } -} - -static void -bfin_sport_spi_u8_writer(struct bfin_sport_spi_master_data *drv_data) -{ - u16 dummy; - - while (drv_data->tx < drv_data->tx_end) { - bfin_write(&drv_data->regs->tx16, *drv_data->tx8++); - bfin_sport_spi_stat_poll_complete(drv_data); - dummy = bfin_read(&drv_data->regs->rx16); - } -} - -static void -bfin_sport_spi_u8_reader(struct bfin_sport_spi_master_data *drv_data) -{ - u16 tx_val = drv_data->cur_chip->idle_tx_val; - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tx16, tx_val); - bfin_sport_spi_stat_poll_complete(drv_data); - *drv_data->rx8++ = bfin_read(&drv_data->regs->rx16); - } -} - -static void -bfin_sport_spi_u8_duplex(struct bfin_sport_spi_master_data *drv_data) -{ - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tx16, *drv_data->tx8++); - bfin_sport_spi_stat_poll_complete(drv_data); - *drv_data->rx8++ = bfin_read(&drv_data->regs->rx16); - } -} - -static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u8 = { - .write = bfin_sport_spi_u8_writer, - .read = bfin_sport_spi_u8_reader, - .duplex = bfin_sport_spi_u8_duplex, -}; - -static void -bfin_sport_spi_u16_writer(struct bfin_sport_spi_master_data *drv_data) -{ - u16 dummy; - - while (drv_data->tx < drv_data->tx_end) { - bfin_write(&drv_data->regs->tx16, *drv_data->tx16++); - bfin_sport_spi_stat_poll_complete(drv_data); - dummy = bfin_read(&drv_data->regs->rx16); - } -} - -static void -bfin_sport_spi_u16_reader(struct bfin_sport_spi_master_data *drv_data) -{ - u16 tx_val = drv_data->cur_chip->idle_tx_val; - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tx16, tx_val); - bfin_sport_spi_stat_poll_complete(drv_data); - *drv_data->rx16++ = bfin_read(&drv_data->regs->rx16); - } -} - -static void -bfin_sport_spi_u16_duplex(struct bfin_sport_spi_master_data *drv_data) -{ - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tx16, *drv_data->tx16++); - bfin_sport_spi_stat_poll_complete(drv_data); - *drv_data->rx16++ = bfin_read(&drv_data->regs->rx16); - } -} - -static struct bfin_sport_transfer_ops bfin_sport_transfer_ops_u16 = { - .write = bfin_sport_spi_u16_writer, - .read = bfin_sport_spi_u16_reader, - .duplex = bfin_sport_spi_u16_duplex, -}; - -/* stop controller and re-config current chip */ -static void -bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data) -{ - struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip; - - bfin_sport_spi_disable(drv_data); - dev_dbg(drv_data->dev, "restoring spi ctl state\n"); - - bfin_write(&drv_data->regs->tcr1, chip->ctl_reg); - bfin_write(&drv_data->regs->tclkdiv, chip->baud); - SSYNC(); - - bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS)); - SSYNC(); - - bfin_sport_spi_cs_active(chip); -} - -/* test if there is more transfer to be done */ -static enum bfin_sport_spi_state -bfin_sport_spi_next_transfer(struct bfin_sport_spi_master_data *drv_data) -{ - struct spi_message *msg = drv_data->cur_msg; - struct spi_transfer *trans = drv_data->cur_transfer; - - /* Move to next transfer */ - if (trans->transfer_list.next != &msg->transfers) { - drv_data->cur_transfer = - list_entry(trans->transfer_list.next, - struct spi_transfer, transfer_list); - return RUNNING_STATE; - } - - return DONE_STATE; -} - -/* - * caller already set message->status; - * dma and pio irqs are blocked give finished message back - */ -static void -bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data) -{ - struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip; - unsigned long flags; - struct spi_message *msg; - - spin_lock_irqsave(&drv_data->lock, flags); - msg = drv_data->cur_msg; - drv_data->state = START_STATE; - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - schedule_work(&drv_data->pump_messages); - spin_unlock_irqrestore(&drv_data->lock, flags); - - if (!drv_data->cs_change) - bfin_sport_spi_cs_deactive(chip); - - if (msg->complete) - msg->complete(msg->context); -} - -static irqreturn_t -sport_err_handler(int irq, void *dev_id) -{ - struct bfin_sport_spi_master_data *drv_data = dev_id; - u16 status; - - dev_dbg(drv_data->dev, "%s enter\n", __func__); - status = bfin_read(&drv_data->regs->stat) & (TOVF | TUVF | ROVF | RUVF); - - if (status) { - bfin_write(&drv_data->regs->stat, status); - SSYNC(); - - bfin_sport_spi_disable(drv_data); - dev_err(drv_data->dev, "status error:%s%s%s%s\n", - status & TOVF ? " TOVF" : "", - status & TUVF ? " TUVF" : "", - status & ROVF ? " ROVF" : "", - status & RUVF ? " RUVF" : ""); - } - - return IRQ_HANDLED; -} - -static void -bfin_sport_spi_pump_transfers(unsigned long data) -{ - struct bfin_sport_spi_master_data *drv_data = (void *)data; - struct spi_message *message = NULL; - struct spi_transfer *transfer = NULL; - struct spi_transfer *previous = NULL; - struct bfin_sport_spi_slave_data *chip = NULL; - unsigned int bits_per_word; - u32 tranf_success = 1; - u32 transfer_speed; - u8 full_duplex = 0; - - /* Get current state information */ - message = drv_data->cur_msg; - transfer = drv_data->cur_transfer; - chip = drv_data->cur_chip; - - transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz); - bfin_write(&drv_data->regs->tclkdiv, transfer_speed); - SSYNC(); - - /* - * if msg is error or done, report it back using complete() callback - */ - - /* Handle for abort */ - if (drv_data->state == ERROR_STATE) { - dev_dbg(drv_data->dev, "transfer: we've hit an error\n"); - message->status = -EIO; - bfin_sport_spi_giveback(drv_data); - return; - } - - /* Handle end of message */ - if (drv_data->state == DONE_STATE) { - dev_dbg(drv_data->dev, "transfer: all done!\n"); - message->status = 0; - bfin_sport_spi_giveback(drv_data); - return; - } - - /* Delay if requested at end of transfer */ - if (drv_data->state == RUNNING_STATE) { - dev_dbg(drv_data->dev, "transfer: still running ...\n"); - previous = list_entry(transfer->transfer_list.prev, - struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); - } - - if (transfer->len == 0) { - /* Move to next transfer of this msg */ - drv_data->state = bfin_sport_spi_next_transfer(drv_data); - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - } - - if (transfer->tx_buf != NULL) { - drv_data->tx = (void *)transfer->tx_buf; - drv_data->tx_end = drv_data->tx + transfer->len; - dev_dbg(drv_data->dev, "tx_buf is %p, tx_end is %p\n", - transfer->tx_buf, drv_data->tx_end); - } else - drv_data->tx = NULL; - - if (transfer->rx_buf != NULL) { - full_duplex = transfer->tx_buf != NULL; - drv_data->rx = transfer->rx_buf; - drv_data->rx_end = drv_data->rx + transfer->len; - dev_dbg(drv_data->dev, "rx_buf is %p, rx_end is %p\n", - transfer->rx_buf, drv_data->rx_end); - } else - drv_data->rx = NULL; - - drv_data->cs_change = transfer->cs_change; - - /* Bits per word setup */ - bits_per_word = transfer->bits_per_word; - if (bits_per_word == 16) - drv_data->ops = &bfin_sport_transfer_ops_u16; - else - drv_data->ops = &bfin_sport_transfer_ops_u8; - bfin_write(&drv_data->regs->tcr2, bits_per_word - 1); - bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1); - bfin_write(&drv_data->regs->rcr2, bits_per_word - 1); - - drv_data->state = RUNNING_STATE; - - if (drv_data->cs_change) - bfin_sport_spi_cs_active(chip); - - dev_dbg(drv_data->dev, - "now pumping a transfer: width is %d, len is %d\n", - bits_per_word, transfer->len); - - /* PIO mode write then read */ - dev_dbg(drv_data->dev, "doing IO transfer\n"); - - bfin_sport_spi_enable(drv_data); - if (full_duplex) { - /* full duplex mode */ - BUG_ON((drv_data->tx_end - drv_data->tx) != - (drv_data->rx_end - drv_data->rx)); - drv_data->ops->duplex(drv_data); - - if (drv_data->tx != drv_data->tx_end) - tranf_success = 0; - } else if (drv_data->tx != NULL) { - /* write only half duplex */ - - drv_data->ops->write(drv_data); - - if (drv_data->tx != drv_data->tx_end) - tranf_success = 0; - } else if (drv_data->rx != NULL) { - /* read only half duplex */ - - drv_data->ops->read(drv_data); - if (drv_data->rx != drv_data->rx_end) - tranf_success = 0; - } - bfin_sport_spi_disable(drv_data); - - if (!tranf_success) { - dev_dbg(drv_data->dev, "IO write error!\n"); - drv_data->state = ERROR_STATE; - } else { - /* Update total byte transferred */ - message->actual_length += transfer->len; - /* Move to next transfer of this msg */ - drv_data->state = bfin_sport_spi_next_transfer(drv_data); - if (drv_data->cs_change) - bfin_sport_spi_cs_deactive(chip); - } - - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); -} - -/* pop a msg from queue and kick off real transfer */ -static void -bfin_sport_spi_pump_messages(struct work_struct *work) -{ - struct bfin_sport_spi_master_data *drv_data; - unsigned long flags; - struct spi_message *next_msg; - - drv_data = container_of(work, struct bfin_sport_spi_master_data, pump_messages); - - /* Lock queue and check for queue work */ - spin_lock_irqsave(&drv_data->lock, flags); - if (list_empty(&drv_data->queue) || !drv_data->run) { - /* pumper kicked off but no work to do */ - drv_data->busy = 0; - spin_unlock_irqrestore(&drv_data->lock, flags); - return; - } - - /* Make sure we are not already running a message */ - if (drv_data->cur_msg) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return; - } - - /* Extract head of queue */ - next_msg = list_entry(drv_data->queue.next, - struct spi_message, queue); - - drv_data->cur_msg = next_msg; - - /* Setup the SSP using the per chip configuration */ - drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); - - list_del_init(&drv_data->cur_msg->queue); - - /* Initialize message state */ - drv_data->cur_msg->state = START_STATE; - drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, - struct spi_transfer, transfer_list); - bfin_sport_spi_restore_state(drv_data); - dev_dbg(drv_data->dev, "got a message to pump, " - "state is set to: baud %d, cs_gpio %i, ctl 0x%x\n", - drv_data->cur_chip->baud, drv_data->cur_chip->cs_gpio, - drv_data->cur_chip->ctl_reg); - - dev_dbg(drv_data->dev, - "the first transfer len is %d\n", - drv_data->cur_transfer->len); - - /* Mark as busy and launch transfers */ - tasklet_schedule(&drv_data->pump_transfers); - - drv_data->busy = 1; - spin_unlock_irqrestore(&drv_data->lock, flags); -} - -/* - * got a msg to transfer, queue it in drv_data->queue. - * And kick off message pumper - */ -static int -bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct bfin_sport_spi_master_data *drv_data = spi_master_get_devdata(spi->master); - unsigned long flags; - - spin_lock_irqsave(&drv_data->lock, flags); - - if (!drv_data->run) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return -ESHUTDOWN; - } - - msg->actual_length = 0; - msg->status = -EINPROGRESS; - msg->state = START_STATE; - - dev_dbg(&spi->dev, "adding an msg in transfer()\n"); - list_add_tail(&msg->queue, &drv_data->queue); - - if (drv_data->run && !drv_data->busy) - schedule_work(&drv_data->pump_messages); - - spin_unlock_irqrestore(&drv_data->lock, flags); - - return 0; -} - -/* Called every time common spi devices change state */ -static int -bfin_sport_spi_setup(struct spi_device *spi) -{ - struct bfin_sport_spi_slave_data *chip, *first = NULL; - int ret; - - /* Only alloc (or use chip_info) on first setup */ - chip = spi_get_ctldata(spi); - if (chip == NULL) { - struct bfin5xx_spi_chip *chip_info; - - chip = first = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) - return -ENOMEM; - - /* platform chip_info isn't required */ - chip_info = spi->controller_data; - if (chip_info) { - /* - * DITFS and TDTYPE are only thing we don't set, but - * they probably shouldn't be changed by people. - */ - if (chip_info->ctl_reg || chip_info->enable_dma) { - ret = -EINVAL; - dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields\n"); - goto error; - } - chip->cs_chg_udelay = chip_info->cs_chg_udelay; - chip->idle_tx_val = chip_info->idle_tx_val; - } - } - - /* translate common spi framework into our register - * following configure contents are same for tx and rx. - */ - - if (spi->mode & SPI_CPHA) - chip->ctl_reg &= ~TCKFE; - else - chip->ctl_reg |= TCKFE; - - if (spi->mode & SPI_LSB_FIRST) - chip->ctl_reg |= TLSBIT; - else - chip->ctl_reg &= ~TLSBIT; - - /* Sport in master mode */ - chip->ctl_reg |= ITCLK | ITFS | TFSR | LATFS | LTFS; - - chip->baud = bfin_sport_hz_to_spi_baud(spi->max_speed_hz); - - chip->cs_gpio = spi->chip_select; - ret = gpio_request(chip->cs_gpio, spi->modalias); - if (ret) - goto error; - - dev_dbg(&spi->dev, "setup spi chip %s, width is %d\n", - spi->modalias, spi->bits_per_word); - dev_dbg(&spi->dev, "ctl_reg is 0x%x, GPIO is %i\n", - chip->ctl_reg, spi->chip_select); - - spi_set_ctldata(spi, chip); - - bfin_sport_spi_cs_deactive(chip); - - return ret; - - error: - kfree(first); - return ret; -} - -/* - * callback for spi framework. - * clean driver specific data - */ -static void -bfin_sport_spi_cleanup(struct spi_device *spi) -{ - struct bfin_sport_spi_slave_data *chip = spi_get_ctldata(spi); - - if (!chip) - return; - - gpio_free(chip->cs_gpio); - - kfree(chip); -} - -static int -bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data) -{ - INIT_LIST_HEAD(&drv_data->queue); - spin_lock_init(&drv_data->lock); - - drv_data->run = false; - drv_data->busy = 0; - - /* init transfer tasklet */ - tasklet_init(&drv_data->pump_transfers, - bfin_sport_spi_pump_transfers, (unsigned long)drv_data); - - INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages); - - return 0; -} - -static int -bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data) -{ - unsigned long flags; - - spin_lock_irqsave(&drv_data->lock, flags); - - if (drv_data->run || drv_data->busy) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return -EBUSY; - } - - drv_data->run = true; - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - spin_unlock_irqrestore(&drv_data->lock, flags); - - schedule_work(&drv_data->pump_messages); - - return 0; -} - -static inline int -bfin_sport_spi_stop_queue(struct bfin_sport_spi_master_data *drv_data) -{ - unsigned long flags; - unsigned limit = 500; - int status = 0; - - spin_lock_irqsave(&drv_data->lock, flags); - - /* - * This is a bit lame, but is optimized for the common execution path. - * A wait_queue on the drv_data->busy could be used, but then the common - * execution path (pump_messages) would be required to call wake_up or - * friends on every SPI message. Do this instead - */ - drv_data->run = false; - while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { - spin_unlock_irqrestore(&drv_data->lock, flags); - msleep(10); - spin_lock_irqsave(&drv_data->lock, flags); - } - - if (!list_empty(&drv_data->queue) || drv_data->busy) - status = -EBUSY; - - spin_unlock_irqrestore(&drv_data->lock, flags); - - return status; -} - -static inline int -bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data) -{ - int status; - - status = bfin_sport_spi_stop_queue(drv_data); - if (status) - return status; - - flush_work(&drv_data->pump_messages); - - return 0; -} - -static int bfin_sport_spi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct bfin5xx_spi_master *platform_info; - struct spi_master *master; - struct resource *res, *ires; - struct bfin_sport_spi_master_data *drv_data; - int status; - - platform_info = dev_get_platdata(dev); - - /* Allocate master with space for drv_data */ - master = spi_alloc_master(dev, sizeof(*master) + 16); - if (!master) { - dev_err(dev, "cannot alloc spi_master\n"); - return -ENOMEM; - } - - drv_data = spi_master_get_devdata(master); - drv_data->master = master; - drv_data->dev = dev; - drv_data->pin_req = platform_info->pin_req; - - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); - master->bus_num = pdev->id; - master->num_chipselect = platform_info->num_chipselect; - master->cleanup = bfin_sport_spi_cleanup; - master->setup = bfin_sport_spi_setup; - master->transfer = bfin_sport_spi_transfer; - - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(dev, "cannot get IORESOURCE_MEM\n"); - status = -ENOENT; - goto out_error_get_res; - } - - drv_data->regs = ioremap(res->start, resource_size(res)); - if (drv_data->regs == NULL) { - dev_err(dev, "cannot map registers\n"); - status = -ENXIO; - goto out_error_ioremap; - } - - ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!ires) { - dev_err(dev, "cannot get IORESOURCE_IRQ\n"); - status = -ENODEV; - goto out_error_get_ires; - } - drv_data->err_irq = ires->start; - - /* Initial and start queue */ - status = bfin_sport_spi_init_queue(drv_data); - if (status) { - dev_err(dev, "problem initializing queue\n"); - goto out_error_queue_alloc; - } - - status = bfin_sport_spi_start_queue(drv_data); - if (status) { - dev_err(dev, "problem starting queue\n"); - goto out_error_queue_alloc; - } - - status = request_irq(drv_data->err_irq, sport_err_handler, - 0, "sport_spi_err", drv_data); - if (status) { - dev_err(dev, "unable to request sport err irq\n"); - goto out_error_irq; - } - - status = peripheral_request_list(drv_data->pin_req, DRV_NAME); - if (status) { - dev_err(dev, "requesting peripherals failed\n"); - goto out_error_peripheral; - } - - /* Register with the SPI framework */ - platform_set_drvdata(pdev, drv_data); - status = spi_register_master(master); - if (status) { - dev_err(dev, "problem registering spi master\n"); - goto out_error_master; - } - - dev_info(dev, "%s, regs_base@%p\n", DRV_DESC, drv_data->regs); - return 0; - - out_error_master: - peripheral_free_list(drv_data->pin_req); - out_error_peripheral: - free_irq(drv_data->err_irq, drv_data); - out_error_irq: - out_error_queue_alloc: - bfin_sport_spi_destroy_queue(drv_data); - out_error_get_ires: - iounmap(drv_data->regs); - out_error_ioremap: - out_error_get_res: - spi_master_put(master); - - return status; -} - -/* stop hardware and remove the driver */ -static int bfin_sport_spi_remove(struct platform_device *pdev) -{ - struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev); - int status = 0; - - if (!drv_data) - return 0; - - /* Remove the queue */ - status = bfin_sport_spi_destroy_queue(drv_data); - if (status) - return status; - - /* Disable the SSP at the peripheral and SOC level */ - bfin_sport_spi_disable(drv_data); - - /* Disconnect from the SPI framework */ - spi_unregister_master(drv_data->master); - - peripheral_free_list(drv_data->pin_req); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int bfin_sport_spi_suspend(struct device *dev) -{ - struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev); - int status; - - status = bfin_sport_spi_stop_queue(drv_data); - if (status) - return status; - - /* stop hardware */ - bfin_sport_spi_disable(drv_data); - - return status; -} - -static int bfin_sport_spi_resume(struct device *dev) -{ - struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev); - int status; - - /* Enable the SPI interface */ - bfin_sport_spi_enable(drv_data); - - /* Start the queue running */ - status = bfin_sport_spi_start_queue(drv_data); - if (status) - dev_err(drv_data->dev, "problem resuming queue\n"); - - return status; -} - -static SIMPLE_DEV_PM_OPS(bfin_sport_spi_pm_ops, bfin_sport_spi_suspend, - bfin_sport_spi_resume); - -#define BFIN_SPORT_SPI_PM_OPS (&bfin_sport_spi_pm_ops) -#else -#define BFIN_SPORT_SPI_PM_OPS NULL -#endif - -static struct platform_driver bfin_sport_spi_driver = { - .driver = { - .name = DRV_NAME, - .pm = BFIN_SPORT_SPI_PM_OPS, - }, - .probe = bfin_sport_spi_probe, - .remove = bfin_sport_spi_remove, -}; -module_platform_driver(bfin_sport_spi_driver); diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c deleted file mode 100644 index 249c7a3677c9..000000000000 --- a/drivers/spi/spi-bfin5xx.c +++ /dev/null @@ -1,1462 +0,0 @@ -/* - * Blackfin On-Chip SPI Driver - * - * Copyright 2004-2010 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/irq.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/spi/spi.h> -#include <linux/workqueue.h> - -#include <asm/dma.h> -#include <asm/portmux.h> -#include <asm/bfin5xx_spi.h> -#include <asm/cacheflush.h> - -#define DRV_NAME "bfin-spi" -#define DRV_AUTHOR "Bryan Wu, Luke Yang" -#define DRV_DESC "Blackfin on-chip SPI Controller Driver" -#define DRV_VERSION "1.0" - -MODULE_AUTHOR(DRV_AUTHOR); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_LICENSE("GPL"); - -#define START_STATE ((void *)0) -#define RUNNING_STATE ((void *)1) -#define DONE_STATE ((void *)2) -#define ERROR_STATE ((void *)-1) - -struct bfin_spi_master_data; - -struct bfin_spi_transfer_ops { - void (*write) (struct bfin_spi_master_data *); - void (*read) (struct bfin_spi_master_data *); - void (*duplex) (struct bfin_spi_master_data *); -}; - -struct bfin_spi_master_data { - /* Driver model hookup */ - struct platform_device *pdev; - - /* SPI framework hookup */ - struct spi_master *master; - - /* Regs base of SPI controller */ - struct bfin_spi_regs __iomem *regs; - - /* Pin request list */ - u16 *pin_req; - - /* BFIN hookup */ - struct bfin5xx_spi_master *master_info; - - struct work_struct pump_messages; - spinlock_t lock; - struct list_head queue; - int busy; - bool running; - - /* Message Transfer pump */ - struct tasklet_struct pump_transfers; - - /* Current message transfer state info */ - struct spi_message *cur_msg; - struct spi_transfer *cur_transfer; - struct bfin_spi_slave_data *cur_chip; - size_t len_in_bytes; - size_t len; - void *tx; - void *tx_end; - void *rx; - void *rx_end; - - /* DMA stuffs */ - int dma_channel; - int dma_mapped; - int dma_requested; - dma_addr_t rx_dma; - dma_addr_t tx_dma; - - int irq_requested; - int spi_irq; - - size_t rx_map_len; - size_t tx_map_len; - u8 n_bytes; - u16 ctrl_reg; - u16 flag_reg; - - int cs_change; - const struct bfin_spi_transfer_ops *ops; -}; - -struct bfin_spi_slave_data { - u16 ctl_reg; - u16 baud; - u16 flag; - - u8 chip_select_num; - u8 enable_dma; - u16 cs_chg_udelay; /* Some devices require > 255usec delay */ - u32 cs_gpio; - u16 idle_tx_val; - u8 pio_interrupt; /* use spi data irq */ - const struct bfin_spi_transfer_ops *ops; -}; - -static void bfin_spi_enable(struct bfin_spi_master_data *drv_data) -{ - bfin_write_or(&drv_data->regs->ctl, BIT_CTL_ENABLE); -} - -static void bfin_spi_disable(struct bfin_spi_master_data *drv_data) -{ - bfin_write_and(&drv_data->regs->ctl, ~BIT_CTL_ENABLE); -} - -/* Caculate the SPI_BAUD register value based on input HZ */ -static u16 hz_to_spi_baud(u32 speed_hz) -{ - u_long sclk = get_sclk(); - u16 spi_baud = (sclk / (2 * speed_hz)); - - if ((sclk % (2 * speed_hz)) > 0) - spi_baud++; - - if (spi_baud < MIN_SPI_BAUD_VAL) - spi_baud = MIN_SPI_BAUD_VAL; - - return spi_baud; -} - -static int bfin_spi_flush(struct bfin_spi_master_data *drv_data) -{ - unsigned long limit = loops_per_jiffy << 1; - - /* wait for stop and clear stat */ - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF) && --limit) - cpu_relax(); - - bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); - - return limit; -} - -/* Chip select operation functions for cs_change flag */ -static void bfin_spi_cs_active(struct bfin_spi_master_data *drv_data, struct bfin_spi_slave_data *chip) -{ - if (likely(chip->chip_select_num < MAX_CTRL_CS)) - bfin_write_and(&drv_data->regs->flg, ~chip->flag); - else - gpio_set_value(chip->cs_gpio, 0); -} - -static void bfin_spi_cs_deactive(struct bfin_spi_master_data *drv_data, - struct bfin_spi_slave_data *chip) -{ - if (likely(chip->chip_select_num < MAX_CTRL_CS)) - bfin_write_or(&drv_data->regs->flg, chip->flag); - else - gpio_set_value(chip->cs_gpio, 1); - - /* Move delay here for consistency */ - if (chip->cs_chg_udelay) - udelay(chip->cs_chg_udelay); -} - -/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ -static inline void bfin_spi_cs_enable(struct bfin_spi_master_data *drv_data, - struct bfin_spi_slave_data *chip) -{ - if (chip->chip_select_num < MAX_CTRL_CS) - bfin_write_or(&drv_data->regs->flg, chip->flag >> 8); -} - -static inline void bfin_spi_cs_disable(struct bfin_spi_master_data *drv_data, - struct bfin_spi_slave_data *chip) -{ - if (chip->chip_select_num < MAX_CTRL_CS) - bfin_write_and(&drv_data->regs->flg, ~(chip->flag >> 8)); -} - -/* stop controller and re-config current chip*/ -static void bfin_spi_restore_state(struct bfin_spi_master_data *drv_data) -{ - struct bfin_spi_slave_data *chip = drv_data->cur_chip; - - /* Clear status and disable clock */ - bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); - bfin_spi_disable(drv_data); - dev_dbg(&drv_data->pdev->dev, "restoring spi ctl state\n"); - - SSYNC(); - - /* Load the registers */ - bfin_write(&drv_data->regs->ctl, chip->ctl_reg); - bfin_write(&drv_data->regs->baud, chip->baud); - - bfin_spi_enable(drv_data); - bfin_spi_cs_active(drv_data, chip); -} - -/* used to kick off transfer in rx mode and read unwanted RX data */ -static inline void bfin_spi_dummy_read(struct bfin_spi_master_data *drv_data) -{ - (void) bfin_read(&drv_data->regs->rdbr); -} - -static void bfin_spi_u8_writer(struct bfin_spi_master_data *drv_data) -{ - /* clear RXS (we check for RXS inside the loop) */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->tx < drv_data->tx_end) { - bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++))); - /* wait until transfer finished. - checking SPIF or TXS may not guarantee transfer completion */ - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - /* discard RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - } -} - -static void bfin_spi_u8_reader(struct bfin_spi_master_data *drv_data) -{ - u16 tx_val = drv_data->cur_chip->idle_tx_val; - - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tdbr, tx_val); - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr); - } -} - -static void bfin_spi_u8_duplex(struct bfin_spi_master_data *drv_data) -{ - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tdbr, (*(u8 *) (drv_data->tx++))); - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - *(u8 *) (drv_data->rx++) = bfin_read(&drv_data->regs->rdbr); - } -} - -static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { - .write = bfin_spi_u8_writer, - .read = bfin_spi_u8_reader, - .duplex = bfin_spi_u8_duplex, -}; - -static void bfin_spi_u16_writer(struct bfin_spi_master_data *drv_data) -{ - /* clear RXS (we check for RXS inside the loop) */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->tx < drv_data->tx_end) { - bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx))); - drv_data->tx += 2; - /* wait until transfer finished. - checking SPIF or TXS may not guarantee transfer completion */ - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - /* discard RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - } -} - -static void bfin_spi_u16_reader(struct bfin_spi_master_data *drv_data) -{ - u16 tx_val = drv_data->cur_chip->idle_tx_val; - - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tdbr, tx_val); - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr); - drv_data->rx += 2; - } -} - -static void bfin_spi_u16_duplex(struct bfin_spi_master_data *drv_data) -{ - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - - while (drv_data->rx < drv_data->rx_end) { - bfin_write(&drv_data->regs->tdbr, (*(u16 *) (drv_data->tx))); - drv_data->tx += 2; - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - *(u16 *) (drv_data->rx) = bfin_read(&drv_data->regs->rdbr); - drv_data->rx += 2; - } -} - -static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { - .write = bfin_spi_u16_writer, - .read = bfin_spi_u16_reader, - .duplex = bfin_spi_u16_duplex, -}; - -/* test if there is more transfer to be done */ -static void *bfin_spi_next_transfer(struct bfin_spi_master_data *drv_data) -{ - struct spi_message *msg = drv_data->cur_msg; - struct spi_transfer *trans = drv_data->cur_transfer; - - /* Move to next transfer */ - if (trans->transfer_list.next != &msg->transfers) { - drv_data->cur_transfer = - list_entry(trans->transfer_list.next, - struct spi_transfer, transfer_list); - return RUNNING_STATE; - } else - return DONE_STATE; -} - -/* - * caller already set message->status; - * dma and pio irqs are blocked give finished message back - */ -static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data) -{ - struct bfin_spi_slave_data *chip = drv_data->cur_chip; - unsigned long flags; - struct spi_message *msg; - - spin_lock_irqsave(&drv_data->lock, flags); - msg = drv_data->cur_msg; - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - schedule_work(&drv_data->pump_messages); - spin_unlock_irqrestore(&drv_data->lock, flags); - - msg->state = NULL; - - if (!drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - - /* Not stop spi in autobuffer mode */ - if (drv_data->tx_dma != 0xFFFF) - bfin_spi_disable(drv_data); - - if (msg->complete) - msg->complete(msg->context); -} - -/* spi data irq handler */ -static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id) -{ - struct bfin_spi_master_data *drv_data = dev_id; - struct bfin_spi_slave_data *chip = drv_data->cur_chip; - struct spi_message *msg = drv_data->cur_msg; - int n_bytes = drv_data->n_bytes; - int loop = 0; - - /* wait until transfer finished. */ - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_RXS)) - cpu_relax(); - - if ((drv_data->tx && drv_data->tx >= drv_data->tx_end) || - (drv_data->rx && drv_data->rx >= (drv_data->rx_end - n_bytes))) { - /* last read */ - if (drv_data->rx) { - dev_dbg(&drv_data->pdev->dev, "last read\n"); - if (!(n_bytes % 2)) { - u16 *buf = (u16 *)drv_data->rx; - for (loop = 0; loop < n_bytes / 2; loop++) - *buf++ = bfin_read(&drv_data->regs->rdbr); - } else { - u8 *buf = (u8 *)drv_data->rx; - for (loop = 0; loop < n_bytes; loop++) - *buf++ = bfin_read(&drv_data->regs->rdbr); - } - drv_data->rx += n_bytes; - } - - msg->actual_length += drv_data->len_in_bytes; - if (drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - /* Move to next transfer */ - msg->state = bfin_spi_next_transfer(drv_data); - - disable_irq_nosync(drv_data->spi_irq); - - /* Schedule transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - return IRQ_HANDLED; - } - - if (drv_data->rx && drv_data->tx) { - /* duplex */ - dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n"); - if (!(n_bytes % 2)) { - u16 *buf = (u16 *)drv_data->rx; - u16 *buf2 = (u16 *)drv_data->tx; - for (loop = 0; loop < n_bytes / 2; loop++) { - *buf++ = bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, *buf2++); - } - } else { - u8 *buf = (u8 *)drv_data->rx; - u8 *buf2 = (u8 *)drv_data->tx; - for (loop = 0; loop < n_bytes; loop++) { - *buf++ = bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, *buf2++); - } - } - } else if (drv_data->rx) { - /* read */ - dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n"); - if (!(n_bytes % 2)) { - u16 *buf = (u16 *)drv_data->rx; - for (loop = 0; loop < n_bytes / 2; loop++) { - *buf++ = bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val); - } - } else { - u8 *buf = (u8 *)drv_data->rx; - for (loop = 0; loop < n_bytes; loop++) { - *buf++ = bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val); - } - } - } else if (drv_data->tx) { - /* write */ - dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n"); - if (!(n_bytes % 2)) { - u16 *buf = (u16 *)drv_data->tx; - for (loop = 0; loop < n_bytes / 2; loop++) { - bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, *buf++); - } - } else { - u8 *buf = (u8 *)drv_data->tx; - for (loop = 0; loop < n_bytes; loop++) { - bfin_read(&drv_data->regs->rdbr); - bfin_write(&drv_data->regs->tdbr, *buf++); - } - } - } - - if (drv_data->tx) - drv_data->tx += n_bytes; - if (drv_data->rx) - drv_data->rx += n_bytes; - - return IRQ_HANDLED; -} - -static irqreturn_t bfin_spi_dma_irq_handler(int irq, void *dev_id) -{ - struct bfin_spi_master_data *drv_data = dev_id; - struct bfin_spi_slave_data *chip = drv_data->cur_chip; - struct spi_message *msg = drv_data->cur_msg; - unsigned long timeout; - unsigned short dmastat = get_dma_curr_irqstat(drv_data->dma_channel); - u16 spistat = bfin_read(&drv_data->regs->stat); - - dev_dbg(&drv_data->pdev->dev, - "in dma_irq_handler dmastat:0x%x spistat:0x%x\n", - dmastat, spistat); - - if (drv_data->rx != NULL) { - u16 cr = bfin_read(&drv_data->regs->ctl); - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_ENABLE); /* Disable SPI */ - bfin_write(&drv_data->regs->ctl, cr & ~BIT_CTL_TIMOD); /* Restore State */ - bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); /* Clear Status */ - } - - clear_dma_irqstat(drv_data->dma_channel); - - /* - * wait for the last transaction shifted out. HRM states: - * at this point there may still be data in the SPI DMA FIFO waiting - * to be transmitted ... software needs to poll TXS in the SPI_STAT - * register until it goes low for 2 successive reads - */ - if (drv_data->tx != NULL) { - while ((bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS) || - (bfin_read(&drv_data->regs->stat) & BIT_STAT_TXS)) - cpu_relax(); - } - - dev_dbg(&drv_data->pdev->dev, - "in dma_irq_handler dmastat:0x%x spistat:0x%x\n", - dmastat, bfin_read(&drv_data->regs->stat)); - - timeout = jiffies + HZ; - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF)) - if (!time_before(jiffies, timeout)) { - dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF\n"); - break; - } else - cpu_relax(); - - if ((dmastat & DMA_ERR) && (spistat & BIT_STAT_RBSY)) { - msg->state = ERROR_STATE; - dev_err(&drv_data->pdev->dev, "dma receive: fifo/buffer overflow\n"); - } else { - msg->actual_length += drv_data->len_in_bytes; - - if (drv_data->cs_change) - bfin_spi_cs_deactive(drv_data, chip); - - /* Move to next transfer */ - msg->state = bfin_spi_next_transfer(drv_data); - } - - /* Schedule transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - - /* free the irq handler before next transfer */ - dev_dbg(&drv_data->pdev->dev, - "disable dma channel irq%d\n", - drv_data->dma_channel); - dma_disable_irq_nosync(drv_data->dma_channel); - - return IRQ_HANDLED; -} - -static void bfin_spi_pump_transfers(unsigned long data) -{ - struct bfin_spi_master_data *drv_data = (struct bfin_spi_master_data *)data; - struct spi_message *message = NULL; - struct spi_transfer *transfer = NULL; - struct spi_transfer *previous = NULL; - struct bfin_spi_slave_data *chip = NULL; - unsigned int bits_per_word; - u16 cr, cr_width = 0, dma_width, dma_config; - u32 tranf_success = 1; - u8 full_duplex = 0; - - /* Get current state information */ - message = drv_data->cur_msg; - transfer = drv_data->cur_transfer; - chip = drv_data->cur_chip; - - /* - * if msg is error or done, report it back using complete() callback - */ - - /* Handle for abort */ - if (message->state == ERROR_STATE) { - dev_dbg(&drv_data->pdev->dev, "transfer: we've hit an error\n"); - message->status = -EIO; - bfin_spi_giveback(drv_data); - return; - } - - /* Handle end of message */ - if (message->state == DONE_STATE) { - dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n"); - message->status = 0; - bfin_spi_flush(drv_data); - bfin_spi_giveback(drv_data); - return; - } - - /* Delay if requested at end of transfer */ - if (message->state == RUNNING_STATE) { - dev_dbg(&drv_data->pdev->dev, "transfer: still running ...\n"); - previous = list_entry(transfer->transfer_list.prev, - struct spi_transfer, transfer_list); - if (previous->delay_usecs) - udelay(previous->delay_usecs); - } - - /* Flush any existing transfers that may be sitting in the hardware */ - if (bfin_spi_flush(drv_data) == 0) { - dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); - message->status = -EIO; - bfin_spi_giveback(drv_data); - return; - } - - if (transfer->len == 0) { - /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); - return; - } - - if (transfer->tx_buf != NULL) { - drv_data->tx = (void *)transfer->tx_buf; - drv_data->tx_end = drv_data->tx + transfer->len; - dev_dbg(&drv_data->pdev->dev, "tx_buf is %p, tx_end is %p\n", - transfer->tx_buf, drv_data->tx_end); - } else { - drv_data->tx = NULL; - } - - if (transfer->rx_buf != NULL) { - full_duplex = transfer->tx_buf != NULL; - drv_data->rx = transfer->rx_buf; - drv_data->rx_end = drv_data->rx + transfer->len; - dev_dbg(&drv_data->pdev->dev, "rx_buf is %p, rx_end is %p\n", - transfer->rx_buf, drv_data->rx_end); - } else { - drv_data->rx = NULL; - } - - drv_data->rx_dma = transfer->rx_dma; - drv_data->tx_dma = transfer->tx_dma; - drv_data->len_in_bytes = transfer->len; - drv_data->cs_change = transfer->cs_change; - - /* Bits per word setup */ - bits_per_word = transfer->bits_per_word; - if (bits_per_word == 16) { - drv_data->n_bytes = bits_per_word/8; - drv_data->len = (transfer->len) >> 1; - cr_width = BIT_CTL_WORDSIZE; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u16; - } else if (bits_per_word == 8) { - drv_data->n_bytes = bits_per_word/8; - drv_data->len = transfer->len; - drv_data->ops = &bfin_bfin_spi_transfer_ops_u8; - } - cr = bfin_read(&drv_data->regs->ctl) & ~(BIT_CTL_TIMOD | BIT_CTL_WORDSIZE); - cr |= cr_width; - bfin_write(&drv_data->regs->ctl, cr); - - dev_dbg(&drv_data->pdev->dev, - "transfer: drv_data->ops is %p, chip->ops is %p, u8_ops is %p\n", - drv_data->ops, chip->ops, &bfin_bfin_spi_transfer_ops_u8); - - message->state = RUNNING_STATE; - dma_config = 0; - - bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz)); - - bfin_write(&drv_data->regs->stat, BIT_STAT_CLR); - bfin_spi_cs_active(drv_data, chip); - - dev_dbg(&drv_data->pdev->dev, - "now pumping a transfer: width is %d, len is %d\n", - cr_width, transfer->len); - - /* - * Try to map dma buffer and do a dma transfer. If successful use, - * different way to r/w according to the enable_dma settings and if - * we are not doing a full duplex transfer (since the hardware does - * not support full duplex DMA transfers). - */ - if (!full_duplex && drv_data->cur_chip->enable_dma - && drv_data->len > 6) { - - unsigned long dma_start_addr, flags; - - disable_dma(drv_data->dma_channel); - clear_dma_irqstat(drv_data->dma_channel); - - /* config dma channel */ - dev_dbg(&drv_data->pdev->dev, "doing dma transfer\n"); - set_dma_x_count(drv_data->dma_channel, drv_data->len); - if (cr_width == BIT_CTL_WORDSIZE) { - set_dma_x_modify(drv_data->dma_channel, 2); - dma_width = WDSIZE_16; - } else { - set_dma_x_modify(drv_data->dma_channel, 1); - dma_width = WDSIZE_8; - } - - /* poll for SPI completion before start */ - while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF)) - cpu_relax(); - - /* dirty hack for autobuffer DMA mode */ - if (drv_data->tx_dma == 0xFFFF) { - dev_dbg(&drv_data->pdev->dev, - "doing autobuffer DMA out.\n"); - - /* no irq in autobuffer mode */ - dma_config = - (DMAFLOW_AUTO | RESTART | dma_width | DI_EN); - set_dma_config(drv_data->dma_channel, dma_config); - set_dma_start_addr(drv_data->dma_channel, - (unsigned long)drv_data->tx); - enable_dma(drv_data->dma_channel); - - /* start SPI transfer */ - bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TIMOD_DMA_TX); - - /* just return here, there can only be one transfer - * in this mode - */ - message->status = 0; - bfin_spi_giveback(drv_data); - return; - } - - /* In dma mode, rx or tx must be NULL in one transfer */ - dma_config = (RESTART | dma_width | DI_EN); - if (drv_data->rx != NULL) { - /* set transfer mode, and enable SPI */ - dev_dbg(&drv_data->pdev->dev, "doing DMA in to %p (size %zx)\n", - drv_data->rx, drv_data->len_in_bytes); - - /* invalidate caches, if needed */ - if (bfin_addr_dcacheable((unsigned long) drv_data->rx)) - invalidate_dcache_range((unsigned long) drv_data->rx, - (unsigned long) (drv_data->rx + - drv_data->len_in_bytes)); - - dma_config |= WNR; - dma_start_addr = (unsigned long)drv_data->rx; - cr |= BIT_CTL_TIMOD_DMA_RX | BIT_CTL_SENDOPT; - - } else if (drv_data->tx != NULL) { - dev_dbg(&drv_data->pdev->dev, "doing DMA out.\n"); - - /* flush caches, if needed */ - if (bfin_addr_dcacheable((unsigned long) drv_data->tx)) - flush_dcache_range((unsigned long) drv_data->tx, - (unsigned long) (drv_data->tx + - drv_data->len_in_bytes)); - - dma_start_addr = (unsigned long)drv_data->tx; - cr |= BIT_CTL_TIMOD_DMA_TX; - - } else - BUG(); - - /* oh man, here there be monsters ... and i dont mean the - * fluffy cute ones from pixar, i mean the kind that'll eat - * your data, kick your dog, and love it all. do *not* try - * and change these lines unless you (1) heavily test DMA - * with SPI flashes on a loaded system (e.g. ping floods), - * (2) know just how broken the DMA engine interaction with - * the SPI peripheral is, and (3) have someone else to blame - * when you screw it all up anyways. - */ - set_dma_start_addr(drv_data->dma_channel, dma_start_addr); - set_dma_config(drv_data->dma_channel, dma_config); - local_irq_save(flags); - SSYNC(); - bfin_write(&drv_data->regs->ctl, cr); - enable_dma(drv_data->dma_channel); - dma_enable_irq(drv_data->dma_channel); - local_irq_restore(flags); - - return; - } - - /* - * We always use SPI_WRITE mode (transfer starts with TDBR write). - * SPI_READ mode (transfer starts with RDBR read) seems to have - * problems with setting up the output value in TDBR prior to the - * start of the transfer. - */ - bfin_write(&drv_data->regs->ctl, cr | BIT_CTL_TXMOD); - - if (chip->pio_interrupt) { - /* SPI irq should have been disabled by now */ - - /* discard old RX data and clear RXS */ - bfin_spi_dummy_read(drv_data); - - /* start transfer */ - if (drv_data->tx == NULL) - bfin_write(&drv_data->regs->tdbr, chip->idle_tx_val); - else { - int loop; - if (bits_per_word == 16) { - u16 *buf = (u16 *)drv_data->tx; - for (loop = 0; loop < bits_per_word / 16; - loop++) { - bfin_write(&drv_data->regs->tdbr, *buf++); - } - } else if (bits_per_word == 8) { - u8 *buf = (u8 *)drv_data->tx; - for (loop = 0; loop < bits_per_word / 8; loop++) - bfin_write(&drv_data->regs->tdbr, *buf++); - } - - drv_data->tx += drv_data->n_bytes; - } - - /* once TDBR is empty, interrupt is triggered */ - enable_irq(drv_data->spi_irq); - return; - } - - /* IO mode */ - dev_dbg(&drv_data->pdev->dev, "doing IO transfer\n"); - - if (full_duplex) { - /* full duplex mode */ - BUG_ON((drv_data->tx_end - drv_data->tx) != - (drv_data->rx_end - drv_data->rx)); - dev_dbg(&drv_data->pdev->dev, - "IO duplex: cr is 0x%x\n", cr); - - drv_data->ops->duplex(drv_data); - - if (drv_data->tx != drv_data->tx_end) - tranf_success = 0; - } else if (drv_data->tx != NULL) { - /* write only half duplex */ - dev_dbg(&drv_data->pdev->dev, - "IO write: cr is 0x%x\n", cr); - - drv_data->ops->write(drv_data); - - if (drv_data->tx != drv_data->tx_end) - tranf_success = 0; - } else if (drv_data->rx != NULL) { - /* read only half duplex */ - dev_dbg(&drv_data->pdev->dev, - "IO read: cr is 0x%x\n", cr); - - drv_data->ops->read(drv_data); - if (drv_data->rx != drv_data->rx_end) - tranf_success = 0; - } - - if (!tranf_success) { - dev_dbg(&drv_data->pdev->dev, - "IO write error!\n"); - message->state = ERROR_STATE; - } else { - /* Update total byte transferred */ - message->actual_length += drv_data->len_in_bytes; - /* Move to next transfer of this msg */ - message->state = bfin_spi_next_transfer(drv_data); - if (drv_data->cs_change && message->state != DONE_STATE) { - bfin_spi_flush(drv_data); - bfin_spi_cs_deactive(drv_data, chip); - } - } - - /* Schedule next transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); -} - -/* pop a msg from queue and kick off real transfer */ -static void bfin_spi_pump_messages(struct work_struct *work) -{ - struct bfin_spi_master_data *drv_data; - unsigned long flags; - - drv_data = container_of(work, struct bfin_spi_master_data, pump_messages); - - /* Lock queue and check for queue work */ - spin_lock_irqsave(&drv_data->lock, flags); - if (list_empty(&drv_data->queue) || !drv_data->running) { - /* pumper kicked off but no work to do */ - drv_data->busy = 0; - spin_unlock_irqrestore(&drv_data->lock, flags); - return; - } - - /* Make sure we are not already running a message */ - if (drv_data->cur_msg) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return; - } - - /* Extract head of queue */ - drv_data->cur_msg = list_entry(drv_data->queue.next, - struct spi_message, queue); - - /* Setup the SSP using the per chip configuration */ - drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); - bfin_spi_restore_state(drv_data); - - list_del_init(&drv_data->cur_msg->queue); - - /* Initial message state */ - drv_data->cur_msg->state = START_STATE; - drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, - struct spi_transfer, transfer_list); - - dev_dbg(&drv_data->pdev->dev, - "got a message to pump, state is set to: baud " - "%d, flag 0x%x, ctl 0x%x\n", - drv_data->cur_chip->baud, drv_data->cur_chip->flag, - drv_data->cur_chip->ctl_reg); - - dev_dbg(&drv_data->pdev->dev, - "the first transfer len is %d\n", - drv_data->cur_transfer->len); - - /* Mark as busy and launch transfers */ - tasklet_schedule(&drv_data->pump_transfers); - - drv_data->busy = 1; - spin_unlock_irqrestore(&drv_data->lock, flags); -} - -/* - * got a msg to transfer, queue it in drv_data->queue. - * And kick off message pumper - */ -static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); - unsigned long flags; - - spin_lock_irqsave(&drv_data->lock, flags); - - if (!drv_data->running) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return -ESHUTDOWN; - } - - msg->actual_length = 0; - msg->status = -EINPROGRESS; - msg->state = START_STATE; - - dev_dbg(&spi->dev, "adding an msg in transfer() \n"); - list_add_tail(&msg->queue, &drv_data->queue); - - if (drv_data->running && !drv_data->busy) - schedule_work(&drv_data->pump_messages); - - spin_unlock_irqrestore(&drv_data->lock, flags); - - return 0; -} - -#define MAX_SPI_SSEL 7 - -static const u16 ssel[][MAX_SPI_SSEL] = { - {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, - P_SPI0_SSEL4, P_SPI0_SSEL5, - P_SPI0_SSEL6, P_SPI0_SSEL7}, - - {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, - P_SPI1_SSEL4, P_SPI1_SSEL5, - P_SPI1_SSEL6, P_SPI1_SSEL7}, - - {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, - P_SPI2_SSEL4, P_SPI2_SSEL5, - P_SPI2_SSEL6, P_SPI2_SSEL7}, -}; - -/* setup for devices (may be called multiple times -- not just first setup) */ -static int bfin_spi_setup(struct spi_device *spi) -{ - struct bfin5xx_spi_chip *chip_info; - struct bfin_spi_slave_data *chip = NULL; - struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); - u16 bfin_ctl_reg; - int ret = -EINVAL; - - /* Only alloc (or use chip_info) on first setup */ - chip_info = NULL; - chip = spi_get_ctldata(spi); - if (chip == NULL) { - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - dev_err(&spi->dev, "cannot allocate chip data\n"); - ret = -ENOMEM; - goto error; - } - - chip->enable_dma = 0; - chip_info = spi->controller_data; - } - - /* Let people set non-standard bits directly */ - bfin_ctl_reg = BIT_CTL_OPENDRAIN | BIT_CTL_EMISO | - BIT_CTL_PSSE | BIT_CTL_GM | BIT_CTL_SZ; - - /* chip_info isn't always needed */ - if (chip_info) { - /* Make sure people stop trying to set fields via ctl_reg - * when they should actually be using common SPI framework. - * Currently we let through: WOM EMISO PSSE GM SZ. - * Not sure if a user actually needs/uses any of these, - * but let's assume (for now) they do. - */ - if (chip_info->ctl_reg & ~bfin_ctl_reg) { - dev_err(&spi->dev, - "do not set bits in ctl_reg that the SPI framework manages\n"); - goto error; - } - chip->enable_dma = chip_info->enable_dma != 0 - && drv_data->master_info->enable_dma; - chip->ctl_reg = chip_info->ctl_reg; - chip->cs_chg_udelay = chip_info->cs_chg_udelay; - chip->idle_tx_val = chip_info->idle_tx_val; - chip->pio_interrupt = chip_info->pio_interrupt; - } else { - /* force a default base state */ - chip->ctl_reg &= bfin_ctl_reg; - } - - /* translate common spi framework into our register */ - if (spi->mode & SPI_CPOL) - chip->ctl_reg |= BIT_CTL_CPOL; - if (spi->mode & SPI_CPHA) - chip->ctl_reg |= BIT_CTL_CPHA; - if (spi->mode & SPI_LSB_FIRST) - chip->ctl_reg |= BIT_CTL_LSBF; - /* we dont support running in slave mode (yet?) */ - chip->ctl_reg |= BIT_CTL_MASTER; - - /* - * Notice: for blackfin, the speed_hz is the value of register - * SPI_BAUD, not the real baudrate - */ - chip->baud = hz_to_spi_baud(spi->max_speed_hz); - chip->chip_select_num = spi->chip_select; - if (chip->chip_select_num < MAX_CTRL_CS) { - if (!(spi->mode & SPI_CPHA)) - dev_warn(&spi->dev, - "Warning: SPI CPHA not set: Slave Select not under software control!\n" - "See Documentation/blackfin/bfin-spi-notes.txt\n"); - - chip->flag = (1 << spi->chip_select) << 8; - } else - chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS; - - if (chip->enable_dma && chip->pio_interrupt) { - dev_err(&spi->dev, - "enable_dma is set, do not set pio_interrupt\n"); - goto error; - } - /* - * if any one SPI chip is registered and wants DMA, request the - * DMA channel for it - */ - if (chip->enable_dma && !drv_data->dma_requested) { - /* register dma irq handler */ - ret = request_dma(drv_data->dma_channel, "BFIN_SPI_DMA"); - if (ret) { - dev_err(&spi->dev, - "Unable to request BlackFin SPI DMA channel\n"); - goto error; - } - drv_data->dma_requested = 1; - - ret = set_dma_callback(drv_data->dma_channel, - bfin_spi_dma_irq_handler, drv_data); - if (ret) { - dev_err(&spi->dev, "Unable to set dma callback\n"); - goto error; - } - dma_disable_irq(drv_data->dma_channel); - } - - if (chip->pio_interrupt && !drv_data->irq_requested) { - ret = request_irq(drv_data->spi_irq, bfin_spi_pio_irq_handler, - 0, "BFIN_SPI", drv_data); - if (ret) { - dev_err(&spi->dev, "Unable to register spi IRQ\n"); - goto error; - } - drv_data->irq_requested = 1; - /* we use write mode, spi irq has to be disabled here */ - disable_irq(drv_data->spi_irq); - } - - if (chip->chip_select_num >= MAX_CTRL_CS) { - /* Only request on first setup */ - if (spi_get_ctldata(spi) == NULL) { - ret = gpio_request(chip->cs_gpio, spi->modalias); - if (ret) { - dev_err(&spi->dev, "gpio_request() error\n"); - goto pin_error; - } - gpio_direction_output(chip->cs_gpio, 1); - } - } - - dev_dbg(&spi->dev, "setup spi chip %s, width is %d, dma is %d\n", - spi->modalias, spi->bits_per_word, chip->enable_dma); - dev_dbg(&spi->dev, "ctl_reg is 0x%x, flag_reg is 0x%x\n", - chip->ctl_reg, chip->flag); - - spi_set_ctldata(spi, chip); - - dev_dbg(&spi->dev, "chip select number is %d\n", chip->chip_select_num); - if (chip->chip_select_num < MAX_CTRL_CS) { - ret = peripheral_request(ssel[spi->master->bus_num] - [chip->chip_select_num-1], spi->modalias); - if (ret) { - dev_err(&spi->dev, "peripheral_request() error\n"); - goto pin_error; - } - } - - bfin_spi_cs_enable(drv_data, chip); - bfin_spi_cs_deactive(drv_data, chip); - - return 0; - - pin_error: - if (chip->chip_select_num >= MAX_CTRL_CS) - gpio_free(chip->cs_gpio); - else - peripheral_free(ssel[spi->master->bus_num] - [chip->chip_select_num - 1]); - error: - if (chip) { - if (drv_data->dma_requested) - free_dma(drv_data->dma_channel); - drv_data->dma_requested = 0; - - kfree(chip); - /* prevent free 'chip' twice */ - spi_set_ctldata(spi, NULL); - } - - return ret; -} - -/* - * callback for spi framework. - * clean driver specific data - */ -static void bfin_spi_cleanup(struct spi_device *spi) -{ - struct bfin_spi_slave_data *chip = spi_get_ctldata(spi); - struct bfin_spi_master_data *drv_data = spi_master_get_devdata(spi->master); - - if (!chip) - return; - - if (chip->chip_select_num < MAX_CTRL_CS) { - peripheral_free(ssel[spi->master->bus_num] - [chip->chip_select_num-1]); - bfin_spi_cs_disable(drv_data, chip); - } else - gpio_free(chip->cs_gpio); - - kfree(chip); - /* prevent free 'chip' twice */ - spi_set_ctldata(spi, NULL); -} - -static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) -{ - INIT_LIST_HEAD(&drv_data->queue); - spin_lock_init(&drv_data->lock); - - drv_data->running = false; - drv_data->busy = 0; - - /* init transfer tasklet */ - tasklet_init(&drv_data->pump_transfers, - bfin_spi_pump_transfers, (unsigned long)drv_data); - - INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages); - - return 0; -} - -static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) -{ - unsigned long flags; - - spin_lock_irqsave(&drv_data->lock, flags); - - if (drv_data->running || drv_data->busy) { - spin_unlock_irqrestore(&drv_data->lock, flags); - return -EBUSY; - } - - drv_data->running = true; - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - spin_unlock_irqrestore(&drv_data->lock, flags); - - schedule_work(&drv_data->pump_messages); - - return 0; -} - -static int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data) -{ - unsigned long flags; - unsigned limit = 500; - int status = 0; - - spin_lock_irqsave(&drv_data->lock, flags); - - /* - * This is a bit lame, but is optimized for the common execution path. - * A wait_queue on the drv_data->busy could be used, but then the common - * execution path (pump_messages) would be required to call wake_up or - * friends on every SPI message. Do this instead - */ - drv_data->running = false; - while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) { - spin_unlock_irqrestore(&drv_data->lock, flags); - msleep(10); - spin_lock_irqsave(&drv_data->lock, flags); - } - - if (!list_empty(&drv_data->queue) || drv_data->busy) - status = -EBUSY; - - spin_unlock_irqrestore(&drv_data->lock, flags); - - return status; -} - -static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) -{ - int status; - - status = bfin_spi_stop_queue(drv_data); - if (status != 0) - return status; - - flush_work(&drv_data->pump_messages); - - return 0; -} - -static int bfin_spi_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct bfin5xx_spi_master *platform_info; - struct spi_master *master; - struct bfin_spi_master_data *drv_data; - struct resource *res; - int status = 0; - - platform_info = dev_get_platdata(dev); - - /* Allocate master with space for drv_data */ - master = spi_alloc_master(dev, sizeof(*drv_data)); - if (!master) { - dev_err(&pdev->dev, "can not alloc spi_master\n"); - return -ENOMEM; - } - - drv_data = spi_master_get_devdata(master); - drv_data->master = master; - drv_data->master_info = platform_info; - drv_data->pdev = pdev; - drv_data->pin_req = platform_info->pin_req; - - /* the spi->mode bits supported by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); - master->bus_num = pdev->id; - master->num_chipselect = platform_info->num_chipselect; - master->cleanup = bfin_spi_cleanup; - master->setup = bfin_spi_setup; - master->transfer = bfin_spi_transfer; - - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(dev, "Cannot get IORESOURCE_MEM\n"); - status = -ENOENT; - goto out_error_get_res; - } - - drv_data->regs = ioremap(res->start, resource_size(res)); - if (drv_data->regs == NULL) { - dev_err(dev, "Cannot map IO\n"); - status = -ENXIO; - goto out_error_ioremap; - } - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res == NULL) { - dev_err(dev, "No DMA channel specified\n"); - status = -ENOENT; - goto out_error_free_io; - } - drv_data->dma_channel = res->start; - - drv_data->spi_irq = platform_get_irq(pdev, 0); - if (drv_data->spi_irq < 0) { - dev_err(dev, "No spi pio irq specified\n"); - status = -ENOENT; - goto out_error_free_io; - } - - /* Initial and start queue */ - status = bfin_spi_init_queue(drv_data); - if (status != 0) { - dev_err(dev, "problem initializing queue\n"); - goto out_error_queue_alloc; - } - - status = bfin_spi_start_queue(drv_data); - if (status != 0) { - dev_err(dev, "problem starting queue\n"); - goto out_error_queue_alloc; - } - - status = peripheral_request_list(drv_data->pin_req, DRV_NAME); - if (status != 0) { - dev_err(&pdev->dev, ": Requesting Peripherals failed\n"); - goto out_error_queue_alloc; - } - - /* Reset SPI registers. If these registers were used by the boot loader, - * the sky may fall on your head if you enable the dma controller. - */ - bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER); - bfin_write(&drv_data->regs->flg, 0xFF00); - - /* Register with the SPI framework */ - platform_set_drvdata(pdev, drv_data); - status = spi_register_master(master); - if (status != 0) { - dev_err(dev, "problem registering spi master\n"); - goto out_error_queue_alloc; - } - - dev_info(dev, "%s, Version %s, regs@%p, dma channel@%d\n", - DRV_DESC, DRV_VERSION, drv_data->regs, - drv_data->dma_channel); - return status; - -out_error_queue_alloc: - bfin_spi_destroy_queue(drv_data); -out_error_free_io: - iounmap(drv_data->regs); -out_error_ioremap: -out_error_get_res: - spi_master_put(master); - - return status; -} - -/* stop hardware and remove the driver */ -static int bfin_spi_remove(struct platform_device *pdev) -{ - struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev); - int status = 0; - - if (!drv_data) - return 0; - - /* Remove the queue */ - status = bfin_spi_destroy_queue(drv_data); - if (status != 0) - return status; - - /* Disable the SSP at the peripheral and SOC level */ - bfin_spi_disable(drv_data); - - /* Release DMA */ - if (drv_data->master_info->enable_dma) { - if (dma_channel_active(drv_data->dma_channel)) - free_dma(drv_data->dma_channel); - } - - if (drv_data->irq_requested) { - free_irq(drv_data->spi_irq, drv_data); - drv_data->irq_requested = 0; - } - - /* Disconnect from the SPI framework */ - spi_unregister_master(drv_data->master); - - peripheral_free_list(drv_data->pin_req); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int bfin_spi_suspend(struct device *dev) -{ - struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev); - int status = 0; - - status = bfin_spi_stop_queue(drv_data); - if (status != 0) - return status; - - drv_data->ctrl_reg = bfin_read(&drv_data->regs->ctl); - drv_data->flag_reg = bfin_read(&drv_data->regs->flg); - - /* - * reset SPI_CTL and SPI_FLG registers - */ - bfin_write(&drv_data->regs->ctl, BIT_CTL_CPHA | BIT_CTL_MASTER); - bfin_write(&drv_data->regs->flg, 0xFF00); - - return 0; -} - -static int bfin_spi_resume(struct device *dev) -{ - struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev); - int status = 0; - - bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg); - bfin_write(&drv_data->regs->flg, drv_data->flag_reg); - - /* Start the queue running */ - status = bfin_spi_start_queue(drv_data); - if (status != 0) { - dev_err(dev, "problem starting queue (%d)\n", status); - return status; - } - - return 0; -} - -static SIMPLE_DEV_PM_OPS(bfin_spi_pm_ops, bfin_spi_suspend, bfin_spi_resume); - -#define BFIN_SPI_PM_OPS (&bfin_spi_pm_ops) -#else -#define BFIN_SPI_PM_OPS NULL -#endif - -MODULE_ALIAS("platform:bfin-spi"); -static struct platform_driver bfin_spi_driver = { - .driver = { - .name = DRV_NAME, - .pm = BFIN_SPI_PM_OPS, - }, - .probe = bfin_spi_probe, - .remove = bfin_spi_remove, -}; - -static int __init bfin_spi_init(void) -{ - return platform_driver_register(&bfin_spi_driver); -} -subsys_initcall(bfin_spi_init); - -static void __exit bfin_spi_exit(void) -{ - platform_driver_unregister(&bfin_spi_driver); -} -module_exit(bfin_spi_exit); diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index 8abc1ab3c0c7..bd9445956511 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -14,6 +14,5 @@ source "drivers/staging/iio/impedance-analyzer/Kconfig" source "drivers/staging/iio/light/Kconfig" source "drivers/staging/iio/meter/Kconfig" source "drivers/staging/iio/resolver/Kconfig" -source "drivers/staging/iio/trigger/Kconfig" endmenu diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 455bffc29649..e99a375c07b9 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -13,4 +13,3 @@ obj-y += impedance-analyzer/ obj-y += light/ obj-y += meter/ obj-y += resolver/ -obj-y += trigger/ diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig deleted file mode 100644 index 0b01d24cea51..000000000000 --- a/drivers/staging/iio/trigger/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ - # -# Industrial I/O standalone triggers -# -comment "Triggers - standalone" - -if IIO_TRIGGER - -config IIO_BFIN_TMR_TRIGGER - tristate "Blackfin TIMER trigger" - depends on BLACKFIN - select BFIN_GPTIMERS - help - Provides support for using a Blackfin timer as IIO triggers. - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called iio-trig-bfin-timer. - -endif # IIO_TRIGGER diff --git a/drivers/staging/iio/trigger/Makefile b/drivers/staging/iio/trigger/Makefile deleted file mode 100644 index 1300a21363db..000000000000 --- a/drivers/staging/iio/trigger/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for triggers not associated with iio-devices -# - -obj-$(CONFIG_IIO_BFIN_TMR_TRIGGER) += iio-trig-bfin-timer.o diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c deleted file mode 100644 index 71f11d7472c0..000000000000 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/delay.h> - -#include <asm/gptimers.h> -#include <asm/portmux.h> - -#include <linux/iio/iio.h> -#include <linux/iio/trigger.h> - -#include "iio-trig-bfin-timer.h" - -struct bfin_timer { - unsigned short id, bit; - unsigned long irqbit; - int irq; - int pin; -}; - -/* - * this covers all hardware timer configurations on - * all Blackfin derivatives out there today - */ - -static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = { - {TIMER0_id, TIMER0bit, TIMER_STATUS_TIMIL0, IRQ_TIMER0, P_TMR0}, - {TIMER1_id, TIMER1bit, TIMER_STATUS_TIMIL1, IRQ_TIMER1, P_TMR1}, - {TIMER2_id, TIMER2bit, TIMER_STATUS_TIMIL2, IRQ_TIMER2, P_TMR2}, -#if (MAX_BLACKFIN_GPTIMERS > 3) - {TIMER3_id, TIMER3bit, TIMER_STATUS_TIMIL3, IRQ_TIMER3, P_TMR3}, - {TIMER4_id, TIMER4bit, TIMER_STATUS_TIMIL4, IRQ_TIMER4, P_TMR4}, - {TIMER5_id, TIMER5bit, TIMER_STATUS_TIMIL5, IRQ_TIMER5, P_TMR5}, - {TIMER6_id, TIMER6bit, TIMER_STATUS_TIMIL6, IRQ_TIMER6, P_TMR6}, - {TIMER7_id, TIMER7bit, TIMER_STATUS_TIMIL7, IRQ_TIMER7, P_TMR7}, -#endif -#if (MAX_BLACKFIN_GPTIMERS > 8) - {TIMER8_id, TIMER8bit, TIMER_STATUS_TIMIL8, IRQ_TIMER8, P_TMR8}, - {TIMER9_id, TIMER9bit, TIMER_STATUS_TIMIL9, IRQ_TIMER9, P_TMR9}, - {TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10, P_TMR10}, -#if (MAX_BLACKFIN_GPTIMERS > 11) - {TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11, P_TMR11}, -#endif -#endif -}; - -struct bfin_tmr_state { - struct iio_trigger *trig; - struct bfin_timer *t; - unsigned int timer_num; - bool output_enable; - unsigned int duty; - int irq; -}; - -static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state) -{ - struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); - - if (get_gptimer_period(st->t->id) == 0) - return -EINVAL; - - if (state) - enable_gptimers(st->t->bit); - else - disable_gptimers(st->t->bit); - - return 0; -} - -static ssize_t frequency_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iio_trigger *trig = to_iio_trigger(dev); - struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); - unsigned int val; - bool enabled; - int ret; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - if (val > 100000) - return -EINVAL; - - enabled = get_enabled_gptimers() & st->t->bit; - - if (enabled) - disable_gptimers(st->t->bit); - - if (!val) - return count; - - val = get_sclk() / val; - if (val <= 4 || val <= st->duty) - return -EINVAL; - - set_gptimer_period(st->t->id, val); - set_gptimer_pwidth(st->t->id, val - st->duty); - - if (enabled) - enable_gptimers(st->t->bit); - - return count; -} - -static ssize_t frequency_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_trigger *trig = to_iio_trigger(dev); - struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig); - unsigned int period = get_gptimer_period(st->t->id); - unsigned long val; - - if (!period) - val = 0; - else - val = get_sclk() / get_gptimer_period(st->t->id); - - return sprintf(buf, "%lu\n", val); -} - -static DEVICE_ATTR_RW(frequency); - -static struct attribute *iio_bfin_tmr_trigger_attrs[] = { - &dev_attr_frequency.attr, - NULL, -}; - -static const struct attribute_group iio_bfin_tmr_trigger_attr_group = { - .attrs = iio_bfin_tmr_trigger_attrs, -}; - -static const struct attribute_group *iio_bfin_tmr_trigger_attr_groups[] = { - &iio_bfin_tmr_trigger_attr_group, - NULL -}; - -static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid) -{ - struct bfin_tmr_state *st = devid; - - clear_gptimer_intr(st->t->id); - iio_trigger_poll(st->trig); - - return IRQ_HANDLED; -} - -static int iio_bfin_tmr_get_number(int irq) -{ - int i; - - for (i = 0; i < MAX_BLACKFIN_GPTIMERS; i++) - if (iio_bfin_timer_code[i].irq == irq) - return i; - - return -ENODEV; -} - -static const struct iio_trigger_ops iio_bfin_tmr_trigger_ops = { - .set_trigger_state = iio_bfin_tmr_set_state, -}; - -static int iio_bfin_tmr_trigger_probe(struct platform_device *pdev) -{ - struct iio_bfin_timer_trigger_pdata *pdata; - struct bfin_tmr_state *st; - unsigned int config; - int ret; - - st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); - if (!st) - return -ENOMEM; - - st->irq = platform_get_irq(pdev, 0); - if (st->irq < 0) { - dev_err(&pdev->dev, "No IRQs specified"); - return st->irq; - } - - ret = iio_bfin_tmr_get_number(st->irq); - if (ret < 0) - return ret; - - st->timer_num = ret; - st->t = &iio_bfin_timer_code[st->timer_num]; - - st->trig = iio_trigger_alloc("bfintmr%d", st->timer_num); - if (!st->trig) - return -ENOMEM; - - st->trig->ops = &iio_bfin_tmr_trigger_ops; - st->trig->dev.groups = iio_bfin_tmr_trigger_attr_groups; - iio_trigger_set_drvdata(st->trig, st); - ret = iio_trigger_register(st->trig); - if (ret) - goto out; - - ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr, - 0, st->trig->name, st); - if (ret) { - dev_err(&pdev->dev, - "request IRQ-%d failed", st->irq); - goto out1; - } - - config = PWM_OUT | PERIOD_CNT | IRQ_ENA; - - pdata = dev_get_platdata(&pdev->dev); - if (pdata && pdata->output_enable) { - unsigned long long val; - - st->output_enable = true; - - ret = peripheral_request(st->t->pin, st->trig->name); - if (ret) - goto out_free_irq; - - val = (unsigned long long)get_sclk() * pdata->duty_ns; - do_div(val, NSEC_PER_SEC); - st->duty = val; - - /** - * The interrupt will be generated at the end of the period, - * since we want the interrupt to be generated at end of the - * pulse we invert both polarity and duty cycle, so that the - * pulse will be generated directly before the interrupt. - */ - if (pdata->active_low) - config |= PULSE_HI; - } else { - st->duty = 1; - config |= OUT_DIS; - } - - set_gptimer_config(st->t->id, config); - - dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d", - st->timer_num, st->irq); - platform_set_drvdata(pdev, st); - - return 0; -out_free_irq: - free_irq(st->irq, st); -out1: - iio_trigger_unregister(st->trig); -out: - iio_trigger_free(st->trig); - return ret; -} - -static int iio_bfin_tmr_trigger_remove(struct platform_device *pdev) -{ - struct bfin_tmr_state *st = platform_get_drvdata(pdev); - - disable_gptimers(st->t->bit); - if (st->output_enable) - peripheral_free(st->t->pin); - free_irq(st->irq, st); - iio_trigger_unregister(st->trig); - iio_trigger_free(st->trig); - - return 0; -} - -static struct platform_driver iio_bfin_tmr_trigger_driver = { - .driver = { - .name = "iio_bfin_tmr_trigger", - }, - .probe = iio_bfin_tmr_trigger_probe, - .remove = iio_bfin_tmr_trigger_remove, -}; - -module_platform_driver(iio_bfin_tmr_trigger_driver); - -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Blackfin system timer based trigger for the iio subsystem"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:iio-trig-bfin-timer"); diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.h b/drivers/staging/iio/trigger/iio-trig-bfin-timer.h deleted file mode 100644 index fb05a2a8397c..000000000000 --- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IIO_BFIN_TIMER_TRIGGER_H__ -#define __IIO_BFIN_TIMER_TRIGGER_H__ - -/** - * struct iio_bfin_timer_trigger_pdata - timer trigger platform data - * @output_enable: Enable external trigger pulse generation. - * @active_low: Whether the trigger pulse is active low. - * @duty_ns: Length of the trigger pulse in nanoseconds. - * - * This struct is used to configure the output pulse generation of the blackfin - * timer trigger. If output_enable is set to true an external trigger signal - * will generated on the pin corresponding to the timer. This is useful for - * converters which needs an external signal to start conversion. active_low and - * duty_ns are used to configure the type of the trigger pulse. If output_enable - * is set to false no external trigger pulse will be generated and active_low - * and duty_ns are ignored. - **/ -struct iio_bfin_timer_trigger_pdata { - bool output_enable; - bool active_low; - unsigned int duty_ns; -}; - -#endif diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig index 7e8037e230b8..efd6f4560d3e 100644 --- a/drivers/staging/speakup/Kconfig +++ b/drivers/staging/speakup/Kconfig @@ -1,7 +1,7 @@ menu "Speakup console speech" config SPEAKUP - depends on VT && !MN10300 + depends on VT tristate "Speakup core" ---help--- This is the Speakup screen reader. Think of it as a diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index b811442c5ce6..e5041c605fd0 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -151,19 +151,6 @@ config LEGACY_PTY_COUNT When not in use, each legacy PTY occupies 12 bytes on 32-bit architectures and 24 bytes on 64-bit architectures. -config BFIN_JTAG_COMM - tristate "Blackfin JTAG Communication" - depends on BLACKFIN - help - Add support for emulating a TTY device over the Blackfin JTAG. - - To compile this driver as a module, choose M here: the - module will be called bfin_jtag_comm. - -config BFIN_JTAG_COMM_CONSOLE - bool "Console on Blackfin JTAG" - depends on BFIN_JTAG_COMM=y - config SERIAL_NONSTANDARD bool "Non-standard serial port support" depends on HAS_IOMEM @@ -402,19 +389,6 @@ config GOLDFISH_TTY_EARLY_CONSOLE default y if GOLDFISH_TTY=y select SERIAL_EARLYCON -config DA_TTY - bool "DA TTY" - depends on METAG_DA - select SERIAL_NONSTANDARD - help - This enables a TTY on a Dash channel. - -config DA_CONSOLE - bool "DA Console" - depends on DA_TTY - help - This enables a console on a Dash channel. - config MIPS_EJTAG_FDC_TTY bool "MIPS EJTAG Fast Debug Channel TTY" depends on MIPS_CDMM diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index 8ce3a8661b31..c72cafdf32b4 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile @@ -20,7 +20,6 @@ obj-$(CONFIG_SERIAL_DEV_BUS) += serdev/ # tty drivers obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o -obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o obj-$(CONFIG_CYCLADES) += cyclades.o obj-$(CONFIG_ISI) += isicom.o obj-$(CONFIG_MOXA_INTELLIO) += moxa.o @@ -32,7 +31,6 @@ obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o obj-$(CONFIG_SYNCLINK) += synclink.o obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o -obj-$(CONFIG_DA_TTY) += metag_da.o obj-$(CONFIG_MIPS_EJTAG_FDC_TTY) += mips_ejtag_fdc.o obj-$(CONFIG_VCC) += vcc.o diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c deleted file mode 100644 index c369bf27a67b..000000000000 --- a/drivers/tty/bfin_jtag_comm.c +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * TTY over Blackfin JTAG Communication - * - * Copyright 2008-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -#define DRV_NAME "bfin-jtag-comm" -#define DEV_NAME "ttyBFJC" -#define pr_fmt(fmt) DRV_NAME ": " fmt - -#include <linux/circ_buf.h> -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/kthread.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/atomic.h> - -#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) - -/* See the Debug/Emulation chapter in the HRM */ -#define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ -#define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ -#define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ -#define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ - -static inline uint32_t bfin_write_emudat(uint32_t emudat) -{ - __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_read_emudat(void) -{ - uint32_t emudat; - __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d) -{ - return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24)); -} - -#define CIRC_SIZE 2048 /* see comment in tty_io.c:do_tty_write() */ -#define CIRC_MASK (CIRC_SIZE - 1) -#define circ_empty(circ) ((circ)->head == (circ)->tail) -#define circ_free(circ) CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE) -#define circ_cnt(circ) CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE) -#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK]) - -static struct tty_driver *bfin_jc_driver; -static struct task_struct *bfin_jc_kthread; -static struct tty_port port; -static volatile struct circ_buf bfin_jc_write_buf; - -static int -bfin_jc_emudat_manager(void *arg) -{ - uint32_t inbound_len = 0, outbound_len = 0; - - while (!kthread_should_stop()) { - struct tty_struct *tty = tty_port_tty_get(&port); - /* no one left to give data to, so sleep */ - if (tty == NULL && circ_empty(&bfin_jc_write_buf)) { - pr_debug("waiting for readers\n"); - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule(); - continue; - } - - /* no data available, so just chill */ - if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) { - pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n", - inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head); - tty_kref_put(tty); - if (inbound_len) - schedule(); - else - schedule_timeout_interruptible(HZ); - continue; - } - - /* if incoming data is ready, eat it */ - if (bfin_read_DBGSTAT() & EMUDIF) { - uint32_t emudat = bfin_read_emudat(); - if (inbound_len == 0) { - pr_debug("incoming length: 0x%08x\n", emudat); - inbound_len = emudat; - } else { - size_t num_chars = (4 <= inbound_len ? 4 : inbound_len); - pr_debug(" incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars); - inbound_len -= num_chars; - tty_insert_flip_string(&port, (unsigned char *)&emudat, num_chars); - tty_flip_buffer_push(&port); - } - } - - /* if outgoing data is ready, post it */ - if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) { - if (outbound_len == 0) { - outbound_len = circ_cnt(&bfin_jc_write_buf); - bfin_write_emudat(outbound_len); - pr_debug("outgoing length: 0x%08x\n", outbound_len); - } else { - int tail = bfin_jc_write_buf.tail; - size_t ate = (4 <= outbound_len ? 4 : outbound_len); - uint32_t emudat = - bfin_write_emudat_chars( - circ_byte(&bfin_jc_write_buf, tail + 0), - circ_byte(&bfin_jc_write_buf, tail + 1), - circ_byte(&bfin_jc_write_buf, tail + 2), - circ_byte(&bfin_jc_write_buf, tail + 3) - ); - bfin_jc_write_buf.tail += ate; - outbound_len -= ate; - if (tty) - tty_wakeup(tty); - pr_debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate); - } - } - tty_kref_put(tty); - } - - __set_current_state(TASK_RUNNING); - return 0; -} - -static int -bfin_jc_open(struct tty_struct *tty, struct file *filp) -{ - unsigned long flags; - - spin_lock_irqsave(&port.lock, flags); - port.count++; - spin_unlock_irqrestore(&port.lock, flags); - tty_port_tty_set(&port, tty); - wake_up_process(bfin_jc_kthread); - return 0; -} - -static void -bfin_jc_close(struct tty_struct *tty, struct file *filp) -{ - unsigned long flags; - bool last; - - spin_lock_irqsave(&port.lock, flags); - last = --port.count == 0; - spin_unlock_irqrestore(&port.lock, flags); - if (last) - tty_port_tty_set(&port, NULL); - wake_up_process(bfin_jc_kthread); -} - -/* XXX: we dont handle the put_char() case where we must handle count = 1 */ -static int -bfin_jc_circ_write(const unsigned char *buf, int count) -{ - int i; - count = min(count, circ_free(&bfin_jc_write_buf)); - pr_debug("going to write chunk of %i bytes\n", count); - for (i = 0; i < count; ++i) - circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i]; - bfin_jc_write_buf.head += i; - return i; -} - -#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE -# define console_lock() -# define console_unlock() -#endif -static int -bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - int i; - console_lock(); - i = bfin_jc_circ_write(buf, count); - console_unlock(); - wake_up_process(bfin_jc_kthread); - return i; -} - -static void -bfin_jc_flush_chars(struct tty_struct *tty) -{ - wake_up_process(bfin_jc_kthread); -} - -static int -bfin_jc_write_room(struct tty_struct *tty) -{ - return circ_free(&bfin_jc_write_buf); -} - -static int -bfin_jc_chars_in_buffer(struct tty_struct *tty) -{ - return circ_cnt(&bfin_jc_write_buf); -} - -static const struct tty_operations bfin_jc_ops = { - .open = bfin_jc_open, - .close = bfin_jc_close, - .write = bfin_jc_write, - /*.put_char = bfin_jc_put_char,*/ - .flush_chars = bfin_jc_flush_chars, - .write_room = bfin_jc_write_room, - .chars_in_buffer = bfin_jc_chars_in_buffer, -}; - -static int __init bfin_jc_init(void) -{ - int ret; - - bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); - if (IS_ERR(bfin_jc_kthread)) - return PTR_ERR(bfin_jc_kthread); - - ret = -ENOMEM; - - bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0; - bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL); - if (!bfin_jc_write_buf.buf) - goto err_buf; - - bfin_jc_driver = alloc_tty_driver(1); - if (!bfin_jc_driver) - goto err_driver; - - tty_port_init(&port); - - bfin_jc_driver->driver_name = DRV_NAME; - bfin_jc_driver->name = DEV_NAME; - bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; - bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; - bfin_jc_driver->init_termios = tty_std_termios; - tty_set_operations(bfin_jc_driver, &bfin_jc_ops); - tty_port_link_device(&port, bfin_jc_driver, 0); - - ret = tty_register_driver(bfin_jc_driver); - if (ret) - goto err; - - pr_init(KERN_INFO DRV_NAME ": initialized\n"); - - return 0; - - err: - tty_port_destroy(&port); - put_tty_driver(bfin_jc_driver); - err_driver: - kfree(bfin_jc_write_buf.buf); - err_buf: - kthread_stop(bfin_jc_kthread); - return ret; -} -module_init(bfin_jc_init); - -static void __exit bfin_jc_exit(void) -{ - kthread_stop(bfin_jc_kthread); - kfree(bfin_jc_write_buf.buf); - tty_unregister_driver(bfin_jc_driver); - put_tty_driver(bfin_jc_driver); - tty_port_destroy(&port); -} -module_exit(bfin_jc_exit); - -#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK) -static void -bfin_jc_straight_buffer_write(const char *buf, unsigned count) -{ - unsigned ate = 0; - while (bfin_read_DBGSTAT() & EMUDOF) - continue; - bfin_write_emudat(count); - while (ate < count) { - while (bfin_read_DBGSTAT() & EMUDOF) - continue; - bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]); - ate += 4; - } -} -#endif - -#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE -static void -bfin_jc_console_write(struct console *co, const char *buf, unsigned count) -{ - if (bfin_jc_kthread == NULL) - bfin_jc_straight_buffer_write(buf, count); - else - bfin_jc_circ_write(buf, count); -} - -static struct tty_driver * -bfin_jc_console_device(struct console *co, int *index) -{ - *index = co->index; - return bfin_jc_driver; -} - -static struct console bfin_jc_console = { - .name = DEV_NAME, - .write = bfin_jc_console_write, - .device = bfin_jc_console_device, - .flags = CON_ANYTIME | CON_PRINTBUFFER, - .index = -1, -}; - -static int __init bfin_jc_console_init(void) -{ - register_console(&bfin_jc_console); - return 0; -} -console_initcall(bfin_jc_console_init); -#endif - -#ifdef CONFIG_EARLY_PRINTK -static void __init -bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) -{ - bfin_jc_straight_buffer_write(buf, count); -} - -static struct console bfin_jc_early_console __initdata = { - .name = "early_BFJC", - .write = bfin_jc_early_write, - .flags = CON_ANYTIME | CON_PRINTBUFFER, - .index = -1, -}; - -struct console * __init -bfin_jc_early_init(unsigned int port, unsigned int cflag) -{ - return &bfin_jc_early_console; -} -#endif - -MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); -MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication"); -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig index fec457edad14..3bade5ad3d71 100644 --- a/drivers/tty/hvc/Kconfig +++ b/drivers/tty/hvc/Kconfig @@ -88,15 +88,6 @@ config HVC_DCC driver. This console is used through a JTAG only on ARM. If you don't have a JTAG then you probably don't want this option. -config HVC_BFIN_JTAG - bool "Blackfin JTAG console" - depends on BLACKFIN - select HVC_DRIVER - help - This console uses the Blackfin JTAG to create a console under the - the HVC driver. If you don't have JTAG, then you probably don't - want this option. - config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES && HVC_CONSOLE diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile index 0b02ec7f1dfd..7da1934d34e8 100644 --- a/drivers/tty/hvc/Makefile +++ b/drivers/tty/hvc/Makefile @@ -3,12 +3,10 @@ obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi_lib.o obj-$(CONFIG_HVC_OPAL) += hvc_opal.o hvsi_lib.o obj-$(CONFIG_HVC_OLD_HVSI) += hvsi.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o -obj-$(CONFIG_HVC_TILE) += hvc_tile.o obj-$(CONFIG_HVC_DCC) += hvc_dcc.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_HVC_IRQ) += hvc_irq.o obj-$(CONFIG_HVC_XEN) += hvc_xen.o obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o -obj-$(CONFIG_HVC_BFIN_JTAG) += hvc_bfin_jtag.o obj-$(CONFIG_HVCS) += hvcs.o diff --git a/drivers/tty/hvc/hvc_bfin_jtag.c b/drivers/tty/hvc/hvc_bfin_jtag.c deleted file mode 100644 index dd7cae4c195b..000000000000 --- a/drivers/tty/hvc/hvc_bfin_jtag.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Console via Blackfin JTAG Communication - * - * Copyright 2008-2011 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/moduleparam.h> -#include <linux/types.h> - -#include "hvc_console.h" - -/* See the Debug/Emulation chapter in the HRM */ -#define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ -#define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ -#define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ -#define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ - -/* Helper functions to glue the register API to simple C operations */ -static inline uint32_t bfin_write_emudat(uint32_t emudat) -{ - __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); - return emudat; -} - -static inline uint32_t bfin_read_emudat(void) -{ - uint32_t emudat; - __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); - return emudat; -} - -/* Send data to the host */ -static int hvc_bfin_put_chars(uint32_t vt, const char *buf, int count) -{ - static uint32_t outbound_len; - uint32_t emudat; - int ret; - - if (bfin_read_DBGSTAT() & EMUDOF) - return 0; - - if (!outbound_len) { - outbound_len = count; - bfin_write_emudat(outbound_len); - return 0; - } - - ret = min(outbound_len, (uint32_t)4); - memcpy(&emudat, buf, ret); - bfin_write_emudat(emudat); - outbound_len -= ret; - - return ret; -} - -/* Receive data from the host */ -static int hvc_bfin_get_chars(uint32_t vt, char *buf, int count) -{ - static uint32_t inbound_len; - uint32_t emudat; - int ret; - - if (!(bfin_read_DBGSTAT() & EMUDIF)) - return 0; - emudat = bfin_read_emudat(); - - if (!inbound_len) { - inbound_len = emudat; - return 0; - } - - ret = min(inbound_len, (uint32_t)4); - memcpy(buf, &emudat, ret); - inbound_len -= ret; - - return ret; -} - -/* Glue the HVC layers to the Blackfin layers */ -static const struct hv_ops hvc_bfin_get_put_ops = { - .get_chars = hvc_bfin_get_chars, - .put_chars = hvc_bfin_put_chars, -}; - -static int __init hvc_bfin_console_init(void) -{ - hvc_instantiate(0, 0, &hvc_bfin_get_put_ops); - return 0; -} -console_initcall(hvc_bfin_console_init); - -static int __init hvc_bfin_init(void) -{ - hvc_alloc(0, 0, &hvc_bfin_get_put_ops, 128); - return 0; -} -device_initcall(hvc_bfin_init); diff --git a/drivers/tty/hvc/hvc_tile.c b/drivers/tty/hvc/hvc_tile.c deleted file mode 100644 index b517c0661abb..000000000000 --- a/drivers/tty/hvc/hvc_tile.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2010 Tilera Corporation. All Rights Reserved. - * - * Tilera TILE Processor hypervisor console - */ - -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/moduleparam.h> -#include <linux/platform_device.h> -#include <linux/types.h> - -#include <asm/setup.h> -#include <arch/sim_def.h> - -#include <hv/hypervisor.h> - -#include "hvc_console.h" - -static int use_sim_console; -static int __init sim_console(char *str) -{ - use_sim_console = 1; - return 0; -} -early_param("sim_console", sim_console); - -int tile_console_write(const char *buf, int count) -{ - if (unlikely(use_sim_console)) { - int i; - for (i = 0; i < count; ++i) - __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC | - (buf[i] << _SIM_CONTROL_OPERATOR_BITS)); - __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC | - (SIM_PUTC_FLUSH_BINARY << - _SIM_CONTROL_OPERATOR_BITS)); - return 0; - } else { - /* Translate 0 bytes written to EAGAIN for hvc_console_print. */ - return hv_console_write((HV_VirtAddr)buf, count) ?: -EAGAIN; - } -} - -static int hvc_tile_put_chars(uint32_t vt, const char *buf, int count) -{ - return tile_console_write(buf, count); -} - -static int hvc_tile_get_chars(uint32_t vt, char *buf, int count) -{ - int i, c; - - for (i = 0; i < count; ++i) { - c = hv_console_read_if_ready(); - if (c < 0) - break; - buf[i] = c; - } - - return i; -} - -#ifdef __tilegx__ -/* - * IRQ based callbacks. - */ -static int hvc_tile_notifier_add_irq(struct hvc_struct *hp, int irq) -{ - int rc; - int cpu = raw_smp_processor_id(); /* Choose an arbitrary cpu */ - HV_Coord coord = { .x = cpu_x(cpu), .y = cpu_y(cpu) }; - - rc = notifier_add_irq(hp, irq); - if (rc) - return rc; - - /* - * Request that the hypervisor start sending us interrupts. - * If the hypervisor returns an error, we still return 0, so that - * we can fall back to polling. - */ - if (hv_console_set_ipi(KERNEL_PL, irq, coord) < 0) - notifier_del_irq(hp, irq); - - return 0; -} - -static void hvc_tile_notifier_del_irq(struct hvc_struct *hp, int irq) -{ - HV_Coord coord = { 0, 0 }; - - /* Tell the hypervisor to stop sending us interrupts. */ - hv_console_set_ipi(KERNEL_PL, -1, coord); - - notifier_del_irq(hp, irq); -} - -static void hvc_tile_notifier_hangup_irq(struct hvc_struct *hp, int irq) -{ - hvc_tile_notifier_del_irq(hp, irq); -} -#endif - -static const struct hv_ops hvc_tile_get_put_ops = { - .get_chars = hvc_tile_get_chars, - .put_chars = hvc_tile_put_chars, -#ifdef __tilegx__ - .notifier_add = hvc_tile_notifier_add_irq, - .notifier_del = hvc_tile_notifier_del_irq, - .notifier_hangup = hvc_tile_notifier_hangup_irq, -#endif -}; - - -#ifdef __tilegx__ -static int hvc_tile_probe(struct platform_device *pdev) -{ - struct hvc_struct *hp; - int tile_hvc_irq; - - /* Create our IRQ and register it. */ - tile_hvc_irq = irq_alloc_hwirq(-1); - if (!tile_hvc_irq) - return -ENXIO; - - tile_irq_activate(tile_hvc_irq, TILE_IRQ_PERCPU); - hp = hvc_alloc(0, tile_hvc_irq, &hvc_tile_get_put_ops, 128); - if (IS_ERR(hp)) { - irq_free_hwirq(tile_hvc_irq); - return PTR_ERR(hp); - } - dev_set_drvdata(&pdev->dev, hp); - - return 0; -} - -static int hvc_tile_remove(struct platform_device *pdev) -{ - int rc; - struct hvc_struct *hp = dev_get_drvdata(&pdev->dev); - - rc = hvc_remove(hp); - if (rc == 0) - irq_free_hwirq(hp->data); - - return rc; -} - -static void hvc_tile_shutdown(struct platform_device *pdev) -{ - struct hvc_struct *hp = dev_get_drvdata(&pdev->dev); - - hvc_tile_notifier_del_irq(hp, hp->data); -} - -static struct platform_device hvc_tile_pdev = { - .name = "hvc-tile", - .id = 0, -}; - -static struct platform_driver hvc_tile_driver = { - .probe = hvc_tile_probe, - .remove = hvc_tile_remove, - .shutdown = hvc_tile_shutdown, - .driver = { - .name = "hvc-tile", - } -}; -#endif - -static int __init hvc_tile_console_init(void) -{ - hvc_instantiate(0, 0, &hvc_tile_get_put_ops); - add_preferred_console("hvc", 0, NULL); - return 0; -} -console_initcall(hvc_tile_console_init); - -static int __init hvc_tile_init(void) -{ -#ifndef __tilegx__ - struct hvc_struct *hp; - hp = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128); - return PTR_ERR_OR_ZERO(hp); -#else - platform_device_register(&hvc_tile_pdev); - return platform_driver_register(&hvc_tile_driver); -#endif -} -device_initcall(hvc_tile_init); diff --git a/drivers/tty/metag_da.c b/drivers/tty/metag_da.c deleted file mode 100644 index 99eaed4b2dbc..000000000000 --- a/drivers/tty/metag_da.c +++ /dev/null @@ -1,665 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * dashtty.c - tty driver for Dash channels interface. - * - * Copyright (C) 2007,2008,2012 Imagination Technologies - */ - -#include <linux/atomic.h> -#include <linux/completion.h> -#include <linux/console.h> -#include <linux/delay.h> -#include <linux/export.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/kthread.h> -#include <linux/moduleparam.h> -#include <linux/mutex.h> -#include <linux/sched.h> -#include <linux/serial.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/tty.h> -#include <linux/tty_driver.h> -#include <linux/tty_flip.h> -#include <linux/uaccess.h> - -#include <asm/da.h> - -/* Channel error codes */ -#define CONAOK 0 -#define CONERR 1 -#define CONBAD 2 -#define CONPRM 3 -#define CONADR 4 -#define CONCNT 5 -#define CONCBF 6 -#define CONCBE 7 -#define CONBSY 8 - -/* Default channel for the console */ -#define CONSOLE_CHANNEL 1 - -#define NUM_TTY_CHANNELS 6 - -/* Auto allocate */ -#define DA_TTY_MAJOR 0 - -/* A speedy poll rate helps the userland debug process connection response. - * But, if you set it too high then no other userland processes get much - * of a look in. - */ -#define DA_TTY_POLL (HZ / 50) - -/* - * A short put delay improves latency but has a high throughput overhead - */ -#define DA_TTY_PUT_DELAY (HZ / 100) - -static atomic_t num_channels_need_poll = ATOMIC_INIT(0); - -static struct timer_list poll_timer; - -static struct tty_driver *channel_driver; - -static struct timer_list put_timer; -static struct task_struct *dashtty_thread; - -/* - * The console_poll parameter determines whether the console channel should be - * polled for input. - * By default the console channel isn't polled at all, in order to avoid the - * overhead, but that means it isn't possible to have a login on /dev/console. - */ -static bool console_poll; -module_param(console_poll, bool, S_IRUGO); - -#define RX_BUF_SIZE 1024 - -enum { - INCHR = 1, - OUTCHR, - RDBUF, - WRBUF, - RDSTAT -}; - -/** - * struct dashtty_port - Wrapper struct for dashtty tty_port. - * @port: TTY port data - * @rx_lock: Lock for rx_buf. - * This protects between the poll timer and user context. - * It's also held during read SWITCH operations. - * @rx_buf: Read buffer - * @xmit_lock: Lock for xmit_*, and port.xmit_buf. - * This protects between user context and kernel thread. - * It's also held during write SWITCH operations. - * @xmit_cnt: Size of xmit buffer contents - * @xmit_head: Head of xmit buffer where data is written - * @xmit_tail: Tail of xmit buffer where data is read - * @xmit_empty: Completion for xmit buffer being empty - */ -struct dashtty_port { - struct tty_port port; - spinlock_t rx_lock; - void *rx_buf; - struct mutex xmit_lock; - unsigned int xmit_cnt; - unsigned int xmit_head; - unsigned int xmit_tail; - struct completion xmit_empty; -}; - -static struct dashtty_port dashtty_ports[NUM_TTY_CHANNELS]; - -static atomic_t dashtty_xmit_cnt = ATOMIC_INIT(0); -static wait_queue_head_t dashtty_waitqueue; - -/* - * Low-level DA channel access routines - */ -static int chancall(int in_bios_function, int in_channel, - int in_arg2, void *in_arg3, - void *in_arg4) -{ - register int bios_function asm("D1Ar1") = in_bios_function; - register int channel asm("D0Ar2") = in_channel; - register int arg2 asm("D1Ar3") = in_arg2; - register void *arg3 asm("D0Ar4") = in_arg3; - register void *arg4 asm("D1Ar5") = in_arg4; - register int bios_call asm("D0Ar6") = 3; - register int result asm("D0Re0"); - - asm volatile ( - "MSETL [A0StP++], %6,%4,%2\n\t" - "ADD A0StP, A0StP, #8\n\t" - "SWITCH #0x0C30208\n\t" - "GETD %0, [A0StP+#-8]\n\t" - "SUB A0StP, A0StP, #(4*6)+8\n\t" - : "=d" (result) /* outs */ - : "d" (bios_function), - "d" (channel), - "d" (arg2), - "d" (arg3), - "d" (arg4), - "d" (bios_call) /* ins */ - : "memory"); - - return result; -} - -/* - * Attempts to fetch count bytes from channel and returns actual count. - */ -static int fetch_data(unsigned int channel) -{ - struct dashtty_port *dport = &dashtty_ports[channel]; - int received = 0; - - spin_lock_bh(&dport->rx_lock); - /* check the port isn't being shut down */ - if (!dport->rx_buf) - goto unlock; - if (chancall(RDBUF, channel, RX_BUF_SIZE, - (void *)dport->rx_buf, &received) == CONAOK) { - if (received) { - int space; - unsigned char *cbuf; - - space = tty_prepare_flip_string(&dport->port, &cbuf, - received); - - if (space <= 0) - goto unlock; - - memcpy(cbuf, dport->rx_buf, space); - tty_flip_buffer_push(&dport->port); - } - } -unlock: - spin_unlock_bh(&dport->rx_lock); - - return received; -} - -/** - * find_channel_to_poll() - Returns number of the next channel to poll. - * Returns: The number of the next channel to poll, or -1 if none need - * polling. - */ -static int find_channel_to_poll(void) -{ - static int last_polled_channel; - int last = last_polled_channel; - int chan; - struct dashtty_port *dport; - - for (chan = last + 1; ; ++chan) { - if (chan >= NUM_TTY_CHANNELS) - chan = 0; - - dport = &dashtty_ports[chan]; - if (dport->rx_buf) { - last_polled_channel = chan; - return chan; - } - - if (chan == last) - break; - } - return -1; -} - -/** - * put_channel_data() - Write out a block of channel data. - * @chan: DA channel number. - * - * Write a single block of data out to the debug adapter. If the circular buffer - * is wrapped then only the first block is written. - * - * Returns: 1 if the remote buffer was too full to accept data. - * 0 otherwise. - */ -static int put_channel_data(unsigned int chan) -{ - struct dashtty_port *dport; - struct tty_struct *tty; - int number_written; - unsigned int count = 0; - - dport = &dashtty_ports[chan]; - mutex_lock(&dport->xmit_lock); - if (dport->xmit_cnt) { - count = min((unsigned int)(SERIAL_XMIT_SIZE - dport->xmit_tail), - dport->xmit_cnt); - chancall(WRBUF, chan, count, - dport->port.xmit_buf + dport->xmit_tail, - &number_written); - dport->xmit_cnt -= number_written; - if (!dport->xmit_cnt) { - /* reset pointers to avoid wraps */ - dport->xmit_head = 0; - dport->xmit_tail = 0; - complete(&dport->xmit_empty); - } else { - dport->xmit_tail += number_written; - if (dport->xmit_tail >= SERIAL_XMIT_SIZE) - dport->xmit_tail -= SERIAL_XMIT_SIZE; - } - atomic_sub(number_written, &dashtty_xmit_cnt); - } - mutex_unlock(&dport->xmit_lock); - - /* if we've made more data available, wake up tty */ - if (count && number_written) { - tty = tty_port_tty_get(&dport->port); - if (tty) { - tty_wakeup(tty); - tty_kref_put(tty); - } - } - - /* did the write fail? */ - return count && !number_written; -} - -/** - * put_data() - Kernel thread to write out blocks of channel data to DA. - * @arg: Unused. - * - * This kernel thread runs while @dashtty_xmit_cnt != 0, and loops over the - * channels to write out any buffered data. If any of the channels stall due to - * the remote buffer being full, a hold off happens to allow the debugger to - * drain the buffer. - */ -static int put_data(void *arg) -{ - unsigned int chan, stall; - - __set_current_state(TASK_RUNNING); - while (!kthread_should_stop()) { - /* - * For each channel see if there's anything to transmit in the - * port's xmit_buf. - */ - stall = 0; - for (chan = 0; chan < NUM_TTY_CHANNELS; ++chan) - stall += put_channel_data(chan); - - /* - * If some of the buffers are full, hold off for a short while - * to allow them to empty. - */ - if (stall) - msleep(25); - - wait_event_interruptible(dashtty_waitqueue, - atomic_read(&dashtty_xmit_cnt)); - } - - return 0; -} - -/* - * This gets called every DA_TTY_POLL and polls the channels for data - */ -static void dashtty_timer(struct timer_list *poll_timer) -{ - int channel; - - /* If there are no ports open do nothing and don't poll again. */ - if (!atomic_read(&num_channels_need_poll)) - return; - - channel = find_channel_to_poll(); - - /* Did we find a channel to poll? */ - if (channel >= 0) - fetch_data(channel); - - mod_timer(poll_timer, jiffies + DA_TTY_POLL); -} - -static void add_poll_timer(struct timer_list *poll_timer) -{ - timer_setup(poll_timer, dashtty_timer, TIMER_PINNED); - poll_timer->expires = jiffies + DA_TTY_POLL; - - /* - * Always attach the timer to the boot CPU. The DA channels are per-CPU - * so all polling should be from a single CPU. - */ - add_timer_on(poll_timer, 0); -} - -static int dashtty_port_activate(struct tty_port *port, struct tty_struct *tty) -{ - struct dashtty_port *dport = container_of(port, struct dashtty_port, - port); - void *rx_buf; - - /* Allocate the buffer we use for writing data */ - if (tty_port_alloc_xmit_buf(port) < 0) - goto err; - - /* Allocate the buffer we use for reading data */ - rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL); - if (!rx_buf) - goto err_free_xmit; - - spin_lock_bh(&dport->rx_lock); - dport->rx_buf = rx_buf; - spin_unlock_bh(&dport->rx_lock); - - /* - * Don't add the poll timer if we're opening a console. This - * avoids the overhead of polling the Dash but means it is not - * possible to have a login on /dev/console. - * - */ - if (console_poll || dport != &dashtty_ports[CONSOLE_CHANNEL]) - if (atomic_inc_return(&num_channels_need_poll) == 1) - add_poll_timer(&poll_timer); - - return 0; -err_free_xmit: - tty_port_free_xmit_buf(port); -err: - return -ENOMEM; -} - -static void dashtty_port_shutdown(struct tty_port *port) -{ - struct dashtty_port *dport = container_of(port, struct dashtty_port, - port); - void *rx_buf; - unsigned int count; - - /* stop reading */ - if (console_poll || dport != &dashtty_ports[CONSOLE_CHANNEL]) - if (atomic_dec_and_test(&num_channels_need_poll)) - del_timer_sync(&poll_timer); - - mutex_lock(&dport->xmit_lock); - count = dport->xmit_cnt; - mutex_unlock(&dport->xmit_lock); - if (count) { - /* - * There's still data to write out, so wake and wait for the - * writer thread to drain the buffer. - */ - del_timer(&put_timer); - wake_up_interruptible(&dashtty_waitqueue); - wait_for_completion(&dport->xmit_empty); - } - - /* Null the read buffer (timer could still be running!) */ - spin_lock_bh(&dport->rx_lock); - rx_buf = dport->rx_buf; - dport->rx_buf = NULL; - spin_unlock_bh(&dport->rx_lock); - /* Free the read buffer */ - kfree(rx_buf); - - /* Free the write buffer */ - tty_port_free_xmit_buf(port); -} - -static const struct tty_port_operations dashtty_port_ops = { - .activate = dashtty_port_activate, - .shutdown = dashtty_port_shutdown, -}; - -static int dashtty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - return tty_port_install(&dashtty_ports[tty->index].port, driver, tty); -} - -static int dashtty_open(struct tty_struct *tty, struct file *filp) -{ - return tty_port_open(tty->port, tty, filp); -} - -static void dashtty_close(struct tty_struct *tty, struct file *filp) -{ - return tty_port_close(tty->port, tty, filp); -} - -static void dashtty_hangup(struct tty_struct *tty) -{ - int channel; - struct dashtty_port *dport; - - channel = tty->index; - dport = &dashtty_ports[channel]; - - /* drop any data in the xmit buffer */ - mutex_lock(&dport->xmit_lock); - if (dport->xmit_cnt) { - atomic_sub(dport->xmit_cnt, &dashtty_xmit_cnt); - dport->xmit_cnt = 0; - dport->xmit_head = 0; - dport->xmit_tail = 0; - complete(&dport->xmit_empty); - } - mutex_unlock(&dport->xmit_lock); - - tty_port_hangup(tty->port); -} - -/** - * dashtty_put_timer() - Delayed wake up of kernel thread. - * @ignored: unused - * - * This timer function wakes up the kernel thread if any data exists in the - * buffers. It is used to delay the expensive writeout until the writer has - * stopped writing. - */ -static void dashtty_put_timer(struct timer_list *unused) -{ - if (atomic_read(&dashtty_xmit_cnt)) - wake_up_interruptible(&dashtty_waitqueue); -} - -static int dashtty_write(struct tty_struct *tty, const unsigned char *buf, - int total) -{ - int channel, count, block; - struct dashtty_port *dport; - - /* Determine the channel */ - channel = tty->index; - dport = &dashtty_ports[channel]; - - /* - * Write to output buffer. - * - * The reason that we asynchronously write the buffer is because if we - * were to write the buffer synchronously then because DA channels are - * per-CPU the buffer would be written to the channel of whatever CPU - * we're running on. - * - * What we actually want to happen is have all input and output done on - * one CPU. - */ - mutex_lock(&dport->xmit_lock); - /* work out how many bytes we can write to the xmit buffer */ - total = min(total, (int)(SERIAL_XMIT_SIZE - dport->xmit_cnt)); - atomic_add(total, &dashtty_xmit_cnt); - dport->xmit_cnt += total; - /* write the actual bytes (may need splitting if it wraps) */ - for (count = total; count; count -= block) { - block = min(count, (int)(SERIAL_XMIT_SIZE - dport->xmit_head)); - memcpy(dport->port.xmit_buf + dport->xmit_head, buf, block); - dport->xmit_head += block; - if (dport->xmit_head >= SERIAL_XMIT_SIZE) - dport->xmit_head -= SERIAL_XMIT_SIZE; - buf += block; - } - count = dport->xmit_cnt; - /* xmit buffer no longer empty? */ - if (count) - reinit_completion(&dport->xmit_empty); - mutex_unlock(&dport->xmit_lock); - - if (total) { - /* - * If the buffer is full, wake up the kthread, otherwise allow - * some more time for the buffer to fill up a bit before waking - * it. - */ - if (count == SERIAL_XMIT_SIZE) { - del_timer(&put_timer); - wake_up_interruptible(&dashtty_waitqueue); - } else { - mod_timer(&put_timer, jiffies + DA_TTY_PUT_DELAY); - } - } - return total; -} - -static int dashtty_write_room(struct tty_struct *tty) -{ - struct dashtty_port *dport; - int channel; - int room; - - channel = tty->index; - dport = &dashtty_ports[channel]; - - /* report the space in the xmit buffer */ - mutex_lock(&dport->xmit_lock); - room = SERIAL_XMIT_SIZE - dport->xmit_cnt; - mutex_unlock(&dport->xmit_lock); - - return room; -} - -static int dashtty_chars_in_buffer(struct tty_struct *tty) -{ - struct dashtty_port *dport; - int channel; - int chars; - - channel = tty->index; - dport = &dashtty_ports[channel]; - - /* report the number of bytes in the xmit buffer */ - mutex_lock(&dport->xmit_lock); - chars = dport->xmit_cnt; - mutex_unlock(&dport->xmit_lock); - - return chars; -} - -static const struct tty_operations dashtty_ops = { - .install = dashtty_install, - .open = dashtty_open, - .close = dashtty_close, - .hangup = dashtty_hangup, - .write = dashtty_write, - .write_room = dashtty_write_room, - .chars_in_buffer = dashtty_chars_in_buffer, -}; - -static int __init dashtty_init(void) -{ - int ret; - int nport; - struct dashtty_port *dport; - - if (!metag_da_enabled()) - return -ENODEV; - - channel_driver = tty_alloc_driver(NUM_TTY_CHANNELS, - TTY_DRIVER_REAL_RAW); - if (IS_ERR(channel_driver)) - return PTR_ERR(channel_driver); - - channel_driver->driver_name = "metag_da"; - channel_driver->name = "ttyDA"; - channel_driver->major = DA_TTY_MAJOR; - channel_driver->minor_start = 0; - channel_driver->type = TTY_DRIVER_TYPE_SERIAL; - channel_driver->subtype = SERIAL_TYPE_NORMAL; - channel_driver->init_termios = tty_std_termios; - channel_driver->init_termios.c_cflag |= CLOCAL; - - tty_set_operations(channel_driver, &dashtty_ops); - for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) { - dport = &dashtty_ports[nport]; - tty_port_init(&dport->port); - dport->port.ops = &dashtty_port_ops; - spin_lock_init(&dport->rx_lock); - mutex_init(&dport->xmit_lock); - /* the xmit buffer starts empty, i.e. completely written */ - init_completion(&dport->xmit_empty); - complete(&dport->xmit_empty); - } - - timer_setup(&put_timer, dashtty_put_timer, 0); - - init_waitqueue_head(&dashtty_waitqueue); - dashtty_thread = kthread_create(put_data, NULL, "ttyDA"); - if (IS_ERR(dashtty_thread)) { - pr_err("Couldn't create dashtty thread\n"); - ret = PTR_ERR(dashtty_thread); - goto err_destroy_ports; - } - /* - * Bind the writer thread to the boot CPU so it can't migrate. - * DA channels are per-CPU and we want all channel I/O to be on a single - * predictable CPU. - */ - kthread_bind(dashtty_thread, 0); - wake_up_process(dashtty_thread); - - ret = tty_register_driver(channel_driver); - - if (ret < 0) { - pr_err("Couldn't install dashtty driver: err %d\n", - ret); - goto err_stop_kthread; - } - - return 0; - -err_stop_kthread: - kthread_stop(dashtty_thread); -err_destroy_ports: - for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) { - dport = &dashtty_ports[nport]; - tty_port_destroy(&dport->port); - } - put_tty_driver(channel_driver); - return ret; -} -device_initcall(dashtty_init); - -#ifdef CONFIG_DA_CONSOLE - -static void dash_console_write(struct console *co, const char *s, - unsigned int count) -{ - int actually_written; - - chancall(WRBUF, CONSOLE_CHANNEL, count, (void *)s, &actually_written); -} - -static struct tty_driver *dash_console_device(struct console *c, int *index) -{ - *index = c->index; - return channel_driver; -} - -struct console dash_console = { - .name = "ttyDA", - .write = dash_console_write, - .device = dash_console_device, - .flags = CON_PRINTBUFFER, - .index = 1, -}; - -#endif diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 3682fd3e960c..736720a8d84f 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -498,92 +498,6 @@ config SERIAL_SA1100_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_BFIN - tristate "Blackfin serial port support" - depends on BLACKFIN - select SERIAL_CORE - select SERIAL_BFIN_UART0 if (BF531 || BF532 || BF533 || BF561) - help - Add support for the built-in UARTs on the Blackfin. - - To compile this driver as a module, choose M here: the - module is named bfin_uart.ko. - -config SERIAL_BFIN_CONSOLE - bool "Console on Blackfin serial port" - depends on SERIAL_BFIN=y - select SERIAL_CORE_CONSOLE - -choice - prompt "UART Mode" - depends on SERIAL_BFIN - default SERIAL_BFIN_DMA - help - This driver supports the built-in serial ports of the Blackfin family - of CPUs - -config SERIAL_BFIN_DMA - bool "DMA mode" - depends on !DMA_UNCACHED_NONE && KGDB_SERIAL_CONSOLE=n - help - This driver works under DMA mode. If this option is selected, the - blackfin simple dma driver is also enabled. - -config SERIAL_BFIN_PIO - bool "PIO mode" - help - This driver works under PIO mode. - -endchoice - -config SERIAL_BFIN_UART0 - bool "Enable UART0" - depends on SERIAL_BFIN - help - Enable UART0 - -config BFIN_UART0_CTSRTS - bool "Enable UART0 hardware flow control" - depends on SERIAL_BFIN_UART0 - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_UART1 - bool "Enable UART1" - depends on SERIAL_BFIN && (!BF531 && !BF532 && !BF533 && !BF561) - help - Enable UART1 - -config BFIN_UART1_CTSRTS - bool "Enable UART1 hardware flow control" - depends on SERIAL_BFIN_UART1 - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_UART2 - bool "Enable UART2" - depends on SERIAL_BFIN && (BF54x || BF538 || BF539) - help - Enable UART2 - -config BFIN_UART2_CTSRTS - bool "Enable UART2 hardware flow control" - depends on SERIAL_BFIN_UART2 - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_UART3 - bool "Enable UART3" - depends on SERIAL_BFIN && (BF54x) - help - Enable UART3 - -config BFIN_UART3_CTSRTS - bool "Enable UART3 hardware flow control" - depends on SERIAL_BFIN_UART3 - help - Enable hardware flow control in the driver. - config SERIAL_IMX tristate "IMX serial port support" depends on HAS_DMA @@ -991,35 +905,6 @@ config SERIAL_ICOM This driver can also be built as a module. If so, the module will be called icom. -config SERIAL_M32R_SIO - bool "M32R SIO I/F" - depends on M32R - default y - select SERIAL_CORE - help - Say Y here if you want to use the M32R serial controller. - -config SERIAL_M32R_SIO_CONSOLE - bool "use SIO console" - depends on SERIAL_M32R_SIO=y - select SERIAL_CORE_CONSOLE - help - Say Y here if you want to support a serial console. - - If you use an M3T-M32700UT or an OPSPUT platform, - please say also y for SERIAL_M32R_PLDSIO. - -config SERIAL_M32R_PLDSIO - bool "M32R SIO I/F on a PLD" - depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT) - default n - help - Say Y here if you want to use the M32R serial controller - on a PLD (Programmable Logic Device). - - If you use an M3T-M32700UT or an OPSPUT platform, - please say Y. - config SERIAL_TXX9 bool "TMPTX39XX/49XX SIO support" depends on HAS_TXX9_SERIAL @@ -1114,17 +999,6 @@ config SERIAL_VT8500_CONSOLE depends on SERIAL_VT8500=y select SERIAL_CORE_CONSOLE -config SERIAL_ETRAXFS - bool "ETRAX FS serial port support" - depends on ETRAX_ARCH_V32 && OF - select SERIAL_CORE - select SERIAL_MCTRL_GPIO if GPIOLIB - -config SERIAL_ETRAXFS_CONSOLE - bool "ETRAX FS serial console support" - depends on SERIAL_ETRAXFS - select SERIAL_CORE_CONSOLE - config SERIAL_NETX tristate "NetX serial port support" depends on ARCH_NETX @@ -1242,69 +1116,6 @@ config SERIAL_SC16IS7XX_SPI This is additional support to exsisting driver. You must select at least one bus for the driver to be built. -config SERIAL_BFIN_SPORT - tristate "Blackfin SPORT emulate UART" - depends on BLACKFIN - select SERIAL_CORE - help - Enable SPORT emulate UART on Blackfin series. - - To compile this driver as a module, choose M here: the - module will be called bfin_sport_uart. - -config SERIAL_BFIN_SPORT_CONSOLE - bool "Console on Blackfin sport emulated uart" - depends on SERIAL_BFIN_SPORT=y - select SERIAL_CORE_CONSOLE - -config SERIAL_BFIN_SPORT0_UART - bool "Enable UART over SPORT0" - depends on SERIAL_BFIN_SPORT && !(BF542 || BF544) - help - Enable UART over SPORT0 - -config SERIAL_BFIN_SPORT0_UART_CTSRTS - bool "Enable UART over SPORT0 hardware flow control" - depends on SERIAL_BFIN_SPORT0_UART - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_SPORT1_UART - bool "Enable UART over SPORT1" - depends on SERIAL_BFIN_SPORT - help - Enable UART over SPORT1 - -config SERIAL_BFIN_SPORT1_UART_CTSRTS - bool "Enable UART over SPORT1 hardware flow control" - depends on SERIAL_BFIN_SPORT1_UART - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_SPORT2_UART - bool "Enable UART over SPORT2" - depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) - help - Enable UART over SPORT2 - -config SERIAL_BFIN_SPORT2_UART_CTSRTS - bool "Enable UART over SPORT2 hardware flow control" - depends on SERIAL_BFIN_SPORT2_UART - help - Enable hardware flow control in the driver. - -config SERIAL_BFIN_SPORT3_UART - bool "Enable UART over SPORT3" - depends on SERIAL_BFIN_SPORT && (BF54x || BF538 || BF539) - help - Enable UART over SPORT3 - -config SERIAL_BFIN_SPORT3_UART_CTSRTS - bool "Enable UART over SPORT3 hardware flow control" - depends on SERIAL_BFIN_SPORT3_UART - help - Enable hardware flow control in the driver. - config SERIAL_TIMBERDALE tristate "Support for timberdale UART" select SERIAL_CORE @@ -1519,15 +1330,6 @@ config SERIAL_EFM32_UART_CONSOLE depends on SERIAL_EFM32_UART=y select SERIAL_CORE_CONSOLE -config SERIAL_TILEGX - tristate "TILE-Gx on-chip serial port support" - depends on TILEGX - select TILE_GXIO_UART - select SERIAL_CORE - ---help--- - This device provides access to the on-chip UARTs on the TILE-Gx - processor. - config SERIAL_ARC tristate "ARC UART driver support" select SERIAL_CORE diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 842d185d697e..b30ee2e5d518 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -29,8 +29,6 @@ obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o -obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o -obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o @@ -47,12 +45,9 @@ obj-$(CONFIG_SERIAL_CPM) += cpm_uart/ obj-$(CONFIG_SERIAL_IMX) += imx.o obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o obj-$(CONFIG_SERIAL_ICOM) += icom.o -obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o obj-$(CONFIG_SERIAL_MPSC) += mpsc.o obj-$(CONFIG_SERIAL_MESON) += meson_uart.o obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o -obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o -obj-$(CONFIG_SERIAL_ETRAXFS) += etraxfs-uart.o obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o obj-$(CONFIG_SERIAL_SC16IS7XX_CORE) += sc16is7xx.o obj-$(CONFIG_SERIAL_JSM) += jsm/ @@ -68,7 +63,6 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o -obj-$(CONFIG_SERIAL_TILEGX) += tilegx.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c deleted file mode 100644 index 4ccca5d22f4f..000000000000 --- a/drivers/tty/serial/bfin_sport_uart.c +++ /dev/null @@ -1,937 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Blackfin On-Chip Sport Emulated UART Driver - * - * Copyright 2006-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -/* - * This driver and the hardware supported are in term of EE-191 of ADI. - * http://www.analog.com/static/imported-files/application_notes/EE191.pdf - * This application note describe how to implement a UART on a Sharc DSP, - * but this driver is implemented on Blackfin Processor. - * Transmit Frame Sync is not used by this driver to transfer data out. - */ - -/* #define DEBUG */ - -#define DRV_NAME "bfin-sport-uart" -#define DEVICE_NAME "ttySS" -#define pr_fmt(fmt) DRV_NAME ": " fmt - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/gpio.h> - -#include <asm/bfin_sport.h> -#include <asm/delay.h> -#include <asm/portmux.h> - -#include "bfin_sport_uart.h" - -struct sport_uart_port { - struct uart_port port; - int err_irq; - unsigned short csize; - unsigned short rxmask; - unsigned short txmask1; - unsigned short txmask2; - unsigned char stopb; -/* unsigned char parib; */ -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - int cts_pin; - int rts_pin; -#endif -}; - -static int sport_uart_tx_chars(struct sport_uart_port *up); -static void sport_stop_tx(struct uart_port *port); - -static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) -{ - pr_debug("%s value:%x, mask1=0x%x, mask2=0x%x\n", __func__, value, - up->txmask1, up->txmask2); - - /* Place Start and Stop bits */ - __asm__ __volatile__ ( - "%[val] <<= 1;" - "%[val] = %[val] & %[mask1];" - "%[val] = %[val] | %[mask2];" - : [val]"+d"(value) - : [mask1]"d"(up->txmask1), [mask2]"d"(up->txmask2) - : "ASTAT" - ); - pr_debug("%s value:%x\n", __func__, value); - - SPORT_PUT_TX(up, value); -} - -static inline unsigned char rx_one_byte(struct sport_uart_port *up) -{ - unsigned int value; - unsigned char extract; - u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; - - if ((up->csize + up->stopb) > 7) - value = SPORT_GET_RX32(up); - else - value = SPORT_GET_RX(up); - - pr_debug("%s value:%x, cs=%d, mask=0x%x\n", __func__, value, - up->csize, up->rxmask); - - /* Extract data */ - __asm__ __volatile__ ( - "%[extr] = 0;" - "%[mask1] = %[rxmask];" - "%[mask2] = 0x0200(Z);" - "%[shift] = 0;" - "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" - ".Lloop_s:" - "%[tmp] = extract(%[val], %[mask1].L)(Z);" - "%[tmp] <<= %[shift];" - "%[extr] = %[extr] | %[tmp];" - "%[mask1] = %[mask1] - %[mask2];" - ".Lloop_e:" - "%[shift] += 1;" - : [extr]"=&d"(extract), [shift]"=&d"(tmp_shift), [tmp]"=&d"(tmp), - [mask1]"=&d"(tmp_mask1), [mask2]"=&d"(tmp_mask2) - : [val]"d"(value), [rxmask]"d"(up->rxmask), [lc]"a"(up->csize) - : "ASTAT", "LB0", "LC0", "LT0" - ); - - pr_debug(" extract:%x\n", extract); - return extract; -} - -static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) -{ - int tclkdiv, rclkdiv; - unsigned int sclk = get_sclk(); - - /* Set TCR1 and TCR2, TFSR is not enabled for uart */ - SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); - SPORT_PUT_TCR2(up, size + 1); - pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); - - /* Set RCR1 and RCR2 */ - SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK)); - SPORT_PUT_RCR2(up, (size + 1) * 2 - 1); - pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up)); - - tclkdiv = sclk / (2 * baud_rate) - 1; - /* The actual uart baud rate of devices vary between +/-2%. The sport - * RX sample rate should be faster than the double of the worst case, - * otherwise, wrong data are received. So, set sport RX clock to be - * 3% faster. - */ - rclkdiv = sclk / (2 * baud_rate * 2 * 97 / 100) - 1; - SPORT_PUT_TCLKDIV(up, tclkdiv); - SPORT_PUT_RCLKDIV(up, rclkdiv); - SSYNC(); - pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, rclkdiv:%d\n", - __func__, sclk, baud_rate, tclkdiv, rclkdiv); - - return 0; -} - -static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id) -{ - struct sport_uart_port *up = dev_id; - struct tty_port *port = &up->port.state->port; - unsigned int ch; - - spin_lock(&up->port.lock); - - while (SPORT_GET_STAT(up) & RXNE) { - ch = rx_one_byte(up); - up->port.icount.rx++; - - if (!uart_handle_sysrq_char(&up->port, ch)) - tty_insert_flip_char(port, ch, TTY_NORMAL); - } - - spin_unlock(&up->port.lock); - - /* XXX this won't deadlock with lowlat? */ - tty_flip_buffer_push(port); - - return IRQ_HANDLED; -} - -static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id) -{ - struct sport_uart_port *up = dev_id; - - spin_lock(&up->port.lock); - sport_uart_tx_chars(up); - spin_unlock(&up->port.lock); - - return IRQ_HANDLED; -} - -static irqreturn_t sport_uart_err_irq(int irq, void *dev_id) -{ - struct sport_uart_port *up = dev_id; - unsigned int stat = SPORT_GET_STAT(up); - - spin_lock(&up->port.lock); - - /* Overflow in RX FIFO */ - if (stat & ROVF) { - up->port.icount.overrun++; - tty_insert_flip_char(&up->port.state->port, 0, TTY_OVERRUN); - SPORT_PUT_STAT(up, ROVF); /* Clear ROVF bit */ - } - /* These should not happen */ - if (stat & (TOVF | TUVF | RUVF)) { - pr_err("SPORT Error:%s %s %s\n", - (stat & TOVF) ? "TX overflow" : "", - (stat & TUVF) ? "TX underflow" : "", - (stat & RUVF) ? "RX underflow" : ""); - SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); - SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); - } - SSYNC(); - - spin_unlock(&up->port.lock); - /* XXX we don't push the overrun bit to TTY? */ - - return IRQ_HANDLED; -} - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS -static unsigned int sport_get_mctrl(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - if (up->cts_pin < 0) - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - - /* CTS PIN is negative assertive. */ - if (SPORT_UART_GET_CTS(up)) - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - else - return TIOCM_DSR | TIOCM_CAR; -} - -static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - if (up->rts_pin < 0) - return; - - /* RTS PIN is negative assertive. */ - if (mctrl & TIOCM_RTS) - SPORT_UART_ENABLE_RTS(up); - else - SPORT_UART_DISABLE_RTS(up); -} - -/* - * Handle any change of modem status signal. - */ -static irqreturn_t sport_mctrl_cts_int(int irq, void *dev_id) -{ - struct sport_uart_port *up = (struct sport_uart_port *)dev_id; - unsigned int status; - - status = sport_get_mctrl(&up->port); - uart_handle_cts_change(&up->port, status & TIOCM_CTS); - - return IRQ_HANDLED; -} -#else -static unsigned int sport_get_mctrl(struct uart_port *port) -{ - pr_debug("%s enter\n", __func__); - return TIOCM_CTS | TIOCM_CD | TIOCM_DSR; -} - -static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - pr_debug("%s enter\n", __func__); -} -#endif - -/* Reqeust IRQ, Setup clock */ -static int sport_startup(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - int ret; - - pr_debug("%s enter\n", __func__); - ret = request_irq(up->port.irq, sport_uart_rx_irq, 0, - "SPORT_UART_RX", up); - if (ret) { - dev_err(port->dev, "unable to request SPORT RX interrupt\n"); - return ret; - } - - ret = request_irq(up->port.irq+1, sport_uart_tx_irq, 0, - "SPORT_UART_TX", up); - if (ret) { - dev_err(port->dev, "unable to request SPORT TX interrupt\n"); - goto fail1; - } - - ret = request_irq(up->err_irq, sport_uart_err_irq, 0, - "SPORT_UART_STATUS", up); - if (ret) { - dev_err(port->dev, "unable to request SPORT status interrupt\n"); - goto fail2; - } - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - if (up->cts_pin >= 0) { - if (request_irq(gpio_to_irq(up->cts_pin), - sport_mctrl_cts_int, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | - 0, "BFIN_SPORT_UART_CTS", up)) { - up->cts_pin = -1; - dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); - } - } - if (up->rts_pin >= 0) { - if (gpio_request(up->rts_pin, DRV_NAME)) { - dev_info(port->dev, "fail to request RTS PIN at GPIO_%d\n", up->rts_pin); - up->rts_pin = -1; - } else - gpio_direction_output(up->rts_pin, 0); - } -#endif - - return 0; - fail2: - free_irq(up->port.irq+1, up); - fail1: - free_irq(up->port.irq, up); - - return ret; -} - -/* - * sport_uart_tx_chars - * - * ret 1 means need to enable sport. - * ret 0 means do nothing. - */ -static int sport_uart_tx_chars(struct sport_uart_port *up) -{ - struct circ_buf *xmit = &up->port.state->xmit; - - if (SPORT_GET_STAT(up) & TXF) - return 0; - - if (up->port.x_char) { - tx_one_byte(up, up->port.x_char); - up->port.icount.tx++; - up->port.x_char = 0; - return 1; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - /* The waiting loop to stop SPORT TX from TX interrupt is - * too long. This may block SPORT RX interrupts and cause - * RX FIFO overflow. So, do stop sport TX only after the last - * char in TX FIFO is moved into the shift register. - */ - if (SPORT_GET_STAT(up) & TXHRE) - sport_stop_tx(&up->port); - return 0; - } - - while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) { - tx_one_byte(up, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1); - up->port.icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); - - return 1; -} - -static unsigned int sport_tx_empty(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - unsigned int stat; - - stat = SPORT_GET_STAT(up); - pr_debug("%s stat:%04x\n", __func__, stat); - if (stat & TXHRE) { - return TIOCSER_TEMT; - } else - return 0; -} - -static void sport_stop_tx(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - pr_debug("%s enter\n", __func__); - - if (!(SPORT_GET_TCR1(up) & TSPEN)) - return; - - /* Although the hold register is empty, last byte is still in shift - * register and not sent out yet. So, put a dummy data into TX FIFO. - * Then, sport tx stops when last byte is shift out and the dummy - * data is moved into the shift register. - */ - SPORT_PUT_TX(up, 0xffff); - while (!(SPORT_GET_STAT(up) & TXHRE)) - cpu_relax(); - - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); - SSYNC(); - - return; -} - -static void sport_start_tx(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - pr_debug("%s enter\n", __func__); - - /* Write data into SPORT FIFO before enable SPROT to transmit */ - if (sport_uart_tx_chars(up)) { - /* Enable transmit, then an interrupt will generated */ - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); - SSYNC(); - } - - pr_debug("%s exit\n", __func__); -} - -static void sport_stop_rx(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - pr_debug("%s enter\n", __func__); - /* Disable sport to stop rx */ - SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); - SSYNC(); -} - -static void sport_break_ctl(struct uart_port *port, int break_state) -{ - pr_debug("%s enter\n", __func__); -} - -static void sport_shutdown(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - dev_dbg(port->dev, "%s enter\n", __func__); - - /* Disable sport */ - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); - SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN)); - SSYNC(); - - free_irq(up->port.irq, up); - free_irq(up->port.irq+1, up); - free_irq(up->err_irq, up); -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - if (up->cts_pin >= 0) - free_irq(gpio_to_irq(up->cts_pin), up); - if (up->rts_pin >= 0) - gpio_free(up->rts_pin); -#endif -} - -static const char *sport_type(struct uart_port *port) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - pr_debug("%s enter\n", __func__); - return up->port.type == PORT_BFIN_SPORT ? "BFIN-SPORT-UART" : NULL; -} - -static void sport_release_port(struct uart_port *port) -{ - pr_debug("%s enter\n", __func__); -} - -static int sport_request_port(struct uart_port *port) -{ - pr_debug("%s enter\n", __func__); - return 0; -} - -static void sport_config_port(struct uart_port *port, int flags) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - pr_debug("%s enter\n", __func__); - up->port.type = PORT_BFIN_SPORT; -} - -static int sport_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - pr_debug("%s enter\n", __func__); - return 0; -} - -static void sport_set_termios(struct uart_port *port, - struct ktermios *termios, struct ktermios *old) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - unsigned long flags; - int i; - - pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - if (old == NULL && up->cts_pin != -1) - termios->c_cflag |= CRTSCTS; - else if (up->cts_pin == -1) - termios->c_cflag &= ~CRTSCTS; -#endif - - switch (termios->c_cflag & CSIZE) { - case CS8: - up->csize = 8; - break; - case CS7: - up->csize = 7; - break; - case CS6: - up->csize = 6; - break; - case CS5: - up->csize = 5; - break; - default: - pr_warn("requested word length not supported\n"); - break; - } - - if (termios->c_cflag & CSTOPB) { - up->stopb = 1; - } - if (termios->c_cflag & PARENB) { - pr_warn("PAREN bit is not supported yet\n"); - /* up->parib = 1; */ - } - - spin_lock_irqsave(&up->port.lock, flags); - - port->read_status_mask = 0; - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - - /* RX extract mask */ - up->rxmask = 0x01 | (((up->csize + up->stopb) * 2 - 1) << 0x8); - /* TX masks, 8 bit data and 1 bit stop for example: - * mask1 = b#0111111110 - * mask2 = b#1000000000 - */ - for (i = 0, up->txmask1 = 0; i < up->csize; i++) - up->txmask1 |= (1<<i); - up->txmask2 = (1<<i); - if (up->stopb) { - ++i; - up->txmask2 |= (1<<i); - } - up->txmask1 <<= 1; - up->txmask2 <<= 1; - /* uart baud rate */ - port->uartclk = uart_get_baud_rate(port, termios, old, 0, get_sclk()/16); - - /* Disable UART */ - SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); - SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN); - - sport_uart_setup(up, up->csize + up->stopb, port->uartclk); - - /* driver TX line high after config, one dummy data is - * necessary to stop sport after shift one byte - */ - SPORT_PUT_TX(up, 0xffff); - SPORT_PUT_TX(up, 0xffff); - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); - SSYNC(); - while (!(SPORT_GET_STAT(up) & TXHRE)) - cpu_relax(); - SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN); - SSYNC(); - - /* Port speed changed, update the per-port timeout. */ - uart_update_timeout(port, termios->c_cflag, port->uartclk); - - /* Enable sport rx */ - SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) | RSPEN); - SSYNC(); - - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static const struct uart_ops sport_uart_ops = { - .tx_empty = sport_tx_empty, - .set_mctrl = sport_set_mctrl, - .get_mctrl = sport_get_mctrl, - .stop_tx = sport_stop_tx, - .start_tx = sport_start_tx, - .stop_rx = sport_stop_rx, - .break_ctl = sport_break_ctl, - .startup = sport_startup, - .shutdown = sport_shutdown, - .set_termios = sport_set_termios, - .type = sport_type, - .release_port = sport_release_port, - .request_port = sport_request_port, - .config_port = sport_config_port, - .verify_port = sport_verify_port, -}; - -#define BFIN_SPORT_UART_MAX_PORTS 4 - -static struct sport_uart_port *bfin_sport_uart_ports[BFIN_SPORT_UART_MAX_PORTS]; - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE -#define CLASS_BFIN_SPORT_CONSOLE "bfin-sport-console" - -static int __init -sport_uart_console_setup(struct console *co, char *options) -{ - struct sport_uart_port *up; - int baud = 57600; - int bits = 8; - int parity = 'n'; -# ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - int flow = 'r'; -# else - int flow = 'n'; -# endif - - /* Check whether an invalid uart number has been specified */ - if (co->index < 0 || co->index >= BFIN_SPORT_UART_MAX_PORTS) - return -ENODEV; - - up = bfin_sport_uart_ports[co->index]; - if (!up) - return -ENODEV; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(&up->port, co, baud, parity, bits, flow); -} - -static void sport_uart_console_putchar(struct uart_port *port, int ch) -{ - struct sport_uart_port *up = (struct sport_uart_port *)port; - - while (SPORT_GET_STAT(up) & TXF) - barrier(); - - tx_one_byte(up, ch); -} - -/* - * Interrupts are disabled on entering - */ -static void -sport_uart_console_write(struct console *co, const char *s, unsigned int count) -{ - struct sport_uart_port *up = bfin_sport_uart_ports[co->index]; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); - - if (SPORT_GET_TCR1(up) & TSPEN) - uart_console_write(&up->port, s, count, sport_uart_console_putchar); - else { - /* dummy data to start sport */ - while (SPORT_GET_STAT(up) & TXF) - barrier(); - SPORT_PUT_TX(up, 0xffff); - /* Enable transmit, then an interrupt will generated */ - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN)); - SSYNC(); - - uart_console_write(&up->port, s, count, sport_uart_console_putchar); - - /* Although the hold register is empty, last byte is still in shift - * register and not sent out yet. So, put a dummy data into TX FIFO. - * Then, sport tx stops when last byte is shift out and the dummy - * data is moved into the shift register. - */ - while (SPORT_GET_STAT(up) & TXF) - barrier(); - SPORT_PUT_TX(up, 0xffff); - while (!(SPORT_GET_STAT(up) & TXHRE)) - barrier(); - - /* Stop sport tx transfer */ - SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN)); - SSYNC(); - } - - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static struct uart_driver sport_uart_reg; - -static struct console sport_uart_console = { - .name = DEVICE_NAME, - .write = sport_uart_console_write, - .device = uart_console_device, - .setup = sport_uart_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &sport_uart_reg, -}; - -#define SPORT_UART_CONSOLE (&sport_uart_console) -#else -#define SPORT_UART_CONSOLE NULL -#endif /* CONFIG_SERIAL_BFIN_SPORT_CONSOLE */ - - -static struct uart_driver sport_uart_reg = { - .owner = THIS_MODULE, - .driver_name = DRV_NAME, - .dev_name = DEVICE_NAME, - .major = 204, - .minor = 84, - .nr = BFIN_SPORT_UART_MAX_PORTS, - .cons = SPORT_UART_CONSOLE, -}; - -#ifdef CONFIG_PM -static int sport_uart_suspend(struct device *dev) -{ - struct sport_uart_port *sport = dev_get_drvdata(dev); - - dev_dbg(dev, "%s enter\n", __func__); - if (sport) - uart_suspend_port(&sport_uart_reg, &sport->port); - - return 0; -} - -static int sport_uart_resume(struct device *dev) -{ - struct sport_uart_port *sport = dev_get_drvdata(dev); - - dev_dbg(dev, "%s enter\n", __func__); - if (sport) - uart_resume_port(&sport_uart_reg, &sport->port); - - return 0; -} - -static const struct dev_pm_ops bfin_sport_uart_dev_pm_ops = { - .suspend = sport_uart_suspend, - .resume = sport_uart_resume, -}; -#endif - -static int sport_uart_probe(struct platform_device *pdev) -{ - struct resource *res; - struct sport_uart_port *sport; - int ret = 0; - - dev_dbg(&pdev->dev, "%s enter\n", __func__); - - if (pdev->id < 0 || pdev->id >= BFIN_SPORT_UART_MAX_PORTS) { - dev_err(&pdev->dev, "Wrong sport uart platform device id.\n"); - return -ENOENT; - } - - if (bfin_sport_uart_ports[pdev->id] == NULL) { - bfin_sport_uart_ports[pdev->id] = - kzalloc(sizeof(struct sport_uart_port), GFP_KERNEL); - sport = bfin_sport_uart_ports[pdev->id]; - if (!sport) { - dev_err(&pdev->dev, - "Fail to malloc sport_uart_port\n"); - return -ENOMEM; - } - - ret = peripheral_request_list(dev_get_platdata(&pdev->dev), - DRV_NAME); - if (ret) { - dev_err(&pdev->dev, - "Fail to request SPORT peripherals\n"); - goto out_error_free_mem; - } - - spin_lock_init(&sport->port.lock); - sport->port.fifosize = SPORT_TX_FIFO_SIZE, - sport->port.ops = &sport_uart_ops; - sport->port.line = pdev->id; - sport->port.iotype = UPIO_MEM; - sport->port.flags = UPF_BOOT_AUTOCONF; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); - ret = -ENOENT; - goto out_error_free_peripherals; - } - - sport->port.membase = ioremap(res->start, resource_size(res)); - if (!sport->port.membase) { - dev_err(&pdev->dev, "Cannot map sport IO\n"); - ret = -ENXIO; - goto out_error_free_peripherals; - } - sport->port.mapbase = res->start; - - sport->port.irq = platform_get_irq(pdev, 0); - if ((int)sport->port.irq < 0) { - dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - - sport->err_irq = platform_get_irq(pdev, 1); - if (sport->err_irq < 0) { - dev_err(&pdev->dev, "No sport status IRQ specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } -#ifdef CONFIG_SERIAL_BFIN_SPORT_CTSRTS - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (res == NULL) - sport->cts_pin = -1; - else - sport->cts_pin = res->start; - - res = platform_get_resource(pdev, IORESOURCE_IO, 1); - if (res == NULL) - sport->rts_pin = -1; - else - sport->rts_pin = res->start; -#endif - } - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE - if (!is_early_platform_device(pdev)) { -#endif - sport = bfin_sport_uart_ports[pdev->id]; - sport->port.dev = &pdev->dev; - dev_set_drvdata(&pdev->dev, sport); - ret = uart_add_one_port(&sport_uart_reg, &sport->port); -#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE - } -#endif - if (!ret) - return 0; - - if (sport) { -out_error_unmap: - iounmap(sport->port.membase); -out_error_free_peripherals: - peripheral_free_list(dev_get_platdata(&pdev->dev)); -out_error_free_mem: - kfree(sport); - bfin_sport_uart_ports[pdev->id] = NULL; - } - - return ret; -} - -static int sport_uart_remove(struct platform_device *pdev) -{ - struct sport_uart_port *sport = platform_get_drvdata(pdev); - - dev_dbg(&pdev->dev, "%s enter\n", __func__); - dev_set_drvdata(&pdev->dev, NULL); - - if (sport) { - uart_remove_one_port(&sport_uart_reg, &sport->port); - iounmap(sport->port.membase); - peripheral_free_list(dev_get_platdata(&pdev->dev)); - kfree(sport); - bfin_sport_uart_ports[pdev->id] = NULL; - } - - return 0; -} - -static struct platform_driver sport_uart_driver = { - .probe = sport_uart_probe, - .remove = sport_uart_remove, - .driver = { - .name = DRV_NAME, -#ifdef CONFIG_PM - .pm = &bfin_sport_uart_dev_pm_ops, -#endif - }, -}; - -#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE -static struct early_platform_driver early_sport_uart_driver __initdata = { - .class_str = CLASS_BFIN_SPORT_CONSOLE, - .pdrv = &sport_uart_driver, - .requested_id = EARLY_PLATFORM_ID_UNSET, -}; - -static int __init sport_uart_rs_console_init(void) -{ - early_platform_driver_register(&early_sport_uart_driver, DRV_NAME); - - early_platform_driver_probe(CLASS_BFIN_SPORT_CONSOLE, - BFIN_SPORT_UART_MAX_PORTS, 0); - - register_console(&sport_uart_console); - - return 0; -} -console_initcall(sport_uart_rs_console_init); -#endif - -static int __init sport_uart_init(void) -{ - int ret; - - pr_info("Blackfin uart over sport driver\n"); - - ret = uart_register_driver(&sport_uart_reg); - if (ret) { - pr_err("failed to register %s:%d\n", - sport_uart_reg.driver_name, ret); - return ret; - } - - ret = platform_driver_register(&sport_uart_driver); - if (ret) { - pr_err("failed to register sport uart driver:%d\n", ret); - uart_unregister_driver(&sport_uart_reg); - } - - return ret; -} -module_init(sport_uart_init); - -static void __exit sport_uart_exit(void) -{ - platform_driver_unregister(&sport_uart_driver); - uart_unregister_driver(&sport_uart_reg); -} -module_exit(sport_uart_exit); - -MODULE_AUTHOR("Sonic Zhang, Roy Huang"); -MODULE_DESCRIPTION("Blackfin serial over SPORT driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/tty/serial/bfin_sport_uart.h b/drivers/tty/serial/bfin_sport_uart.h deleted file mode 100644 index 4b12f45d6580..000000000000 --- a/drivers/tty/serial/bfin_sport_uart.h +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Blackfin On-Chip Sport Emulated UART Driver - * - * Copyright 2006-2008 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -/* - * This driver and the hardware supported are in term of EE-191 of ADI. - * http://www.analog.com/static/imported-files/application_notes/EE191.pdf - * This application note describe how to implement a UART on a Sharc DSP, - * but this driver is implemented on Blackfin Processor. - * Transmit Frame Sync is not used by this driver to transfer data out. - */ - -#ifndef _BFIN_SPORT_UART_H -#define _BFIN_SPORT_UART_H - -#define OFFSET_TCR1 0x00 /* Transmit Configuration 1 Register */ -#define OFFSET_TCR2 0x04 /* Transmit Configuration 2 Register */ -#define OFFSET_TCLKDIV 0x08 /* Transmit Serial Clock Divider Register */ -#define OFFSET_TFSDIV 0x0C /* Transmit Frame Sync Divider Register */ -#define OFFSET_TX 0x10 /* Transmit Data Register */ -#define OFFSET_RX 0x18 /* Receive Data Register */ -#define OFFSET_RCR1 0x20 /* Receive Configuration 1 Register */ -#define OFFSET_RCR2 0x24 /* Receive Configuration 2 Register */ -#define OFFSET_RCLKDIV 0x28 /* Receive Serial Clock Divider Register */ -#define OFFSET_RFSDIV 0x2c /* Receive Frame Sync Divider Register */ -#define OFFSET_STAT 0x30 /* Status Register */ - -#define SPORT_GET_TCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR1)) -#define SPORT_GET_TCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_TCR2)) -#define SPORT_GET_TCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TCLKDIV)) -#define SPORT_GET_TFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_TFSDIV)) -#define SPORT_GET_TX(sport) bfin_read16(((sport)->port.membase + OFFSET_TX)) -#define SPORT_GET_RX(sport) bfin_read16(((sport)->port.membase + OFFSET_RX)) -/* - * If another interrupt fires while doing a 32-bit read from RX FIFO, - * a fake RX underflow error will be generated. So disable interrupts - * to prevent interruption while reading the FIFO. - */ -#define SPORT_GET_RX32(sport) \ -({ \ - unsigned int __ret; \ - unsigned long flags; \ - if (ANOMALY_05000473) \ - local_irq_save(flags); \ - __ret = bfin_read32((sport)->port.membase + OFFSET_RX); \ - if (ANOMALY_05000473) \ - local_irq_restore(flags); \ - __ret; \ -}) -#define SPORT_GET_RCR1(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR1)) -#define SPORT_GET_RCR2(sport) bfin_read16(((sport)->port.membase + OFFSET_RCR2)) -#define SPORT_GET_RCLKDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV)) -#define SPORT_GET_RFSDIV(sport) bfin_read16(((sport)->port.membase + OFFSET_RFSDIV)) -#define SPORT_GET_STAT(sport) bfin_read16(((sport)->port.membase + OFFSET_STAT)) - -#define SPORT_PUT_TCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR1), v) -#define SPORT_PUT_TCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCR2), v) -#define SPORT_PUT_TCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TCLKDIV), v) -#define SPORT_PUT_TFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TFSDIV), v) -#define SPORT_PUT_TX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_TX), v) -#define SPORT_PUT_RX(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RX), v) -#define SPORT_PUT_RCR1(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR1), v) -#define SPORT_PUT_RCR2(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCR2), v) -#define SPORT_PUT_RCLKDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v) -#define SPORT_PUT_RFSDIV(sport, v) bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v) -#define SPORT_PUT_STAT(sport, v) bfin_write16(((sport)->port.membase + OFFSET_STAT), v) - -#define SPORT_TX_FIFO_SIZE 8 - -#define SPORT_UART_GET_CTS(x) gpio_get_value(x->cts_pin) -#define SPORT_UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1) -#define SPORT_UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0) - -#if defined(CONFIG_SERIAL_BFIN_SPORT0_UART_CTSRTS) \ - || defined(CONFIG_SERIAL_BFIN_SPORT1_UART_CTSRTS) \ - || defined(CONFIG_SERIAL_BFIN_SPORT2_UART_CTSRTS) \ - || defined(CONFIG_SERIAL_BFIN_SPORT3_UART_CTSRTS) -# define CONFIG_SERIAL_BFIN_SPORT_CTSRTS -#endif - -#endif /* _BFIN_SPORT_UART_H */ diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c deleted file mode 100644 index 4755fa696321..000000000000 --- a/drivers/tty/serial/bfin_uart.c +++ /dev/null @@ -1,1551 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Blackfin On-Chip Serial Driver - * - * Copyright 2006-2011 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -#if defined(CONFIG_SERIAL_BFIN_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#define DRIVER_NAME "bfin-uart" -#define pr_fmt(fmt) DRIVER_NAME ": " fmt - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/gfp.h> -#include <linux/io.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/platform_device.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/serial_core.h> -#include <linux/gpio.h> -#include <linux/irq.h> -#include <linux/kgdb.h> -#include <linux/slab.h> -#include <linux/dma-mapping.h> - -#include <asm/portmux.h> -#include <asm/cacheflush.h> -#include <asm/dma.h> -#include <asm/bfin_serial.h> - -#ifdef CONFIG_SERIAL_BFIN_MODULE -# undef CONFIG_EARLY_PRINTK -#endif - -/* UART name and device definitions */ -#define BFIN_SERIAL_DEV_NAME "ttyBF" -#define BFIN_SERIAL_MAJOR 204 -#define BFIN_SERIAL_MINOR 64 - -static struct bfin_serial_port *bfin_serial_ports[BFIN_UART_NR_PORTS]; - -#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) - -# ifndef CONFIG_SERIAL_BFIN_PIO -# error KGDB only support UART in PIO mode. -# endif - -static int kgdboc_port_line; -static int kgdboc_break_enabled; -#endif -/* - * Setup for console. Argument comes from the menuconfig - */ -#define DMA_RX_XCOUNT 512 -#define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT) - -#define DMA_RX_FLUSH_JIFFIES (HZ / 50) - -#ifdef CONFIG_SERIAL_BFIN_DMA -static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart); -#else -static void bfin_serial_tx_chars(struct bfin_serial_port *uart); -#endif - -static void bfin_serial_reset_irda(struct uart_port *port); - -#if defined(SERIAL_BFIN_CTSRTS) || \ - defined(SERIAL_BFIN_HARD_CTSRTS) -static unsigned int bfin_serial_get_mctrl(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - if (uart->cts_pin < 0) - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - - /* CTS PIN is negative assertive. */ - if (UART_GET_CTS(uart)) - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; - else - return TIOCM_DSR | TIOCM_CAR; -} - -static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - if (uart->rts_pin < 0) - return; - - /* RTS PIN is negative assertive. */ - if (mctrl & TIOCM_RTS) - UART_ENABLE_RTS(uart); - else - UART_DISABLE_RTS(uart); -} - -/* - * Handle any change of modem status signal. - */ -static irqreturn_t bfin_serial_mctrl_cts_int(int irq, void *dev_id) -{ - struct bfin_serial_port *uart = dev_id; - struct uart_port *uport = &uart->port; - unsigned int status = bfin_serial_get_mctrl(uport); -#ifdef SERIAL_BFIN_HARD_CTSRTS - - UART_CLEAR_SCTS(uart); - if (uport->hw_stopped) { - if (status) { - uport->hw_stopped = 0; - uart_write_wakeup(uport); - } - } else { - if (!status) - uport->hw_stopped = 1; - } -#else - uart_handle_cts_change(uport, status & TIOCM_CTS); -#endif - - return IRQ_HANDLED; -} -#else -static unsigned int bfin_serial_get_mctrl(struct uart_port *port) -{ - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; -} - -static void bfin_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ -} -#endif - -/* - * interrupts are disabled on entry - */ -static void bfin_serial_stop_tx(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; -#ifdef CONFIG_SERIAL_BFIN_DMA - struct circ_buf *xmit = &uart->port.state->xmit; -#endif - - while (!(UART_GET_LSR(uart) & TEMT)) - cpu_relax(); - -#ifdef CONFIG_SERIAL_BFIN_DMA - disable_dma(uart->tx_dma_channel); - xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); - uart->port.icount.tx += uart->tx_count; - uart->tx_count = 0; - uart->tx_done = 1; -#else -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - /* Clear TFI bit */ - UART_PUT_LSR(uart, TFI); -#endif - UART_CLEAR_IER(uart, ETBEI); -#endif -} - -/* - * port is locked and interrupts are disabled - */ -static void bfin_serial_start_tx(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - struct tty_struct *tty = uart->port.state->port.tty; - - /* - * To avoid losting RX interrupt, we reset IR function - * before sending data. - */ - if (tty->termios.c_line == N_IRDA) - bfin_serial_reset_irda(port); - -#ifdef CONFIG_SERIAL_BFIN_DMA - if (uart->tx_done) - bfin_serial_dma_tx_chars(uart); -#else - UART_SET_IER(uart, ETBEI); - bfin_serial_tx_chars(uart); -#endif -} - -/* - * Interrupts are enabled - */ -static void bfin_serial_stop_rx(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - - UART_CLEAR_IER(uart, ERBFI); -} - -#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO) -# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold) -# define UART_SET_ANOMALY_THRESHOLD(uart, v) ((uart)->anomaly_threshold = (v)) -#else -# define UART_GET_ANOMALY_THRESHOLD(uart) 0 -# define UART_SET_ANOMALY_THRESHOLD(uart, v) -#endif - -#ifdef CONFIG_SERIAL_BFIN_PIO -static void bfin_serial_rx_chars(struct bfin_serial_port *uart) -{ - unsigned int status, ch, flg; - static u64 anomaly_start; - - status = UART_GET_LSR(uart); - UART_CLEAR_LSR(uart); - - ch = UART_GET_CHAR(uart); - uart->port.icount.rx++; - -#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) - if (kgdb_connected && kgdboc_port_line == uart->port.line - && kgdboc_break_enabled) - if (ch == 0x3) {/* Ctrl + C */ - kgdb_breakpoint(); - return; - } - - if (!uart->port.state) - return; -#endif - if (ANOMALY_05000363) { - /* The BF533 (and BF561) family of processors have a nice anomaly - * where they continuously generate characters for a "single" break. - * We have to basically ignore this flood until the "next" valid - * character comes across. Due to the nature of the flood, it is - * not possible to reliably catch bytes that are sent too quickly - * after this break. So application code talking to the Blackfin - * which sends a break signal must allow at least 1.5 character - * times after the end of the break for things to stabilize. This - * timeout was picked as it must absolutely be larger than 1 - * character time +/- some percent. So 1.5 sounds good. All other - * Blackfin families operate properly. Woo. - */ - if (anomaly_start > 0) { - u64 curr, nsecs, threshold_ns; - - if ((~ch & (~ch + 1)) & 0xff) - goto known_good_char; - - curr = ktime_get_ns(); - nsecs = curr - anomaly_start; - if (nsecs >> 32) - goto known_good_char; - - threshold_ns = UART_GET_ANOMALY_THRESHOLD(uart) - * NSEC_PER_USEC; - if (nsecs > threshold_ns) - goto known_good_char; - - if (ch) - anomaly_start = 0; - else - anomaly_start = curr; - - return; - - known_good_char: - status &= ~BI; - anomaly_start = 0; - } - } - - if (status & BI) { - if (ANOMALY_05000363) - if (bfin_revid() < 5) - anomaly_start = ktime_get_ns(); - uart->port.icount.brk++; - if (uart_handle_break(&uart->port)) - goto ignore_char; - status &= ~(PE | FE); - } - if (status & PE) - uart->port.icount.parity++; - if (status & OE) - uart->port.icount.overrun++; - if (status & FE) - uart->port.icount.frame++; - - status &= uart->port.read_status_mask; - - if (status & BI) - flg = TTY_BREAK; - else if (status & PE) - flg = TTY_PARITY; - else if (status & FE) - flg = TTY_FRAME; - else - flg = TTY_NORMAL; - - if (uart_handle_sysrq_char(&uart->port, ch)) - goto ignore_char; - - uart_insert_char(&uart->port, status, OE, ch, flg); - - ignore_char: - tty_flip_buffer_push(&uart->port.state->port); -} - -static void bfin_serial_tx_chars(struct bfin_serial_port *uart) -{ - struct circ_buf *xmit = &uart->port.state->xmit; - - if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { -#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) - /* Clear TFI bit */ - UART_PUT_LSR(uart, TFI); -#endif - /* Anomaly notes: - * 05000215 - we always clear ETBEI within last UART TX - * interrupt to end a string. It is always set - * when start a new tx. - */ - UART_CLEAR_IER(uart, ETBEI); - return; - } - - if (uart->port.x_char) { - UART_PUT_CHAR(uart, uart->port.x_char); - uart->port.icount.tx++; - uart->port.x_char = 0; - } - - while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { - UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - uart->port.icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uart->port); -} - -static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) -{ - struct bfin_serial_port *uart = dev_id; - - while (UART_GET_LSR(uart) & DR) - bfin_serial_rx_chars(uart); - - return IRQ_HANDLED; -} - -static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) -{ - struct bfin_serial_port *uart = dev_id; - - spin_lock(&uart->port.lock); - if (UART_GET_LSR(uart) & THRE) - bfin_serial_tx_chars(uart); - spin_unlock(&uart->port.lock); - - return IRQ_HANDLED; -} -#endif - -#ifdef CONFIG_SERIAL_BFIN_DMA -static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) -{ - struct circ_buf *xmit = &uart->port.state->xmit; - - uart->tx_done = 0; - - if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { - uart->tx_count = 0; - uart->tx_done = 1; - return; - } - - if (uart->port.x_char) { - UART_PUT_CHAR(uart, uart->port.x_char); - uart->port.icount.tx++; - uart->port.x_char = 0; - } - - uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); - if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) - uart->tx_count = UART_XMIT_SIZE - xmit->tail; - blackfin_dcache_flush_range((unsigned long)(xmit->buf+xmit->tail), - (unsigned long)(xmit->buf+xmit->tail+uart->tx_count)); - set_dma_config(uart->tx_dma_channel, - set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, - INTR_ON_BUF, - DIMENSION_LINEAR, - DATA_SIZE_8, - DMA_SYNC_RESTART)); - set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); - set_dma_x_count(uart->tx_dma_channel, uart->tx_count); - set_dma_x_modify(uart->tx_dma_channel, 1); - SSYNC(); - enable_dma(uart->tx_dma_channel); - - UART_SET_IER(uart, ETBEI); -} - -static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) -{ - int i, flg, status; - - status = UART_GET_LSR(uart); - UART_CLEAR_LSR(uart); - - uart->port.icount.rx += - CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, - UART_XMIT_SIZE); - - if (status & BI) { - uart->port.icount.brk++; - if (uart_handle_break(&uart->port)) - goto dma_ignore_char; - status &= ~(PE | FE); - } - if (status & PE) - uart->port.icount.parity++; - if (status & OE) - uart->port.icount.overrun++; - if (status & FE) - uart->port.icount.frame++; - - status &= uart->port.read_status_mask; - - if (status & BI) - flg = TTY_BREAK; - else if (status & PE) - flg = TTY_PARITY; - else if (status & FE) - flg = TTY_FRAME; - else - flg = TTY_NORMAL; - - for (i = uart->rx_dma_buf.tail; ; i++) { - if (i >= UART_XMIT_SIZE) - i = 0; - if (i == uart->rx_dma_buf.head) - break; - if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) - uart_insert_char(&uart->port, status, OE, - uart->rx_dma_buf.buf[i], flg); - } - - dma_ignore_char: - tty_flip_buffer_push(&uart->port.state->port); -} - -void bfin_serial_rx_dma_timeout(struct timer_list *t) -{ - struct bfin_serial_port *uart = from_timer(uart, t, rx_dma_timer); - int x_pos, pos; - unsigned long flags; - - dma_disable_irq_nosync(uart->rx_dma_channel); - spin_lock_irqsave(&uart->rx_lock, flags); - - /* 2D DMA RX buffer ring is used. Because curr_y_count and - * curr_x_count can't be read as an atomic operation, - * curr_y_count should be read before curr_x_count. When - * curr_x_count is read, curr_y_count may already indicate - * next buffer line. But, the position calculated here is - * still indicate the old line. The wrong position data may - * be smaller than current buffer tail, which cause garbages - * are received if it is not prohibit. - */ - uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); - x_pos = get_dma_curr_xcount(uart->rx_dma_channel); - uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; - if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) - uart->rx_dma_nrows = 0; - x_pos = DMA_RX_XCOUNT - x_pos; - if (x_pos == DMA_RX_XCOUNT) - x_pos = 0; - - pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; - /* Ignore receiving data if new position is in the same line of - * current buffer tail and small. - */ - if (pos > uart->rx_dma_buf.tail || - uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { - uart->rx_dma_buf.head = pos; - bfin_serial_dma_rx_chars(uart); - uart->rx_dma_buf.tail = uart->rx_dma_buf.head; - } - - spin_unlock_irqrestore(&uart->rx_lock, flags); - dma_enable_irq(uart->rx_dma_channel); - - mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); -} - -static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) -{ - struct bfin_serial_port *uart = dev_id; - struct circ_buf *xmit = &uart->port.state->xmit; - - spin_lock(&uart->port.lock); - if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { - disable_dma(uart->tx_dma_channel); - clear_dma_irqstat(uart->tx_dma_channel); - /* Anomaly notes: - * 05000215 - we always clear ETBEI within last UART TX - * interrupt to end a string. It is always set - * when start a new tx. - */ - UART_CLEAR_IER(uart, ETBEI); - uart->port.icount.tx += uart->tx_count; - if (!(xmit->tail == 0 && xmit->head == 0)) { - xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&uart->port); - } - - bfin_serial_dma_tx_chars(uart); - } - - spin_unlock(&uart->port.lock); - return IRQ_HANDLED; -} - -static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) -{ - struct bfin_serial_port *uart = dev_id; - unsigned int irqstat; - int x_pos, pos; - - spin_lock(&uart->rx_lock); - irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); - clear_dma_irqstat(uart->rx_dma_channel); - - uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); - x_pos = get_dma_curr_xcount(uart->rx_dma_channel); - uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; - if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) - uart->rx_dma_nrows = 0; - - pos = uart->rx_dma_nrows * DMA_RX_XCOUNT; - if (pos > uart->rx_dma_buf.tail || - uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { - uart->rx_dma_buf.head = pos; - bfin_serial_dma_rx_chars(uart); - uart->rx_dma_buf.tail = uart->rx_dma_buf.head; - } - - spin_unlock(&uart->rx_lock); - - return IRQ_HANDLED; -} -#endif - -/* - * Return TIOCSER_TEMT when transmitter is not busy. - */ -static unsigned int bfin_serial_tx_empty(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - unsigned int lsr; - - lsr = UART_GET_LSR(uart); - if (lsr & TEMT) - return TIOCSER_TEMT; - else - return 0; -} - -static void bfin_serial_break_ctl(struct uart_port *port, int break_state) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - u32 lcr = UART_GET_LCR(uart); - if (break_state) - lcr |= SB; - else - lcr &= ~SB; - UART_PUT_LCR(uart, lcr); - SSYNC(); -} - -static int bfin_serial_startup(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - -#ifdef CONFIG_SERIAL_BFIN_DMA - dma_addr_t dma_handle; - - if (request_dma(uart->rx_dma_channel, "BFIN_UART_RX") < 0) { - printk(KERN_NOTICE "Unable to attach Blackfin UART RX DMA channel\n"); - return -EBUSY; - } - - if (request_dma(uart->tx_dma_channel, "BFIN_UART_TX") < 0) { - printk(KERN_NOTICE "Unable to attach Blackfin UART TX DMA channel\n"); - free_dma(uart->rx_dma_channel); - return -EBUSY; - } - - set_dma_callback(uart->rx_dma_channel, bfin_serial_dma_rx_int, uart); - set_dma_callback(uart->tx_dma_channel, bfin_serial_dma_tx_int, uart); - - uart->rx_dma_buf.buf = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_DMA); - uart->rx_dma_buf.head = 0; - uart->rx_dma_buf.tail = 0; - uart->rx_dma_nrows = 0; - - set_dma_config(uart->rx_dma_channel, - set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO, - INTR_ON_ROW, DIMENSION_2D, - DATA_SIZE_8, - DMA_SYNC_RESTART)); - set_dma_x_count(uart->rx_dma_channel, DMA_RX_XCOUNT); - set_dma_x_modify(uart->rx_dma_channel, 1); - set_dma_y_count(uart->rx_dma_channel, DMA_RX_YCOUNT); - set_dma_y_modify(uart->rx_dma_channel, 1); - set_dma_start_addr(uart->rx_dma_channel, (unsigned long)uart->rx_dma_buf.buf); - enable_dma(uart->rx_dma_channel); - - uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; - add_timer(&(uart->rx_dma_timer)); -#else -# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) - if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled) - kgdboc_break_enabled = 0; - else { -# endif - if (request_irq(uart->rx_irq, bfin_serial_rx_int, 0, - "BFIN_UART_RX", uart)) { - printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); - return -EBUSY; - } - - if (request_irq - (uart->tx_irq, bfin_serial_tx_int, 0, - "BFIN_UART_TX", uart)) { - printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n"); - free_irq(uart->rx_irq, uart); - return -EBUSY; - } - -# ifdef CONFIG_BF54x - { - /* - * UART2 and UART3 on BF548 share interrupt PINs and DMA - * controllers with SPORT2 and SPORT3. UART rx and tx - * interrupts are generated in PIO mode only when configure - * their peripheral mapping registers properly, which means - * request corresponding DMA channels in PIO mode as well. - */ - unsigned uart_dma_ch_rx, uart_dma_ch_tx; - - switch (uart->rx_irq) { - case IRQ_UART3_RX: - uart_dma_ch_rx = CH_UART3_RX; - uart_dma_ch_tx = CH_UART3_TX; - break; - case IRQ_UART2_RX: - uart_dma_ch_rx = CH_UART2_RX; - uart_dma_ch_tx = CH_UART2_TX; - break; - default: - uart_dma_ch_rx = uart_dma_ch_tx = 0; - break; - } - - if (uart_dma_ch_rx && - request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { - printk(KERN_NOTICE"Fail to attach UART interrupt\n"); - free_irq(uart->rx_irq, uart); - free_irq(uart->tx_irq, uart); - return -EBUSY; - } - if (uart_dma_ch_tx && - request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) { - printk(KERN_NOTICE "Fail to attach UART interrupt\n"); - free_dma(uart_dma_ch_rx); - free_irq(uart->rx_irq, uart); - free_irq(uart->tx_irq, uart); - return -EBUSY; - } - } -# endif -# if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ - defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) - } -# endif -#endif - -#ifdef SERIAL_BFIN_CTSRTS - if (uart->cts_pin >= 0) { - if (request_irq(gpio_to_irq(uart->cts_pin), - bfin_serial_mctrl_cts_int, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | - 0, "BFIN_UART_CTS", uart)) { - uart->cts_pin = -1; - pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); - } - } - if (uart->rts_pin >= 0) { - if (gpio_request(uart->rts_pin, DRIVER_NAME)) { - pr_info("fail to request RTS PIN at GPIO_%d\n", uart->rts_pin); - uart->rts_pin = -1; - } else - gpio_direction_output(uart->rts_pin, 0); - } -#endif -#ifdef SERIAL_BFIN_HARD_CTSRTS - if (uart->cts_pin >= 0) { - if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int, - 0, "BFIN_UART_MODEM_STATUS", uart)) { - uart->cts_pin = -1; - dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n"); - } - - /* CTS RTS PINs are negative assertive. */ - UART_PUT_MCR(uart, UART_GET_MCR(uart) | ACTS); - UART_SET_IER(uart, EDSSI); - } -#endif - - UART_SET_IER(uart, ERBFI); - return 0; -} - -static void bfin_serial_shutdown(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - -#ifdef CONFIG_SERIAL_BFIN_DMA - disable_dma(uart->tx_dma_channel); - free_dma(uart->tx_dma_channel); - disable_dma(uart->rx_dma_channel); - free_dma(uart->rx_dma_channel); - del_timer(&(uart->rx_dma_timer)); - dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0); -#else -#ifdef CONFIG_BF54x - switch (uart->port.irq) { - case IRQ_UART3_RX: - free_dma(CH_UART3_RX); - free_dma(CH_UART3_TX); - break; - case IRQ_UART2_RX: - free_dma(CH_UART2_RX); - free_dma(CH_UART2_TX); - break; - default: - break; - } -#endif - free_irq(uart->rx_irq, uart); - free_irq(uart->tx_irq, uart); -#endif - -#ifdef SERIAL_BFIN_CTSRTS - if (uart->cts_pin >= 0) - free_irq(gpio_to_irq(uart->cts_pin), uart); - if (uart->rts_pin >= 0) - gpio_free(uart->rts_pin); -#endif -#ifdef SERIAL_BFIN_HARD_CTSRTS - if (uart->cts_pin >= 0) - free_irq(uart->status_irq, uart); -#endif -} - -static void -bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - unsigned long flags; - unsigned int baud, quot; - unsigned int ier, lcr = 0; - unsigned long timeout; - -#ifdef SERIAL_BFIN_CTSRTS - if (old == NULL && uart->cts_pin != -1) - termios->c_cflag |= CRTSCTS; - else if (uart->cts_pin == -1) - termios->c_cflag &= ~CRTSCTS; -#endif - - switch (termios->c_cflag & CSIZE) { - case CS8: - lcr = WLS(8); - break; - case CS7: - lcr = WLS(7); - break; - case CS6: - lcr = WLS(6); - break; - case CS5: - lcr = WLS(5); - break; - default: - printk(KERN_ERR "%s: word length not supported\n", - __func__); - } - - /* Anomaly notes: - * 05000231 - STOP bit is always set to 1 whatever the user is set. - */ - if (termios->c_cflag & CSTOPB) { - if (ANOMALY_05000231) - printk(KERN_WARNING "STOP bits other than 1 is not " - "supported in case of anomaly 05000231.\n"); - else - lcr |= STB; - } - if (termios->c_cflag & PARENB) - lcr |= PEN; - if (!(termios->c_cflag & PARODD)) - lcr |= EPS; - if (termios->c_cflag & CMSPAR) - lcr |= STP; - - spin_lock_irqsave(&uart->port.lock, flags); - - port->read_status_mask = OE; - if (termios->c_iflag & INPCK) - port->read_status_mask |= (FE | PE); - if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= BI; - - /* - * Characters to ignore - */ - port->ignore_status_mask = 0; - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= FE | PE; - if (termios->c_iflag & IGNBRK) { - port->ignore_status_mask |= BI; - /* - * If we're ignoring parity and break indicators, - * ignore overruns too (for real raw support). - */ - if (termios->c_iflag & IGNPAR) - port->ignore_status_mask |= OE; - } - - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - /* If discipline is not IRDA, apply ANOMALY_05000230 */ - if (termios->c_line != N_IRDA) - quot -= ANOMALY_05000230; - - UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15); - - /* Wait till the transfer buffer is empty */ - timeout = jiffies + msecs_to_jiffies(10); - while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT)) - if (time_after(jiffies, timeout)) { - dev_warn(port->dev, "timeout waiting for TX buffer empty\n"); - break; - } - - /* Disable UART */ - ier = UART_GET_IER(uart); - UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN); - UART_DISABLE_INTS(uart); - - /* Set DLAB in LCR to Access CLK */ - UART_SET_DLAB(uart); - - UART_PUT_CLK(uart, quot); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - UART_CLEAR_DLAB(uart); - - UART_PUT_LCR(uart, (UART_GET_LCR(uart) & ~LCR_MASK) | lcr); - - /* Enable UART */ - UART_ENABLE_INTS(uart, ier); - UART_PUT_GCTL(uart, UART_GET_GCTL(uart) | UCEN); - - /* Port speed changed, update the per-port timeout. */ - uart_update_timeout(port, termios->c_cflag, baud); - - spin_unlock_irqrestore(&uart->port.lock, flags); -} - -static const char *bfin_serial_type(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - - return uart->port.type == PORT_BFIN ? "BFIN-UART" : NULL; -} - -/* - * Release the memory region(s) being used by 'port'. - */ -static void bfin_serial_release_port(struct uart_port *port) -{ -} - -/* - * Request the memory region(s) being used by 'port'. - */ -static int bfin_serial_request_port(struct uart_port *port) -{ - return 0; -} - -/* - * Configure/autoconfigure the port. - */ -static void bfin_serial_config_port(struct uart_port *port, int flags) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - - if (flags & UART_CONFIG_TYPE && - bfin_serial_request_port(&uart->port) == 0) - uart->port.type = PORT_BFIN; -} - -/* - * Verify the new serial_struct (for TIOCSSERIAL). - * The only change we allow are to the flags and type, and - * even then only between PORT_BFIN and PORT_UNKNOWN - */ -static int -bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - return 0; -} - -/* - * 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, - struct ktermios *termios) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - unsigned int val; - - switch (termios->c_line) { - case N_IRDA: - val = UART_GET_GCTL(uart); - val |= (UMOD_IRDA | RPOLC); - UART_PUT_GCTL(uart, val); - break; - default: - val = UART_GET_GCTL(uart); - val &= ~(UMOD_MASK | RPOLC); - UART_PUT_GCTL(uart, val); - } -} - -static void bfin_serial_reset_irda(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - unsigned int val; - - val = UART_GET_GCTL(uart); - val &= ~(UMOD_MASK | RPOLC); - UART_PUT_GCTL(uart, val); - SSYNC(); - val |= (UMOD_IRDA | RPOLC); - UART_PUT_GCTL(uart, val); - SSYNC(); -} - -#ifdef CONFIG_CONSOLE_POLL -/* Anomaly notes: - * 05000099 - Because we only use THRE in poll_put and DR in poll_get, - * losing other bits of UART_LSR is not a problem here. - */ -static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - - while (!(UART_GET_LSR(uart) & THRE)) - cpu_relax(); - - UART_CLEAR_DLAB(uart); - UART_PUT_CHAR(uart, (unsigned char)chr); -} - -static int bfin_serial_poll_get_char(struct uart_port *port) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - unsigned char chr; - - while (!(UART_GET_LSR(uart) & DR)) - cpu_relax(); - - UART_CLEAR_DLAB(uart); - chr = UART_GET_CHAR(uart); - - return chr; -} -#endif - -static struct uart_ops bfin_serial_pops = { - .tx_empty = bfin_serial_tx_empty, - .set_mctrl = bfin_serial_set_mctrl, - .get_mctrl = bfin_serial_get_mctrl, - .stop_tx = bfin_serial_stop_tx, - .start_tx = bfin_serial_start_tx, - .stop_rx = bfin_serial_stop_rx, - .break_ctl = bfin_serial_break_ctl, - .startup = bfin_serial_startup, - .shutdown = bfin_serial_shutdown, - .set_termios = bfin_serial_set_termios, - .set_ldisc = bfin_serial_set_ldisc, - .type = bfin_serial_type, - .release_port = bfin_serial_release_port, - .request_port = bfin_serial_request_port, - .config_port = bfin_serial_config_port, - .verify_port = bfin_serial_verify_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_put_char = bfin_serial_poll_put_char, - .poll_get_char = bfin_serial_poll_get_char, -#endif -}; - -#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK) -/* - * If the port was already initialised (eg, by a boot loader), - * try to determine the current setup. - */ -static void __init -bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, - int *parity, int *bits) -{ - unsigned int status; - - status = UART_GET_IER(uart) & (ERBFI | ETBEI); - if (status == (ERBFI | ETBEI)) { - /* ok, the port was enabled */ - u32 lcr, clk; - - lcr = UART_GET_LCR(uart); - - *parity = 'n'; - if (lcr & PEN) { - if (lcr & EPS) - *parity = 'e'; - else - *parity = 'o'; - } - *bits = ((lcr & WLS_MASK) >> WLS_OFFSET) + 5; - - /* Set DLAB in LCR to Access CLK */ - UART_SET_DLAB(uart); - - clk = UART_GET_CLK(uart); - - /* Clear DLAB in LCR to Access THR RBR IER */ - UART_CLEAR_DLAB(uart); - - *baud = get_sclk() / (16*clk); - } - pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits); -} - -static struct uart_driver bfin_serial_reg; - -static void bfin_serial_console_putchar(struct uart_port *port, int ch) -{ - struct bfin_serial_port *uart = (struct bfin_serial_port *)port; - while (!(UART_GET_LSR(uart) & THRE)) - barrier(); - UART_PUT_CHAR(uart, ch); -} - -#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) || - defined (CONFIG_EARLY_PRINTK) */ - -#ifdef CONFIG_SERIAL_BFIN_CONSOLE -#define CLASS_BFIN_CONSOLE "bfin-console" -/* - * Interrupts are disabled on entering - */ -static void -bfin_serial_console_write(struct console *co, const char *s, unsigned int count) -{ - struct bfin_serial_port *uart = bfin_serial_ports[co->index]; - unsigned long flags; - - spin_lock_irqsave(&uart->port.lock, flags); - uart_console_write(&uart->port, s, count, bfin_serial_console_putchar); - spin_unlock_irqrestore(&uart->port.lock, flags); - -} - -static int __init -bfin_serial_console_setup(struct console *co, char *options) -{ - struct bfin_serial_port *uart; - int baud = 57600; - int bits = 8; - int parity = 'n'; -# if defined(SERIAL_BFIN_CTSRTS) || \ - defined(SERIAL_BFIN_HARD_CTSRTS) - int flow = 'r'; -# else - int flow = 'n'; -# endif - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index < 0 || co->index >= BFIN_UART_NR_PORTS) - return -ENODEV; - - uart = bfin_serial_ports[co->index]; - if (!uart) - return -ENODEV; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else - bfin_serial_console_get_options(uart, &baud, &parity, &bits); - - return uart_set_options(&uart->port, co, baud, parity, bits, flow); -} - -static struct console bfin_serial_console = { - .name = BFIN_SERIAL_DEV_NAME, - .write = bfin_serial_console_write, - .device = uart_console_device, - .setup = bfin_serial_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &bfin_serial_reg, -}; -#define BFIN_SERIAL_CONSOLE (&bfin_serial_console) -#else -#define BFIN_SERIAL_CONSOLE NULL -#endif /* CONFIG_SERIAL_BFIN_CONSOLE */ - -#ifdef CONFIG_EARLY_PRINTK -static struct bfin_serial_port bfin_earlyprintk_port; -#define CLASS_BFIN_EARLYPRINTK "bfin-earlyprintk" - -/* - * Interrupts are disabled on entering - */ -static void -bfin_earlyprintk_console_write(struct console *co, const char *s, unsigned int count) -{ - unsigned long flags; - - if (bfin_earlyprintk_port.port.line != co->index) - return; - - spin_lock_irqsave(&bfin_earlyprintk_port.port.lock, flags); - uart_console_write(&bfin_earlyprintk_port.port, s, count, - bfin_serial_console_putchar); - spin_unlock_irqrestore(&bfin_earlyprintk_port.port.lock, flags); -} - -/* - * This should have a .setup or .early_setup in it, but then things get called - * without the command line options, and the baud rate gets messed up - so - * don't let the common infrastructure play with things. (see calls to setup - * & earlysetup in ./kernel/printk.c:register_console() - */ -static struct console bfin_early_serial_console __initdata = { - .name = "early_BFuart", - .write = bfin_earlyprintk_console_write, - .device = uart_console_device, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &bfin_serial_reg, -}; -#endif - -static struct uart_driver bfin_serial_reg = { - .owner = THIS_MODULE, - .driver_name = DRIVER_NAME, - .dev_name = BFIN_SERIAL_DEV_NAME, - .major = BFIN_SERIAL_MAJOR, - .minor = BFIN_SERIAL_MINOR, - .nr = BFIN_UART_NR_PORTS, - .cons = BFIN_SERIAL_CONSOLE, -}; - -static int bfin_serial_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct bfin_serial_port *uart = platform_get_drvdata(pdev); - - return uart_suspend_port(&bfin_serial_reg, &uart->port); -} - -static int bfin_serial_resume(struct platform_device *pdev) -{ - struct bfin_serial_port *uart = platform_get_drvdata(pdev); - - return uart_resume_port(&bfin_serial_reg, &uart->port); -} - -static int bfin_serial_probe(struct platform_device *pdev) -{ - struct resource *res; - struct bfin_serial_port *uart = NULL; - int ret = 0; - - if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) { - dev_err(&pdev->dev, "Wrong bfin uart platform device id.\n"); - return -ENOENT; - } - - if (bfin_serial_ports[pdev->id] == NULL) { - - uart = kzalloc(sizeof(*uart), GFP_KERNEL); - if (!uart) { - dev_err(&pdev->dev, - "fail to malloc bfin_serial_port\n"); - return -ENOMEM; - } - bfin_serial_ports[pdev->id] = uart; - -#ifdef CONFIG_EARLY_PRINTK - if (!(bfin_earlyprintk_port.port.membase - && bfin_earlyprintk_port.port.line == pdev->id)) { - /* - * If the peripheral PINs of current port is allocated - * in earlyprintk probe stage, don't do it again. - */ -#endif - ret = peripheral_request_list( - dev_get_platdata(&pdev->dev), - DRIVER_NAME); - if (ret) { - dev_err(&pdev->dev, - "fail to request bfin serial peripherals\n"); - goto out_error_free_mem; - } -#ifdef CONFIG_EARLY_PRINTK - } -#endif - - spin_lock_init(&uart->port.lock); - uart->port.uartclk = get_sclk(); - uart->port.fifosize = BFIN_UART_TX_FIFO_SIZE; - uart->port.ops = &bfin_serial_pops; - uart->port.line = pdev->id; - uart->port.iotype = UPIO_MEM; - uart->port.flags = UPF_BOOT_AUTOCONF; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); - ret = -ENOENT; - goto out_error_free_peripherals; - } - - uart->port.membase = ioremap(res->start, resource_size(res)); - if (!uart->port.membase) { - dev_err(&pdev->dev, "Cannot map uart IO\n"); - ret = -ENXIO; - goto out_error_free_peripherals; - } - uart->port.mapbase = res->start; - - uart->tx_irq = platform_get_irq(pdev, 0); - if (uart->tx_irq < 0) { - dev_err(&pdev->dev, "No uart TX IRQ specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - - uart->rx_irq = platform_get_irq(pdev, 1); - if (uart->rx_irq < 0) { - dev_err(&pdev->dev, "No uart RX IRQ specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - uart->port.irq = uart->rx_irq; - - uart->status_irq = platform_get_irq(pdev, 2); - if (uart->status_irq < 0) { - dev_err(&pdev->dev, "No uart status IRQ specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - -#ifdef CONFIG_SERIAL_BFIN_DMA - spin_lock_init(&uart->rx_lock); - uart->tx_done = 1; - uart->tx_count = 0; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res == NULL) { - dev_err(&pdev->dev, "No uart TX DMA channel specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - uart->tx_dma_channel = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res == NULL) { - dev_err(&pdev->dev, "No uart RX DMA channel specified\n"); - ret = -ENOENT; - goto out_error_unmap; - } - uart->rx_dma_channel = res->start; - - timer_setup(&uart->rx_dma_timer, bfin_serial_rx_dma_timeout, 0); -#endif - -#if defined(SERIAL_BFIN_CTSRTS) || \ - defined(SERIAL_BFIN_HARD_CTSRTS) - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (res == NULL) - uart->cts_pin = -1; - else - uart->cts_pin = res->start; - - res = platform_get_resource(pdev, IORESOURCE_IO, 1); - if (res == NULL) - uart->rts_pin = -1; - else - uart->rts_pin = res->start; -#endif - } - -#ifdef CONFIG_SERIAL_BFIN_CONSOLE - if (!is_early_platform_device(pdev)) { -#endif - uart = bfin_serial_ports[pdev->id]; - uart->port.dev = &pdev->dev; - dev_set_drvdata(&pdev->dev, uart); - ret = uart_add_one_port(&bfin_serial_reg, &uart->port); -#ifdef CONFIG_SERIAL_BFIN_CONSOLE - } -#endif - - if (!ret) - return 0; - - if (uart) { -out_error_unmap: - iounmap(uart->port.membase); -out_error_free_peripherals: - peripheral_free_list(dev_get_platdata(&pdev->dev)); -out_error_free_mem: - kfree(uart); - bfin_serial_ports[pdev->id] = NULL; - } - - return ret; -} - -static int bfin_serial_remove(struct platform_device *pdev) -{ - struct bfin_serial_port *uart = platform_get_drvdata(pdev); - - dev_set_drvdata(&pdev->dev, NULL); - - if (uart) { - uart_remove_one_port(&bfin_serial_reg, &uart->port); - iounmap(uart->port.membase); - peripheral_free_list(dev_get_platdata(&pdev->dev)); - kfree(uart); - bfin_serial_ports[pdev->id] = NULL; - } - - return 0; -} - -static struct platform_driver bfin_serial_driver = { - .probe = bfin_serial_probe, - .remove = bfin_serial_remove, - .suspend = bfin_serial_suspend, - .resume = bfin_serial_resume, - .driver = { - .name = DRIVER_NAME, - }, -}; - -#if defined(CONFIG_SERIAL_BFIN_CONSOLE) -static struct early_platform_driver early_bfin_serial_driver __initdata = { - .class_str = CLASS_BFIN_CONSOLE, - .pdrv = &bfin_serial_driver, - .requested_id = EARLY_PLATFORM_ID_UNSET, -}; - -static int __init bfin_serial_rs_console_init(void) -{ - early_platform_driver_register(&early_bfin_serial_driver, DRIVER_NAME); - - early_platform_driver_probe(CLASS_BFIN_CONSOLE, BFIN_UART_NR_PORTS, 0); - - register_console(&bfin_serial_console); - - return 0; -} -console_initcall(bfin_serial_rs_console_init); -#endif - -#ifdef CONFIG_EARLY_PRINTK -/* - * Memory can't be allocated dynamically during earlyprink init stage. - * So, do individual probe for earlyprink with a static uart port variable. - */ -static int bfin_earlyprintk_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret; - - if (pdev->id < 0 || pdev->id >= BFIN_UART_NR_PORTS) { - dev_err(&pdev->dev, "Wrong earlyprintk platform device id.\n"); - return -ENOENT; - } - - ret = peripheral_request_list(dev_get_platdata(&pdev->dev), - DRIVER_NAME); - if (ret) { - dev_err(&pdev->dev, - "fail to request bfin serial peripherals\n"); - return ret; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); - ret = -ENOENT; - goto out_error_free_peripherals; - } - - bfin_earlyprintk_port.port.membase = ioremap(res->start, - resource_size(res)); - if (!bfin_earlyprintk_port.port.membase) { - dev_err(&pdev->dev, "Cannot map uart IO\n"); - ret = -ENXIO; - goto out_error_free_peripherals; - } - bfin_earlyprintk_port.port.mapbase = res->start; - bfin_earlyprintk_port.port.line = pdev->id; - bfin_earlyprintk_port.port.uartclk = get_sclk(); - bfin_earlyprintk_port.port.fifosize = BFIN_UART_TX_FIFO_SIZE; - spin_lock_init(&bfin_earlyprintk_port.port.lock); - - return 0; - -out_error_free_peripherals: - peripheral_free_list(dev_get_platdata(&pdev->dev)); - - return ret; -} - -static struct platform_driver bfin_earlyprintk_driver = { - .probe = bfin_earlyprintk_probe, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -static struct early_platform_driver early_bfin_earlyprintk_driver __initdata = { - .class_str = CLASS_BFIN_EARLYPRINTK, - .pdrv = &bfin_earlyprintk_driver, - .requested_id = EARLY_PLATFORM_ID_UNSET, -}; - -struct console __init *bfin_earlyserial_init(unsigned int port, - unsigned int cflag) -{ - struct ktermios t; - char port_name[20]; - - if (port < 0 || port >= BFIN_UART_NR_PORTS) - return NULL; - - /* - * Only probe resource of the given port in earlyprintk boot arg. - * The expected port id should be indicated in port name string. - */ - snprintf(port_name, 20, DRIVER_NAME ".%d", port); - early_platform_driver_register(&early_bfin_earlyprintk_driver, - port_name); - early_platform_driver_probe(CLASS_BFIN_EARLYPRINTK, 1, 0); - - if (!bfin_earlyprintk_port.port.membase) - return NULL; - -#ifdef CONFIG_SERIAL_BFIN_CONSOLE - /* - * If we are using early serial, don't let the normal console rewind - * log buffer, since that causes things to be printed multiple times - */ - bfin_serial_console.flags &= ~CON_PRINTBUFFER; -#endif - - bfin_early_serial_console.index = port; - t.c_cflag = cflag; - t.c_iflag = 0; - t.c_oflag = 0; - t.c_lflag = ICANON; - t.c_line = port; - bfin_serial_set_termios(&bfin_earlyprintk_port.port, &t, &t); - - return &bfin_early_serial_console; -} -#endif /* CONFIG_EARLY_PRINTK */ - -static int __init bfin_serial_init(void) -{ - int ret; - - pr_info("Blackfin serial driver\n"); - - ret = uart_register_driver(&bfin_serial_reg); - if (ret) { - pr_err("failed to register %s:%d\n", - bfin_serial_reg.driver_name, ret); - } - - ret = platform_driver_register(&bfin_serial_driver); - if (ret) { - pr_err("fail to register bfin uart\n"); - uart_unregister_driver(&bfin_serial_reg); - } - - return ret; -} - -static void __exit bfin_serial_exit(void) -{ - platform_driver_unregister(&bfin_serial_driver); - uart_unregister_driver(&bfin_serial_reg); -} - - -module_init(bfin_serial_init); -module_exit(bfin_serial_exit); - -MODULE_AUTHOR("Sonic Zhang, Aubrey Li"); -MODULE_DESCRIPTION("Blackfin generic serial port driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR); -MODULE_ALIAS("platform:bfin-uart"); diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c deleted file mode 100644 index c9458a033e3c..000000000000 --- a/drivers/tty/serial/crisv10.c +++ /dev/null @@ -1,4248 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Serial port driver for the ETRAX 100LX chip - * - * Copyright (C) 1998-2007 Axis Communications AB - * - * Many, many authors. Based once upon a time on serial.c for 16x50. - * - */ - -static char *serial_version = "$Revision: 1.25 $"; - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/sched/signal.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/major.h> -#include <linux/string.h> -#include <linux/fcntl.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/mutex.h> -#include <linux/bitops.h> -#include <linux/seq_file.h> -#include <linux/delay.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -#include <asm/irq.h> -#include <asm/dma.h> - -#include <arch/svinto.h> -#include <arch/system.h> - -/* non-arch dependent serial structures are in linux/serial.h */ -#include <linux/serial.h> -/* while we keep our own stuff (struct e100_serial) in a local .h file */ -#include "crisv10.h" -#include <asm/fasttimer.h> -#include <arch/io_interface_mux.h> - -#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER -#ifndef CONFIG_ETRAX_FAST_TIMER -#error "Enable FAST_TIMER to use SERIAL_FAST_TIMER" -#endif -#endif - -#if defined(CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS) && \ - (CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS == 0) -#error "RX_TIMEOUT_TICKS == 0 not allowed, use 1" -#endif - -/* - * All of the compatibilty code so we can compile serial.c against - * older kernels is hidden in serial_compat.h - */ -#if defined(LOCAL_HEADERS) -#include "serial_compat.h" -#endif - -struct tty_driver *serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -//#define SERIAL_DEBUG_INTR -//#define SERIAL_DEBUG_OPEN -//#define SERIAL_DEBUG_FLOW -//#define SERIAL_DEBUG_DATA -//#define SERIAL_DEBUG_THROTTLE -//#define SERIAL_DEBUG_IO /* Debug for Extra control and status pins */ -//#define SERIAL_DEBUG_LINE 0 /* What serport we want to debug */ - -/* Enable this to use serial interrupts to handle when you - expect the first received event on the serial port to - be an error, break or similar. Used to be able to flash IRMA - from eLinux */ -#define SERIAL_HANDLE_EARLY_ERRORS - -/* Currently 16 descriptors x 128 bytes = 2048 bytes */ -#define SERIAL_DESCR_BUF_SIZE 256 - -#define SERIAL_PRESCALE_BASE 3125000 /* 3.125MHz */ -#define DEF_BAUD_BASE SERIAL_PRESCALE_BASE - -/* We don't want to load the system with massive fast timer interrupt - * on high baudrates so limit it to 250 us (4kHz) */ -#define MIN_FLUSH_TIME_USEC 250 - -/* Add an x here to log a lot of timer stuff */ -#define TIMERD(x) -/* Debug details of interrupt handling */ -#define DINTR1(x) /* irq on/off, errors */ -#define DINTR2(x) /* tx and rx */ -/* Debug flip buffer stuff */ -#define DFLIP(x) -/* Debug flow control and overview of data flow */ -#define DFLOW(x) -#define DBAUD(x) -#define DLOG_INT_TRIG(x) - -//#define DEBUG_LOG_INCLUDED -#ifndef DEBUG_LOG_INCLUDED -#define DEBUG_LOG(line, string, value) -#else -struct debug_log_info -{ - unsigned long time; - unsigned long timer_data; -// int line; - const char *string; - int value; -}; -#define DEBUG_LOG_SIZE 4096 - -struct debug_log_info debug_log[DEBUG_LOG_SIZE]; -int debug_log_pos = 0; - -#define DEBUG_LOG(_line, _string, _value) do { \ - if ((_line) == SERIAL_DEBUG_LINE) {\ - debug_log_func(_line, _string, _value); \ - }\ -}while(0) - -void debug_log_func(int line, const char *string, int value) -{ - if (debug_log_pos < DEBUG_LOG_SIZE) { - debug_log[debug_log_pos].time = jiffies; - debug_log[debug_log_pos].timer_data = *R_TIMER_DATA; -// debug_log[debug_log_pos].line = line; - debug_log[debug_log_pos].string = string; - debug_log[debug_log_pos].value = value; - debug_log_pos++; - } - /*printk(string, value);*/ -} -#endif - -#ifndef CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS -/* Default number of timer ticks before flushing rx fifo - * When using "little data, low latency applications: use 0 - * When using "much data applications (PPP)" use ~5 - */ -#define CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS 5 -#endif - -unsigned long timer_data_to_ns(unsigned long timer_data); - -static void change_speed(struct e100_serial *info); -static void rs_throttle(struct tty_struct * tty); -static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -static int rs_write(struct tty_struct *tty, - const unsigned char *buf, int count); -#ifdef CONFIG_ETRAX_RS485 -static int e100_write_rs485(struct tty_struct *tty, - const unsigned char *buf, int count); -#endif -static int get_lsr_info(struct e100_serial *info, unsigned int *value); - - -#define DEF_BAUD 115200 /* 115.2 kbit/s */ -#define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */ -/* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */ -#define DEF_TX 0x80 /* or SERIAL_CTRL_B */ - -/* offsets from R_SERIALx_CTRL */ - -#define REG_DATA 0 -#define REG_DATA_STATUS32 0 /* this is the 32 bit register R_SERIALx_READ */ -#define REG_TR_DATA 0 -#define REG_STATUS 1 -#define REG_TR_CTRL 1 -#define REG_REC_CTRL 2 -#define REG_BAUD 3 -#define REG_XOFF 4 /* this is a 32 bit register */ - -/* The bitfields are the same for all serial ports */ -#define SER_RXD_MASK IO_MASK(R_SERIAL0_STATUS, rxd) -#define SER_DATA_AVAIL_MASK IO_MASK(R_SERIAL0_STATUS, data_avail) -#define SER_FRAMING_ERR_MASK IO_MASK(R_SERIAL0_STATUS, framing_err) -#define SER_PAR_ERR_MASK IO_MASK(R_SERIAL0_STATUS, par_err) -#define SER_OVERRUN_MASK IO_MASK(R_SERIAL0_STATUS, overrun) - -#define SER_ERROR_MASK (SER_OVERRUN_MASK | SER_PAR_ERR_MASK | SER_FRAMING_ERR_MASK) - -/* Values for info->errorcode */ -#define ERRCODE_SET_BREAK (TTY_BREAK) -#define ERRCODE_INSERT 0x100 -#define ERRCODE_INSERT_BREAK (ERRCODE_INSERT | TTY_BREAK) - -#define FORCE_EOP(info) *R_SET_EOP = 1U << info->iseteop; - -/* - * General note regarding the use of IO_* macros in this file: - * - * We will use the bits defined for DMA channel 6 when using various - * IO_* macros (e.g. IO_STATE, IO_MASK, IO_EXTRACT) and _assume_ they are - * the same for all channels (which of course they are). - * - * We will also use the bits defined for serial port 0 when writing commands - * to the different ports, as these bits too are the same for all ports. - */ - - -/* Mask for the irqs possibly enabled in R_IRQ_MASK1_RD etc. */ -static const unsigned long e100_ser_int_mask = 0 -#ifdef CONFIG_ETRAX_SERIAL_PORT0 -| IO_MASK(R_IRQ_MASK1_RD, ser0_data) | IO_MASK(R_IRQ_MASK1_RD, ser0_ready) -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT1 -| IO_MASK(R_IRQ_MASK1_RD, ser1_data) | IO_MASK(R_IRQ_MASK1_RD, ser1_ready) -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2 -| IO_MASK(R_IRQ_MASK1_RD, ser2_data) | IO_MASK(R_IRQ_MASK1_RD, ser2_ready) -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3 -| IO_MASK(R_IRQ_MASK1_RD, ser3_data) | IO_MASK(R_IRQ_MASK1_RD, ser3_ready) -#endif -; -unsigned long r_alt_ser_baudrate_shadow = 0; - -/* this is the data for the four serial ports in the etrax100 */ -/* DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */ -/* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */ - -static struct e100_serial rs_table[] = { - { .baud = DEF_BAUD, - .ioport = (unsigned char *)R_SERIAL0_CTRL, - .irq = 1U << 12, /* uses DMA 6 and 7 */ - .oclrintradr = R_DMA_CH6_CLR_INTR, - .ofirstadr = R_DMA_CH6_FIRST, - .ocmdadr = R_DMA_CH6_CMD, - .ostatusadr = R_DMA_CH6_STATUS, - .iclrintradr = R_DMA_CH7_CLR_INTR, - .ifirstadr = R_DMA_CH7_FIRST, - .icmdadr = R_DMA_CH7_CMD, - .idescradr = R_DMA_CH7_DESCR, - .rx_ctrl = DEF_RX, - .tx_ctrl = DEF_TX, - .iseteop = 2, - .dma_owner = dma_ser0, - .io_if = if_serial_0, -#ifdef CONFIG_ETRAX_SERIAL_PORT0 - .enabled = 1, -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT - .dma_out_enabled = 1, - .dma_out_nbr = SER0_TX_DMA_NBR, - .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, - .dma_out_irq_flags = 0, - .dma_out_irq_description = "serial 0 dma tr", -#else - .dma_out_enabled = 0, - .dma_out_nbr = UINT_MAX, - .dma_out_irq_nbr = 0, - .dma_out_irq_flags = 0, - .dma_out_irq_description = NULL, -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN - .dma_in_enabled = 1, - .dma_in_nbr = SER0_RX_DMA_NBR, - .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, - .dma_in_irq_flags = 0, - .dma_in_irq_description = "serial 0 dma rec", -#else - .dma_in_enabled = 0, - .dma_in_nbr = UINT_MAX, - .dma_in_irq_nbr = 0, - .dma_in_irq_flags = 0, - .dma_in_irq_description = NULL, -#endif -#else - .enabled = 0, - .io_if_description = NULL, - .dma_out_enabled = 0, - .dma_in_enabled = 0 -#endif - -}, /* ttyS0 */ - { .baud = DEF_BAUD, - .ioport = (unsigned char *)R_SERIAL1_CTRL, - .irq = 1U << 16, /* uses DMA 8 and 9 */ - .oclrintradr = R_DMA_CH8_CLR_INTR, - .ofirstadr = R_DMA_CH8_FIRST, - .ocmdadr = R_DMA_CH8_CMD, - .ostatusadr = R_DMA_CH8_STATUS, - .iclrintradr = R_DMA_CH9_CLR_INTR, - .ifirstadr = R_DMA_CH9_FIRST, - .icmdadr = R_DMA_CH9_CMD, - .idescradr = R_DMA_CH9_DESCR, - .rx_ctrl = DEF_RX, - .tx_ctrl = DEF_TX, - .iseteop = 3, - .dma_owner = dma_ser1, - .io_if = if_serial_1, -#ifdef CONFIG_ETRAX_SERIAL_PORT1 - .enabled = 1, - .io_if_description = "ser1", -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA8_OUT - .dma_out_enabled = 1, - .dma_out_nbr = SER1_TX_DMA_NBR, - .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, - .dma_out_irq_flags = 0, - .dma_out_irq_description = "serial 1 dma tr", -#else - .dma_out_enabled = 0, - .dma_out_nbr = UINT_MAX, - .dma_out_irq_nbr = 0, - .dma_out_irq_flags = 0, - .dma_out_irq_description = NULL, -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT1_DMA9_IN - .dma_in_enabled = 1, - .dma_in_nbr = SER1_RX_DMA_NBR, - .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, - .dma_in_irq_flags = 0, - .dma_in_irq_description = "serial 1 dma rec", -#else - .dma_in_enabled = 0, - .dma_in_enabled = 0, - .dma_in_nbr = UINT_MAX, - .dma_in_irq_nbr = 0, - .dma_in_irq_flags = 0, - .dma_in_irq_description = NULL, -#endif -#else - .enabled = 0, - .io_if_description = NULL, - .dma_in_irq_nbr = 0, - .dma_out_enabled = 0, - .dma_in_enabled = 0 -#endif -}, /* ttyS1 */ - - { .baud = DEF_BAUD, - .ioport = (unsigned char *)R_SERIAL2_CTRL, - .irq = 1U << 4, /* uses DMA 2 and 3 */ - .oclrintradr = R_DMA_CH2_CLR_INTR, - .ofirstadr = R_DMA_CH2_FIRST, - .ocmdadr = R_DMA_CH2_CMD, - .ostatusadr = R_DMA_CH2_STATUS, - .iclrintradr = R_DMA_CH3_CLR_INTR, - .ifirstadr = R_DMA_CH3_FIRST, - .icmdadr = R_DMA_CH3_CMD, - .idescradr = R_DMA_CH3_DESCR, - .rx_ctrl = DEF_RX, - .tx_ctrl = DEF_TX, - .iseteop = 0, - .dma_owner = dma_ser2, - .io_if = if_serial_2, -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - .enabled = 1, - .io_if_description = "ser2", -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT - .dma_out_enabled = 1, - .dma_out_nbr = SER2_TX_DMA_NBR, - .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, - .dma_out_irq_flags = 0, - .dma_out_irq_description = "serial 2 dma tr", -#else - .dma_out_enabled = 0, - .dma_out_nbr = UINT_MAX, - .dma_out_irq_nbr = 0, - .dma_out_irq_flags = 0, - .dma_out_irq_description = NULL, -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN - .dma_in_enabled = 1, - .dma_in_nbr = SER2_RX_DMA_NBR, - .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, - .dma_in_irq_flags = 0, - .dma_in_irq_description = "serial 2 dma rec", -#else - .dma_in_enabled = 0, - .dma_in_nbr = UINT_MAX, - .dma_in_irq_nbr = 0, - .dma_in_irq_flags = 0, - .dma_in_irq_description = NULL, -#endif -#else - .enabled = 0, - .io_if_description = NULL, - .dma_out_enabled = 0, - .dma_in_enabled = 0 -#endif - }, /* ttyS2 */ - - { .baud = DEF_BAUD, - .ioport = (unsigned char *)R_SERIAL3_CTRL, - .irq = 1U << 8, /* uses DMA 4 and 5 */ - .oclrintradr = R_DMA_CH4_CLR_INTR, - .ofirstadr = R_DMA_CH4_FIRST, - .ocmdadr = R_DMA_CH4_CMD, - .ostatusadr = R_DMA_CH4_STATUS, - .iclrintradr = R_DMA_CH5_CLR_INTR, - .ifirstadr = R_DMA_CH5_FIRST, - .icmdadr = R_DMA_CH5_CMD, - .idescradr = R_DMA_CH5_DESCR, - .rx_ctrl = DEF_RX, - .tx_ctrl = DEF_TX, - .iseteop = 1, - .dma_owner = dma_ser3, - .io_if = if_serial_3, -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - .enabled = 1, - .io_if_description = "ser3", -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT - .dma_out_enabled = 1, - .dma_out_nbr = SER3_TX_DMA_NBR, - .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, - .dma_out_irq_flags = 0, - .dma_out_irq_description = "serial 3 dma tr", -#else - .dma_out_enabled = 0, - .dma_out_nbr = UINT_MAX, - .dma_out_irq_nbr = 0, - .dma_out_irq_flags = 0, - .dma_out_irq_description = NULL, -#endif -#ifdef CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN - .dma_in_enabled = 1, - .dma_in_nbr = SER3_RX_DMA_NBR, - .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, - .dma_in_irq_flags = 0, - .dma_in_irq_description = "serial 3 dma rec", -#else - .dma_in_enabled = 0, - .dma_in_nbr = UINT_MAX, - .dma_in_irq_nbr = 0, - .dma_in_irq_flags = 0, - .dma_in_irq_description = NULL -#endif -#else - .enabled = 0, - .io_if_description = NULL, - .dma_out_enabled = 0, - .dma_in_enabled = 0 -#endif - } /* ttyS3 */ -}; - - -#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) - -#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER -static struct fast_timer fast_timers[NR_PORTS]; -#endif - -/* RS-485 */ -#if defined(CONFIG_ETRAX_RS485) -#ifdef CONFIG_ETRAX_FAST_TIMER -static struct fast_timer fast_timers_rs485[NR_PORTS]; -#endif -#if defined(CONFIG_ETRAX_RS485_ON_PA) -static int rs485_pa_bit = CONFIG_ETRAX_RS485_ON_PA_BIT; -#endif -#endif - -/* Info and macros needed for each ports extra control/status signals. */ -#define E100_STRUCT_PORT(line, pinname) \ - ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \ - (R_PORT_PA_DATA): ( \ - (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \ - (R_PORT_PB_DATA):&dummy_ser[line])) - -#define E100_STRUCT_SHADOW(line, pinname) \ - ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \ - (&port_pa_data_shadow): ( \ - (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \ - (&port_pb_data_shadow):&dummy_ser[line])) -#define E100_STRUCT_MASK(line, pinname) \ - ((CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT >= 0)? \ - (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PA_BIT): ( \ - (CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT >= 0)? \ - (1<<CONFIG_ETRAX_SER##line##_##pinname##_ON_PB_BIT):DUMMY_##pinname##_MASK)) - -#define DUMMY_DTR_MASK 1 -#define DUMMY_RI_MASK 2 -#define DUMMY_DSR_MASK 4 -#define DUMMY_CD_MASK 8 -static unsigned char dummy_ser[NR_PORTS] = {0xFF, 0xFF, 0xFF,0xFF}; - -/* If not all status pins are used or disabled, use mixed mode */ -#ifdef CONFIG_ETRAX_SERIAL_PORT0 - -#define SER0_PA_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PA_BIT+CONFIG_ETRAX_SER0_RI_ON_PA_BIT+CONFIG_ETRAX_SER0_DSR_ON_PA_BIT+CONFIG_ETRAX_SER0_CD_ON_PA_BIT) - -#if SER0_PA_BITSUM != -4 -# if CONFIG_ETRAX_SER0_DTR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_RI_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_DSR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_CD_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#define SER0_PB_BITSUM (CONFIG_ETRAX_SER0_DTR_ON_PB_BIT+CONFIG_ETRAX_SER0_RI_ON_PB_BIT+CONFIG_ETRAX_SER0_DSR_ON_PB_BIT+CONFIG_ETRAX_SER0_CD_ON_PB_BIT) - -#if SER0_PB_BITSUM != -4 -# if CONFIG_ETRAX_SER0_DTR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_RI_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_DSR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER0_CD_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#endif /* PORT0 */ - - -#ifdef CONFIG_ETRAX_SERIAL_PORT1 - -#define SER1_PA_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PA_BIT+CONFIG_ETRAX_SER1_RI_ON_PA_BIT+CONFIG_ETRAX_SER1_DSR_ON_PA_BIT+CONFIG_ETRAX_SER1_CD_ON_PA_BIT) - -#if SER1_PA_BITSUM != -4 -# if CONFIG_ETRAX_SER1_DTR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_RI_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_DSR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_CD_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#define SER1_PB_BITSUM (CONFIG_ETRAX_SER1_DTR_ON_PB_BIT+CONFIG_ETRAX_SER1_RI_ON_PB_BIT+CONFIG_ETRAX_SER1_DSR_ON_PB_BIT+CONFIG_ETRAX_SER1_CD_ON_PB_BIT) - -#if SER1_PB_BITSUM != -4 -# if CONFIG_ETRAX_SER1_DTR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_RI_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_DSR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER1_CD_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#endif /* PORT1 */ - -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - -#define SER2_PA_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PA_BIT+CONFIG_ETRAX_SER2_RI_ON_PA_BIT+CONFIG_ETRAX_SER2_DSR_ON_PA_BIT+CONFIG_ETRAX_SER2_CD_ON_PA_BIT) - -#if SER2_PA_BITSUM != -4 -# if CONFIG_ETRAX_SER2_DTR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_RI_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_DSR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_CD_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#define SER2_PB_BITSUM (CONFIG_ETRAX_SER2_DTR_ON_PB_BIT+CONFIG_ETRAX_SER2_RI_ON_PB_BIT+CONFIG_ETRAX_SER2_DSR_ON_PB_BIT+CONFIG_ETRAX_SER2_CD_ON_PB_BIT) - -#if SER2_PB_BITSUM != -4 -# if CONFIG_ETRAX_SER2_DTR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_RI_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_DSR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER2_CD_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#endif /* PORT2 */ - -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - -#define SER3_PA_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PA_BIT+CONFIG_ETRAX_SER3_RI_ON_PA_BIT+CONFIG_ETRAX_SER3_DSR_ON_PA_BIT+CONFIG_ETRAX_SER3_CD_ON_PA_BIT) - -#if SER3_PA_BITSUM != -4 -# if CONFIG_ETRAX_SER3_DTR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_RI_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_DSR_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_CD_ON_PA_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#define SER3_PB_BITSUM (CONFIG_ETRAX_SER3_DTR_ON_PB_BIT+CONFIG_ETRAX_SER3_RI_ON_PB_BIT+CONFIG_ETRAX_SER3_DSR_ON_PB_BIT+CONFIG_ETRAX_SER3_CD_ON_PB_BIT) - -#if SER3_PB_BITSUM != -4 -# if CONFIG_ETRAX_SER3_DTR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_RI_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_DSR_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -# if CONFIG_ETRAX_SER3_CD_ON_PB_BIT == -1 -# ifndef CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED -# define CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED 1 -# endif -# endif -#endif - -#endif /* PORT3 */ - - -#if defined(CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED) || \ - defined(CONFIG_ETRAX_SER1_DTR_RI_DSR_CD_MIXED) || \ - defined(CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED) || \ - defined(CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED) -#define ETRAX_SERX_DTR_RI_DSR_CD_MIXED -#endif - -#ifdef ETRAX_SERX_DTR_RI_DSR_CD_MIXED -/* The pins can be mixed on PA and PB */ -#define CONTROL_PINS_PORT_NOT_USED(line) \ - &dummy_ser[line], &dummy_ser[line], \ - &dummy_ser[line], &dummy_ser[line], \ - &dummy_ser[line], &dummy_ser[line], \ - &dummy_ser[line], &dummy_ser[line], \ - DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK - - -struct control_pins -{ - volatile unsigned char *dtr_port; - unsigned char *dtr_shadow; - volatile unsigned char *ri_port; - unsigned char *ri_shadow; - volatile unsigned char *dsr_port; - unsigned char *dsr_shadow; - volatile unsigned char *cd_port; - unsigned char *cd_shadow; - - unsigned char dtr_mask; - unsigned char ri_mask; - unsigned char dsr_mask; - unsigned char cd_mask; -}; - -static const struct control_pins e100_modem_pins[NR_PORTS] = -{ - /* Ser 0 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT0 - E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR), - E100_STRUCT_PORT(0,RI), E100_STRUCT_SHADOW(0,RI), - E100_STRUCT_PORT(0,DSR), E100_STRUCT_SHADOW(0,DSR), - E100_STRUCT_PORT(0,CD), E100_STRUCT_SHADOW(0,CD), - E100_STRUCT_MASK(0,DTR), - E100_STRUCT_MASK(0,RI), - E100_STRUCT_MASK(0,DSR), - E100_STRUCT_MASK(0,CD) -#else - CONTROL_PINS_PORT_NOT_USED(0) -#endif - }, - - /* Ser 1 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT1 - E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR), - E100_STRUCT_PORT(1,RI), E100_STRUCT_SHADOW(1,RI), - E100_STRUCT_PORT(1,DSR), E100_STRUCT_SHADOW(1,DSR), - E100_STRUCT_PORT(1,CD), E100_STRUCT_SHADOW(1,CD), - E100_STRUCT_MASK(1,DTR), - E100_STRUCT_MASK(1,RI), - E100_STRUCT_MASK(1,DSR), - E100_STRUCT_MASK(1,CD) -#else - CONTROL_PINS_PORT_NOT_USED(1) -#endif - }, - - /* Ser 2 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR), - E100_STRUCT_PORT(2,RI), E100_STRUCT_SHADOW(2,RI), - E100_STRUCT_PORT(2,DSR), E100_STRUCT_SHADOW(2,DSR), - E100_STRUCT_PORT(2,CD), E100_STRUCT_SHADOW(2,CD), - E100_STRUCT_MASK(2,DTR), - E100_STRUCT_MASK(2,RI), - E100_STRUCT_MASK(2,DSR), - E100_STRUCT_MASK(2,CD) -#else - CONTROL_PINS_PORT_NOT_USED(2) -#endif - }, - - /* Ser 3 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR), - E100_STRUCT_PORT(3,RI), E100_STRUCT_SHADOW(3,RI), - E100_STRUCT_PORT(3,DSR), E100_STRUCT_SHADOW(3,DSR), - E100_STRUCT_PORT(3,CD), E100_STRUCT_SHADOW(3,CD), - E100_STRUCT_MASK(3,DTR), - E100_STRUCT_MASK(3,RI), - E100_STRUCT_MASK(3,DSR), - E100_STRUCT_MASK(3,CD) -#else - CONTROL_PINS_PORT_NOT_USED(3) -#endif - } -}; -#else /* ETRAX_SERX_DTR_RI_DSR_CD_MIXED */ - -/* All pins are on either PA or PB for each serial port */ -#define CONTROL_PINS_PORT_NOT_USED(line) \ - &dummy_ser[line], &dummy_ser[line], \ - DUMMY_DTR_MASK, DUMMY_RI_MASK, DUMMY_DSR_MASK, DUMMY_CD_MASK - - -struct control_pins -{ - volatile unsigned char *port; - unsigned char *shadow; - - unsigned char dtr_mask; - unsigned char ri_mask; - unsigned char dsr_mask; - unsigned char cd_mask; -}; - -#define dtr_port port -#define dtr_shadow shadow -#define ri_port port -#define ri_shadow shadow -#define dsr_port port -#define dsr_shadow shadow -#define cd_port port -#define cd_shadow shadow - -static const struct control_pins e100_modem_pins[NR_PORTS] = -{ - /* Ser 0 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT0 - E100_STRUCT_PORT(0,DTR), E100_STRUCT_SHADOW(0,DTR), - E100_STRUCT_MASK(0,DTR), - E100_STRUCT_MASK(0,RI), - E100_STRUCT_MASK(0,DSR), - E100_STRUCT_MASK(0,CD) -#else - CONTROL_PINS_PORT_NOT_USED(0) -#endif - }, - - /* Ser 1 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT1 - E100_STRUCT_PORT(1,DTR), E100_STRUCT_SHADOW(1,DTR), - E100_STRUCT_MASK(1,DTR), - E100_STRUCT_MASK(1,RI), - E100_STRUCT_MASK(1,DSR), - E100_STRUCT_MASK(1,CD) -#else - CONTROL_PINS_PORT_NOT_USED(1) -#endif - }, - - /* Ser 2 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - E100_STRUCT_PORT(2,DTR), E100_STRUCT_SHADOW(2,DTR), - E100_STRUCT_MASK(2,DTR), - E100_STRUCT_MASK(2,RI), - E100_STRUCT_MASK(2,DSR), - E100_STRUCT_MASK(2,CD) -#else - CONTROL_PINS_PORT_NOT_USED(2) -#endif - }, - - /* Ser 3 */ - { -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - E100_STRUCT_PORT(3,DTR), E100_STRUCT_SHADOW(3,DTR), - E100_STRUCT_MASK(3,DTR), - E100_STRUCT_MASK(3,RI), - E100_STRUCT_MASK(3,DSR), - E100_STRUCT_MASK(3,CD) -#else - CONTROL_PINS_PORT_NOT_USED(3) -#endif - } -}; -#endif /* !ETRAX_SERX_DTR_RI_DSR_CD_MIXED */ - -#define E100_RTS_MASK 0x20 -#define E100_CTS_MASK 0x40 - -/* All serial port signals are active low: - * active = 0 -> 3.3V to RS-232 driver -> -12V on RS-232 level - * inactive = 1 -> 0V to RS-232 driver -> +12V on RS-232 level - * - * These macros returns the pin value: 0=0V, >=1 = 3.3V on ETRAX chip - */ - -/* Output */ -#define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK) -/* Input */ -#define E100_CTS_GET(info) ((info)->ioport[REG_STATUS] & E100_CTS_MASK) - -/* These are typically PA or PB and 0 means 0V, 1 means 3.3V */ -/* Is an output */ -#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].dtr_shadow) & e100_modem_pins[(info)->line].dtr_mask) - -/* Normally inputs */ -#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].ri_port) & e100_modem_pins[(info)->line].ri_mask) -#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].cd_port) & e100_modem_pins[(info)->line].cd_mask) - -/* Input */ -#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].dsr_port) & e100_modem_pins[(info)->line].dsr_mask) - -/* Calculate the chartime depending on baudrate, numbor of bits etc. */ -static void update_char_time(struct e100_serial * info) -{ - tcflag_t cflags = info->port.tty->termios.c_cflag; - int bits; - - /* calc. number of bits / data byte */ - /* databits + startbit and 1 stopbit */ - if ((cflags & CSIZE) == CS7) - bits = 9; - else - bits = 10; - - if (cflags & CSTOPB) /* 2 stopbits ? */ - bits++; - - if (cflags & PARENB) /* parity bit ? */ - bits++; - - /* calc timeout */ - info->char_time_usec = ((bits * 1000000) / info->baud) + 1; - info->flush_time_usec = 4*info->char_time_usec; - if (info->flush_time_usec < MIN_FLUSH_TIME_USEC) - info->flush_time_usec = MIN_FLUSH_TIME_USEC; - -} - -/* - * This function maps from the Bxxxx defines in asm/termbits.h into real - * baud rates. - */ - -static int -cflag_to_baud(unsigned int cflag) -{ - static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }; - - static int ext_baud_table[] = { - 0, 57600, 115200, 230400, 460800, 921600, 1843200, 6250000, - 0, 0, 0, 0, 0, 0, 0, 0 }; - - if (cflag & CBAUDEX) - return ext_baud_table[(cflag & CBAUD) & ~CBAUDEX]; - else - return baud_table[cflag & CBAUD]; -} - -/* and this maps to an etrax100 hardware baud constant */ - -static unsigned char -cflag_to_etrax_baud(unsigned int cflag) -{ - char retval; - - static char baud_table[] = { - -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, 3, 4, 5, 6, 7 }; - - static char ext_baud_table[] = { - -1, 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1 }; - - if (cflag & CBAUDEX) - retval = ext_baud_table[(cflag & CBAUD) & ~CBAUDEX]; - else - retval = baud_table[cflag & CBAUD]; - - if (retval < 0) { - printk(KERN_WARNING "serdriver tried setting invalid baud rate, flags %x.\n", cflag); - retval = 5; /* choose default 9600 instead */ - } - - return retval | (retval << 4); /* choose same for both TX and RX */ -} - - -/* Various static support functions */ - -/* Functions to set or clear DTR/RTS on the requested line */ -/* It is complicated by the fact that RTS is a serial port register, while - * DTR might not be implemented in the HW at all, and if it is, it can be on - * any general port. - */ - - -static inline void -e100_dtr(struct e100_serial *info, int set) -{ - unsigned char mask = e100_modem_pins[info->line].dtr_mask; - -#ifdef SERIAL_DEBUG_IO - printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask); - printk("ser%i shadow before 0x%02X get: %i\n", - info->line, *e100_modem_pins[info->line].dtr_shadow, - E100_DTR_GET(info)); -#endif - /* DTR is active low */ - { - unsigned long flags; - - local_irq_save(flags); - *e100_modem_pins[info->line].dtr_shadow &= ~mask; - *e100_modem_pins[info->line].dtr_shadow |= (set ? 0 : mask); - *e100_modem_pins[info->line].dtr_port = *e100_modem_pins[info->line].dtr_shadow; - local_irq_restore(flags); - } - -#ifdef SERIAL_DEBUG_IO - printk("ser%i shadow after 0x%02X get: %i\n", - info->line, *e100_modem_pins[info->line].dtr_shadow, - E100_DTR_GET(info)); -#endif -} - -/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive - * 0=0V , 1=3.3V - */ -static inline void -e100_rts(struct e100_serial *info, int set) -{ - unsigned long flags; - local_irq_save(flags); - info->rx_ctrl &= ~E100_RTS_MASK; - info->rx_ctrl |= (set ? 0 : E100_RTS_MASK); /* RTS is active low */ - info->ioport[REG_REC_CTRL] = info->rx_ctrl; - local_irq_restore(flags); -#ifdef SERIAL_DEBUG_IO - printk("ser%i rts %i\n", info->line, set); -#endif -} - - -/* If this behaves as a modem, RI and CD is an output */ -static inline void -e100_ri_out(struct e100_serial *info, int set) -{ - /* RI is active low */ - { - unsigned char mask = e100_modem_pins[info->line].ri_mask; - unsigned long flags; - - local_irq_save(flags); - *e100_modem_pins[info->line].ri_shadow &= ~mask; - *e100_modem_pins[info->line].ri_shadow |= (set ? 0 : mask); - *e100_modem_pins[info->line].ri_port = *e100_modem_pins[info->line].ri_shadow; - local_irq_restore(flags); - } -} -static inline void -e100_cd_out(struct e100_serial *info, int set) -{ - /* CD is active low */ - { - unsigned char mask = e100_modem_pins[info->line].cd_mask; - unsigned long flags; - - local_irq_save(flags); - *e100_modem_pins[info->line].cd_shadow &= ~mask; - *e100_modem_pins[info->line].cd_shadow |= (set ? 0 : mask); - *e100_modem_pins[info->line].cd_port = *e100_modem_pins[info->line].cd_shadow; - local_irq_restore(flags); - } -} - -static inline void -e100_disable_rx(struct e100_serial *info) -{ - /* disable the receiver */ - info->ioport[REG_REC_CTRL] = - (info->rx_ctrl &= ~IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); -} - -static inline void -e100_enable_rx(struct e100_serial *info) -{ - /* enable the receiver */ - info->ioport[REG_REC_CTRL] = - (info->rx_ctrl |= IO_MASK(R_SERIAL0_REC_CTRL, rec_enable)); -} - -/* the rx DMA uses both the dma_descr and the dma_eop interrupts */ - -static inline void -e100_disable_rxdma_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("rxdma_irq(%d): 0\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ disable_rxdma_irq %i\n", info->line)); - *R_IRQ_MASK2_CLR = (info->irq << 2) | (info->irq << 3); -} - -static inline void -e100_enable_rxdma_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("rxdma_irq(%d): 1\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ enable_rxdma_irq %i\n", info->line)); - *R_IRQ_MASK2_SET = (info->irq << 2) | (info->irq << 3); -} - -/* the tx DMA uses only dma_descr interrupt */ - -static void e100_disable_txdma_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("txdma_irq(%d): 0\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ disable_txdma_irq %i\n", info->line)); - *R_IRQ_MASK2_CLR = info->irq; -} - -static void e100_enable_txdma_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("txdma_irq(%d): 1\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ enable_txdma_irq %i\n", info->line)); - *R_IRQ_MASK2_SET = info->irq; -} - -static void e100_disable_txdma_channel(struct e100_serial *info) -{ - unsigned long flags; - - /* Disable output DMA channel for the serial port in question - * ( set to something other than serialX) - */ - local_irq_save(flags); - DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); - if (info->line == 0) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma6)) == - IO_STATE(R_GEN_CONFIG, dma6, serial0)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); - } - } else if (info->line == 1) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma8)) == - IO_STATE(R_GEN_CONFIG, dma8, serial1)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); - } - } else if (info->line == 2) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma2)) == - IO_STATE(R_GEN_CONFIG, dma2, serial2)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); - } - } else if (info->line == 3) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma4)) == - IO_STATE(R_GEN_CONFIG, dma4, serial3)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); - } - } - *R_GEN_CONFIG = genconfig_shadow; - local_irq_restore(flags); -} - - -static void e100_enable_txdma_channel(struct e100_serial *info) -{ - unsigned long flags; - - local_irq_save(flags); - DFLOW(DEBUG_LOG(info->line, "enable_txdma_channel %i\n", info->line)); - /* Enable output DMA channel for the serial port in question */ - if (info->line == 0) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, serial0); - } else if (info->line == 1) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, serial1); - } else if (info->line == 2) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, serial2); - } else if (info->line == 3) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, serial3); - } - *R_GEN_CONFIG = genconfig_shadow; - local_irq_restore(flags); -} - -static void e100_disable_rxdma_channel(struct e100_serial *info) -{ - unsigned long flags; - - /* Disable input DMA channel for the serial port in question - * ( set to something other than serialX) - */ - local_irq_save(flags); - if (info->line == 0) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma7)) == - IO_STATE(R_GEN_CONFIG, dma7, serial0)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, unused); - } - } else if (info->line == 1) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma9)) == - IO_STATE(R_GEN_CONFIG, dma9, serial1)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, usb); - } - } else if (info->line == 2) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma3)) == - IO_STATE(R_GEN_CONFIG, dma3, serial2)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0); - } - } else if (info->line == 3) { - if ((genconfig_shadow & IO_MASK(R_GEN_CONFIG, dma5)) == - IO_STATE(R_GEN_CONFIG, dma5, serial3)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1); - } - } - *R_GEN_CONFIG = genconfig_shadow; - local_irq_restore(flags); -} - - -static void e100_enable_rxdma_channel(struct e100_serial *info) -{ - unsigned long flags; - - local_irq_save(flags); - /* Enable input DMA channel for the serial port in question */ - if (info->line == 0) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma7); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma7, serial0); - } else if (info->line == 1) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma9); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma9, serial1); - } else if (info->line == 2) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, serial2); - } else if (info->line == 3) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, serial3); - } - *R_GEN_CONFIG = genconfig_shadow; - local_irq_restore(flags); -} - -#ifdef SERIAL_HANDLE_EARLY_ERRORS -/* in order to detect and fix errors on the first byte - we have to use the serial interrupts as well. */ - -static inline void -e100_disable_serial_data_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("ser_irq(%d): 0\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ disable data_irq %i\n", info->line)); - *R_IRQ_MASK1_CLR = (1U << (8+2*info->line)); -} - -static inline void -e100_enable_serial_data_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("ser_irq(%d): 1\n",info->line); - printk("**** %d = %d\n", - (8+2*info->line), - (1U << (8+2*info->line))); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ enable data_irq %i\n", info->line)); - *R_IRQ_MASK1_SET = (1U << (8+2*info->line)); -} -#endif - -static inline void -e100_disable_serial_tx_ready_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("ser_tx_irq(%d): 0\n",info->line); -#endif - DINTR1(DEBUG_LOG(info->line,"IRQ disable ready_irq %i\n", info->line)); - *R_IRQ_MASK1_CLR = (1U << (8+1+2*info->line)); -} - -static inline void -e100_enable_serial_tx_ready_irq(struct e100_serial *info) -{ -#ifdef SERIAL_DEBUG_INTR - printk("ser_tx_irq(%d): 1\n",info->line); - printk("**** %d = %d\n", - (8+1+2*info->line), - (1U << (8+1+2*info->line))); -#endif - DINTR2(DEBUG_LOG(info->line,"IRQ enable ready_irq %i\n", info->line)); - *R_IRQ_MASK1_SET = (1U << (8+1+2*info->line)); -} - -static inline void e100_enable_rx_irq(struct e100_serial *info) -{ - if (info->uses_dma_in) - e100_enable_rxdma_irq(info); - else - e100_enable_serial_data_irq(info); -} -static inline void e100_disable_rx_irq(struct e100_serial *info) -{ - if (info->uses_dma_in) - e100_disable_rxdma_irq(info); - else - e100_disable_serial_data_irq(info); -} - -#if defined(CONFIG_ETRAX_RS485) -/* Enable RS-485 mode on selected port. This is UGLY. */ -static int -e100_enable_rs485(struct tty_struct *tty, struct serial_rs485 *r) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - -#if defined(CONFIG_ETRAX_RS485_ON_PA) - *R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit); -#endif - - info->rs485 = *r; - - /* Maximum delay before RTS equal to 1000 */ - if (info->rs485.delay_rts_before_send >= 1000) - info->rs485.delay_rts_before_send = 1000; - -/* printk("rts: on send = %i, after = %i, enabled = %i", - info->rs485.rts_on_send, - info->rs485.rts_after_sent, - info->rs485.enabled - ); -*/ - return 0; -} - -static int -e100_write_rs485(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - int old_value = (info->rs485.flags) & SER_RS485_ENABLED; - - /* rs485 is always implicitly enabled if we're using the ioctl() - * but it doesn't have to be set in the serial_rs485 - * (to be backward compatible with old apps) - * So we store, set and restore it. - */ - info->rs485.flags |= SER_RS485_ENABLED; - /* rs_write now deals with RS485 if enabled */ - count = rs_write(tty, buf, count); - if (!old_value) - info->rs485.flags &= ~(SER_RS485_ENABLED); - return count; -} - -#ifdef CONFIG_ETRAX_FAST_TIMER -/* Timer function to toggle RTS when using FAST_TIMER */ -static void rs485_toggle_rts_timer_function(unsigned long data) -{ - struct e100_serial *info = (struct e100_serial *)data; - - fast_timers_rs485[info->line].function = NULL; - e100_rts(info, (info->rs485.flags & SER_RS485_RTS_AFTER_SEND)); -#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER) - e100_enable_rx(info); - e100_enable_rx_irq(info); -#endif -} -#endif -#endif /* CONFIG_ETRAX_RS485 */ - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter using the XOFF registers, as necessary. - * ------------------------------------------------------------ - */ - -static void -rs_stop(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - if (info) { - unsigned long flags; - unsigned long xoff; - - local_irq_save(flags); - DFLOW(DEBUG_LOG(info->line, "XOFF rs_stop xmit %i\n", - CIRC_CNT(info->xmit.head, - info->xmit.tail,SERIAL_XMIT_SIZE))); - - xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, - STOP_CHAR(info->port.tty)); - xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (I_IXON(tty)) - xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - - *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; - local_irq_restore(flags); - } -} - -static void -rs_start(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - if (info) { - unsigned long flags; - unsigned long xoff; - - local_irq_save(flags); - DFLOW(DEBUG_LOG(info->line, "XOFF rs_start xmit %i\n", - CIRC_CNT(info->xmit.head, - info->xmit.tail,SERIAL_XMIT_SIZE))); - xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); - xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (I_IXON(tty)) - xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - - *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; - if (!info->uses_dma_out && - info->xmit.head != info->xmit.tail && info->xmit.buf) - e100_enable_serial_tx_ready_irq(info); - - local_irq_restore(flags); - } -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static void rs_sched_event(struct e100_serial *info, int event) -{ - if (info->event & (1 << event)) - return; - info->event |= 1 << event; - schedule_work(&info->work); -} - -/* The output DMA channel is free - use it to send as many chars as possible - * NOTES: - * We don't pay attention to info->x_char, which means if the TTY wants to - * use XON/XOFF it will set info->x_char but we won't send any X char! - * - * To implement this, we'd just start a DMA send of 1 byte pointing at a - * buffer containing the X char, and skip updating xmit. We'd also have to - * check if the last sent char was the X char when we enter this function - * the next time, to avoid updating xmit with the sent X value. - */ - -static void -transmit_chars_dma(struct e100_serial *info) -{ - unsigned int c, sentl; - struct etrax_dma_descr *descr; - - /* acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ - *info->oclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - -#ifdef SERIAL_DEBUG_INTR - if (info->line == SERIAL_DEBUG_LINE) - printk("tc\n"); -#endif - if (!info->tr_running) { - /* weirdo... we shouldn't get here! */ - printk(KERN_WARNING "Achtung: transmit_chars_dma with !tr_running\n"); - return; - } - - descr = &info->tr_descr; - - /* first get the amount of bytes sent during the last DMA transfer, - and update xmit accordingly */ - - /* if the stop bit was not set, all data has been sent */ - if (!(descr->status & d_stop)) { - sentl = descr->sw_len; - } else - /* otherwise we find the amount of data sent here */ - sentl = descr->hw_len; - - DFLOW(DEBUG_LOG(info->line, "TX %i done\n", sentl)); - - /* update stats */ - info->icount.tx += sentl; - - /* update xmit buffer */ - info->xmit.tail = (info->xmit.tail + sentl) & (SERIAL_XMIT_SIZE - 1); - - /* if there is only a few chars left in the buf, wake up the blocked - write if any */ - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - - /* find out the largest amount of consecutive bytes we want to send now */ - - c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - - /* Don't send all in one DMA transfer - divide it so we wake up - * application before all is sent - */ - - if (c >= 4*WAKEUP_CHARS) - c = c/2; - - if (c <= 0) { - /* our job here is done, don't schedule any new DMA transfer */ - info->tr_running = 0; - -#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER) - if (info->rs485.flags & SER_RS485_ENABLED) { - /* Set a short timer to toggle RTS */ - start_one_shot_timer(&fast_timers_rs485[info->line], - rs485_toggle_rts_timer_function, - (unsigned long)info, - info->char_time_usec*2, - "RS-485"); - } -#endif /* RS485 */ - return; - } - - /* ok we can schedule a dma send of c chars starting at info->xmit.tail */ - /* set up the descriptor correctly for output */ - DFLOW(DEBUG_LOG(info->line, "TX %i\n", c)); - descr->ctrl = d_int | d_eol | d_wait; /* Wait needed for tty_wait_until_sent() */ - descr->sw_len = c; - descr->buf = virt_to_phys(info->xmit.buf + info->xmit.tail); - descr->status = 0; - - *info->ofirstadr = virt_to_phys(descr); /* write to R_DMAx_FIRST */ - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start); - - /* DMA is now running (hopefully) */ -} /* transmit_chars_dma */ - -static void -start_transmit(struct e100_serial *info) -{ -#if 0 - if (info->line == SERIAL_DEBUG_LINE) - printk("x\n"); -#endif - - info->tr_descr.sw_len = 0; - info->tr_descr.hw_len = 0; - info->tr_descr.status = 0; - info->tr_running = 1; - if (info->uses_dma_out) - transmit_chars_dma(info); - else - e100_enable_serial_tx_ready_irq(info); -} /* start_transmit */ - -#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER -static int serial_fast_timer_started = 0; -static int serial_fast_timer_expired = 0; -static void flush_timeout_function(unsigned long data); -#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) {\ - unsigned long timer_flags; \ - local_irq_save(timer_flags); \ - if (fast_timers[info->line].function == NULL) { \ - serial_fast_timer_started++; \ - TIMERD(DEBUG_LOG(info->line, "start_timer %i ", info->line)); \ - TIMERD(DEBUG_LOG(info->line, "num started: %i\n", serial_fast_timer_started)); \ - start_one_shot_timer(&fast_timers[info->line], \ - flush_timeout_function, \ - (unsigned long)info, \ - (usec), \ - string); \ - } \ - else { \ - TIMERD(DEBUG_LOG(info->line, "timer %i already running\n", info->line)); \ - } \ - local_irq_restore(timer_flags); \ -} -#define START_FLUSH_FAST_TIMER(info, string) START_FLUSH_FAST_TIMER_TIME(info, string, info->flush_time_usec) - -#else -#define START_FLUSH_FAST_TIMER_TIME(info, string, usec) -#define START_FLUSH_FAST_TIMER(info, string) -#endif - -static struct etrax_recv_buffer * -alloc_recv_buffer(unsigned int size) -{ - struct etrax_recv_buffer *buffer; - - buffer = kmalloc(sizeof *buffer + size, GFP_ATOMIC); - if (!buffer) - return NULL; - - buffer->next = NULL; - buffer->length = 0; - buffer->error = TTY_NORMAL; - - return buffer; -} - -static void -append_recv_buffer(struct e100_serial *info, struct etrax_recv_buffer *buffer) -{ - unsigned long flags; - - local_irq_save(flags); - - if (!info->first_recv_buffer) - info->first_recv_buffer = buffer; - else - info->last_recv_buffer->next = buffer; - - info->last_recv_buffer = buffer; - - info->recv_cnt += buffer->length; - if (info->recv_cnt > info->max_recv_cnt) - info->max_recv_cnt = info->recv_cnt; - - local_irq_restore(flags); -} - -static int -add_char_and_flag(struct e100_serial *info, unsigned char data, unsigned char flag) -{ - struct etrax_recv_buffer *buffer; - if (info->uses_dma_in) { - buffer = alloc_recv_buffer(4); - if (!buffer) - return 0; - - buffer->length = 1; - buffer->error = flag; - buffer->buffer[0] = data; - - append_recv_buffer(info, buffer); - - info->icount.rx++; - } else { - tty_insert_flip_char(&info->port, data, flag); - info->icount.rx++; - } - - return 1; -} - -static unsigned int handle_descr_data(struct e100_serial *info, - struct etrax_dma_descr *descr, - unsigned int recvl) -{ - struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; - - if (info->recv_cnt + recvl > 65536) { - printk(KERN_WARNING - "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl); - return 0; - } - - buffer->length = recvl; - - if (info->errorcode == ERRCODE_SET_BREAK) - buffer->error = TTY_BREAK; - info->errorcode = 0; - - append_recv_buffer(info, buffer); - - buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE); - if (!buffer) - panic("%s: Failed to allocate memory for receive buffer!\n", __func__); - - descr->buf = virt_to_phys(buffer->buffer); - - return recvl; -} - -static unsigned int handle_all_descr_data(struct e100_serial *info) -{ - struct etrax_dma_descr *descr; - unsigned int recvl; - unsigned int ret = 0; - - while (1) - { - descr = &info->rec_descr[info->cur_rec_descr]; - - if (descr == phys_to_virt(*info->idescradr)) - break; - - if (++info->cur_rec_descr == SERIAL_RECV_DESCRIPTORS) - info->cur_rec_descr = 0; - - /* find out how many bytes were read */ - - /* if the eop bit was not set, all data has been received */ - if (!(descr->status & d_eop)) { - recvl = descr->sw_len; - } else { - /* otherwise we find the amount of data received here */ - recvl = descr->hw_len; - } - - /* Reset the status information */ - descr->status = 0; - - DFLOW( DEBUG_LOG(info->line, "RX %lu\n", recvl); - if (info->port.tty->stopped) { - unsigned char *buf = phys_to_virt(descr->buf); - DEBUG_LOG(info->line, "rx 0x%02X\n", buf[0]); - DEBUG_LOG(info->line, "rx 0x%02X\n", buf[1]); - DEBUG_LOG(info->line, "rx 0x%02X\n", buf[2]); - } - ); - - /* update stats */ - info->icount.rx += recvl; - - ret += handle_descr_data(info, descr, recvl); - } - - return ret; -} - -static void receive_chars_dma(struct e100_serial *info) -{ - struct tty_struct *tty; - unsigned char rstat; - - /* Acknowledge both dma_descr and dma_eop irq in R_DMA_CHx_CLR_INTR */ - *info->iclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - - tty = info->port.tty; - if (!tty) /* Something wrong... */ - return; - -#ifdef SERIAL_HANDLE_EARLY_ERRORS - if (info->uses_dma_in) - e100_enable_serial_data_irq(info); -#endif - - if (info->errorcode == ERRCODE_INSERT_BREAK) - add_char_and_flag(info, '\0', TTY_BREAK); - - handle_all_descr_data(info); - - /* Read the status register to detect errors */ - rstat = info->ioport[REG_STATUS]; - if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { - DFLOW(DEBUG_LOG(info->line, "XOFF detect stat %x\n", rstat)); - } - - if (rstat & SER_ERROR_MASK) { - /* If we got an error, we must reset it by reading the - * data_in field - */ - unsigned char data = info->ioport[REG_DATA]; - - DEBUG_LOG(info->line, "#dERR: s d 0x%04X\n", - ((rstat & SER_ERROR_MASK) << 8) | data); - - if (rstat & SER_PAR_ERR_MASK) - add_char_and_flag(info, data, TTY_PARITY); - else if (rstat & SER_OVERRUN_MASK) - add_char_and_flag(info, data, TTY_OVERRUN); - else if (rstat & SER_FRAMING_ERR_MASK) - add_char_and_flag(info, data, TTY_FRAME); - } - - START_FLUSH_FAST_TIMER(info, "receive_chars"); - - /* Restart the receiving DMA */ - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); -} - -static int start_recv_dma(struct e100_serial *info) -{ - struct etrax_dma_descr *descr = info->rec_descr; - struct etrax_recv_buffer *buffer; - int i; - - /* Set up the receiving descriptors */ - for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) { - buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE); - if (!buffer) - panic("%s: Failed to allocate memory for receive buffer!\n", __func__); - - descr[i].ctrl = d_int; - descr[i].buf = virt_to_phys(buffer->buffer); - descr[i].sw_len = SERIAL_DESCR_BUF_SIZE; - descr[i].hw_len = 0; - descr[i].status = 0; - descr[i].next = virt_to_phys(&descr[i+1]); - } - - /* Link the last descriptor to the first */ - descr[i-1].next = virt_to_phys(&descr[0]); - - /* Start with the first descriptor in the list */ - info->cur_rec_descr = 0; - - /* Start the DMA */ - *info->ifirstadr = virt_to_phys(&descr[info->cur_rec_descr]); - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, start); - - /* Input DMA should be running now */ - return 1; -} - -static void -start_receive(struct e100_serial *info) -{ - if (info->uses_dma_in) { - /* reset the input dma channel to be sure it works */ - - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - - start_recv_dma(info); - } -} - - -/* the bits in the MASK2 register are laid out like this: - DMAI_EOP DMAI_DESCR DMAO_EOP DMAO_DESCR - where I is the input channel and O is the output channel for the port. - info->irq is the bit number for the DMAO_DESCR so to check the others we - shift info->irq to the left. -*/ - -/* dma output channel interrupt handler - this interrupt is called from DMA2(ser2), DMA4(ser3), DMA6(ser0) or - DMA8(ser1) when they have finished a descriptor with the intr flag set. -*/ - -static irqreturn_t -tr_interrupt(int irq, void *dev_id) -{ - struct e100_serial *info; - unsigned long ireg; - int i; - int handled = 0; - - /* find out the line that caused this irq and get it from rs_table */ - - ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ - - for (i = 0; i < NR_PORTS; i++) { - info = rs_table + i; - if (!info->enabled || !info->uses_dma_out) - continue; - /* check for dma_descr (don't need to check for dma_eop in output dma for serial */ - if (ireg & info->irq) { - handled = 1; - /* we can send a new dma bunch. make it so. */ - DINTR2(DEBUG_LOG(info->line, "tr_interrupt %i\n", i)); - /* Read jiffies_usec first, - * we want this time to be as late as possible - */ - info->last_tx_active_usec = GET_JIFFIES_USEC(); - info->last_tx_active = jiffies; - transmit_chars_dma(info); - } - - /* FIXME: here we should really check for a change in the - status lines and if so call status_handle(info) */ - } - return IRQ_RETVAL(handled); -} /* tr_interrupt */ - -/* dma input channel interrupt handler */ - -static irqreturn_t -rec_interrupt(int irq, void *dev_id) -{ - struct e100_serial *info; - unsigned long ireg; - int i; - int handled = 0; - - /* find out the line that caused this irq and get it from rs_table */ - - ireg = *R_IRQ_MASK2_RD; /* get the active irq bits for the dma channels */ - - for (i = 0; i < NR_PORTS; i++) { - info = rs_table + i; - if (!info->enabled || !info->uses_dma_in) - continue; - /* check for both dma_eop and dma_descr for the input dma channel */ - if (ireg & ((info->irq << 2) | (info->irq << 3))) { - handled = 1; - /* we have received something */ - receive_chars_dma(info); - } - - /* FIXME: here we should really check for a change in the - status lines and if so call status_handle(info) */ - } - return IRQ_RETVAL(handled); -} /* rec_interrupt */ - -static int force_eop_if_needed(struct e100_serial *info) -{ - /* We check data_avail bit to determine if data has - * arrived since last time - */ - unsigned char rstat = info->ioport[REG_STATUS]; - - /* error or datavail? */ - if (rstat & SER_ERROR_MASK) { - /* Some error has occurred. If there has been valid data, an - * EOP interrupt will be made automatically. If no data, the - * normal ser_interrupt should be enabled and handle it. - * So do nothing! - */ - DEBUG_LOG(info->line, "timeout err: rstat 0x%03X\n", - rstat | (info->line << 8)); - return 0; - } - - if (rstat & SER_DATA_AVAIL_MASK) { - /* Ok data, no error, count it */ - TIMERD(DEBUG_LOG(info->line, "timeout: rstat 0x%03X\n", - rstat | (info->line << 8))); - /* Read data to clear status flags */ - (void)info->ioport[REG_DATA]; - - info->forced_eop = 0; - START_FLUSH_FAST_TIMER(info, "magic"); - return 0; - } - - /* hit the timeout, force an EOP for the input - * dma channel if we haven't already - */ - if (!info->forced_eop) { - info->forced_eop = 1; - TIMERD(DEBUG_LOG(info->line, "timeout EOP %i\n", info->line)); - FORCE_EOP(info); - } - - return 1; -} - -static void flush_to_flip_buffer(struct e100_serial *info) -{ - struct etrax_recv_buffer *buffer; - unsigned long flags; - - local_irq_save(flags); - - while ((buffer = info->first_recv_buffer) != NULL) { - unsigned int count = buffer->length; - - tty_insert_flip_string(&info->port, buffer->buffer, count); - info->recv_cnt -= count; - - if (count == buffer->length) { - info->first_recv_buffer = buffer->next; - kfree(buffer); - } else { - buffer->length -= count; - memmove(buffer->buffer, buffer->buffer + count, buffer->length); - buffer->error = TTY_NORMAL; - } - } - - if (!info->first_recv_buffer) - info->last_recv_buffer = NULL; - - local_irq_restore(flags); - - /* This includes a check for low-latency */ - tty_flip_buffer_push(&info->port); -} - -static void check_flush_timeout(struct e100_serial *info) -{ - /* Flip what we've got (if we can) */ - flush_to_flip_buffer(info); - - /* We might need to flip later, but not to fast - * since the system is busy processing input... */ - if (info->first_recv_buffer) - START_FLUSH_FAST_TIMER_TIME(info, "flip", 2000); - - /* Force eop last, since data might have come while we're processing - * and if we started the slow timer above, we won't start a fast - * below. - */ - force_eop_if_needed(info); -} - -#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER -static void flush_timeout_function(unsigned long data) -{ - struct e100_serial *info = (struct e100_serial *)data; - - fast_timers[info->line].function = NULL; - serial_fast_timer_expired++; - TIMERD(DEBUG_LOG(info->line, "flush_timeout %i ", info->line)); - TIMERD(DEBUG_LOG(info->line, "num expired: %i\n", serial_fast_timer_expired)); - check_flush_timeout(info); -} - -#else - -/* dma fifo/buffer timeout handler - forces an end-of-packet for the dma input channel if no chars - have been received for CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS/100 s. -*/ - -static struct timer_list flush_timer; - -static void -timed_flush_handler(struct timer_list *unused) -{ - struct e100_serial *info; - int i; - - for (i = 0; i < NR_PORTS; i++) { - info = rs_table + i; - if (info->uses_dma_in) - check_flush_timeout(info); - } - - /* restart flush timer */ - mod_timer(&flush_timer, jiffies + CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS); -} -#endif - -#ifdef SERIAL_HANDLE_EARLY_ERRORS - -/* If there is an error (ie break) when the DMA is running and - * there are no bytes in the fifo the DMA is stopped and we get no - * eop interrupt. Thus we have to monitor the first bytes on a DMA - * transfer, and if it is without error we can turn the serial - * interrupts off. - */ - -/* -BREAK handling on ETRAX 100: -ETRAX will generate interrupt although there is no stop bit between the -characters. - -Depending on how long the break sequence is, the end of the breaksequence -will look differently: -| indicates start/end of a character. - -B= Break character (0x00) with framing error. -E= Error byte with parity error received after B characters. -F= "Faked" valid byte received immediately after B characters. -V= Valid byte - -1. - B BL ___________________________ V -.._|__________|__________| |valid data | - -Multiple frame errors with data == 0x00 (B), -the timing matches up "perfectly" so no extra ending char is detected. -The RXD pin is 1 in the last interrupt, in that case -we set info->errorcode = ERRCODE_INSERT_BREAK, but we can't really -know if another byte will come and this really is case 2. below -(e.g F=0xFF or 0xFE) -If RXD pin is 0 we can expect another character (see 2. below). - - -2. - - B B E or F__________________..__ V -.._|__________|__________|______ | |valid data - "valid" or - parity error - -Multiple frame errors with data == 0x00 (B), -but the part of the break trigs is interpreted as a start bit (and possibly -some 0 bits followed by a number of 1 bits and a stop bit). -Depending on parity settings etc. this last character can be either -a fake "valid" char (F) or have a parity error (E). - -If the character is valid it will be put in the buffer, -we set info->errorcode = ERRCODE_SET_BREAK so the receive interrupt -will set the flags so the tty will handle it, -if it's an error byte it will not be put in the buffer -and we set info->errorcode = ERRCODE_INSERT_BREAK. - -To distinguish a V byte in 1. from an F byte in 2. we keep a timestamp -of the last faulty char (B) and compares it with the current time: -If the time elapsed time is less then 2*char_time_usec we will assume -it's a faked F char and not a Valid char and set -info->errorcode = ERRCODE_SET_BREAK. - -Flaws in the above solution: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We use the timer to distinguish a F character from a V character, -if a V character is to close after the break we might make the wrong decision. - -TODO: The break will be delayed until an F or V character is received. - -*/ - -static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info) -{ - unsigned long data_read; - - /* Read data and status at the same time */ - data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); -more_data: - if (data_read & IO_MASK(R_SERIAL0_READ, xoff_detect) ) { - DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); - } - DINTR2(DEBUG_LOG(info->line, "ser_rx %c\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read))); - - if (data_read & ( IO_MASK(R_SERIAL0_READ, framing_err) | - IO_MASK(R_SERIAL0_READ, par_err) | - IO_MASK(R_SERIAL0_READ, overrun) )) { - /* An error */ - info->last_rx_active_usec = GET_JIFFIES_USEC(); - info->last_rx_active = jiffies; - DINTR1(DEBUG_LOG(info->line, "ser_rx err stat_data %04X\n", data_read)); - DLOG_INT_TRIG( - if (!log_int_trig1_pos) { - log_int_trig1_pos = log_int_pos; - log_int(rdpc(), 0, 0); - } - ); - - - if ( ((data_read & IO_MASK(R_SERIAL0_READ, data_in)) == 0) && - (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) ) { - /* Most likely a break, but we get interrupts over and - * over again. - */ - - if (!info->break_detected_cnt) { - DEBUG_LOG(info->line, "#BRK start\n", 0); - } - if (data_read & IO_MASK(R_SERIAL0_READ, rxd)) { - /* The RX pin is high now, so the break - * must be over, but.... - * we can't really know if we will get another - * last byte ending the break or not. - * And we don't know if the byte (if any) will - * have an error or look valid. - */ - DEBUG_LOG(info->line, "# BL BRK\n", 0); - info->errorcode = ERRCODE_INSERT_BREAK; - } - info->break_detected_cnt++; - } else { - /* The error does not look like a break, but could be - * the end of one - */ - if (info->break_detected_cnt) { - DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); - info->errorcode = ERRCODE_INSERT_BREAK; - } else { - unsigned char data = IO_EXTRACT(R_SERIAL0_READ, - data_in, data_read); - char flag = TTY_NORMAL; - if (info->errorcode == ERRCODE_INSERT_BREAK) { - tty_insert_flip_char(&info->port, 0, flag); - info->icount.rx++; - } - - if (data_read & IO_MASK(R_SERIAL0_READ, par_err)) { - info->icount.parity++; - flag = TTY_PARITY; - } else if (data_read & IO_MASK(R_SERIAL0_READ, overrun)) { - info->icount.overrun++; - flag = TTY_OVERRUN; - } else if (data_read & IO_MASK(R_SERIAL0_READ, framing_err)) { - info->icount.frame++; - flag = TTY_FRAME; - } - tty_insert_flip_char(&info->port, data, flag); - info->errorcode = 0; - } - info->break_detected_cnt = 0; - } - } else if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { - /* No error */ - DLOG_INT_TRIG( - if (!log_int_trig1_pos) { - if (log_int_pos >= log_int_size) { - log_int_pos = 0; - } - log_int_trig0_pos = log_int_pos; - log_int(rdpc(), 0, 0); - } - ); - tty_insert_flip_char(&info->port, - IO_EXTRACT(R_SERIAL0_READ, data_in, data_read), - TTY_NORMAL); - } else { - DEBUG_LOG(info->line, "ser_rx int but no data_avail %08lX\n", data_read); - } - - - info->icount.rx++; - data_read = *((unsigned long *)&info->ioport[REG_DATA_STATUS32]); - if (data_read & IO_MASK(R_SERIAL0_READ, data_avail)) { - DEBUG_LOG(info->line, "ser_rx %c in loop\n", IO_EXTRACT(R_SERIAL0_READ, data_in, data_read)); - goto more_data; - } - - tty_flip_buffer_push(&info->port); -} - -static void handle_ser_rx_interrupt(struct e100_serial *info) -{ - unsigned char rstat; - -#ifdef SERIAL_DEBUG_INTR - printk("Interrupt from serport %d\n", i); -#endif -/* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */ - if (!info->uses_dma_in) { - handle_ser_rx_interrupt_no_dma(info); - return; - } - /* DMA is used */ - rstat = info->ioport[REG_STATUS]; - if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) { - DFLOW(DEBUG_LOG(info->line, "XOFF detect\n", 0)); - } - - if (rstat & SER_ERROR_MASK) { - unsigned char data; - - info->last_rx_active_usec = GET_JIFFIES_USEC(); - info->last_rx_active = jiffies; - /* If we got an error, we must reset it by reading the - * data_in field - */ - data = info->ioport[REG_DATA]; - DINTR1(DEBUG_LOG(info->line, "ser_rx! %c\n", data)); - DINTR1(DEBUG_LOG(info->line, "ser_rx err stat %02X\n", rstat)); - if (!data && (rstat & SER_FRAMING_ERR_MASK)) { - /* Most likely a break, but we get interrupts over and - * over again. - */ - - if (!info->break_detected_cnt) { - DEBUG_LOG(info->line, "#BRK start\n", 0); - } - if (rstat & SER_RXD_MASK) { - /* The RX pin is high now, so the break - * must be over, but.... - * we can't really know if we will get another - * last byte ending the break or not. - * And we don't know if the byte (if any) will - * have an error or look valid. - */ - DEBUG_LOG(info->line, "# BL BRK\n", 0); - info->errorcode = ERRCODE_INSERT_BREAK; - } - info->break_detected_cnt++; - } else { - /* The error does not look like a break, but could be - * the end of one - */ - if (info->break_detected_cnt) { - DEBUG_LOG(info->line, "EBRK %i\n", info->break_detected_cnt); - info->errorcode = ERRCODE_INSERT_BREAK; - } else { - if (info->errorcode == ERRCODE_INSERT_BREAK) { - info->icount.brk++; - add_char_and_flag(info, '\0', TTY_BREAK); - } - - if (rstat & SER_PAR_ERR_MASK) { - info->icount.parity++; - add_char_and_flag(info, data, TTY_PARITY); - } else if (rstat & SER_OVERRUN_MASK) { - info->icount.overrun++; - add_char_and_flag(info, data, TTY_OVERRUN); - } else if (rstat & SER_FRAMING_ERR_MASK) { - info->icount.frame++; - add_char_and_flag(info, data, TTY_FRAME); - } - - info->errorcode = 0; - } - info->break_detected_cnt = 0; - DEBUG_LOG(info->line, "#iERR s d %04X\n", - ((rstat & SER_ERROR_MASK) << 8) | data); - } - } else { /* It was a valid byte, now let the DMA do the rest */ - unsigned long curr_time_u = GET_JIFFIES_USEC(); - unsigned long curr_time = jiffies; - - if (info->break_detected_cnt) { - /* Detect if this character is a new valid char or the - * last char in a break sequence: If LSBits are 0 and - * MSBits are high AND the time is close to the - * previous interrupt we should discard it. - */ - long elapsed_usec = - (curr_time - info->last_rx_active) * (1000000/HZ) + - curr_time_u - info->last_rx_active_usec; - if (elapsed_usec < 2*info->char_time_usec) { - DEBUG_LOG(info->line, "FBRK %i\n", info->line); - /* Report as BREAK (error) and let - * receive_chars_dma() handle it - */ - info->errorcode = ERRCODE_SET_BREAK; - } else { - DEBUG_LOG(info->line, "Not end of BRK (V)%i\n", info->line); - } - DEBUG_LOG(info->line, "num brk %i\n", info->break_detected_cnt); - } - -#ifdef SERIAL_DEBUG_INTR - printk("** OK, disabling ser_interrupts\n"); -#endif - e100_disable_serial_data_irq(info); - DINTR2(DEBUG_LOG(info->line, "ser_rx OK %d\n", info->line)); - info->break_detected_cnt = 0; - - } - /* Restarting the DMA never hurts */ - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart); - START_FLUSH_FAST_TIMER(info, "ser_int"); -} /* handle_ser_rx_interrupt */ - -static void handle_ser_tx_interrupt(struct e100_serial *info) -{ - unsigned long flags; - - if (info->x_char) { - unsigned char rstat; - DFLOW(DEBUG_LOG(info->line, "tx_int: xchar 0x%02X\n", info->x_char)); - local_irq_save(flags); - rstat = info->ioport[REG_STATUS]; - DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); - - info->ioport[REG_TR_DATA] = info->x_char; - info->icount.tx++; - info->x_char = 0; - /* We must enable since it is disabled in ser_interrupt */ - e100_enable_serial_tx_ready_irq(info); - local_irq_restore(flags); - return; - } - if (info->uses_dma_out) { - unsigned char rstat; - int i; - /* We only use normal tx interrupt when sending x_char */ - DFLOW(DEBUG_LOG(info->line, "tx_int: xchar sent\n", 0)); - local_irq_save(flags); - rstat = info->ioport[REG_STATUS]; - DFLOW(DEBUG_LOG(info->line, "stat %x\n", rstat)); - e100_disable_serial_tx_ready_irq(info); - if (info->port.tty->stopped) - rs_stop(info->port.tty); - /* Enable the DMA channel and tell it to continue */ - e100_enable_txdma_channel(info); - /* Wait 12 cycles before doing the DMA command */ - for(i = 6; i > 0; i--) - nop(); - - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, continue); - local_irq_restore(flags); - return; - } - /* Normal char-by-char interrupt */ - if (info->xmit.head == info->xmit.tail - || info->port.tty->stopped) { - DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n", - info->port.tty->stopped)); - e100_disable_serial_tx_ready_irq(info); - info->tr_running = 0; - return; - } - DINTR2(DEBUG_LOG(info->line, "tx_int %c\n", info->xmit.buf[info->xmit.tail])); - /* Send a byte, rs485 timing is critical so turn of ints */ - local_irq_save(flags); - info->ioport[REG_TR_DATA] = info->xmit.buf[info->xmit.tail]; - info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); - info->icount.tx++; - if (info->xmit.head == info->xmit.tail) { -#if defined(CONFIG_ETRAX_RS485) && defined(CONFIG_ETRAX_FAST_TIMER) - if (info->rs485.flags & SER_RS485_ENABLED) { - /* Set a short timer to toggle RTS */ - start_one_shot_timer(&fast_timers_rs485[info->line], - rs485_toggle_rts_timer_function, - (unsigned long)info, - info->char_time_usec*2, - "RS-485"); - } -#endif /* RS485 */ - info->last_tx_active_usec = GET_JIFFIES_USEC(); - info->last_tx_active = jiffies; - e100_disable_serial_tx_ready_irq(info); - info->tr_running = 0; - DFLOW(DEBUG_LOG(info->line, "tx_int: stop2\n", 0)); - } else { - /* We must enable since it is disabled in ser_interrupt */ - e100_enable_serial_tx_ready_irq(info); - } - local_irq_restore(flags); - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - -} /* handle_ser_tx_interrupt */ - -/* result of time measurements: - * RX duration 54-60 us when doing something, otherwise 6-9 us - * ser_int duration: just sending: 8-15 us normally, up to 73 us - */ -static irqreturn_t -ser_interrupt(int irq, void *dev_id) -{ - static volatile int tx_started = 0; - struct e100_serial *info; - int i; - unsigned long flags; - unsigned long irq_mask1_rd; - unsigned long data_mask = (1 << (8+2*0)); /* ser0 data_avail */ - int handled = 0; - static volatile unsigned long reentered_ready_mask = 0; - - local_irq_save(flags); - irq_mask1_rd = *R_IRQ_MASK1_RD; - /* First handle all rx interrupts with ints disabled */ - info = rs_table; - irq_mask1_rd &= e100_ser_int_mask; - for (i = 0; i < NR_PORTS; i++) { - /* Which line caused the data irq? */ - if (irq_mask1_rd & data_mask) { - handled = 1; - handle_ser_rx_interrupt(info); - } - info += 1; - data_mask <<= 2; - } - /* Handle tx interrupts with interrupts enabled so we - * can take care of new data interrupts while transmitting - * We protect the tx part with the tx_started flag. - * We disable the tr_ready interrupts we are about to handle and - * unblock the serial interrupt so new serial interrupts may come. - * - * If we get a new interrupt: - * - it migth be due to synchronous serial ports. - * - serial irq will be blocked by general irq handler. - * - async data will be handled above (sync will be ignored). - * - tx_started flag will prevent us from trying to send again and - * we will exit fast - no need to unblock serial irq. - * - Next (sync) serial interrupt handler will be runned with - * disabled interrupt due to restore_flags() at end of function, - * so sync handler will not be preempted or reentered. - */ - if (!tx_started) { - unsigned long ready_mask; - unsigned long - tx_started = 1; - /* Only the tr_ready interrupts left */ - irq_mask1_rd &= (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser1_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser2_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser3_ready)); - while (irq_mask1_rd) { - /* Disable those we are about to handle */ - *R_IRQ_MASK1_CLR = irq_mask1_rd; - /* Unblock the serial interrupt */ - *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - - local_irq_enable(); - ready_mask = (1 << (8+1+2*0)); /* ser0 tr_ready */ - info = rs_table; - for (i = 0; i < NR_PORTS; i++) { - /* Which line caused the ready irq? */ - if (irq_mask1_rd & ready_mask) { - handled = 1; - handle_ser_tx_interrupt(info); - } - info += 1; - ready_mask <<= 2; - } - /* handle_ser_tx_interrupt enables tr_ready interrupts */ - local_irq_disable(); - /* Handle reentered TX interrupt */ - irq_mask1_rd = reentered_ready_mask; - } - local_irq_disable(); - tx_started = 0; - } else { - unsigned long ready_mask; - ready_mask = irq_mask1_rd & (IO_MASK(R_IRQ_MASK1_RD, ser0_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser1_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser2_ready) | - IO_MASK(R_IRQ_MASK1_RD, ser3_ready)); - if (ready_mask) { - reentered_ready_mask |= ready_mask; - /* Disable those we are about to handle */ - *R_IRQ_MASK1_CLR = ready_mask; - DFLOW(DEBUG_LOG(SERIAL_DEBUG_LINE, "ser_int reentered with TX %X\n", ready_mask)); - } - } - - local_irq_restore(flags); - return IRQ_RETVAL(handled); -} /* ser_interrupt */ -#endif - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void -do_softint(struct work_struct *work) -{ - struct e100_serial *info; - struct tty_struct *tty; - - info = container_of(work, struct e100_serial, work); - - tty = info->port.tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) - tty_wakeup(tty); -} - -static int -startup(struct e100_serial * info) -{ - unsigned long flags; - unsigned long xmit_page; - int i; - - xmit_page = get_zeroed_page(GFP_KERNEL); - if (!xmit_page) - return -ENOMEM; - - local_irq_save(flags); - - /* if it was already initialized, skip this */ - - if (tty_port_initialized(&info->port)) { - local_irq_restore(flags); - free_page(xmit_page); - return 0; - } - - if (info->xmit.buf) - free_page(xmit_page); - else - info->xmit.buf = (unsigned char *) xmit_page; - -#ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%d (xmit_buf 0x%p)...\n", info->line, info->xmit.buf); -#endif - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - - /* - * Reset the DMA channels and make sure their interrupts are cleared - */ - - if (info->dma_in_enabled) { - info->uses_dma_in = 1; - e100_enable_rxdma_channel(info); - - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - - /* Wait until reset cycle is complete */ - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->icmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - - /* Make sure the irqs are cleared */ - *info->iclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - } else { - e100_disable_rxdma_channel(info); - } - - if (info->dma_out_enabled) { - info->uses_dma_out = 1; - e100_enable_txdma_channel(info); - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - - /* Make sure the irqs are cleared */ - *info->oclrintradr = - IO_STATE(R_DMA_CH6_CLR_INTR, clr_descr, do) | - IO_STATE(R_DMA_CH6_CLR_INTR, clr_eop, do); - } else { - e100_disable_txdma_channel(info); - } - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->xmit.head = info->xmit.tail = 0; - info->first_recv_buffer = info->last_recv_buffer = NULL; - info->recv_cnt = info->max_recv_cnt = 0; - - for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) - info->rec_descr[i].buf = 0; - - /* - * and set the speed and other flags of the serial port - * this will start the rx/tx as well - */ -#ifdef SERIAL_HANDLE_EARLY_ERRORS - e100_enable_serial_data_irq(info); -#endif - change_speed(info); - - /* dummy read to reset any serial errors */ - - (void)info->ioport[REG_DATA]; - - /* enable the interrupts */ - if (info->uses_dma_out) - e100_enable_txdma_irq(info); - - e100_enable_rx_irq(info); - - info->tr_running = 0; /* to be sure we don't lock up the transmitter */ - - /* setup the dma input descriptor and start dma */ - - start_receive(info); - - /* for safety, make sure the descriptors last result is 0 bytes written */ - - info->tr_descr.sw_len = 0; - info->tr_descr.hw_len = 0; - info->tr_descr.status = 0; - - /* enable RTS/DTR last */ - - e100_rts(info, 1); - e100_dtr(info, 1); - - tty_port_set_initialized(&info->port, 1); - - local_irq_restore(flags); - return 0; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void -shutdown(struct e100_serial * info) -{ - unsigned long flags; - struct etrax_dma_descr *descr = info->rec_descr; - struct etrax_recv_buffer *buffer; - int i; - - /* shut down the transmitter and receiver */ - DFLOW(DEBUG_LOG(info->line, "shutdown %i\n", info->line)); - e100_disable_rx(info); - info->ioport[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40); - - /* disable interrupts, reset dma channels */ - if (info->uses_dma_in) { - e100_disable_rxdma_irq(info); - *info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - info->uses_dma_in = 0; - } else { - e100_disable_serial_data_irq(info); - } - - if (info->uses_dma_out) { - e100_disable_txdma_irq(info); - info->tr_running = 0; - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - info->uses_dma_out = 0; - } else { - e100_disable_serial_tx_ready_irq(info); - info->tr_running = 0; - } - - if (!tty_port_initialized(&info->port)) - return; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d (irq %d)....\n", info->line, - info->irq); -#endif - - local_irq_save(flags); - - if (info->xmit.buf) { - free_page((unsigned long)info->xmit.buf); - info->xmit.buf = NULL; - } - - for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) - if (descr[i].buf) { - buffer = phys_to_virt(descr[i].buf) - sizeof *buffer; - kfree(buffer); - descr[i].buf = 0; - } - - if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) { - /* hang up DTR and RTS if HUPCL is enabled */ - e100_dtr(info, 0); - e100_rts(info, 0); /* could check CRTSCTS before doing this */ - } - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - tty_port_set_initialized(&info->port, 0); - local_irq_restore(flags); -} - - -/* change baud rate and other assorted parameters */ - -static void -change_speed(struct e100_serial *info) -{ - unsigned int cflag; - unsigned long xoff; - unsigned long flags; - /* first some safety checks */ - - if (!info->port.tty) - return; - if (!info->ioport) - return; - - cflag = info->port.tty->termios.c_cflag; - - /* possibly, the tx/rx should be disabled first to do this safely */ - - /* change baud-rate and write it to the hardware */ - if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) { - /* Special baudrate */ - u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ - unsigned long alt_source = - IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) | - IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); - /* R_ALT_SER_BAUDRATE selects the source */ - DBAUD(printk("Custom baudrate: baud_base/divisor %lu/%i\n", - (unsigned long)info->baud_base, info->custom_divisor)); - if (info->baud_base == SERIAL_PRESCALE_BASE) { - /* 0, 2-65535 (0=65536) */ - u16 divisor = info->custom_divisor; - /* R_SERIAL_PRESCALE (upper 16 bits of R_CLOCK_PRESCALE) */ - /* baudrate is 3.125MHz/custom_divisor */ - alt_source = - IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, prescale) | - IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, prescale); - alt_source = 0x11; - DBAUD(printk("Writing SERIAL_PRESCALE: divisor %i\n", divisor)); - *R_SERIAL_PRESCALE = divisor; - info->baud = SERIAL_PRESCALE_BASE/divisor; - } - else - { - /* Bad baudbase, we don't support using timer0 - * for baudrate. - */ - printk(KERN_WARNING "Bad baud_base/custom_divisor: %lu/%i\n", - (unsigned long)info->baud_base, info->custom_divisor); - } - r_alt_ser_baudrate_shadow &= ~mask; - r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); - *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; - } else { - /* Normal baudrate */ - /* Make sure we use normal baudrate */ - u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */ - unsigned long alt_source = - IO_STATE(R_ALT_SER_BAUDRATE, ser0_rec, normal) | - IO_STATE(R_ALT_SER_BAUDRATE, ser0_tr, normal); - r_alt_ser_baudrate_shadow &= ~mask; - r_alt_ser_baudrate_shadow |= (alt_source << (info->line*8)); - *R_ALT_SER_BAUDRATE = r_alt_ser_baudrate_shadow; - - info->baud = cflag_to_baud(cflag); - info->ioport[REG_BAUD] = cflag_to_etrax_baud(cflag); - } - - /* start with default settings and then fill in changes */ - local_irq_save(flags); - /* 8 bit, no/even parity */ - info->rx_ctrl &= ~(IO_MASK(R_SERIAL0_REC_CTRL, rec_bitnr) | - IO_MASK(R_SERIAL0_REC_CTRL, rec_par_en) | - IO_MASK(R_SERIAL0_REC_CTRL, rec_par)); - - /* 8 bit, no/even parity, 1 stop bit, no cts */ - info->tx_ctrl &= ~(IO_MASK(R_SERIAL0_TR_CTRL, tr_bitnr) | - IO_MASK(R_SERIAL0_TR_CTRL, tr_par_en) | - IO_MASK(R_SERIAL0_TR_CTRL, tr_par) | - IO_MASK(R_SERIAL0_TR_CTRL, stop_bits) | - IO_MASK(R_SERIAL0_TR_CTRL, auto_cts)); - - if ((cflag & CSIZE) == CS7) { - /* set 7 bit mode */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); - } - - if (cflag & CSTOPB) { - /* set 2 stop bit mode */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, two_bits); - } - - if (cflag & PARENB) { - /* enable parity */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); - } - - if (cflag & CMSPAR) { - /* enable stick parity, PARODD mean Mark which matches ETRAX */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, stick); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, stick); - } - if (cflag & PARODD) { - /* set odd parity (or Mark if CMSPAR) */ - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd); - } - - if (cflag & CRTSCTS) { - /* enable automatic CTS handling */ - DFLOW(DEBUG_LOG(info->line, "FLOW auto_cts enabled\n", 0)); - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, active); - } - - /* make sure the tx and rx are enabled */ - - info->tx_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable); - info->rx_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); - - /* actually write the control regs to the hardware */ - - info->ioport[REG_TR_CTRL] = info->tx_ctrl; - info->ioport[REG_REC_CTRL] = info->rx_ctrl; - xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); - xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (info->port.tty->termios.c_iflag & IXON ) { - DFLOW(DEBUG_LOG(info->line, "FLOW XOFF enabled 0x%02X\n", - STOP_CHAR(info->port.tty))); - xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } - - *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; - local_irq_restore(flags); - - update_char_time(info); - -} /* change_speed */ - -/* start transmitting chars NOW */ - -static void -rs_flush_chars(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - if (info->tr_running || - info->xmit.head == info->xmit.tail || - tty->stopped || - !info->xmit.buf) - return; - -#ifdef SERIAL_DEBUG_FLOW - printk("rs_flush_chars\n"); -#endif - - /* this protection might not exactly be necessary here */ - - local_irq_save(flags); - start_transmit(info); - local_irq_restore(flags); -} - -static int rs_raw_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - /* first some sanity checks */ - - if (!info->xmit.buf) - return 0; - -#ifdef SERIAL_DEBUG_DATA - if (info->line == SERIAL_DEBUG_LINE) - printk("rs_raw_write (%d), status %d\n", - count, info->ioport[REG_STATUS]); -#endif - - local_save_flags(flags); - DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); - DFLOW(DEBUG_LOG(info->line, "ldisc\n")); - - - /* The local_irq_disable/restore_flags pairs below are needed - * because the DMA interrupt handler moves the info->xmit values. - * the memcpy needs to be in the critical region unfortunately, - * because we need to read xmit values, memcpy, write xmit values - * in one atomic operation... this could perhaps be avoided by - * more clever design. - */ - local_irq_disable(); - while (count) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - - if (count < c) - c = count; - if (c <= 0) - break; - - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = (info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1); - buf += c; - count -= c; - ret += c; - } - local_irq_restore(flags); - - /* enable transmitter if not running, unless the tty is stopped - * this does not need IRQ protection since if tr_running == 0 - * the IRQ's are not running anyway for this port. - */ - DFLOW(DEBUG_LOG(info->line, "write ret %i\n", ret)); - - if (info->xmit.head != info->xmit.tail && - !tty->stopped && - !info->tr_running) { - start_transmit(info); - } - - return ret; -} /* raw_raw_write() */ - -static int -rs_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ -#if defined(CONFIG_ETRAX_RS485) - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - - if (info->rs485.flags & SER_RS485_ENABLED) - { - /* If we are in RS-485 mode, we need to toggle RTS and disable - * the receiver before initiating a DMA transfer - */ -#ifdef CONFIG_ETRAX_FAST_TIMER - /* Abort any started timer */ - fast_timers_rs485[info->line].function = NULL; - del_fast_timer(&fast_timers_rs485[info->line]); -#endif - e100_rts(info, (info->rs485.flags & SER_RS485_RTS_ON_SEND)); -#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER) - e100_disable_rx(info); - e100_enable_rx_irq(info); -#endif - if (info->rs485.delay_rts_before_send > 0) - msleep(info->rs485.delay_rts_before_send); - } -#endif /* CONFIG_ETRAX_RS485 */ - - count = rs_raw_write(tty, buf, count); - -#if defined(CONFIG_ETRAX_RS485) - if (info->rs485.flags & SER_RS485_ENABLED) - { - unsigned int val; - /* If we are in RS-485 mode the following has to be done: - * wait until DMA is ready - * wait on transmit shift register - * toggle RTS - * enable the receiver - */ - - /* Sleep until all sent */ - tty_wait_until_sent(tty, 0); -#ifdef CONFIG_ETRAX_FAST_TIMER - /* Now sleep a little more so that shift register is empty */ - schedule_usleep(info->char_time_usec * 2); -#endif - /* wait on transmit shift register */ - do{ - get_lsr_info(info, &val); - }while (!(val & TIOCSER_TEMT)); - - e100_rts(info, (info->rs485.flags & SER_RS485_RTS_AFTER_SEND)); - -#if defined(CONFIG_ETRAX_RS485_DISABLE_RECEIVER) - e100_enable_rx(info); - e100_enable_rxdma_irq(info); -#endif - } -#endif /* CONFIG_ETRAX_RS485 */ - - return count; -} /* rs_write */ - - -/* how much space is available in the xmit buffer? */ - -static int -rs_write_room(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -/* How many chars are in the xmit buffer? - * This does not include any chars in the transmitter FIFO. - * Use wait_until_sent for waiting for FIFO drain. - */ - -static int -rs_chars_in_buffer(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -/* discard everything in the xmit buffer */ - -static void -rs_flush_buffer(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - local_irq_save(flags); - info->xmit.head = info->xmit.tail = 0; - local_irq_restore(flags); - - tty_wakeup(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - * - * Since we use DMA we don't check for info->x_char in transmit_chars_dma(), - * but we do it in handle_ser_tx_interrupt(). - * We disable DMA channel and enable tx ready interrupt and write the - * character when possible. - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - local_irq_save(flags); - if (info->uses_dma_out) { - /* Put the DMA on hold and disable the channel */ - *info->ocmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, hold); - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *info->ocmdadr) != - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, hold)); - e100_disable_txdma_channel(info); - } - - /* Must make sure transmitter is not stopped before we can transmit */ - if (tty->stopped) - rs_start(tty); - - /* Enable manual transmit interrupt and send from there */ - DFLOW(DEBUG_LOG(info->line, "rs_send_xchar 0x%02X\n", ch)); - info->x_char = ch; - e100_enable_serial_tx_ready_irq(info); - local_irq_restore(flags); -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void -rs_throttle(struct tty_struct * tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; -#ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s ....\n", tty_name(tty)); -#endif - DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); - - /* Do RTS before XOFF since XOFF might take some time */ - if (C_CRTSCTS(tty)) { - /* Turn off RTS line */ - e100_rts(info, 0); - } - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - -} - -static void -rs_unthrottle(struct tty_struct * tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; -#ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s ....\n", tty_name(tty)); -#endif - DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); - DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); - /* Do RTS before XOFF since XOFF might take some time */ - if (C_CRTSCTS(tty)) { - /* Assert RTS line */ - e100_rts(info, 1); - } - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int -get_serial_info(struct e100_serial * info, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - - /* this is all probably wrong, there are a lot of fields - * here that we don't have in e100_serial and maybe we - * should set them to something else than 0. - */ - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = (int)info->ioport; - tmp.irq = info->irq; - tmp.flags = info->port.flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->port.close_delay; - tmp.closing_wait = info->port.closing_wait; - tmp.custom_divisor = info->custom_divisor; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int -set_serial_info(struct e100_serial *info, - struct serial_struct *new_info) -{ - struct serial_struct new_serial; - struct e100_serial old_info; - int retval = 0; - - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.type != info->type) || - (new_serial.close_delay != info->port.close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->port.flags & ~ASYNC_USR_MASK))) - return -EPERM; - info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - goto check_and_exit; - } - - if (info->port.count > 1) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->custom_divisor = new_serial.custom_divisor; - info->type = new_serial.type; - info->port.close_delay = new_serial.close_delay; - info->port.closing_wait = new_serial.closing_wait; - info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - check_and_exit: - if (tty_port_initialized(&info->port)) - change_speed(info); - else - retval = startup(info); - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int -get_lsr_info(struct e100_serial * info, unsigned int *value) -{ - unsigned int result = TIOCSER_TEMT; - unsigned long curr_time = jiffies; - unsigned long curr_time_usec = GET_JIFFIES_USEC(); - unsigned long elapsed_usec = - (curr_time - info->last_tx_active) * 1000000/HZ + - curr_time_usec - info->last_tx_active_usec; - - if (info->xmit.head != info->xmit.tail || - elapsed_usec < 2*info->char_time_usec) { - result = 0; - } - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - -#ifdef SERIAL_DEBUG_IO -struct state_str -{ - int state; - const char *str; -}; - -const struct state_str control_state_str[] = { - {TIOCM_DTR, "DTR" }, - {TIOCM_RTS, "RTS"}, - {TIOCM_ST, "ST?" }, - {TIOCM_SR, "SR?" }, - {TIOCM_CTS, "CTS" }, - {TIOCM_CD, "CD" }, - {TIOCM_RI, "RI" }, - {TIOCM_DSR, "DSR" }, - {0, NULL } -}; - -char *get_control_state_str(int MLines, char *s) -{ - int i = 0; - - s[0]='\0'; - while (control_state_str[i].str != NULL) { - if (MLines & control_state_str[i].state) { - if (s[0] != '\0') { - strcat(s, ", "); - } - strcat(s, control_state_str[i].str); - } - i++; - } - return s; -} -#endif - -static int -rs_break(struct tty_struct *tty, int break_state) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - if (!info->ioport) - return -EIO; - - local_irq_save(flags); - if (break_state == -1) { - /* Go to manual mode and set the txd pin to 0 */ - /* Clear bit 7 (txd) and 6 (tr_enable) */ - info->tx_ctrl &= 0x3F; - } else { - /* Set bit 7 (txd) and 6 (tr_enable) */ - info->tx_ctrl |= (0x80 | 0x40); - } - info->ioport[REG_TR_CTRL] = info->tx_ctrl; - local_irq_restore(flags); - return 0; -} - -static int -rs_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - local_irq_save(flags); - - if (clear & TIOCM_RTS) - e100_rts(info, 0); - if (clear & TIOCM_DTR) - e100_dtr(info, 0); - /* Handle FEMALE behaviour */ - if (clear & TIOCM_RI) - e100_ri_out(info, 0); - if (clear & TIOCM_CD) - e100_cd_out(info, 0); - - if (set & TIOCM_RTS) - e100_rts(info, 1); - if (set & TIOCM_DTR) - e100_dtr(info, 1); - /* Handle FEMALE behaviour */ - if (set & TIOCM_RI) - e100_ri_out(info, 1); - if (set & TIOCM_CD) - e100_cd_out(info, 1); - - local_irq_restore(flags); - return 0; -} - -static int -rs_tiocmget(struct tty_struct *tty) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned int result; - unsigned long flags; - - local_irq_save(flags); - - result = - (!E100_RTS_GET(info) ? TIOCM_RTS : 0) - | (!E100_DTR_GET(info) ? TIOCM_DTR : 0) - | (!E100_RI_GET(info) ? TIOCM_RNG : 0) - | (!E100_DSR_GET(info) ? TIOCM_DSR : 0) - | (!E100_CD_GET(info) ? TIOCM_CAR : 0) - | (!E100_CTS_GET(info) ? TIOCM_CTS : 0); - - local_irq_restore(flags); - -#ifdef SERIAL_DEBUG_IO - printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n", - info->line, result, result); - { - char s[100]; - - get_control_state_str(result, s); - printk(KERN_DEBUG "state: %s\n", s); - } -#endif - return result; - -} - - -static int -rs_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty_io_error(tty)) - return -EIO; - } - - switch (cmd) { - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct e100_serial *) arg, - info, sizeof(struct e100_serial))) - return -EFAULT; - return 0; - -#if defined(CONFIG_ETRAX_RS485) - case TIOCSERSETRS485: - { - /* In this ioctl we still use the old structure - * rs485_control for backward compatibility - * (if we use serial_rs485, then old user-level code - * wouldn't work anymore...). - * The use of this ioctl is deprecated: use TIOCSRS485 - * instead.*/ - struct rs485_control rs485ctrl; - struct serial_rs485 rs485data; - printk(KERN_DEBUG "The use of this ioctl is deprecated. Use TIOCSRS485 instead\n"); - if (copy_from_user(&rs485ctrl, (struct rs485_control *)arg, - sizeof(rs485ctrl))) - return -EFAULT; - - rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send; - rs485data.flags = 0; - - if (rs485ctrl.enabled) - rs485data.flags |= SER_RS485_ENABLED; - else - rs485data.flags &= ~(SER_RS485_ENABLED); - - if (rs485ctrl.rts_on_send) - rs485data.flags |= SER_RS485_RTS_ON_SEND; - else - rs485data.flags &= ~(SER_RS485_RTS_ON_SEND); - - if (rs485ctrl.rts_after_sent) - rs485data.flags |= SER_RS485_RTS_AFTER_SEND; - else - rs485data.flags &= ~(SER_RS485_RTS_AFTER_SEND); - - return e100_enable_rs485(tty, &rs485data); - } - - case TIOCSRS485: - { - /* This is the new version of TIOCSRS485, with new - * data structure serial_rs485 */ - struct serial_rs485 rs485data; - if (copy_from_user(&rs485data, (struct rs485_control *)arg, - sizeof(rs485data))) - return -EFAULT; - - 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(struct serial_rs485))) - return -EFAULT; - break; - } - - case TIOCSERWRRS485: - { - struct rs485_write rs485wr; - if (copy_from_user(&rs485wr, (struct rs485_write *)arg, - sizeof(rs485wr))) - return -EFAULT; - - return e100_write_rs485(tty, rs485wr.outc, rs485wr.outc_size); - } -#endif - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void -rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - - change_speed(info); - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) - rs_start(tty); - -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * S structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void -rs_close(struct tty_struct *tty, struct file * filp) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - unsigned long flags; - - if (!info) - return; - - /* interrupts are disabled for this entire function */ - - local_irq_save(flags); - - if (tty_hung_up_p(filp)) { - local_irq_restore(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("[%d] rs_close ttyS%d, count = %d\n", current->pid, - info->line, info->count); -#endif - if ((tty->count == 1) && (info->port.count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk(KERN_ERR - "rs_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->port.count); - info->port.count = 1; - } - if (--info->port.count < 0) { - printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n", - info->line, info->port.count); - info->port.count = 0; - } - if (info->port.count) { - local_irq_restore(flags); - return; - } - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->port.closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the serial receiver and the DMA receive interrupt. - */ -#ifdef SERIAL_HANDLE_EARLY_ERRORS - e100_disable_serial_data_irq(info); -#endif - - e100_disable_rx(info); - e100_disable_rx_irq(info); - - if (tty_port_initialized(&info->port)) { - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important as we have a transmit FIFO! - */ - rs_wait_until_sent(tty, HZ); - } - - shutdown(info); - rs_flush_buffer(tty); - tty_ldisc_flush(tty); - tty->closing = 0; - info->event = 0; - info->port.tty = NULL; - if (info->port.blocked_open) { - if (info->port.close_delay) - schedule_timeout_interruptible(info->port.close_delay); - wake_up_interruptible(&info->port.open_wait); - } - local_irq_restore(flags); - tty_port_set_active(&info->port, 0); - - /* port closed */ - -#if defined(CONFIG_ETRAX_RS485) - if (info->rs485.flags & SER_RS485_ENABLED) { - info->rs485.flags &= ~(SER_RS485_ENABLED); -#if defined(CONFIG_ETRAX_RS485_ON_PA) - *R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit); -#endif - } -#endif - - /* - * Release any allocated DMA irq's. - */ - if (info->dma_in_enabled) { - free_irq(info->dma_in_irq_nbr, info); - cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); - info->uses_dma_in = 0; -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "DMA irq '%s' freed\n", - info->dma_in_irq_description); -#endif - } - if (info->dma_out_enabled) { - free_irq(info->dma_out_irq_nbr, info); - cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); - info->uses_dma_out = 0; -#ifdef SERIAL_DEBUG_OPEN - printk(KERN_DEBUG "DMA irq '%s' freed\n", - info->dma_out_irq_description); -#endif - } -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - unsigned long orig_jiffies; - struct e100_serial *info = (struct e100_serial *)tty->driver_data; - unsigned long curr_time = jiffies; - unsigned long curr_time_usec = GET_JIFFIES_USEC(); - long elapsed_usec = - (curr_time - info->last_tx_active) * (1000000/HZ) + - curr_time_usec - info->last_tx_active_usec; - - /* - * 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) - */ - orig_jiffies = jiffies; - while (info->xmit.head != info->xmit.tail || /* More in send queue */ - (*info->ostatusadr & 0x007f) || /* more in FIFO */ - (elapsed_usec < 2*info->char_time_usec)) { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - curr_time = jiffies; - curr_time_usec = GET_JIFFIES_USEC(); - elapsed_usec = - (curr_time - info->last_tx_active) * (1000000/HZ) + - curr_time_usec - info->last_tx_active_usec; - } - set_current_state(TASK_RUNNING); -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void -rs_hangup(struct tty_struct *tty) -{ - struct e100_serial * info = (struct e100_serial *)tty->driver_data; - - rs_flush_buffer(tty); - shutdown(info); - info->event = 0; - info->port.count = 0; - tty_port_set_active(&info->port, 0); - info->port.tty = NULL; - wake_up_interruptible(&info->port.open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int -block_til_ready(struct tty_struct *tty, struct file * filp, - struct e100_serial *info) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int retval; - int do_clocal = 0; - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || tty_io_error(tty)) { - tty_port_set_active(&info->port, 1); - return 0; - } - - if (C_CLOCAL(tty)) - do_clocal = 1; - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->port.count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->port.open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttyS%d, count = %d\n", - info->line, info->port.count); -#endif - local_irq_save(flags); - info->port.count--; - local_irq_restore(flags); - info->port.blocked_open++; - while (1) { - local_irq_save(flags); - /* assert RTS and DTR */ - e100_rts(info, 1); - e100_dtr(info, 1); - local_irq_restore(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || !tty_port_initialized(&info->port)) { -#ifdef SERIAL_DO_RESTART - if (info->port.flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (do_clocal) - /* && (do_clocal || DCD_IS_ASSERTED) */ - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttyS%d, count = %d\n", - info->line, info->port.count); -#endif - tty_unlock(tty); - schedule(); - tty_lock(tty); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->port.open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->port.count++; - info->port.blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttyS%d, count = %d\n", - info->line, info->port.count); -#endif - if (retval) - return retval; - tty_port_set_active(&info->port, 1); - return 0; -} - -static void -deinit_port(struct e100_serial *info) -{ - if (info->dma_out_enabled) { - cris_free_dma(info->dma_out_nbr, info->dma_out_irq_description); - free_irq(info->dma_out_irq_nbr, info); - } - if (info->dma_in_enabled) { - cris_free_dma(info->dma_in_nbr, info->dma_in_irq_description); - free_irq(info->dma_in_irq_nbr, info); - } -} - -/* - * This routine is called whenever a serial port is opened. - * It performs the serial-specific initialization for the tty structure. - */ -static int -rs_open(struct tty_struct *tty, struct file * filp) -{ - struct e100_serial *info; - int retval; - int allocated_resources = 0; - - info = rs_table + tty->index; - if (!info->enabled) - return -ENODEV; - -#ifdef SERIAL_DEBUG_OPEN - printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name, - info->port.count); -#endif - - info->port.count++; - tty->driver_data = info; - info->port.tty = tty; - - info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY); - - /* - * If DMA is enabled try to allocate the irq's. - */ - if (info->port.count == 1) { - allocated_resources = 1; - if (info->dma_in_enabled) { - if (request_irq(info->dma_in_irq_nbr, - rec_interrupt, - info->dma_in_irq_flags, - info->dma_in_irq_description, - info)) { - printk(KERN_WARNING "DMA irq '%s' busy; " - "falling back to non-DMA mode\n", - info->dma_in_irq_description); - /* Make sure we never try to use DMA in */ - /* for the port again. */ - info->dma_in_enabled = 0; - } else if (cris_request_dma(info->dma_in_nbr, - info->dma_in_irq_description, - DMA_VERBOSE_ON_ERROR, - info->dma_owner)) { - free_irq(info->dma_in_irq_nbr, info); - printk(KERN_WARNING "DMA '%s' busy; " - "falling back to non-DMA mode\n", - info->dma_in_irq_description); - /* Make sure we never try to use DMA in */ - /* for the port again. */ - info->dma_in_enabled = 0; - } -#ifdef SERIAL_DEBUG_OPEN - else - printk(KERN_DEBUG "DMA irq '%s' allocated\n", - info->dma_in_irq_description); -#endif - } - if (info->dma_out_enabled) { - if (request_irq(info->dma_out_irq_nbr, - tr_interrupt, - info->dma_out_irq_flags, - info->dma_out_irq_description, - info)) { - printk(KERN_WARNING "DMA irq '%s' busy; " - "falling back to non-DMA mode\n", - info->dma_out_irq_description); - /* Make sure we never try to use DMA out */ - /* for the port again. */ - info->dma_out_enabled = 0; - } else if (cris_request_dma(info->dma_out_nbr, - info->dma_out_irq_description, - DMA_VERBOSE_ON_ERROR, - info->dma_owner)) { - free_irq(info->dma_out_irq_nbr, info); - printk(KERN_WARNING "DMA '%s' busy; " - "falling back to non-DMA mode\n", - info->dma_out_irq_description); - /* Make sure we never try to use DMA out */ - /* for the port again. */ - info->dma_out_enabled = 0; - } -#ifdef SERIAL_DEBUG_OPEN - else - printk(KERN_DEBUG "DMA irq '%s' allocated\n", - info->dma_out_irq_description); -#endif - } - } - - /* - * Start up the serial port - */ - - retval = startup(info); - if (retval) { - if (allocated_resources) - deinit_port(info); - - /* FIXME Decrease count info->port.count here too? */ - return retval; - } - - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open returning after block_til_ready with %d\n", - retval); -#endif - if (allocated_resources) - deinit_port(info); - - return retval; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open ttyS%d successful...\n", info->line); -#endif - DLOG_INT_TRIG( log_int_pos = 0); - - DFLIP( if (info->line == SERIAL_DEBUG_LINE) { - info->icount.rx = 0; - } ); - - return 0; -} - -#ifdef CONFIG_PROC_FS -/* - * /proc fs routines.... - */ - -static void seq_line_info(struct seq_file *m, struct e100_serial *info) -{ - unsigned long tmp; - - seq_printf(m, "%d: uart:E100 port:%lX irq:%d", - info->line, (unsigned long)info->ioport, info->irq); - - if (!info->ioport || (info->type == PORT_UNKNOWN)) { - seq_printf(m, "\n"); - return; - } - - seq_printf(m, " baud:%d", info->baud); - seq_printf(m, " tx:%lu rx:%lu", - (unsigned long)info->icount.tx, - (unsigned long)info->icount.rx); - tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (tmp) - seq_printf(m, " tx_pend:%lu/%lu", - (unsigned long)tmp, - (unsigned long)SERIAL_XMIT_SIZE); - - seq_printf(m, " rx_pend:%lu/%lu", - (unsigned long)info->recv_cnt, - (unsigned long)info->max_recv_cnt); - -#if 1 - if (info->port.tty) { - if (info->port.tty->stopped) - seq_printf(m, " stopped:%i", - (int)info->port.tty->stopped); - } - - { - unsigned char rstat = info->ioport[REG_STATUS]; - if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect)) - seq_printf(m, " xoff_detect:1"); - } - -#endif - - if (info->icount.frame) - seq_printf(m, " fe:%lu", (unsigned long)info->icount.frame); - - if (info->icount.parity) - seq_printf(m, " pe:%lu", (unsigned long)info->icount.parity); - - if (info->icount.brk) - seq_printf(m, " brk:%lu", (unsigned long)info->icount.brk); - - if (info->icount.overrun) - seq_printf(m, " oe:%lu", (unsigned long)info->icount.overrun); - - /* - * Last thing is the RS-232 status lines - */ - if (!E100_RTS_GET(info)) - seq_puts(m, "|RTS"); - if (!E100_CTS_GET(info)) - seq_puts(m, "|CTS"); - if (!E100_DTR_GET(info)) - seq_puts(m, "|DTR"); - if (!E100_DSR_GET(info)) - seq_puts(m, "|DSR"); - if (!E100_CD_GET(info)) - seq_puts(m, "|CD"); - if (!E100_RI_GET(info)) - seq_puts(m, "|RI"); - seq_puts(m, "\n"); -} - - -static int crisv10_proc_show(struct seq_file *m, void *v) -{ - int i; - - seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); - - for (i = 0; i < NR_PORTS; i++) { - if (!rs_table[i].enabled) - continue; - seq_line_info(m, &rs_table[i]); - } -#ifdef DEBUG_LOG_INCLUDED - for (i = 0; i < debug_log_pos; i++) { - seq_printf(m, "%-4i %lu.%lu ", - i, debug_log[i].time, - timer_data_to_ns(debug_log[i].timer_data)); - seq_printf(m, debug_log[i].string, debug_log[i].value); - } - seq_printf(m, "debug_log %i/%i\n", i, DEBUG_LOG_SIZE); - debug_log_pos = 0; -#endif - return 0; -} - -static int crisv10_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, crisv10_proc_show, NULL); -} - -static const struct file_operations crisv10_proc_fops = { - .owner = THIS_MODULE, - .open = crisv10_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - - -/* Finally, routines used to initialize the serial driver. */ - -static void show_serial_version(void) -{ - printk(KERN_INFO - "ETRAX 100LX serial-driver %s, " - "(c) 2000-2004 Axis Communications AB\r\n", - &serial_version[11]); /* "$Revision: x.yy" */ -} - -/* rs_init inits the driver at boot (using the initcall chain) */ - -static const struct tty_operations rs_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .break_ctl = rs_break, - .send_xchar = rs_send_xchar, - .wait_until_sent = rs_wait_until_sent, - .tiocmget = rs_tiocmget, - .tiocmset = rs_tiocmset, -#ifdef CONFIG_PROC_FS - .proc_fops = &crisv10_proc_fops, -#endif -}; - -static int __init rs_init(void) -{ - int i; - struct e100_serial *info; - struct tty_driver *driver = alloc_tty_driver(NR_PORTS); - - if (!driver) - return -ENOMEM; - - show_serial_version(); - - /* Setup the timed flush handler system */ - -#if !defined(CONFIG_ETRAX_SERIAL_FAST_TIMER) - timer_setup(&flush_timer, timed_flush_handler, 0); - mod_timer(&flush_timer, jiffies + 5); -#endif - -#if defined(CONFIG_ETRAX_RS485) -#if defined(CONFIG_ETRAX_RS485_ON_PA) - if (cris_io_interface_allocate_pins(if_serial_0, 'a', rs485_pa_bit, - rs485_pa_bit)) { - printk(KERN_ERR "ETRAX100LX serial: Could not allocate " - "RS485 pin\n"); - put_tty_driver(driver); - return -EBUSY; - } -#endif -#endif - - /* Initialize the tty_driver structure */ - - driver->driver_name = "serial"; - driver->name = "ttyS"; - driver->major = TTY_MAJOR; - driver->minor_start = 64; - driver->type = TTY_DRIVER_TYPE_SERIAL; - driver->subtype = SERIAL_TYPE_NORMAL; - driver->init_termios = tty_std_termios; - driver->init_termios.c_cflag = - B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ - driver->init_termios.c_ispeed = 115200; - driver->init_termios.c_ospeed = 115200; - driver->flags = TTY_DRIVER_REAL_RAW; - - tty_set_operations(driver, &rs_ops); - serial_driver = driver; - - /* do some initializing for the separate ports */ - for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { - if (info->enabled) { - if (cris_request_io_interface(info->io_if, - info->io_if_description)) { - printk(KERN_ERR "ETRAX100LX async serial: " - "Could not allocate IO pins for " - "%s, port %d\n", - info->io_if_description, i); - info->enabled = 0; - } - } - tty_port_init(&info->port); - info->uses_dma_in = 0; - info->uses_dma_out = 0; - info->line = i; - info->port.tty = NULL; - info->type = PORT_ETRAX; - info->tr_running = 0; - info->forced_eop = 0; - info->baud_base = DEF_BAUD_BASE; - info->custom_divisor = 0; - info->x_char = 0; - info->event = 0; - info->xmit.buf = NULL; - info->xmit.tail = info->xmit.head = 0; - info->first_recv_buffer = info->last_recv_buffer = NULL; - info->recv_cnt = info->max_recv_cnt = 0; - info->last_tx_active_usec = 0; - info->last_tx_active = 0; - -#if defined(CONFIG_ETRAX_RS485) - /* Set sane defaults */ - info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND); - info->rs485.flags |= SER_RS485_RTS_AFTER_SEND; - info->rs485.delay_rts_before_send = 0; - info->rs485.flags &= ~(SER_RS485_ENABLED); -#endif - INIT_WORK(&info->work, do_softint); - - if (info->enabled) { - printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", - serial_driver->name, info->line, info->ioport); - } - tty_port_link_device(&info->port, driver, i); - } - - if (tty_register_driver(driver)) - panic("Couldn't register serial driver\n"); - -#ifdef CONFIG_ETRAX_FAST_TIMER -#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER - memset(fast_timers, 0, sizeof(fast_timers)); -#endif -#ifdef CONFIG_ETRAX_RS485 - memset(fast_timers_rs485, 0, sizeof(fast_timers_rs485)); -#endif - fast_timer_init(); -#endif - -#ifndef CONFIG_ETRAX_KGDB - /* Not needed in simulator. May only complicate stuff. */ - /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ - - if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, - IRQF_SHARED, "serial ", driver)) - panic("%s: Failed to request irq8", __func__); - -#endif - - return 0; -} - -/* this makes sure that rs_init is called during kernel boot */ -device_initcall(rs_init); diff --git a/drivers/tty/serial/crisv10.h b/drivers/tty/serial/crisv10.h deleted file mode 100644 index 79ba2bc95d3d..000000000000 --- a/drivers/tty/serial/crisv10.h +++ /dev/null @@ -1,133 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * serial.h: Arch-dep definitions for the Etrax100 serial driver. - * - * Copyright (C) 1998-2007 Axis Communications AB - */ - -#ifndef _ETRAX_SERIAL_H -#define _ETRAX_SERIAL_H - -#include <linux/circ_buf.h> -#include <asm/termios.h> -#include <asm/dma.h> -#include <arch/io_interface_mux.h> - -/* Software state per channel */ - -#ifdef __KERNEL__ -/* - * This is our internal structure for each serial port's state. - * - * Many fields are paralleled by the structure used by the serial_struct - * structure. - * - * For definitions of the flags field, see tty.h - */ - -#define SERIAL_RECV_DESCRIPTORS 8 - -struct etrax_recv_buffer { - struct etrax_recv_buffer *next; - unsigned short length; - unsigned char error; - unsigned char pad; - - unsigned char buffer[0]; -}; - -struct e100_serial { - struct tty_port port; - int baud; - volatile u8 *ioport; /* R_SERIALx_CTRL */ - u32 irq; /* bitnr in R_IRQ_MASK2 for dmaX_descr */ - - /* Output registers */ - volatile u8 *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ - volatile u32 *ofirstadr; /* adr to R_DMA_CHx_FIRST */ - volatile u8 *ocmdadr; /* adr to R_DMA_CHx_CMD */ - const volatile u8 *ostatusadr; /* adr to R_DMA_CHx_STATUS */ - - /* Input registers */ - volatile u8 *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR */ - volatile u32 *ifirstadr; /* adr to R_DMA_CHx_FIRST */ - volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */ - volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */ - - u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */ - u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */ - u8 iseteop; /* bit number for R_SET_EOP for the input dma */ - int enabled; /* Set to 1 if the port is enabled in HW config */ - - u8 dma_out_enabled; /* Set to 1 if DMA should be used */ - u8 dma_in_enabled; /* Set to 1 if DMA should be used */ - - /* end of fields defined in rs_table[] in .c-file */ - int dma_owner; - unsigned int dma_in_nbr; - unsigned int dma_out_nbr; - unsigned int dma_in_irq_nbr; - unsigned int dma_out_irq_nbr; - unsigned long dma_in_irq_flags; - unsigned long dma_out_irq_flags; - char *dma_in_irq_description; - char *dma_out_irq_description; - - enum cris_io_interface io_if; - char *io_if_description; - - u8 uses_dma_in; /* Set to 1 if DMA is used */ - u8 uses_dma_out; /* Set to 1 if DMA is used */ - u8 forced_eop; /* a fifo eop has been forced */ - int baud_base; /* For special baudrates */ - int custom_divisor; /* For special baudrates */ - struct etrax_dma_descr tr_descr; - struct etrax_dma_descr rec_descr[SERIAL_RECV_DESCRIPTORS]; - int cur_rec_descr; - - volatile int tr_running; /* 1 if output is running */ - - int x_char; /* xon/xoff character */ - unsigned long event; - int line; - int type; /* PORT_ETRAX */ - struct circ_buf xmit; - struct etrax_recv_buffer *first_recv_buffer; - struct etrax_recv_buffer *last_recv_buffer; - unsigned int recv_cnt; - unsigned int max_recv_cnt; - - struct work_struct work; - struct async_icount icount; /* error-statistics etc.*/ - - unsigned long char_time_usec; /* The time for 1 char, in usecs */ - unsigned long flush_time_usec; /* How often we should flush */ - unsigned long last_tx_active_usec; /* Last tx usec in the jiffies */ - unsigned long last_tx_active; /* Last tx time in jiffies */ - unsigned long last_rx_active_usec; /* Last rx usec in the jiffies */ - unsigned long last_rx_active; /* Last rx time in jiffies */ - - int break_detected_cnt; - int errorcode; - -#ifdef CONFIG_ETRAX_RS485 - struct serial_rs485 rs485; /* RS-485 support */ -#endif -}; - -/* this PORT is not in the standard serial.h. it's not actually used for - * anything since we only have one type of async serial-port anyway in this - * system. - */ - -#define PORT_ETRAX 1 - -/* - * Events are used to schedule things to happen at timer-interrupt - * time, instead of at rs interrupt time. - */ -#define RS_EVENT_WRITE_WAKEUP 0 - -#endif /* __KERNEL__ */ - -#endif /* !_ETRAX_SERIAL_H */ diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c deleted file mode 100644 index 24bf6bfb29b4..000000000000 --- a/drivers/tty/serial/etraxfs-uart.c +++ /dev/null @@ -1,960 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/module.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/platform_device.h> -#include <linux/serial_core.h> -#include <linux/tty_flip.h> -#include <linux/of.h> -#include <linux/gpio.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> -#include <hwregs/ser_defs.h> - -#include "serial_mctrl_gpio.h" - -#define DRV_NAME "etraxfs-uart" -#define UART_NR CONFIG_ETRAX_SERIAL_PORTS - -#define MODIFY_REG(instance, reg, var) \ - do { \ - if (REG_RD_INT(ser, instance, reg) != \ - REG_TYPE_CONV(int, reg_ser_##reg, var)) \ - REG_WR(ser, instance, reg, var); \ - } while (0) - -struct uart_cris_port { - struct uart_port port; - - int initialized; - int irq; - - void __iomem *regi_ser; - - struct mctrl_gpios *gpios; - - int write_ongoing; -}; - -static struct uart_driver etraxfs_uart_driver; -static struct uart_port *console_port; -static int console_baud = 115200; -static struct uart_cris_port *etraxfs_uart_ports[UART_NR]; - -static void cris_serial_port_init(struct uart_port *port, int line); -static void etraxfs_uart_stop_rx(struct uart_port *port); -static inline void etraxfs_uart_start_tx_bottom(struct uart_port *port); - -#ifdef CONFIG_SERIAL_ETRAXFS_CONSOLE -static void -cris_console_write(struct console *co, const char *s, unsigned int count) -{ - struct uart_cris_port *up; - int i; - reg_ser_r_stat_din stat; - reg_ser_rw_tr_dma_en tr_dma_en, old; - - up = etraxfs_uart_ports[co->index]; - - if (!up) - return; - - /* Switch to manual mode. */ - tr_dma_en = old = REG_RD(ser, up->regi_ser, rw_tr_dma_en); - if (tr_dma_en.en == regk_ser_yes) { - tr_dma_en.en = regk_ser_no; - REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en); - } - - /* Send data. */ - for (i = 0; i < count; i++) { - /* LF -> CRLF */ - if (s[i] == '\n') { - do { - stat = REG_RD(ser, up->regi_ser, r_stat_din); - } while (!stat.tr_rdy); - REG_WR_INT(ser, up->regi_ser, rw_dout, '\r'); - } - /* Wait until transmitter is ready and send. */ - do { - stat = REG_RD(ser, up->regi_ser, r_stat_din); - } while (!stat.tr_rdy); - REG_WR_INT(ser, up->regi_ser, rw_dout, s[i]); - } - - /* Restore mode. */ - if (tr_dma_en.en != old.en) - REG_WR(ser, up->regi_ser, rw_tr_dma_en, old); -} - -static int __init -cris_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 115200; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - if (co->index < 0 || co->index >= UART_NR) - co->index = 0; - port = &etraxfs_uart_ports[co->index]->port; - console_port = port; - - co->flags |= CON_CONSDEV; - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - console_baud = baud; - cris_serial_port_init(port, co->index); - uart_set_options(port, co, baud, parity, bits, flow); - - return 0; -} - -static struct console cris_console = { - .name = "ttyS", - .write = cris_console_write, - .device = uart_console_device, - .setup = cris_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &etraxfs_uart_driver, -}; -#endif /* CONFIG_SERIAL_ETRAXFS_CONSOLE */ - -static struct uart_driver etraxfs_uart_driver = { - .owner = THIS_MODULE, - .driver_name = "serial", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, - .nr = UART_NR, -#ifdef CONFIG_SERIAL_ETRAXFS_CONSOLE - .cons = &cris_console, -#endif /* CONFIG_SERIAL_ETRAXFS_CONSOLE */ -}; - -static inline int crisv32_serial_get_rts(struct uart_cris_port *up) -{ - void __iomem *regi_ser = up->regi_ser; - /* - * Return what the user has controlled rts to or - * what the pin is? (if auto_rts is used it differs during tx) - */ - reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din); - - return !(rstat.rts_n == regk_ser_active); -} - -/* - * A set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive - * 0=0V , 1=3.3V - */ -static inline void crisv32_serial_set_rts(struct uart_cris_port *up, - int set, int force) -{ - void __iomem *regi_ser = up->regi_ser; - - unsigned long flags; - reg_ser_rw_rec_ctrl rec_ctrl; - - local_irq_save(flags); - rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl); - - if (set) - rec_ctrl.rts_n = regk_ser_active; - else - rec_ctrl.rts_n = regk_ser_inactive; - REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); - local_irq_restore(flags); -} - -static inline int crisv32_serial_get_cts(struct uart_cris_port *up) -{ - void __iomem *regi_ser = up->regi_ser; - reg_ser_r_stat_din rstat = REG_RD(ser, regi_ser, r_stat_din); - - return (rstat.cts_n == regk_ser_active); -} - -/* - * Send a single character for XON/XOFF purposes. We do it in this separate - * function instead of the alternative support port.x_char, in the ...start_tx - * function, so we don't mix up this case with possibly enabling transmission - * of queued-up data (in case that's disabled after *receiving* an XOFF or - * negative CTS). This function is used for both DMA and non-DMA case; see HW - * docs specifically blessing sending characters manually when DMA for - * transmission is enabled and running. We may be asked to transmit despite - * the transmitter being disabled by a ..._stop_tx call so we need to enable - * it temporarily but restore the state afterwards. - */ -static void etraxfs_uart_send_xchar(struct uart_port *port, char ch) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - reg_ser_rw_dout dout = { .data = ch }; - reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes }; - reg_ser_r_stat_din rstat; - reg_ser_rw_tr_ctrl prev_tr_ctrl, tr_ctrl; - void __iomem *regi_ser = up->regi_ser; - unsigned long flags; - - /* - * Wait for tr_rdy in case a character is already being output. Make - * sure we have integrity between the register reads and the writes - * below, but don't busy-wait with interrupts off and the port lock - * taken. - */ - spin_lock_irqsave(&port->lock, flags); - do { - spin_unlock_irqrestore(&port->lock, flags); - spin_lock_irqsave(&port->lock, flags); - prev_tr_ctrl = tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); - rstat = REG_RD(ser, regi_ser, r_stat_din); - } while (!rstat.tr_rdy); - - /* - * Ack an interrupt if one was just issued for the previous character - * that was output. This is required for non-DMA as the interrupt is - * used as the only indicator that the transmitter is ready and it - * isn't while this x_char is being transmitted. - */ - REG_WR(ser, regi_ser, rw_ack_intr, ack_intr); - - /* Enable the transmitter in case it was disabled. */ - tr_ctrl.stop = 0; - REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); - - /* - * Finally, send the blessed character; nothing should stop it now, - * except for an xoff-detected state, which we'll handle below. - */ - REG_WR(ser, regi_ser, rw_dout, dout); - up->port.icount.tx++; - - /* There might be an xoff state to clear. */ - rstat = REG_RD(ser, up->regi_ser, r_stat_din); - - /* - * Clear any xoff state that *may* have been there to - * inhibit transmission of the character. - */ - if (rstat.xoff_detect) { - reg_ser_rw_xoff_clr xoff_clr = { .clr = 1 }; - reg_ser_rw_tr_dma_en tr_dma_en; - - REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr); - tr_dma_en = REG_RD(ser, regi_ser, rw_tr_dma_en); - - /* - * If we had an xoff state but cleared it, instead sneak in a - * disabled state for the transmitter, after the character we - * sent. Thus we keep the port disabled, just as if the xoff - * state was still in effect (or actually, as if stop_tx had - * been called, as we stop DMA too). - */ - prev_tr_ctrl.stop = 1; - - tr_dma_en.en = 0; - REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en); - } - - /* Restore "previous" enabled/disabled state of the transmitter. */ - REG_WR(ser, regi_ser, rw_tr_ctrl, prev_tr_ctrl); - - spin_unlock_irqrestore(&port->lock, flags); -} - -/* - * Do not spin_lock_irqsave or disable interrupts by other means here; it's - * already done by the caller. - */ -static void etraxfs_uart_start_tx(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - - /* we have already done below if a write is ongoing */ - if (up->write_ongoing) - return; - - /* Signal that write is ongoing */ - up->write_ongoing = 1; - - etraxfs_uart_start_tx_bottom(port); -} - -static inline void etraxfs_uart_start_tx_bottom(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - void __iomem *regi_ser = up->regi_ser; - reg_ser_rw_tr_ctrl tr_ctrl; - reg_ser_rw_intr_mask intr_mask; - - tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); - tr_ctrl.stop = regk_ser_no; - REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); - intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); - intr_mask.tr_rdy = regk_ser_yes; - REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); -} - -/* - * This function handles both the DMA and non-DMA case by ordering the - * transmitter to stop of after the current character. We don't need to wait - * for any such character to be completely transmitted; we do that where it - * matters, like in etraxfs_uart_set_termios. Don't busy-wait here; see - * Documentation/serial/driver: this function is called within - * spin_lock_irq{,save} and thus separate ones would be disastrous (when SMP). - * There's no documented need to set the txd pin to any particular value; - * break setting is controlled solely by etraxfs_uart_break_ctl. - */ -static void etraxfs_uart_stop_tx(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - void __iomem *regi_ser = up->regi_ser; - reg_ser_rw_tr_ctrl tr_ctrl; - reg_ser_rw_intr_mask intr_mask; - reg_ser_rw_tr_dma_en tr_dma_en = {0}; - reg_ser_rw_xoff_clr xoff_clr = {0}; - - /* - * For the non-DMA case, we'd get a tr_rdy interrupt that we're not - * interested in as we're not transmitting any characters. For the - * DMA case, that interrupt is already turned off, but no reason to - * waste code on conditionals here. - */ - intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); - intr_mask.tr_rdy = regk_ser_no; - REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); - - tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl); - tr_ctrl.stop = 1; - REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl); - - /* - * Always clear possible hardware xoff-detected state here, no need to - * unnecessary consider mctrl settings and when they change. We clear - * it here rather than in start_tx: both functions are called as the - * effect of XOFF processing, but start_tx is also called when upper - * levels tell the driver that there are more characters to send, so - * avoid adding code there. - */ - xoff_clr.clr = 1; - REG_WR(ser, regi_ser, rw_xoff_clr, xoff_clr); - - /* - * Disable transmitter DMA, so that if we're in XON/XOFF, we can send - * those single characters without also giving go-ahead for queued up - * DMA data. - */ - tr_dma_en.en = 0; - REG_WR(ser, regi_ser, rw_tr_dma_en, tr_dma_en); - - /* - * Make sure that write_ongoing is reset when stopping tx. - */ - up->write_ongoing = 0; -} - -static void etraxfs_uart_stop_rx(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - void __iomem *regi_ser = up->regi_ser; - reg_ser_rw_rec_ctrl rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl); - - rec_ctrl.en = regk_ser_no; - REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); -} - -static unsigned int etraxfs_uart_tx_empty(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned long flags; - unsigned int ret; - reg_ser_r_stat_din rstat = {0}; - - spin_lock_irqsave(&up->port.lock, flags); - - rstat = REG_RD(ser, up->regi_ser, r_stat_din); - ret = rstat.tr_empty ? TIOCSER_TEMT : 0; - - spin_unlock_irqrestore(&up->port.lock, flags); - return ret; -} -static unsigned int etraxfs_uart_get_mctrl(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned int ret; - - ret = 0; - if (crisv32_serial_get_rts(up)) - ret |= TIOCM_RTS; - if (crisv32_serial_get_cts(up)) - ret |= TIOCM_CTS; - return mctrl_gpio_get(up->gpios, &ret); -} - -static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - - crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0); - mctrl_gpio_set(up->gpios, mctrl); -} - -static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned long flags; - reg_ser_rw_tr_ctrl tr_ctrl; - reg_ser_rw_tr_dma_en tr_dma_en; - reg_ser_rw_intr_mask intr_mask; - - spin_lock_irqsave(&up->port.lock, flags); - tr_ctrl = REG_RD(ser, up->regi_ser, rw_tr_ctrl); - tr_dma_en = REG_RD(ser, up->regi_ser, rw_tr_dma_en); - intr_mask = REG_RD(ser, up->regi_ser, rw_intr_mask); - - if (break_state != 0) { /* Send break */ - /* - * We need to disable DMA (if used) or tr_rdy interrupts if no - * DMA. No need to make this conditional on use of DMA; - * disabling will be a no-op for the other mode. - */ - intr_mask.tr_rdy = regk_ser_no; - tr_dma_en.en = 0; - - /* - * Stop transmission and set the txd pin to 0 after the - * current character. The txd setting will take effect after - * any current transmission has completed. - */ - tr_ctrl.stop = 1; - tr_ctrl.txd = 0; - } else { - /* Re-enable the serial interrupt. */ - intr_mask.tr_rdy = regk_ser_yes; - - tr_ctrl.stop = 0; - tr_ctrl.txd = 1; - } - REG_WR(ser, up->regi_ser, rw_tr_ctrl, tr_ctrl); - REG_WR(ser, up->regi_ser, rw_tr_dma_en, tr_dma_en); - REG_WR(ser, up->regi_ser, rw_intr_mask, intr_mask); - - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static void -transmit_chars_no_dma(struct uart_cris_port *up) -{ - int max_count; - struct circ_buf *xmit = &up->port.state->xmit; - - void __iomem *regi_ser = up->regi_ser; - reg_ser_r_stat_din rstat; - reg_ser_rw_ack_intr ack_intr = { .tr_rdy = regk_ser_yes }; - - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - /* No more to send, so disable the interrupt. */ - reg_ser_rw_intr_mask intr_mask; - - intr_mask = REG_RD(ser, regi_ser, rw_intr_mask); - intr_mask.tr_rdy = 0; - intr_mask.tr_empty = 0; - REG_WR(ser, regi_ser, rw_intr_mask, intr_mask); - up->write_ongoing = 0; - return; - } - - /* If the serport is fast, we send up to max_count bytes before - exiting the loop. */ - max_count = 64; - do { - reg_ser_rw_dout dout = { .data = xmit->buf[xmit->tail] }; - - REG_WR(ser, regi_ser, rw_dout, dout); - REG_WR(ser, regi_ser, rw_ack_intr, ack_intr); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); - up->port.icount.tx++; - if (xmit->head == xmit->tail) - break; - rstat = REG_RD(ser, regi_ser, r_stat_din); - } while ((--max_count > 0) && rstat.tr_rdy); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); -} - -static void receive_chars_no_dma(struct uart_cris_port *up) -{ - reg_ser_rs_stat_din stat_din; - reg_ser_r_stat_din rstat; - struct tty_port *port; - struct uart_icount *icount; - int max_count = 16; - char flag; - reg_ser_rw_ack_intr ack_intr = { 0 }; - - rstat = REG_RD(ser, up->regi_ser, r_stat_din); - icount = &up->port.icount; - port = &up->port.state->port; - - do { - stat_din = REG_RD(ser, up->regi_ser, rs_stat_din); - - flag = TTY_NORMAL; - ack_intr.dav = 1; - REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr); - icount->rx++; - - if (stat_din.framing_err | stat_din.par_err | stat_din.orun) { - if (stat_din.data == 0x00 && - stat_din.framing_err) { - /* Most likely a break. */ - flag = TTY_BREAK; - icount->brk++; - } else if (stat_din.par_err) { - flag = TTY_PARITY; - icount->parity++; - } else if (stat_din.orun) { - flag = TTY_OVERRUN; - icount->overrun++; - } else if (stat_din.framing_err) { - flag = TTY_FRAME; - icount->frame++; - } - } - - /* - * If this becomes important, we probably *could* handle this - * gracefully by keeping track of the unhandled character. - */ - if (!tty_insert_flip_char(port, stat_din.data, flag)) - panic("%s: No tty buffer space", __func__); - rstat = REG_RD(ser, up->regi_ser, r_stat_din); - } while (rstat.dav && (max_count-- > 0)); - spin_unlock(&up->port.lock); - tty_flip_buffer_push(port); - spin_lock(&up->port.lock); -} - -static irqreturn_t -ser_interrupt(int irq, void *dev_id) -{ - struct uart_cris_port *up = (struct uart_cris_port *)dev_id; - void __iomem *regi_ser; - int handled = 0; - - spin_lock(&up->port.lock); - - regi_ser = up->regi_ser; - - if (regi_ser) { - reg_ser_r_masked_intr masked_intr; - - masked_intr = REG_RD(ser, regi_ser, r_masked_intr); - /* - * Check what interrupts are active before taking - * actions. If DMA is used the interrupt shouldn't - * be enabled. - */ - if (masked_intr.dav) { - receive_chars_no_dma(up); - handled = 1; - } - - if (masked_intr.tr_rdy) { - transmit_chars_no_dma(up); - handled = 1; - } - } - spin_unlock(&up->port.lock); - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_CONSOLE_POLL -static int etraxfs_uart_get_poll_char(struct uart_port *port) -{ - reg_ser_rs_stat_din stat; - reg_ser_rw_ack_intr ack_intr = { 0 }; - struct uart_cris_port *up = (struct uart_cris_port *)port; - - do { - stat = REG_RD(ser, up->regi_ser, rs_stat_din); - } while (!stat.dav); - - /* Ack the data_avail interrupt. */ - ack_intr.dav = 1; - REG_WR(ser, up->regi_ser, rw_ack_intr, ack_intr); - - return stat.data; -} - -static void etraxfs_uart_put_poll_char(struct uart_port *port, - unsigned char c) -{ - reg_ser_r_stat_din stat; - struct uart_cris_port *up = (struct uart_cris_port *)port; - - do { - stat = REG_RD(ser, up->regi_ser, r_stat_din); - } while (!stat.tr_rdy); - REG_WR_INT(ser, up->regi_ser, rw_dout, c); -} -#endif /* CONFIG_CONSOLE_POLL */ - -static int etraxfs_uart_startup(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned long flags; - reg_ser_rw_intr_mask ser_intr_mask = {0}; - - ser_intr_mask.dav = regk_ser_yes; - - if (request_irq(etraxfs_uart_ports[port->line]->irq, ser_interrupt, - 0, DRV_NAME, etraxfs_uart_ports[port->line])) - panic("irq ser%d", port->line); - - spin_lock_irqsave(&up->port.lock, flags); - - REG_WR(ser, up->regi_ser, rw_intr_mask, ser_intr_mask); - - etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); - - spin_unlock_irqrestore(&up->port.lock, flags); - - return 0; -} - -static void etraxfs_uart_shutdown(struct uart_port *port) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); - - etraxfs_uart_stop_tx(port); - etraxfs_uart_stop_rx(port); - - free_irq(etraxfs_uart_ports[port->line]->irq, - etraxfs_uart_ports[port->line]); - - etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); - - spin_unlock_irqrestore(&up->port.lock, flags); - -} - -static void -etraxfs_uart_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - unsigned long flags; - reg_ser_rw_xoff xoff; - reg_ser_rw_xoff_clr xoff_clr = {0}; - reg_ser_rw_tr_ctrl tx_ctrl = {0}; - reg_ser_rw_tr_dma_en tx_dma_en = {0}; - reg_ser_rw_rec_ctrl rx_ctrl = {0}; - reg_ser_rw_tr_baud_div tx_baud_div = {0}; - reg_ser_rw_rec_baud_div rx_baud_div = {0}; - int baud; - - if (old && - termios->c_cflag == old->c_cflag && - termios->c_iflag == old->c_iflag) - return; - - /* Tx: 8 bit, no/even parity, 1 stop bit, no cts. */ - tx_ctrl.base_freq = regk_ser_f29_493; - tx_ctrl.en = 0; - tx_ctrl.stop = 0; - tx_ctrl.auto_rts = regk_ser_no; - tx_ctrl.txd = 1; - tx_ctrl.auto_cts = 0; - /* Rx: 8 bit, no/even parity. */ - rx_ctrl.dma_err = regk_ser_stop; - rx_ctrl.sampling = regk_ser_majority; - rx_ctrl.timeout = 1; - - rx_ctrl.rts_n = regk_ser_inactive; - - /* Common for tx and rx: 8N1. */ - tx_ctrl.data_bits = regk_ser_bits8; - rx_ctrl.data_bits = regk_ser_bits8; - tx_ctrl.par = regk_ser_even; - rx_ctrl.par = regk_ser_even; - tx_ctrl.par_en = regk_ser_no; - rx_ctrl.par_en = regk_ser_no; - - tx_ctrl.stop_bits = regk_ser_bits1; - - /* - * Change baud-rate and write it to the hardware. - * - * baud_clock = base_freq / (divisor*8) - * divisor = base_freq / (baud_clock * 8) - * base_freq is either: - * off, ext, 29.493MHz, 32.000 MHz, 32.768 MHz or 100 MHz - * 20.493MHz is used for standard baudrates - */ - - /* - * For the console port we keep the original baudrate here. Not very - * beautiful. - */ - if ((port != console_port) || old) - baud = uart_get_baud_rate(port, termios, old, 0, - port->uartclk / 8); - else - baud = console_baud; - - tx_baud_div.div = 29493000 / (8 * baud); - /* Rx uses same as tx. */ - rx_baud_div.div = tx_baud_div.div; - rx_ctrl.base_freq = tx_ctrl.base_freq; - - if ((termios->c_cflag & CSIZE) == CS7) { - /* Set 7 bit mode. */ - tx_ctrl.data_bits = regk_ser_bits7; - rx_ctrl.data_bits = regk_ser_bits7; - } - - if (termios->c_cflag & CSTOPB) { - /* Set 2 stop bit mode. */ - tx_ctrl.stop_bits = regk_ser_bits2; - } - - if (termios->c_cflag & PARENB) { - /* Enable parity. */ - tx_ctrl.par_en = regk_ser_yes; - rx_ctrl.par_en = regk_ser_yes; - } - - if (termios->c_cflag & CMSPAR) { - if (termios->c_cflag & PARODD) { - /* Set mark parity if PARODD and CMSPAR. */ - tx_ctrl.par = regk_ser_mark; - rx_ctrl.par = regk_ser_mark; - } else { - tx_ctrl.par = regk_ser_space; - rx_ctrl.par = regk_ser_space; - } - } else { - if (termios->c_cflag & PARODD) { - /* Set odd parity. */ - tx_ctrl.par = regk_ser_odd; - rx_ctrl.par = regk_ser_odd; - } - } - - if (termios->c_cflag & CRTSCTS) { - /* Enable automatic CTS handling. */ - tx_ctrl.auto_cts = regk_ser_yes; - } - - /* Make sure the tx and rx are enabled. */ - tx_ctrl.en = regk_ser_yes; - rx_ctrl.en = regk_ser_yes; - - spin_lock_irqsave(&port->lock, flags); - - tx_dma_en.en = 0; - REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en); - - /* Actually write the control regs (if modified) to the hardware. */ - uart_update_timeout(port, termios->c_cflag, port->uartclk/8); - MODIFY_REG(up->regi_ser, rw_rec_baud_div, rx_baud_div); - MODIFY_REG(up->regi_ser, rw_rec_ctrl, rx_ctrl); - - MODIFY_REG(up->regi_ser, rw_tr_baud_div, tx_baud_div); - MODIFY_REG(up->regi_ser, rw_tr_ctrl, tx_ctrl); - - tx_dma_en.en = 0; - REG_WR(ser, up->regi_ser, rw_tr_dma_en, tx_dma_en); - - xoff = REG_RD(ser, up->regi_ser, rw_xoff); - - if (up->port.state && up->port.state->port.tty && - (up->port.state->port.tty->termios.c_iflag & IXON)) { - xoff.chr = STOP_CHAR(up->port.state->port.tty); - xoff.automatic = regk_ser_yes; - } else - xoff.automatic = regk_ser_no; - - MODIFY_REG(up->regi_ser, rw_xoff, xoff); - - /* - * Make sure we don't start in an automatically shut-off state due to - * a previous early exit. - */ - xoff_clr.clr = 1; - REG_WR(ser, up->regi_ser, rw_xoff_clr, xoff_clr); - - etraxfs_uart_set_mctrl(&up->port, up->port.mctrl); - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static const char * -etraxfs_uart_type(struct uart_port *port) -{ - return "CRISv32"; -} - -static void etraxfs_uart_release_port(struct uart_port *port) -{ -} - -static int etraxfs_uart_request_port(struct uart_port *port) -{ - return 0; -} - -static void etraxfs_uart_config_port(struct uart_port *port, int flags) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - - up->port.type = PORT_CRIS; -} - -static const struct uart_ops etraxfs_uart_pops = { - .tx_empty = etraxfs_uart_tx_empty, - .set_mctrl = etraxfs_uart_set_mctrl, - .get_mctrl = etraxfs_uart_get_mctrl, - .stop_tx = etraxfs_uart_stop_tx, - .start_tx = etraxfs_uart_start_tx, - .send_xchar = etraxfs_uart_send_xchar, - .stop_rx = etraxfs_uart_stop_rx, - .break_ctl = etraxfs_uart_break_ctl, - .startup = etraxfs_uart_startup, - .shutdown = etraxfs_uart_shutdown, - .set_termios = etraxfs_uart_set_termios, - .type = etraxfs_uart_type, - .release_port = etraxfs_uart_release_port, - .request_port = etraxfs_uart_request_port, - .config_port = etraxfs_uart_config_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = etraxfs_uart_get_poll_char, - .poll_put_char = etraxfs_uart_put_poll_char, -#endif -}; - -static void cris_serial_port_init(struct uart_port *port, int line) -{ - struct uart_cris_port *up = (struct uart_cris_port *)port; - - if (up->initialized) - return; - up->initialized = 1; - port->line = line; - spin_lock_init(&port->lock); - port->ops = &etraxfs_uart_pops; - port->irq = up->irq; - port->iobase = (unsigned long) up->regi_ser; - port->uartclk = 29493000; - - /* - * We can't fit any more than 255 here (unsigned char), though - * actually UART_XMIT_SIZE characters could be pending output. - * At time of this writing, the definition of "fifosize" is here the - * amount of characters that can be pending output after a start_tx call - * until tx_empty returns 1: see serial_core.c:uart_wait_until_sent. - * This matters for timeout calculations unfortunately, but keeping - * larger amounts at the DMA wouldn't win much so let's just play nice. - */ - port->fifosize = 255; - port->flags = UPF_BOOT_AUTOCONF; -} - -static int etraxfs_uart_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - struct uart_cris_port *up; - int dev_id; - - if (!np) - return -ENODEV; - - dev_id = of_alias_get_id(np, "serial"); - if (dev_id < 0) - dev_id = 0; - - if (dev_id >= UART_NR) - return -EINVAL; - - if (etraxfs_uart_ports[dev_id]) - return -EBUSY; - - up = devm_kzalloc(&pdev->dev, sizeof(struct uart_cris_port), - GFP_KERNEL); - if (!up) - return -ENOMEM; - - up->irq = irq_of_parse_and_map(np, 0); - up->regi_ser = of_iomap(np, 0); - up->port.dev = &pdev->dev; - - up->gpios = mctrl_gpio_init_noauto(&pdev->dev, 0); - if (IS_ERR(up->gpios)) - return PTR_ERR(up->gpios); - - cris_serial_port_init(&up->port, dev_id); - - etraxfs_uart_ports[dev_id] = up; - platform_set_drvdata(pdev, &up->port); - uart_add_one_port(&etraxfs_uart_driver, &up->port); - - return 0; -} - -static int etraxfs_uart_remove(struct platform_device *pdev) -{ - struct uart_port *port; - - port = platform_get_drvdata(pdev); - uart_remove_one_port(&etraxfs_uart_driver, port); - etraxfs_uart_ports[port->line] = NULL; - - return 0; -} - -static const struct of_device_id etraxfs_uart_dt_ids[] = { - { .compatible = "axis,etraxfs-uart" }, - { /* sentinel */ } -}; - -MODULE_DEVICE_TABLE(of, etraxfs_uart_dt_ids); - -static struct platform_driver etraxfs_uart_platform_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = of_match_ptr(etraxfs_uart_dt_ids), - }, - .probe = etraxfs_uart_probe, - .remove = etraxfs_uart_remove, -}; - -static int __init etraxfs_uart_init(void) -{ - int ret; - - ret = uart_register_driver(&etraxfs_uart_driver); - if (ret) - return ret; - - ret = platform_driver_register(&etraxfs_uart_platform_driver); - if (ret) - uart_unregister_driver(&etraxfs_uart_driver); - - return ret; -} - -static void __exit etraxfs_uart_exit(void) -{ - platform_driver_unregister(&etraxfs_uart_platform_driver); - uart_unregister_driver(&etraxfs_uart_driver); -} - -module_init(etraxfs_uart_init); -module_exit(etraxfs_uart_exit); diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c deleted file mode 100644 index 7b83a8aab495..000000000000 --- a/drivers/tty/serial/m32r_sio.c +++ /dev/null @@ -1,1053 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * m32r_sio.c - * - * Driver for M32R serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * Based on drivers/serial/8250.c. - * - * Copyright (C) 2001 Russell King. - * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org> - */ - -/* - * A note about mapbase / membase - * - * mapbase is the physical address of the IO port. Currently, we don't - * support this very well, and it may well be dropped from this driver - * in future. As such, mapbase should be NULL. - * - * membase is an 'ioremapped' cookie. This is compatible with the old - * serial.c driver, and is currently the preferred form. - */ - -#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/console.h> -#include <linux/sysrq.h> -#include <linux/serial.h> -#include <linux/delay.h> - -#include <asm/m32r.h> -#include <asm/io.h> -#include <asm/irq.h> - -#define BAUD_RATE 115200 - -#include <linux/serial_core.h> -#include "m32r_sio_reg.h" - -#define PASS_LIMIT 256 - -static const struct { - unsigned int port; - unsigned int irq; -} old_serial_port[] = { -#if defined(CONFIG_PLAT_USRV) - /* PORT IRQ FLAGS */ - { 0x3F8, PLD_IRQ_UART0 }, /* ttyS0 */ - { 0x2F8, PLD_IRQ_UART1 }, /* ttyS1 */ -#elif defined(CONFIG_SERIAL_M32R_PLDSIO) - { ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV }, /* ttyS0 */ -#else - { M32R_SIO_OFFSET, M32R_IRQ_SIO0_R }, /* ttyS0 */ -#endif -}; - -#define UART_NR ARRAY_SIZE(old_serial_port) - -struct uart_sio_port { - struct uart_port port; - struct timer_list timer; /* "no irq" timer */ - struct list_head list; /* ports on this IRQ */ - unsigned char ier; -}; - -struct irq_info { - spinlock_t lock; - struct list_head *head; -}; - -static struct irq_info irq_lists[NR_IRQS]; - -#ifdef CONFIG_SERIAL_M32R_PLDSIO - -#define __sio_in(x) inw((unsigned long)(x)) -#define __sio_out(v,x) outw((v),(unsigned long)(x)) - -static inline void sio_set_baud_rate(unsigned long baud) -{ - unsigned short sbaud; - sbaud = (boot_cpu_data.bus_clock / (baud * 4))-1; - __sio_out(sbaud, PLD_ESIO0BAUR); -} - -static void sio_reset(void) -{ - unsigned short tmp; - - tmp = __sio_in(PLD_ESIO0RXB); - tmp = __sio_in(PLD_ESIO0RXB); - tmp = __sio_in(PLD_ESIO0CR); - sio_set_baud_rate(BAUD_RATE); - __sio_out(0x0300, PLD_ESIO0CR); - __sio_out(0x0003, PLD_ESIO0CR); -} - -static void sio_init(void) -{ - unsigned short tmp; - - tmp = __sio_in(PLD_ESIO0RXB); - tmp = __sio_in(PLD_ESIO0RXB); - tmp = __sio_in(PLD_ESIO0CR); - __sio_out(0x0300, PLD_ESIO0CR); - __sio_out(0x0003, PLD_ESIO0CR); -} - -static void sio_error(int *status) -{ - printk("SIO0 error[%04x]\n", *status); - do { - sio_init(); - } while ((*status = __sio_in(PLD_ESIO0CR)) != 3); -} - -#else /* not CONFIG_SERIAL_M32R_PLDSIO */ - -#define __sio_in(x) inl(x) -#define __sio_out(v,x) outl((v),(x)) - -static inline void sio_set_baud_rate(unsigned long baud) -{ - unsigned long i, j; - - i = boot_cpu_data.bus_clock / (baud * 16); - j = (boot_cpu_data.bus_clock - (i * baud * 16)) / baud; - i -= 1; - j = (j + 1) >> 1; - - __sio_out(i, M32R_SIO0_BAUR_PORTL); - __sio_out(j, M32R_SIO0_RBAUR_PORTL); -} - -static void sio_reset(void) -{ - __sio_out(0x00000300, M32R_SIO0_CR_PORTL); /* init status */ - __sio_out(0x00000800, M32R_SIO0_MOD1_PORTL); /* 8bit */ - __sio_out(0x00000080, M32R_SIO0_MOD0_PORTL); /* 1stop non */ - sio_set_baud_rate(BAUD_RATE); - __sio_out(0x00000000, M32R_SIO0_TRCR_PORTL); - __sio_out(0x00000003, M32R_SIO0_CR_PORTL); /* RXCEN */ -} - -static void sio_init(void) -{ - unsigned int tmp; - - tmp = __sio_in(M32R_SIO0_RXB_PORTL); - tmp = __sio_in(M32R_SIO0_RXB_PORTL); - tmp = __sio_in(M32R_SIO0_STS_PORTL); - __sio_out(0x00000003, M32R_SIO0_CR_PORTL); -} - -static void sio_error(int *status) -{ - printk("SIO0 error[%04x]\n", *status); - do { - sio_init(); - } while ((*status = __sio_in(M32R_SIO0_CR_PORTL)) != 3); -} - -#endif /* CONFIG_SERIAL_M32R_PLDSIO */ - -static unsigned int sio_in(struct uart_sio_port *up, int offset) -{ - return __sio_in(up->port.iobase + offset); -} - -static void sio_out(struct uart_sio_port *up, int offset, int value) -{ - __sio_out(value, up->port.iobase + offset); -} - -static unsigned int serial_in(struct uart_sio_port *up, int offset) -{ - if (!offset) - return 0; - - return __sio_in(offset); -} - -static void serial_out(struct uart_sio_port *up, int offset, int value) -{ - if (!offset) - return; - - __sio_out(value, offset); -} - -static void m32r_sio_stop_tx(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - if (up->ier & UART_IER_THRI) { - up->ier &= ~UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -} - -static void m32r_sio_start_tx(struct uart_port *port) -{ -#ifdef CONFIG_SERIAL_M32R_PLDSIO - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - struct circ_buf *xmit = &up->port.state->xmit; - - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - if (!uart_circ_empty(xmit)) { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; - } - } - while((serial_in(up, UART_LSR) & UART_EMPTY) != UART_EMPTY); -#else - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - if (!(up->ier & UART_IER_THRI)) { - up->ier |= UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } -#endif -} - -static void m32r_sio_stop_rx(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - up->ier &= ~UART_IER_RLSI; - up->port.read_status_mask &= ~UART_LSR_DR; - serial_out(up, UART_IER, up->ier); -} - -static void m32r_sio_enable_ms(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - up->ier |= UART_IER_MSI; - serial_out(up, UART_IER, up->ier); -} - -static void receive_chars(struct uart_sio_port *up, int *status) -{ - struct tty_port *port = &up->port.state->port; - unsigned char ch; - unsigned char flag; - int max_count = 256; - - do { - ch = sio_in(up, SIORXB); - flag = TTY_NORMAL; - up->port.icount.rx++; - - if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE))) { - /* - * 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 ingored. - */ - *status &= up->port.read_status_mask; - - if (*status & UART_LSR_BI) { - pr_debug("handling break....\n"); - 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; - if ((*status & up->port.ignore_status_mask) == 0) - tty_insert_flip_char(port, ch, flag); - - if (*status & UART_LSR_OE) { - /* - * Overrun is special, since it's reported - * immediately, and doesn't affect the current - * character. - */ - tty_insert_flip_char(port, 0, TTY_OVERRUN); - } - ignore_char: - *status = serial_in(up, UART_LSR); - } while ((*status & UART_LSR_DR) && (max_count-- > 0)); - - spin_unlock(&up->port.lock); - tty_flip_buffer_push(port); - spin_lock(&up->port.lock); -} - -static void transmit_chars(struct uart_sio_port *up) -{ - struct circ_buf *xmit = &up->port.state->xmit; - int count; - - if (up->port.x_char) { -#ifndef CONFIG_SERIAL_M32R_PLDSIO /* XXX */ - serial_out(up, UART_TX, up->port.x_char); -#endif - up->port.icount.tx++; - up->port.x_char = 0; - return; - } - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - m32r_sio_stop_tx(&up->port); - return; - } - - count = up->port.fifosize; - do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; - if (uart_circ_empty(xmit)) - break; - while (!(serial_in(up, UART_LSR) & UART_LSR_THRE)); - - } while (--count > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); - - pr_debug("THRE...\n"); - - if (uart_circ_empty(xmit)) - m32r_sio_stop_tx(&up->port); -} - -/* - * This handles the interrupt from one port. - */ -static inline void m32r_sio_handle_port(struct uart_sio_port *up, - unsigned int status) -{ - pr_debug("status = %x...\n", status); - - if (status & 0x04) - receive_chars(up, &status); - if (status & 0x01) - transmit_chars(up); -} - -/* - * This is the serial driver's interrupt routine. - * - * Arjan thinks the old way was overly complex, so it got simplified. - * Alan disagrees, saying that need the complexity to handle the weird - * nature of ISA shared interrupts. (This is a special exception.) - * - * In order to handle ISA shared interrupts properly, we need to check - * that all ports have been serviced, and therefore the ISA interrupt - * line has been de-asserted. - * - * This means we need to loop through all ports. checking that they - * don't have an interrupt pending. - */ -static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) -{ - struct irq_info *i = dev_id; - struct list_head *l, *end = NULL; - int pass_counter = 0; - - pr_debug("m32r_sio_interrupt(%d)...\n", irq); - -#ifdef CONFIG_SERIAL_M32R_PLDSIO -// if (irq == PLD_IRQ_SIO0_SND) -// irq = PLD_IRQ_SIO0_RCV; -#else - if (irq == M32R_IRQ_SIO0_S) - irq = M32R_IRQ_SIO0_R; -#endif - - spin_lock(&i->lock); - - l = i->head; - do { - struct uart_sio_port *up; - unsigned int sts; - - up = list_entry(l, struct uart_sio_port, list); - - sts = sio_in(up, SIOSTS); - if (sts & 0x5) { - spin_lock(&up->port.lock); - m32r_sio_handle_port(up, sts); - spin_unlock(&up->port.lock); - - end = NULL; - } else if (end == NULL) - end = l; - - l = l->next; - - if (l == i->head && pass_counter++ > PASS_LIMIT) { - if (sts & 0xe0) - sio_error(&sts); - break; - } - } while (l != end); - - spin_unlock(&i->lock); - - pr_debug("end.\n"); - - return IRQ_HANDLED; -} - -/* - * To support ISA shared interrupts, we need to have one interrupt - * handler that ensures that the IRQ line has been deasserted - * before returning. Failing to do this will result in the IRQ - * line being stuck active, and, since ISA irqs are edge triggered, - * no more IRQs will be seen. - */ -static void serial_do_unlink(struct irq_info *i, struct uart_sio_port *up) -{ - spin_lock_irq(&i->lock); - - if (!list_empty(i->head)) { - if (i->head == &up->list) - i->head = i->head->next; - list_del(&up->list); - } else { - BUG_ON(i->head != &up->list); - i->head = NULL; - } - - spin_unlock_irq(&i->lock); -} - -static int serial_link_irq_chain(struct uart_sio_port *up) -{ - struct irq_info *i = irq_lists + up->port.irq; - int ret, irq_flags = 0; - - spin_lock_irq(&i->lock); - - if (i->head) { - list_add(&up->list, i->head); - spin_unlock_irq(&i->lock); - - ret = 0; - } else { - INIT_LIST_HEAD(&up->list); - i->head = &up->list; - spin_unlock_irq(&i->lock); - - ret = request_irq(up->port.irq, m32r_sio_interrupt, - irq_flags, "SIO0-RX", i); - ret |= request_irq(up->port.irq + 1, m32r_sio_interrupt, - irq_flags, "SIO0-TX", i); - if (ret < 0) - serial_do_unlink(i, up); - } - - return ret; -} - -static void serial_unlink_irq_chain(struct uart_sio_port *up) -{ - struct irq_info *i = irq_lists + up->port.irq; - - BUG_ON(i->head == NULL); - - if (list_empty(i->head)) { - free_irq(up->port.irq, i); - free_irq(up->port.irq + 1, i); - } - - serial_do_unlink(i, up); -} - -/* - * This function is used to handle ports that do not have an interrupt. - */ -static void m32r_sio_timeout(struct timer_list *t) -{ - struct uart_sio_port *up = from_timer(up, t, timer); - unsigned int timeout; - unsigned int sts; - - sts = sio_in(up, SIOSTS); - if (sts & 0x5) { - spin_lock(&up->port.lock); - m32r_sio_handle_port(up, sts); - spin_unlock(&up->port.lock); - } - - timeout = up->port.timeout; - timeout = timeout > 6 ? (timeout / 2 - 2) : 1; - mod_timer(&up->timer, jiffies + timeout); -} - -static unsigned int m32r_sio_tx_empty(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_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 m32r_sio_get_mctrl(struct uart_port *port) -{ - return 0; -} - -static void m32r_sio_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - -} - -static void m32r_sio_break_ctl(struct uart_port *port, int break_state) -{ - -} - -static int m32r_sio_startup(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - int retval; - - sio_init(); - - /* - * If the "interrupt" for this port doesn't correspond with any - * hardware interrupt, we use a timer-based system. The original - * driver used to do this with IRQ0. - */ - if (!up->port.irq) { - unsigned int timeout = up->port.timeout; - - timeout = timeout > 6 ? (timeout / 2 - 2) : 1; - - mod_timer(&up->timer, jiffies + timeout); - } else { - retval = serial_link_irq_chain(up); - if (retval) - return retval; - } - - /* - * 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. - * - M32R_SIO: 0x0c - * - M32R_PLDSIO: 0x04 - */ - up->ier = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - sio_out(up, SIOTRCR, up->ier); - - /* - * And clear the interrupt registers again for luck. - */ - sio_reset(); - - return 0; -} - -static void m32r_sio_shutdown(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - /* - * Disable interrupts from this port - */ - up->ier = 0; - sio_out(up, SIOTRCR, 0); - - /* - * Disable break condition and FIFOs - */ - - sio_init(); - - if (!up->port.irq) - del_timer_sync(&up->timer); - else - serial_unlink_irq_chain(up); -} - -static unsigned int m32r_sio_get_divisor(struct uart_port *port, - unsigned int baud) -{ - return uart_get_divisor(port, baud); -} - -static void m32r_sio_set_termios(struct uart_port *port, - struct ktermios *termios, struct ktermios *old) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - unsigned char cval = 0; - unsigned long flags; - unsigned int baud, quot; - - 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; - } - - 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; -#ifdef CMSPAR - if (termios->c_cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - /* - * Ask the core to calculate the divisor for us. - */ -#ifdef CONFIG_SERIAL_M32R_PLDSIO - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/4); -#else - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); -#endif - quot = m32r_sio_get_divisor(port, baud); - - /* - * Ok, we're now changing the port state. Do it with - * interrupts disabled. - */ - spin_lock_irqsave(&up->port.lock, flags); - - sio_set_baud_rate(baud); - - /* - * 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 & (IGNBRK | BRKINT | PARMRK)) - up->port.read_status_mask |= UART_LSR_BI; - - /* - * Characteres 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 - */ - 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); - - spin_unlock_irqrestore(&up->port.lock, flags); -} - -/* - * Resource handling. This is complicated by the fact that resources - * depend on the port type. Maybe we should be claiming the standard - * 8250 ports, and then trying to get other resources as necessary? - */ -static int -m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res) -{ - unsigned int size = 8 << up->port.regshift; -#ifndef CONFIG_SERIAL_M32R_PLDSIO - unsigned long start; -#endif - int ret = 0; - - switch (up->port.iotype) { - case UPIO_MEM: - if (up->port.mapbase) { -#ifdef CONFIG_SERIAL_M32R_PLDSIO - *res = request_mem_region(up->port.mapbase, size, "serial"); -#else - start = up->port.mapbase; - *res = request_mem_region(start, size, "serial"); -#endif - if (!*res) - ret = -EBUSY; - } - break; - - case UPIO_PORT: - *res = request_region(up->port.iobase, size, "serial"); - if (!*res) - ret = -EBUSY; - break; - } - return ret; -} - -static void m32r_sio_release_port(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - unsigned long start, offset = 0, size = 0; - - size <<= up->port.regshift; - - switch (up->port.iotype) { - case UPIO_MEM: - if (up->port.mapbase) { - /* - * Unmap the area. - */ - iounmap(up->port.membase); - up->port.membase = NULL; - - start = up->port.mapbase; - - if (size) - release_mem_region(start + offset, size); - release_mem_region(start, 8 << up->port.regshift); - } - break; - - case UPIO_PORT: - start = up->port.iobase; - - if (size) - release_region(start + offset, size); - release_region(start + offset, 8 << up->port.regshift); - break; - - default: - break; - } -} - -static int m32r_sio_request_port(struct uart_port *port) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - struct resource *res = NULL; - int ret = 0; - - ret = m32r_sio_request_std_resource(up, &res); - - /* - * If we have a mapbase, then request that as well. - */ - if (ret == 0 && up->port.flags & UPF_IOREMAP) { - int size = resource_size(res); - - up->port.membase = ioremap(up->port.mapbase, size); - if (!up->port.membase) - ret = -ENOMEM; - } - - if (ret < 0) { - if (res) - release_resource(res); - } - - return ret; -} - -static void m32r_sio_config_port(struct uart_port *port, int unused) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - unsigned long flags; - - spin_lock_irqsave(&up->port.lock, flags); - - up->port.fifosize = 1; - - spin_unlock_irqrestore(&up->port.lock, flags); -} - -static int -m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser) -{ - if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600) - return -EINVAL; - return 0; -} - -static const struct uart_ops m32r_sio_pops = { - .tx_empty = m32r_sio_tx_empty, - .set_mctrl = m32r_sio_set_mctrl, - .get_mctrl = m32r_sio_get_mctrl, - .stop_tx = m32r_sio_stop_tx, - .start_tx = m32r_sio_start_tx, - .stop_rx = m32r_sio_stop_rx, - .enable_ms = m32r_sio_enable_ms, - .break_ctl = m32r_sio_break_ctl, - .startup = m32r_sio_startup, - .shutdown = m32r_sio_shutdown, - .set_termios = m32r_sio_set_termios, - .release_port = m32r_sio_release_port, - .request_port = m32r_sio_request_port, - .config_port = m32r_sio_config_port, - .verify_port = m32r_sio_verify_port, -}; - -static struct uart_sio_port m32r_sio_ports[UART_NR]; - -static void __init m32r_sio_init_ports(void) -{ - struct uart_sio_port *up; - static int first = 1; - int i; - - if (!first) - return; - first = 0; - - for (i = 0, up = m32r_sio_ports; i < UART_NR; i++, up++) { - up->port.iobase = old_serial_port[i].port; - up->port.irq = irq_canonicalize(old_serial_port[i].irq); - up->port.uartclk = BAUD_RATE * 16; - up->port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; - up->port.membase = 0; - up->port.iotype = 0; - up->port.regshift = 0; - up->port.ops = &m32r_sio_pops; - } -} - -static void __init m32r_sio_register_ports(struct uart_driver *drv) -{ - int i; - - m32r_sio_init_ports(); - - for (i = 0; i < UART_NR; i++) { - struct uart_sio_port *up = &m32r_sio_ports[i]; - - up->port.line = i; - up->port.ops = &m32r_sio_pops; - timer_setup(&up->timer, m32r_sio_timeout, 0); - - uart_add_one_port(drv, &up->port); - } -} - -#ifdef CONFIG_SERIAL_M32R_SIO_CONSOLE - -/* - * Wait for transmitter & holding register to empty - */ -static void wait_for_xmitr(struct uart_sio_port *up) -{ - unsigned int status, tmout = 10000; - - /* Wait up to 10ms for the character(s) to be sent. */ - do { - status = sio_in(up, SIOSTS); - - if (--tmout == 0) - break; - udelay(1); - } while ((status & UART_EMPTY) != UART_EMPTY); - - /* Wait up to 1s for flow control if necessary */ - if (up->port.flags & UPF_CONS_FLOW) { - tmout = 1000000; - while (--tmout) - udelay(1); - } -} - -static void m32r_sio_console_putchar(struct uart_port *port, int ch) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - wait_for_xmitr(up); - sio_out(up, SIOTXB, 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 m32r_sio_console_write(struct console *co, const char *s, - unsigned int count) -{ - struct uart_sio_port *up = &m32r_sio_ports[co->index]; - unsigned int ier; - - /* - * First save the UER then disable the interrupts - */ - ier = sio_in(up, SIOTRCR); - sio_out(up, SIOTRCR, 0); - - uart_console_write(&up->port, s, count, m32r_sio_console_putchar); - - /* - * Finally, wait for transmitter to become empty - * and restore the IER - */ - wait_for_xmitr(up); - sio_out(up, SIOTRCR, ier); -} - -static int __init m32r_sio_console_setup(struct console *co, char *options) -{ - struct uart_port *port; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int flow = 'n'; - - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index >= UART_NR) - co->index = 0; - port = &m32r_sio_ports[co->index].port; - - /* - * Temporary fix. - */ - spin_lock_init(&port->lock); - - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, co, baud, parity, bits, flow); -} - -static struct uart_driver m32r_sio_reg; -static struct console m32r_sio_console = { - .name = "ttyS", - .write = m32r_sio_console_write, - .device = uart_console_device, - .setup = m32r_sio_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &m32r_sio_reg, -}; - -static int __init m32r_sio_console_init(void) -{ - sio_reset(); - sio_init(); - m32r_sio_init_ports(); - register_console(&m32r_sio_console); - return 0; -} -console_initcall(m32r_sio_console_init); - -#define M32R_SIO_CONSOLE &m32r_sio_console -#else -#define M32R_SIO_CONSOLE NULL -#endif - -static struct uart_driver m32r_sio_reg = { - .owner = THIS_MODULE, - .driver_name = "sio", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = 64, - .nr = UART_NR, - .cons = M32R_SIO_CONSOLE, -}; - -static int __init m32r_sio_init(void) -{ - int ret, i; - - printk(KERN_INFO "Serial: M32R SIO driver\n"); - - for (i = 0; i < nr_irqs; i++) - spin_lock_init(&irq_lists[i].lock); - - ret = uart_register_driver(&m32r_sio_reg); - if (ret >= 0) - m32r_sio_register_ports(&m32r_sio_reg); - - return ret; -} -device_initcall(m32r_sio_init); diff --git a/drivers/tty/serial/m32r_sio_reg.h b/drivers/tty/serial/m32r_sio_reg.h deleted file mode 100644 index 6eed48828f94..000000000000 --- a/drivers/tty/serial/m32r_sio_reg.h +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: GPL-1.0+ -/* - * m32r_sio_reg.h - * - * Copyright (C) 1992, 1994 by Theodore Ts'o. - * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org> - * - * These are the UART port assignments, expressed as offsets from the base - * register. These assignments should hold for any serial port based on - * a 8250, 16450, or 16550(A). - */ - -#ifndef _M32R_SIO_REG_H -#define _M32R_SIO_REG_H - - -#ifdef CONFIG_SERIAL_M32R_PLDSIO - -#define SIOCR 0x000 -#define SIOMOD0 0x002 -#define SIOMOD1 0x004 -#define SIOSTS 0x006 -#define SIOTRCR 0x008 -#define SIOBAUR 0x00a -// #define SIORBAUR 0x018 -#define SIOTXB 0x00c -#define SIORXB 0x00e - -#define UART_RX ((unsigned long) PLD_ESIO0RXB) - /* In: Receive buffer (DLAB=0) */ -#define UART_TX ((unsigned long) PLD_ESIO0TXB) - /* Out: Transmit buffer (DLAB=0) */ -#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ -#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx - * In: Fifo count - * Out: Fifo custom trigger levels - * XR16C85x only */ - -#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */ -#define UART_IER ((unsigned long) PLD_ESIO0INTCR) - /* Out: Interrupt Enable Register */ -#define UART_FCTR 0 /* (LCR=BF) Feature Control Register - * XR16C85x only */ - -#define UART_IIR 0 /* In: Interrupt ID Register */ -#define UART_FCR 0 /* Out: FIFO Control Register */ -#define UART_EFR 0 /* I/O: Extended Features Register */ - /* (DLAB=1, 16C660 only) */ - -#define UART_LCR 0 /* Out: Line Control Register */ -#define UART_MCR 0 /* Out: Modem Control Register */ -#define UART_LSR ((unsigned long) PLD_ESIO0STS) - /* In: Line Status Register */ -#define UART_MSR 0 /* In: Modem Status Register */ -#define UART_SCR 0 /* I/O: Scratch Register */ -#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register - * FCTR bit 6 selects SCR or EMSR - * XR16c85x only */ - -#else /* not CONFIG_SERIAL_M32R_PLDSIO */ - -#define SIOCR 0x000 -#define SIOMOD0 0x004 -#define SIOMOD1 0x008 -#define SIOSTS 0x00c -#define SIOTRCR 0x010 -#define SIOBAUR 0x014 -#define SIORBAUR 0x018 -#define SIOTXB 0x01c -#define SIORXB 0x020 - -#define UART_RX M32R_SIO0_RXB_PORTL /* In: Receive buffer (DLAB=0) */ -#define UART_TX M32R_SIO0_TXB_PORTL /* Out: Transmit buffer (DLAB=0) */ -#define UART_DLL 0 /* Out: Divisor Latch Low (DLAB=1) */ -#define UART_TRG 0 /* (LCR=BF) FCTR bit 7 selects Rx or Tx - * In: Fifo count - * Out: Fifo custom trigger levels - * XR16C85x only */ - -#define UART_DLM 0 /* Out: Divisor Latch High (DLAB=1) */ -#define UART_IER M32R_SIO0_TRCR_PORTL /* Out: Interrupt Enable Register */ -#define UART_FCTR 0 /* (LCR=BF) Feature Control Register - * XR16C85x only */ - -#define UART_IIR 0 /* In: Interrupt ID Register */ -#define UART_FCR 0 /* Out: FIFO Control Register */ -#define UART_EFR 0 /* I/O: Extended Features Register */ - /* (DLAB=1, 16C660 only) */ - -#define UART_LCR 0 /* Out: Line Control Register */ -#define UART_MCR 0 /* Out: Modem Control Register */ -#define UART_LSR M32R_SIO0_STS_PORTL /* In: Line Status Register */ -#define UART_MSR 0 /* In: Modem Status Register */ -#define UART_SCR 0 /* I/O: Scratch Register */ -#define UART_EMSR 0 /* (LCR=BF) Extended Mode Select Register - * FCTR bit 6 selects SCR or EMSR - * XR16c85x only */ - -#endif /* CONFIG_SERIAL_M32R_PLDSIO */ - -#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - -/* - * These are the definitions for the Line Control Register - * - * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting - * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. - */ -#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ -#define UART_LCR_SBC 0x40 /* Set break control */ -#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ -#define UART_LCR_EPAR 0x10 /* Even parity select */ -#define UART_LCR_PARITY 0x08 /* Parity Enable */ -#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ -#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ -#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ -#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ -#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ - -/* - * These are the definitions for the Line Status Register - */ -#define UART_LSR_TEMT 0x02 /* Transmitter empty */ -#define UART_LSR_THRE 0x01 /* Transmit-hold-register empty */ -#define UART_LSR_BI 0x00 /* Break interrupt indicator */ -#define UART_LSR_FE 0x80 /* Frame error indicator */ -#define UART_LSR_PE 0x40 /* Parity error indicator */ -#define UART_LSR_OE 0x20 /* Overrun error indicator */ -#define UART_LSR_DR 0x04 /* Receiver data ready */ - -/* - * These are the definitions for the Interrupt Identification Register - */ -#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ -#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ - -#define UART_IIR_MSI 0x00 /* Modem status interrupt */ -#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ -#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ -#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ - -/* - * These are the definitions for the Interrupt Enable Register - */ -#define UART_IER_MSI 0x00 /* Enable Modem status interrupt */ -#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */ -#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */ -#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */ - -#endif /* _M32R_SIO_REG_H */ diff --git a/drivers/tty/serial/tilegx.c b/drivers/tty/serial/tilegx.c deleted file mode 100644 index f0a3ae57f881..000000000000 --- a/drivers/tty/serial/tilegx.c +++ /dev/null @@ -1,689 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2013 Tilera Corporation. All Rights Reserved. - * - * TILEGx UART driver. - */ - -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/module.h> -#include <linux/serial_core.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> - -#include <gxio/common.h> -#include <gxio/iorpc_globals.h> -#include <gxio/iorpc_uart.h> -#include <gxio/kiorpc.h> - -#include <hv/drv_uart_intf.h> - -/* - * Use device name ttyS, major 4, minor 64-65. - * This is the usual serial port name, 8250 conventional range. - */ -#define TILEGX_UART_MAJOR TTY_MAJOR -#define TILEGX_UART_MINOR 64 -#define TILEGX_UART_NAME "ttyS" -#define DRIVER_NAME_STRING "TILEGx_Serial" -#define TILEGX_UART_REF_CLK 125000000; /* REF_CLK is always 125 MHz. */ - -struct tile_uart_port { - /* UART port. */ - struct uart_port uart; - - /* GXIO device context. */ - gxio_uart_context_t context; - - /* UART access mutex. */ - struct mutex mutex; - - /* CPU receiving interrupts. */ - int irq_cpu; -}; - -static struct tile_uart_port tile_uart_ports[TILEGX_UART_NR]; -static struct uart_driver tilegx_uart_driver; - - -/* - * Read UART rx fifo, and insert the chars into tty buffer. - */ -static void receive_chars(struct tile_uart_port *tile_uart, - struct tty_struct *tty) -{ - int i; - char c; - UART_FIFO_COUNT_t count; - gxio_uart_context_t *context = &tile_uart->context; - struct tty_port *port = tty->port; - - count.word = gxio_uart_read(context, UART_FIFO_COUNT); - for (i = 0; i < count.rfifo_count; i++) { - c = (char)gxio_uart_read(context, UART_RECEIVE_DATA); - tty_insert_flip_char(port, c, TTY_NORMAL); - } -} - - -/* - * Drain the Rx FIFO, called by interrupt handler. - */ -static void handle_receive(struct tile_uart_port *tile_uart) -{ - struct tty_port *port = &tile_uart->uart.state->port; - struct tty_struct *tty = tty_port_tty_get(port); - gxio_uart_context_t *context = &tile_uart->context; - - if (!tty) - return; - - /* First read UART rx fifo. */ - receive_chars(tile_uart, tty); - - /* Reset RFIFO_WE interrupt. */ - gxio_uart_write(context, UART_INTERRUPT_STATUS, - UART_INTERRUPT_MASK__RFIFO_WE_MASK); - - /* Final read, if any chars comes between the first read and - * the interrupt reset. - */ - receive_chars(tile_uart, tty); - - spin_unlock(&tile_uart->uart.lock); - tty_flip_buffer_push(port); - spin_lock(&tile_uart->uart.lock); - tty_kref_put(tty); -} - - -/* - * Push one char to UART Write FIFO. - * Return 0 on success, -1 if write filo is full. - */ -static int tilegx_putchar(gxio_uart_context_t *context, char c) -{ - UART_FLAG_t flag; - flag.word = gxio_uart_read(context, UART_FLAG); - if (flag.wfifo_full) - return -1; - - gxio_uart_write(context, UART_TRANSMIT_DATA, (unsigned long)c); - return 0; -} - - -/* - * Send chars to UART Write FIFO; called by interrupt handler. - */ -static void handle_transmit(struct tile_uart_port *tile_uart) -{ - unsigned char ch; - struct uart_port *port; - struct circ_buf *xmit; - gxio_uart_context_t *context = &tile_uart->context; - - /* First reset WFIFO_RE interrupt. */ - gxio_uart_write(context, UART_INTERRUPT_STATUS, - UART_INTERRUPT_MASK__WFIFO_RE_MASK); - - port = &tile_uart->uart; - xmit = &port->state->xmit; - if (port->x_char) { - if (tilegx_putchar(context, port->x_char)) - return; - port->x_char = 0; - port->icount.tx++; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) - return; - - while (!uart_circ_empty(xmit)) { - ch = xmit->buf[xmit->tail]; - if (tilegx_putchar(context, ch)) - break; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } - - /* Reset WFIFO_RE interrupt. */ - gxio_uart_write(context, UART_INTERRUPT_STATUS, - UART_INTERRUPT_MASK__WFIFO_RE_MASK); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); -} - - -/* - * UART Interrupt handler. - */ -static irqreturn_t tilegx_interrupt(int irq, void *dev_id) -{ - unsigned long flags; - UART_INTERRUPT_STATUS_t intr_stat; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - struct uart_port *port = dev_id; - irqreturn_t ret = IRQ_NONE; - - spin_lock_irqsave(&port->lock, flags); - - tile_uart = container_of(port, struct tile_uart_port, uart); - context = &tile_uart->context; - intr_stat.word = gxio_uart_read(context, UART_INTERRUPT_STATUS); - - if (intr_stat.rfifo_we) { - handle_receive(tile_uart); - ret = IRQ_HANDLED; - } - if (intr_stat.wfifo_re) { - handle_transmit(tile_uart); - ret = IRQ_HANDLED; - } - - spin_unlock_irqrestore(&port->lock, flags); - return ret; -} - - -/* - * Return TIOCSER_TEMT when transmitter FIFO is empty. - */ -static u_int tilegx_tx_empty(struct uart_port *port) -{ - int ret; - UART_FLAG_t flag; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (!mutex_trylock(&tile_uart->mutex)) - return 0; - context = &tile_uart->context; - - flag.word = gxio_uart_read(context, UART_FLAG); - ret = (flag.wfifo_empty) ? TIOCSER_TEMT : 0; - mutex_unlock(&tile_uart->mutex); - - return ret; -} - - -/* - * Set state of the modem control output lines. - */ -static void tilegx_set_mctrl(struct uart_port *port, u_int mctrl) -{ - /* N/A */ -} - - -/* - * Get state of the modem control input lines. - */ -static u_int tilegx_get_mctrl(struct uart_port *port) -{ - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; -} - - -/* - * Stop transmitting. - */ -static void tilegx_stop_tx(struct uart_port *port) -{ - /* N/A */ -} - - -/* - * Start transmitting. - */ -static void tilegx_start_tx(struct uart_port *port) -{ - unsigned char ch; - struct circ_buf *xmit; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (!mutex_trylock(&tile_uart->mutex)) - return; - context = &tile_uart->context; - xmit = &port->state->xmit; - if (port->x_char) { - if (tilegx_putchar(context, port->x_char)) - return; - port->x_char = 0; - port->icount.tx++; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - mutex_unlock(&tile_uart->mutex); - return; - } - - while (!uart_circ_empty(xmit)) { - ch = xmit->buf[xmit->tail]; - if (tilegx_putchar(context, ch)) - break; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - } - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - mutex_unlock(&tile_uart->mutex); -} - - -/* - * Stop receiving - port is in process of being closed. - */ -static void tilegx_stop_rx(struct uart_port *port) -{ - int err; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - int cpu; - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (!mutex_trylock(&tile_uart->mutex)) - return; - - context = &tile_uart->context; - cpu = tile_uart->irq_cpu; - err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), - KERNEL_PL, -1); - mutex_unlock(&tile_uart->mutex); -} - -/* - * Control the transmission of a break signal. - */ -static void tilegx_break_ctl(struct uart_port *port, int break_state) -{ - /* N/A */ -} - - -/* - * Perform initialization and enable port for reception. - */ -static int tilegx_startup(struct uart_port *port) -{ - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - int ret = 0; - int cpu = raw_smp_processor_id(); /* pick an arbitrary cpu */ - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (mutex_lock_interruptible(&tile_uart->mutex)) - return -EBUSY; - context = &tile_uart->context; - - /* Now open the hypervisor device if we haven't already. */ - if (context->fd < 0) { - UART_INTERRUPT_MASK_t intr_mask; - - /* Initialize UART device. */ - ret = gxio_uart_init(context, port->line); - if (ret) { - ret = -ENXIO; - goto err; - } - - /* Create our IRQs. */ - port->irq = irq_alloc_hwirq(-1); - if (!port->irq) - goto err_uart_dest; - tile_irq_activate(port->irq, TILE_IRQ_PERCPU); - - /* Register our IRQs. */ - ret = request_irq(port->irq, tilegx_interrupt, 0, - tilegx_uart_driver.driver_name, port); - if (ret) - goto err_dest_irq; - - /* Request that the hardware start sending us interrupts. */ - tile_uart->irq_cpu = cpu; - ret = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), - KERNEL_PL, port->irq); - if (ret) - goto err_free_irq; - - /* Enable UART Tx/Rx Interrupt. */ - intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); - intr_mask.wfifo_re = 0; - intr_mask.rfifo_we = 0; - gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); - - /* Reset the Tx/Rx interrupt in case it's set. */ - gxio_uart_write(context, UART_INTERRUPT_STATUS, - UART_INTERRUPT_MASK__WFIFO_RE_MASK | - UART_INTERRUPT_MASK__RFIFO_WE_MASK); - } - - mutex_unlock(&tile_uart->mutex); - return ret; - -err_free_irq: - free_irq(port->irq, port); -err_dest_irq: - irq_free_hwirq(port->irq); -err_uart_dest: - gxio_uart_destroy(context); - ret = -ENXIO; -err: - mutex_unlock(&tile_uart->mutex); - return ret; -} - - -/* - * Release kernel resources if it is the last close, disable the port, - * free IRQ and close the port. - */ -static void tilegx_shutdown(struct uart_port *port) -{ - int err; - UART_INTERRUPT_MASK_t intr_mask; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - int cpu; - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (mutex_lock_interruptible(&tile_uart->mutex)) - return; - context = &tile_uart->context; - - /* Disable UART Tx/Rx Interrupt. */ - intr_mask.word = gxio_uart_read(context, UART_INTERRUPT_MASK); - intr_mask.wfifo_re = 1; - intr_mask.rfifo_we = 1; - gxio_uart_write(context, UART_INTERRUPT_MASK, intr_mask.word); - - /* Request that the hardware stop sending us interrupts. */ - cpu = tile_uart->irq_cpu; - err = gxio_uart_cfg_interrupt(context, cpu_x(cpu), cpu_y(cpu), - KERNEL_PL, -1); - - if (port->irq > 0) { - free_irq(port->irq, port); - irq_free_hwirq(port->irq); - port->irq = 0; - } - - gxio_uart_destroy(context); - - mutex_unlock(&tile_uart->mutex); -} - - -/* - * Flush the buffer. - */ -static void tilegx_flush_buffer(struct uart_port *port) -{ - /* N/A */ -} - - -/* - * Change the port parameters. - */ -static void tilegx_set_termios(struct uart_port *port, - struct ktermios *termios, struct ktermios *old) -{ - int err; - UART_DIVISOR_t divisor; - UART_TYPE_t type; - unsigned int baud; - struct tile_uart_port *tile_uart; - gxio_uart_context_t *context; - - tile_uart = container_of(port, struct tile_uart_port, uart); - if (!mutex_trylock(&tile_uart->mutex)) - return; - context = &tile_uart->context; - - /* Open the hypervisor device if we haven't already. */ - if (context->fd < 0) { - err = gxio_uart_init(context, port->line); - if (err) { - mutex_unlock(&tile_uart->mutex); - return; - } - } - - divisor.word = gxio_uart_read(context, UART_DIVISOR); - type.word = gxio_uart_read(context, UART_TYPE); - - /* Divisor. */ - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); - divisor.divisor = uart_get_divisor(port, baud); - - /* Byte size. */ - if ((termios->c_cflag & CSIZE) == CS7) - type.dbits = UART_TYPE__DBITS_VAL_SEVEN_DBITS; - else - type.dbits = UART_TYPE__DBITS_VAL_EIGHT_DBITS; - - /* Parity. */ - if (termios->c_cflag & PARENB) { - /* Mark or Space parity. */ - if (termios->c_cflag & CMSPAR) - if (termios->c_cflag & PARODD) - type.ptype = UART_TYPE__PTYPE_VAL_MARK; - else - type.ptype = UART_TYPE__PTYPE_VAL_SPACE; - else if (termios->c_cflag & PARODD) - type.ptype = UART_TYPE__PTYPE_VAL_ODD; - else - type.ptype = UART_TYPE__PTYPE_VAL_EVEN; - } else - type.ptype = UART_TYPE__PTYPE_VAL_NONE; - - /* Stop bits. */ - if (termios->c_cflag & CSTOPB) - type.sbits = UART_TYPE__SBITS_VAL_TWO_SBITS; - else - type.sbits = UART_TYPE__SBITS_VAL_ONE_SBITS; - - /* Set the uart paramters. */ - gxio_uart_write(context, UART_DIVISOR, divisor.word); - gxio_uart_write(context, UART_TYPE, type.word); - - mutex_unlock(&tile_uart->mutex); -} - - -/* - * Return string describing the specified port. - */ -static const char *tilegx_type(struct uart_port *port) -{ - return port->type == PORT_TILEGX ? DRIVER_NAME_STRING : NULL; -} - - -/* - * Release the resources being used by 'port'. - */ -static void tilegx_release_port(struct uart_port *port) -{ - /* Nothing to release. */ -} - - -/* - * Request the resources being used by 'port'. - */ -static int tilegx_request_port(struct uart_port *port) -{ - /* Always present. */ - return 0; -} - - -/* - * Configure/autoconfigure the port. - */ -static void tilegx_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - port->type = PORT_TILEGX; -} - - -/* - * Verify the new serial_struct (for TIOCSSERIAL). - */ -static int tilegx_verify_port(struct uart_port *port, - struct serial_struct *ser) -{ - if ((ser->type != PORT_UNKNOWN) && (ser->type != PORT_TILEGX)) - return -EINVAL; - - return 0; -} - -#ifdef CONFIG_CONSOLE_POLL - -/* - * Console polling routines for writing and reading from the uart while - * in an interrupt or debug context. - */ - -static int tilegx_poll_get_char(struct uart_port *port) -{ - UART_FIFO_COUNT_t count; - gxio_uart_context_t *context; - struct tile_uart_port *tile_uart; - - tile_uart = container_of(port, struct tile_uart_port, uart); - context = &tile_uart->context; - count.word = gxio_uart_read(context, UART_FIFO_COUNT); - if (count.rfifo_count == 0) - return NO_POLL_CHAR; - return (char)gxio_uart_read(context, UART_RECEIVE_DATA); -} - -static void tilegx_poll_put_char(struct uart_port *port, unsigned char c) -{ - gxio_uart_context_t *context; - struct tile_uart_port *tile_uart; - - tile_uart = container_of(port, struct tile_uart_port, uart); - context = &tile_uart->context; - gxio_uart_write(context, UART_TRANSMIT_DATA, (unsigned long)c); -} - -#endif /* CONFIG_CONSOLE_POLL */ - - -static const struct uart_ops tilegx_ops = { - .tx_empty = tilegx_tx_empty, - .set_mctrl = tilegx_set_mctrl, - .get_mctrl = tilegx_get_mctrl, - .stop_tx = tilegx_stop_tx, - .start_tx = tilegx_start_tx, - .stop_rx = tilegx_stop_rx, - .break_ctl = tilegx_break_ctl, - .startup = tilegx_startup, - .shutdown = tilegx_shutdown, - .flush_buffer = tilegx_flush_buffer, - .set_termios = tilegx_set_termios, - .type = tilegx_type, - .release_port = tilegx_release_port, - .request_port = tilegx_request_port, - .config_port = tilegx_config_port, - .verify_port = tilegx_verify_port, -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = tilegx_poll_get_char, - .poll_put_char = tilegx_poll_put_char, -#endif -}; - - -static void tilegx_init_ports(void) -{ - int i; - struct uart_port *port; - - for (i = 0; i < TILEGX_UART_NR; i++) { - port = &tile_uart_ports[i].uart; - port->ops = &tilegx_ops; - port->line = i; - port->type = PORT_TILEGX; - port->uartclk = TILEGX_UART_REF_CLK; - port->flags = UPF_BOOT_AUTOCONF; - - tile_uart_ports[i].context.fd = -1; - mutex_init(&tile_uart_ports[i].mutex); - } -} - - -static struct uart_driver tilegx_uart_driver = { - .owner = THIS_MODULE, - .driver_name = DRIVER_NAME_STRING, - .dev_name = TILEGX_UART_NAME, - .major = TILEGX_UART_MAJOR, - .minor = TILEGX_UART_MINOR, - .nr = TILEGX_UART_NR, -}; - - -static int __init tilegx_init(void) -{ - int i; - int ret; - struct tty_driver *tty_drv; - - ret = uart_register_driver(&tilegx_uart_driver); - if (ret) - return ret; - tty_drv = tilegx_uart_driver.tty_driver; - tty_drv->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; - tty_drv->init_termios.c_ispeed = 115200; - tty_drv->init_termios.c_ospeed = 115200; - - tilegx_init_ports(); - - for (i = 0; i < TILEGX_UART_NR; i++) { - struct uart_port *port = &tile_uart_ports[i].uart; - ret = uart_add_one_port(&tilegx_uart_driver, port); - } - - return 0; -} - - -static void __exit tilegx_exit(void) -{ - int i; - struct uart_port *port; - - for (i = 0; i < TILEGX_UART_NR; i++) { - port = &tile_uart_ports[i].uart; - uart_remove_one_port(&tilegx_uart_driver, port); - } - - uart_unregister_driver(&tilegx_uart_driver); -} - - -module_init(tilegx_init); -module_exit(tilegx_exit); - -MODULE_AUTHOR("Tilera Corporation"); -MODULE_DESCRIPTION("TILEGx serial port driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/function/f_uac1_legacy.c b/drivers/usb/gadget/function/f_uac1_legacy.c index 04f4b2862256..24c086bcdeaa 100644 --- a/drivers/usb/gadget/function/f_uac1_legacy.c +++ b/drivers/usb/gadget/function/f_uac1_legacy.c @@ -4,8 +4,6 @@ * * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> * Copyright (C) 2008 Analog Devices, Inc - * - * Enter bugs at http://blackfin.uclinux.org/ */ #include <linux/slab.h> diff --git a/drivers/usb/gadget/function/u_uac1_legacy.c b/drivers/usb/gadget/function/u_uac1_legacy.c index cbc868d117af..5393e5c37a4b 100644 --- a/drivers/usb/gadget/function/u_uac1_legacy.c +++ b/drivers/usb/gadget/function/u_uac1_legacy.c @@ -4,8 +4,6 @@ * * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> * Copyright (C) 2008 Analog Devices, Inc - * - * Enter bugs at http://blackfin.uclinux.org/ */ #include <linux/kernel.h> diff --git a/drivers/usb/gadget/function/u_uac1_legacy.h b/drivers/usb/gadget/function/u_uac1_legacy.h index dd69e408a3d9..5c1bdf46fe32 100644 --- a/drivers/usb/gadget/function/u_uac1_legacy.h +++ b/drivers/usb/gadget/function/u_uac1_legacy.h @@ -4,8 +4,6 @@ * * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> * Copyright (C) 2008 Analog Devices, Inc - * - * Enter bugs at http://blackfin.uclinux.org/ */ #ifndef __U_UAC1_LEGACY_H diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c index 7b11dce98b94..dd81fd538cb8 100644 --- a/drivers/usb/gadget/legacy/audio.c +++ b/drivers/usb/gadget/legacy/audio.c @@ -4,8 +4,6 @@ * * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org> * Copyright (C) 2008 Analog Devices, Inc - * - * Enter bugs at http://blackfin.uclinux.org/ */ /* #define VERBOSE_DEBUG */ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4fcfb3084b36..b85822f0c874 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -360,6 +360,7 @@ config USB_ISP116X_HCD config USB_ISP1362_HCD tristate "ISP1362 HCD support" depends on HAS_IOMEM + depends on COMPILE_TEST # nothing uses this ---help--- Supports the Philips ISP1362 chip as a host controller diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 7f0737449df7..d927adf3afcd 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1275,11 +1275,6 @@ MODULE_LICENSE ("GPL"); #define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver #endif -#ifdef CONFIG_TILE_USB -#include "ehci-tilegx.c" -#define PLATFORM_DRIVER ehci_hcd_tilegx_driver -#endif - #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP #include "ehci-pmcmsp.c" #define PLATFORM_DRIVER ehci_hcd_msp_driver diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c deleted file mode 100644 index 610ed437ed2c..000000000000 --- a/drivers/usb/host/ehci-tilegx.c +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2012 Tilera Corporation. All Rights Reserved. - */ - -/* - * Tilera TILE-Gx USB EHCI host controller driver. - */ - -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/usb/tilegx.h> -#include <linux/usb.h> - -#include <asm/homecache.h> - -#include <gxio/iorpc_usb_host.h> -#include <gxio/usb_host.h> - -static void tilegx_start_ehc(void) -{ -} - -static void tilegx_stop_ehc(void) -{ -} - -static int tilegx_ehci_setup(struct usb_hcd *hcd) -{ - int ret = ehci_init(hcd); - - /* - * Some drivers do: - * - * struct ehci_hcd *ehci = hcd_to_ehci(hcd); - * ehci->need_io_watchdog = 0; - * - * here, but since this is a new driver we're going to leave the - * watchdog enabled. Later we may try to turn it off and see - * whether we run into any problems. - */ - - return ret; -} - -static const struct hc_driver ehci_tilegx_hc_driver = { - .description = hcd_name, - .product_desc = "Tile-Gx EHCI", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * Generic hardware linkage. - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, - - /* - * Basic lifecycle operations. - */ - .reset = tilegx_ehci_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * Managing I/O requests and associated device resources. - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * Scheduling support. - */ - .get_frame_number = ehci_get_frame, - - /* - * Root hub support. - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; - -static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); - pte_t pte = { 0 }; - int my_cpu = smp_processor_id(); - int ret; - - if (usb_disabled()) - return -ENODEV; - - /* - * Try to initialize our GXIO context; if we can't, the device - * doesn't exist. - */ - if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 1) != 0) - return -ENXIO; - - hcd = usb_create_hcd(&ehci_tilegx_hc_driver, &pdev->dev, - dev_name(&pdev->dev)); - if (!hcd) { - ret = -ENOMEM; - goto err_hcd; - } - - /* - * We don't use rsrc_start to map in our registers, but seems like - * we ought to set it to something, so we use the register VA. - */ - hcd->rsrc_start = - (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); - hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); - hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); - - tilegx_start_ehc(); - - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs; - ehci->regs = - hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = readl(&ehci->caps->hcs_params); - - /* Create our IRQs and register them. */ - pdata->irq = irq_alloc_hwirq(-1); - if (!pdata->irq) { - ret = -ENXIO; - goto err_no_irq; - } - - tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); - - /* Configure interrupts. */ - ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, - cpu_x(my_cpu), cpu_y(my_cpu), - KERNEL_PL, pdata->irq); - if (ret) { - ret = -ENXIO; - goto err_have_irq; - } - - /* Register all of our memory. */ - pte = pte_set_home(pte, PAGE_HOME_HASH); - ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); - if (ret) { - ret = -ENXIO; - goto err_have_irq; - } - - ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); - if (ret == 0) { - platform_set_drvdata(pdev, hcd); - device_wakeup_enable(hcd->self.controller); - return ret; - } - -err_have_irq: - irq_free_hwirq(pdata->irq); -err_no_irq: - tilegx_stop_ehc(); - usb_put_hcd(hcd); -err_hcd: - gxio_usb_host_destroy(&pdata->usb_ctx); - return ret; -} - -static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - tilegx_stop_ehc(); - gxio_usb_host_destroy(&pdata->usb_ctx); - irq_free_hwirq(pdata->irq); - - return 0; -} - -static void ehci_hcd_tilegx_drv_shutdown(struct platform_device *pdev) -{ - usb_hcd_platform_shutdown(pdev); - ehci_hcd_tilegx_drv_remove(pdev); -} - -static struct platform_driver ehci_hcd_tilegx_driver = { - .probe = ehci_hcd_tilegx_drv_probe, - .remove = ehci_hcd_tilegx_drv_remove, - .shutdown = ehci_hcd_tilegx_drv_shutdown, - .driver = { - .name = "tilegx-ehci", - } -}; - -MODULE_ALIAS("platform:tilegx-ehci"); diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index da79e36ced89..650240846ee2 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -6,49 +6,6 @@ */ /* ------------------------------------------------------------------------- */ -/* - * Platform specific compile time options - */ -#if defined(CONFIG_BLACKFIN) - -#include <linux/io.h> -#define USE_32BIT 0 -#define MAX_ROOT_PORTS 2 -#define USE_PLATFORM_DELAY 0 -#define USE_NDELAY 1 - -#define DUMMY_DELAY_ACCESS \ - do { \ - bfin_read16(ASYNC_BANK0_BASE); \ - bfin_read16(ASYNC_BANK0_BASE); \ - bfin_read16(ASYNC_BANK0_BASE); \ - } while (0) - -#undef insw -#undef outsw - -#define insw delayed_insw -#define outsw delayed_outsw - -static inline void delayed_outsw(unsigned int addr, void *buf, int len) -{ - unsigned short *bp = (unsigned short *)buf; - while (len--) { - DUMMY_DELAY_ACCESS; - outw(*bp++, addr); - } -} - -static inline void delayed_insw(unsigned int addr, void *buf, int len) -{ - unsigned short *bp = (unsigned short *)buf; - while (len--) { - DUMMY_DELAY_ACCESS; - *bp++ = inw(addr); - } -} - -#else #define MAX_ROOT_PORTS 2 @@ -60,9 +17,6 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len) #define DUMMY_DELAY_ACCESS do {} while (0) -#endif - - /* ------------------------------------------------------------------------- */ #define USB_RESET_WIDTH 50 diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d088c340e4d0..4806e0f9e8d4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1245,11 +1245,6 @@ MODULE_LICENSE ("GPL"); #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver #endif -#ifdef CONFIG_TILE_USB -#include "ohci-tilegx.c" -#define PLATFORM_DRIVER ohci_hcd_tilegx_driver -#endif - static int __init ohci_hcd_mod_init(void) { int retval = 0; @@ -1274,12 +1269,6 @@ static int __init ohci_hcd_mod_init(void) goto error_ps3; #endif -#ifdef PLATFORM_DRIVER - retval = platform_driver_register(&PLATFORM_DRIVER); - if (retval < 0) - goto error_platform; -#endif - #ifdef OF_PLATFORM_DRIVER retval = platform_driver_register(&OF_PLATFORM_DRIVER); if (retval < 0) @@ -1323,10 +1312,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&OF_PLATFORM_DRIVER); error_of_platform: #endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); - error_platform: -#endif #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); error_ps3: @@ -1354,9 +1339,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef OF_PLATFORM_DRIVER platform_driver_unregister(&OF_PLATFORM_DRIVER); #endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -#endif #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c deleted file mode 100644 index d21ca3ce9a30..000000000000 --- a/drivers/usb/host/ohci-tilegx.c +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright 2012 Tilera Corporation. All Rights Reserved. - */ - -/* - * Tilera TILE-Gx USB OHCI host controller driver. - */ - -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/usb/tilegx.h> -#include <linux/usb.h> - -#include <asm/homecache.h> - -#include <gxio/iorpc_usb_host.h> -#include <gxio/usb_host.h> - -static void tilegx_start_ohc(void) -{ -} - -static void tilegx_stop_ohc(void) -{ -} - -static int tilegx_ohci_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ret = ohci_init(ohci); - if (ret < 0) - return ret; - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - -static const struct hc_driver ohci_tilegx_hc_driver = { - .description = hcd_name, - .product_desc = "Tile-Gx OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * Generic hardware linkage. - */ - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_LOCAL_MEM | HCD_USB11, - - /* - * Basic lifecycle operations. - */ - .start = tilegx_ohci_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, - - /* - * Managing I/O requests and associated device resources. - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * Scheduling support. - */ - .get_frame_number = ohci_get_frame, - - /* - * Root hub support. - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, - .start_port_reset = ohci_start_port_reset, -}; - -static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); - pte_t pte = { 0 }; - int my_cpu = smp_processor_id(); - int ret; - - if (usb_disabled()) - return -ENODEV; - - /* - * Try to initialize our GXIO context; if we can't, the device - * doesn't exist. - */ - if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 0) != 0) - return -ENXIO; - - hcd = usb_create_hcd(&ohci_tilegx_hc_driver, &pdev->dev, - dev_name(&pdev->dev)); - if (!hcd) { - ret = -ENOMEM; - goto err_hcd; - } - - /* - * We don't use rsrc_start to map in our registers, but seems like - * we ought to set it to something, so we use the register VA. - */ - hcd->rsrc_start = - (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx); - hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx); - hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx); - - tilegx_start_ohc(); - - /* Create our IRQs and register them. */ - pdata->irq = irq_alloc_hwirq(-1); - if (!pdata->irq) { - ret = -ENXIO; - goto err_no_irq; - } - - tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU); - - /* Configure interrupts. */ - ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx, - cpu_x(my_cpu), cpu_y(my_cpu), - KERNEL_PL, pdata->irq); - if (ret) { - ret = -ENXIO; - goto err_have_irq; - } - - /* Register all of our memory. */ - pte = pte_set_home(pte, PAGE_HOME_HASH); - ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0); - if (ret) { - ret = -ENXIO; - goto err_have_irq; - } - - ohci_hcd_init(hcd_to_ohci(hcd)); - - ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED); - if (ret == 0) { - platform_set_drvdata(pdev, hcd); - device_wakeup_enable(hcd->self.controller); - return ret; - } - -err_have_irq: - irq_free_hwirq(pdata->irq); -err_no_irq: - tilegx_stop_ohc(); - usb_put_hcd(hcd); -err_hcd: - gxio_usb_host_destroy(&pdata->usb_ctx); - return ret; -} - -static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); - - usb_remove_hcd(hcd); - usb_put_hcd(hcd); - tilegx_stop_ohc(); - gxio_usb_host_destroy(&pdata->usb_ctx); - irq_free_hwirq(pdata->irq); - - return 0; -} - -static void ohci_hcd_tilegx_drv_shutdown(struct platform_device *pdev) -{ - usb_hcd_platform_shutdown(pdev); - ohci_hcd_tilegx_drv_remove(pdev); -} - -static struct platform_driver ohci_hcd_tilegx_driver = { - .probe = ohci_hcd_tilegx_drv_probe, - .remove = ohci_hcd_tilegx_drv_remove, - .shutdown = ohci_hcd_tilegx_drv_shutdown, - .driver = { - .name = "tilegx-ohci", - } -}; - -MODULE_ALIAS("platform:tilegx-ohci"); diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 5506a9c03c1f..ad08895e78f9 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -5,7 +5,7 @@ # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC - tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)' + tristate 'Inventra Highspeed Dual Role Controller' depends on (USB || USB_GADGET) depends on HAS_IOMEM help @@ -18,9 +18,6 @@ config USB_MUSB_HDRC Texas Instruments families using this IP include DaVinci (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. - Analog Devices parts using this IP include Blackfin BF54x, - BF525 and BF527. - Allwinner SoCs using this IP include A10, A13, A20, ... If you do not know what this is, please say N. @@ -87,7 +84,7 @@ config USB_MUSB_DA8XX config USB_MUSB_TUSB6010 tristate "TUSB6010" depends on HAS_IOMEM - depends on (ARCH_OMAP2PLUS || COMPILE_TEST) && !BLACKFIN + depends on ARCH_OMAP2PLUS || COMPILE_TEST depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules config USB_MUSB_OMAP2PLUS @@ -107,11 +104,6 @@ config USB_MUSB_DSPS depends on ARCH_OMAP2PLUS || COMPILE_TEST depends on OF_IRQ -config USB_MUSB_BLACKFIN - tristate "Blackfin" - depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523) - depends on NOP_USB_XCEIV - config USB_MUSB_UX500 tristate "Ux500 platforms" depends on ARCH_U8500 || COMPILE_TEST @@ -149,7 +141,7 @@ config USB_UX500_DMA config USB_INVENTRA_DMA bool 'Inventra' - depends on USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN + depends on USB_MUSB_OMAP2PLUS help Enable DMA transfers using Mentor's engine. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 79d4d5439164..3a88c79e650c 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o obj-$(CONFIG_USB_MUSB_TUSB6010) += tusb6010.o obj-$(CONFIG_USB_MUSB_DAVINCI) += davinci.o obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o -obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c deleted file mode 100644 index 0a98dcd66d19..000000000000 --- a/drivers/usb/musb/blackfin.c +++ /dev/null @@ -1,623 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * MUSB OTG controller driver for Blackfin Processors - * - * Copyright 2006-2008 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/list.h> -#include <linux/gpio.h> -#include <linux/io.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/prefetch.h> -#include <linux/usb/usb_phy_generic.h> - -#include <asm/cacheflush.h> - -#include "musb_core.h" -#include "musbhsdma.h" -#include "blackfin.h" - -struct bfin_glue { - struct device *dev; - struct platform_device *musb; - struct platform_device *phy; -}; -#define glue_to_musb(g) platform_get_drvdata(g->musb) - -static u32 bfin_fifo_offset(u8 epnum) -{ - return USB_OFFSET(USB_EP0_FIFO) + (epnum * 8); -} - -static u8 bfin_readb(const void __iomem *addr, unsigned offset) -{ - return (u8)(bfin_read16(addr + offset)); -} - -static u16 bfin_readw(const void __iomem *addr, unsigned offset) -{ - return bfin_read16(addr + offset); -} - -static u32 bfin_readl(const void __iomem *addr, unsigned offset) -{ - return (u32)(bfin_read16(addr + offset)); -} - -static void bfin_writeb(void __iomem *addr, unsigned offset, u8 data) -{ - bfin_write16(addr + offset, (u16)data); -} - -static void bfin_writew(void __iomem *addr, unsigned offset, u16 data) -{ - bfin_write16(addr + offset, data); -} - -static void bfin_writel(void __iomem *addr, unsigned offset, u32 data) -{ - bfin_write16(addr + offset, (u16)data); -} - -/* - * Load an endpoint's FIFO - */ -static void bfin_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) -{ - struct musb *musb = hw_ep->musb; - void __iomem *fifo = hw_ep->fifo; - void __iomem *epio = hw_ep->regs; - u8 epnum = hw_ep->epnum; - - prefetch((u8 *)src); - - musb_writew(epio, MUSB_TXCOUNT, len); - - dev_dbg(musb->controller, "TX ep%d fifo %p count %d buf %p, epio %p\n", - hw_ep->epnum, fifo, len, src, epio); - - dump_fifo_data(src, len); - - if (!ANOMALY_05000380 && epnum != 0) { - u16 dma_reg; - - flush_dcache_range((unsigned long)src, - (unsigned long)(src + len)); - - /* Setup DMA address register */ - dma_reg = (u32)src; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); - SSYNC(); - - dma_reg = (u32)src >> 16; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); - SSYNC(); - - /* Setup DMA count register */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); - SSYNC(); - - /* Enable the DMA */ - dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); - SSYNC(); - - /* Wait for complete */ - while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) - cpu_relax(); - - /* acknowledge dma interrupt */ - bfin_write_USB_DMA_INTERRUPT(1 << epnum); - SSYNC(); - - /* Reset DMA */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); - SSYNC(); - } else { - SSYNC(); - - if (unlikely((unsigned long)src & 0x01)) - outsw_8((unsigned long)fifo, src, (len + 1) >> 1); - else - outsw((unsigned long)fifo, src, (len + 1) >> 1); - } -} -/* - * Unload an endpoint's FIFO - */ -static void bfin_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) -{ - struct musb *musb = hw_ep->musb; - void __iomem *fifo = hw_ep->fifo; - u8 epnum = hw_ep->epnum; - - if (ANOMALY_05000467 && epnum != 0) { - u16 dma_reg; - - invalidate_dcache_range((unsigned long)dst, - (unsigned long)(dst + len)); - - /* Setup DMA address register */ - dma_reg = (u32)dst; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); - SSYNC(); - - dma_reg = (u32)dst >> 16; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); - SSYNC(); - - /* Setup DMA count register */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); - SSYNC(); - - /* Enable the DMA */ - dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); - SSYNC(); - - /* Wait for complete */ - while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) - cpu_relax(); - - /* acknowledge dma interrupt */ - bfin_write_USB_DMA_INTERRUPT(1 << epnum); - SSYNC(); - - /* Reset DMA */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); - SSYNC(); - } else { - SSYNC(); - /* Read the last byte of packet with odd size from address fifo + 4 - * to trigger 1 byte access to EP0 FIFO. - */ - if (len == 1) - *dst = (u8)inw((unsigned long)fifo + 4); - else { - if (unlikely((unsigned long)dst & 0x01)) - insw_8((unsigned long)fifo, dst, len >> 1); - else - insw((unsigned long)fifo, dst, len >> 1); - - if (len & 0x01) - *(dst + len - 1) = (u8)inw((unsigned long)fifo + 4); - } - } - dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", - 'R', hw_ep->epnum, fifo, len, dst); - - dump_fifo_data(dst, len); -} - -static irqreturn_t blackfin_interrupt(int irq, void *__hci) -{ - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - struct musb *musb = __hci; - - spin_lock_irqsave(&musb->lock, flags); - - musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); - musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); - musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); - - if (musb->int_usb || musb->int_tx || musb->int_rx) { - musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); - musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); - musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); - retval = musb_interrupt(musb); - } - - /* Start sampling ID pin, when plug is removed from MUSB */ - if ((musb->xceiv->otg->state == OTG_STATE_B_IDLE - || musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON) || - (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) { - mod_timer(&musb->dev_timer, jiffies + TIMER_DELAY); - musb->a_wait_bcon = TIMER_DELAY; - } - - spin_unlock_irqrestore(&musb->lock, flags); - - return retval; -} - -static void musb_conn_timer_handler(struct timer_list *t) -{ - struct musb *musb = from_timer(musb, t, dev_timer); - unsigned long flags; - u16 val; - static u8 toggle; - - spin_lock_irqsave(&musb->lock, flags); - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_IDLE: - case OTG_STATE_A_WAIT_BCON: - /* Start a new session */ - val = musb_readw(musb->mregs, MUSB_DEVCTL); - val &= ~MUSB_DEVCTL_SESSION; - musb_writew(musb->mregs, MUSB_DEVCTL, val); - val |= MUSB_DEVCTL_SESSION; - musb_writew(musb->mregs, MUSB_DEVCTL, val); - /* Check if musb is host or peripheral. */ - val = musb_readw(musb->mregs, MUSB_DEVCTL); - - if (!(val & MUSB_DEVCTL_BDEVICE)) { - gpio_set_value(musb->config->gpio_vrsel, 1); - musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; - } else { - gpio_set_value(musb->config->gpio_vrsel, 0); - /* Ignore VBUSERROR and SUSPEND IRQ */ - val = musb_readb(musb->mregs, MUSB_INTRUSBE); - val &= ~MUSB_INTR_VBUSERROR; - musb_writeb(musb->mregs, MUSB_INTRUSBE, val); - - val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; - musb_writeb(musb->mregs, MUSB_INTRUSB, val); - musb->xceiv->otg->state = OTG_STATE_B_IDLE; - } - mod_timer(&musb->dev_timer, jiffies + TIMER_DELAY); - break; - case OTG_STATE_B_IDLE: - /* - * Start a new session. It seems that MUSB needs taking - * some time to recognize the type of the plug inserted? - */ - val = musb_readw(musb->mregs, MUSB_DEVCTL); - val |= MUSB_DEVCTL_SESSION; - musb_writew(musb->mregs, MUSB_DEVCTL, val); - val = musb_readw(musb->mregs, MUSB_DEVCTL); - - if (!(val & MUSB_DEVCTL_BDEVICE)) { - gpio_set_value(musb->config->gpio_vrsel, 1); - musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; - } else { - gpio_set_value(musb->config->gpio_vrsel, 0); - - /* Ignore VBUSERROR and SUSPEND IRQ */ - val = musb_readb(musb->mregs, MUSB_INTRUSBE); - val &= ~MUSB_INTR_VBUSERROR; - musb_writeb(musb->mregs, MUSB_INTRUSBE, val); - - val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; - musb_writeb(musb->mregs, MUSB_INTRUSB, val); - - /* Toggle the Soft Conn bit, so that we can response to - * the inserting of either A-plug or B-plug. - */ - if (toggle) { - val = musb_readb(musb->mregs, MUSB_POWER); - val &= ~MUSB_POWER_SOFTCONN; - musb_writeb(musb->mregs, MUSB_POWER, val); - toggle = 0; - } else { - val = musb_readb(musb->mregs, MUSB_POWER); - val |= MUSB_POWER_SOFTCONN; - musb_writeb(musb->mregs, MUSB_POWER, val); - toggle = 1; - } - /* The delay time is set to 1/4 second by default, - * shortening it, if accelerating A-plug detection - * is needed in OTG mode. - */ - mod_timer(&musb->dev_timer, jiffies + TIMER_DELAY / 4); - } - break; - default: - dev_dbg(musb->controller, "%s state not handled\n", - usb_otg_state_string(musb->xceiv->otg->state)); - break; - } - spin_unlock_irqrestore(&musb->lock, flags); - - dev_dbg(musb->controller, "state is %s\n", - usb_otg_state_string(musb->xceiv->otg->state)); -} - -static void bfin_musb_enable(struct musb *musb) -{ - /* REVISIT is this really correct ? */ -} - -static void bfin_musb_disable(struct musb *musb) -{ -} - -static void bfin_musb_set_vbus(struct musb *musb, int is_on) -{ - int value = musb->config->gpio_vrsel_active; - if (!is_on) - value = !value; - gpio_set_value(musb->config->gpio_vrsel, value); - - dev_dbg(musb->controller, "VBUS %s, devctl %02x " - /* otg %3x conf %08x prcm %08x */ "\n", - usb_otg_state_string(musb->xceiv->otg->state), - musb_readb(musb->mregs, MUSB_DEVCTL)); -} - -static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) -{ - return 0; -} - -static int bfin_musb_vbus_status(struct musb *musb) -{ - return 0; -} - -static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode) -{ - return -EIO; -} - -static int bfin_musb_adjust_channel_params(struct dma_channel *channel, - u16 packet_sz, u8 *mode, - dma_addr_t *dma_addr, u32 *len) -{ - struct musb_dma_channel *musb_channel = channel->private_data; - - /* - * Anomaly 05000450 might cause data corruption when using DMA - * MODE 1 transmits with short packet. So to work around this, - * we truncate all MODE 1 transfers down to a multiple of the - * max packet size, and then do the last short packet transfer - * (if there is any) using MODE 0. - */ - if (ANOMALY_05000450) { - if (musb_channel->transmit && *mode == 1) - *len = *len - (*len % packet_sz); - } - - return 0; -} - -static void bfin_musb_reg_init(struct musb *musb) -{ - if (ANOMALY_05000346) { - bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); - SSYNC(); - } - - if (ANOMALY_05000347) { - bfin_write_USB_APHY_CNTRL(0x0); - SSYNC(); - } - - /* Configure PLL oscillator register */ - bfin_write_USB_PLLOSC_CTRL(0x3080 | - ((480/musb->config->clkin) << 1)); - SSYNC(); - - bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1); - SSYNC(); - - bfin_write_USB_EP_NI0_RXMAXP(64); - SSYNC(); - - bfin_write_USB_EP_NI0_TXMAXP(64); - SSYNC(); - - /* Route INTRUSB/INTR_RX/INTR_TX to USB_INT0*/ - bfin_write_USB_GLOBINTR(0x7); - SSYNC(); - - bfin_write_USB_GLOBAL_CTL(GLOBAL_ENA | EP1_TX_ENA | EP2_TX_ENA | - EP3_TX_ENA | EP4_TX_ENA | EP5_TX_ENA | - EP6_TX_ENA | EP7_TX_ENA | EP1_RX_ENA | - EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | - EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); - SSYNC(); -} - -static int bfin_musb_init(struct musb *musb) -{ - - /* - * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE - * and OTG HOST modes, while rev 1.1 and greater require PE7 to - * be low for DEVICE mode and high for HOST mode. We set it high - * here because we are in host mode - */ - - if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) { - printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n", - musb->config->gpio_vrsel); - return -ENODEV; - } - gpio_direction_output(musb->config->gpio_vrsel, 0); - - musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(musb->xceiv)) { - gpio_free(musb->config->gpio_vrsel); - return -EPROBE_DEFER; - } - - bfin_musb_reg_init(musb); - - timer_setup(&musb->dev_timer, musb_conn_timer_handler, 0); - - musb->xceiv->set_power = bfin_musb_set_power; - - musb->isr = blackfin_interrupt; - musb->double_buffer_not_ok = true; - - return 0; -} - -static int bfin_musb_exit(struct musb *musb) -{ - gpio_free(musb->config->gpio_vrsel); - usb_put_phy(musb->xceiv); - - return 0; -} - -static const struct musb_platform_ops bfin_ops = { - .quirks = MUSB_DMA_INVENTRA, - .init = bfin_musb_init, - .exit = bfin_musb_exit, - - .fifo_offset = bfin_fifo_offset, - .readb = bfin_readb, - .writeb = bfin_writeb, - .readw = bfin_readw, - .writew = bfin_writew, - .readl = bfin_readl, - .writel = bfin_writel, - .fifo_mode = 2, - .read_fifo = bfin_read_fifo, - .write_fifo = bfin_write_fifo, -#ifdef CONFIG_USB_INVENTRA_DMA - .dma_init = musbhs_dma_controller_create, - .dma_exit = musbhs_dma_controller_destroy, -#endif - .enable = bfin_musb_enable, - .disable = bfin_musb_disable, - - .set_mode = bfin_musb_set_mode, - - .vbus_status = bfin_musb_vbus_status, - .set_vbus = bfin_musb_set_vbus, - - .adjust_channel_params = bfin_musb_adjust_channel_params, -}; - -static u64 bfin_dmamask = DMA_BIT_MASK(32); - -static int bfin_probe(struct platform_device *pdev) -{ - struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct platform_device *musb; - struct bfin_glue *glue; - - int ret = -ENOMEM; - - glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); - if (!glue) - goto err0; - - musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); - if (!musb) - goto err0; - - musb->dev.parent = &pdev->dev; - musb->dev.dma_mask = &bfin_dmamask; - musb->dev.coherent_dma_mask = bfin_dmamask; - - glue->dev = &pdev->dev; - glue->musb = musb; - - pdata->platform_ops = &bfin_ops; - - glue->phy = usb_phy_generic_register(); - if (IS_ERR(glue->phy)) - goto err1; - platform_set_drvdata(pdev, glue); - - memset(musb_resources, 0x00, sizeof(*musb_resources) * - ARRAY_SIZE(musb_resources)); - - musb_resources[0].name = pdev->resource[0].name; - musb_resources[0].start = pdev->resource[0].start; - musb_resources[0].end = pdev->resource[0].end; - musb_resources[0].flags = pdev->resource[0].flags; - - musb_resources[1].name = pdev->resource[1].name; - musb_resources[1].start = pdev->resource[1].start; - musb_resources[1].end = pdev->resource[1].end; - musb_resources[1].flags = pdev->resource[1].flags; - - ret = platform_device_add_resources(musb, musb_resources, - ARRAY_SIZE(musb_resources)); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); - goto err2; - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err2; - } - - ret = platform_device_add(musb); - if (ret) { - dev_err(&pdev->dev, "failed to register musb device\n"); - goto err2; - } - - return 0; - -err2: - usb_phy_generic_unregister(glue->phy); - -err1: - platform_device_put(musb); - -err0: - return ret; -} - -static int bfin_remove(struct platform_device *pdev) -{ - struct bfin_glue *glue = platform_get_drvdata(pdev); - - platform_device_unregister(glue->musb); - usb_phy_generic_unregister(glue->phy); - - return 0; -} - -static int __maybe_unused bfin_suspend(struct device *dev) -{ - struct bfin_glue *glue = dev_get_drvdata(dev); - struct musb *musb = glue_to_musb(glue); - - if (is_host_active(musb)) - /* - * During hibernate gpio_vrsel will change from high to low - * low which will generate wakeup event resume the system - * immediately. Set it to 0 before hibernate to avoid this - * wakeup event. - */ - gpio_set_value(musb->config->gpio_vrsel, 0); - - return 0; -} - -static int __maybe_unused bfin_resume(struct device *dev) -{ - struct bfin_glue *glue = dev_get_drvdata(dev); - struct musb *musb = glue_to_musb(glue); - - bfin_musb_reg_init(musb); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(bfin_pm_ops, bfin_suspend, bfin_resume); - -static struct platform_driver bfin_driver = { - .probe = bfin_probe, - .remove = bfin_remove, - .driver = { - .name = "musb-blackfin", - .pm = &bfin_pm_ops, - }, -}; - -MODULE_DESCRIPTION("Blackfin MUSB Glue Layer"); -MODULE_AUTHOR("Bryan Wy <cooloney@kernel.org>"); -MODULE_LICENSE("GPL v2"); -module_platform_driver(bfin_driver); diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h deleted file mode 100644 index 5b149915b0f8..000000000000 --- a/drivers/usb/musb/blackfin.h +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2007 by Analog Devices, Inc. - */ - -#ifndef __MUSB_BLACKFIN_H__ -#define __MUSB_BLACKFIN_H__ - -/* - * Blackfin specific definitions - */ - -/* Anomalies notes: - * - * 05000450 - USB DMA Mode 1 Short Packet Data Corruption: - * MUSB driver is designed to transfer buffer of N * maxpacket size - * in DMA mode 1 and leave the rest of the data to the next - * transfer in DMA mode 0, so we never transmit a short packet in - * DMA mode 1. - * - * 05000463 - This anomaly doesn't affect this driver since it - * never uses L1 or L2 memory as data destination. - * - * 05000464 - This anomaly doesn't affect this driver since it - * never uses L1 or L2 memory as data source. - * - * 05000465 - The anomaly can be seen when SCLK is over 100 MHz, and there is - * no way to workaround for bulk endpoints. Since the wMaxPackSize - * of bulk is less than or equal to 512, while the fifo size of - * endpoint 5, 6, 7 is 1024, the double buffer mode is enabled - * automatically when these endpoints are used for bulk OUT. - * - * 05000466 - This anomaly doesn't affect this driver since it never mixes - * concurrent DMA and core accesses to the TX endpoint FIFOs. - * - * 05000467 - The workaround for this anomaly will introduce another - * anomaly - 05000465. - */ - -/* The Mentor USB DMA engine on BF52x (silicon v0.0 and v0.1) seems to be - * unstable in host mode. This may be caused by Anomaly 05000380. After - * digging out the root cause, we will change this number accordingly. - * So, need to either use silicon v0.2+ or disable DMA mode in MUSB. - */ -#if ANOMALY_05000380 && defined(CONFIG_BF52x) && \ - !defined(CONFIG_MUSB_PIO_ONLY) -# error "Please use PIO mode in MUSB driver on bf52x chip v0.0 and v0.1" -#endif - -#undef DUMP_FIFO_DATA -#ifdef DUMP_FIFO_DATA -static void dump_fifo_data(u8 *buf, u16 len) -{ - u8 *tmp = buf; - int i; - - for (i = 0; i < len; i++) { - if (!(i % 16) && i) - pr_debug("\n"); - pr_debug("%02x ", *tmp++); - } - pr_debug("\n"); -} -#else -#define dump_fifo_data(buf, len) do {} while (0) -#endif - - -#define USB_DMA_BASE USB_DMA_INTERRUPT -#define USB_DMAx_CTRL 0x04 -#define USB_DMAx_ADDR_LOW 0x08 -#define USB_DMAx_ADDR_HIGH 0x0C -#define USB_DMAx_COUNT_LOW 0x10 -#define USB_DMAx_COUNT_HIGH 0x14 - -#define USB_DMA_REG(ep, reg) (USB_DMA_BASE + 0x20 * ep + reg) - -/* Almost 1 second */ -#define TIMER_DELAY (1 * HZ) - -#endif /* __MUSB_BLACKFIN_H__ */ diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4d723077be2b..fb5e4523dc28 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -126,7 +126,6 @@ EXPORT_SYMBOL_GPL(musb_get_mode); /*-------------------------------------------------------------------------*/ -#ifndef CONFIG_BLACKFIN static int musb_ulpi_read(struct usb_phy *phy, u32 reg) { void __iomem *addr = phy->io_priv; @@ -208,10 +207,6 @@ out: return ret; } -#else -#define musb_ulpi_read NULL -#define musb_ulpi_write NULL -#endif static struct usb_phy_io_ops musb_ulpi_access = { .read = musb_ulpi_read, @@ -2173,7 +2168,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) * - initializes musb->xceiv, usually by otg_get_phy() * - stops powering VBUS * - * There are various transceiver configurations. Blackfin, + * There are various transceiver configurations. * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses * external/discrete ones in various flavors (twl4030 family, * isp1504, non-OTG, etc) mostly hooking up through ULPI. diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 385841ee6f46..8a74cb2907f8 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -414,19 +414,6 @@ struct musb { struct usb_gadget_driver *gadget_driver; /* its driver */ struct usb_hcd *hcd; /* the usb hcd */ - /* - * FIXME: Remove this flag. - * - * This is only added to allow Blackfin to work - * with current driver. For some unknown reason - * Blackfin doesn't work with double buffering - * and that's enabled by default. - * - * We added this flag to forcefully disable double - * buffering until we get it working. - */ - unsigned double_buffer_not_ok:1; - const struct musb_hdrc_config *config; int xceiv_old_state; @@ -467,34 +454,6 @@ static inline char *musb_ep_xfertype_string(u8 type) return s; } -#ifdef CONFIG_BLACKFIN -static inline int musb_read_fifosize(struct musb *musb, - struct musb_hw_ep *hw_ep, u8 epnum) -{ - musb->nr_endpoints++; - musb->epmask |= (1 << epnum); - - if (epnum < 5) { - hw_ep->max_packet_sz_tx = 128; - hw_ep->max_packet_sz_rx = 128; - } else { - hw_ep->max_packet_sz_tx = 1024; - hw_ep->max_packet_sz_rx = 1024; - } - hw_ep->is_shared_fifo = false; - - return 0; -} - -static inline void musb_configure_ep0(struct musb *musb) -{ - musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; - musb->endpoints[0].is_shared_fifo = true; -} - -#else - static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) { @@ -531,8 +490,6 @@ static inline void musb_configure_ep0(struct musb *musb) musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; musb->endpoints[0].is_shared_fifo = true; } -#endif /* CONFIG_BLACKFIN */ - /***************************** Glue it together *****************************/ diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 7cf5a1bbdaff..7dac456f7ebc 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -70,7 +70,6 @@ static const struct musb_register_map musb_regmap[] = { { "DMA_CNTLch7", 0x274, 16 }, { "DMA_ADDRch7", 0x278, 32 }, { "DMA_COUNTch7", 0x27C, 32 }, -#ifndef CONFIG_BLACKFIN { "ConfigData", MUSB_CONFIGDATA,8 }, { "BabbleCtl", MUSB_BABBLE_CTL,8 }, { "TxFIFOsz", MUSB_TXFIFOSZ, 8 }, @@ -79,7 +78,6 @@ static const struct musb_register_map musb_regmap[] = { { "RxFIFOadd", MUSB_RXFIFOADD, 16 }, { "EPInfo", MUSB_EPINFO, 8 }, { "RAMInfo", MUSB_RAMINFO, 8 }, -#endif { } /* Terminating Entry */ }; diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index a4241f4d430e..0fc8cd0c2a5c 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -80,17 +80,6 @@ struct musb_hw_ep; #define is_cppi_enabled(musb) 0 #endif -/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1 - * Only allow DMA mode 1 to be used when the USB will actually generate the - * interrupts we expect. - */ -#ifdef CONFIG_BLACKFIN -# undef USE_MODE1 -# if !ANOMALY_05000456 -# define USE_MODE1 -# endif -#endif - /* * DMA channel status ... updated by the dma controller driver whenever that * status changes, and protected by the overall controller spinlock. diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 293e5b8da565..e564695c6c8d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -995,15 +995,11 @@ static int musb_gadget_enable(struct usb_ep *ep, /* Set TXMAXP with the FIFO size of the endpoint * to disable double buffering mode. */ - if (musb->double_buffer_not_ok) { - musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx); - } else { - if (can_bulk_split(musb, musb_ep->type)) - musb_ep->hb_mult = (hw_ep->max_packet_sz_tx / - musb_ep->packet_sz) - 1; - musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz - | (musb_ep->hb_mult << 11)); - } + if (can_bulk_split(musb, musb_ep->type)) + musb_ep->hb_mult = (hw_ep->max_packet_sz_tx / + musb_ep->packet_sz) - 1; + musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz + | (musb_ep->hb_mult << 11)); csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; if (musb_readw(regs, MUSB_TXCSR) @@ -1038,11 +1034,8 @@ static int musb_gadget_enable(struct usb_ep *ep, /* Set RXMAXP with the FIFO size of the endpoint * to disable double buffering mode. */ - if (musb->double_buffer_not_ok) - musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_tx); - else - musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz - | (musb_ep->hb_mult << 11)); + musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz + | (musb_ep->hb_mult << 11)); /* force shared fifo to OUT-only mode */ if (hw_ep->is_shared_fifo) { @@ -1680,40 +1673,6 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) return 0; } -#ifdef CONFIG_BLACKFIN -static struct usb_ep *musb_match_ep(struct usb_gadget *g, - struct usb_endpoint_descriptor *desc, - struct usb_ss_ep_comp_descriptor *ep_comp) -{ - struct usb_ep *ep = NULL; - - switch (usb_endpoint_type(desc)) { - case USB_ENDPOINT_XFER_ISOC: - case USB_ENDPOINT_XFER_BULK: - if (usb_endpoint_dir_in(desc)) - ep = gadget_find_ep_by_name(g, "ep5in"); - else - ep = gadget_find_ep_by_name(g, "ep6out"); - break; - case USB_ENDPOINT_XFER_INT: - if (usb_endpoint_dir_in(desc)) - ep = gadget_find_ep_by_name(g, "ep1in"); - else - ep = gadget_find_ep_by_name(g, "ep2out"); - break; - default: - break; - } - - if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) - return ep; - - return NULL; -} -#else -#define musb_match_ep NULL -#endif - static int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int musb_gadget_stop(struct usb_gadget *g); @@ -1727,7 +1686,6 @@ static const struct usb_gadget_ops musb_gadget_operations = { .pullup = musb_gadget_pullup, .udc_start = musb_gadget_start, .udc_stop = musb_gadget_stop, - .match_ep = musb_match_ep, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 45ed32c2cba9..3a8451a15f7f 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -574,11 +574,8 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, u8 epnum) /* Set RXMAXP with the FIFO size of the endpoint * to disable double buffer mode. */ - if (musb->double_buffer_not_ok) - musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx); - else - musb_writew(ep->regs, MUSB_RXMAXP, - qh->maxpacket | ((qh->hb_mult - 1) << 11)); + musb_writew(ep->regs, MUSB_RXMAXP, + qh->maxpacket | ((qh->hb_mult - 1) << 11)); ep->rx_reinit = 0; } @@ -804,10 +801,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* protocol/endpoint/interval/NAKlimit */ if (epnum) { musb_writeb(epio, MUSB_TXTYPE, qh->type_reg); - if (musb->double_buffer_not_ok) { - musb_writew(epio, MUSB_TXMAXP, - hw_ep->max_packet_sz_tx); - } else if (can_bulk_split(musb, qh->type)) { + if (can_bulk_split(musb, qh->type)) { qh->hb_mult = hw_ep->max_packet_sz_tx / packet_sz; musb_writew(epio, MUSB_TXMAXP, packet_sz diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index a4beba184798..88466622c89f 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -195,8 +195,6 @@ #define MUSB_HUBADDR_MULTI_TT 0x80 -#ifndef CONFIG_BLACKFIN - /* * Common USB registers */ @@ -416,184 +414,4 @@ static inline u8 musb_read_txhubport(struct musb *musb, u8 epnum) musb->io.busctl_offset(epnum, MUSB_TXHUBPORT)); } -#else /* CONFIG_BLACKFIN */ - -#define USB_BASE USB_FADDR -#define USB_OFFSET(reg) (reg - USB_BASE) - -/* - * Common USB registers - */ -#define MUSB_FADDR USB_OFFSET(USB_FADDR) /* 8-bit */ -#define MUSB_POWER USB_OFFSET(USB_POWER) /* 8-bit */ -#define MUSB_INTRTX USB_OFFSET(USB_INTRTX) /* 16-bit */ -#define MUSB_INTRRX USB_OFFSET(USB_INTRRX) -#define MUSB_INTRTXE USB_OFFSET(USB_INTRTXE) -#define MUSB_INTRRXE USB_OFFSET(USB_INTRRXE) -#define MUSB_INTRUSB USB_OFFSET(USB_INTRUSB) /* 8 bit */ -#define MUSB_INTRUSBE USB_OFFSET(USB_INTRUSBE)/* 8 bit */ -#define MUSB_FRAME USB_OFFSET(USB_FRAME) -#define MUSB_INDEX USB_OFFSET(USB_INDEX) /* 8 bit */ -#define MUSB_TESTMODE USB_OFFSET(USB_TESTMODE)/* 8 bit */ - -/* - * Additional Control Registers - */ - -#define MUSB_DEVCTL USB_OFFSET(USB_OTG_DEV_CTL) /* 8 bit */ - -#define MUSB_LINKINFO USB_OFFSET(USB_LINKINFO)/* 8 bit */ -#define MUSB_VPLEN USB_OFFSET(USB_VPLEN) /* 8 bit */ -#define MUSB_HS_EOF1 USB_OFFSET(USB_HS_EOF1) /* 8 bit */ -#define MUSB_FS_EOF1 USB_OFFSET(USB_FS_EOF1) /* 8 bit */ -#define MUSB_LS_EOF1 USB_OFFSET(USB_LS_EOF1) /* 8 bit */ - -/* Offsets to endpoint registers */ -#define MUSB_TXMAXP 0x00 -#define MUSB_TXCSR 0x04 -#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ -#define MUSB_RXMAXP 0x08 -#define MUSB_RXCSR 0x0C -#define MUSB_RXCOUNT 0x10 -#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ -#define MUSB_TXTYPE 0x14 -#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ -#define MUSB_TXINTERVAL 0x18 -#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ -#define MUSB_RXTYPE 0x1C -#define MUSB_RXINTERVAL 0x20 -#define MUSB_TXCOUNT 0x28 - -/* Offsets to endpoint registers in indexed model (using INDEX register) */ -#define MUSB_INDEXED_OFFSET(_epnum, _offset) \ - (0x40 + (_offset)) - -/* Offsets to endpoint registers in flat models */ -#define MUSB_FLAT_OFFSET(_epnum, _offset) \ - (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset)) - -/* Not implemented - HW has separate Tx/Rx FIFO */ -#define MUSB_TXCSR_MODE 0x0000 - -static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) -{ -} - -static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) -{ -} - -static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) -{ -} - -static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) -{ -} - -static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) -{ -} - -static inline u8 musb_read_txfifosz(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_txfifoadd(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_rxfifosz(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_rxfifoadd(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) -{ - return 0; -} - -static inline u8 musb_read_configdata(void __iomem *mbase) -{ - return 0; -} - -static inline u16 musb_read_hwvers(void __iomem *mbase) -{ - /* - * This register is invisible on Blackfin, actually the MUSB - * RTL version of Blackfin is 1.9, so just hardcode its value. - */ - return MUSB_HWVERS_1900; -} - -static inline void musb_write_rxfunaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_req) -{ -} - -static inline void musb_write_rxhubaddr(void __iomem *mbase, u8 epnum, - u8 qh_h_addr_reg) -{ -} - -static inline void musb_write_rxhubport(void __iomem *mbase, u8 epnum, - u8 qh_h_port_reg) -{ -} - -static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ -} - -static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum, - u8 qh_addr_reg) -{ -} - -static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, - u8 qh_h_port_reg) -{ -} - -static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum) -{ - return 0; -} - -#endif /* CONFIG_BLACKFIN */ - #endif /* __MUSB_REGS_H__ */ diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 21fb9e6622f3..4389fc3422bd 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -235,11 +235,6 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); -#ifdef CONFIG_BLACKFIN - /* Clear DMA interrupt flags */ - musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); -#endif - if (!int_hsdma) { musb_dbg(musb, "spurious DMA irq"); diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h index 44f7983df0a1..93665135aff1 100644 --- a/drivers/usb/musb/musbhsdma.h +++ b/drivers/usb/musb/musbhsdma.h @@ -6,8 +6,6 @@ * Copyright (C) 2005-2007 by Texas Instruments */ -#ifndef CONFIG_BLACKFIN - #define MUSB_HSDMA_BASE 0x200 #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) #define MUSB_HSDMA_CONTROL 0x4 @@ -34,68 +32,6 @@ musb_writel(mbase, \ MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ len) -#else - -#define MUSB_HSDMA_BASE 0x400 -#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) -#define MUSB_HSDMA_CONTROL 0x04 -#define MUSB_HSDMA_ADDR_LOW 0x08 -#define MUSB_HSDMA_ADDR_HIGH 0x0C -#define MUSB_HSDMA_COUNT_LOW 0x10 -#define MUSB_HSDMA_COUNT_HIGH 0x14 - -#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ - (MUSB_HSDMA_BASE + (_bchannel * 0x20) + _offset) - -static inline u32 musb_read_hsdma_addr(void __iomem *mbase, u8 bchannel) -{ - u32 addr = musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH)); - - addr = addr << 16; - - addr |= musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW)); - - return addr; -} - -static inline void musb_write_hsdma_addr(void __iomem *mbase, - u8 bchannel, dma_addr_t dma_addr) -{ - musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW), - dma_addr); - musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH), - (dma_addr >> 16)); -} - -static inline u32 musb_read_hsdma_count(void __iomem *mbase, u8 bchannel) -{ - u32 count = musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH)); - - count = count << 16; - - count |= musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW)); - - return count; -} - -static inline void musb_write_hsdma_count(void __iomem *mbase, - u8 bchannel, u32 len) -{ - musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW),len); - musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH), - (len >> 16)); -} - -#endif /* CONFIG_BLACKFIN */ - /* control register (16-bit): */ #define MUSB_HSDMA_ENABLE_SHIFT 0 #define MUSB_HSDMA_TRANSMIT_SHIFT 1 diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 27bb893cf6b2..198574b7dbef 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -6,8 +6,7 @@ menu "Console display driver support" config VGA_CONSOLE bool "VGA text console" if EXPERT || !X86 - depends on !4xx && !PPC_8xx && !SPARC && !M68K && !PARISC && !FRV && \ - !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \ + depends on !4xx && !PPC_8xx && !SPARC && !M68K && !PARISC && !SUPERH && \ (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \ !ARM64 && !ARC && !MICROBLAZE && !OPENRISC && !NDS32 default y diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 11e699f1062b..399573742487 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -580,109 +580,6 @@ config FB_VGA16 To compile this driver as a module, choose M here: the module will be called vga16fb. -config FB_BF54X_LQ043 - tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)" - depends on FB && (BF54x) && !BF542 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD - -config FB_BFIN_T350MCQB - tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)" - depends on FB && BLACKFIN - select BFIN_GPTIMERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD - This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI - It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK. - -config FB_BFIN_LQ035Q1 - tristate "SHARP LQ035Q1DH02 TFT LCD" - depends on FB && BLACKFIN && SPI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BFIN_GPTIMERS - help - This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on - the Blackfin Landscape LCD EZ-Extender Card. - This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI - It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK. - - To compile this driver as a module, choose M here: the - module will be called bfin-lq035q1-fb. - -config FB_BF537_LQ035 - tristate "SHARP LQ035 TFT LCD (BF537 STAMP)" - depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BFIN_GPTIMERS - help - This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD - attached to a BF537. - - To compile this driver as a module, choose M here: the - module will be called bf537-lq035. - -config FB_BFIN_7393 - tristate "Blackfin ADV7393 Video encoder" - depends on FB && BLACKFIN - select I2C - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for a ADV7393 video encoder - attached to a Blackfin on the PPI port. - If your Blackfin board has a ADV7393 select Y. - - To compile this driver as a module, choose M here: the - module will be called bfin_adv7393fb. - -choice - prompt "Video mode support" - depends on FB_BFIN_7393 - default NTSC - -config NTSC - bool 'NTSC 720x480' - -config PAL - bool 'PAL 720x576' - -config NTSC_640x480 - bool 'NTSC 640x480 (Experimental)' - -config PAL_640x480 - bool 'PAL 640x480 (Experimental)' - -config NTSC_YCBCR - bool 'NTSC 720x480 YCbCR input' - -config PAL_YCBCR - bool 'PAL 720x576 YCbCR input' - -endchoice - -choice - prompt "Size of ADV7393 frame buffer memory Single/Double Size" - depends on (FB_BFIN_7393) - default ADV7393_1XMEM - -config ADV7393_1XMEM - bool 'Single' - -config ADV7393_2XMEM - bool 'Double' -endchoice - config FB_STI tristate "HP STI frame buffer device support" depends on FB && PARISC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 115961e0721b..55282a21b500 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -136,11 +136,6 @@ obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o -obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o -obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o -obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o -obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o -obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o obj-$(CONFIG_FB_MX3) += mx3fb.o obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_MXS) += mxsfb.o diff --git a/drivers/video/fbdev/bf537-lq035.c b/drivers/video/fbdev/bf537-lq035.c deleted file mode 100644 index ef29fb425122..000000000000 --- a/drivers/video/fbdev/bf537-lq035.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Analog Devices Blackfin(BF537 STAMP) + SHARP TFT LCD. - * http://docs.blackfin.uclinux.org/doku.php?id=hw:cards:tft-lcd - * - * Copyright 2006-2010 Analog Devices Inc. - * Licensed under the GPL-2. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/device.h> -#include <linux/backlight.h> -#include <linux/lcd.h> -#include <linux/i2c.h> -#include <linux/spinlock.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> -#include <linux/platform_device.h> - -#include <asm/blackfin.h> -#include <asm/irq.h> -#include <asm/dpmc.h> -#include <asm/dma.h> -#include <asm/portmux.h> - -#define NO_BL 1 - -#define MAX_BRIGHENESS 95 -#define MIN_BRIGHENESS 5 -#define NBR_PALETTE 256 - -static const unsigned short ppi_pins[] = { - P_PPI0_CLK, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, 0 -}; - -static unsigned char *fb_buffer; /* RGB Buffer */ -static unsigned long *dma_desc_table; -static int t_conf_done, lq035_open_cnt; -static DEFINE_SPINLOCK(bfin_lq035_lock); - -static int landscape; -module_param(landscape, int, 0); -MODULE_PARM_DESC(landscape, - "LANDSCAPE use 320x240 instead of Native 240x320 Resolution"); - -static int bgr; -module_param(bgr, int, 0); -MODULE_PARM_DESC(bgr, - "BGR use 16-bit BGR-565 instead of RGB-565"); - -static int nocursor = 1; -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); - -static unsigned long current_brightness; /* backlight */ - -/* AD5280 vcomm */ -static unsigned char vcomm_value = 150; -static struct i2c_client *ad5280_client; - -static void set_vcomm(void) -{ - int nr; - - if (!ad5280_client) - return; - - nr = i2c_smbus_write_byte_data(ad5280_client, 0x00, vcomm_value); - if (nr) - pr_err("i2c_smbus_write_byte_data fail: %d\n", nr); -} - -static int ad5280_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); - return -EIO; - } - - ret = i2c_smbus_write_byte_data(client, 0x00, vcomm_value); - if (ret) { - dev_err(&client->dev, "write fail: %d\n", ret); - return ret; - } - - ad5280_client = client; - - return 0; -} - -static int ad5280_remove(struct i2c_client *client) -{ - ad5280_client = NULL; - return 0; -} - -static const struct i2c_device_id ad5280_id[] = { - {"bf537-lq035-ad5280", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ad5280_id); - -static struct i2c_driver ad5280_driver = { - .driver = { - .name = "bf537-lq035-ad5280", - }, - .probe = ad5280_probe, - .remove = ad5280_remove, - .id_table = ad5280_id, -}; - -#ifdef CONFIG_PNAV10 -#define MOD GPIO_PH13 - -#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER0_CONFIG -#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER0_WIDTH -#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER0_PERIOD -#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER0_COUNTER -#define TIMDIS_LP TIMDIS0 -#define TIMEN_LP TIMEN0 - -#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG -#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH -#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD -#define TIMDIS_SPS TIMDIS1 -#define TIMEN_SPS TIMEN1 - -#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER5_CONFIG -#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER5_WIDTH -#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER5_PERIOD -#define TIMDIS_SP TIMDIS5 -#define TIMEN_SP TIMEN5 - -#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER2_CONFIG -#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER2_WIDTH -#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER2_PERIOD -#define TIMDIS_PS_CLS TIMDIS2 -#define TIMEN_PS_CLS TIMEN2 - -#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER3_CONFIG -#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER3_WIDTH -#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER3_PERIOD -#define TIMDIS_REV TIMDIS3 -#define TIMEN_REV TIMEN3 -#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER3_COUNTER - -#define FREQ_PPI_CLK (5*1024*1024) /* PPI_CLK 5MHz */ - -#define TIMERS {P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR5, 0} - -#else - -#define UD GPIO_PF13 /* Up / Down */ -#define MOD GPIO_PF10 -#define LBR GPIO_PF14 /* Left Right */ - -#define bfin_write_TIMER_LP_CONFIG bfin_write_TIMER6_CONFIG -#define bfin_write_TIMER_LP_WIDTH bfin_write_TIMER6_WIDTH -#define bfin_write_TIMER_LP_PERIOD bfin_write_TIMER6_PERIOD -#define bfin_read_TIMER_LP_COUNTER bfin_read_TIMER6_COUNTER -#define TIMDIS_LP TIMDIS6 -#define TIMEN_LP TIMEN6 - -#define bfin_write_TIMER_SPS_CONFIG bfin_write_TIMER1_CONFIG -#define bfin_write_TIMER_SPS_WIDTH bfin_write_TIMER1_WIDTH -#define bfin_write_TIMER_SPS_PERIOD bfin_write_TIMER1_PERIOD -#define TIMDIS_SPS TIMDIS1 -#define TIMEN_SPS TIMEN1 - -#define bfin_write_TIMER_SP_CONFIG bfin_write_TIMER0_CONFIG -#define bfin_write_TIMER_SP_WIDTH bfin_write_TIMER0_WIDTH -#define bfin_write_TIMER_SP_PERIOD bfin_write_TIMER0_PERIOD -#define TIMDIS_SP TIMDIS0 -#define TIMEN_SP TIMEN0 - -#define bfin_write_TIMER_PS_CLS_CONFIG bfin_write_TIMER7_CONFIG -#define bfin_write_TIMER_PS_CLS_WIDTH bfin_write_TIMER7_WIDTH -#define bfin_write_TIMER_PS_CLS_PERIOD bfin_write_TIMER7_PERIOD -#define TIMDIS_PS_CLS TIMDIS7 -#define TIMEN_PS_CLS TIMEN7 - -#define bfin_write_TIMER_REV_CONFIG bfin_write_TIMER5_CONFIG -#define bfin_write_TIMER_REV_WIDTH bfin_write_TIMER5_WIDTH -#define bfin_write_TIMER_REV_PERIOD bfin_write_TIMER5_PERIOD -#define TIMDIS_REV TIMDIS5 -#define TIMEN_REV TIMEN5 -#define bfin_read_TIMER_REV_COUNTER bfin_read_TIMER5_COUNTER - -#define FREQ_PPI_CLK (6*1000*1000) /* PPI_CLK 6MHz */ -#define TIMERS {P_TMR0, P_TMR1, P_TMR5, P_TMR6, P_TMR7, 0} - -#endif - -#define LCD_X_RES 240 /* Horizontal Resolution */ -#define LCD_Y_RES 320 /* Vertical Resolution */ - -#define LCD_BBP 16 /* Bit Per Pixel */ - -/* the LCD and the DMA start counting differently; - * since one starts at 0 and the other starts at 1, - * we have a difference of 1 between START_LINES - * and U_LINES. - */ -#define START_LINES 8 /* lines for field flyback or field blanking signal */ -#define U_LINES 9 /* number of undisplayed blanking lines */ - -#define FRAMES_PER_SEC (60) - -#define DCLKS_PER_FRAME (FREQ_PPI_CLK/FRAMES_PER_SEC) -#define DCLKS_PER_LINE (DCLKS_PER_FRAME/(LCD_Y_RES+U_LINES)) - -#define PPI_CONFIG_VALUE (PORT_DIR|XFR_TYPE|DLEN_16|POLS) -#define PPI_DELAY_VALUE (0) -#define TIMER_CONFIG (PWM_OUT|PERIOD_CNT|TIN_SEL|CLK_SEL) - -#define ACTIVE_VIDEO_MEM_OFFSET (LCD_X_RES*START_LINES*(LCD_BBP/8)) -#define ACTIVE_VIDEO_MEM_SIZE (LCD_Y_RES*LCD_X_RES*(LCD_BBP/8)) -#define TOTAL_VIDEO_MEM_SIZE ((LCD_Y_RES+U_LINES)*LCD_X_RES*(LCD_BBP/8)) -#define TOTAL_DMA_DESC_SIZE (2 * sizeof(u32) * (LCD_Y_RES + U_LINES)) - -static void start_timers(void) /* CHECK with HW */ -{ - unsigned long flags; - - local_irq_save(flags); - - bfin_write_TIMER_ENABLE(TIMEN_REV); - SSYNC(); - - while (bfin_read_TIMER_REV_COUNTER() <= 11) - continue; - bfin_write_TIMER_ENABLE(TIMEN_LP); - SSYNC(); - - while (bfin_read_TIMER_LP_COUNTER() < 3) - continue; - bfin_write_TIMER_ENABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS); - SSYNC(); - t_conf_done = 1; - local_irq_restore(flags); -} - -static void config_timers(void) -{ - /* Stop timers */ - bfin_write_TIMER_DISABLE(TIMDIS_SP|TIMDIS_SPS|TIMDIS_REV| - TIMDIS_LP|TIMDIS_PS_CLS); - SSYNC(); - - /* LP, timer 6 */ - bfin_write_TIMER_LP_CONFIG(TIMER_CONFIG|PULSE_HI); - bfin_write_TIMER_LP_WIDTH(1); - - bfin_write_TIMER_LP_PERIOD(DCLKS_PER_LINE); - SSYNC(); - - /* SPS, timer 1 */ - bfin_write_TIMER_SPS_CONFIG(TIMER_CONFIG|PULSE_HI); - bfin_write_TIMER_SPS_WIDTH(DCLKS_PER_LINE*2); - bfin_write_TIMER_SPS_PERIOD((DCLKS_PER_LINE * (LCD_Y_RES+U_LINES))); - SSYNC(); - - /* SP, timer 0 */ - bfin_write_TIMER_SP_CONFIG(TIMER_CONFIG|PULSE_HI); - bfin_write_TIMER_SP_WIDTH(1); - bfin_write_TIMER_SP_PERIOD(DCLKS_PER_LINE); - SSYNC(); - - /* PS & CLS, timer 7 */ - bfin_write_TIMER_PS_CLS_CONFIG(TIMER_CONFIG); - bfin_write_TIMER_PS_CLS_WIDTH(LCD_X_RES + START_LINES); - bfin_write_TIMER_PS_CLS_PERIOD(DCLKS_PER_LINE); - - SSYNC(); - -#ifdef NO_BL - /* REV, timer 5 */ - bfin_write_TIMER_REV_CONFIG(TIMER_CONFIG|PULSE_HI); - - bfin_write_TIMER_REV_WIDTH(DCLKS_PER_LINE); - bfin_write_TIMER_REV_PERIOD(DCLKS_PER_LINE*2); - - SSYNC(); -#endif -} - -static void config_ppi(void) -{ - bfin_write_PPI_DELAY(PPI_DELAY_VALUE); - bfin_write_PPI_COUNT(LCD_X_RES-1); - /* 0x10 -> PORT_CFG -> 2 or 3 frame syncs */ - bfin_write_PPI_CONTROL((PPI_CONFIG_VALUE|0x10) & (~POLS)); -} - -static int config_dma(void) -{ - u32 i; - - if (landscape) { - - for (i = 0; i < U_LINES; ++i) { - /* blanking lines point to first line of fb_buffer */ - dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2]; - dma_desc_table[2*i+1] = (unsigned long)fb_buffer; - } - - for (i = U_LINES; i < U_LINES + LCD_Y_RES; ++i) { - /* visible lines */ - dma_desc_table[2*i] = (unsigned long)&dma_desc_table[2*i+2]; - dma_desc_table[2*i+1] = (unsigned long)fb_buffer + - (LCD_Y_RES+U_LINES-1-i)*2; - } - - /* last descriptor points to first */ - dma_desc_table[2*(LCD_Y_RES+U_LINES-1)] = (unsigned long)&dma_desc_table[0]; - - set_dma_x_count(CH_PPI, LCD_X_RES); - set_dma_x_modify(CH_PPI, LCD_Y_RES * (LCD_BBP / 8)); - set_dma_y_count(CH_PPI, 0); - set_dma_y_modify(CH_PPI, 0); - set_dma_next_desc_addr(CH_PPI, (void *)dma_desc_table[0]); - set_dma_config(CH_PPI, DMAFLOW_LARGE | NDSIZE_4 | WDSIZE_16); - - } else { - - set_dma_config(CH_PPI, set_bfin_dma_config(DIR_READ, - DMA_FLOW_AUTO, - INTR_DISABLE, - DIMENSION_2D, - DATA_SIZE_16, - DMA_NOSYNC_KEEP_DMA_BUF)); - set_dma_x_count(CH_PPI, LCD_X_RES); - set_dma_x_modify(CH_PPI, LCD_BBP / 8); - set_dma_y_count(CH_PPI, LCD_Y_RES+U_LINES); - set_dma_y_modify(CH_PPI, LCD_BBP / 8); - set_dma_start_addr(CH_PPI, (unsigned long) fb_buffer); - } - - return 0; -} - -static int request_ports(void) -{ - u16 tmr_req[] = TIMERS; - - /* - UD: PF13 - MOD: PF10 - LBR: PF14 - PPI_CLK: PF15 - */ - - if (peripheral_request_list(ppi_pins, KBUILD_MODNAME)) { - pr_err("requesting PPI peripheral failed\n"); - return -EBUSY; - } - - if (peripheral_request_list(tmr_req, KBUILD_MODNAME)) { - peripheral_free_list(ppi_pins); - pr_err("requesting timer peripheral failed\n"); - return -EBUSY; - } - -#if (defined(UD) && defined(LBR)) - if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) { - pr_err("requesting GPIO %d failed\n", UD); - return -EBUSY; - } - - if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) { - pr_err("requesting GPIO %d failed\n", LBR); - gpio_free(UD); - return -EBUSY; - } -#endif - - if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) { - pr_err("requesting GPIO %d failed\n", MOD); -#if (defined(UD) && defined(LBR)) - gpio_free(LBR); - gpio_free(UD); -#endif - return -EBUSY; - } - - SSYNC(); - return 0; -} - -static void free_ports(void) -{ - u16 tmr_req[] = TIMERS; - - peripheral_free_list(ppi_pins); - peripheral_free_list(tmr_req); - -#if defined(UD) && defined(LBR) - gpio_free(LBR); - gpio_free(UD); -#endif - gpio_free(MOD); -} - -static struct fb_info bfin_lq035_fb; - -static struct fb_var_screeninfo bfin_lq035_fb_defined = { - .bits_per_pixel = LCD_BBP, - .activate = FB_ACTIVATE_TEST, - .xres = LCD_X_RES, /*default portrait mode RGB*/ - .yres = LCD_Y_RES, - .xres_virtual = LCD_X_RES, - .yres_virtual = LCD_Y_RES, - .height = -1, - .width = -1, - .left_margin = 0, - .right_margin = 0, - .upper_margin = 0, - .lower_margin = 0, - .red = {11, 5, 0}, - .green = {5, 6, 0}, - .blue = {0, 5, 0}, - .transp = {0, 0, 0}, -}; - -static struct fb_fix_screeninfo bfin_lq035_fb_fix = { - .id = KBUILD_MODNAME, - .smem_len = ACTIVE_VIDEO_MEM_SIZE, - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 0, - .ypanstep = 0, - .line_length = LCD_X_RES*(LCD_BBP/8), - .accel = FB_ACCEL_NONE, -}; - - -static int bfin_lq035_fb_open(struct fb_info *info, int user) -{ - unsigned long flags; - - spin_lock_irqsave(&bfin_lq035_lock, flags); - lq035_open_cnt++; - spin_unlock_irqrestore(&bfin_lq035_lock, flags); - - if (lq035_open_cnt <= 1) { - bfin_write_PPI_CONTROL(0); - SSYNC(); - - set_vcomm(); - config_dma(); - config_ppi(); - - /* start dma */ - enable_dma(CH_PPI); - SSYNC(); - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); - SSYNC(); - - if (!t_conf_done) { - config_timers(); - start_timers(); - } - /* gpio_set_value(MOD,1); */ - } - - return 0; -} - -static int bfin_lq035_fb_release(struct fb_info *info, int user) -{ - unsigned long flags; - - spin_lock_irqsave(&bfin_lq035_lock, flags); - lq035_open_cnt--; - spin_unlock_irqrestore(&bfin_lq035_lock, flags); - - - if (lq035_open_cnt <= 0) { - - bfin_write_PPI_CONTROL(0); - SSYNC(); - - disable_dma(CH_PPI); - } - - return 0; -} - - -static int bfin_lq035_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - switch (var->bits_per_pixel) { - case 16:/* DIRECTCOLOUR, 64k */ - var->red.offset = info->var.red.offset; - var->green.offset = info->var.green.offset; - var->blue.offset = info->var.blue.offset; - var->red.length = info->var.red.length; - var->green.length = info->var.green.length; - var->blue.length = info->var.blue.length; - var->transp.offset = 0; - var->transp.length = 0; - var->transp.msb_right = 0; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - break; - default: - pr_debug("%s: depth not supported: %u BPP\n", __func__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || - info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u\n", - __func__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __func__, var->yres_virtual); - return -ENOMEM; - } - - return 0; -} - -static int bfin_lq035_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_lq035_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= NBR_PALETTE) - return -EINVAL; - - if (info->var.grayscale) - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset)| - (blue << info->var.blue.offset); - value &= 0xFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - - } - - return 0; -} - -static struct fb_ops bfin_lq035_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_lq035_fb_open, - .fb_release = bfin_lq035_fb_release, - .fb_check_var = bfin_lq035_fb_check_var, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = bfin_lq035_fb_cursor, - .fb_setcolreg = bfin_lq035_fb_setcolreg, -}; - -static int bl_get_brightness(struct backlight_device *bd) -{ - return current_brightness; -} - -static const struct backlight_ops bfin_lq035fb_bl_ops = { - .get_brightness = bl_get_brightness, -}; - -static struct backlight_device *bl_dev; - -static int bfin_lcd_get_power(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_power(struct lcd_device *dev, int power) -{ - return 0; -} - -static int bfin_lcd_get_contrast(struct lcd_device *dev) -{ - return (int)vcomm_value; -} - -static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) -{ - if (contrast > 255) - contrast = 255; - if (contrast < 0) - contrast = 0; - - vcomm_value = (unsigned char)contrast; - set_vcomm(); - return 0; -} - -static int bfin_lcd_check_fb(struct lcd_device *lcd, struct fb_info *fi) -{ - if (!fi || (fi == &bfin_lq035_fb)) - return 1; - return 0; -} - -static struct lcd_ops bfin_lcd_ops = { - .get_power = bfin_lcd_get_power, - .set_power = bfin_lcd_set_power, - .get_contrast = bfin_lcd_get_contrast, - .set_contrast = bfin_lcd_set_contrast, - .check_fb = bfin_lcd_check_fb, -}; - -static struct lcd_device *lcd_dev; - -static int bfin_lq035_probe(struct platform_device *pdev) -{ - struct backlight_properties props; - dma_addr_t dma_handle; - int ret; - - if (request_dma(CH_PPI, KBUILD_MODNAME)) { - pr_err("couldn't request PPI DMA\n"); - return -EFAULT; - } - - if (request_ports()) { - pr_err("couldn't request gpio port\n"); - ret = -EFAULT; - goto out_ports; - } - - fb_buffer = dma_alloc_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, - &dma_handle, GFP_KERNEL); - if (fb_buffer == NULL) { - pr_err("couldn't allocate dma buffer\n"); - ret = -ENOMEM; - goto out_dma_coherent; - } - - if (L1_DATA_A_LENGTH) - dma_desc_table = l1_data_sram_zalloc(TOTAL_DMA_DESC_SIZE); - else - dma_desc_table = dma_alloc_coherent(NULL, TOTAL_DMA_DESC_SIZE, - &dma_handle, 0); - - if (dma_desc_table == NULL) { - pr_err("couldn't allocate dma descriptor\n"); - ret = -ENOMEM; - goto out_table; - } - - bfin_lq035_fb.screen_base = (void *)fb_buffer; - bfin_lq035_fb_fix.smem_start = (int)fb_buffer; - if (landscape) { - bfin_lq035_fb_defined.xres = LCD_Y_RES; - bfin_lq035_fb_defined.yres = LCD_X_RES; - bfin_lq035_fb_defined.xres_virtual = LCD_Y_RES; - bfin_lq035_fb_defined.yres_virtual = LCD_X_RES; - - bfin_lq035_fb_fix.line_length = LCD_Y_RES*(LCD_BBP/8); - } else { - bfin_lq035_fb.screen_base += ACTIVE_VIDEO_MEM_OFFSET; - bfin_lq035_fb_fix.smem_start += ACTIVE_VIDEO_MEM_OFFSET; - } - - bfin_lq035_fb_defined.green.msb_right = 0; - bfin_lq035_fb_defined.red.msb_right = 0; - bfin_lq035_fb_defined.blue.msb_right = 0; - bfin_lq035_fb_defined.green.offset = 5; - bfin_lq035_fb_defined.green.length = 6; - bfin_lq035_fb_defined.red.length = 5; - bfin_lq035_fb_defined.blue.length = 5; - - if (bgr) { - bfin_lq035_fb_defined.red.offset = 0; - bfin_lq035_fb_defined.blue.offset = 11; - } else { - bfin_lq035_fb_defined.red.offset = 11; - bfin_lq035_fb_defined.blue.offset = 0; - } - - bfin_lq035_fb.fbops = &bfin_lq035_fb_ops; - bfin_lq035_fb.var = bfin_lq035_fb_defined; - - bfin_lq035_fb.fix = bfin_lq035_fb_fix; - bfin_lq035_fb.flags = FBINFO_DEFAULT; - - - bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev, - sizeof(u32) * 16, - GFP_KERNEL); - if (bfin_lq035_fb.pseudo_palette == NULL) { - pr_err("failed to allocate pseudo_palette\n"); - ret = -ENOMEM; - goto out_table; - } - - if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) { - pr_err("failed to allocate colormap (%d entries)\n", - NBR_PALETTE); - ret = -EFAULT; - goto out_table; - } - - if (register_framebuffer(&bfin_lq035_fb) < 0) { - pr_err("unable to register framebuffer\n"); - ret = -EINVAL; - goto out_reg; - } - - i2c_add_driver(&ad5280_driver); - - memset(&props, 0, sizeof(props)); - props.type = BACKLIGHT_RAW; - props.max_brightness = MAX_BRIGHENESS; - bl_dev = backlight_device_register("bf537-bl", NULL, NULL, - &bfin_lq035fb_bl_ops, &props); - - lcd_dev = lcd_device_register(KBUILD_MODNAME, &pdev->dev, NULL, - &bfin_lcd_ops); - if (IS_ERR(lcd_dev)) { - pr_err("unable to register lcd\n"); - ret = PTR_ERR(lcd_dev); - goto out_lcd; - } - lcd_dev->props.max_contrast = 255, - - pr_info("initialized"); - - return 0; -out_lcd: - unregister_framebuffer(&bfin_lq035_fb); -out_reg: - fb_dealloc_cmap(&bfin_lq035_fb.cmap); -out_table: - dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0); - fb_buffer = NULL; -out_dma_coherent: - free_ports(); -out_ports: - free_dma(CH_PPI); - return ret; -} - -static int bfin_lq035_remove(struct platform_device *pdev) -{ - if (fb_buffer != NULL) - dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0); - - if (L1_DATA_A_LENGTH) - l1_data_sram_free(dma_desc_table); - else - dma_free_coherent(NULL, TOTAL_DMA_DESC_SIZE, NULL, 0); - - bfin_write_TIMER_DISABLE(TIMEN_SP|TIMEN_SPS|TIMEN_PS_CLS| - TIMEN_LP|TIMEN_REV); - t_conf_done = 0; - - free_dma(CH_PPI); - - - fb_dealloc_cmap(&bfin_lq035_fb.cmap); - - - lcd_device_unregister(lcd_dev); - backlight_device_unregister(bl_dev); - - unregister_framebuffer(&bfin_lq035_fb); - i2c_del_driver(&ad5280_driver); - - free_ports(); - - pr_info("unregistered LCD driver\n"); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_lq035_suspend(struct platform_device *pdev, pm_message_t state) -{ - if (lq035_open_cnt > 0) { - bfin_write_PPI_CONTROL(0); - SSYNC(); - disable_dma(CH_PPI); - } - - return 0; -} - -static int bfin_lq035_resume(struct platform_device *pdev) -{ - if (lq035_open_cnt > 0) { - bfin_write_PPI_CONTROL(0); - SSYNC(); - - config_dma(); - config_ppi(); - - enable_dma(CH_PPI); - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); - SSYNC(); - - config_timers(); - start_timers(); - } else { - t_conf_done = 0; - } - - return 0; -} -#else -# define bfin_lq035_suspend NULL -# define bfin_lq035_resume NULL -#endif - -static struct platform_driver bfin_lq035_driver = { - .probe = bfin_lq035_probe, - .remove = bfin_lq035_remove, - .suspend = bfin_lq035_suspend, - .resume = bfin_lq035_resume, - .driver = { - .name = KBUILD_MODNAME, - }, -}; - -static int __init bfin_lq035_driver_init(void) -{ - request_module("i2c-bfin-twi"); - return platform_driver_register(&bfin_lq035_driver); -} -module_init(bfin_lq035_driver_init); - -static void __exit bfin_lq035_driver_cleanup(void) -{ - platform_driver_unregister(&bfin_lq035_driver); -} -module_exit(bfin_lq035_driver_cleanup); - -MODULE_DESCRIPTION("SHARP LQ035Q7DB03 TFT LCD Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/bf54x-lq043fb.c b/drivers/video/fbdev/bf54x-lq043fb.c deleted file mode 100644 index 8f1f97c75619..000000000000 --- a/drivers/video/fbdev/bf54x-lq043fb.c +++ /dev/null @@ -1,764 +0,0 @@ -/* - * File: drivers/video/bf54x-lq043.c - * Based on: - * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> - * - * Created: - * Description: ADSP-BF54x Framebuffer driver - * - * - * Modified: - * Copyright 2007-2008 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/device.h> -#include <linux/backlight.h> -#include <linux/lcd.h> -#include <linux/spinlock.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> - -#include <asm/blackfin.h> -#include <asm/irq.h> -#include <asm/dpmc.h> -#include <asm/dma-mapping.h> -#include <asm/dma.h> -#include <asm/portmux.h> - -#include <mach/bf54x-lq043.h> - -#define NO_BL_SUPPORT - -#define DRIVER_NAME "bf54x-lq043" -static char driver_name[] = DRIVER_NAME; - -#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 - -#define EPPI0_18 {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, \ - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, \ - P_PPI0_D11, P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, P_PPI0_D16, P_PPI0_D17, 0} - -#define EPPI0_24 {P_PPI0_D18, P_PPI0_D19, P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23, 0} - -struct bfin_bf54xfb_info { - struct fb_info *fb; - struct device *dev; - - struct bfin_bf54xfb_mach_info *mach_info; - - unsigned char *fb_buffer; /* RGB Buffer */ - - dma_addr_t dma_handle; - int lq043_open_cnt; - int irq; - spinlock_t lock; /* lock */ -}; - -static int nocursor; -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); - -static int outp_rgb666; -module_param(outp_rgb666, int, 0); -MODULE_PARM_DESC(outp_rgb666, "Output 18-bit RGB666"); - -#define LCD_X_RES 480 /*Horizontal Resolution */ -#define LCD_Y_RES 272 /* Vertical Resolution */ - -#define LCD_BPP 24 /* Bit Per Pixel */ -#define DMA_BUS_SIZE 32 - -/* -- Horizontal synchronizing -- - * - * Timing characteristics taken from the SHARP LQ043T1DG01 datasheet - * (LCY-W-06602A Page 9 of 22) - * - * Clock Frequency 1/Tc Min 7.83 Typ 9.00 Max 9.26 MHz - * - * Period TH - 525 - Clock - * Pulse width THp - 41 - Clock - * Horizontal period THd - 480 - Clock - * Back porch THb - 2 - Clock - * Front porch THf - 2 - Clock - * - * -- Vertical synchronizing -- - * Period TV - 286 - Line - * Pulse width TVp - 10 - Line - * Vertical period TVd - 272 - Line - * Back porch TVb - 2 - Line - * Front porch TVf - 2 - Line - */ - -#define LCD_CLK (8*1000*1000) /* 8MHz */ - -/* # active data to transfer after Horizontal Delay clock */ -#define EPPI_HCOUNT LCD_X_RES - -/* # active lines to transfer after Vertical Delay clock */ -#define EPPI_VCOUNT LCD_Y_RES - -/* Samples per Line = 480 (active data) + 45 (padding) */ -#define EPPI_LINE 525 - -/* Lines per Frame = 272 (active data) + 14 (padding) */ -#define EPPI_FRAME 286 - -/* FS1 (Hsync) Width (Typical)*/ -#define EPPI_FS1W_HBL 41 - -/* FS1 (Hsync) Period (Typical) */ -#define EPPI_FS1P_AVPL EPPI_LINE - -/* Horizontal Delay clock after assertion of Hsync (Typical) */ -#define EPPI_HDELAY 43 - -/* FS2 (Vsync) Width = FS1 (Hsync) Period * 10 */ -#define EPPI_FS2W_LVB (EPPI_LINE * 10) - - /* FS2 (Vsync) Period = FS1 (Hsync) Period * Lines per Frame */ -#define EPPI_FS2P_LAVF (EPPI_LINE * EPPI_FRAME) - -/* Vertical Delay after assertion of Vsync (2 Lines) */ -#define EPPI_VDELAY 12 - -#define EPPI_CLIP 0xFF00FF00 - -/* EPPI Control register configuration value for RGB out - * - EPPI as Output - * GP 2 frame sync mode, - * Internal Clock generation disabled, Internal FS generation enabled, - * Receives samples on EPPI_CLK raising edge, Transmits samples on EPPI_CLK falling edge, - * FS1 & FS2 are active high, - * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out) - * DMA Unpacking disabled when RGB Formating is enabled, otherwise DMA unpacking enabled - * Swapping Enabled, - * One (DMA) Channel Mode, - * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output - * Regular watermark - when FIFO is 100% full, - * Urgent watermark - when FIFO is 75% full - */ - -#define EPPI_CONTROL (0x20136E2E | SWAPEN) - -static inline u16 get_eppi_clkdiv(u32 target_ppi_clk) -{ - u32 sclk = get_sclk(); - - /* EPPI_CLK = (SCLK) / (2 * (EPPI_CLKDIV[15:0] + 1)) */ - - return (((sclk / target_ppi_clk) / 2) - 1); -} - -static void config_ppi(struct bfin_bf54xfb_info *fbi) -{ - - u16 eppi_clkdiv = get_eppi_clkdiv(LCD_CLK); - - bfin_write_EPPI0_FS1W_HBL(EPPI_FS1W_HBL); - bfin_write_EPPI0_FS1P_AVPL(EPPI_FS1P_AVPL); - bfin_write_EPPI0_FS2W_LVB(EPPI_FS2W_LVB); - bfin_write_EPPI0_FS2P_LAVF(EPPI_FS2P_LAVF); - bfin_write_EPPI0_CLIP(EPPI_CLIP); - - bfin_write_EPPI0_FRAME(EPPI_FRAME); - bfin_write_EPPI0_LINE(EPPI_LINE); - - bfin_write_EPPI0_HCOUNT(EPPI_HCOUNT); - bfin_write_EPPI0_HDELAY(EPPI_HDELAY); - bfin_write_EPPI0_VCOUNT(EPPI_VCOUNT); - bfin_write_EPPI0_VDELAY(EPPI_VDELAY); - - bfin_write_EPPI0_CLKDIV(eppi_clkdiv); - -/* - * DLEN = 6 (24 bits for RGB888 out) or 5 (18 bits for RGB666 out) - * RGB Formatting Enabled for RGB666 output, disabled for RGB888 output - */ - if (outp_rgb666) - bfin_write_EPPI0_CONTROL((EPPI_CONTROL & ~DLENGTH) | DLEN_18 | - RGB_FMT_EN); - else - bfin_write_EPPI0_CONTROL(((EPPI_CONTROL & ~DLENGTH) | DLEN_24) & - ~RGB_FMT_EN); - - -} - -static int config_dma(struct bfin_bf54xfb_info *fbi) -{ - - set_dma_config(CH_EPPI0, - set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, - INTR_DISABLE, DIMENSION_2D, - DATA_SIZE_32, - DMA_NOSYNC_KEEP_DMA_BUF)); - set_dma_x_count(CH_EPPI0, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE); - set_dma_x_modify(CH_EPPI0, DMA_BUS_SIZE / 8); - set_dma_y_count(CH_EPPI0, LCD_Y_RES); - set_dma_y_modify(CH_EPPI0, DMA_BUS_SIZE / 8); - set_dma_start_addr(CH_EPPI0, (unsigned long)fbi->fb_buffer); - - return 0; -} - -static int request_ports(struct bfin_bf54xfb_info *fbi) -{ - - u16 eppi_req_18[] = EPPI0_18; - u16 disp = fbi->mach_info->disp; - - if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) { - printk(KERN_ERR "Requesting GPIO %d failed\n", disp); - return -EFAULT; - } - - if (peripheral_request_list(eppi_req_18, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals failed\n"); - gpio_free(disp); - return -EFAULT; - } - - if (!outp_rgb666) { - - u16 eppi_req_24[] = EPPI0_24; - - if (peripheral_request_list(eppi_req_24, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals failed\n"); - peripheral_free_list(eppi_req_18); - gpio_free(disp); - return -EFAULT; - } - } - - return 0; -} - -static void free_ports(struct bfin_bf54xfb_info *fbi) -{ - - u16 eppi_req_18[] = EPPI0_18; - - gpio_free(fbi->mach_info->disp); - - peripheral_free_list(eppi_req_18); - - if (!outp_rgb666) { - u16 eppi_req_24[] = EPPI0_24; - peripheral_free_list(eppi_req_24); - } -} - -static int bfin_bf54x_fb_open(struct fb_info *info, int user) -{ - struct bfin_bf54xfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - fbi->lq043_open_cnt++; - - if (fbi->lq043_open_cnt <= 1) { - - bfin_write_EPPI0_CONTROL(0); - SSYNC(); - - config_dma(fbi); - config_ppi(fbi); - - /* start dma */ - enable_dma(CH_EPPI0); - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_bf54x_fb_release(struct fb_info *info, int user) -{ - struct bfin_bf54xfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - - fbi->lq043_open_cnt--; - - if (fbi->lq043_open_cnt <= 0) { - - bfin_write_EPPI0_CONTROL(0); - SSYNC(); - disable_dma(CH_EPPI0); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - - switch (var->bits_per_pixel) { - case 24:/* TRUECOLOUR, 16m */ - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; - var->red.length = var->green.length = var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - var->transp.msb_right = 0; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - break; - default: - pr_debug("%s: depth not supported: %u BPP\n", __func__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u \n", - __func__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __func__, var->yres_virtual); - return -ENOMEM; - } - - return 0; -} - -int bfin_bf54x_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_bf54x_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) - return -EINVAL; - - if (info->var.grayscale) { - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - } - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - value &= 0xFFFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - - } - - return 0; -} - -static struct fb_ops bfin_bf54x_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_bf54x_fb_open, - .fb_release = bfin_bf54x_fb_release, - .fb_check_var = bfin_bf54x_fb_check_var, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = bfin_bf54x_fb_cursor, - .fb_setcolreg = bfin_bf54x_fb_setcolreg, -}; - -#ifndef NO_BL_SUPPORT -static int bl_get_brightness(struct backlight_device *bd) -{ - return 0; -} - -static const struct backlight_ops bfin_lq043fb_bl_ops = { - .get_brightness = bl_get_brightness, -}; - -static struct backlight_device *bl_dev; - -static int bfin_lcd_get_power(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_power(struct lcd_device *dev, int power) -{ - return 0; -} - -static int bfin_lcd_get_contrast(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) -{ - - return 0; -} - -static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi) -{ - if (!fi || (fi == &bfin_bf54x_fb)) - return 1; - return 0; -} - -static struct lcd_ops bfin_lcd_ops = { - .get_power = bfin_lcd_get_power, - .set_power = bfin_lcd_set_power, - .get_contrast = bfin_lcd_get_contrast, - .set_contrast = bfin_lcd_set_contrast, - .check_fb = bfin_lcd_check_fb, -}; - -static struct lcd_device *lcd_dev; -#endif - -static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) -{ - /*struct bfin_bf54xfb_info *info = dev_id;*/ - - u16 status = bfin_read_EPPI0_STATUS(); - - bfin_write_EPPI0_STATUS(0xFFFF); - - if (status) { - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); - disable_dma(CH_EPPI0); - - /* start dma */ - enable_dma(CH_EPPI0); - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); - bfin_write_EPPI0_STATUS(0xFFFF); - } - - return IRQ_HANDLED; -} - -static int bfin_bf54x_probe(struct platform_device *pdev) -{ -#ifndef NO_BL_SUPPORT - struct backlight_properties props; -#endif - struct bfin_bf54xfb_info *info; - struct fb_info *fbinfo; - int ret; - - printk(KERN_INFO DRIVER_NAME ": FrameBuffer initializing...\n"); - - if (request_dma(CH_EPPI0, "CH_EPPI0") < 0) { - printk(KERN_ERR DRIVER_NAME - ": couldn't request CH_EPPI0 DMA\n"); - ret = -EFAULT; - goto out1; - } - - fbinfo = - framebuffer_alloc(sizeof(struct bfin_bf54xfb_info), &pdev->dev); - if (!fbinfo) { - ret = -ENOMEM; - goto out2; - } - - info = fbinfo->par; - info->fb = fbinfo; - info->dev = &pdev->dev; - spin_lock_init(&info->lock); - - platform_set_drvdata(pdev, fbinfo); - - strcpy(fbinfo->fix.id, driver_name); - - info->mach_info = pdev->dev.platform_data; - - if (info->mach_info == NULL) { - dev_err(&pdev->dev, - "no platform data for lcd, cannot attach\n"); - ret = -EINVAL; - goto out3; - } - - fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; - fbinfo->fix.type_aux = 0; - fbinfo->fix.xpanstep = 0; - fbinfo->fix.ypanstep = 0; - fbinfo->fix.ywrapstep = 0; - fbinfo->fix.accel = FB_ACCEL_NONE; - fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; - - fbinfo->var.nonstd = 0; - fbinfo->var.activate = FB_ACTIVATE_NOW; - fbinfo->var.height = info->mach_info->height; - fbinfo->var.width = info->mach_info->width; - fbinfo->var.accel_flags = 0; - fbinfo->var.vmode = FB_VMODE_NONINTERLACED; - - fbinfo->fbops = &bfin_bf54x_fb_ops; - fbinfo->flags = FBINFO_FLAG_DEFAULT; - - fbinfo->var.xres = info->mach_info->xres.defval; - fbinfo->var.xres_virtual = info->mach_info->xres.defval; - fbinfo->var.yres = info->mach_info->yres.defval; - fbinfo->var.yres_virtual = info->mach_info->yres.defval; - fbinfo->var.bits_per_pixel = info->mach_info->bpp.defval; - - fbinfo->var.upper_margin = 0; - fbinfo->var.lower_margin = 0; - fbinfo->var.vsync_len = 0; - - fbinfo->var.left_margin = 0; - fbinfo->var.right_margin = 0; - fbinfo->var.hsync_len = 0; - - fbinfo->var.red.offset = 16; - fbinfo->var.green.offset = 8; - fbinfo->var.blue.offset = 0; - fbinfo->var.transp.offset = 0; - fbinfo->var.red.length = 8; - fbinfo->var.green.length = 8; - fbinfo->var.blue.length = 8; - fbinfo->var.transp.length = 0; - fbinfo->fix.smem_len = info->mach_info->xres.max * - info->mach_info->yres.max * info->mach_info->bpp.max / 8; - - fbinfo->fix.line_length = fbinfo->var.xres_virtual * - fbinfo->var.bits_per_pixel / 8; - - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); - - if (NULL == info->fb_buffer) { - printk(KERN_ERR DRIVER_NAME - ": couldn't allocate dma buffer.\n"); - ret = -ENOMEM; - goto out3; - } - - fbinfo->screen_base = (void *)info->fb_buffer; - fbinfo->fix.smem_start = (int)info->fb_buffer; - - fbinfo->fbops = &bfin_bf54x_fb_ops; - - fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, - GFP_KERNEL); - if (!fbinfo->pseudo_palette) { - printk(KERN_ERR DRIVER_NAME - "Fail to allocate pseudo_palette\n"); - - ret = -ENOMEM; - goto out4; - } - - if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) - < 0) { - printk(KERN_ERR DRIVER_NAME - "Fail to allocate colormap (%d entries)\n", - BFIN_LCD_NBR_PALETTE_ENTRIES); - ret = -EFAULT; - goto out4; - } - - if (request_ports(info)) { - printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n"); - ret = -EFAULT; - goto out6; - } - - info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - ret = -EINVAL; - goto out7; - } - - if (request_irq(info->irq, bfin_bf54x_irq_error, 0, - "PPI ERROR", info) < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to request PPI ERROR IRQ\n"); - ret = -EFAULT; - goto out7; - } - - if (register_framebuffer(fbinfo) < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to register framebuffer.\n"); - ret = -EINVAL; - goto out8; - } -#ifndef NO_BL_SUPPORT - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 255; - bl_dev = backlight_device_register("bf54x-bl", NULL, NULL, - &bfin_lq043fb_bl_ops, &props); - if (IS_ERR(bl_dev)) { - printk(KERN_ERR DRIVER_NAME - ": unable to register backlight.\n"); - ret = -EINVAL; - unregister_framebuffer(fbinfo); - goto out8; - } - - lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); - lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); -#endif - - return 0; - -out8: - free_irq(info->irq, info); -out7: - free_ports(info); -out6: - fb_dealloc_cmap(&fbinfo->cmap); -out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); -out3: - framebuffer_release(fbinfo); -out2: - free_dma(CH_EPPI0); -out1: - - return ret; -} - -static int bfin_bf54x_remove(struct platform_device *pdev) -{ - - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_bf54xfb_info *info = fbinfo->par; - - free_dma(CH_EPPI0); - free_irq(info->irq, info); - - if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); - - fb_dealloc_cmap(&fbinfo->cmap); - -#ifndef NO_BL_SUPPORT - lcd_device_unregister(lcd_dev); - backlight_device_unregister(bl_dev); -#endif - - unregister_framebuffer(fbinfo); - - free_ports(info); - - printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n"); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) -{ - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); - disable_dma(CH_EPPI0); - bfin_write_EPPI0_STATUS(0xFFFF); - - return 0; -} - -static int bfin_bf54x_resume(struct platform_device *pdev) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_bf54xfb_info *info = fbinfo->par; - - if (info->lq043_open_cnt) { - - bfin_write_EPPI0_CONTROL(0); - SSYNC(); - - config_dma(info); - config_ppi(info); - - /* start dma */ - enable_dma(CH_EPPI0); - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); - } - - return 0; -} -#else -#define bfin_bf54x_suspend NULL -#define bfin_bf54x_resume NULL -#endif - -static struct platform_driver bfin_bf54x_driver = { - .probe = bfin_bf54x_probe, - .remove = bfin_bf54x_remove, - .suspend = bfin_bf54x_suspend, - .resume = bfin_bf54x_resume, - .driver = { - .name = DRIVER_NAME, - }, -}; -module_platform_driver(bfin_bf54x_driver); - -MODULE_DESCRIPTION("Blackfin BF54x TFT LCD Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/bfin-lq035q1-fb.c b/drivers/video/fbdev/bfin-lq035q1-fb.c deleted file mode 100644 index b459354ad940..000000000000 --- a/drivers/video/fbdev/bfin-lq035q1-fb.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02 - * - * Copyright 2008-2009 Analog Devices Inc. - * Licensed under the GPL-2 or later. - */ - -#define DRIVER_NAME "bfin-lq035q1" -#define pr_fmt(fmt) DRIVER_NAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/fb.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/backlight.h> -#include <linux/lcd.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> -#include <linux/spi/spi.h> - -#include <asm/blackfin.h> -#include <asm/irq.h> -#include <asm/dma.h> -#include <asm/portmux.h> -#include <asm/gptimers.h> - -#include <asm/bfin-lq035q1.h> - -#if defined(BF533_FAMILY) || defined(BF538_FAMILY) -#define TIMER_HSYNC_id TIMER1_id -#define TIMER_HSYNCbit TIMER1bit -#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN1 -#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1 -#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF1 - -#define TIMER_VSYNC_id TIMER2_id -#define TIMER_VSYNCbit TIMER2bit -#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN2 -#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL2 -#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF2 -#else -#define TIMER_HSYNC_id TIMER0_id -#define TIMER_HSYNCbit TIMER0bit -#define TIMER_HSYNC_STATUS_TRUN TIMER_STATUS_TRUN0 -#define TIMER_HSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL0 -#define TIMER_HSYNC_STATUS_TOVF TIMER_STATUS_TOVF0 - -#define TIMER_VSYNC_id TIMER1_id -#define TIMER_VSYNCbit TIMER1bit -#define TIMER_VSYNC_STATUS_TRUN TIMER_STATUS_TRUN1 -#define TIMER_VSYNC_STATUS_TIMIL TIMER_STATUS_TIMIL1 -#define TIMER_VSYNC_STATUS_TOVF TIMER_STATUS_TOVF1 -#endif - -#define LCD_X_RES 320 /* Horizontal Resolution */ -#define LCD_Y_RES 240 /* Vertical Resolution */ -#define DMA_BUS_SIZE 16 -#define U_LINE 4 /* Blanking Lines */ - - -/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD) - * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165 - */ - - -#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 - -#define PPI_TX_MODE 0x2 -#define PPI_XFER_TYPE_11 0xC -#define PPI_PORT_CFG_01 0x10 -#define PPI_POLS_1 0x8000 - -#define LQ035_INDEX 0x74 -#define LQ035_DATA 0x76 - -#define LQ035_DRIVER_OUTPUT_CTL 0x1 -#define LQ035_SHUT_CTL 0x11 - -#define LQ035_DRIVER_OUTPUT_MASK (LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV) -#define LQ035_DRIVER_OUTPUT_DEFAULT (0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK) - -#define LQ035_SHUT (1 << 0) /* Shutdown */ -#define LQ035_ON (0 << 0) /* Shutdown */ - -struct bfin_lq035q1fb_info { - struct fb_info *fb; - struct device *dev; - struct spi_driver spidrv; - struct bfin_lq035q1fb_disp_info *disp_info; - unsigned char *fb_buffer; /* RGB Buffer */ - dma_addr_t dma_handle; - int lq035_open_cnt; - int irq; - spinlock_t lock; /* lock */ - u32 pseudo_pal[16]; - - u32 lcd_bpp; - u32 h_actpix; - u32 h_period; - u32 h_pulse; - u32 h_start; - u32 v_lines; - u32 v_pulse; - u32 v_period; -}; - -static int nocursor; -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); - -struct spi_control { - unsigned short mode; -}; - -static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value) -{ - int ret; - u8 regs[3] = { LQ035_INDEX, 0, 0 }; - u8 dat[3] = { LQ035_DATA, 0, 0 }; - - if (!spi) - return -ENODEV; - - regs[2] = reg; - dat[1] = value >> 8; - dat[2] = value & 0xFF; - - ret = spi_write(spi, regs, ARRAY_SIZE(regs)); - ret |= spi_write(spi, dat, ARRAY_SIZE(dat)); - return ret; -} - -static int lq035q1_spidev_probe(struct spi_device *spi) -{ - int ret; - struct spi_control *ctl; - struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver, - struct bfin_lq035q1fb_info, - spidrv.driver); - - ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); - - if (!ctl) - return -ENOMEM; - - ctl->mode = (info->disp_info->mode & - LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT; - - ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); - ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); - if (ret) { - kfree(ctl); - return ret; - } - - spi_set_drvdata(spi, ctl); - - return 0; -} - -static int lq035q1_spidev_remove(struct spi_device *spi) -{ - return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); -} - -#ifdef CONFIG_PM_SLEEP -static int lq035q1_spidev_suspend(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - - return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); -} - -static int lq035q1_spidev_resume(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct spi_control *ctl = spi_get_drvdata(spi); - int ret; - - ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); - if (ret) - return ret; - - return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); -} - -static SIMPLE_DEV_PM_OPS(lq035q1_spidev_pm_ops, lq035q1_spidev_suspend, - lq035q1_spidev_resume); -#define LQ035Q1_SPIDEV_PM_OPS (&lq035q1_spidev_pm_ops) - -#else -#define LQ035Q1_SPIDEV_PM_OPS NULL -#endif - -/* Power down all displays on reboot, poweroff or halt */ -static void lq035q1_spidev_shutdown(struct spi_device *spi) -{ - lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); -} - -static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg) -{ - if (info->disp_info->use_bl) - gpio_set_value(info->disp_info->gpio_bl, arg); - - return 0; -} - -static int bfin_lq035q1_calc_timing(struct bfin_lq035q1fb_info *fbi) -{ - unsigned long clocks_per_pix, cpld_pipeline_delay_cor; - - /* - * Interface 16/18-bit TFT over an 8-bit wide PPI using a small - * Programmable Logic Device (CPLD) - * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165 - */ - - switch (fbi->disp_info->ppi_mode) { - case USE_RGB565_16_BIT_PPI: - fbi->lcd_bpp = 16; - clocks_per_pix = 1; - cpld_pipeline_delay_cor = 0; - break; - case USE_RGB565_8_BIT_PPI: - fbi->lcd_bpp = 16; - clocks_per_pix = 2; - cpld_pipeline_delay_cor = 3; - break; - case USE_RGB888_8_BIT_PPI: - fbi->lcd_bpp = 24; - clocks_per_pix = 3; - cpld_pipeline_delay_cor = 5; - break; - default: - return -EINVAL; - } - - /* - * HS and VS timing parameters (all in number of PPI clk ticks) - */ - - fbi->h_actpix = (LCD_X_RES * clocks_per_pix); /* active horizontal pixel */ - fbi->h_period = (336 * clocks_per_pix); /* HS period */ - fbi->h_pulse = (2 * clocks_per_pix); /* HS pulse width */ - fbi->h_start = (7 * clocks_per_pix + cpld_pipeline_delay_cor); /* first valid pixel */ - - fbi->v_lines = (LCD_Y_RES + U_LINE); /* total vertical lines */ - fbi->v_pulse = (2 * clocks_per_pix); /* VS pulse width (1-5 H_PERIODs) */ - fbi->v_period = (fbi->h_period * fbi->v_lines); /* VS period */ - - return 0; -} - -static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi) -{ - unsigned ppi_pmode; - - if (fbi->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI) - ppi_pmode = DLEN_16; - else - ppi_pmode = (DLEN_8 | PACK_EN); - - bfin_write_PPI_DELAY(fbi->h_start); - bfin_write_PPI_COUNT(fbi->h_actpix - 1); - bfin_write_PPI_FRAME(fbi->v_lines); - - bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */ - PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */ - PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */ - ppi_pmode | /* 8/16 bit data length / PACK_EN? */ - PPI_POLS_1); /* faling edge syncs POLS */ -} - -static inline void bfin_lq035q1_disable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); -} - -static inline void bfin_lq035q1_enable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); -} - -static void bfin_lq035q1_start_timers(void) -{ - enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit); -} - -static void bfin_lq035q1_stop_timers(void) -{ - disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit); - - set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN | - TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL | - TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF); - -} - -static void bfin_lq035q1_init_timers(struct bfin_lq035q1fb_info *fbi) -{ - - bfin_lq035q1_stop_timers(); - - set_gptimer_period(TIMER_HSYNC_id, fbi->h_period); - set_gptimer_pwidth(TIMER_HSYNC_id, fbi->h_pulse); - set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL| - TIMER_EMU_RUN); - - set_gptimer_period(TIMER_VSYNC_id, fbi->v_period); - set_gptimer_pwidth(TIMER_VSYNC_id, fbi->v_pulse); - set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL | - TIMER_EMU_RUN); - -} - -static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi) -{ - - - set_dma_config(CH_PPI, - set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, - INTR_DISABLE, DIMENSION_2D, - DATA_SIZE_16, - DMA_NOSYNC_KEEP_DMA_BUF)); - set_dma_x_count(CH_PPI, (LCD_X_RES * fbi->lcd_bpp) / DMA_BUS_SIZE); - set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_y_count(CH_PPI, fbi->v_lines); - - set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer); - -} - -static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, - P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, - P_PPI0_D6, P_PPI0_D7, P_PPI0_D8, - P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, - P_PPI0_D15, 0}; - -static const u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, - P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, - P_PPI0_D6, P_PPI0_D7, 0}; - -static inline void bfin_lq035q1_free_ports(unsigned ppi16) -{ - if (ppi16) - peripheral_free_list(ppi0_req_16); - else - peripheral_free_list(ppi0_req_8); - - if (ANOMALY_05000400) - gpio_free(P_IDENT(P_PPI0_FS3)); -} - -static int bfin_lq035q1_request_ports(struct platform_device *pdev, - unsigned ppi16) -{ - int ret; - /* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode: - * Drive PPI_FS3 Low - */ - if (ANOMALY_05000400) { - int ret = gpio_request_one(P_IDENT(P_PPI0_FS3), - GPIOF_OUT_INIT_LOW, "PPI_FS3"); - if (ret) - return ret; - } - - if (ppi16) - ret = peripheral_request_list(ppi0_req_16, DRIVER_NAME); - else - ret = peripheral_request_list(ppi0_req_8, DRIVER_NAME); - - if (ret) { - dev_err(&pdev->dev, "requesting peripherals failed\n"); - return -EFAULT; - } - - return 0; -} - -static int bfin_lq035q1_fb_open(struct fb_info *info, int user) -{ - struct bfin_lq035q1fb_info *fbi = info->par; - - spin_lock(&fbi->lock); - fbi->lq035_open_cnt++; - - if (fbi->lq035_open_cnt <= 1) { - - bfin_lq035q1_disable_ppi(); - SSYNC(); - - bfin_lq035q1_config_dma(fbi); - bfin_lq035q1_config_ppi(fbi); - bfin_lq035q1_init_timers(fbi); - - /* start dma */ - enable_dma(CH_PPI); - bfin_lq035q1_enable_ppi(); - bfin_lq035q1_start_timers(); - lq035q1_backlight(fbi, 1); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_lq035q1_fb_release(struct fb_info *info, int user) -{ - struct bfin_lq035q1fb_info *fbi = info->par; - - spin_lock(&fbi->lock); - - fbi->lq035_open_cnt--; - - if (fbi->lq035_open_cnt <= 0) { - lq035q1_backlight(fbi, 0); - bfin_lq035q1_disable_ppi(); - SSYNC(); - disable_dma(CH_PPI); - bfin_lq035q1_stop_timers(); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct bfin_lq035q1fb_info *fbi = info->par; - - if (var->bits_per_pixel == fbi->lcd_bpp) { - var->red.offset = info->var.red.offset; - var->green.offset = info->var.green.offset; - var->blue.offset = info->var.blue.offset; - var->red.length = info->var.red.length; - var->green.length = info->var.green.length; - var->blue.length = info->var.blue.length; - var->transp.offset = 0; - var->transp.length = 0; - var->transp.msb_right = 0; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - } else { - pr_debug("%s: depth not supported: %u BPP\n", __func__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u \n", - __func__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __func__, var->yres_virtual); - return -ENOMEM; - } - - - return 0; -} - -int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) - return -EINVAL; - - if (info->var.grayscale) { - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - } - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - value &= 0xFFFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - - } - - return 0; -} - -static struct fb_ops bfin_lq035q1_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_lq035q1_fb_open, - .fb_release = bfin_lq035q1_fb_release, - .fb_check_var = bfin_lq035q1_fb_check_var, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = bfin_lq035q1_fb_cursor, - .fb_setcolreg = bfin_lq035q1_fb_setcolreg, -}; - -static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id) -{ - /*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/ - - u16 status = bfin_read_PPI_STATUS(); - bfin_write_PPI_STATUS(-1); - - if (status) { - bfin_lq035q1_disable_ppi(); - disable_dma(CH_PPI); - - /* start dma */ - enable_dma(CH_PPI); - bfin_lq035q1_enable_ppi(); - bfin_write_PPI_STATUS(-1); - } - - return IRQ_HANDLED; -} - -static int bfin_lq035q1_probe(struct platform_device *pdev) -{ - struct bfin_lq035q1fb_info *info; - struct fb_info *fbinfo; - u32 active_video_mem_offset; - int ret; - - ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI"); - if (ret < 0) { - dev_err(&pdev->dev, "PPI DMA unavailable\n"); - goto out1; - } - - fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev); - if (!fbinfo) { - ret = -ENOMEM; - goto out2; - } - - info = fbinfo->par; - info->fb = fbinfo; - info->dev = &pdev->dev; - spin_lock_init(&info->lock); - - info->disp_info = pdev->dev.platform_data; - - platform_set_drvdata(pdev, fbinfo); - - ret = bfin_lq035q1_calc_timing(info); - if (ret < 0) { - dev_err(&pdev->dev, "Failed PPI Mode\n"); - goto out3; - } - - strcpy(fbinfo->fix.id, DRIVER_NAME); - - fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; - fbinfo->fix.type_aux = 0; - fbinfo->fix.xpanstep = 0; - fbinfo->fix.ypanstep = 0; - fbinfo->fix.ywrapstep = 0; - fbinfo->fix.accel = FB_ACCEL_NONE; - fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; - - fbinfo->var.nonstd = 0; - fbinfo->var.activate = FB_ACTIVATE_NOW; - fbinfo->var.height = -1; - fbinfo->var.width = -1; - fbinfo->var.accel_flags = 0; - fbinfo->var.vmode = FB_VMODE_NONINTERLACED; - - fbinfo->var.xres = LCD_X_RES; - fbinfo->var.xres_virtual = LCD_X_RES; - fbinfo->var.yres = LCD_Y_RES; - fbinfo->var.yres_virtual = LCD_Y_RES; - fbinfo->var.bits_per_pixel = info->lcd_bpp; - - if (info->disp_info->mode & LQ035_BGR) { - if (info->lcd_bpp == 24) { - fbinfo->var.red.offset = 0; - fbinfo->var.green.offset = 8; - fbinfo->var.blue.offset = 16; - } else { - fbinfo->var.red.offset = 0; - fbinfo->var.green.offset = 5; - fbinfo->var.blue.offset = 11; - } - } else { - if (info->lcd_bpp == 24) { - fbinfo->var.red.offset = 16; - fbinfo->var.green.offset = 8; - fbinfo->var.blue.offset = 0; - } else { - fbinfo->var.red.offset = 11; - fbinfo->var.green.offset = 5; - fbinfo->var.blue.offset = 0; - } - } - - fbinfo->var.transp.offset = 0; - - if (info->lcd_bpp == 24) { - fbinfo->var.red.length = 8; - fbinfo->var.green.length = 8; - fbinfo->var.blue.length = 8; - } else { - fbinfo->var.red.length = 5; - fbinfo->var.green.length = 6; - fbinfo->var.blue.length = 5; - } - - fbinfo->var.transp.length = 0; - - active_video_mem_offset = ((U_LINE / 2) * LCD_X_RES * (info->lcd_bpp / 8)); - - fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * info->lcd_bpp / 8 - + active_video_mem_offset; - - fbinfo->fix.line_length = fbinfo->var.xres_virtual * - fbinfo->var.bits_per_pixel / 8; - - - fbinfo->fbops = &bfin_lq035q1_fb_ops; - fbinfo->flags = FBINFO_FLAG_DEFAULT; - - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); - - if (NULL == info->fb_buffer) { - dev_err(&pdev->dev, "couldn't allocate dma buffer\n"); - ret = -ENOMEM; - goto out3; - } - - fbinfo->screen_base = (void *)info->fb_buffer + active_video_mem_offset; - fbinfo->fix.smem_start = (int)info->fb_buffer + active_video_mem_offset; - - fbinfo->fbops = &bfin_lq035q1_fb_ops; - - fbinfo->pseudo_palette = &info->pseudo_pal; - - ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0); - if (ret < 0) { - dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n", - BFIN_LCD_NBR_PALETTE_ENTRIES); - goto out4; - } - - ret = bfin_lq035q1_request_ports(pdev, - info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI); - if (ret) { - dev_err(&pdev->dev, "couldn't request gpio port\n"); - goto out6; - } - - info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - ret = -EINVAL; - goto out7; - } - - ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0, - DRIVER_NAME" PPI ERROR", info); - if (ret < 0) { - dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); - goto out7; - } - - info->spidrv.driver.name = DRIVER_NAME"-spi"; - info->spidrv.probe = lq035q1_spidev_probe; - info->spidrv.remove = lq035q1_spidev_remove; - info->spidrv.shutdown = lq035q1_spidev_shutdown; - info->spidrv.driver.pm = LQ035Q1_SPIDEV_PM_OPS; - - ret = spi_register_driver(&info->spidrv); - if (ret < 0) { - dev_err(&pdev->dev, "couldn't register SPI Interface\n"); - goto out8; - } - - if (info->disp_info->use_bl) { - ret = gpio_request_one(info->disp_info->gpio_bl, - GPIOF_OUT_INIT_LOW, "LQ035 Backlight"); - - if (ret) { - dev_err(&pdev->dev, "failed to request GPIO %d\n", - info->disp_info->gpio_bl); - goto out9; - } - } - - ret = register_framebuffer(fbinfo); - if (ret < 0) { - dev_err(&pdev->dev, "unable to register framebuffer\n"); - goto out10; - } - - dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n", - LCD_X_RES, LCD_Y_RES, info->lcd_bpp); - - return 0; - - out10: - if (info->disp_info->use_bl) - gpio_free(info->disp_info->gpio_bl); - out9: - spi_unregister_driver(&info->spidrv); - out8: - free_irq(info->irq, info); - out7: - bfin_lq035q1_free_ports(info->disp_info->ppi_mode == - USE_RGB565_16_BIT_PPI); - out6: - fb_dealloc_cmap(&fbinfo->cmap); - out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); - out3: - framebuffer_release(fbinfo); - out2: - free_dma(CH_PPI); - out1: - - return ret; -} - -static int bfin_lq035q1_remove(struct platform_device *pdev) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_lq035q1fb_info *info = fbinfo->par; - - if (info->disp_info->use_bl) - gpio_free(info->disp_info->gpio_bl); - - spi_unregister_driver(&info->spidrv); - - unregister_framebuffer(fbinfo); - - free_dma(CH_PPI); - free_irq(info->irq, info); - - if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); - - fb_dealloc_cmap(&fbinfo->cmap); - - bfin_lq035q1_free_ports(info->disp_info->ppi_mode == - USE_RGB565_16_BIT_PPI); - - framebuffer_release(fbinfo); - - dev_info(&pdev->dev, "unregistered LCD driver\n"); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_lq035q1_suspend(struct device *dev) -{ - struct fb_info *fbinfo = dev_get_drvdata(dev); - struct bfin_lq035q1fb_info *info = fbinfo->par; - - if (info->lq035_open_cnt) { - lq035q1_backlight(info, 0); - bfin_lq035q1_disable_ppi(); - SSYNC(); - disable_dma(CH_PPI); - bfin_lq035q1_stop_timers(); - bfin_write_PPI_STATUS(-1); - } - - return 0; -} - -static int bfin_lq035q1_resume(struct device *dev) -{ - struct fb_info *fbinfo = dev_get_drvdata(dev); - struct bfin_lq035q1fb_info *info = fbinfo->par; - - if (info->lq035_open_cnt) { - bfin_lq035q1_disable_ppi(); - SSYNC(); - - bfin_lq035q1_config_dma(info); - bfin_lq035q1_config_ppi(info); - bfin_lq035q1_init_timers(info); - - /* start dma */ - enable_dma(CH_PPI); - bfin_lq035q1_enable_ppi(); - bfin_lq035q1_start_timers(); - lq035q1_backlight(info, 1); - } - - return 0; -} - -static const struct dev_pm_ops bfin_lq035q1_dev_pm_ops = { - .suspend = bfin_lq035q1_suspend, - .resume = bfin_lq035q1_resume, -}; -#endif - -static struct platform_driver bfin_lq035q1_driver = { - .probe = bfin_lq035q1_probe, - .remove = bfin_lq035q1_remove, - .driver = { - .name = DRIVER_NAME, -#ifdef CONFIG_PM - .pm = &bfin_lq035q1_dev_pm_ops, -#endif - }, -}; - -module_platform_driver(bfin_lq035q1_driver); - -MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/bfin-t350mcqb-fb.c b/drivers/video/fbdev/bfin-t350mcqb-fb.c deleted file mode 100644 index e5ee4d9677f7..000000000000 --- a/drivers/video/fbdev/bfin-t350mcqb-fb.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * File: drivers/video/bfin-t350mcqb-fb.c - * Based on: - * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> - * - * Created: - * Description: Blackfin LCD Framebuffer driver - * - * - * Modified: - * Copyright 2004-2007 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/gfp.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/backlight.h> -#include <linux/lcd.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> - -#include <asm/blackfin.h> -#include <asm/irq.h> -#include <asm/dma-mapping.h> -#include <asm/dma.h> -#include <asm/portmux.h> -#include <asm/gptimers.h> - -#define NO_BL_SUPPORT - -#define LCD_X_RES 320 /* Horizontal Resolution */ -#define LCD_Y_RES 240 /* Vertical Resolution */ -#define LCD_BPP 24 /* Bit Per Pixel */ - -#define DMA_BUS_SIZE 16 -#define LCD_CLK (12*1000*1000) /* 12MHz */ - -#define CLOCKS_PER_PIX 3 - - /* - * HS and VS timing parameters (all in number of PPI clk ticks) - */ - -#define U_LINE 1 /* Blanking Lines */ - -#define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */ -#define H_PERIOD (408 * CLOCKS_PER_PIX) /* HS period */ -#define H_PULSE 90 /* HS pulse width */ -#define H_START 204 /* first valid pixel */ - -#define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */ -#define V_PULSE (3 * H_PERIOD) /* VS pulse width (1-5 H_PERIODs) */ -#define V_PERIOD (H_PERIOD * V_LINES) /* VS period */ - -#define ACTIVE_VIDEO_MEM_OFFSET (U_LINE * H_ACTPIX) - -#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 - -#define DRIVER_NAME "bfin-t350mcqb" -static char driver_name[] = DRIVER_NAME; - -struct bfin_t350mcqbfb_info { - struct fb_info *fb; - struct device *dev; - unsigned char *fb_buffer; /* RGB Buffer */ - dma_addr_t dma_handle; - int lq043_open_cnt; - int irq; - spinlock_t lock; /* lock */ - u32 pseudo_pal[16]; -}; - -static int nocursor; -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); - -#define PPI_TX_MODE 0x2 -#define PPI_XFER_TYPE_11 0xC -#define PPI_PORT_CFG_01 0x10 -#define PPI_PACK_EN 0x80 -#define PPI_POLS_1 0x8000 - -static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi) -{ - bfin_write_PPI_DELAY(H_START); - bfin_write_PPI_COUNT(H_ACTPIX-1); - bfin_write_PPI_FRAME(V_LINES); - - bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */ - PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */ - PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */ - PPI_PACK_EN | /* packing enabled PACK_EN */ - PPI_POLS_1); /* faling edge syncs POLS */ -} - -static inline void bfin_t350mcqb_disable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); -} - -static inline void bfin_t350mcqb_enable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); -} - -static void bfin_t350mcqb_start_timers(void) -{ - unsigned long flags; - - local_irq_save(flags); - enable_gptimers(TIMER1bit); - enable_gptimers(TIMER0bit); - local_irq_restore(flags); -} - -static void bfin_t350mcqb_stop_timers(void) -{ - disable_gptimers(TIMER0bit | TIMER1bit); - - set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 | - TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 | - TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1); - -} - -static void bfin_t350mcqb_init_timers(void) -{ - - bfin_t350mcqb_stop_timers(); - - set_gptimer_period(TIMER0_id, H_PERIOD); - set_gptimer_pwidth(TIMER0_id, H_PULSE); - set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL| - TIMER_EMU_RUN); - - set_gptimer_period(TIMER1_id, V_PERIOD); - set_gptimer_pwidth(TIMER1_id, V_PULSE); - set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT | - TIMER_TIN_SEL | TIMER_CLK_SEL | - TIMER_EMU_RUN); - -} - -static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi) -{ - - set_dma_config(CH_PPI, - set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO, - INTR_DISABLE, DIMENSION_2D, - DATA_SIZE_16, - DMA_NOSYNC_KEEP_DMA_BUF)); - set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE); - set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_y_count(CH_PPI, V_LINES); - - set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8); - set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer); - -} - -static u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, - P_PPI0_D3, P_PPI0_D4, P_PPI0_D5, - P_PPI0_D6, P_PPI0_D7, 0}; - -static int bfin_t350mcqb_request_ports(int action) -{ - if (action) { - if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) { - printk(KERN_ERR "Requesting Peripherals failed\n"); - return -EFAULT; - } - } else - peripheral_free_list(ppi0_req_8); - - return 0; -} - -static int bfin_t350mcqb_fb_open(struct fb_info *info, int user) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - fbi->lq043_open_cnt++; - - if (fbi->lq043_open_cnt <= 1) { - - bfin_t350mcqb_disable_ppi(); - SSYNC(); - - bfin_t350mcqb_config_dma(fbi); - bfin_t350mcqb_config_ppi(fbi); - bfin_t350mcqb_init_timers(); - - /* start dma */ - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - bfin_t350mcqb_start_timers(); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_t350mcqb_fb_release(struct fb_info *info, int user) -{ - struct bfin_t350mcqbfb_info *fbi = info->par; - - spin_lock(&fbi->lock); - - fbi->lq043_open_cnt--; - - if (fbi->lq043_open_cnt <= 0) { - bfin_t350mcqb_disable_ppi(); - SSYNC(); - disable_dma(CH_PPI); - bfin_t350mcqb_stop_timers(); - } - - spin_unlock(&fbi->lock); - - return 0; -} - -static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - - switch (var->bits_per_pixel) { - case 24:/* TRUECOLOUR, 16m */ - var->red.offset = 0; - var->green.offset = 8; - var->blue.offset = 16; - var->red.length = var->green.length = var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - var->transp.msb_right = 0; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - break; - default: - pr_debug("%s: depth not supported: %u BPP\n", __func__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u \n", - __func__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __func__, var->yres_virtual); - return -ENOMEM; - } - - return 0; -} - -int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) - return -EINVAL; - - if (info->var.grayscale) { - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - } - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - value &= 0xFFFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - - } - - return 0; -} - -static struct fb_ops bfin_t350mcqb_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_t350mcqb_fb_open, - .fb_release = bfin_t350mcqb_fb_release, - .fb_check_var = bfin_t350mcqb_fb_check_var, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = bfin_t350mcqb_fb_cursor, - .fb_setcolreg = bfin_t350mcqb_fb_setcolreg, -}; - -#ifndef NO_BL_SUPPORT -static int bl_get_brightness(struct backlight_device *bd) -{ - return 0; -} - -static const struct backlight_ops bfin_lq043fb_bl_ops = { - .get_brightness = bl_get_brightness, -}; - -static struct backlight_device *bl_dev; - -static int bfin_lcd_get_power(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_power(struct lcd_device *dev, int power) -{ - return 0; -} - -static int bfin_lcd_get_contrast(struct lcd_device *dev) -{ - return 0; -} - -static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast) -{ - - return 0; -} - -static int bfin_lcd_check_fb(struct lcd_device *dev, struct fb_info *fi) -{ - if (!fi || (fi == &bfin_t350mcqb_fb)) - return 1; - return 0; -} - -static struct lcd_ops bfin_lcd_ops = { - .get_power = bfin_lcd_get_power, - .set_power = bfin_lcd_set_power, - .get_contrast = bfin_lcd_get_contrast, - .set_contrast = bfin_lcd_set_contrast, - .check_fb = bfin_lcd_check_fb, -}; - -static struct lcd_device *lcd_dev; -#endif - -static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id) -{ - /*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/ - - u16 status = bfin_read_PPI_STATUS(); - bfin_write_PPI_STATUS(0xFFFF); - - if (status) { - bfin_t350mcqb_disable_ppi(); - disable_dma(CH_PPI); - - /* start dma */ - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - bfin_write_PPI_STATUS(0xFFFF); - } - - return IRQ_HANDLED; -} - -static int bfin_t350mcqb_probe(struct platform_device *pdev) -{ -#ifndef NO_BL_SUPPORT - struct backlight_properties props; -#endif - struct bfin_t350mcqbfb_info *info; - struct fb_info *fbinfo; - int ret; - - printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n", - LCD_X_RES, LCD_Y_RES, LCD_BPP); - - if (request_dma(CH_PPI, "CH_PPI") < 0) { - printk(KERN_ERR DRIVER_NAME - ": couldn't request CH_PPI DMA\n"); - ret = -EFAULT; - goto out1; - } - - fbinfo = - framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev); - if (!fbinfo) { - ret = -ENOMEM; - goto out2; - } - - info = fbinfo->par; - info->fb = fbinfo; - info->dev = &pdev->dev; - spin_lock_init(&info->lock); - - platform_set_drvdata(pdev, fbinfo); - - strcpy(fbinfo->fix.id, driver_name); - - fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; - fbinfo->fix.type_aux = 0; - fbinfo->fix.xpanstep = 0; - fbinfo->fix.ypanstep = 0; - fbinfo->fix.ywrapstep = 0; - fbinfo->fix.accel = FB_ACCEL_NONE; - fbinfo->fix.visual = FB_VISUAL_TRUECOLOR; - - fbinfo->var.nonstd = 0; - fbinfo->var.activate = FB_ACTIVATE_NOW; - fbinfo->var.height = 53; - fbinfo->var.width = 70; - fbinfo->var.accel_flags = 0; - fbinfo->var.vmode = FB_VMODE_NONINTERLACED; - - fbinfo->var.xres = LCD_X_RES; - fbinfo->var.xres_virtual = LCD_X_RES; - fbinfo->var.yres = LCD_Y_RES; - fbinfo->var.yres_virtual = LCD_Y_RES; - fbinfo->var.bits_per_pixel = LCD_BPP; - - fbinfo->var.red.offset = 0; - fbinfo->var.green.offset = 8; - fbinfo->var.blue.offset = 16; - fbinfo->var.transp.offset = 0; - fbinfo->var.red.length = 8; - fbinfo->var.green.length = 8; - fbinfo->var.blue.length = 8; - fbinfo->var.transp.length = 0; - fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8; - - fbinfo->fix.line_length = fbinfo->var.xres_virtual * - fbinfo->var.bits_per_pixel / 8; - - - fbinfo->fbops = &bfin_t350mcqb_fb_ops; - fbinfo->flags = FBINFO_FLAG_DEFAULT; - - info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + - ACTIVE_VIDEO_MEM_OFFSET, - &info->dma_handle, GFP_KERNEL); - - if (NULL == info->fb_buffer) { - printk(KERN_ERR DRIVER_NAME - ": couldn't allocate dma buffer.\n"); - ret = -ENOMEM; - goto out3; - } - - fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; - fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET; - - fbinfo->fbops = &bfin_t350mcqb_fb_ops; - - fbinfo->pseudo_palette = &info->pseudo_pal; - - if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) - < 0) { - printk(KERN_ERR DRIVER_NAME - "Fail to allocate colormap (%d entries)\n", - BFIN_LCD_NBR_PALETTE_ENTRIES); - ret = -EFAULT; - goto out4; - } - - if (bfin_t350mcqb_request_ports(1)) { - printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n"); - ret = -EFAULT; - goto out6; - } - - info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - ret = -EINVAL; - goto out7; - } - - ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0, - "PPI ERROR", info); - if (ret < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to request PPI ERROR IRQ\n"); - goto out7; - } - - if (register_framebuffer(fbinfo) < 0) { - printk(KERN_ERR DRIVER_NAME - ": unable to register framebuffer.\n"); - ret = -EINVAL; - goto out8; - } -#ifndef NO_BL_SUPPORT - memset(&props, 0, sizeof(struct backlight_properties)); - props.type = BACKLIGHT_RAW; - props.max_brightness = 255; - bl_dev = backlight_device_register("bf52x-bl", NULL, NULL, - &bfin_lq043fb_bl_ops, &props); - if (IS_ERR(bl_dev)) { - printk(KERN_ERR DRIVER_NAME - ": unable to register backlight.\n"); - ret = -EINVAL; - unregister_framebuffer(fbinfo); - goto out8; - } - - lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); - lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n"); -#endif - - return 0; - -out8: - free_irq(info->irq, info); -out7: - bfin_t350mcqb_request_ports(0); -out6: - fb_dealloc_cmap(&fbinfo->cmap); -out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, - info->fb_buffer, info->dma_handle); -out3: - framebuffer_release(fbinfo); -out2: - free_dma(CH_PPI); -out1: - - return ret; -} - -static int bfin_t350mcqb_remove(struct platform_device *pdev) -{ - - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *info = fbinfo->par; - - unregister_framebuffer(fbinfo); - - free_dma(CH_PPI); - free_irq(info->irq, info); - - if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len + - ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, - info->dma_handle); - - fb_dealloc_cmap(&fbinfo->cmap); - -#ifndef NO_BL_SUPPORT - lcd_device_unregister(lcd_dev); - backlight_device_unregister(bl_dev); -#endif - - bfin_t350mcqb_request_ports(0); - - framebuffer_release(fbinfo); - - printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n"); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *fbi = fbinfo->par; - - if (fbi->lq043_open_cnt) { - bfin_t350mcqb_disable_ppi(); - disable_dma(CH_PPI); - bfin_t350mcqb_stop_timers(); - bfin_write_PPI_STATUS(-1); - } - - - return 0; -} - -static int bfin_t350mcqb_resume(struct platform_device *pdev) -{ - struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_t350mcqbfb_info *fbi = fbinfo->par; - - if (fbi->lq043_open_cnt) { - bfin_t350mcqb_config_dma(fbi); - bfin_t350mcqb_config_ppi(fbi); - bfin_t350mcqb_init_timers(); - - /* start dma */ - enable_dma(CH_PPI); - bfin_t350mcqb_enable_ppi(); - bfin_t350mcqb_start_timers(); - } - - return 0; -} -#else -#define bfin_t350mcqb_suspend NULL -#define bfin_t350mcqb_resume NULL -#endif - -static struct platform_driver bfin_t350mcqb_driver = { - .probe = bfin_t350mcqb_probe, - .remove = bfin_t350mcqb_remove, - .suspend = bfin_t350mcqb_suspend, - .resume = bfin_t350mcqb_resume, - .driver = { - .name = DRIVER_NAME, - }, -}; -module_platform_driver(bfin_t350mcqb_driver); - -MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c deleted file mode 100644 index 542ffaddc6ab..000000000000 --- a/drivers/video/fbdev/bfin_adv7393fb.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Frame buffer driver for ADV7393/2 video encoder - * - * Copyright 2006-2009 Analog Devices Inc. - * Licensed under the GPL-2 or late. - */ - -/* - * TODO: Remove Globals - * TODO: Code Cleanup - */ - -#define DRIVER_NAME "bfin-adv7393" - -#define pr_fmt(fmt) DRIVER_NAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/sched.h> -#include <asm/blackfin.h> -#include <asm/irq.h> -#include <asm/dma.h> -#include <linux/uaccess.h> -#include <linux/gpio.h> -#include <asm/portmux.h> - -#include <linux/dma-mapping.h> -#include <linux/proc_fs.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> - -#include "bfin_adv7393fb.h" - -static int mode = VMODE; -static int mem = VMEM; -static int nocursor = 1; - -static const unsigned short ppi_pins[] = { - P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2, - P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3, - P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7, - P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11, - P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15, - 0 -}; - -/* - * card parameters - */ - -static struct bfin_adv7393_fb_par { - /* structure holding blackfin / adv7393 parameters when - screen is blanked */ - struct { - u8 Mode; /* ntsc/pal/? */ - } vga_state; - atomic_t ref_count; -} bfin_par; - -/* --------------------------------------------------------------------- */ - -static struct fb_var_screeninfo bfin_adv7393_fb_defined = { - .xres = 720, - .yres = 480, - .xres_virtual = 720, - .yres_virtual = 480, - .bits_per_pixel = 16, - .activate = FB_ACTIVATE_TEST, - .height = -1, - .width = -1, - .left_margin = 0, - .right_margin = 0, - .upper_margin = 0, - .lower_margin = 0, - .vmode = FB_VMODE_INTERLACED, - .red = {11, 5, 0}, - .green = {5, 6, 0}, - .blue = {0, 5, 0}, - .transp = {0, 0, 0}, -}; - -static struct fb_fix_screeninfo bfin_adv7393_fb_fix = { - .id = "BFIN ADV7393", - .smem_len = 720 * 480 * 2, - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 0, - .ypanstep = 0, - .line_length = 720 * 2, - .accel = FB_ACCEL_NONE -}; - -static struct fb_ops bfin_adv7393_fb_ops = { - .owner = THIS_MODULE, - .fb_open = bfin_adv7393_fb_open, - .fb_release = bfin_adv7393_fb_release, - .fb_check_var = bfin_adv7393_fb_check_var, - .fb_pan_display = bfin_adv7393_fb_pan_display, - .fb_blank = bfin_adv7393_fb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = bfin_adv7393_fb_cursor, - .fb_setcolreg = bfin_adv7393_fb_setcolreg, -}; - -static int dma_desc_list(struct adv7393fb_device *fbdev, u16 arg) -{ - if (arg == BUILD) { /* Build */ - fbdev->vb1 = l1_data_sram_zalloc(sizeof(struct dmasg)); - if (fbdev->vb1 == NULL) - goto error; - - fbdev->av1 = l1_data_sram_zalloc(sizeof(struct dmasg)); - if (fbdev->av1 == NULL) - goto error; - - fbdev->vb2 = l1_data_sram_zalloc(sizeof(struct dmasg)); - if (fbdev->vb2 == NULL) - goto error; - - fbdev->av2 = l1_data_sram_zalloc(sizeof(struct dmasg)); - if (fbdev->av2 == NULL) - goto error; - - /* Build linked DMA descriptor list */ - fbdev->vb1->next_desc_addr = fbdev->av1; - fbdev->av1->next_desc_addr = fbdev->vb2; - fbdev->vb2->next_desc_addr = fbdev->av2; - fbdev->av2->next_desc_addr = fbdev->vb1; - - /* Save list head */ - fbdev->descriptor_list_head = fbdev->av2; - - /* Vertical Blanking Field 1 */ - fbdev->vb1->start_addr = VB_DUMMY_MEMORY_SOURCE; - fbdev->vb1->cfg = DMA_CFG_VAL; - - fbdev->vb1->x_count = - fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; - - fbdev->vb1->x_modify = 0; - fbdev->vb1->y_count = fbdev->modes[mode].vb1_lines; - fbdev->vb1->y_modify = 0; - - /* Active Video Field 1 */ - - fbdev->av1->start_addr = (unsigned long)fbdev->fb_mem; - fbdev->av1->cfg = DMA_CFG_VAL; - fbdev->av1->x_count = - fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; - fbdev->av1->x_modify = fbdev->modes[mode].bpp / 8; - fbdev->av1->y_count = fbdev->modes[mode].a_lines; - fbdev->av1->y_modify = - (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank + - 1) * (fbdev->modes[mode].bpp / 8); - - /* Vertical Blanking Field 2 */ - - fbdev->vb2->start_addr = VB_DUMMY_MEMORY_SOURCE; - fbdev->vb2->cfg = DMA_CFG_VAL; - fbdev->vb2->x_count = - fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; - - fbdev->vb2->x_modify = 0; - fbdev->vb2->y_count = fbdev->modes[mode].vb2_lines; - fbdev->vb2->y_modify = 0; - - /* Active Video Field 2 */ - - fbdev->av2->start_addr = - (unsigned long)fbdev->fb_mem + fbdev->line_len; - - fbdev->av2->cfg = DMA_CFG_VAL; - - fbdev->av2->x_count = - fbdev->modes[mode].xres + fbdev->modes[mode].boeft_blank; - - fbdev->av2->x_modify = (fbdev->modes[mode].bpp / 8); - fbdev->av2->y_count = fbdev->modes[mode].a_lines; - - fbdev->av2->y_modify = - (fbdev->modes[mode].xres - fbdev->modes[mode].boeft_blank + - 1) * (fbdev->modes[mode].bpp / 8); - - return 1; - } - -error: - l1_data_sram_free(fbdev->vb1); - l1_data_sram_free(fbdev->av1); - l1_data_sram_free(fbdev->vb2); - l1_data_sram_free(fbdev->av2); - - return 0; -} - -static int bfin_config_dma(struct adv7393fb_device *fbdev) -{ - BUG_ON(!(fbdev->fb_mem)); - - set_dma_x_count(CH_PPI, fbdev->descriptor_list_head->x_count); - set_dma_x_modify(CH_PPI, fbdev->descriptor_list_head->x_modify); - set_dma_y_count(CH_PPI, fbdev->descriptor_list_head->y_count); - set_dma_y_modify(CH_PPI, fbdev->descriptor_list_head->y_modify); - set_dma_start_addr(CH_PPI, fbdev->descriptor_list_head->start_addr); - set_dma_next_desc_addr(CH_PPI, - fbdev->descriptor_list_head->next_desc_addr); - set_dma_config(CH_PPI, fbdev->descriptor_list_head->cfg); - - return 1; -} - -static void bfin_disable_dma(void) -{ - bfin_write_DMA0_CONFIG(bfin_read_DMA0_CONFIG() & ~DMAEN); -} - -static void bfin_config_ppi(struct adv7393fb_device *fbdev) -{ - if (ANOMALY_05000183) { - bfin_write_TIMER2_CONFIG(WDTH_CAP); - bfin_write_TIMER_ENABLE(TIMEN2); - } - - bfin_write_PPI_CONTROL(0x381E); - bfin_write_PPI_FRAME(fbdev->modes[mode].tot_lines); - bfin_write_PPI_COUNT(fbdev->modes[mode].xres + - fbdev->modes[mode].boeft_blank - 1); - bfin_write_PPI_DELAY(fbdev->modes[mode].aoeft_blank - 1); -} - -static void bfin_enable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN); -} - -static void bfin_disable_ppi(void) -{ - bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN); -} - -static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static inline int adv7393_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int -adv7393_write_block(struct i2c_client *client, - const u8 *data, unsigned int len) -{ - int ret = -1; - u8 reg; - - while (len >= 2) { - reg = *data++; - ret = adv7393_write(client, reg, *data++); - if (ret < 0) - break; - len -= 2; - } - - return ret; -} - -static int adv7393_mode(struct i2c_client *client, u16 mode) -{ - switch (mode) { - case POWER_ON: /* ADV7393 Sleep mode OFF */ - adv7393_write(client, 0x00, 0x1E); - break; - case POWER_DOWN: /* ADV7393 Sleep mode ON */ - adv7393_write(client, 0x00, 0x1F); - break; - case BLANK_OFF: /* Pixel Data Valid */ - adv7393_write(client, 0x82, 0xCB); - break; - case BLANK_ON: /* Pixel Data Invalid */ - adv7393_write(client, 0x82, 0x8B); - break; - default: - return -EINVAL; - break; - } - return 0; -} - -static irqreturn_t ppi_irq_error(int irq, void *dev_id) -{ - - struct adv7393fb_device *fbdev = (struct adv7393fb_device *)dev_id; - - u16 status = bfin_read_PPI_STATUS(); - - pr_debug("%s: PPI Status = 0x%X\n", __func__, status); - - if (status) { - bfin_disable_dma(); /* TODO: Check Sequence */ - bfin_disable_ppi(); - bfin_clear_PPI_STATUS(); - bfin_config_dma(fbdev); - bfin_enable_ppi(); - } - - return IRQ_HANDLED; - -} - -static int proc_output(char *buf) -{ - char *p = buf; - - p += sprintf(p, - "Usage:\n" - "echo 0x[REG][Value] > adv7393\n" - "example: echo 0x1234 >adv7393\n" - "writes 0x34 into Register 0x12\n"); - - return p - buf; -} - -static ssize_t -adv7393_read_proc(struct file *file, char __user *buf, - size_t size, loff_t *ppos) -{ - static const char message[] = "Usage:\n" - "echo 0x[REG][Value] > adv7393\n" - "example: echo 0x1234 >adv7393\n" - "writes 0x34 into Register 0x12\n"; - return simple_read_from_buffer(buf, size, ppos, message, - sizeof(message)); -} - -static ssize_t -adv7393_write_proc(struct file *file, const char __user * buffer, - size_t count, loff_t *ppos) -{ - struct adv7393fb_device *fbdev = PDE_DATA(file_inode(file)); - unsigned int val; - int ret; - - ret = kstrtouint_from_user(buffer, count, 0, &val); - if (ret) - return -EFAULT; - - adv7393_write(fbdev->client, val >> 8, val & 0xff); - - return count; -} - -static const struct file_operations fops = { - .read = adv7393_read_proc, - .write = adv7393_write_proc, - .llseek = default_llseek, -}; - -static int bfin_adv7393_fb_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret = 0; - struct proc_dir_entry *entry; - - struct adv7393fb_device *fbdev = NULL; - - if (mem > 2) { - dev_err(&client->dev, "mem out of allowed range [1;2]\n"); - return -EINVAL; - } - - if (mode >= ARRAY_SIZE(known_modes)) { - dev_err(&client->dev, "mode %d: not supported", mode); - return -EFAULT; - } - - fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); - if (!fbdev) { - dev_err(&client->dev, "failed to allocate device private record"); - return -ENOMEM; - } - - i2c_set_clientdata(client, fbdev); - - fbdev->modes = known_modes; - fbdev->client = client; - - fbdev->fb_len = - mem * fbdev->modes[mode].xres * fbdev->modes[mode].xres * - (fbdev->modes[mode].bpp / 8); - - fbdev->line_len = - fbdev->modes[mode].xres * (fbdev->modes[mode].bpp / 8); - - /* Workaround "PPI Does Not Start Properly In Specific Mode" */ - if (ANOMALY_05000400) { - ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW, - "PPI0_FS3"); - if (ret) { - dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); - ret = -EBUSY; - goto free_fbdev; - } - } - - if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { - dev_err(&client->dev, "requesting PPI peripheral failed\n"); - ret = -EFAULT; - goto free_gpio; - } - - fbdev->fb_mem = - dma_alloc_coherent(NULL, fbdev->fb_len, &fbdev->dma_handle, - GFP_KERNEL); - - if (NULL == fbdev->fb_mem) { - dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n", - (u32) fbdev->fb_len); - ret = -ENOMEM; - goto free_ppi_pins; - } - - fbdev->info.screen_base = (void *)fbdev->fb_mem; - bfin_adv7393_fb_fix.smem_start = (int)fbdev->fb_mem; - - bfin_adv7393_fb_fix.smem_len = fbdev->fb_len; - bfin_adv7393_fb_fix.line_length = fbdev->line_len; - - if (mem > 1) - bfin_adv7393_fb_fix.ypanstep = 1; - - bfin_adv7393_fb_defined.red.length = 5; - bfin_adv7393_fb_defined.green.length = 6; - bfin_adv7393_fb_defined.blue.length = 5; - - bfin_adv7393_fb_defined.xres = fbdev->modes[mode].xres; - bfin_adv7393_fb_defined.yres = fbdev->modes[mode].yres; - bfin_adv7393_fb_defined.xres_virtual = fbdev->modes[mode].xres; - bfin_adv7393_fb_defined.yres_virtual = mem * fbdev->modes[mode].yres; - bfin_adv7393_fb_defined.bits_per_pixel = fbdev->modes[mode].bpp; - - fbdev->info.fbops = &bfin_adv7393_fb_ops; - fbdev->info.var = bfin_adv7393_fb_defined; - fbdev->info.fix = bfin_adv7393_fb_fix; - fbdev->info.par = &bfin_par; - fbdev->info.flags = FBINFO_DEFAULT; - - fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); - if (!fbdev->info.pseudo_palette) { - dev_err(&client->dev, "failed to allocate pseudo_palette\n"); - ret = -ENOMEM; - goto free_fb_mem; - } - - if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { - dev_err(&client->dev, "failed to allocate colormap (%d entries)\n", - BFIN_LCD_NBR_PALETTE_ENTRIES); - ret = -EFAULT; - goto free_palette; - } - - if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) { - dev_err(&client->dev, "unable to request PPI DMA\n"); - ret = -EFAULT; - goto free_cmap; - } - - if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0, - "PPI ERROR", fbdev) < 0) { - dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); - ret = -EFAULT; - goto free_ch_ppi; - } - - fbdev->open = 0; - - ret = adv7393_write_block(client, fbdev->modes[mode].adv7393_i2c_initd, - fbdev->modes[mode].adv7393_i2c_initd_len); - - if (ret) { - dev_err(&client->dev, "i2c attach: init error\n"); - goto free_irq_ppi; - } - - - if (register_framebuffer(&fbdev->info) < 0) { - dev_err(&client->dev, "unable to register framebuffer\n"); - ret = -EFAULT; - goto free_irq_ppi; - } - - dev_info(&client->dev, "fb%d: %s frame buffer device\n", - fbdev->info.node, fbdev->info.fix.id); - dev_info(&client->dev, "fb memory address : 0x%p\n", fbdev->fb_mem); - - entry = proc_create_data("driver/adv7393", 0, NULL, &fops, fbdev); - if (!entry) { - dev_err(&client->dev, "unable to create /proc entry\n"); - ret = -EFAULT; - goto free_fb; - } - return 0; - -free_fb: - unregister_framebuffer(&fbdev->info); -free_irq_ppi: - free_irq(IRQ_PPI_ERROR, fbdev); -free_ch_ppi: - free_dma(CH_PPI); -free_cmap: - fb_dealloc_cmap(&fbdev->info.cmap); -free_palette: - kfree(fbdev->info.pseudo_palette); -free_fb_mem: - dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, - fbdev->dma_handle); -free_ppi_pins: - peripheral_free_list(ppi_pins); -free_gpio: - if (ANOMALY_05000400) - gpio_free(P_IDENT(P_PPI0_FS3)); -free_fbdev: - kfree(fbdev); - - return ret; -} - -static int bfin_adv7393_fb_open(struct fb_info *info, int user) -{ - struct adv7393fb_device *fbdev = to_adv7393fb_device(info); - - fbdev->info.screen_base = (void *)fbdev->fb_mem; - if (!fbdev->info.screen_base) { - dev_err(&fbdev->client->dev, "unable to map device\n"); - return -ENOMEM; - } - - fbdev->open = 1; - dma_desc_list(fbdev, BUILD); - adv7393_mode(fbdev->client, BLANK_OFF); - bfin_config_ppi(fbdev); - bfin_config_dma(fbdev); - bfin_enable_ppi(); - - return 0; -} - -static int bfin_adv7393_fb_release(struct fb_info *info, int user) -{ - struct adv7393fb_device *fbdev = to_adv7393fb_device(info); - - adv7393_mode(fbdev->client, BLANK_ON); - bfin_disable_dma(); - bfin_disable_ppi(); - dma_desc_list(fbdev, DESTRUCT); - fbdev->open = 0; - return 0; -} - -static int -bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - - switch (var->bits_per_pixel) { - case 16:/* DIRECTCOLOUR, 64k */ - var->red.offset = info->var.red.offset; - var->green.offset = info->var.green.offset; - var->blue.offset = info->var.blue.offset; - var->red.length = info->var.red.length; - var->green.length = info->var.green.length; - var->blue.length = info->var.blue.length; - var->transp.offset = 0; - var->transp.length = 0; - var->transp.msb_right = 0; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - break; - default: - pr_debug("%s: depth not supported: %u BPP\n", __func__, - var->bits_per_pixel); - return -EINVAL; - } - - if (info->var.xres != var->xres || - info->var.yres != var->yres || - info->var.xres_virtual != var->xres_virtual || - info->var.yres_virtual != var->yres_virtual) { - pr_debug("%s: Resolution not supported: X%u x Y%u\n", - __func__, var->xres, var->yres); - return -EINVAL; - } - - /* - * Memory limit - */ - - if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) { - pr_debug("%s: Memory Limit requested yres_virtual = %u\n", - __func__, var->yres_virtual); - return -ENOMEM; - } - - return 0; -} - -static int -bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -{ - int dy; - u32 dmaaddr; - struct adv7393fb_device *fbdev = to_adv7393fb_device(info); - - if (!var || !info) - return -EINVAL; - - if (var->xoffset - info->var.xoffset) { - /* No support for X panning for now! */ - return -EINVAL; - } - dy = var->yoffset - info->var.yoffset; - - if (dy) { - pr_debug("%s: Panning screen of %d lines\n", __func__, dy); - - dmaaddr = fbdev->av1->start_addr; - dmaaddr += (info->fix.line_length * dy); - /* TODO: Wait for current frame to finished */ - - fbdev->av1->start_addr = (unsigned long)dmaaddr; - fbdev->av2->start_addr = (unsigned long)dmaaddr + fbdev->line_len; - } - - return 0; - -} - -/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ -static int bfin_adv7393_fb_blank(int blank, struct fb_info *info) -{ - struct adv7393fb_device *fbdev = to_adv7393fb_device(info); - - switch (blank) { - - case VESA_NO_BLANKING: - /* Turn on panel */ - adv7393_mode(fbdev->client, BLANK_OFF); - break; - - case VESA_VSYNC_SUSPEND: - case VESA_HSYNC_SUSPEND: - case VESA_POWERDOWN: - /* Turn off panel */ - adv7393_mode(fbdev->client, BLANK_ON); - break; - - default: - return -EINVAL; - break; - } - return 0; -} - -int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - if (nocursor) - return 0; - else - return -EINVAL; /* just to force soft_cursor() call */ -} - -static int bfin_adv7393_fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES) - return -EINVAL; - - if (info->var.grayscale) - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 value; - /* Place color in the pseudopalette */ - if (regno > 16) - return -EINVAL; - - red >>= (16 - info->var.red.length); - green >>= (16 - info->var.green.length); - blue >>= (16 - info->var.blue.length); - - value = (red << info->var.red.offset) | - (green << info->var.green.offset)| - (blue << info->var.blue.offset); - value &= 0xFFFF; - - ((u32 *) (info->pseudo_palette))[regno] = value; - } - - return 0; -} - -static int bfin_adv7393_fb_remove(struct i2c_client *client) -{ - struct adv7393fb_device *fbdev = i2c_get_clientdata(client); - - adv7393_mode(client, POWER_DOWN); - - if (fbdev->fb_mem) - dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem, fbdev->dma_handle); - free_dma(CH_PPI); - free_irq(IRQ_PPI_ERROR, fbdev); - unregister_framebuffer(&fbdev->info); - remove_proc_entry("driver/adv7393", NULL); - fb_dealloc_cmap(&fbdev->info.cmap); - kfree(fbdev->info.pseudo_palette); - - if (ANOMALY_05000400) - gpio_free(P_IDENT(P_PPI0_FS3)); /* FS3 */ - peripheral_free_list(ppi_pins); - kfree(fbdev); - - return 0; -} - -#ifdef CONFIG_PM -static int bfin_adv7393_fb_suspend(struct device *dev) -{ - struct adv7393fb_device *fbdev = dev_get_drvdata(dev); - - if (fbdev->open) { - bfin_disable_dma(); - bfin_disable_ppi(); - dma_desc_list(fbdev, DESTRUCT); - } - adv7393_mode(fbdev->client, POWER_DOWN); - - return 0; -} - -static int bfin_adv7393_fb_resume(struct device *dev) -{ - struct adv7393fb_device *fbdev = dev_get_drvdata(dev); - - adv7393_mode(fbdev->client, POWER_ON); - - if (fbdev->open) { - dma_desc_list(fbdev, BUILD); - bfin_config_ppi(fbdev); - bfin_config_dma(fbdev); - bfin_enable_ppi(); - } - - return 0; -} - -static const struct dev_pm_ops bfin_adv7393_dev_pm_ops = { - .suspend = bfin_adv7393_fb_suspend, - .resume = bfin_adv7393_fb_resume, -}; -#endif - -static const struct i2c_device_id bfin_adv7393_id[] = { - {DRIVER_NAME, 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, bfin_adv7393_id); - -static struct i2c_driver bfin_adv7393_fb_driver = { - .driver = { - .name = DRIVER_NAME, -#ifdef CONFIG_PM - .pm = &bfin_adv7393_dev_pm_ops, -#endif - }, - .probe = bfin_adv7393_fb_probe, - .remove = bfin_adv7393_fb_remove, - .id_table = bfin_adv7393_id, -}; - -static int __init bfin_adv7393_fb_driver_init(void) -{ -#if IS_ENABLED(CONFIG_I2C_BLACKFIN_TWI) - request_module("i2c-bfin-twi"); -#else - request_module("i2c-gpio"); -#endif - - return i2c_add_driver(&bfin_adv7393_fb_driver); -} -module_init(bfin_adv7393_fb_driver_init); - -static void __exit bfin_adv7393_fb_driver_cleanup(void) -{ - i2c_del_driver(&bfin_adv7393_fb_driver); -} -module_exit(bfin_adv7393_fb_driver_cleanup); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); -MODULE_DESCRIPTION("Frame buffer driver for ADV7393/2 Video Encoder"); - -module_param(mode, int, 0); -MODULE_PARM_DESC(mode, - "Video Mode (0=NTSC,1=PAL,2=NTSC 640x480,3=PAL 640x480,4=NTSC YCbCr input,5=PAL YCbCr input)"); - -module_param(mem, int, 0); -MODULE_PARM_DESC(mem, - "Size of frame buffer memory 1=Single 2=Double Size (allows y-panning / frame stacking)"); - -module_param(nocursor, int, 0644); -MODULE_PARM_DESC(nocursor, "cursor enable/disable"); diff --git a/drivers/video/fbdev/bfin_adv7393fb.h b/drivers/video/fbdev/bfin_adv7393fb.h deleted file mode 100644 index afd0380e19e1..000000000000 --- a/drivers/video/fbdev/bfin_adv7393fb.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Frame buffer driver for ADV7393/2 video encoder - * - * Copyright 2006-2009 Analog Devices Inc. - * Licensed under the GPL-2 or late. - */ - -#ifndef __BFIN_ADV7393FB_H__ -#define __BFIN_ADV7393FB_H__ - -#define BFIN_LCD_NBR_PALETTE_ENTRIES 256 - -#ifdef CONFIG_NTSC -# define VMODE 0 -#endif -#ifdef CONFIG_PAL -# define VMODE 1 -#endif -#ifdef CONFIG_NTSC_640x480 -# define VMODE 2 -#endif -#ifdef CONFIG_PAL_640x480 -# define VMODE 3 -#endif -#ifdef CONFIG_NTSC_YCBCR -# define VMODE 4 -#endif -#ifdef CONFIG_PAL_YCBCR -# define VMODE 5 -#endif - -#ifndef VMODE -# define VMODE 1 -#endif - -#ifdef CONFIG_ADV7393_2XMEM -# define VMEM 2 -#else -# define VMEM 1 -#endif - -#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534) -# define DMA_CFG_VAL 0x7935 /* Set Sync Bit */ -# define VB_DUMMY_MEMORY_SOURCE L1_DATA_B_START -#else -# define DMA_CFG_VAL 0x7915 -# define VB_DUMMY_MEMORY_SOURCE BOOT_ROM_START -#endif - -enum { - DESTRUCT, - BUILD, -}; - -enum { - POWER_ON, - POWER_DOWN, - BLANK_ON, - BLANK_OFF, -}; - -struct adv7393fb_modes { - const s8 name[25]; /* Full name */ - u16 xres; /* Active Horizonzal Pixels */ - u16 yres; /* Active Vertical Pixels */ - u16 bpp; - u16 vmode; - u16 a_lines; /* Active Lines per Field */ - u16 vb1_lines; /* Vertical Blanking Field 1 Lines */ - u16 vb2_lines; /* Vertical Blanking Field 2 Lines */ - u16 tot_lines; /* Total Lines per Frame */ - u16 boeft_blank; /* Before Odd/Even Field Transition No. of Blank Pixels */ - u16 aoeft_blank; /* After Odd/Even Field Transition No. of Blank Pixels */ - const s8 *adv7393_i2c_initd; - u16 adv7393_i2c_initd_len; -}; - -static const u8 init_NTSC_TESTPATTERN[] = { - 0x00, 0x1E, /* Power up all DACs and PLL */ - 0x01, 0x00, /* SD-Only Mode */ - 0x80, 0x10, /* SSAF Luma Filter Enabled, NTSC Mode */ - 0x82, 0xCB, /* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */ - 0x84, 0x40, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */ -}; - -static const u8 init_NTSC[] = { - 0x00, 0x1E, /* Power up all DACs and PLL */ - 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */ - 0x8C, 0x1F, /* NTSC Subcarrier Frequency */ - 0x8D, 0x7C, /* NTSC Subcarrier Frequency */ - 0x8E, 0xF0, /* NTSC Subcarrier Frequency */ - 0x8F, 0x21, /* NTSC Subcarrier Frequency */ - 0x01, 0x00, /* SD-Only Mode */ - 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */ - 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */ - 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */ - 0x86, 0x82, - 0x8B, 0x11, - 0x88, 0x20, - 0x8A, 0x0d, -}; - -static const u8 init_PAL[] = { - 0x00, 0x1E, /* Power up all DACs and PLL */ - 0xC3, 0x26, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC5, 0x12, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC2, 0x4A, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xC6, 0x5E, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xBD, 0x19, /* Program RGB->YCrCb Color Space conversion matrix */ - 0xBF, 0x42, /* Program RGB->YCrCb Color Space conversion matrix */ - 0x8C, 0xCB, /* PAL Subcarrier Frequency */ - 0x8D, 0x8A, /* PAL Subcarrier Frequency */ - 0x8E, 0x09, /* PAL Subcarrier Frequency */ - 0x8F, 0x2A, /* PAL Subcarrier Frequency */ - 0x01, 0x00, /* SD-Only Mode */ - 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */ - 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */ - 0x87, 0x80, /* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */ - 0x86, 0x82, - 0x8B, 0x11, - 0x88, 0x20, - 0x8A, 0x0d, -}; - -static const u8 init_NTSC_YCbCr[] = { - 0x00, 0x1E, /* Power up all DACs and PLL */ - 0x8C, 0x1F, /* NTSC Subcarrier Frequency */ - 0x8D, 0x7C, /* NTSC Subcarrier Frequency */ - 0x8E, 0xF0, /* NTSC Subcarrier Frequency */ - 0x8F, 0x21, /* NTSC Subcarrier Frequency */ - 0x01, 0x00, /* SD-Only Mode */ - 0x80, 0x30, /* SSAF Luma Filter Enabled, NTSC Mode */ - 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */ - 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */ - 0x86, 0x82, - 0x8B, 0x11, - 0x88, 0x08, - 0x8A, 0x0d, -}; - -static const u8 init_PAL_YCbCr[] = { - 0x00, 0x1E, /* Power up all DACs and PLL */ - 0x8C, 0xCB, /* PAL Subcarrier Frequency */ - 0x8D, 0x8A, /* PAL Subcarrier Frequency */ - 0x8E, 0x09, /* PAL Subcarrier Frequency */ - 0x8F, 0x2A, /* PAL Subcarrier Frequency */ - 0x01, 0x00, /* SD-Only Mode */ - 0x80, 0x11, /* SSAF Luma Filter Enabled, PAL Mode */ - 0x82, 0x8B, /* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */ - 0x87, 0x00, /* DAC 2 = Luma, DAC 3 = Chroma */ - 0x86, 0x82, - 0x8B, 0x11, - 0x88, 0x08, - 0x8A, 0x0d, -}; - -static struct adv7393fb_modes known_modes[] = { - /* NTSC 720x480 CRT */ - { - .name = "NTSC 720x480", - .xres = 720, - .yres = 480, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 240, - .vb1_lines = 22, - .vb2_lines = 23, - .tot_lines = 525, - .boeft_blank = 16, - .aoeft_blank = 122, - .adv7393_i2c_initd = init_NTSC, - .adv7393_i2c_initd_len = sizeof(init_NTSC) - }, - /* PAL 720x480 CRT */ - { - .name = "PAL 720x576", - .xres = 720, - .yres = 576, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 288, - .vb1_lines = 24, - .vb2_lines = 25, - .tot_lines = 625, - .boeft_blank = 12, - .aoeft_blank = 132, - .adv7393_i2c_initd = init_PAL, - .adv7393_i2c_initd_len = sizeof(init_PAL) - }, - /* NTSC 640x480 CRT Experimental */ - { - .name = "NTSC 640x480", - .xres = 640, - .yres = 480, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 240, - .vb1_lines = 22, - .vb2_lines = 23, - .tot_lines = 525, - .boeft_blank = 16 + 40, - .aoeft_blank = 122 + 40, - .adv7393_i2c_initd = init_NTSC, - .adv7393_i2c_initd_len = sizeof(init_NTSC) - }, - /* PAL 640x480 CRT Experimental */ - { - .name = "PAL 640x480", - .xres = 640, - .yres = 480, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 288 - 20, - .vb1_lines = 24 + 20, - .vb2_lines = 25 + 20, - .tot_lines = 625, - .boeft_blank = 12 + 40, - .aoeft_blank = 132 + 40, - .adv7393_i2c_initd = init_PAL, - .adv7393_i2c_initd_len = sizeof(init_PAL) - }, - /* NTSC 720x480 YCbCR */ - { - .name = "NTSC 720x480 YCbCR", - .xres = 720, - .yres = 480, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 240, - .vb1_lines = 22, - .vb2_lines = 23, - .tot_lines = 525, - .boeft_blank = 16, - .aoeft_blank = 122, - .adv7393_i2c_initd = init_NTSC_YCbCr, - .adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr) - }, - /* PAL 720x480 CRT */ - { - .name = "PAL 720x576 YCbCR", - .xres = 720, - .yres = 576, - .bpp = 16, - .vmode = FB_VMODE_INTERLACED, - .a_lines = 288, - .vb1_lines = 24, - .vb2_lines = 25, - .tot_lines = 625, - .boeft_blank = 12, - .aoeft_blank = 132, - .adv7393_i2c_initd = init_PAL_YCbCr, - .adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr) - } -}; - -struct adv7393fb_regs { - -}; - -struct adv7393fb_device { - struct fb_info info; /* FB driver info record */ - - struct i2c_client *client; - - struct dmasg *descriptor_list_head; - struct dmasg *vb1; - struct dmasg *av1; - struct dmasg *vb2; - struct dmasg *av2; - - dma_addr_t dma_handle; - - struct fb_info bfin_adv7393_fb; - - struct adv7393fb_modes *modes; - - struct adv7393fb_regs *regs; /* Registers memory map */ - size_t regs_len; - size_t fb_len; - size_t line_len; - u16 open; - u16 *fb_mem; /* RGB Buffer */ - -}; - -#define to_adv7393fb_device(_info) \ - (_info ? container_of(_info, struct adv7393fb_device, info) : NULL); - -static int bfin_adv7393_fb_open(struct fb_info *info, int user); -static int bfin_adv7393_fb_release(struct fb_info *info, int user); -static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info); - -static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info); - -static int bfin_adv7393_fb_blank(int blank, struct fb_info *info); - -static void bfin_config_ppi(struct adv7393fb_device *fbdev); -static int bfin_config_dma(struct adv7393fb_device *fbdev); -static void bfin_disable_dma(void); -static void bfin_enable_ppi(void); -static void bfin_disable_ppi(void); - -static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value); -static inline int adv7393_read(struct i2c_client *client, u8 reg); -static int adv7393_write_block(struct i2c_client *client, const u8 *data, - unsigned int len); - -int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor); -static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int, - u_int, struct fb_info *info); - -#endif diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c index 5d6179ef0298..e04efb567b5c 100644 --- a/drivers/video/fbdev/s1d13xxxfb.c +++ b/drivers/video/fbdev/s1d13xxxfb.c @@ -96,18 +96,12 @@ static const struct fb_fix_screeninfo s1d13xxxfb_fix = { static inline u8 s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno) { -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3) - regno=((regno & 1) ? (regno & ~1L) : (regno + 1)); -#endif return readb(par->regs + regno); } static inline void s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value) { -#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI3) - regno=((regno & 1) ? (regno & ~1L) : (regno + 1)); -#endif writeb(value, par->regs + regno); } @@ -296,11 +290,7 @@ s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n", regno, pseudo_val); -#if defined(CONFIG_PLAT_MAPPI) - ((u32 *)info->pseudo_palette)[regno] = cpu_to_le16(pseudo_val); -#else ((u32 *)info->pseudo_palette)[regno] = pseudo_val; -#endif break; case FB_VISUAL_PSEUDOCOLOR: diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index 0037104d66ac..d1f6196c8b9a 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -27,16 +27,6 @@ config LOGO_LINUX_CLUT224 bool "Standard 224-color Linux logo" default y -config LOGO_BLACKFIN_VGA16 - bool "16-colour Blackfin Processor Linux logo" - depends on BLACKFIN - default y - -config LOGO_BLACKFIN_CLUT224 - bool "224-colour Blackfin Processor Linux logo" - depends on BLACKFIN - default y - config LOGO_DEC_CLUT224 bool "224-color Digital Equipment Corporation Linux logo" depends on MACH_DECSTATION || ALPHA @@ -77,9 +67,4 @@ config LOGO_SUPERH_CLUT224 depends on SUPERH default y -config LOGO_M32R_CLUT224 - bool "224-color M32R Linux logo" - depends on M32R - default y - endif # LOGO diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile index 6194373ee424..228a89b9bdd1 100644 --- a/drivers/video/logo/Makefile +++ b/drivers/video/logo/Makefile @@ -5,8 +5,6 @@ obj-$(CONFIG_LOGO) += logo.o obj-$(CONFIG_LOGO_LINUX_MONO) += logo_linux_mono.o obj-$(CONFIG_LOGO_LINUX_VGA16) += logo_linux_vga16.o obj-$(CONFIG_LOGO_LINUX_CLUT224) += logo_linux_clut224.o -obj-$(CONFIG_LOGO_BLACKFIN_CLUT224) += logo_blackfin_clut224.o -obj-$(CONFIG_LOGO_BLACKFIN_VGA16) += logo_blackfin_vga16.o obj-$(CONFIG_LOGO_DEC_CLUT224) += logo_dec_clut224.o obj-$(CONFIG_LOGO_MAC_CLUT224) += logo_mac_clut224.o obj-$(CONFIG_LOGO_PARISC_CLUT224) += logo_parisc_clut224.o @@ -15,7 +13,6 @@ obj-$(CONFIG_LOGO_SUN_CLUT224) += logo_sun_clut224.o obj-$(CONFIG_LOGO_SUPERH_MONO) += logo_superh_mono.o obj-$(CONFIG_LOGO_SUPERH_VGA16) += logo_superh_vga16.o obj-$(CONFIG_LOGO_SUPERH_CLUT224) += logo_superh_clut224.o -obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o obj-$(CONFIG_SPU_BASE) += logo_spe_clut224.o diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index 4d50bfd13e7c..36aa050f9a21 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -63,10 +63,6 @@ const struct linux_logo * __ref fb_find_logo(int depth) /* Generic Linux logo */ logo = &logo_linux_vga16; #endif -#ifdef CONFIG_LOGO_BLACKFIN_VGA16 - /* Blackfin processor logo */ - logo = &logo_blackfin_vga16; -#endif #ifdef CONFIG_LOGO_SUPERH_VGA16 /* SuperH Linux logo */ logo = &logo_superh_vga16; @@ -78,10 +74,6 @@ const struct linux_logo * __ref fb_find_logo(int depth) /* Generic Linux logo */ logo = &logo_linux_clut224; #endif -#ifdef CONFIG_LOGO_BLACKFIN_CLUT224 - /* Blackfin Linux logo */ - logo = &logo_blackfin_clut224; -#endif #ifdef CONFIG_LOGO_DEC_CLUT224 /* DEC Linux logo on MIPS/MIPS64 or ALPHA */ logo = &logo_dec_clut224; @@ -107,10 +99,6 @@ const struct linux_logo * __ref fb_find_logo(int depth) /* SuperH Linux logo */ logo = &logo_superh_clut224; #endif -#ifdef CONFIG_LOGO_M32R_CLUT224 - /* M32R Linux logo */ - logo = &logo_m32r_clut224; -#endif } return logo; } diff --git a/drivers/video/logo/logo_blackfin_clut224.ppm b/drivers/video/logo/logo_blackfin_clut224.ppm deleted file mode 100644 index dc9a50a14477..000000000000 --- a/drivers/video/logo/logo_blackfin_clut224.ppm +++ /dev/null @@ -1,1127 +0,0 @@ -P3 -# This was generated by the GIMP & Netpbm tools -# gimp linux_bf.svg (create 80x80 save as linux_bf.ppm) -# pnmquant 224 linux_bf.ppm | pnmnoraw > logo_blackfin_clut224.ppm -# -80 80 -255 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 3 3 3 4 6 6 6 6 6 4 6 6 3 3 3 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 2 2 2 10 10 10 26 26 27 -44 44 45 66 66 66 78 81 81 78 81 81 75 75 76 60 60 60 -39 39 39 20 20 20 6 6 6 1 1 1 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 2 2 2 14 14 14 47 47 47 84 84 84 75 75 76 -47 47 47 12 12 12 0 0 0 0 0 0 0 0 0 20 20 20 -53 54 54 81 81 82 74 74 74 31 31 31 6 6 6 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 4 4 34 34 35 84 84 84 60 60 60 4 4 4 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 17 18 18 75 75 76 66 66 66 17 18 18 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 -42 42 43 84 84 84 8 8 8 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 3 3 36 40 40 10 16 16 0 0 0 31 31 31 84 84 84 -29 29 30 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 26 27 27 -84 84 84 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -15 19 19 114 115 115 110 114 114 44 46 46 0 0 0 12 12 12 -90 87 86 24 24 24 1 1 1 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 75 75 76 -14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -30 40 40 133 133 133 129 130 130 78 85 85 23 31 30 0 0 0 -19 19 19 78 81 81 13 13 13 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 26 27 27 81 81 82 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -36 40 40 89 90 91 55 63 63 23 31 30 4 6 6 0 0 0 -0 0 0 60 60 60 47 47 47 2 2 2 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 2 2 2 53 54 54 34 34 35 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 10 10 7 9 9 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 84 84 84 13 13 13 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 4 6 6 78 81 81 2 2 2 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 65 64 64 36 36 36 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 11 11 81 81 82 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 12 12 12 67 70 70 4 4 4 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 16 16 16 81 81 82 0 0 0 -0 0 0 0 0 0 4 10 10 44 50 50 18 21 21 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 1 1 78 85 85 120 121 122 7 9 9 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 82 82 81 12 12 12 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 81 81 82 0 0 0 -0 0 0 2 2 2 8 8 8 55 63 63 108 110 110 52 58 58 -0 0 0 0 0 0 0 0 0 0 0 0 42 42 43 129 130 130 -140 142 143 114 115 115 110 114 114 129 130 130 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 75 75 76 24 24 24 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 74 74 74 0 0 0 -4 6 6 167 168 167 196 196 197 196 196 197 61 65 66 78 85 85 -0 0 0 0 0 0 0 0 0 118 118 118 202 202 203 219 219 219 -219 219 219 214 214 215 187 187 188 78 85 85 29 33 34 0 0 0 -0 0 0 0 0 0 0 0 0 60 60 60 39 39 39 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 72 71 71 0 0 0 -185 185 184 244 245 245 250 251 252 251 251 252 247 248 249 36 36 36 -0 0 0 0 0 0 13 13 13 243 243 241 252 252 252 253 253 253 -253 253 253 252 252 252 247 247 246 193 193 194 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 42 42 43 50 51 51 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 78 81 81 0 0 0 -247 247 246 193 193 194 95 97 97 193 193 194 255 255 255 237 237 238 -0 0 0 0 0 0 202 202 203 255 255 255 247 247 246 108 107 107 -82 85 86 167 168 167 255 255 255 248 248 249 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 34 34 35 56 56 56 2 2 2 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 78 81 81 0 0 0 -250 250 251 50 51 51 153 154 155 150 151 151 244 245 245 244 245 245 -44 50 50 84 89 89 153 154 155 255 255 255 140 142 143 0 0 0 -149 149 150 156 155 156 237 237 238 254 254 254 67 70 70 0 0 0 -0 0 0 0 0 0 0 0 0 39 39 39 47 47 47 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 19 19 19 81 81 82 0 0 0 -248 248 249 34 34 35 72 71 71 165 165 165 202 202 203 244 245 245 -10 16 16 82 85 86 89 90 91 255 255 255 95 97 97 0 0 0 -0 0 0 53 54 54 177 177 174 255 255 255 127 127 126 0 0 0 -0 0 0 0 0 0 0 0 0 39 39 39 36 36 36 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 14 14 14 78 81 81 0 0 0 -243 243 243 89 90 91 0 0 0 36 40 40 201 147 55 241 205 27 -241 205 27 241 205 27 241 205 27 238 192 33 108 110 110 0 0 0 -0 0 0 0 0 0 191 190 190 254 254 254 34 34 35 0 0 0 -0 0 0 0 0 0 0 0 0 42 42 43 42 42 43 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 75 75 76 0 0 0 -202 202 203 218 217 217 21 19 17 230 165 41 199 129 48 213 157 40 -244 212 23 243 206 27 180 121 62 243 206 27 244 209 25 226 179 40 -15 10 7 103 103 103 254 254 254 251 251 252 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 17 18 18 58 58 58 2 2 2 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 9 9 9 84 84 84 0 0 0 -0 0 0 226 226 219 213 157 40 244 209 25 245 211 23 245 211 23 -245 214 38 245 214 38 245 211 23 245 211 23 245 211 23 244 212 23 -244 212 23 241 205 27 226 179 40 196 196 197 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 4 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 7 7 7 84 84 84 0 0 0 -54 42 32 213 157 40 243 206 27 245 211 23 245 211 23 245 211 23 -245 215 41 245 214 35 245 211 23 245 211 23 245 214 35 245 215 41 -245 214 35 245 211 23 245 211 23 238 204 29 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 81 81 82 12 12 12 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 4 6 6 74 74 74 0 0 0 -201 147 55 241 205 27 245 211 23 245 211 23 245 211 23 245 213 29 -245 214 38 245 211 23 245 211 23 245 214 35 245 215 41 245 215 41 -245 213 29 142 83 36 142 83 36 244 209 25 1 1 1 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 25 25 26 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 4 4 4 72 71 71 6 6 6 -213 157 40 244 209 25 245 211 23 245 211 23 245 211 23 245 213 29 -244 212 23 245 211 23 245 214 35 245 215 41 245 215 41 245 213 29 -142 83 36 142 83 36 238 192 33 241 205 27 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 44 44 44 49 50 50 -2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 3 3 3 65 64 64 17 18 18 -199 129 48 199 129 48 245 211 23 245 211 23 245 211 23 245 211 23 -245 211 23 244 212 23 245 214 38 245 214 38 142 83 36 142 83 36 -142 83 36 245 211 23 244 210 23 230 165 41 0 0 0 0 0 0 -78 81 81 114 115 115 73 79 79 0 0 0 3 3 3 81 81 82 -9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 1 1 1 49 50 50 29 29 30 -90 87 86 199 129 48 173 101 51 173 101 51 245 211 23 245 211 23 -245 211 23 230 165 41 142 83 36 142 83 36 142 83 36 245 211 23 -244 210 23 241 205 27 230 165 41 175 173 165 3 3 3 0 0 0 -44 46 46 118 118 118 118 118 118 108 110 110 0 0 0 75 75 76 -28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 1 1 1 52 53 53 26 26 27 -118 118 118 175 173 165 199 129 48 173 101 51 173 101 51 173 101 51 -173 101 51 142 83 36 173 101 51 245 211 23 244 209 25 238 204 29 -213 157 40 214 196 166 227 227 227 214 214 215 120 121 122 0 0 0 -0 0 0 108 110 110 118 118 118 118 118 118 0 0 0 23 23 23 -66 66 66 4 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 7 7 7 75 75 76 4 4 4 -127 127 126 205 205 205 181 181 181 199 129 48 226 179 40 244 209 25 -244 209 25 244 209 25 243 206 27 238 192 33 213 157 40 187 166 103 -234 234 234 248 248 249 251 252 252 248 248 249 214 214 215 0 0 0 -0 0 0 0 0 0 103 103 103 100 103 103 0 0 0 0 0 0 -78 81 81 24 24 24 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 26 27 27 82 82 81 0 0 0 -146 146 147 234 234 234 222 221 221 178 178 179 180 121 62 213 157 40 -213 157 40 213 157 40 201 147 55 180 121 62 219 219 219 243 243 241 -253 253 253 255 255 255 255 255 255 255 255 255 250 250 251 120 121 122 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -20 20 20 72 71 71 8 8 8 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 10 10 10 75 75 76 22 22 22 0 0 0 -205 205 205 253 253 253 247 248 249 212 211 212 178 178 179 161 161 162 -165 165 165 181 181 181 205 205 205 227 227 227 244 245 245 254 254 254 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 239 239 240 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 67 70 70 39 39 39 2 2 2 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 4 4 4 50 51 51 60 60 60 0 0 0 16 16 16 -249 250 251 255 255 255 255 255 255 240 240 240 209 210 210 193 193 194 -200 200 197 212 211 212 231 231 231 246 247 248 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 253 253 253 -153 154 155 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 3 3 3 84 84 84 20 20 20 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 2 2 33 33 34 81 81 82 0 0 0 0 0 0 231 231 231 -255 255 255 255 255 255 255 255 255 253 253 253 234 234 234 222 221 221 -227 227 227 237 237 238 250 250 251 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -240 240 240 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 26 27 27 72 71 71 8 8 8 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 -21 21 22 84 84 84 7 7 7 0 0 0 150 151 151 252 252 252 -255 255 255 255 255 255 255 255 255 255 255 255 252 252 252 244 245 245 -246 247 248 253 253 253 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -251 251 252 9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 65 64 64 47 47 47 3 3 3 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 12 12 -75 75 76 26 26 27 0 0 0 1 1 1 239 239 240 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 202 202 203 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 84 84 84 28 28 29 -1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 55 55 55 -60 60 60 0 0 0 0 0 0 95 97 97 248 248 249 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 244 245 245 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 82 82 81 -15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 1 1 1 29 29 30 84 84 84 -0 0 0 0 0 0 0 0 0 156 155 156 247 247 246 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 247 247 246 240 240 240 232 232 233 232 232 233 -243 243 243 253 253 253 53 54 54 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 44 44 -60 60 60 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 10 10 10 81 81 82 14 14 14 -0 0 0 0 0 0 6 6 6 150 151 151 214 214 215 250 251 252 -255 255 255 255 255 255 255 255 255 246 247 248 218 217 217 214 214 215 -218 217 217 244 245 245 255 255 255 255 255 255 255 255 255 250 248 249 -232 232 233 214 214 215 196 196 197 182 183 184 181 181 181 181 181 181 -187 187 188 240 240 240 232 232 233 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -78 81 81 34 34 35 1 1 1 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 1 1 1 39 39 39 74 74 74 0 0 0 -0 0 0 0 0 0 60 60 60 161 161 162 200 200 197 229 229 230 -251 251 252 255 255 255 255 255 255 255 255 255 243 243 241 214 214 215 -248 248 249 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 -239 239 240 214 214 215 193 193 194 182 183 184 178 178 179 176 177 177 -176 177 177 182 183 184 248 248 249 14 14 14 0 0 0 61 65 66 -10 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 10 10 84 84 84 13 13 13 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 10 11 11 82 82 81 7 7 7 0 0 0 -0 0 0 0 0 0 165 165 165 229 229 230 249 250 251 254 254 254 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 253 253 253 240 240 240 227 227 227 205 205 205 -181 181 181 176 177 177 191 190 190 227 227 227 0 0 0 44 50 50 -84 89 89 61 65 66 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 58 58 58 49 50 50 3 3 3 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 36 36 36 66 66 66 0 0 0 29 33 34 -0 3 3 26 27 27 234 234 234 254 254 254 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -254 254 254 253 253 254 252 253 253 253 253 254 253 254 254 253 254 254 -254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 251 251 252 -227 227 227 187 187 188 176 177 177 222 221 221 13 13 13 0 0 0 -12 15 14 73 79 79 36 40 40 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 90 87 86 17 18 18 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 7 7 7 78 81 81 12 12 12 23 31 30 52 58 58 -0 0 0 209 210 210 253 253 253 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 -251 251 252 150 151 151 103 103 103 129 130 130 196 196 197 250 250 251 -252 252 253 254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 240 240 240 193 193 194 196 196 197 229 229 230 0 0 0 -0 0 0 4 10 10 30 40 40 0 3 3 0 0 0 0 0 0 -0 0 0 0 0 0 47 47 47 53 54 54 3 3 3 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 23 23 23 81 81 82 0 0 0 52 58 58 36 40 40 -42 42 43 250 250 251 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 -227 227 227 7 7 7 7 7 7 7 7 7 7 7 7 44 44 45 -156 155 156 249 250 251 253 253 253 254 254 254 255 255 255 255 255 255 -255 255 255 255 255 255 247 247 246 222 221 221 239 239 240 0 0 0 -30 40 40 44 50 50 23 31 30 29 33 34 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 90 87 86 16 16 16 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 2 2 50 51 51 42 42 43 29 33 34 52 58 58 0 0 0 -232 232 233 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 -250 251 252 44 44 44 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 56 56 56 209 210 210 252 252 253 254 254 254 255 255 255 -255 255 255 255 255 255 255 255 255 254 253 253 249 250 251 146 146 147 -36 40 40 44 50 50 36 40 40 67 70 70 61 65 66 0 0 0 -0 0 0 0 0 0 0 0 0 55 55 55 44 44 45 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 10 10 81 81 82 1 1 1 52 58 58 44 50 50 52 53 53 -251 251 252 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 -253 253 253 187 187 188 8 8 8 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 19 19 19 178 178 179 252 252 253 254 254 254 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 237 237 238 -10 16 16 30 40 40 0 3 3 23 31 30 84 89 89 0 0 0 -0 0 0 0 0 0 0 0 0 3 3 3 81 81 82 9 9 9 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -29 29 30 72 71 71 10 16 16 52 58 58 0 0 0 222 221 221 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -254 254 254 251 251 252 95 97 97 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 10 10 10 161 161 162 251 252 252 -254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 248 248 249 -0 0 0 0 0 0 0 0 0 0 0 0 84 89 89 0 3 3 -0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 26 27 27 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 -65 64 64 20 20 20 20 25 25 30 40 40 0 0 0 247 247 246 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 253 253 254 222 221 221 9 9 9 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 149 149 150 -252 252 253 254 254 254 255 255 255 255 255 255 255 255 255 252 252 252 -0 0 0 0 0 0 0 0 0 0 0 0 73 79 79 12 15 14 -0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 58 58 58 -3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 20 20 -74 74 74 0 0 0 4 10 10 4 10 10 36 36 36 252 252 252 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 227 227 227 253 253 253 255 255 255 -255 255 255 254 254 254 250 251 252 65 64 64 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 -146 146 147 251 252 252 254 254 254 255 255 255 255 255 255 253 254 254 -0 0 0 0 0 0 0 0 0 0 0 0 52 58 58 10 16 16 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 82 81 -9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 4 6 6 65 64 64 -25 25 25 0 3 3 30 40 40 0 0 0 187 187 188 254 254 254 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 193 193 194 253 252 252 255 255 255 -255 255 255 255 255 255 252 253 253 129 130 130 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -8 8 8 149 149 150 252 252 253 254 254 254 255 255 255 254 254 254 -52 53 53 0 0 0 0 0 0 0 0 0 20 25 25 2 5 4 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 81 82 -20 20 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 26 26 27 81 81 82 -0 0 0 18 21 21 73 79 79 0 0 0 237 237 238 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 182 183 184 255 255 255 255 255 255 -255 255 255 255 255 255 253 253 253 176 177 177 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 8 8 8 153 154 155 251 252 252 254 254 254 255 255 255 -150 151 151 0 0 0 0 0 0 0 0 0 20 25 25 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65 64 64 -33 33 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 6 6 6 67 70 70 20 20 20 -0 0 0 23 31 30 82 85 86 0 0 0 247 247 246 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 182 183 184 255 255 255 255 255 255 -255 255 255 255 255 255 253 254 254 214 214 215 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 8 8 8 156 155 156 252 252 253 254 254 254 -167 168 167 0 0 0 0 0 0 0 0 0 67 70 70 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 47 47 -44 44 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 21 21 22 75 75 76 0 0 0 -0 0 0 29 33 34 84 89 89 0 0 0 248 248 249 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 248 248 249 181 181 181 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 240 240 240 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 8 8 8 161 161 162 251 252 252 -185 185 184 4 4 4 0 0 0 10 11 11 100 103 103 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 -55 55 55 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 33 33 34 50 51 51 0 0 0 -0 0 0 9 11 11 82 85 86 10 16 16 248 248 249 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 245 244 245 179 180 181 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 251 252 252 20 20 20 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 10 10 10 161 161 162 -205 205 205 17 18 18 0 0 0 95 97 97 78 81 81 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 -53 54 54 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 31 31 31 58 58 58 0 0 0 -0 0 0 0 0 0 67 70 70 78 81 81 248 248 249 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 234 234 234 179 180 181 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 251 252 252 23 23 23 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -10 11 11 84 84 84 161 161 162 209 210 210 229 229 230 237 237 238 -202 202 203 26 26 27 9 11 11 44 50 50 0 0 0 4 6 6 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 52 53 53 -39 39 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 23 23 23 78 81 81 213 157 40 -243 206 27 243 206 27 54 42 32 73 79 79 222 221 221 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 238 238 236 178 178 179 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 251 252 253 36 36 36 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 84 84 84 -222 221 221 251 252 252 252 253 253 253 253 253 253 254 254 252 252 253 -146 146 147 140 142 143 156 155 156 110 114 114 26 27 27 82 85 86 -84 89 89 95 97 97 36 40 40 0 0 0 0 0 0 74 74 74 -23 23 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 14 14 14 -24 24 24 26 26 27 26 26 27 26 26 27 25 25 26 21 21 22 -7 7 7 0 0 0 1 1 1 34 34 35 238 192 33 244 210 23 -244 212 23 244 212 23 244 210 23 88 79 47 200 200 197 254 254 254 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 244 245 245 179 180 181 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 252 252 253 36 36 36 7 7 7 -7 7 7 7 7 7 7 7 7 8 8 8 149 149 150 251 251 252 -252 252 253 253 253 253 253 253 253 250 248 249 239 223 156 239 223 156 -120 121 122 182 183 184 176 177 177 120 121 122 33 33 34 3 3 3 -0 0 0 67 70 70 146 146 147 20 25 25 1 1 1 82 82 81 -9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 19 19 19 89 90 91 -146 146 147 150 151 151 150 151 151 150 151 151 150 151 151 129 130 130 -58 58 58 6 6 6 14 14 14 201 147 55 245 211 23 245 213 29 -245 214 35 245 215 41 245 213 29 244 210 23 142 83 36 232 232 233 -254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 185 185 184 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 251 252 252 50 51 51 7 7 7 -7 7 7 7 7 7 7 7 7 146 146 147 251 252 252 252 253 253 -251 252 253 239 239 240 171 168 154 129 130 130 137 136 134 175 173 165 -221 218 200 65 64 64 22 22 22 186 186 187 114 115 115 26 26 27 -2 2 2 0 0 0 61 65 66 31 33 27 238 192 33 108 96 91 -9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 2 2 2 52 53 53 178 178 179 -21 21 22 7 7 7 7 7 7 7 7 7 7 7 7 118 118 118 -137 136 134 36 36 36 65 64 64 243 206 27 244 212 23 245 215 41 -245 215 41 245 215 41 245 215 41 244 209 25 244 209 25 1 1 1 -219 219 219 253 253 253 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 214 214 215 255 255 255 255 255 255 -255 255 255 255 255 255 254 254 254 252 252 253 50 51 51 7 7 7 -7 7 7 7 7 7 84 84 84 250 251 252 252 253 253 251 251 252 -167 168 167 22 22 22 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 34 34 35 187 187 188 103 103 103 -29 29 30 3 3 3 7 9 9 238 204 29 245 215 41 245 214 35 -28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 7 7 7 90 87 86 178 178 179 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 16 16 16 -193 193 194 133 133 133 187 166 103 245 218 76 245 218 76 245 216 51 -245 216 51 245 218 76 246 224 96 245 218 76 245 218 76 245 218 76 -25 25 25 186 186 187 252 252 252 254 254 254 254 254 254 253 254 254 -254 254 254 254 254 254 254 254 254 246 247 248 254 254 254 253 254 254 -254 254 254 254 254 254 253 254 254 251 252 252 36 36 36 7 7 7 -7 7 7 20 20 20 229 229 230 253 253 253 252 253 253 178 178 179 -10 10 10 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 42 42 43 196 196 197 -118 118 118 33 33 34 238 204 29 245 215 41 245 215 41 245 215 41 -49 50 50 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 17 18 18 120 121 122 137 136 134 -7 7 7 7 7 7 34 34 35 20 20 20 7 7 7 7 7 7 -202 202 203 209 206 202 193 187 162 193 187 162 248 234 156 245 218 76 -245 218 76 248 234 156 193 187 162 193 187 162 193 187 162 214 196 166 -240 219 129 95 97 97 196 196 197 186 186 187 187 187 188 196 196 197 -252 252 253 251 252 253 212 211 212 187 187 188 196 196 197 251 252 252 -218 217 217 187 187 188 191 190 190 250 251 252 24 24 24 7 7 7 -7 7 7 110 114 114 252 252 253 253 254 254 250 251 252 89 90 91 -89 90 91 129 130 130 127 127 126 44 44 44 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 49 50 50 -202 202 203 214 196 166 245 216 51 245 214 38 245 214 35 245 214 38 -58 58 58 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 31 31 31 156 155 156 82 82 81 -7 7 7 10 10 10 237 237 238 66 66 66 7 7 7 25 25 25 -247 248 249 81 81 82 7 7 7 31 31 31 247 237 174 245 218 76 -246 226 108 200 200 197 7 7 7 7 7 7 7 7 7 137 136 134 -247 237 174 193 193 194 72 71 71 7 7 7 7 7 7 8 8 8 -196 196 197 250 251 252 67 70 70 7 7 7 84 84 84 244 245 245 -47 47 47 7 7 7 118 118 118 249 250 251 12 12 12 7 7 7 -9 9 9 218 217 217 253 253 253 254 254 254 252 253 253 251 251 252 -249 250 251 237 237 238 95 97 97 9 9 9 15 15 15 95 97 97 -47 47 47 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -66 66 66 240 230 197 246 226 108 245 214 38 245 211 23 244 212 23 -65 64 64 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 2 2 2 52 53 53 185 185 184 25 25 25 -7 7 7 60 60 60 240 240 240 14 14 14 7 7 7 84 84 84 -247 248 249 23 23 23 7 7 7 94 91 88 248 234 156 245 218 76 -248 234 156 127 127 126 7 7 7 7 7 7 7 7 7 167 168 167 -251 248 240 65 64 64 7 7 7 7 7 7 7 7 7 7 7 7 -84 84 84 243 243 243 15 15 15 7 7 7 140 142 143 146 146 147 -7 7 7 33 33 34 237 237 238 243 243 243 21 21 22 120 121 122 -218 217 217 252 252 253 254 254 254 253 253 254 252 253 253 251 252 252 -247 248 249 72 71 71 7 7 7 58 58 58 222 221 221 248 248 249 -75 75 76 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 82 82 81 246 239 193 246 226 108 245 216 51 245 214 38 -238 192 33 21 21 22 1 1 1 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 8 8 8 90 87 86 182 183 184 7 7 7 -7 7 7 120 121 122 187 187 188 7 7 7 7 7 7 146 146 147 -205 205 205 7 7 7 7 7 7 153 153 148 240 219 129 246 224 96 -246 239 193 39 39 39 60 60 60 108 110 110 7 7 7 202 202 203 -227 227 227 7 7 7 7 7 7 205 205 205 89 90 91 7 7 7 -120 121 122 193 193 194 7 7 7 7 7 7 186 186 187 25 25 25 -7 7 7 167 168 167 251 251 252 243 243 243 214 214 215 250 251 252 -251 252 253 254 254 254 253 253 253 219 219 219 140 140 139 140 140 139 -118 118 118 7 7 7 52 53 53 237 237 238 247 247 246 176 177 177 -8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 95 97 97 246 239 193 246 226 108 245 216 51 -245 214 38 201 147 55 31 31 31 103 103 103 103 103 103 72 71 71 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 17 18 18 127 127 126 140 140 139 7 7 7 -7 7 7 17 18 18 17 18 18 7 7 7 95 97 97 244 245 245 -146 146 147 7 7 7 7 7 7 200 200 197 246 226 108 240 219 129 -194 194 184 7 7 7 140 140 139 89 90 91 7 7 7 232 232 233 -165 165 165 7 7 7 31 31 31 249 250 251 39 39 39 7 7 7 -176 177 177 133 133 133 7 7 7 22 22 22 108 110 110 7 7 7 -72 71 71 251 252 252 252 253 253 250 251 252 247 248 249 205 205 205 -251 252 253 254 254 254 252 252 253 84 84 84 7 7 7 7 7 7 -7 7 7 7 7 7 140 142 143 247 248 249 140 140 139 14 14 14 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 16 16 16 -14 14 14 7 7 7 7 7 7 114 115 115 246 239 193 246 224 96 -245 216 51 245 216 51 243 235 220 176 177 177 185 185 184 229 229 230 -47 47 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 31 31 31 156 155 156 90 87 86 7 7 7 -7 7 7 7 7 7 7 7 7 31 31 31 243 243 241 247 247 246 -84 84 84 7 7 7 26 27 27 246 239 193 246 226 108 248 234 156 -108 110 110 7 7 7 212 211 212 44 44 44 22 22 22 249 250 251 -108 107 107 7 7 7 89 90 91 238 238 236 114 115 115 118 118 118 -231 231 231 75 75 76 7 7 7 34 34 35 10 11 11 12 12 12 -214 214 215 253 253 253 253 253 253 200 200 197 31 31 31 103 103 103 -252 252 253 252 253 253 218 217 217 9 9 9 7 7 7 7 7 7 -7 7 7 7 7 7 25 25 25 39 39 39 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 103 103 103 234 234 234 -181 181 181 7 7 7 7 7 7 7 7 7 133 133 133 247 237 174 -246 224 96 246 226 108 185 185 184 177 177 174 153 154 155 181 181 181 -140 140 139 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 1 1 1 49 50 50 186 186 187 28 28 28 7 7 7 -12 12 12 22 22 22 7 7 7 7 7 7 108 107 107 247 247 246 -25 25 25 7 7 7 90 87 86 247 237 174 246 226 108 246 239 193 -28 28 28 44 44 44 237 237 238 9 9 9 53 54 54 249 250 251 -49 50 50 7 7 7 153 153 148 249 241 199 214 196 166 185 185 184 -229 229 230 19 19 19 7 7 7 7 7 7 7 7 7 103 103 103 -251 252 253 254 254 254 253 253 253 150 151 151 7 7 7 187 187 188 -252 252 253 251 251 252 103 103 103 7 7 7 7 7 7 7 7 7 -7 7 7 23 23 23 17 18 18 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 12 12 12 153 153 148 246 239 193 249 241 199 -161 161 162 9 9 9 84 84 84 108 110 110 25 25 25 153 153 148 -247 237 174 246 224 96 218 217 217 165 165 165 182 183 184 193 193 194 -114 115 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 4 4 4 74 74 74 181 181 181 7 7 7 7 7 7 -110 114 114 200 200 197 7 7 7 7 7 7 60 60 60 209 210 210 -7 7 7 7 7 7 146 146 147 248 234 156 248 234 156 177 177 174 -7 7 7 118 118 118 193 193 194 7 7 7 84 84 84 232 232 233 -8 8 8 7 7 7 209 210 210 221 218 200 193 187 162 219 219 219 -200 200 197 7 7 7 7 7 7 7 7 7 7 7 7 95 97 97 -251 252 252 254 254 254 252 253 253 118 118 118 29 29 30 247 248 249 -252 252 253 227 227 227 16 16 16 7 7 7 7 7 7 7 7 7 -100 103 103 218 217 217 219 218 214 7 7 7 7 7 7 7 7 7 -7 7 7 21 21 22 185 185 184 246 239 193 248 234 156 240 230 197 -60 60 60 194 194 184 246 239 193 249 241 199 137 136 134 10 10 10 -171 168 154 248 234 156 248 234 156 226 226 219 209 210 210 249 241 199 -28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 13 13 13 108 110 110 146 146 147 7 7 7 7 7 7 -167 168 167 140 140 139 7 7 7 7 7 7 120 121 122 146 146 147 -7 7 7 7 7 7 194 194 184 240 219 129 247 237 174 95 97 97 -7 7 7 95 97 97 90 87 86 7 7 7 118 118 118 176 177 177 -7 7 7 28 28 28 248 248 249 44 44 45 7 7 7 167 168 167 -140 140 139 7 7 7 36 36 36 74 74 74 7 7 7 65 64 64 -251 252 253 254 254 254 251 252 252 81 81 82 108 110 110 251 252 252 -251 251 252 127 127 126 7 7 7 7 7 7 8 8 8 140 140 139 -181 181 181 140 140 139 221 218 200 7 7 7 7 7 7 7 7 7 -34 34 35 209 210 210 231 231 231 246 239 193 247 237 174 194 194 184 -227 227 227 249 241 199 240 219 129 248 234 156 153 153 148 7 7 7 -13 13 13 185 185 184 248 234 156 245 218 76 245 216 51 245 214 38 -31 31 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 31 31 31 153 154 155 89 90 91 7 7 7 8 8 8 -232 232 233 82 82 81 7 7 7 7 7 7 179 180 181 89 90 91 -7 7 7 24 24 24 243 235 220 248 234 156 240 230 197 20 20 20 -7 7 7 7 7 7 7 7 7 7 7 7 149 149 150 118 118 118 -7 7 7 90 87 86 229 229 230 7 7 7 7 7 7 229 229 230 -82 82 81 7 7 7 95 97 97 100 103 103 7 7 7 34 34 35 -251 252 252 253 253 254 251 251 252 47 47 47 193 193 194 251 252 252 -239 239 240 23 23 23 7 7 7 13 13 13 165 165 165 234 234 234 -149 149 150 146 114 101 200 200 197 7 7 7 7 7 7 52 53 53 -227 227 227 167 168 167 16 16 16 214 196 166 248 234 156 243 235 220 -219 219 219 156 155 156 247 237 174 246 239 193 75 75 76 7 7 7 -60 60 60 227 227 227 243 235 220 240 219 129 245 218 76 245 213 29 -16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -1 1 1 49 50 50 185 185 184 33 33 34 7 7 7 10 11 11 -56 56 56 16 16 16 7 7 7 10 10 10 237 237 238 26 27 27 -7 7 7 55 55 55 185 185 184 221 218 200 167 168 167 7 7 7 -20 20 20 39 39 39 10 11 11 7 7 7 181 181 181 58 58 58 -7 7 7 103 103 103 133 133 133 7 7 7 44 44 44 247 248 249 -24 24 24 7 7 7 156 155 156 129 130 130 7 7 7 9 9 9 -244 245 245 252 253 253 237 237 238 34 34 35 248 248 249 251 251 252 -161 161 162 7 7 7 24 24 24 187 187 188 212 211 212 67 70 70 -187 187 188 173 170 143 209 206 202 10 10 10 95 97 97 237 237 238 -129 130 130 8 8 8 89 90 91 246 239 193 247 237 174 177 177 174 -17 18 18 137 136 134 249 241 199 219 218 214 10 10 10 95 97 97 -243 243 243 150 151 151 31 31 31 221 218 200 240 219 129 53 54 54 -3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -4 4 4 72 71 71 182 183 184 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 12 12 12 161 161 162 209 210 210 7 7 7 -7 7 7 7 7 7 7 7 7 187 187 188 82 82 81 7 7 7 -146 146 147 247 248 249 17 18 18 7 7 7 212 211 212 47 47 47 -7 7 7 7 7 7 7 7 7 8 8 8 146 146 147 205 205 205 -7 7 7 7 7 7 214 214 215 156 155 156 7 7 7 7 7 7 -218 217 217 251 252 252 186 186 187 110 114 114 249 250 251 248 248 249 -75 75 76 34 34 35 205 205 205 129 130 130 16 16 16 7 7 7 -156 155 156 214 196 166 240 230 197 243 243 241 227 227 227 74 74 74 -7 7 7 29 29 30 226 226 219 249 241 199 175 173 165 14 14 14 -9 9 9 221 218 200 246 239 193 153 153 148 146 146 147 246 247 248 -110 114 114 7 7 7 7 7 7 42 42 43 193 193 194 95 97 97 -19 19 19 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -6 6 6 84 84 84 140 142 143 7 7 7 7 7 7 7 7 7 -7 7 7 20 20 20 177 177 174 249 241 199 149 149 150 7 7 7 -7 7 7 7 7 7 10 11 11 226 226 219 13 13 13 8 8 8 -219 218 214 219 218 214 7 7 7 8 8 8 238 238 236 200 200 197 -13 13 13 7 7 7 13 13 13 161 161 162 243 235 220 146 146 147 -7 7 7 29 29 30 232 232 233 176 177 177 7 7 7 7 7 7 -182 183 184 237 237 238 129 130 130 167 168 167 176 177 177 202 202 203 -10 11 11 95 97 97 44 44 45 7 7 7 7 7 7 7 7 7 -75 75 76 226 226 219 243 235 220 156 155 156 24 24 24 7 7 7 -7 7 7 176 177 177 247 247 246 200 200 197 17 18 18 7 7 7 -49 50 50 246 239 193 248 234 156 251 248 240 239 239 240 84 84 84 -7 7 7 7 7 7 7 7 7 7 7 7 60 60 60 187 187 188 -84 84 84 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -4 4 4 53 54 54 137 136 134 156 155 156 161 161 162 161 161 162 -167 168 167 239 223 156 240 219 129 246 226 108 239 223 156 239 223 156 -239 223 156 239 223 156 214 196 166 239 223 156 193 187 162 193 187 162 -248 234 156 239 223 156 193 187 162 193 187 162 248 234 156 248 234 156 -214 196 166 193 187 162 214 196 166 248 234 156 240 219 129 214 196 166 -193 187 162 193 187 162 171 168 154 146 146 147 137 136 134 137 136 134 -161 161 162 209 210 210 65 64 64 202 202 203 179 180 181 140 140 139 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 60 60 60 39 39 39 7 7 7 7 7 7 7 7 7 -66 66 66 249 250 251 202 202 203 16 16 16 7 7 7 7 7 7 -23 23 23 243 235 220 246 239 193 226 226 219 52 53 53 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 75 75 76 -176 177 177 66 66 66 9 9 9 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 10 10 10 28 28 29 34 34 35 36 36 36 36 36 36 -44 44 45 146 114 101 241 207 50 241 207 50 241 207 50 241 211 63 -241 211 63 241 211 63 241 211 63 241 211 63 241 211 63 245 216 51 -245 216 51 245 216 51 241 211 63 241 211 63 245 216 51 241 211 63 -245 218 76 245 218 76 245 216 51 245 215 41 245 214 38 241 207 50 -241 211 63 201 147 55 88 79 47 29 29 30 34 34 35 42 42 43 -103 103 103 191 190 190 75 75 76 196 196 197 200 200 197 65 64 64 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -90 87 86 146 146 147 19 19 19 7 7 7 7 7 7 7 7 7 -7 7 7 90 87 86 140 140 139 31 31 31 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -103 103 103 161 161 162 53 54 54 7 7 7 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 12 12 12 50 51 51 146 114 101 180 121 62 199 129 48 -201 147 55 213 157 40 213 157 40 230 165 41 226 179 40 226 179 40 -238 192 33 241 205 27 244 209 25 244 210 23 244 212 23 245 211 23 -245 211 23 245 211 23 245 211 23 244 209 25 238 204 29 226 179 40 -213 157 40 199 129 48 54 42 32 0 0 0 4 6 6 44 44 45 -150 151 151 129 130 130 137 136 134 205 205 205 202 202 203 8 8 8 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 129 130 130 146 146 147 47 47 47 4 4 4 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 2 2 2 12 12 12 28 28 29 49 50 50 -74 74 74 108 96 91 180 121 62 180 121 62 199 129 48 201 147 55 -213 157 40 230 165 41 226 179 40 238 192 33 241 205 27 241 205 27 -243 206 27 243 206 27 241 205 27 238 204 29 226 179 40 213 157 40 -199 129 48 199 129 48 21 19 17 65 64 64 103 103 103 167 168 167 -202 202 203 24 24 24 193 193 194 229 229 230 140 140 139 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 8 8 8 156 155 156 133 133 133 36 36 36 3 3 3 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 -4 4 4 10 11 11 21 21 22 39 39 39 60 60 60 108 96 91 -180 121 62 199 129 48 199 129 48 213 157 40 230 165 41 226 179 40 -226 179 40 226 179 40 226 179 40 226 179 40 213 157 40 199 129 48 -180 121 62 99 91 79 72 71 71 56 56 56 129 130 130 167 168 167 -21 21 22 17 18 18 231 231 231 229 229 230 52 53 53 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 13 13 13 176 177 177 120 121 122 33 33 34 -2 2 2 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 8 8 8 -21 21 22 47 47 47 99 91 79 180 121 62 199 129 48 199 129 48 -201 147 55 213 157 40 213 157 40 201 147 55 199 129 48 180 121 62 -99 91 79 26 26 27 9 9 9 60 60 60 186 186 187 31 31 31 -7 7 7 60 60 60 243 243 243 209 210 210 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 -7 7 7 7 7 7 7 7 7 26 27 27 193 193 194 108 110 110 -22 22 22 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 1 1 1 8 8 8 24 24 24 58 58 58 108 96 91 -180 121 62 180 121 62 180 121 62 180 121 62 180 121 62 72 71 71 -15 15 15 0 0 0 4 6 6 75 75 76 156 155 156 24 24 24 -24 24 24 108 107 107 232 232 233 137 136 134 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 -24 24 24 24 24 24 24 24 24 24 24 24 58 58 58 176 177 177 -60 60 60 3 3 3 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 12 12 12 -26 27 27 44 44 44 55 55 55 50 51 51 29 29 30 8 8 8 -0 0 0 0 0 0 3 3 3 47 47 47 127 127 126 150 151 151 -150 151 151 140 142 143 129 130 130 140 142 143 150 151 151 150 151 151 -150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 -150 151 151 150 151 151 153 154 155 161 161 162 165 165 165 167 168 167 -177 177 174 167 168 167 161 161 162 156 155 156 150 151 151 150 151 151 -150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 -150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 -150 151 151 150 151 151 150 151 151 150 151 151 149 149 150 127 127 126 -44 44 45 2 2 2 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 2 2 2 1 1 1 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 7 7 7 21 21 22 25 25 26 -25 25 26 24 24 24 20 20 20 23 23 24 25 25 26 26 26 27 -26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 -26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 27 27 -28 28 29 26 27 27 26 26 27 26 26 27 26 26 27 26 26 27 -26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 -26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 -26 26 27 26 26 27 26 26 27 26 26 27 25 25 26 21 21 22 -7 7 7 0 0 0 diff --git a/drivers/video/logo/logo_blackfin_vga16.ppm b/drivers/video/logo/logo_blackfin_vga16.ppm deleted file mode 100644 index 1352b02a9d93..000000000000 --- a/drivers/video/logo/logo_blackfin_vga16.ppm +++ /dev/null @@ -1,1127 +0,0 @@ -P3 -# This was generated by the GIMP & Netpbm tools -# gimp linux_bf.svg (create 80x80 save as linux_bf.ppm) -# ppmquant -mapfile clut_vga16.ppm linux_bf.ppm | pnmnoraw > logo_blackfin_vga16.ppm -# -80 80 -255 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -170 170 170 85 85 85 85 85 85 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 -0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 -0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -255 255 255 170 170 170 85 85 85 170 170 170 255 255 255 255 255 255 -0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 85 85 85 -85 85 85 170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -255 255 255 85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 -85 85 85 85 85 85 170 170 170 255 255 255 170 170 170 0 0 0 -170 170 170 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -255 255 255 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 -0 0 0 85 85 85 85 85 85 255 255 255 85 85 85 0 0 0 -0 0 0 85 85 85 170 170 170 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 255 85 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 85 85 85 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 170 170 255 255 255 0 0 0 255 85 85 170 85 0 170 85 0 -255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 -0 0 0 85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 255 255 255 255 85 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 170 85 0 85 85 85 255 255 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -170 85 0 85 85 85 255 255 85 255 255 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 85 0 170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 -170 85 0 255 255 85 255 255 85 255 85 85 0 0 0 0 0 0 -85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -85 85 85 170 85 0 170 85 0 170 85 0 255 255 85 255 255 85 -255 255 85 255 85 85 170 85 0 170 85 0 170 85 0 255 255 85 -255 255 85 255 255 85 255 85 85 170 170 170 0 0 0 0 0 0 -85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -85 85 85 170 170 170 170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 255 255 85 255 255 85 255 255 85 -255 85 85 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 170 170 170 170 170 170 170 170 170 85 0 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -170 170 170 255 255 255 255 255 255 170 170 170 170 85 0 255 85 85 -255 85 85 255 85 85 255 85 85 255 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -85 85 85 0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 170 170 170 255 255 255 0 0 0 85 85 85 -85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 -0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 85 85 85 170 170 170 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 -0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 -0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 -170 170 170 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 255 255 85 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 -85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 -85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -85 85 85 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 85 85 85 0 0 0 170 170 170 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 0 0 0 255 255 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -170 170 170 0 0 0 85 85 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 255 255 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 -0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 -85 85 85 0 0 0 255 255 85 255 255 85 255 255 85 255 255 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 -255 255 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 -255 255 85 85 85 85 170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 -0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 -85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 255 255 255 85 85 85 0 0 0 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 255 255 255 255 255 85 -255 255 85 170 170 170 0 0 0 0 0 0 0 0 0 170 170 170 -255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 85 85 85 0 0 0 85 85 85 255 255 255 -85 85 85 0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 -0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 85 85 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 255 255 255 255 255 85 255 255 85 255 255 85 255 255 85 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 -0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 85 85 85 -255 255 255 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 -255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 -255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 255 255 255 0 0 0 0 0 0 170 170 170 170 170 170 -0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 85 85 85 0 0 0 85 85 85 255 255 255 255 255 255 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 255 255 255 255 255 85 255 255 85 255 255 85 -255 255 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 170 170 170 -170 170 170 0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 -255 255 255 0 0 0 85 85 85 85 85 85 0 0 0 170 170 170 -255 255 255 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 -85 85 85 170 170 170 0 0 0 0 0 0 170 170 170 0 0 0 -0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 -85 85 85 0 0 0 85 85 85 255 255 255 255 255 255 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 255 255 255 255 255 85 255 255 85 -255 255 85 170 85 0 0 0 0 85 85 85 85 85 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 -170 170 170 0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 -170 170 170 0 0 0 170 170 170 85 85 85 0 0 0 255 255 255 -170 170 170 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 -170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 -85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 -255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 255 255 85 -255 255 85 255 255 85 255 255 255 170 170 170 170 170 170 255 255 255 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 -85 85 85 0 0 0 0 0 0 255 255 255 255 255 85 255 255 85 -85 85 85 0 0 0 255 255 255 85 85 85 0 0 0 255 255 255 -85 85 85 0 0 0 85 85 85 255 255 255 85 85 85 85 85 85 -255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -255 255 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 -0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 255 255 255 -0 0 0 85 85 85 255 255 255 0 0 0 85 85 85 255 255 255 -85 85 85 0 0 0 170 170 170 255 255 255 170 170 170 170 170 170 -255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 170 170 170 -255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 -170 170 170 0 0 0 85 85 85 85 85 85 0 0 0 170 170 170 -255 255 85 255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 -85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 170 170 170 -0 0 0 85 85 85 170 170 170 0 0 0 85 85 85 255 255 255 -0 0 0 0 0 0 170 170 170 170 170 170 170 170 170 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 255 255 255 -255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 255 255 85 255 255 255 -85 85 85 170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 -170 170 170 255 255 85 255 255 85 255 255 255 170 170 170 255 255 255 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 -170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 170 170 170 255 255 85 255 255 255 85 85 85 -0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 170 170 170 -0 0 0 0 0 0 255 255 255 85 85 85 0 0 0 170 170 170 -170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 85 85 85 85 85 85 255 255 255 -255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 -170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 0 0 0 -0 0 0 170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 -255 255 255 255 255 255 255 255 85 255 255 85 170 170 170 0 0 0 -0 0 0 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 255 255 255 255 255 85 255 255 255 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 255 255 255 -85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 85 85 85 170 170 170 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 -170 170 170 85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 -255 255 255 170 170 170 0 0 0 170 170 170 255 255 85 255 255 255 -255 255 255 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 -85 85 85 255 255 255 255 255 255 255 255 85 255 255 85 255 255 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 -85 85 85 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 -0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 85 85 85 170 170 170 0 0 0 85 85 85 255 255 255 -0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 0 0 0 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 170 170 170 255 255 255 85 85 85 -170 170 170 170 170 170 170 170 170 0 0 0 85 85 85 255 255 255 -170 170 170 0 0 0 85 85 85 255 255 255 255 255 85 170 170 170 -0 0 0 170 170 170 255 255 255 255 255 255 0 0 0 85 85 85 -255 255 255 170 170 170 0 0 0 170 170 170 255 255 85 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 -170 170 170 255 255 255 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 -0 0 0 0 0 0 255 255 255 170 170 170 0 0 0 0 0 0 -255 255 255 255 255 255 170 170 170 85 85 85 255 255 255 255 255 255 -85 85 85 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 -170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 -0 0 0 0 0 0 255 255 255 255 255 255 170 170 170 0 0 0 -0 0 0 170 170 170 255 255 255 170 170 170 170 170 170 255 255 255 -85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 -255 255 255 255 255 255 0 0 0 0 0 0 255 255 255 170 170 170 -0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 -0 0 0 0 0 0 255 255 255 170 170 170 0 0 0 0 0 0 -170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 -0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -85 85 85 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 -85 85 85 255 255 255 255 255 85 255 255 255 255 255 255 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 -170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 85 85 85 170 170 170 170 170 170 170 170 170 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 -0 0 0 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 85 85 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 85 85 85 85 85 0 0 0 0 0 0 0 0 0 -85 85 85 170 170 170 85 85 85 170 170 170 170 170 170 85 85 85 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 170 85 0 -170 85 0 255 85 85 255 85 85 255 85 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 85 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 -85 85 85 85 85 85 170 85 0 170 85 0 170 85 0 170 85 0 -255 85 85 255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 -170 85 0 170 85 0 0 0 0 85 85 85 85 85 85 170 170 170 -170 170 170 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 -170 85 0 170 85 0 170 85 0 255 85 85 255 85 85 255 255 85 -255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 170 85 0 -170 85 0 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 -0 0 0 0 0 0 255 255 255 255 255 255 85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 170 85 0 170 85 0 170 85 0 -170 85 0 255 85 85 255 85 85 255 85 85 170 85 0 170 85 0 -85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 -0 0 0 85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 -0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 -170 85 0 170 85 0 170 85 0 170 85 0 170 85 0 85 85 85 -0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 -0 0 0 85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 -85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 -85 85 85 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 diff --git a/drivers/video/logo/logo_m32r_clut224.ppm b/drivers/video/logo/logo_m32r_clut224.ppm deleted file mode 100644 index 8b2983c5a0bd..000000000000 --- a/drivers/video/logo/logo_m32r_clut224.ppm +++ /dev/null @@ -1,1292 +0,0 @@ -P3 -# CREATOR: The GIMP's PNM Filter Version 1.0 -# -# Note: how to convert ppm to pnm(ascii). -# $ convert -posterize 224 m32r.ppm - | pnm2asc -f5 >logo_m32r_clut224.ppm -# -# convert - imagemagick: /usr/bin/convert -# pnm2asc - pnm to ascii-pnm format converter -# http://www.is.aist.go.jp/etlcdb/util/p2a.htm#English - -80 80 -255 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 43 43 43 75 75 75 27 27 27 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 59 59 59 123 123 123 67 67 67 27 27 27 - 2 2 3 2 2 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 10 6 3 59 59 59 80 80 80 43 43 43 27 27 27 - 2 2 3 2 2 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 19 19 19 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 2 2 3 10 6 3 10 6 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 10 6 3 11 11 11 11 11 11 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 2 2 3 2 2 3 27 27 27 10 6 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 19 19 19 2 2 3 2 2 3 51 51 51 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 123 123 123 196 196 196 115 115 115 2 2 3 - 2 2 3 2 2 3 2 2 3 75 75 75 141 141 140 - 172 172 172 196 196 196 190 189 188 2 2 3 11 11 11 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 27 27 27 164 164 164 228 228 228 221 221 220 10 6 3 - 2 2 3 2 2 3 2 2 3 172 172 172 245 245 245 - 254 254 252 254 254 252 221 221 220 35 35 35 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 164 164 164 228 228 228 35 35 35 236 236 236 236 236 236 - 2 2 3 11 11 11 2 2 3 254 254 252 245 245 245 - 2 2 3 75 75 75 245 245 245 245 245 245 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 212 212 212 2 2 3 51 51 51 11 11 11 245 245 245 - 27 27 27 80 80 80 10 6 3 254 254 252 2 2 3 - 2 2 3 91 91 91 19 19 19 254 254 252 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 196 196 196 10 6 3 2 2 3 11 11 11 107 107 107 - 49 35 5 57 42 11 31 22 3 236 236 236 2 2 3 - 2 2 3 2 2 3 2 2 3 254 254 252 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 107 107 107 221 221 220 2 2 3 64 43 7 194 148 10 - 236 188 10 225 180 10 170 126 10 236 188 10 94 86 67 - 2 2 3 2 2 3 204 204 204 236 236 236 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 228 228 228 182 126 10 218 164 9 236 188 10 - 236 188 10 237 204 14 236 205 40 246 214 48 246 214 48 - 245 189 11 209 156 9 196 196 196 11 11 11 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 165 114 10 207 148 7 229 172 9 236 180 10 - 236 196 11 237 204 14 242 218 43 246 218 75 246 218 19 - 246 213 13 246 218 19 244 205 11 218 164 9 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 164 109 5 192 133 7 224 165 9 236 180 10 236 188 10 - 236 196 11 241 212 42 246 218 75 246 218 19 246 218 19 - 246 218 19 236 196 11 150 114 10 229 172 9 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 165 114 10 201 142 7 229 172 9 242 182 11 236 188 10 - 237 204 14 245 213 67 246 218 19 246 213 13 246 213 13 - 154 119 10 207 148 7 218 164 9 216 156 8 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 120 78 3 225 180 10 245 189 11 236 205 40 - 241 212 42 241 212 17 237 204 14 148 107 9 182 126 10 - 216 156 8 218 164 9 207 148 7 82 70 43 2 2 3 - 2 2 3 123 123 123 35 35 35 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 10 6 3 180 180 180 156 102 5 135 88 5 142 106 7 - 126 98 11 165 114 10 185 132 9 207 148 7 215 150 13 - 199 140 8 188 148 71 196 196 196 190 189 188 2 2 3 - 2 2 3 11 11 11 132 132 132 75 75 75 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 10 6 3 190 189 188 190 189 188 151 97 5 192 133 7 - 207 148 7 206 142 8 199 140 8 180 121 7 180 132 31 - 190 189 188 190 189 188 212 212 212 212 212 212 107 107 107 - 2 2 3 2 2 3 99 99 99 51 51 51 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 190 189 188 190 189 188 190 189 188 136 95 7 - 151 97 5 151 97 5 151 97 5 183 156 91 190 189 188 - 190 189 188 228 228 228 254 254 252 254 254 252 221 221 220 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 10 6 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 75 75 75 245 245 245 196 196 196 190 189 188 190 189 188 - 190 189 188 196 196 196 190 189 188 190 189 188 204 204 204 - 236 236 236 254 254 252 254 254 252 254 254 252 254 254 252 - 35 35 35 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 27 27 27 2 2 3 - 245 245 245 254 254 252 245 245 245 190 189 188 190 189 188 - 190 189 188 190 189 188 190 189 188 212 212 212 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 10 6 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 2 2 3 132 132 132 - 254 254 252 254 254 252 254 254 252 236 236 236 196 196 196 - 190 189 188 204 204 204 245 245 245 245 245 245 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 80 80 80 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 2 2 3 2 2 3 2 2 3 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 2 2 3 2 2 3 212 212 212 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 2 2 3 2 2 3 204 204 204 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 245 245 245 236 236 236 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 2 2 3 11 11 11 164 164 164 212 212 212 - 236 236 236 245 245 245 254 254 252 236 236 236 221 221 220 - 221 221 220 228 228 228 245 245 245 245 245 245 245 245 245 - 236 236 236 221 221 220 212 212 212 204 204 204 204 204 204 - 196 196 196 204 204 204 59 59 59 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 2 2 3 27 27 27 172 172 172 212 212 212 - 236 236 236 254 254 252 254 254 252 254 254 252 228 228 228 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 245 245 245 221 221 220 204 204 204 196 196 196 - 196 196 196 196 196 196 228 228 228 19 19 19 2 2 3 - 80 80 80 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 2 2 3 2 2 3 - 11 11 11 2 2 3 164 164 164 236 236 236 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 236 236 236 212 212 212 196 196 196 245 245 245 2 2 3 - 2 2 3 11 11 11 51 51 51 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 2 2 3 86 86 83 - 2 2 3 27 27 27 236 236 236 254 254 252 254 254 252 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 212 212 212 196 196 196 91 91 91 - 2 2 3 2 2 3 2 2 3 11 11 11 2 2 3 - 2 2 3 2 2 3 2 2 3 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 2 2 3 2 2 3 - 2 2 3 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 221 221 220 245 245 245 - 2 2 3 11 11 11 43 43 43 19 19 19 10 6 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 2 2 3 80 80 80 2 2 3 - 2 2 3 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 43 43 43 27 27 27 80 80 80 19 19 19 80 80 80 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 2 2 3 2 2 3 2 2 3 2 2 3 - 245 245 245 254 254 252 254 254 252 17 11 233 254 254 252 - 254 254 252 254 254 252 254 254 252 236 236 236 17 11 233 - 17 11 233 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 11 11 11 11 11 11 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 2 2 3 67 67 67 2 2 3 19 19 19 - 254 254 252 254 254 252 245 245 245 17 11 233 245 245 245 - 254 254 252 254 254 252 17 11 233 228 228 228 17 11 233 - 17 11 233 17 11 233 17 11 233 254 254 252 17 11 233 - 17 11 233 254 254 252 254 254 252 17 11 233 17 11 233 - 17 11 233 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 2 2 3 - 11 11 11 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 10 6 3 11 11 11 2 2 3 228 228 228 - 254 254 252 254 254 252 254 254 252 17 11 233 254 254 252 - 254 254 252 17 11 233 17 11 233 17 11 233 245 245 245 - 254 254 252 254 254 252 17 11 233 17 11 233 17 11 233 - 17 11 233 17 11 233 254 254 252 17 11 233 17 11 233 - 17 11 233 17 11 233 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 2 2 3 - 27 27 27 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 2 2 3 2 2 3 2 2 3 2 2 3 254 254 252 - 254 254 252 254 254 252 254 254 252 17 11 233 17 11 233 - 17 11 233 17 11 233 17 11 233 17 11 233 254 254 252 - 17 11 233 17 11 233 17 11 233 254 254 252 254 254 252 - 17 11 233 17 11 233 254 254 252 17 11 233 17 11 233 - 254 254 252 17 11 233 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 2 2 3 - 11 11 11 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 19 19 19 2 2 3 2 2 3 254 254 252 - 254 254 252 254 254 252 17 11 233 245 245 245 17 11 233 - 17 11 233 245 245 245 254 254 252 17 11 233 254 254 252 - 17 11 233 17 11 233 17 11 233 254 254 252 254 254 252 - 17 11 233 17 11 233 254 254 252 17 11 233 17 11 233 - 17 11 233 17 11 233 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 2 2 3 - 2 2 3 19 19 19 2 2 3 19 19 19 254 254 252 - 254 254 252 245 245 245 17 11 233 254 254 252 17 11 233 - 17 11 233 254 254 252 254 254 252 17 11 233 254 254 252 - 254 254 252 254 254 252 17 11 233 17 11 233 254 254 252 - 17 11 233 17 11 233 254 254 252 17 11 233 17 11 233 - 17 11 233 17 11 233 17 11 233 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 43 43 43 2 2 3 43 43 43 254 254 252 - 245 245 245 254 254 252 17 11 233 254 254 252 17 11 233 - 254 254 252 254 254 252 254 254 252 17 11 233 17 11 233 - 17 11 233 17 11 233 17 11 233 254 254 252 17 11 233 - 17 11 233 17 11 233 17 11 233 17 11 233 17 11 233 - 245 245 245 254 254 252 17 11 233 254 254 252 254 254 252 - 245 245 245 2 2 3 2 2 3 2 2 3 11 11 11 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 75 75 75 2 2 3 99 99 99 254 254 252 - 254 254 252 254 254 252 17 11 233 254 254 252 254 254 252 - 254 254 252 254 254 252 245 245 245 228 228 228 254 254 252 - 254 254 252 17 11 233 245 245 245 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 17 11 233 17 11 233 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 2 2 3 75 75 75 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 2 2 3 - 2 2 3 2 2 3 11 11 11 107 107 107 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 245 245 245 254 254 252 245 245 245 236 236 236 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 2 2 3 11 11 11 19 19 19 - 11 11 11 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 2 2 3 11 11 11 - 140 102 3 11 11 11 10 6 3 67 67 67 254 254 252 - 245 245 245 245 245 245 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 245 245 245 228 228 228 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 245 245 245 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 2 2 3 43 43 43 2 2 3 2 2 3 - 2 2 3 11 11 11 67 67 67 11 11 11 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 185 132 9 242 182 11 - 245 189 11 245 189 11 49 35 5 2 2 3 228 228 228 - 254 254 252 254 254 252 254 254 252 245 245 245 254 254 252 - 254 254 252 254 254 252 254 254 252 228 228 228 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 245 238 222 232 189 94 - 226 186 99 43 43 43 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 59 59 59 2 2 3 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 216 156 8 236 180 22 - 245 189 11 245 189 11 245 189 11 49 35 5 11 11 11 - 212 212 212 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 245 245 245 228 228 228 254 254 252 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 245 245 245 254 254 252 254 254 252 229 172 9 246 218 19 - 246 218 19 41 27 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 19 19 19 27 27 27 196 154 14 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 199 140 8 229 172 9 242 182 11 - 245 189 11 245 189 11 245 189 11 244 196 10 2 2 3 - 2 2 3 115 115 115 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 245 245 245 228 228 228 254 254 252 - 254 254 252 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 224 165 9 245 189 11 - 236 196 11 19 19 19 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 11 11 11 236 196 11 - 244 205 11 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 182 126 10 209 156 9 215 150 13 - 193 140 10 207 148 24 216 156 8 242 182 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 209 156 9 - 2 2 3 2 2 3 43 43 43 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 236 236 236 216 156 8 245 189 11 - 229 172 9 64 43 7 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 207 148 7 236 188 10 - 245 189 11 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 180 121 7 216 156 8 242 182 11 236 180 10 - 229 172 9 242 182 11 242 182 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 237 204 14 - 170 126 10 2 2 3 2 2 3 11 11 11 236 236 236 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 204 204 204 196 196 196 216 156 8 236 180 10 - 224 165 9 182 126 10 73 48 6 2 2 3 2 2 3 - 2 2 3 41 27 3 199 140 8 229 172 9 236 180 10 - 245 189 11 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 185 132 9 229 172 9 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 226 188 11 2 2 3 2 2 3 2 2 3 11 11 11 - 245 245 245 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 196 196 196 196 196 196 215 150 13 236 180 10 - 229 172 9 201 142 7 185 132 9 180 121 7 173 120 10 - 180 121 7 192 133 7 229 172 9 242 182 11 245 189 11 - 245 189 11 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 180 126 47 224 165 9 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 236 188 10 193 140 10 2 2 3 2 2 3 2 2 3 - 2 2 3 212 212 212 254 254 252 245 245 245 245 245 245 - 254 254 252 254 254 252 254 254 252 245 245 245 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 204 204 204 196 196 196 199 140 8 229 172 9 - 236 180 10 218 164 9 215 150 13 207 148 7 207 148 7 - 216 156 8 229 172 9 245 189 11 245 189 11 245 189 11 - 245 189 11 242 182 11 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 185 132 9 216 156 8 242 182 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 236 196 11 19 19 19 2 2 3 2 2 3 - 2 2 3 11 11 11 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 245 245 245 254 254 252 254 254 252 - 245 245 245 221 221 220 196 196 196 185 132 9 229 172 9 - 242 182 11 229 172 9 224 165 9 218 164 9 224 165 9 - 229 172 9 236 180 10 245 189 11 245 189 11 245 189 11 - 245 189 11 236 180 22 242 182 11 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 236 180 22 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 236 188 10 225 180 10 2 2 3 2 2 3 - 2 2 3 11 11 11 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 221 221 220 19 19 19 185 132 9 224 165 9 - 245 189 11 245 189 11 242 182 11 236 180 10 236 180 10 - 242 182 11 242 182 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 196 154 14 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 207 148 7 236 180 22 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 242 182 11 - 245 189 11 245 189 11 237 204 14 135 88 5 2 2 3 - 27 27 27 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 245 245 245 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 67 67 67 19 13 3 185 132 9 229 172 9 - 242 182 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 236 180 22 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 245 189 11 242 182 11 - 242 182 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 236 188 10 226 188 11 104 83 48 - 254 254 252 254 254 252 254 254 252 254 254 252 245 245 245 - 254 254 252 254 254 252 245 245 245 254 254 252 245 245 245 - 254 254 252 245 245 245 254 254 252 254 254 252 254 254 252 - 2 2 3 2 2 3 56 38 5 185 132 9 229 172 9 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 242 182 11 - 229 172 9 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 182 126 10 215 150 13 242 182 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 242 182 11 245 189 11 236 196 11 216 156 8 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 245 245 245 2 2 3 - 2 2 3 2 2 3 75 54 3 182 126 10 229 172 9 - 242 182 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 229 172 9 - 207 148 24 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 192 133 7 229 172 9 242 182 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 242 182 11 225 180 10 224 165 9 - 107 69 5 245 245 245 254 254 252 254 254 252 254 254 252 - 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 - 254 254 252 236 236 236 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 91 67 9 182 126 10 229 172 9 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 242 182 11 242 182 11 216 156 8 180 126 47 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 206 142 8 224 165 9 245 189 11 242 182 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 242 182 11 - 245 189 11 245 189 11 242 182 11 242 182 11 216 156 8 - 156 102 5 19 13 3 43 43 43 196 196 196 254 254 252 - 245 245 245 254 254 252 254 254 252 204 204 204 51 51 51 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 95 62 5 185 132 9 229 172 9 - 242 182 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 242 182 11 245 189 11 245 189 11 - 236 180 22 216 156 8 206 142 8 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 192 133 7 215 150 13 229 172 9 229 172 9 - 236 180 10 236 180 22 242 182 11 242 182 11 245 189 11 - 245 189 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 245 189 11 245 189 11 229 172 9 216 156 8 - 156 102 5 83 54 6 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 115 73 3 185 132 9 229 172 9 - 242 182 11 245 189 11 245 189 11 245 189 11 245 189 11 - 245 189 11 242 182 11 229 172 9 229 172 9 216 156 8 - 180 121 7 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 180 121 7 182 126 10 192 133 7 199 140 8 - 207 148 7 215 150 13 216 156 8 224 165 9 229 172 9 - 236 180 22 245 189 11 242 182 11 245 189 11 242 182 11 - 245 189 11 245 189 11 242 182 11 229 172 9 199 140 8 - 151 97 5 101 67 7 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 115 73 3 180 121 7 216 156 8 - 236 180 22 242 182 11 245 189 11 245 189 11 242 182 11 - 236 180 10 224 165 9 215 150 13 206 142 8 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 156 102 5 164 109 5 172 114 5 180 121 7 180 121 7 - 192 133 7 201 142 7 216 156 8 224 165 9 236 180 22 - 245 189 11 242 182 11 229 172 9 201 142 7 172 114 5 - 125 83 5 83 54 6 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 2 2 3 2 2 3 2 2 3 - 2 2 3 2 2 3 91 58 5 156 102 5 192 133 7 - 216 156 8 229 172 9 236 180 10 236 180 10 229 172 9 - 215 150 13 199 140 8 164 109 5 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 120 78 3 132 82 3 - 151 97 5 157 106 7 180 121 7 185 132 9 193 140 10 - 207 148 7 207 148 7 192 133 7 172 114 5 132 82 3 - 101 67 7 41 27 3 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 73 48 6 143 90 3 180 121 7 - 192 133 7 207 148 7 207 148 7 201 142 7 185 132 9 - 173 120 10 136 95 7 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 91 58 5 125 83 5 135 88 5 - 144 95 7 151 97 5 132 82 3 115 73 3 95 62 5 - 64 43 7 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 64 43 7 91 58 5 151 97 5 - 157 106 7 172 114 5 172 114 5 164 109 5 151 97 5 - 85 59 6 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 73 48 6 - 91 58 5 95 62 5 95 62 5 91 58 5 56 38 5 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 83 54 6 - 107 69 5 132 82 3 125 83 5 101 67 7 71 47 31 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 - 215 150 13 215 150 13 215 150 13 215 150 13 215 150 13 diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 37460cd6cabb..de6847d7b4e3 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -815,23 +815,6 @@ config SPRD_WATCHDOG Say Y here to include watchdog timer supported by Spreadtrum system. -# BLACKFIN Architecture - -config BFIN_WDT - tristate "Blackfin On-Chip Watchdog Timer" - depends on BLACKFIN - ---help--- - If you say yes here you will get support for the Blackfin On-Chip - Watchdog Timer. If you have one of these processors and wish to - have watchdog support enabled, say Y, otherwise say N. - - To compile this driver as a module, choose M here: the - module will be called bfin_wdt. - -# CRIS Architecture - -# FRV Architecture - # X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT @@ -1431,8 +1414,6 @@ config NIC7018_WDT To compile this driver as a module, choose M here: the module will be called nic7018_wdt. -# M32R Architecture - # M68K Architecture config M54xx_WATCHDOG @@ -1605,7 +1586,7 @@ config BCM7038_WDT config IMGPDC_WDT tristate "Imagination Technologies PDC Watchdog Timer" depends on HAS_IOMEM - depends on METAG || MIPS || COMPILE_TEST + depends on MIPS || COMPILE_TEST select WATCHDOG_CORE help Driver for Imagination Technologies PowerDown Controller diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0474d38aa854..e4dd91f5585a 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -91,13 +91,6 @@ obj-$(CONFIG_UNIPHIER_WATCHDOG) += uniphier_wdt.o obj-$(CONFIG_RTD119X_WATCHDOG) += rtd119x_wdt.o obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o -# BLACKFIN Architecture -obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o - -# CRIS Architecture - -# FRV Architecture - # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o @@ -146,8 +139,6 @@ obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o obj-$(CONFIG_NIC7018_WDT) += nic7018_wdt.o -# M32R Architecture - # M68K Architecture obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c deleted file mode 100644 index aa4d2e8a8ef9..000000000000 --- a/drivers/watchdog/bfin_wdt.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Blackfin On-Chip Watchdog Driver - * - * Originally based on softdog.c - * Copyright 2006-2010 Analog Devices Inc. - * Copyright 2006-2007 Michele d'Amico - * Copyright 1996 Alan Cox <alan@lxorguk.ukuu.org.uk> - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/timer.h> -#include <linux/miscdevice.h> -#include <linux/watchdog.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/uaccess.h> -#include <asm/blackfin.h> -#include <asm/bfin_watchdog.h> - -#define stamp(fmt, args...) \ - pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) -#define stampit() stamp("here i am") - -#define WATCHDOG_NAME "bfin-wdt" - -/* The BF561 has two watchdogs (one per core), but since Linux - * only runs on core A, we'll just work with that one. - */ -#ifdef BF561_FAMILY -# define bfin_read_WDOG_CTL() bfin_read_WDOGA_CTL() -# define bfin_read_WDOG_CNT() bfin_read_WDOGA_CNT() -# define bfin_read_WDOG_STAT() bfin_read_WDOGA_STAT() -# define bfin_write_WDOG_CTL(x) bfin_write_WDOGA_CTL(x) -# define bfin_write_WDOG_CNT(x) bfin_write_WDOGA_CNT(x) -# define bfin_write_WDOG_STAT(x) bfin_write_WDOGA_STAT(x) -#endif - -/* some defaults */ -#define WATCHDOG_TIMEOUT 20 - -static unsigned int timeout = WATCHDOG_TIMEOUT; -static bool nowayout = WATCHDOG_NOWAYOUT; -static const struct watchdog_info bfin_wdt_info; -static unsigned long open_check; -static char expect_close; -static DEFINE_SPINLOCK(bfin_wdt_spinlock); - -/** - * bfin_wdt_keepalive - Keep the Userspace Watchdog Alive - * - * The Userspace watchdog got a KeepAlive: schedule the next timeout. - */ -static int bfin_wdt_keepalive(void) -{ - stampit(); - bfin_write_WDOG_STAT(0); - return 0; -} - -/** - * bfin_wdt_stop - Stop the Watchdog - * - * Stops the on-chip watchdog. - */ -static int bfin_wdt_stop(void) -{ - stampit(); - bfin_write_WDOG_CTL(WDEN_DISABLE); - return 0; -} - -/** - * bfin_wdt_start - Start the Watchdog - * - * Starts the on-chip watchdog. Automatically loads WDOG_CNT - * into WDOG_STAT for us. - */ -static int bfin_wdt_start(void) -{ - stampit(); - bfin_write_WDOG_CTL(WDEN_ENABLE | ICTL_RESET); - return 0; -} - -/** - * bfin_wdt_running - Check Watchdog status - * - * See if the watchdog is running. - */ -static int bfin_wdt_running(void) -{ - stampit(); - return ((bfin_read_WDOG_CTL() & WDEN_MASK) != WDEN_DISABLE); -} - -/** - * bfin_wdt_set_timeout - Set the Userspace Watchdog timeout - * @t: new timeout value (in seconds) - * - * Translate the specified timeout in seconds into System Clock - * terms which is what the on-chip Watchdog requires. - */ -static int bfin_wdt_set_timeout(unsigned long t) -{ - u32 cnt, max_t, sclk; - unsigned long flags; - - sclk = get_sclk(); - max_t = -1 / sclk; - cnt = t * sclk; - stamp("maxtimeout=%us newtimeout=%lus (cnt=%#x)", max_t, t, cnt); - - if (t > max_t) { - pr_warn("timeout value is too large\n"); - return -EINVAL; - } - - spin_lock_irqsave(&bfin_wdt_spinlock, flags); - { - int run = bfin_wdt_running(); - bfin_wdt_stop(); - bfin_write_WDOG_CNT(cnt); - if (run) - bfin_wdt_start(); - } - spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); - - timeout = t; - - return 0; -} - -/** - * bfin_wdt_open - Open the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is opened and started. - */ -static int bfin_wdt_open(struct inode *inode, struct file *file) -{ - stampit(); - - if (test_and_set_bit(0, &open_check)) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - bfin_wdt_keepalive(); - bfin_wdt_start(); - - return nonseekable_open(inode, file); -} - -/** - * bfin_wdt_close - Close the Device - * @inode: inode of device - * @file: file handle of device - * - * Watchdog device is closed and stopped. - */ -static int bfin_wdt_release(struct inode *inode, struct file *file) -{ - stampit(); - - if (expect_close == 42) - bfin_wdt_stop(); - else { - pr_crit("Unexpected close, not stopping watchdog!\n"); - bfin_wdt_keepalive(); - } - expect_close = 0; - clear_bit(0, &open_check); - return 0; -} - -/** - * bfin_wdt_write - Write to Device - * @file: file handle of device - * @buf: buffer to write - * @count: length of buffer - * @ppos: offset - * - * Pings the watchdog on write. - */ -static ssize_t bfin_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - stampit(); - - if (len) { - if (!nowayout) { - size_t i; - - /* In case it was set long ago */ - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = 42; - } - } - bfin_wdt_keepalive(); - } - - return len; -} - -/** - * bfin_wdt_ioctl - Query Device - * @file: file handle of device - * @cmd: watchdog command - * @arg: argument - * - * Query basic information from the device or ping it, as outlined by the - * watchdog API. - */ -static long bfin_wdt_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - - stampit(); - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) - return -EFAULT; - else - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); - case WDIOC_SETOPTIONS: { - unsigned long flags; - int options, ret = -EINVAL; - - if (get_user(options, p)) - return -EFAULT; - - spin_lock_irqsave(&bfin_wdt_spinlock, flags); - if (options & WDIOS_DISABLECARD) { - bfin_wdt_stop(); - ret = 0; - } - if (options & WDIOS_ENABLECARD) { - bfin_wdt_start(); - ret = 0; - } - spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); - return ret; - } - case WDIOC_KEEPALIVE: - bfin_wdt_keepalive(); - return 0; - case WDIOC_SETTIMEOUT: { - int new_timeout; - - if (get_user(new_timeout, p)) - return -EFAULT; - if (bfin_wdt_set_timeout(new_timeout)) - return -EINVAL; - } - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user(timeout, p); - default: - return -ENOTTY; - } -} - -#ifdef CONFIG_PM -static int state_before_suspend; - -/** - * bfin_wdt_suspend - suspend the watchdog - * @pdev: device being suspended - * @state: requested suspend state - * - * Remember if the watchdog was running and stop it. - * TODO: is this even right? Doesn't seem to be any - * standard in the watchdog world ... - */ -static int bfin_wdt_suspend(struct platform_device *pdev, pm_message_t state) -{ - stampit(); - - state_before_suspend = bfin_wdt_running(); - bfin_wdt_stop(); - - return 0; -} - -/** - * bfin_wdt_resume - resume the watchdog - * @pdev: device being resumed - * - * If the watchdog was running, turn it back on. - */ -static int bfin_wdt_resume(struct platform_device *pdev) -{ - stampit(); - - if (state_before_suspend) { - bfin_wdt_set_timeout(timeout); - bfin_wdt_start(); - } - - return 0; -} -#else -# define bfin_wdt_suspend NULL -# define bfin_wdt_resume NULL -#endif - -static const struct file_operations bfin_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = bfin_wdt_write, - .unlocked_ioctl = bfin_wdt_ioctl, - .open = bfin_wdt_open, - .release = bfin_wdt_release, -}; - -static struct miscdevice bfin_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &bfin_wdt_fops, -}; - -static const struct watchdog_info bfin_wdt_info = { - .identity = "Blackfin Watchdog", - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, -}; - -/** - * bfin_wdt_probe - Initialize module - * - * Registers the misc device. Actual device - * initialization is handled by bfin_wdt_open(). - */ -static int bfin_wdt_probe(struct platform_device *pdev) -{ - int ret; - - ret = misc_register(&bfin_wdt_miscdev); - if (ret) { - pr_err("cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - return ret; - } - - pr_info("initialized: timeout=%d sec (nowayout=%d)\n", - timeout, nowayout); - - return 0; -} - -/** - * bfin_wdt_remove - Initialize module - * - * Unregisters the misc device. Actual device - * deinitialization is handled by bfin_wdt_close(). - */ -static int bfin_wdt_remove(struct platform_device *pdev) -{ - misc_deregister(&bfin_wdt_miscdev); - return 0; -} - -/** - * bfin_wdt_shutdown - Soft Shutdown Handler - * - * Handles the soft shutdown event. - */ -static void bfin_wdt_shutdown(struct platform_device *pdev) -{ - stampit(); - - bfin_wdt_stop(); -} - -static struct platform_device *bfin_wdt_device; - -static struct platform_driver bfin_wdt_driver = { - .probe = bfin_wdt_probe, - .remove = bfin_wdt_remove, - .shutdown = bfin_wdt_shutdown, - .suspend = bfin_wdt_suspend, - .resume = bfin_wdt_resume, - .driver = { - .name = WATCHDOG_NAME, - }, -}; - -/** - * bfin_wdt_init - Initialize module - * - * Checks the module params and registers the platform device & driver. - * Real work is in the platform probe function. - */ -static int __init bfin_wdt_init(void) -{ - int ret; - - stampit(); - - /* Check that the timeout value is within range */ - if (bfin_wdt_set_timeout(timeout)) - return -EINVAL; - - /* Since this is an on-chip device and needs no board-specific - * resources, we'll handle all the platform device stuff here. - */ - ret = platform_driver_register(&bfin_wdt_driver); - if (ret) { - pr_err("unable to register driver\n"); - return ret; - } - - bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, - -1, NULL, 0); - if (IS_ERR(bfin_wdt_device)) { - pr_err("unable to register device\n"); - platform_driver_unregister(&bfin_wdt_driver); - return PTR_ERR(bfin_wdt_device); - } - - return 0; -} - -/** - * bfin_wdt_exit - Deinitialize module - * - * Back out the platform device & driver steps. Real work is in the - * platform remove function. - */ -static void __exit bfin_wdt_exit(void) -{ - platform_device_unregister(bfin_wdt_device); - platform_driver_unregister(&bfin_wdt_driver); -} - -module_init(bfin_wdt_init); -module_exit(bfin_wdt_exit); - -MODULE_AUTHOR("Michele d'Amico, Mike Frysinger <vapier@gentoo.org>"); -MODULE_DESCRIPTION("Blackfin Watchdog Device Driver"); -MODULE_LICENSE("GPL"); - -module_param(timeout, uint, 0); -MODULE_PARM_DESC(timeout, - "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" - __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); - -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |