diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/arch/cris/arch-v32 | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/arch/cris/arch-v32')
28 files changed, 88 insertions, 3492 deletions
diff --git a/kernel/arch/cris/arch-v32/Kconfig b/kernel/arch/cris/arch-v32/Kconfig index 21bbd93be..17dbe03af 100644 --- a/kernel/arch/cris/arch-v32/Kconfig +++ b/kernel/arch/cris/arch-v32/Kconfig @@ -11,95 +11,6 @@ config ETRAX_DRAM_VIRTUAL_BASE default "c0000000" choice - prompt "Nbr of Ethernet LED groups" - depends on ETRAX_ARCH_V32 - default ETRAX_NBR_LED_GRP_ONE - help - Select how many Ethernet LED groups that can be used. Usually one per Ethernet - interface is a good choice. - -config ETRAX_NBR_LED_GRP_ZERO - bool "Use zero LED groups" - help - Select this if you do not want any Ethernet LEDs. - -config ETRAX_NBR_LED_GRP_ONE - bool "Use one LED group" - help - Select this if you want one Ethernet LED group. This LED group - can be used for one or more Ethernet interfaces. However, it is - recommended that each Ethernet interface use a dedicated LED group. - -config ETRAX_NBR_LED_GRP_TWO - bool "Use two LED groups" - help - Select this if you want two Ethernet LED groups. This is the - best choice if you have more than one Ethernet interface and - would like to have separate LEDs for the interfaces. - -endchoice - -config ETRAX_LED_G_NET0 - string "Ethernet LED group 0 green LED bit" - depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO) - default "PA3" - help - Bit to use for the green LED in Ethernet LED group 0. - -config ETRAX_LED_R_NET0 - string "Ethernet LED group 0 red LED bit" - depends on ETRAX_ARCH_V32 && (ETRAX_NBR_LED_GRP_ONE || ETRAX_NBR_LED_GRP_TWO) - default "PA4" - help - Bit to use for the red LED in Ethernet LED group 0. - -config ETRAX_LED_G_NET1 - string "Ethernet group 1 green LED bit" - depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO - default "" - help - Bit to use for the green LED in Ethernet LED group 1. - -config ETRAX_LED_R_NET1 - string "Ethernet group 1 red LED bit" - depends on ETRAX_ARCH_V32 && ETRAX_NBR_LED_GRP_TWO - default "" - help - Bit to use for the red LED in Ethernet LED group 1. - -config ETRAX_V32_LED2G - string "Second green LED bit" - depends on ETRAX_ARCH_V32 - default "PA5" - help - Bit to use for the first green LED (status LED). - Most Axis products use bit A5 here. - -config ETRAX_V32_LED2R - string "Second red LED bit" - depends on ETRAX_ARCH_V32 - default "PA6" - help - Bit to use for the first red LED (network LED). - Most Axis products use bit A6 here. - -config ETRAX_V32_LED3G - string "Third green LED bit" - depends on ETRAX_ARCH_V32 - default "PA7" - help - Bit to use for the first green LED (drive/power LED). - Most Axis products use bit A7 here. - -config ETRAX_V32_LED3R - string "Third red LED bit" - depends on ETRAX_ARCH_V32 - default "PA7" - help - Bit to use for the first red LED (drive/power LED). - Most Axis products use bit A7 here. - -choice prompt "Kernel GDB port" depends on ETRAX_KGDB default ETRAX_KGDB_PORT0 diff --git a/kernel/arch/cris/arch-v32/drivers/Kconfig b/kernel/arch/cris/arch-v32/drivers/Kconfig index 4fc16b44f..2735eb767 100644 --- a/kernel/arch/cris/arch-v32/drivers/Kconfig +++ b/kernel/arch/cris/arch-v32/drivers/Kconfig @@ -149,173 +149,6 @@ config ETRAX_NANDBOOT Say Y if your boot code, kernel and root file system is in NAND flash. Say N if they are in NOR flash. -config ETRAX_I2C - bool "I2C driver" - depends on ETRAX_ARCH_V32 - help - This option enables the I2C driver used by e.g. the RTC driver. - -config ETRAX_V32_I2C_DATA_PORT - string "I2C data pin" - depends on ETRAX_I2C - help - The pin to use for I2C data. - -config ETRAX_V32_I2C_CLK_PORT - string "I2C clock pin" - depends on ETRAX_I2C - help - The pin to use for I2C clock. - -config ETRAX_GPIO - bool "GPIO support" - depends on ETRAX_ARCH_V32 - ---help--- - Enables the ETRAX general port device (major 120, minors 0-4). - You can use this driver to access the general port bits. It supports - these ioctl's: - #include <linux/etraxgpio.h> - fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set); - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear); - err = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READ_INBITS), &val); - Remember that you need to setup the port directions appropriately in - the General configuration. - -config ETRAX_VIRTUAL_GPIO - bool "Virtual GPIO support" - depends on ETRAX_GPIO - help - Enables the virtual Etrax general port device (major 120, minor 6). - It uses an I/O expander for the I2C-bus. - -config ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN - int "Virtual GPIO interrupt pin on PA pin" - range 0 7 - depends on ETRAX_VIRTUAL_GPIO - help - The pin to use on PA for virtual gpio interrupt. - -config ETRAX_PA_CHANGEABLE_DIR - hex "PA user changeable dir mask" - depends on ETRAX_GPIO - default "0x00" if ETRAXFS - default "0x00000000" if !ETRAXFS - help - This is a bitmask (8 bits) with information of what bits in PA that a - user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0 here, but it depends on your hardware. - -config ETRAX_PA_CHANGEABLE_BITS - hex "PA user changeable bits mask" - depends on ETRAX_GPIO - default "0x00" if ETRAXFS - default "0x00000000" if !ETRAXFS - help - This is a bitmask (8 bits) with information of what bits in PA - that a user can change the value on using ioctl's. - Bit set = changeable. - -config ETRAX_PB_CHANGEABLE_DIR - hex "PB user changeable dir mask" - depends on ETRAX_GPIO - default "0x00000" if ETRAXFS - default "0x00000000" if !ETRAXFS - help - This is a bitmask (18 bits) with information of what bits in PB - that a user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0 here, but it depends on your hardware. - -config ETRAX_PB_CHANGEABLE_BITS - hex "PB user changeable bits mask" - depends on ETRAX_GPIO - default "0x00000" if ETRAXFS - default "0x00000000" if !ETRAXFS - help - This is a bitmask (18 bits) with information of what bits in PB - that a user can change the value on using ioctl's. - Bit set = changeable. - -config ETRAX_PC_CHANGEABLE_DIR - hex "PC user changeable dir mask" - depends on ETRAX_GPIO - default "0x00000" if ETRAXFS - default "0x00000000" if !ETRAXFS - help - This is a bitmask (18 bits) with information of what bits in PC - that a user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0 here, but it depends on your hardware. - -config ETRAX_PC_CHANGEABLE_BITS - hex "PC user changeable bits mask" - depends on ETRAX_GPIO - default "0x00000" if ETRAXFS - default "0x00000000" if ETRAXFS - help - This is a bitmask (18 bits) with information of what bits in PC - that a user can change the value on using ioctl's. - Bit set = changeable. - -config ETRAX_PD_CHANGEABLE_DIR - hex "PD user changeable dir mask" - depends on ETRAX_GPIO && ETRAXFS - default "0x00000" - help - This is a bitmask (18 bits) with information of what bits in PD - that a user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0x00000 here, but it depends on your hardware. - -config ETRAX_PD_CHANGEABLE_BITS - hex "PD user changeable bits mask" - depends on ETRAX_GPIO && ETRAXFS - default "0x00000" - help - This is a bitmask (18 bits) with information of what bits in PD - that a user can change the value on using ioctl's. - Bit set = changeable. - -config ETRAX_PE_CHANGEABLE_DIR - hex "PE user changeable dir mask" - depends on ETRAX_GPIO && ETRAXFS - default "0x00000" - help - This is a bitmask (18 bits) with information of what bits in PE - that a user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0x00000 here, but it depends on your hardware. - -config ETRAX_PE_CHANGEABLE_BITS - hex "PE user changeable bits mask" - depends on ETRAX_GPIO && ETRAXFS - default "0x00000" - help - This is a bitmask (18 bits) with information of what bits in PE - that a user can change the value on using ioctl's. - Bit set = changeable. - -config ETRAX_PV_CHANGEABLE_DIR - hex "PV user changeable dir mask" - depends on ETRAX_VIRTUAL_GPIO - default "0x0000" - help - This is a bitmask (16 bits) with information of what bits in PV - that a user can change direction on using ioctl's. - Bit set = changeable. - You probably want 0x0000 here, but it depends on your hardware. - -config ETRAX_PV_CHANGEABLE_BITS - hex "PV user changeable bits mask" - depends on ETRAX_VIRTUAL_GPIO - default "0x0000" - help - This is a bitmask (16 bits) with information of what bits in PV - that a user can change the value on using ioctl's. - Bit set = changeable. - config ETRAX_CARDBUS bool "Cardbus support" depends on ETRAX_ARCH_V32 diff --git a/kernel/arch/cris/arch-v32/drivers/Makefile b/kernel/arch/cris/arch-v32/drivers/Makefile index 15fbfefce..b5a75fdce 100644 --- a/kernel/arch/cris/arch-v32/drivers/Makefile +++ b/kernel/arch/cris/arch-v32/drivers/Makefile @@ -7,6 +7,5 @@ obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o obj-$(CONFIG_ETRAXFS) += mach-fs/ obj-$(CONFIG_CRIS_MACH_ARTPEC3) += mach-a3/ obj-$(CONFIG_ETRAX_IOP_FW_LOAD) += iop_fw_load.o -obj-$(CONFIG_ETRAX_I2C) += i2c.o obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o obj-$(CONFIG_PCI) += pci/ diff --git a/kernel/arch/cris/arch-v32/drivers/axisflashmap.c b/kernel/arch/cris/arch-v32/drivers/axisflashmap.c index 28dd77144..c6309a182 100644 --- a/kernel/arch/cris/arch-v32/drivers/axisflashmap.c +++ b/kernel/arch/cris/arch-v32/drivers/axisflashmap.c @@ -313,6 +313,7 @@ static int __init init_axis_flash(void) size_t len; int ram_rootfs_partition = -1; /* -1 => no RAM rootfs partition */ int part; + struct mtd_partition *partition; /* We need a root fs. If it resides in RAM, we need to use an * MTDRAM device, so it must be enabled in the kernel config, @@ -329,7 +330,7 @@ static int __init init_axis_flash(void) main_mtd = flash_probe(); if (main_mtd) - printk(KERN_INFO "%s: 0x%08x bytes of NOR flash memory.\n", + printk(KERN_INFO "%s: 0x%08llx bytes of NOR flash memory.\n", main_mtd->name, main_mtd->size); #ifdef CONFIG_ETRAX_NANDFLASH @@ -360,7 +361,7 @@ static int __init init_axis_flash(void) #if 0 /* Dump flash memory so we can see what is going on */ if (main_mtd) { - int sectoraddr, i; + int sectoraddr; for (sectoraddr = 0; sectoraddr < 2*65536+4096; sectoraddr += PAGESIZE) { main_mtd->read(main_mtd, sectoraddr, PAGESIZE, &len, @@ -368,30 +369,16 @@ static int __init init_axis_flash(void) printk(KERN_INFO "Sector at %d (length %d):\n", sectoraddr, len); - for (i = 0; i < PAGESIZE; i += 16) { - printk(KERN_INFO - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x " - "%02x %02x %02x %02x\n", - page[i] & 255, page[i+1] & 255, - page[i+2] & 255, page[i+3] & 255, - page[i+4] & 255, page[i+5] & 255, - page[i+6] & 255, page[i+7] & 255, - page[i+8] & 255, page[i+9] & 255, - page[i+10] & 255, page[i+11] & 255, - page[i+12] & 255, page[i+13] & 255, - page[i+14] & 255, page[i+15] & 255); - } + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, page, PAGESIZE, false); } } #endif if (main_mtd) { + loff_t ptable_sector = CONFIG_ETRAX_PTABLE_SECTOR; main_mtd->owner = THIS_MODULE; axisflash_mtd = main_mtd; - loff_t ptable_sector = CONFIG_ETRAX_PTABLE_SECTOR; /* First partition (rescue) is always set to the default. */ pidx++; @@ -416,25 +403,11 @@ static int __init init_axis_flash(void) #if 0 /* Dump partition table so we can see what is going on */ printk(KERN_INFO - "axisflashmap: flash read %d bytes at 0x%08x, data: " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - len, CONFIG_ETRAX_PTABLE_SECTOR, - page[0] & 255, page[1] & 255, - page[2] & 255, page[3] & 255, - page[4] & 255, page[5] & 255, - page[6] & 255, page[7] & 255); + "axisflashmap: flash read %d bytes at 0x%08x, data: %8ph\n", + len, CONFIG_ETRAX_PTABLE_SECTOR, page); printk(KERN_INFO - "axisflashmap: partition table offset %d, data: " - "%02x %02x %02x %02x %02x %02x %02x %02x\n", - PARTITION_TABLE_OFFSET, - page[PARTITION_TABLE_OFFSET+0] & 255, - page[PARTITION_TABLE_OFFSET+1] & 255, - page[PARTITION_TABLE_OFFSET+2] & 255, - page[PARTITION_TABLE_OFFSET+3] & 255, - page[PARTITION_TABLE_OFFSET+4] & 255, - page[PARTITION_TABLE_OFFSET+5] & 255, - page[PARTITION_TABLE_OFFSET+6] & 255, - page[PARTITION_TABLE_OFFSET+7] & 255); + "axisflashmap: partition table offset %d, data: %8ph\n", + PARTITION_TABLE_OFFSET, page + PARTITION_TABLE_OFFSET); #endif } @@ -517,7 +490,7 @@ static int __init init_axis_flash(void) /* Decide whether to use default partition table. */ /* Only use default table if we actually have a device (main_mtd) */ - struct mtd_partition *partition = &axis_partitions[0]; + partition = &axis_partitions[0]; if (main_mtd && !ptable_ok) { memcpy(axis_partitions, axis_default_partitions, sizeof(axis_default_partitions)); @@ -580,7 +553,7 @@ static int __init init_axis_flash(void) printk(KERN_INFO "axisflashmap: Adding RAM partition " "for rootfs image.\n"); err = mtdram_init_device(mtd_ram, - (void *)partition[part].offset, + (void *)(u_int32_t)partition[part].offset, partition[part].size, partition[part].name); if (err) diff --git a/kernel/arch/cris/arch-v32/drivers/i2c.c b/kernel/arch/cris/arch-v32/drivers/i2c.c deleted file mode 100644 index 3b2c82ce8..000000000 --- a/kernel/arch/cris/arch-v32/drivers/i2c.c +++ /dev/null @@ -1,751 +0,0 @@ -/*!*************************************************************************** -*! -*! FILE NAME : i2c.c -*! -*! DESCRIPTION: implements an interface for IIC/I2C, both directly from other -*! kernel modules (i2c_writereg/readreg) and from userspace using -*! ioctl()'s -*! -*! Nov 30 1998 Torbjorn Eliasson Initial version. -*! Bjorn Wesen Elinux kernel version. -*! Jan 14 2000 Johan Adolfsson Fixed PB shadow register stuff - -*! don't use PB_I2C if DS1302 uses same bits, -*! use PB. -*| June 23 2003 Pieter Grimmerink Added 'i2c_sendnack'. i2c_readreg now -*| generates nack on last received byte, -*| instead of ack. -*| i2c_getack changed data level while clock -*| was high, causing DS75 to see a stop condition -*! -*! --------------------------------------------------------------------------- -*! -*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN -*! -*!***************************************************************************/ - -/****************** INCLUDE FILES SECTION ***********************************/ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/mutex.h> - -#include <asm/etraxi2c.h> - -#include <asm/io.h> -#include <asm/delay.h> - -#include "i2c.h" - -/****************** I2C DEFINITION SECTION *************************/ - -#define D(x) - -#define I2C_MAJOR 123 /* LOCAL/EXPERIMENTAL */ -static DEFINE_MUTEX(i2c_mutex); -static const char i2c_name[] = "i2c"; - -#define CLOCK_LOW_TIME 8 -#define CLOCK_HIGH_TIME 8 -#define START_CONDITION_HOLD_TIME 8 -#define STOP_CONDITION_HOLD_TIME 8 -#define ENABLE_OUTPUT 0x01 -#define ENABLE_INPUT 0x00 -#define I2C_CLOCK_HIGH 1 -#define I2C_CLOCK_LOW 0 -#define I2C_DATA_HIGH 1 -#define I2C_DATA_LOW 0 - -#define i2c_enable() -#define i2c_disable() - -/* enable or disable output-enable, to select output or input on the i2c bus */ - -#define i2c_dir_out() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_out) -#define i2c_dir_in() crisv32_io_set_dir(&cris_i2c_data, crisv32_io_dir_in) - -/* control the i2c clock and data signals */ - -#define i2c_clk(x) crisv32_io_set(&cris_i2c_clk, x) -#define i2c_data(x) crisv32_io_set(&cris_i2c_data, x) - -/* read a bit from the i2c interface */ - -#define i2c_getbit() crisv32_io_rd(&cris_i2c_data) - -#define i2c_delay(usecs) udelay(usecs) - -static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */ - -/****************** VARIABLE SECTION ************************************/ - -static struct crisv32_iopin cris_i2c_clk; -static struct crisv32_iopin cris_i2c_data; - -/****************** FUNCTION DEFINITION SECTION *************************/ - - -/* generate i2c start condition */ - -void -i2c_start(void) -{ - /* - * SCL=1 SDA=1 - */ - i2c_dir_out(); - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_data(I2C_DATA_HIGH); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - /* - * SCL=1 SDA=0 - */ - i2c_data(I2C_DATA_LOW); - i2c_delay(START_CONDITION_HOLD_TIME); - /* - * SCL=0 SDA=0 - */ - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); -} - -/* generate i2c stop condition */ - -void -i2c_stop(void) -{ - i2c_dir_out(); - - /* - * SCL=0 SDA=0 - */ - i2c_clk(I2C_CLOCK_LOW); - i2c_data(I2C_DATA_LOW); - i2c_delay(CLOCK_LOW_TIME*2); - /* - * SCL=1 SDA=0 - */ - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME*2); - /* - * SCL=1 SDA=1 - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(STOP_CONDITION_HOLD_TIME); - - i2c_dir_in(); -} - -/* write a byte to the i2c interface */ - -void -i2c_outbyte(unsigned char x) -{ - int i; - - i2c_dir_out(); - - for (i = 0; i < 8; i++) { - if (x & 0x80) { - i2c_data(I2C_DATA_HIGH); - } else { - i2c_data(I2C_DATA_LOW); - } - - i2c_delay(CLOCK_LOW_TIME/2); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME/2); - x <<= 1; - } - i2c_data(I2C_DATA_LOW); - i2c_delay(CLOCK_LOW_TIME/2); - - /* - * enable input - */ - i2c_dir_in(); -} - -/* read a byte from the i2c interface */ - -unsigned char -i2c_inbyte(void) -{ - unsigned char aBitByte = 0; - int i; - - /* Switch off I2C to get bit */ - i2c_disable(); - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/2); - - /* Get bit */ - aBitByte |= i2c_getbit(); - - /* Enable I2C */ - i2c_enable(); - i2c_delay(CLOCK_LOW_TIME/2); - - for (i = 1; i < 8; i++) { - aBitByte <<= 1; - /* Clock pulse */ - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); - - /* Switch off I2C to get bit */ - i2c_disable(); - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/2); - - /* Get bit */ - aBitByte |= i2c_getbit(); - - /* Enable I2C */ - i2c_enable(); - i2c_delay(CLOCK_LOW_TIME/2); - } - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - - /* - * we leave the clock low, getbyte is usually followed - * by sendack/nack, they assume the clock to be low - */ - i2c_clk(I2C_CLOCK_LOW); - return aBitByte; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_getack -*# -*# DESCRIPTION : checks if ack was received from ic2 -*# -*#--------------------------------------------------------------------------*/ - -int -i2c_getack(void) -{ - int ack = 1; - /* - * enable output - */ - i2c_dir_out(); - /* - * Release data bus by setting - * data high - */ - i2c_data(I2C_DATA_HIGH); - /* - * enable input - */ - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/4); - /* - * generate ACK clock pulse - */ - i2c_clk(I2C_CLOCK_HIGH); -#if 0 - /* - * Use PORT PB instead of I2C - * for input. (I2C not working) - */ - i2c_clk(1); - i2c_data(1); - /* - * switch off I2C - */ - i2c_data(1); - i2c_disable(); - i2c_dir_in(); -#endif - - /* - * now wait for ack - */ - i2c_delay(CLOCK_HIGH_TIME/2); - /* - * check for ack - */ - if (i2c_getbit()) - ack = 0; - i2c_delay(CLOCK_HIGH_TIME/2); - if (!ack) { - if (!i2c_getbit()) /* receiver pulld SDA low */ - ack = 1; - i2c_delay(CLOCK_HIGH_TIME/2); - } - - /* - * our clock is high now, make sure data is low - * before we enable our output. If we keep data high - * and enable output, we would generate a stop condition. - */ -#if 0 - i2c_data(I2C_DATA_LOW); - - /* - * end clock pulse - */ - i2c_enable(); - i2c_dir_out(); -#endif - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_HIGH_TIME/4); - /* - * enable output - */ - i2c_dir_out(); - /* - * remove ACK clock pulse - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(CLOCK_LOW_TIME/2); - return ack; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: I2C::sendAck -*# -*# DESCRIPTION : Send ACK on received data -*# -*#--------------------------------------------------------------------------*/ -void -i2c_sendack(void) -{ - /* - * enable output - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_dir_out(); - /* - * set ack pulse high - */ - i2c_data(I2C_DATA_LOW); - /* - * generate clock pulse - */ - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME/6); - /* - * reset data out - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(CLOCK_LOW_TIME); - - i2c_dir_in(); -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_sendnack -*# -*# DESCRIPTION : Sends NACK on received data -*# -*#--------------------------------------------------------------------------*/ -void -i2c_sendnack(void) -{ - /* - * enable output - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_dir_out(); - /* - * set data high - */ - i2c_data(I2C_DATA_HIGH); - /* - * generate clock pulse - */ - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); - - i2c_dir_in(); -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_write -*# -*# DESCRIPTION : Writes a value to an I2C device -*# -*#--------------------------------------------------------------------------*/ -int -i2c_write(unsigned char theSlave, void *data, size_t nbytes) -{ - int error, cntr = 3; - unsigned char bytes_wrote = 0; - unsigned char value; - unsigned long flags; - - spin_lock_irqsave(&i2c_lock, flags); - - do { - error = 0; - - i2c_start(); - /* - * send slave address - */ - i2c_outbyte((theSlave & 0xfe)); - /* - * wait for ack - */ - if (!i2c_getack()) - error = 1; - /* - * send data - */ - for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) { - memcpy(&value, data + bytes_wrote, sizeof value); - i2c_outbyte(value); - /* - * now it's time to wait for ack - */ - if (!i2c_getack()) - error |= 4; - } - /* - * end byte stream - */ - i2c_stop(); - - } while (error && cntr--); - - i2c_delay(CLOCK_LOW_TIME); - - spin_unlock_irqrestore(&i2c_lock, flags); - - return -error; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_read -*# -*# DESCRIPTION : Reads a value from an I2C device -*# -*#--------------------------------------------------------------------------*/ -int -i2c_read(unsigned char theSlave, void *data, size_t nbytes) -{ - unsigned char b = 0; - unsigned char bytes_read = 0; - int error, cntr = 3; - unsigned long flags; - - spin_lock_irqsave(&i2c_lock, flags); - - do { - error = 0; - memset(data, 0, nbytes); - /* - * generate start condition - */ - i2c_start(); - /* - * send slave address - */ - i2c_outbyte((theSlave | 0x01)); - /* - * wait for ack - */ - if (!i2c_getack()) - error = 1; - /* - * fetch data - */ - for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { - b = i2c_inbyte(); - memcpy(data + bytes_read, &b, sizeof b); - - if (bytes_read < (nbytes - 1)) - i2c_sendack(); - } - /* - * last received byte needs to be nacked - * instead of acked - */ - i2c_sendnack(); - /* - * end sequence - */ - i2c_stop(); - } while (error && cntr--); - - spin_unlock_irqrestore(&i2c_lock, flags); - - return -error; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_writereg -*# -*# DESCRIPTION : Writes a value to an I2C device -*# -*#--------------------------------------------------------------------------*/ -int -i2c_writereg(unsigned char theSlave, unsigned char theReg, - unsigned char theValue) -{ - int error, cntr = 3; - unsigned long flags; - - spin_lock_irqsave(&i2c_lock, flags); - - do { - error = 0; - - i2c_start(); - /* - * send slave address - */ - i2c_outbyte((theSlave & 0xfe)); - /* - * wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * now select register - */ - i2c_dir_out(); - i2c_outbyte(theReg); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error |= 2; - /* - * send register register data - */ - i2c_outbyte(theValue); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error |= 4; - /* - * end byte stream - */ - i2c_stop(); - } while(error && cntr--); - - i2c_delay(CLOCK_LOW_TIME); - - spin_unlock_irqrestore(&i2c_lock, flags); - - return -error; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_readreg -*# -*# DESCRIPTION : Reads a value from the decoder registers. -*# -*#--------------------------------------------------------------------------*/ -unsigned char -i2c_readreg(unsigned char theSlave, unsigned char theReg) -{ - unsigned char b = 0; - int error, cntr = 3; - unsigned long flags; - - spin_lock_irqsave(&i2c_lock, flags); - - do { - error = 0; - /* - * generate start condition - */ - i2c_start(); - - /* - * send slave address - */ - i2c_outbyte((theSlave & 0xfe)); - /* - * wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * now select register - */ - i2c_dir_out(); - i2c_outbyte(theReg); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error |= 2; - /* - * repeat start condition - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_start(); - /* - * send slave address - */ - i2c_outbyte(theSlave | 0x01); - /* - * wait for ack - */ - if(!i2c_getack()) - error |= 4; - /* - * fetch register - */ - b = i2c_inbyte(); - /* - * last received byte needs to be nacked - * instead of acked - */ - i2c_sendnack(); - /* - * end sequence - */ - i2c_stop(); - - } while(error && cntr--); - - spin_unlock_irqrestore(&i2c_lock, flags); - - return b; -} - -static int -i2c_open(struct inode *inode, struct file *filp) -{ - return 0; -} - -static int -i2c_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -/* Main device API. ioctl's to write or read to/from i2c registers. - */ - -static long -i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int ret; - if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { - return -ENOTTY; - } - - switch (_IOC_NR(cmd)) { - case I2C_WRITEREG: - /* write to an i2c slave */ - D(printk("i2cw %d %d %d\n", - I2C_ARGSLAVE(arg), - I2C_ARGREG(arg), - I2C_ARGVALUE(arg))); - - mutex_lock(&i2c_mutex); - ret = i2c_writereg(I2C_ARGSLAVE(arg), - I2C_ARGREG(arg), - I2C_ARGVALUE(arg)); - mutex_unlock(&i2c_mutex); - return ret; - - case I2C_READREG: - { - unsigned char val; - /* read from an i2c slave */ - D(printk("i2cr %d %d ", - I2C_ARGSLAVE(arg), - I2C_ARGREG(arg))); - mutex_lock(&i2c_mutex); - val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg)); - mutex_unlock(&i2c_mutex); - D(printk("= %d\n", val)); - return val; - } - default: - return -EINVAL; - - } - - return 0; -} - -static const struct file_operations i2c_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = i2c_ioctl, - .open = i2c_open, - .release = i2c_release, - .llseek = noop_llseek, -}; - -static int __init i2c_init(void) -{ - static int res; - static int first = 1; - - if (!first) - return res; - - first = 0; - - /* Setup and enable the DATA and CLK pins */ - - res = crisv32_io_get_name(&cris_i2c_data, - CONFIG_ETRAX_V32_I2C_DATA_PORT); - if (res < 0) - return res; - - res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT); - crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out); - - return res; -} - - -static int __init i2c_register(void) -{ - int res; - - res = i2c_init(); - if (res < 0) - return res; - - /* register char device */ - - res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); - if (res < 0) { - printk(KERN_ERR "i2c: couldn't get a major number.\n"); - return res; - } - - printk(KERN_INFO - "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n"); - - return 0; -} -/* this makes sure that i2c_init is called during boot */ -module_init(i2c_register); - -/****************** END OF FILE i2c.c ********************************/ diff --git a/kernel/arch/cris/arch-v32/drivers/i2c.h b/kernel/arch/cris/arch-v32/drivers/i2c.h deleted file mode 100644 index d9cc856f8..000000000 --- a/kernel/arch/cris/arch-v32/drivers/i2c.h +++ /dev/null @@ -1,16 +0,0 @@ - -#include <linux/init.h> - -/* High level I2C actions */ -int i2c_write(unsigned char theSlave, void *data, size_t nbytes); -int i2c_read(unsigned char theSlave, void *data, size_t nbytes); -int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); -unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); - -/* Low level I2C */ -void i2c_start(void); -void i2c_stop(void); -void i2c_outbyte(unsigned char x); -unsigned char i2c_inbyte(void); -int i2c_getack(void); -void i2c_sendack(void); diff --git a/kernel/arch/cris/arch-v32/drivers/mach-a3/Makefile b/kernel/arch/cris/arch-v32/drivers/mach-a3/Makefile index 5c6d2a2a0..59028d0b9 100644 --- a/kernel/arch/cris/arch-v32/drivers/mach-a3/Makefile +++ b/kernel/arch/cris/arch-v32/drivers/mach-a3/Makefile @@ -3,4 +3,3 @@ # obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o -obj-$(CONFIG_ETRAX_GPIO) += gpio.o diff --git a/kernel/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/kernel/arch/cris/arch-v32/drivers/mach-a3/gpio.c deleted file mode 100644 index 74f9fe809..000000000 --- a/kernel/arch/cris/arch-v32/drivers/mach-a3/gpio.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Artec-3 general port I/O device - * - * Copyright (c) 2007 Axis Communications AB - * - * Authors: Bjorn Wesen (initial version) - * Ola Knutsson (LED handling) - * Johan Adolfsson (read/set directions, write, port G, - * port to ETRAX FS. - * Ricard Wanderlof (PWM for Artpec-3) - * - */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/mutex.h> - -#include <asm/etraxgpio.h> -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/gio_defs.h> -#include <hwregs/intr_vect_defs.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <mach/pinmux.h> - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -#include "../i2c.h" - -#define VIRT_I2C_ADDR 0x40 -#endif - -/* The following gio ports on ARTPEC-3 is available: - * pa 32 bits - * pb 32 bits - * pc 16 bits - * each port has a rw_px_dout, r_px_din and rw_px_oe register. - */ - -#define GPIO_MAJOR 120 /* experimental MAJOR number */ - -#define I2C_INTERRUPT_BITS 0x300 /* i2c0_done and i2c1_done bits */ - -#define D(x) - -#if 0 -static int dp_cnt; -#define DP(x) \ - do { \ - dp_cnt++; \ - if (dp_cnt % 1000 == 0) \ - x; \ - } while (0) -#else -#define DP(x) -#endif - -static DEFINE_MUTEX(gpio_mutex); -static char gpio_name[] = "etrax gpio"; - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -#endif -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static ssize_t gpio_write(struct file *file, const char __user *buf, - size_t count, loff_t *off); -static int gpio_open(struct inode *inode, struct file *filp); -static int gpio_release(struct inode *inode, struct file *filp); -static unsigned int gpio_poll(struct file *filp, - struct poll_table_struct *wait); - -/* private data per open() of this driver */ - -struct gpio_private { - struct gpio_private *next; - /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */ - unsigned char clk_mask; - unsigned char data_mask; - unsigned char write_msb; - unsigned char pad1; - /* These fields are generic */ - unsigned long highalarm, lowalarm; - wait_queue_head_t alarm_wq; - int minor; -}; - -static void gpio_set_alarm(struct gpio_private *priv); -static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); -static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, - unsigned long arg); - - -/* linked list of alarms to check for */ - -static struct gpio_private *alarmlist; - -static int wanted_interrupts; - -static DEFINE_SPINLOCK(gpio_lock); - -#define NUM_PORTS (GPIO_MINOR_LAST+1) -#define GIO_REG_RD_ADDR(reg) \ - (unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) -#define GIO_REG_WR_ADDR(reg) \ - (unsigned long *)(regi_gio + REG_WR_ADDR_gio_##reg) -static unsigned long led_dummy; -static unsigned long port_d_dummy; /* Only input on Artpec-3 */ -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static unsigned long port_e_dummy; /* Non existent on Artpec-3 */ -static unsigned long virtual_dummy; -static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE; -static unsigned short cached_virtual_gpio_read; -#endif - -static unsigned long *data_out[NUM_PORTS] = { - GIO_REG_WR_ADDR(rw_pa_dout), - GIO_REG_WR_ADDR(rw_pb_dout), - &led_dummy, - GIO_REG_WR_ADDR(rw_pc_dout), - &port_d_dummy, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &port_e_dummy, - &virtual_dummy, -#endif -}; - -static unsigned long *data_in[NUM_PORTS] = { - GIO_REG_RD_ADDR(r_pa_din), - GIO_REG_RD_ADDR(r_pb_din), - &led_dummy, - GIO_REG_RD_ADDR(r_pc_din), - GIO_REG_RD_ADDR(r_pd_din), -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &port_e_dummy, - &virtual_dummy, -#endif -}; - -static unsigned long changeable_dir[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_DIR, - CONFIG_ETRAX_PB_CHANGEABLE_DIR, - 0, - CONFIG_ETRAX_PC_CHANGEABLE_DIR, - 0, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - 0, - CONFIG_ETRAX_PV_CHANGEABLE_DIR, -#endif -}; - -static unsigned long changeable_bits[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_BITS, - CONFIG_ETRAX_PB_CHANGEABLE_BITS, - 0, - CONFIG_ETRAX_PC_CHANGEABLE_BITS, - 0, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - 0, - CONFIG_ETRAX_PV_CHANGEABLE_BITS, -#endif -}; - -static unsigned long *dir_oe[NUM_PORTS] = { - GIO_REG_WR_ADDR(rw_pa_oe), - GIO_REG_WR_ADDR(rw_pb_oe), - &led_dummy, - GIO_REG_WR_ADDR(rw_pc_oe), - &port_d_dummy, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &port_e_dummy, - &virtual_rw_pv_oe, -#endif -}; - -static void gpio_set_alarm(struct gpio_private *priv) -{ - int bit; - int intr_cfg; - int mask; - int pins; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - intr_cfg = REG_RD_INT(gio, regi_gio, rw_intr_cfg); - pins = REG_RD_INT(gio, regi_gio, rw_intr_pins); - mask = REG_RD_INT(gio, regi_gio, rw_intr_mask) & I2C_INTERRUPT_BITS; - - for (bit = 0; bit < 32; bit++) { - int intr = bit % 8; - int pin = bit / 8; - if (priv->minor < GPIO_MINOR_LEDS) - pin += priv->minor * 4; - else - pin += (priv->minor - 1) * 4; - - if (priv->highalarm & (1<<bit)) { - intr_cfg |= (regk_gio_hi << (intr * 3)); - mask |= 1 << intr; - wanted_interrupts = mask & 0xff; - pins |= pin << (intr * 4); - } else if (priv->lowalarm & (1<<bit)) { - intr_cfg |= (regk_gio_lo << (intr * 3)); - mask |= 1 << intr; - wanted_interrupts = mask & 0xff; - pins |= pin << (intr * 4); - } - } - - REG_WR_INT(gio, regi_gio, rw_intr_cfg, intr_cfg); - REG_WR_INT(gio, regi_gio, rw_intr_pins, pins); - REG_WR_INT(gio, regi_gio, rw_intr_mask, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); -} - -static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait) -{ - unsigned int mask = 0; - struct gpio_private *priv = file->private_data; - unsigned long data; - unsigned long tmp; - - if (priv->minor >= GPIO_MINOR_PWM0 && - priv->minor <= GPIO_MINOR_LAST_PWM) - return 0; - - poll_wait(file, &priv->alarm_wq, wait); - if (priv->minor <= GPIO_MINOR_D) { - data = readl(data_in[priv->minor]); - REG_WR_INT(gio, regi_gio, rw_ack_intr, wanted_interrupts); - tmp = REG_RD_INT(gio, regi_gio, rw_intr_mask); - tmp &= I2C_INTERRUPT_BITS; - tmp |= wanted_interrupts; - REG_WR_INT(gio, regi_gio, rw_intr_mask, tmp); - } else - return 0; - - if ((data & priv->highalarm) || (~data & priv->lowalarm)) - mask = POLLIN|POLLRDNORM; - - DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask)); - return mask; -} - -static irqreturn_t gpio_interrupt(int irq, void *dev_id) -{ - reg_gio_rw_intr_mask intr_mask; - reg_gio_r_masked_intr masked_intr; - reg_gio_rw_ack_intr ack_intr; - unsigned long flags; - unsigned long tmp; - unsigned long tmp2; -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - unsigned char enable_gpiov_ack = 0; -#endif - - /* Find what PA interrupts are active */ - masked_intr = REG_RD(gio, regi_gio, r_masked_intr); - tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr); - - /* Find those that we have enabled */ - spin_lock_irqsave(&gpio_lock, flags); - tmp &= wanted_interrupts; - spin_unlock_irqrestore(&gpio_lock, flags); - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Something changed on virtual GPIO. Interrupt is acked by - * reading the device. - */ - if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) { - i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read, - sizeof(cached_virtual_gpio_read)); - enable_gpiov_ack = 1; - } -#endif - - /* Ack them */ - ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); - REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); - - /* Disable those interrupts.. */ - intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); - tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); - tmp2 &= ~tmp; -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Do not disable interrupt on virtual GPIO. Changes on virtual - * pins are only noticed by an interrupt. - */ - if (enable_gpiov_ack) - tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); - REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); - - return IRQ_RETVAL(tmp); -} - -static void gpio_write_bit(unsigned long *port, unsigned char data, int bit, - unsigned char clk_mask, unsigned char data_mask) -{ - unsigned long shadow = readl(port) & ~clk_mask; - writel(shadow, port); - if (data & 1 << bit) - shadow |= data_mask; - else - shadow &= ~data_mask; - writel(shadow, port); - /* For FPGA: min 5.0ns (DCC) before CCLK high */ - shadow |= clk_mask; - writel(shadow, port); -} - -static void gpio_write_byte(struct gpio_private *priv, unsigned long *port, - unsigned char data) -{ - int i; - - if (priv->write_msb) - for (i = 7; i >= 0; i--) - gpio_write_bit(port, data, i, priv->clk_mask, - priv->data_mask); - else - for (i = 0; i <= 7; i++) - gpio_write_bit(port, data, i, priv->clk_mask, - priv->data_mask); -} - - -static ssize_t gpio_write(struct file *file, const char __user *buf, - size_t count, loff_t *off) -{ - struct gpio_private *priv = file->private_data; - unsigned long flags; - ssize_t retval = count; - /* Only bits 0-7 may be used for write operations but allow all - devices except leds... */ -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - if (priv->minor == GPIO_MINOR_V) - return -EFAULT; -#endif - if (priv->minor == GPIO_MINOR_LEDS) - return -EFAULT; - - if (priv->minor >= GPIO_MINOR_PWM0 && - priv->minor <= GPIO_MINOR_LAST_PWM) - return -EFAULT; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - - /* It must have been configured using the IO_CFG_WRITE_MODE */ - /* Perhaps a better error code? */ - if (priv->clk_mask == 0 || priv->data_mask == 0) - return -EPERM; - - D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X " - "msb: %i\n", - count, priv->data_mask, priv->clk_mask, priv->write_msb)); - - spin_lock_irqsave(&gpio_lock, flags); - - while (count--) - gpio_write_byte(priv, data_out[priv->minor], *buf++); - - spin_unlock_irqrestore(&gpio_lock, flags); - return retval; -} - -static int gpio_open(struct inode *inode, struct file *filp) -{ - struct gpio_private *priv; - int p = iminor(inode); - - if (p > GPIO_MINOR_LAST_PWM || - (p > GPIO_MINOR_LAST && p < GPIO_MINOR_PWM0)) - return -EINVAL; - - priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL); - - if (!priv) - return -ENOMEM; - - mutex_lock(&gpio_mutex); - memset(priv, 0, sizeof(*priv)); - - priv->minor = p; - filp->private_data = priv; - - /* initialize the io/alarm struct, not for PWM ports though */ - if (p <= GPIO_MINOR_LAST) { - - priv->clk_mask = 0; - priv->data_mask = 0; - priv->highalarm = 0; - priv->lowalarm = 0; - - init_waitqueue_head(&priv->alarm_wq); - - /* link it into our alarmlist */ - spin_lock_irq(&gpio_lock); - priv->next = alarmlist; - alarmlist = priv; - spin_unlock_irq(&gpio_lock); - } - - mutex_unlock(&gpio_mutex); - return 0; -} - -static int gpio_release(struct inode *inode, struct file *filp) -{ - struct gpio_private *p; - struct gpio_private *todel; - /* local copies while updating them: */ - unsigned long a_high, a_low; - - /* prepare to free private structure */ - todel = filp->private_data; - - /* unlink from alarmlist - only for non-PWM ports though */ - if (todel->minor <= GPIO_MINOR_LAST) { - spin_lock_irq(&gpio_lock); - p = alarmlist; - - if (p == todel) - alarmlist = todel->next; - else { - while (p->next != todel) - p = p->next; - p->next = todel->next; - } - - /* Check if there are still any alarms set */ - p = alarmlist; - a_high = 0; - a_low = 0; - while (p) { - if (p->minor == GPIO_MINOR_A) { -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - a_high |= p->highalarm; - a_low |= p->lowalarm; - } - - p = p->next; - } - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Variable 'a_low' needs to be set here again - * to ensure that interrupt for virtual GPIO is handled. - */ - a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - - spin_unlock_irq(&gpio_lock); - } - kfree(todel); - - return 0; -} - -/* Main device API. ioctl's to read/set/clear bits, as well as to - * set alarms to wait for using a subsequent select(). - */ - -inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg) -{ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input - */ - unsigned long flags; - unsigned long dir_shadow; - - spin_lock_irqsave(&gpio_lock, flags); - - dir_shadow = readl(dir_oe[priv->minor]) & - ~(arg & changeable_dir[priv->minor]); - writel(dir_shadow, dir_oe[priv->minor]); - - spin_unlock_irqrestore(&gpio_lock, flags); - - if (priv->minor == GPIO_MINOR_C) - dir_shadow ^= 0xFFFF; /* Only 16 bits */ -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - else if (priv->minor == GPIO_MINOR_V) - dir_shadow ^= 0xFFFF; /* Only 16 bits */ -#endif - else - dir_shadow ^= 0xFFFFFFFF; /* PA, PB and PD 32 bits */ - - return dir_shadow; - -} /* setget_input */ - -static inline unsigned long setget_output(struct gpio_private *priv, - unsigned long arg) -{ - unsigned long flags; - unsigned long dir_shadow; - - spin_lock_irqsave(&gpio_lock, flags); - - dir_shadow = readl(dir_oe[priv->minor]) | - (arg & changeable_dir[priv->minor]); - writel(dir_shadow, dir_oe[priv->minor]); - - spin_unlock_irqrestore(&gpio_lock, flags); - return dir_shadow; -} /* setget_output */ - -static long gpio_ioctl_unlocked(struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned long flags; - unsigned long val; - unsigned long shadow; - struct gpio_private *priv = file->private_data; - - if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) - return -ENOTTY; - - /* Check for special ioctl handlers first */ - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - if (priv->minor == GPIO_MINOR_V) - return virtual_gpio_ioctl(file, cmd, arg); -#endif - - if (priv->minor == GPIO_MINOR_LEDS) - return gpio_leds_ioctl(cmd, arg); - - if (priv->minor >= GPIO_MINOR_PWM0 && - priv->minor <= GPIO_MINOR_LAST_PWM) - return gpio_pwm_ioctl(priv, cmd, arg); - - switch (_IOC_NR(cmd)) { - case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ - /* Read the port. */ - return readl(data_in[priv->minor]); - case IO_SETBITS: - spin_lock_irqsave(&gpio_lock, flags); - /* Set changeable bits with a 1 in arg. */ - shadow = readl(data_out[priv->minor]) | - (arg & changeable_bits[priv->minor]); - writel(shadow, data_out[priv->minor]); - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_CLRBITS: - spin_lock_irqsave(&gpio_lock, flags); - /* Clear changeable bits with a 1 in arg. */ - shadow = readl(data_out[priv->minor]) & - ~(arg & changeable_bits[priv->minor]); - writel(shadow, data_out[priv->minor]); - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_HIGHALARM: - /* Set alarm when bits with 1 in arg go high. */ - priv->highalarm |= arg; - gpio_set_alarm(priv); - break; - case IO_LOWALARM: - /* Set alarm when bits with 1 in arg go low. */ - priv->lowalarm |= arg; - gpio_set_alarm(priv); - break; - case IO_CLRALARM: - /* Clear alarm for bits with 1 in arg. */ - priv->highalarm &= ~arg; - priv->lowalarm &= ~arg; - gpio_set_alarm(priv); - break; - case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ - /* Read direction 0=input 1=output */ - return readl(dir_oe[priv->minor]); - - case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input - */ - return setget_input(priv, arg); - - case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ - /* Set direction 0=unchanged 1=output, - * return mask with 1=output - */ - return setget_output(priv, arg); - - case IO_CFG_WRITE_MODE: - { - int res = -EPERM; - unsigned long dir_shadow, clk_mask, data_mask, write_msb; - - clk_mask = arg & 0xFF; - data_mask = (arg >> 8) & 0xFF; - write_msb = (arg >> 16) & 0x01; - - /* Check if we're allowed to change the bits and - * the direction is correct - */ - spin_lock_irqsave(&gpio_lock, flags); - dir_shadow = readl(dir_oe[priv->minor]); - if ((clk_mask & changeable_bits[priv->minor]) && - (data_mask & changeable_bits[priv->minor]) && - (clk_mask & dir_shadow) && - (data_mask & dir_shadow)) { - priv->clk_mask = clk_mask; - priv->data_mask = data_mask; - priv->write_msb = write_msb; - res = 0; - } - spin_unlock_irqrestore(&gpio_lock, flags); - - return res; - } - case IO_READ_INBITS: - /* *arg is result of reading the input pins */ - val = readl(data_in[priv->minor]); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - return 0; - case IO_READ_OUTBITS: - /* *arg is result of reading the output shadow */ - val = *data_out[priv->minor]; - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_INPUT: - /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) - return -EFAULT; - val = setget_input(priv, val); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_OUTPUT: - /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) - return -EFAULT; - val = setget_output(priv, val); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - break; - default: - return -EINVAL; - } /* switch */ - - return 0; -} - -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - mutex_lock(&gpio_mutex); - ret = gpio_ioctl_unlocked(file, cmd, arg); - mutex_unlock(&gpio_mutex); - - return ret; -} - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - unsigned long flags; - unsigned short val; - unsigned short shadow; - struct gpio_private *priv = file->private_data; - - switch (_IOC_NR(cmd)) { - case IO_SETBITS: - spin_lock_irqsave(&gpio_lock, flags); - /* Set changeable bits with a 1 in arg. */ - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - shadow |= ~readl(dir_oe[priv->minor]) | - (arg & changeable_bits[priv->minor]); - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_CLRBITS: - spin_lock_irqsave(&gpio_lock, flags); - /* Clear changeable bits with a 1 in arg. */ - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - shadow |= ~readl(dir_oe[priv->minor]) & - ~(arg & changeable_bits[priv->minor]); - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_HIGHALARM: - /* Set alarm when bits with 1 in arg go high. */ - priv->highalarm |= arg; - break; - case IO_LOWALARM: - /* Set alarm when bits with 1 in arg go low. */ - priv->lowalarm |= arg; - break; - case IO_CLRALARM: - /* Clear alarm for bits with 1 in arg. */ - priv->highalarm &= ~arg; - priv->lowalarm &= ~arg; - break; - case IO_CFG_WRITE_MODE: - { - unsigned long dir_shadow; - dir_shadow = readl(dir_oe[priv->minor]); - - priv->clk_mask = arg & 0xFF; - priv->data_mask = (arg >> 8) & 0xFF; - priv->write_msb = (arg >> 16) & 0x01; - /* Check if we're allowed to change the bits and - * the direction is correct - */ - if (!((priv->clk_mask & changeable_bits[priv->minor]) && - (priv->data_mask & changeable_bits[priv->minor]) && - (priv->clk_mask & dir_shadow) && - (priv->data_mask & dir_shadow))) { - priv->clk_mask = 0; - priv->data_mask = 0; - return -EPERM; - } - break; - } - case IO_READ_INBITS: - /* *arg is result of reading the input pins */ - val = cached_virtual_gpio_read & ~readl(dir_oe[priv->minor]); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - return 0; - - case IO_READ_OUTBITS: - /* *arg is result of reading the output shadow */ - i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val)); - val &= readl(dir_oe[priv->minor]); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_INPUT: - { - /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ - unsigned short input_mask = ~readl(dir_oe[priv->minor]); - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) - return -EFAULT; - val = setget_input(priv, val); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - if ((input_mask & val) != input_mask) { - /* Input pins changed. All ports desired as input - * should be set to logic 1. - */ - unsigned short change = input_mask ^ val; - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, - sizeof(shadow)); - shadow &= ~change; - shadow |= val; - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, - sizeof(shadow)); - } - break; - } - case IO_SETGET_OUTPUT: - /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) - return -EFAULT; - val = setget_output(priv, val); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - return -EFAULT; - break; - default: - return -EINVAL; - } /* switch */ - return 0; -} -#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */ - -static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg) -{ - unsigned char green; - unsigned char red; - - switch (_IOC_NR(cmd)) { - case IO_LEDACTIVE_SET: - green = ((unsigned char) arg) & 1; - red = (((unsigned char) arg) >> 1) & 1; - CRIS_LED_ACTIVE_SET_G(green); - CRIS_LED_ACTIVE_SET_R(red); - break; - - default: - return -EINVAL; - } /* switch */ - - return 0; -} - -static int gpio_pwm_set_mode(unsigned long arg, int pwm_port) -{ - int pinmux_pwm = pinmux_pwm0 + pwm_port; - int mode; - reg_gio_rw_pwm0_ctrl rw_pwm_ctrl = { - .ccd_val = 0, - .ccd_override = regk_gio_no, - .mode = regk_gio_no - }; - int allocstatus; - - if (get_user(mode, &((struct io_pwm_set_mode *) arg)->mode)) - return -EFAULT; - rw_pwm_ctrl.mode = mode; - if (mode != PWM_OFF) - allocstatus = crisv32_pinmux_alloc_fixed(pinmux_pwm); - else - allocstatus = crisv32_pinmux_dealloc_fixed(pinmux_pwm); - if (allocstatus) - return allocstatus; - REG_WRITE(reg_gio_rw_pwm0_ctrl, REG_ADDR(gio, regi_gio, rw_pwm0_ctrl) + - 12 * pwm_port, rw_pwm_ctrl); - return 0; -} - -static int gpio_pwm_set_period(unsigned long arg, int pwm_port) -{ - struct io_pwm_set_period periods; - reg_gio_rw_pwm0_var rw_pwm_widths; - - if (copy_from_user(&periods, (void __user *)arg, sizeof(periods))) - return -EFAULT; - if (periods.lo > 8191 || periods.hi > 8191) - return -EINVAL; - rw_pwm_widths.lo = periods.lo; - rw_pwm_widths.hi = periods.hi; - REG_WRITE(reg_gio_rw_pwm0_var, REG_ADDR(gio, regi_gio, rw_pwm0_var) + - 12 * pwm_port, rw_pwm_widths); - return 0; -} - -static int gpio_pwm_set_duty(unsigned long arg, int pwm_port) -{ - unsigned int duty; - reg_gio_rw_pwm0_data rw_pwm_duty; - - if (get_user(duty, &((struct io_pwm_set_duty *) arg)->duty)) - return -EFAULT; - if (duty > 255) - return -EINVAL; - rw_pwm_duty.data = duty; - REG_WRITE(reg_gio_rw_pwm0_data, REG_ADDR(gio, regi_gio, rw_pwm0_data) + - 12 * pwm_port, rw_pwm_duty); - return 0; -} - -static int gpio_pwm_ioctl(struct gpio_private *priv, unsigned int cmd, - unsigned long arg) -{ - int pwm_port = priv->minor - GPIO_MINOR_PWM0; - - switch (_IOC_NR(cmd)) { - case IO_PWM_SET_MODE: - return gpio_pwm_set_mode(arg, pwm_port); - case IO_PWM_SET_PERIOD: - return gpio_pwm_set_period(arg, pwm_port); - case IO_PWM_SET_DUTY: - return gpio_pwm_set_duty(arg, pwm_port); - default: - return -EINVAL; - } - return 0; -} - -static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .unlocked_ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, - .llseek = noop_llseek, -}; - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static void __init virtual_gpio_init(void) -{ - reg_gio_rw_intr_cfg intr_cfg; - reg_gio_rw_intr_mask intr_mask; - unsigned short shadow; - - shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */ - shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT; - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - - /* Set interrupt mask and on what state the interrupt shall trigger. - * For virtual gpio the interrupt shall trigger on logic '0'. - */ - intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); - intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); - - switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) { - case 0: - intr_cfg.pa0 = regk_gio_lo; - intr_mask.pa0 = regk_gio_yes; - break; - case 1: - intr_cfg.pa1 = regk_gio_lo; - intr_mask.pa1 = regk_gio_yes; - break; - case 2: - intr_cfg.pa2 = regk_gio_lo; - intr_mask.pa2 = regk_gio_yes; - break; - case 3: - intr_cfg.pa3 = regk_gio_lo; - intr_mask.pa3 = regk_gio_yes; - break; - case 4: - intr_cfg.pa4 = regk_gio_lo; - intr_mask.pa4 = regk_gio_yes; - break; - case 5: - intr_cfg.pa5 = regk_gio_lo; - intr_mask.pa5 = regk_gio_yes; - break; - case 6: - intr_cfg.pa6 = regk_gio_lo; - intr_mask.pa6 = regk_gio_yes; - break; - case 7: - intr_cfg.pa7 = regk_gio_lo; - intr_mask.pa7 = regk_gio_yes; - break; - } - - REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); - REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); -} -#endif - -/* main driver initialization routine, called from mem.c */ - -static int __init gpio_init(void) -{ - int res; - - printk(KERN_INFO "ETRAX FS GPIO driver v2.7, (c) 2003-2008 " - "Axis Communications AB\n"); - - /* do the formalities */ - - res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); - if (res < 0) { - printk(KERN_ERR "gpio: couldn't get a major number.\n"); - return res; - } - - /* Clear all leds */ - CRIS_LED_NETWORK_GRP0_SET(0); - CRIS_LED_NETWORK_GRP1_SET(0); - CRIS_LED_ACTIVE_SET(0); - CRIS_LED_DISK_READ(0); - CRIS_LED_DISK_WRITE(0); - - int res2 = request_irq(GIO_INTR_VECT, gpio_interrupt, - IRQF_SHARED, "gpio", &alarmlist); - if (res2) { - printk(KERN_ERR "err: irq for gpio\n"); - return res2; - } - - /* No IRQs by default. */ - REG_WR_INT(gio, regi_gio, rw_intr_pins, 0); - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - virtual_gpio_init(); -#endif - - return res; -} - -/* this makes sure that gpio_init is called during kernel boot */ - -module_init(gpio_init); diff --git a/kernel/arch/cris/arch-v32/drivers/mach-fs/Makefile b/kernel/arch/cris/arch-v32/drivers/mach-fs/Makefile index 5c6d2a2a0..59028d0b9 100644 --- a/kernel/arch/cris/arch-v32/drivers/mach-fs/Makefile +++ b/kernel/arch/cris/arch-v32/drivers/mach-fs/Makefile @@ -3,4 +3,3 @@ # obj-$(CONFIG_ETRAX_NANDFLASH) += nandflash.o -obj-$(CONFIG_ETRAX_GPIO) += gpio.o diff --git a/kernel/arch/cris/arch-v32/drivers/mach-fs/gpio.c b/kernel/arch/cris/arch-v32/drivers/mach-fs/gpio.c deleted file mode 100644 index 009f4ee1b..000000000 --- a/kernel/arch/cris/arch-v32/drivers/mach-fs/gpio.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * ETRAX CRISv32 general port I/O device - * - * Copyright (c) 1999-2006 Axis Communications AB - * - * Authors: Bjorn Wesen (initial version) - * Ola Knutsson (LED handling) - * Johan Adolfsson (read/set directions, write, port G, - * port to ETRAX FS. - * - */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/mutex.h> - -#include <asm/etraxgpio.h> -#include <hwregs/reg_map.h> -#include <hwregs/reg_rdwr.h> -#include <hwregs/gio_defs.h> -#include <hwregs/intr_vect_defs.h> -#include <asm/io.h> -#include <asm/irq.h> - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -#include "../i2c.h" - -#define VIRT_I2C_ADDR 0x40 -#endif - -/* The following gio ports on ETRAX FS is available: - * pa 8 bits, supports interrupts off, hi, low, set, posedge, negedge anyedge - * pb 18 bits - * pc 18 bits - * pd 18 bits - * pe 18 bits - * each port has a rw_px_dout, r_px_din and rw_px_oe register. - */ - -#define GPIO_MAJOR 120 /* experimental MAJOR number */ - -#define D(x) - -#if 0 -static int dp_cnt; -#define DP(x) \ - do { \ - dp_cnt++; \ - if (dp_cnt % 1000 == 0) \ - x; \ - } while (0) -#else -#define DP(x) -#endif - -static DEFINE_MUTEX(gpio_mutex); -static char gpio_name[] = "etrax gpio"; - -#if 0 -static wait_queue_head_t *gpio_wq; -#endif - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -#endif -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static ssize_t gpio_write(struct file *file, const char *buf, size_t count, - loff_t *off); -static int gpio_open(struct inode *inode, struct file *filp); -static int gpio_release(struct inode *inode, struct file *filp); -static unsigned int gpio_poll(struct file *filp, - struct poll_table_struct *wait); - -/* private data per open() of this driver */ - -struct gpio_private { - struct gpio_private *next; - /* The IO_CFG_WRITE_MODE_VALUE only support 8 bits: */ - unsigned char clk_mask; - unsigned char data_mask; - unsigned char write_msb; - unsigned char pad1; - /* These fields are generic */ - unsigned long highalarm, lowalarm; - wait_queue_head_t alarm_wq; - int minor; -}; - -/* linked list of alarms to check for */ - -static struct gpio_private *alarmlist; - -static int gpio_some_alarms; /* Set if someone uses alarm */ -static unsigned long gpio_pa_high_alarms; -static unsigned long gpio_pa_low_alarms; - -static DEFINE_SPINLOCK(alarm_lock); - -#define NUM_PORTS (GPIO_MINOR_LAST+1) -#define GIO_REG_RD_ADDR(reg) \ - (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) -#define GIO_REG_WR_ADDR(reg) \ - (volatile unsigned long *)(regi_gio + REG_RD_ADDR_gio_##reg) -unsigned long led_dummy; -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static unsigned long virtual_dummy; -static unsigned long virtual_rw_pv_oe = CONFIG_ETRAX_DEF_GIO_PV_OE; -static unsigned short cached_virtual_gpio_read; -#endif - -static volatile unsigned long *data_out[NUM_PORTS] = { - GIO_REG_WR_ADDR(rw_pa_dout), - GIO_REG_WR_ADDR(rw_pb_dout), - &led_dummy, - GIO_REG_WR_ADDR(rw_pc_dout), - GIO_REG_WR_ADDR(rw_pd_dout), - GIO_REG_WR_ADDR(rw_pe_dout), -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &virtual_dummy, -#endif -}; - -static volatile unsigned long *data_in[NUM_PORTS] = { - GIO_REG_RD_ADDR(r_pa_din), - GIO_REG_RD_ADDR(r_pb_din), - &led_dummy, - GIO_REG_RD_ADDR(r_pc_din), - GIO_REG_RD_ADDR(r_pd_din), - GIO_REG_RD_ADDR(r_pe_din), -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &virtual_dummy, -#endif -}; - -static unsigned long changeable_dir[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_DIR, - CONFIG_ETRAX_PB_CHANGEABLE_DIR, - 0, - CONFIG_ETRAX_PC_CHANGEABLE_DIR, - CONFIG_ETRAX_PD_CHANGEABLE_DIR, - CONFIG_ETRAX_PE_CHANGEABLE_DIR, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - CONFIG_ETRAX_PV_CHANGEABLE_DIR, -#endif -}; - -static unsigned long changeable_bits[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_BITS, - CONFIG_ETRAX_PB_CHANGEABLE_BITS, - 0, - CONFIG_ETRAX_PC_CHANGEABLE_BITS, - CONFIG_ETRAX_PD_CHANGEABLE_BITS, - CONFIG_ETRAX_PE_CHANGEABLE_BITS, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - CONFIG_ETRAX_PV_CHANGEABLE_BITS, -#endif -}; - -static volatile unsigned long *dir_oe[NUM_PORTS] = { - GIO_REG_WR_ADDR(rw_pa_oe), - GIO_REG_WR_ADDR(rw_pb_oe), - &led_dummy, - GIO_REG_WR_ADDR(rw_pc_oe), - GIO_REG_WR_ADDR(rw_pd_oe), - GIO_REG_WR_ADDR(rw_pe_oe), -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - &virtual_rw_pv_oe, -#endif -}; - - - -static unsigned int gpio_poll(struct file *file, struct poll_table_struct *wait) -{ - unsigned int mask = 0; - struct gpio_private *priv = file->private_data; - unsigned long data; - poll_wait(file, &priv->alarm_wq, wait); - if (priv->minor == GPIO_MINOR_A) { - reg_gio_rw_intr_cfg intr_cfg; - unsigned long tmp; - unsigned long flags; - - local_irq_save(flags); - data = REG_TYPE_CONV(unsigned long, reg_gio_r_pa_din, - REG_RD(gio, regi_gio, r_pa_din)); - /* PA has support for interrupt - * lets activate high for those low and with highalarm set - */ - intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); - - tmp = ~data & priv->highalarm & 0xFF; - if (tmp & (1 << 0)) - intr_cfg.pa0 = regk_gio_hi; - if (tmp & (1 << 1)) - intr_cfg.pa1 = regk_gio_hi; - if (tmp & (1 << 2)) - intr_cfg.pa2 = regk_gio_hi; - if (tmp & (1 << 3)) - intr_cfg.pa3 = regk_gio_hi; - if (tmp & (1 << 4)) - intr_cfg.pa4 = regk_gio_hi; - if (tmp & (1 << 5)) - intr_cfg.pa5 = regk_gio_hi; - if (tmp & (1 << 6)) - intr_cfg.pa6 = regk_gio_hi; - if (tmp & (1 << 7)) - intr_cfg.pa7 = regk_gio_hi; - /* - * lets activate low for those high and with lowalarm set - */ - tmp = data & priv->lowalarm & 0xFF; - if (tmp & (1 << 0)) - intr_cfg.pa0 = regk_gio_lo; - if (tmp & (1 << 1)) - intr_cfg.pa1 = regk_gio_lo; - if (tmp & (1 << 2)) - intr_cfg.pa2 = regk_gio_lo; - if (tmp & (1 << 3)) - intr_cfg.pa3 = regk_gio_lo; - if (tmp & (1 << 4)) - intr_cfg.pa4 = regk_gio_lo; - if (tmp & (1 << 5)) - intr_cfg.pa5 = regk_gio_lo; - if (tmp & (1 << 6)) - intr_cfg.pa6 = regk_gio_lo; - if (tmp & (1 << 7)) - intr_cfg.pa7 = regk_gio_lo; - - REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); - local_irq_restore(flags); - } else if (priv->minor <= GPIO_MINOR_E) - data = *data_in[priv->minor]; - else - return 0; - - if ((data & priv->highalarm) || (~data & priv->lowalarm)) - mask = POLLIN|POLLRDNORM; - - DP(printk(KERN_DEBUG "gpio_poll ready: mask 0x%08X\n", mask)); - return mask; -} - -int etrax_gpio_wake_up_check(void) -{ - struct gpio_private *priv; - unsigned long data = 0; - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&alarm_lock, flags); - priv = alarmlist; - while (priv) { -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - if (priv->minor == GPIO_MINOR_V) - data = (unsigned long)cached_virtual_gpio_read; - else { - data = *data_in[priv->minor]; - if (priv->minor == GPIO_MINOR_A) - priv->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); - } -#else - data = *data_in[priv->minor]; -#endif - if ((data & priv->highalarm) || - (~data & priv->lowalarm)) { - DP(printk(KERN_DEBUG - "etrax_gpio_wake_up_check %i\n", priv->minor)); - wake_up_interruptible(&priv->alarm_wq); - ret = 1; - } - priv = priv->next; - } - spin_unlock_irqrestore(&alarm_lock, flags); - return ret; -} - -static irqreturn_t -gpio_poll_timer_interrupt(int irq, void *dev_id) -{ - if (gpio_some_alarms) - return IRQ_RETVAL(etrax_gpio_wake_up_check()); - return IRQ_NONE; -} - -static irqreturn_t -gpio_pa_interrupt(int irq, void *dev_id) -{ - reg_gio_rw_intr_mask intr_mask; - reg_gio_r_masked_intr masked_intr; - reg_gio_rw_ack_intr ack_intr; - unsigned long tmp; - unsigned long tmp2; -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - unsigned char enable_gpiov_ack = 0; -#endif - - /* Find what PA interrupts are active */ - masked_intr = REG_RD(gio, regi_gio, r_masked_intr); - tmp = REG_TYPE_CONV(unsigned long, reg_gio_r_masked_intr, masked_intr); - - /* Find those that we have enabled */ - spin_lock(&alarm_lock); - tmp &= (gpio_pa_high_alarms | gpio_pa_low_alarms); - spin_unlock(&alarm_lock); - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Something changed on virtual GPIO. Interrupt is acked by - * reading the device. - */ - if (tmp & (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN)) { - i2c_read(VIRT_I2C_ADDR, (void *)&cached_virtual_gpio_read, - sizeof(cached_virtual_gpio_read)); - enable_gpiov_ack = 1; - } -#endif - - /* Ack them */ - ack_intr = REG_TYPE_CONV(reg_gio_rw_ack_intr, unsigned long, tmp); - REG_WR(gio, regi_gio, rw_ack_intr, ack_intr); - - /* Disable those interrupts.. */ - intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); - tmp2 = REG_TYPE_CONV(unsigned long, reg_gio_rw_intr_mask, intr_mask); - tmp2 &= ~tmp; -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Do not disable interrupt on virtual GPIO. Changes on virtual - * pins are only noticed by an interrupt. - */ - if (enable_gpiov_ack) - tmp2 |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - intr_mask = REG_TYPE_CONV(reg_gio_rw_intr_mask, unsigned long, tmp2); - REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); - - if (gpio_some_alarms) - return IRQ_RETVAL(etrax_gpio_wake_up_check()); - return IRQ_NONE; -} - - -static ssize_t gpio_write(struct file *file, const char *buf, size_t count, - loff_t *off) -{ - struct gpio_private *priv = file->private_data; - unsigned char data, clk_mask, data_mask, write_msb; - unsigned long flags; - unsigned long shadow; - volatile unsigned long *port; - ssize_t retval = count; - /* Only bits 0-7 may be used for write operations but allow all - devices except leds... */ -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - if (priv->minor == GPIO_MINOR_V) - return -EFAULT; -#endif - if (priv->minor == GPIO_MINOR_LEDS) - return -EFAULT; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - clk_mask = priv->clk_mask; - data_mask = priv->data_mask; - /* It must have been configured using the IO_CFG_WRITE_MODE */ - /* Perhaps a better error code? */ - if (clk_mask == 0 || data_mask == 0) - return -EPERM; - write_msb = priv->write_msb; - D(printk(KERN_DEBUG "gpio_write: %lu to data 0x%02X clk 0x%02X " - "msb: %i\n", count, data_mask, clk_mask, write_msb)); - port = data_out[priv->minor]; - - while (count--) { - int i; - data = *buf++; - if (priv->write_msb) { - for (i = 7; i >= 0; i--) { - local_irq_save(flags); - shadow = *port; - *port = shadow &= ~clk_mask; - if (data & 1<<i) - *port = shadow |= data_mask; - else - *port = shadow &= ~data_mask; - /* For FPGA: min 5.0ns (DCC) before CCLK high */ - *port = shadow |= clk_mask; - local_irq_restore(flags); - } - } else { - for (i = 0; i <= 7; i++) { - local_irq_save(flags); - shadow = *port; - *port = shadow &= ~clk_mask; - if (data & 1<<i) - *port = shadow |= data_mask; - else - *port = shadow &= ~data_mask; - /* For FPGA: min 5.0ns (DCC) before CCLK high */ - *port = shadow |= clk_mask; - local_irq_restore(flags); - } - } - } - return retval; -} - - - -static int -gpio_open(struct inode *inode, struct file *filp) -{ - struct gpio_private *priv; - int p = iminor(inode); - - if (p > GPIO_MINOR_LAST) - return -EINVAL; - - priv = kmalloc(sizeof(struct gpio_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - mutex_lock(&gpio_mutex); - memset(priv, 0, sizeof(*priv)); - - priv->minor = p; - - /* initialize the io/alarm struct */ - - priv->clk_mask = 0; - priv->data_mask = 0; - priv->highalarm = 0; - priv->lowalarm = 0; - init_waitqueue_head(&priv->alarm_wq); - - filp->private_data = (void *)priv; - - /* link it into our alarmlist */ - spin_lock_irq(&alarm_lock); - priv->next = alarmlist; - alarmlist = priv; - spin_unlock_irq(&alarm_lock); - - mutex_unlock(&gpio_mutex); - return 0; -} - -static int -gpio_release(struct inode *inode, struct file *filp) -{ - struct gpio_private *p; - struct gpio_private *todel; - /* local copies while updating them: */ - unsigned long a_high, a_low; - unsigned long some_alarms; - - /* unlink from alarmlist and free the private structure */ - - spin_lock_irq(&alarm_lock); - p = alarmlist; - todel = filp->private_data; - - if (p == todel) { - alarmlist = todel->next; - } else { - while (p->next != todel) - p = p->next; - p->next = todel->next; - } - - kfree(todel); - /* Check if there are still any alarms set */ - p = alarmlist; - some_alarms = 0; - a_high = 0; - a_low = 0; - while (p) { - if (p->minor == GPIO_MINOR_A) { -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - p->lowalarm |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - a_high |= p->highalarm; - a_low |= p->lowalarm; - } - - if (p->highalarm | p->lowalarm) - some_alarms = 1; - p = p->next; - } - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - /* Variables 'some_alarms' and 'a_low' needs to be set here again - * to ensure that interrupt for virtual GPIO is handled. - */ - some_alarms = 1; - a_low |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); -#endif - - gpio_some_alarms = some_alarms; - gpio_pa_high_alarms = a_high; - gpio_pa_low_alarms = a_low; - spin_unlock_irq(&alarm_lock); - - return 0; -} - -/* Main device API. ioctl's to read/set/clear bits, as well as to - * set alarms to wait for using a subsequent select(). - */ - -inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg) -{ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input - */ - unsigned long flags; - unsigned long dir_shadow; - - local_irq_save(flags); - dir_shadow = *dir_oe[priv->minor]; - dir_shadow &= ~(arg & changeable_dir[priv->minor]); - *dir_oe[priv->minor] = dir_shadow; - local_irq_restore(flags); - - if (priv->minor == GPIO_MINOR_A) - dir_shadow ^= 0xFF; /* Only 8 bits */ -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - else if (priv->minor == GPIO_MINOR_V) - dir_shadow ^= 0xFFFF; /* Only 16 bits */ -#endif - else - dir_shadow ^= 0x3FFFF; /* Only 18 bits */ - return dir_shadow; - -} /* setget_input */ - -inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg) -{ - unsigned long flags; - unsigned long dir_shadow; - - local_irq_save(flags); - dir_shadow = *dir_oe[priv->minor]; - dir_shadow |= (arg & changeable_dir[priv->minor]); - *dir_oe[priv->minor] = dir_shadow; - local_irq_restore(flags); - return dir_shadow; -} /* setget_output */ - -static int gpio_leds_ioctl(unsigned int cmd, unsigned long arg); - -static int -gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned long flags; - unsigned long val; - unsigned long shadow; - struct gpio_private *priv = file->private_data; - if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) - return -EINVAL; - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - if (priv->minor == GPIO_MINOR_V) - return virtual_gpio_ioctl(file, cmd, arg); -#endif - - switch (_IOC_NR(cmd)) { - case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ - /* Read the port. */ - return *data_in[priv->minor]; - break; - case IO_SETBITS: - local_irq_save(flags); - /* Set changeable bits with a 1 in arg. */ - shadow = *data_out[priv->minor]; - shadow |= (arg & changeable_bits[priv->minor]); - *data_out[priv->minor] = shadow; - local_irq_restore(flags); - break; - case IO_CLRBITS: - local_irq_save(flags); - /* Clear changeable bits with a 1 in arg. */ - shadow = *data_out[priv->minor]; - shadow &= ~(arg & changeable_bits[priv->minor]); - *data_out[priv->minor] = shadow; - local_irq_restore(flags); - break; - case IO_HIGHALARM: - /* Set alarm when bits with 1 in arg go high. */ - priv->highalarm |= arg; - spin_lock_irqsave(&alarm_lock, flags); - gpio_some_alarms = 1; - if (priv->minor == GPIO_MINOR_A) - gpio_pa_high_alarms |= arg; - spin_unlock_irqrestore(&alarm_lock, flags); - break; - case IO_LOWALARM: - /* Set alarm when bits with 1 in arg go low. */ - priv->lowalarm |= arg; - spin_lock_irqsave(&alarm_lock, flags); - gpio_some_alarms = 1; - if (priv->minor == GPIO_MINOR_A) - gpio_pa_low_alarms |= arg; - spin_unlock_irqrestore(&alarm_lock, flags); - break; - case IO_CLRALARM: - /* Clear alarm for bits with 1 in arg. */ - priv->highalarm &= ~arg; - priv->lowalarm &= ~arg; - spin_lock_irqsave(&alarm_lock, flags); - if (priv->minor == GPIO_MINOR_A) { - if (gpio_pa_high_alarms & arg || - gpio_pa_low_alarms & arg) - /* Must update the gpio_pa_*alarms masks */ - ; - } - spin_unlock_irqrestore(&alarm_lock, flags); - break; - case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ - /* Read direction 0=input 1=output */ - return *dir_oe[priv->minor]; - case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input - */ - return setget_input(priv, arg); - break; - case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ - /* Set direction 0=unchanged 1=output, - * return mask with 1=output - */ - return setget_output(priv, arg); - - case IO_CFG_WRITE_MODE: - { - unsigned long dir_shadow; - dir_shadow = *dir_oe[priv->minor]; - - priv->clk_mask = arg & 0xFF; - priv->data_mask = (arg >> 8) & 0xFF; - priv->write_msb = (arg >> 16) & 0x01; - /* Check if we're allowed to change the bits and - * the direction is correct - */ - if (!((priv->clk_mask & changeable_bits[priv->minor]) && - (priv->data_mask & changeable_bits[priv->minor]) && - (priv->clk_mask & dir_shadow) && - (priv->data_mask & dir_shadow))) { - priv->clk_mask = 0; - priv->data_mask = 0; - return -EPERM; - } - break; - } - case IO_READ_INBITS: - /* *arg is result of reading the input pins */ - val = *data_in[priv->minor]; - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - return 0; - break; - case IO_READ_OUTBITS: - /* *arg is result of reading the output shadow */ - val = *data_out[priv->minor]; - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_INPUT: - /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ - if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) - return -EFAULT; - val = setget_input(priv, val); - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_OUTPUT: - /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ - if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) - return -EFAULT; - val = setget_output(priv, val); - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - break; - default: - if (priv->minor == GPIO_MINOR_LEDS) - return gpio_leds_ioctl(cmd, arg); - else - return -EINVAL; - } /* switch */ - - return 0; -} - -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - mutex_lock(&gpio_mutex); - ret = gpio_ioctl_unlocked(file, cmd, arg); - mutex_unlock(&gpio_mutex); - - return ret; -} - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static int -virtual_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned long flags; - unsigned short val; - unsigned short shadow; - struct gpio_private *priv = file->private_data; - - switch (_IOC_NR(cmd)) { - case IO_SETBITS: - local_irq_save(flags); - /* Set changeable bits with a 1 in arg. */ - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - shadow |= ~*dir_oe[priv->minor]; - shadow |= (arg & changeable_bits[priv->minor]); - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - local_irq_restore(flags); - break; - case IO_CLRBITS: - local_irq_save(flags); - /* Clear changeable bits with a 1 in arg. */ - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - shadow |= ~*dir_oe[priv->minor]; - shadow &= ~(arg & changeable_bits[priv->minor]); - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - local_irq_restore(flags); - break; - case IO_HIGHALARM: - /* Set alarm when bits with 1 in arg go high. */ - priv->highalarm |= arg; - spin_lock(&alarm_lock); - gpio_some_alarms = 1; - spin_unlock(&alarm_lock); - break; - case IO_LOWALARM: - /* Set alarm when bits with 1 in arg go low. */ - priv->lowalarm |= arg; - spin_lock(&alarm_lock); - gpio_some_alarms = 1; - spin_unlock(&alarm_lock); - break; - case IO_CLRALARM: - /* Clear alarm for bits with 1 in arg. */ - priv->highalarm &= ~arg; - priv->lowalarm &= ~arg; - spin_lock(&alarm_lock); - spin_unlock(&alarm_lock); - break; - case IO_CFG_WRITE_MODE: - { - unsigned long dir_shadow; - dir_shadow = *dir_oe[priv->minor]; - - priv->clk_mask = arg & 0xFF; - priv->data_mask = (arg >> 8) & 0xFF; - priv->write_msb = (arg >> 16) & 0x01; - /* Check if we're allowed to change the bits and - * the direction is correct - */ - if (!((priv->clk_mask & changeable_bits[priv->minor]) && - (priv->data_mask & changeable_bits[priv->minor]) && - (priv->clk_mask & dir_shadow) && - (priv->data_mask & dir_shadow))) { - priv->clk_mask = 0; - priv->data_mask = 0; - return -EPERM; - } - break; - } - case IO_READ_INBITS: - /* *arg is result of reading the input pins */ - val = cached_virtual_gpio_read; - val &= ~*dir_oe[priv->minor]; - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - return 0; - break; - case IO_READ_OUTBITS: - /* *arg is result of reading the output shadow */ - i2c_read(VIRT_I2C_ADDR, (void *)&val, sizeof(val)); - val &= *dir_oe[priv->minor]; - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - break; - case IO_SETGET_INPUT: - { - /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ - unsigned short input_mask = ~*dir_oe[priv->minor]; - if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) - return -EFAULT; - val = setget_input(priv, val); - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - if ((input_mask & val) != input_mask) { - /* Input pins changed. All ports desired as input - * should be set to logic 1. - */ - unsigned short change = input_mask ^ val; - i2c_read(VIRT_I2C_ADDR, (void *)&shadow, - sizeof(shadow)); - shadow &= ~change; - shadow |= val; - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, - sizeof(shadow)); - } - break; - } - case IO_SETGET_OUTPUT: - /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ - if (copy_from_user(&val, (unsigned long *)arg, sizeof(val))) - return -EFAULT; - val = setget_output(priv, val); - if (copy_to_user((unsigned long *)arg, &val, sizeof(val))) - return -EFAULT; - break; - default: - return -EINVAL; - } /* switch */ - return 0; -} -#endif /* CONFIG_ETRAX_VIRTUAL_GPIO */ - -static int -gpio_leds_ioctl(unsigned int cmd, unsigned long arg) -{ - unsigned char green; - unsigned char red; - - switch (_IOC_NR(cmd)) { - case IO_LEDACTIVE_SET: - green = ((unsigned char) arg) & 1; - red = (((unsigned char) arg) >> 1) & 1; - CRIS_LED_ACTIVE_SET_G(green); - CRIS_LED_ACTIVE_SET_R(red); - break; - - default: - return -EINVAL; - } /* switch */ - - return 0; -} - -static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .unlocked_ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, - .llseek = noop_llseek, -}; - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO -static void -virtual_gpio_init(void) -{ - reg_gio_rw_intr_cfg intr_cfg; - reg_gio_rw_intr_mask intr_mask; - unsigned short shadow; - - shadow = ~virtual_rw_pv_oe; /* Input ports should be set to logic 1 */ - shadow |= CONFIG_ETRAX_DEF_GIO_PV_OUT; - i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - - /* Set interrupt mask and on what state the interrupt shall trigger. - * For virtual gpio the interrupt shall trigger on logic '0'. - */ - intr_cfg = REG_RD(gio, regi_gio, rw_intr_cfg); - intr_mask = REG_RD(gio, regi_gio, rw_intr_mask); - - switch (CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN) { - case 0: - intr_cfg.pa0 = regk_gio_lo; - intr_mask.pa0 = regk_gio_yes; - break; - case 1: - intr_cfg.pa1 = regk_gio_lo; - intr_mask.pa1 = regk_gio_yes; - break; - case 2: - intr_cfg.pa2 = regk_gio_lo; - intr_mask.pa2 = regk_gio_yes; - break; - case 3: - intr_cfg.pa3 = regk_gio_lo; - intr_mask.pa3 = regk_gio_yes; - break; - case 4: - intr_cfg.pa4 = regk_gio_lo; - intr_mask.pa4 = regk_gio_yes; - break; - case 5: - intr_cfg.pa5 = regk_gio_lo; - intr_mask.pa5 = regk_gio_yes; - break; - case 6: - intr_cfg.pa6 = regk_gio_lo; - intr_mask.pa6 = regk_gio_yes; - break; - case 7: - intr_cfg.pa7 = regk_gio_lo; - intr_mask.pa7 = regk_gio_yes; - break; - } - - REG_WR(gio, regi_gio, rw_intr_cfg, intr_cfg); - REG_WR(gio, regi_gio, rw_intr_mask, intr_mask); - - gpio_pa_low_alarms |= (1 << CONFIG_ETRAX_VIRTUAL_GPIO_INTERRUPT_PA_PIN); - gpio_some_alarms = 1; -} -#endif - -/* main driver initialization routine, called from mem.c */ - -static __init int -gpio_init(void) -{ - int res; - - /* do the formalities */ - - res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); - if (res < 0) { - printk(KERN_ERR "gpio: couldn't get a major number.\n"); - return res; - } - - /* Clear all leds */ - CRIS_LED_NETWORK_GRP0_SET(0); - CRIS_LED_NETWORK_GRP1_SET(0); - CRIS_LED_ACTIVE_SET(0); - CRIS_LED_DISK_READ(0); - CRIS_LED_DISK_WRITE(0); - - printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 " - "Axis Communications AB\n"); - /* We call etrax_gpio_wake_up_check() from timer interrupt */ - if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt, - IRQF_SHARED, "gpio poll", &alarmlist)) - printk(KERN_ERR "timer0 irq for gpio\n"); - - if (request_irq(GIO_INTR_VECT, gpio_pa_interrupt, - IRQF_SHARED, "gpio PA", &alarmlist)) - printk(KERN_ERR "PA irq for gpio\n"); - -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - virtual_gpio_init(); -#endif - - return res; -} - -/* this makes sure that gpio_init is called during kernel boot */ - -module_init(gpio_init); diff --git a/kernel/arch/cris/arch-v32/drivers/sync_serial.c b/kernel/arch/cris/arch-v32/drivers/sync_serial.c index 4dda9bd6b..e989cee77 100644 --- a/kernel/arch/cris/arch-v32/drivers/sync_serial.c +++ b/kernel/arch/cris/arch-v32/drivers/sync_serial.c @@ -1464,7 +1464,7 @@ static inline void handle_rx_packet(struct sync_port *port) if (port->write_ts_idx == NBR_IN_DESCR) port->write_ts_idx = 0; idx = port->write_ts_idx++; - do_posix_clock_monotonic_gettime(&port->timestamp[idx]); + ktime_get_ts(&port->timestamp[idx]); port->in_buffer_len += port->inbufchunk; } spin_unlock_irqrestore(&port->lock, flags); diff --git a/kernel/arch/cris/arch-v32/kernel/crisksyms.c b/kernel/arch/cris/arch-v32/kernel/crisksyms.c index bde8d1a10..b0566350a 100644 --- a/kernel/arch/cris/arch-v32/kernel/crisksyms.c +++ b/kernel/arch/cris/arch-v32/kernel/crisksyms.c @@ -3,7 +3,6 @@ #include <arch/dma.h> #include <arch/intmem.h> #include <mach/pinmux.h> -#include <arch/io.h> /* Functions for allocating DMA channels */ EXPORT_SYMBOL(crisv32_request_dma); @@ -20,8 +19,6 @@ EXPORT_SYMBOL(crisv32_pinmux_alloc); EXPORT_SYMBOL(crisv32_pinmux_alloc_fixed); EXPORT_SYMBOL(crisv32_pinmux_dealloc); EXPORT_SYMBOL(crisv32_pinmux_dealloc_fixed); -EXPORT_SYMBOL(crisv32_io_get_name); -EXPORT_SYMBOL(crisv32_io_get); /* Functions masking/unmasking interrupts */ EXPORT_SYMBOL(crisv32_mask_irq); diff --git a/kernel/arch/cris/arch-v32/kernel/debugport.c b/kernel/arch/cris/arch-v32/kernel/debugport.c index 02e33ebe5..d2f3f9c37 100644 --- a/kernel/arch/cris/arch-v32/kernel/debugport.c +++ b/kernel/arch/cris/arch-v32/kernel/debugport.c @@ -77,8 +77,6 @@ static struct dbg_port *port = &ports[2]; #elif defined(CONFIG_ETRAX_DEBUG_PORT3) &ports[3]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT4) - &ports[4]; #else NULL; #endif diff --git a/kernel/arch/cris/arch-v32/kernel/entry.S b/kernel/arch/cris/arch-v32/kernel/entry.S index 026a0b21b..b17a20999 100644 --- a/kernel/arch/cris/arch-v32/kernel/entry.S +++ b/kernel/arch/cris/arch-v32/kernel/entry.S @@ -240,6 +240,17 @@ ret_from_sys_call: .type _Rexit,@function _Rexit: +#if defined(CONFIG_TRACE_IRQFLAGS) + addoq +PT_ccs, $sp, $acr + move.d [$acr], $r0 + btstq 15, $r0 ; I1 + bpl 1f + nop + jsr trace_hardirqs_on + nop +1: +#endif + ;; This epilogue MUST match the prologues in multiple_interrupt, irq.h ;; and ptregs.h. addq 4, $sp ; Skip orig_r10. @@ -875,6 +886,14 @@ sys_call_table: .long sys_process_vm_writev .long sys_kcmp /* 350 */ .long sys_finit_module + .long sys_sched_setattr + .long sys_sched_getattr + .long sys_renameat2 + .long sys_seccomp /* 355 */ + .long sys_getrandom + .long sys_memfd_create + .long sys_bpf + .long sys_execveat /* * NOTE!! This doesn't have to be exact - we just have diff --git a/kernel/arch/cris/arch-v32/kernel/head.S b/kernel/arch/cris/arch-v32/kernel/head.S index 74a66e0e3..ea6366800 100644 --- a/kernel/arch/cris/arch-v32/kernel/head.S +++ b/kernel/arch/cris/arch-v32/kernel/head.S @@ -292,11 +292,7 @@ _no_romfs_in_flash: ;; For cramfs, partition starts with magic and length. ;; For jffs2, a jhead is prepended which contains with magic and length. ;; The jhead is not part of the jffs2 partition however. -#ifndef CONFIG_ETRAXFS_SIM move.d __bss_start, $r0 -#else - move.d __end, $r0 -#endif move.d [$r0], $r1 cmp.d CRAMFS_MAGIC, $r1 ; cramfs magic? beq 2f ; yes, jump diff --git a/kernel/arch/cris/arch-v32/kernel/irq.c b/kernel/arch/cris/arch-v32/kernel/irq.c index 6a881e0e9..6de8db67c 100644 --- a/kernel/arch/cris/arch-v32/kernel/irq.c +++ b/kernel/arch/cris/arch-v32/kernel/irq.c @@ -37,7 +37,7 @@ #define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ)) #elif defined(CONFIG_ETRAX_KGDB_PORT1) #define IGNOREMASK (1 << (SER1_INTR_VECT - FIRST_IRQ)) -#elif defined(CONFIG_ETRAX_KGB_PORT2) +#elif defined(CONFIG_ETRAX_KGDB_PORT2) #define IGNOREMASK (1 << (SER2_INTR_VECT - FIRST_IRQ)) #elif defined(CONFIG_ETRAX_KGDB_PORT3) #define IGNOREMASK (1 << (SER3_INTR_VECT - FIRST_IRQ)) @@ -464,14 +464,14 @@ init_IRQ(void) etrax_irv->v[i] = weird_irq; np = of_find_compatible_node(NULL, NULL, "axis,crisv32-intc"); - domain = irq_domain_add_legacy(np, NR_IRQS - FIRST_IRQ, + domain = irq_domain_add_legacy(np, NBR_INTR_VECT - FIRST_IRQ, FIRST_IRQ, FIRST_IRQ, &crisv32_irq_ops, NULL); BUG_ON(!domain); irq_set_default_host(domain); of_node_put(np); - for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) { + for (i = FIRST_IRQ, j = 0; j < NBR_INTR_VECT; i++, j++) { set_exception_vector(i, interrupt[j]); } diff --git a/kernel/arch/cris/arch-v32/kernel/kgdb.c b/kernel/arch/cris/arch-v32/kernel/kgdb.c index b06813aeb..e0fdea706 100644 --- a/kernel/arch/cris/arch-v32/kernel/kgdb.c +++ b/kernel/arch/cris/arch-v32/kernel/kgdb.c @@ -384,19 +384,11 @@ int getDebugChar(void); /* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ void putDebugChar(int val); -/* Returns the integer equivalent of a hexadecimal character. */ -static int hex(char ch); - /* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */ static char *mem2hex(char *buf, unsigned char *mem, int count); -/* Convert the array, in hexadecimal representation, pointed to by buf into - binary representation. Put the result in mem, and return a pointer to - the character after the last byte written. */ -static unsigned char *hex2mem(unsigned char *mem, char *buf, int count); - /* Put the content of the array, in binary representation, pointed to by buf into memory pointed to by mem, and return a pointer to the character after the last byte written. */ @@ -449,7 +441,7 @@ static char output_buffer[BUFMAX]; /* Error and warning messages. */ enum error_type { - SUCCESS, E01, E02, E03, E04, E05, E06, + SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08 }; static char *error_message[] = @@ -461,6 +453,8 @@ static char *error_message[] = "E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.", "E05 Change register content - P - the register is not implemented..", "E06 Change memory content - M - internal error.", + "E07 Change register content - P - the register is not stored on the stack", + "E08 Invalid parameter" }; /********************************** Breakpoint *******************************/ @@ -539,7 +533,7 @@ gdb_cris_strtol(const char *s, char **endptr, int base) /********************************* Register image ****************************/ /* Write a value to a specified register in the register image of the current - thread. Returns status code SUCCESS, E02 or E05. */ + thread. Returns status code SUCCESS, E02, E05 or E08. */ static int write_register(int regno, char *val) { @@ -547,8 +541,9 @@ write_register(int regno, char *val) if (regno >= R0 && regno <= ACR) { /* Consecutive 32-bit registers. */ - hex2mem((unsigned char *)®.r0 + (regno - R0) * sizeof(unsigned int), - val, sizeof(unsigned int)); + if (hex2bin((unsigned char *)®.r0 + (regno - R0) * sizeof(unsigned int), + val, sizeof(unsigned int))) + status = E08; } else if (regno == BZ || regno == VR || regno == WZ || regno == DZ) { /* Read-only registers. */ @@ -557,16 +552,19 @@ write_register(int regno, char *val) } else if (regno == PID) { /* 32-bit register. (Even though we already checked SRS and WZ, we cannot combine this with the EXS - SPC write since SRS and WZ have different size.) */ - hex2mem((unsigned char *)®.pid, val, sizeof(unsigned int)); + if (hex2bin((unsigned char *)®.pid, val, sizeof(unsigned int))) + status = E08; } else if (regno == SRS) { /* 8-bit register. */ - hex2mem((unsigned char *)®.srs, val, sizeof(unsigned char)); + if (hex2bin((unsigned char *)®.srs, val, sizeof(unsigned char))) + status = E08; } else if (regno >= EXS && regno <= SPC) { /* Consecutive 32-bit registers. */ - hex2mem((unsigned char *)®.exs + (regno - EXS) * sizeof(unsigned int), - val, sizeof(unsigned int)); + if (hex2bin((unsigned char *)®.exs + (regno - EXS) * sizeof(unsigned int), + val, sizeof(unsigned int))) + status = E08; } else if (regno == PC) { /* Pseudo-register. Treat as read-only. */ @@ -574,7 +572,9 @@ write_register(int regno, char *val) } else if (regno >= S0 && regno <= S15) { /* 32-bit registers. */ - hex2mem((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int), val, sizeof(unsigned int)); + if (hex2bin((unsigned char *)&sreg.s0_0 + (reg.srs * 16 * sizeof(unsigned int)) + (regno - S0) * sizeof(unsigned int), + val, sizeof(unsigned int))) + status = E08; } else { /* Non-existing register. */ status = E05; @@ -630,19 +630,6 @@ read_register(char regno, unsigned int *valptr) } /********************************** Packet I/O ******************************/ -/* Returns the integer equivalent of a hexadecimal character. */ -static int -hex(char ch) -{ - if ((ch >= 'a') && (ch <= 'f')) - return (ch - 'a' + 10); - if ((ch >= '0') && (ch <= '9')) - return (ch - '0'); - if ((ch >= 'A') && (ch <= 'F')) - return (ch - 'A' + 10); - return -1; -} - /* Convert the memory, pointed to by mem into hexadecimal representation. Put the result in buf, and return a pointer to the last character in buf (null). */ @@ -689,22 +676,6 @@ mem2hex_nbo(char *buf, unsigned char *mem, int count) return buf; } -/* Convert the array, in hexadecimal representation, pointed to by buf into - binary representation. Put the result in mem, and return a pointer to - the character after the last byte written. */ -static unsigned char* -hex2mem(unsigned char *mem, char *buf, int count) -{ - int i; - unsigned char ch; - for (i = 0; i < count; i++) { - ch = hex (*buf++) << 4; - ch = ch + hex (*buf++); - *mem++ = ch; - } - return mem; -} - /* Put the content of the array, in binary representation, pointed to by buf into memory pointed to by mem, and return a pointer to the character after the last byte written. @@ -763,8 +734,8 @@ getpacket(char *buffer) buffer[count] = 0; if (ch == '#') { - xmitcsum = hex(getDebugChar()) << 4; - xmitcsum += hex(getDebugChar()); + xmitcsum = hex_to_bin(getDebugChar()) << 4; + xmitcsum += hex_to_bin(getDebugChar()); if (checksum != xmitcsum) { /* Wrong checksum */ putDebugChar('-'); @@ -1304,14 +1275,17 @@ handle_exception(int sigval) /* Write registers. GXX..XX Each byte of register data is described by two hex digits. Success: OK - Failure: void. */ + Failure: E08. */ /* General and special registers. */ - hex2mem((char *)®, &input_buffer[1], sizeof(registers)); + if (hex2bin((char *)®, &input_buffer[1], sizeof(registers))) + gdb_cris_strcpy(output_buffer, error_message[E08]); /* Support registers. */ - hex2mem((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)), + else if (hex2bin((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)), &input_buffer[1] + sizeof(registers), - 16 * sizeof(unsigned int)); - gdb_cris_strcpy(output_buffer, "OK"); + 16 * sizeof(unsigned int))) + gdb_cris_strcpy(output_buffer, error_message[E08]); + else + gdb_cris_strcpy(output_buffer, "OK"); break; case 'P': @@ -1338,6 +1312,10 @@ handle_exception(int sigval) /* Do not support non-existing registers. */ gdb_cris_strcpy(output_buffer, error_message[E05]); break; + case E08: + /* Invalid parameter. */ + gdb_cris_strcpy(output_buffer, error_message[E08]); + break; default: /* Valid register number. */ gdb_cris_strcpy(output_buffer, "OK"); @@ -1380,7 +1358,7 @@ handle_exception(int sigval) AA..AA is the start address, LLLL is the number of bytes, and XX..XX is the hexadecimal data. Success: OK - Failure: void. */ + Failure: E08. */ { char *lenptr; char *dataptr; @@ -1389,13 +1367,15 @@ handle_exception(int sigval) int len = gdb_cris_strtol(lenptr+1, &dataptr, 16); if (*lenptr == ',' && *dataptr == ':') { if (input_buffer[0] == 'M') { - hex2mem(addr, dataptr + 1, len); + if (hex2bin(addr, dataptr + 1, len)) + gdb_cris_strcpy(output_buffer, error_message[E08]); + else + gdb_cris_strcpy(output_buffer, "OK"); } else /* X */ { bin2mem(addr, dataptr + 1, len); + gdb_cris_strcpy(output_buffer, "OK"); } - gdb_cris_strcpy(output_buffer, "OK"); - } - else { + } else { gdb_cris_strcpy(output_buffer, error_message[E06]); } } diff --git a/kernel/arch/cris/arch-v32/kernel/process.c b/kernel/arch/cris/arch-v32/kernel/process.c index cebd32e2a..c7ce784a3 100644 --- a/kernel/arch/cris/arch-v32/kernel/process.c +++ b/kernel/arch/cris/arch-v32/kernel/process.c @@ -23,9 +23,9 @@ extern void stop_watchdog(void); /* We use this if we don't have any better idle routine. */ void default_idle(void) { + local_irq_enable(); /* Halt until exception. */ - __asm__ volatile("ei \n\t" - "halt "); + __asm__ volatile("halt"); } /* diff --git a/kernel/arch/cris/arch-v32/kernel/setup.c b/kernel/arch/cris/arch-v32/kernel/setup.c index cd1865d68..fe50287aa 100644 --- a/kernel/arch/cris/arch-v32/kernel/setup.c +++ b/kernel/arch/cris/arch-v32/kernel/setup.c @@ -129,10 +129,6 @@ static struct i2c_board_info __initdata i2c_info[] = { #ifdef CONFIG_RTC_DRV_PCF8563 {I2C_BOARD_INFO("pcf8563", 0x51)}, #endif -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - {I2C_BOARD_INFO("vgpio", 0x20)}, - {I2C_BOARD_INFO("vgpio", 0x21)}, -#endif {I2C_BOARD_INFO("pca9536", 0x41)}, {I2C_BOARD_INFO("fnp300", 0x40)}, {I2C_BOARD_INFO("fnp300", 0x42)}, @@ -146,10 +142,6 @@ static struct i2c_board_info __initdata i2c_info2[] = { {I2C_BOARD_INFO("tmp100", 0x4C)}, {I2C_BOARD_INFO("tmp100", 0x4D)}, {I2C_BOARD_INFO("tmp100", 0x4E)}, -#ifdef CONFIG_ETRAX_VIRTUAL_GPIO - {I2C_BOARD_INFO("vgpio", 0x20)}, - {I2C_BOARD_INFO("vgpio", 0x21)}, -#endif {I2C_BOARD_INFO("pca9536", 0x41)}, {I2C_BOARD_INFO("fnp300", 0x40)}, {I2C_BOARD_INFO("fnp300", 0x42)}, diff --git a/kernel/arch/cris/arch-v32/kernel/signal.c b/kernel/arch/cris/arch-v32/kernel/signal.c index 3a36ae6b7..150d1d76c 100644 --- a/kernel/arch/cris/arch-v32/kernel/signal.c +++ b/kernel/arch/cris/arch-v32/kernel/signal.c @@ -19,7 +19,6 @@ #include <asm/processor.h> #include <asm/ucontext.h> #include <asm/uaccess.h> -#include <arch/ptrace.h> #include <arch/hwregs/cpu_vect.h> extern unsigned long cris_signal_return_page; diff --git a/kernel/arch/cris/arch-v32/kernel/time.c b/kernel/arch/cris/arch-v32/kernel/time.c index 4fce9f1f7..d2a844076 100644 --- a/kernel/arch/cris/arch-v32/kernel/time.c +++ b/kernel/arch/cris/arch-v32/kernel/time.c @@ -172,8 +172,7 @@ void handle_watchdog_bite(struct pt_regs *regs) extern void cris_profile_sample(struct pt_regs *regs); static void __iomem *timer_base; -static void crisv32_clkevt_mode(enum clock_event_mode mode, - struct clock_event_device *dev) +static int crisv32_clkevt_switch_state(struct clock_event_device *dev) { reg_timer_rw_tmr0_ctrl ctrl = { .op = regk_timer_hold, @@ -181,6 +180,7 @@ static void crisv32_clkevt_mode(enum clock_event_mode mode, }; REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl); + return 0; } static int crisv32_clkevt_next_event(unsigned long evt, @@ -231,7 +231,9 @@ static struct clock_event_device crisv32_clockevent = { .name = "crisv32-timer", .rating = 300, .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = crisv32_clkevt_mode, + .set_state_oneshot = crisv32_clkevt_switch_state, + .set_state_shutdown = crisv32_clkevt_switch_state, + .tick_resume = crisv32_clkevt_switch_state, .set_next_event = crisv32_clkevt_next_event, }; diff --git a/kernel/arch/cris/arch-v32/mach-a3/Makefile b/kernel/arch/cris/arch-v32/mach-a3/Makefile index 18a227196..0cc6eebac 100644 --- a/kernel/arch/cris/arch-v32/mach-a3/Makefile +++ b/kernel/arch/cris/arch-v32/mach-a3/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := dma.o pinmux.o io.o arbiter.o +obj-y := dma.o pinmux.o arbiter.o clean: diff --git a/kernel/arch/cris/arch-v32/mach-a3/io.c b/kernel/arch/cris/arch-v32/mach-a3/io.c deleted file mode 100644 index 090ceb99e..000000000 --- a/kernel/arch/cris/arch-v32/mach-a3/io.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Helper functions for I/O pins. - * - * Copyright (c) 2005-2007 Axis Communications AB. - */ - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/ctype.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <asm/io.h> -#include <mach/pinmux.h> -#include <hwregs/gio_defs.h> - -struct crisv32_ioport crisv32_ioports[] = { - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din), - 32 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din), - 32 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din), - 16 - }, -}; - -#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports) - -struct crisv32_iopin crisv32_led_net0_green; -struct crisv32_iopin crisv32_led_net0_red; -struct crisv32_iopin crisv32_led2_green; -struct crisv32_iopin crisv32_led2_red; -struct crisv32_iopin crisv32_led3_green; -struct crisv32_iopin crisv32_led3_red; - -/* Dummy port used when green LED and red LED is on the same bit */ -static unsigned long io_dummy; -static struct crisv32_ioport dummy_port = { - &io_dummy, - &io_dummy, - &io_dummy, - 32 -}; -static struct crisv32_iopin dummy_led = { - &dummy_port, - 0 -}; - -static int __init crisv32_io_init(void) -{ - int ret = 0; - - u32 i; - - /* Locks *should* be dynamically initialized. */ - for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++) - spin_lock_init(&crisv32_ioports[i].lock); - spin_lock_init(&dummy_port.lock); - - /* Initialize LEDs */ -#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO)) - ret += crisv32_io_get_name(&crisv32_led_net0_green, - CONFIG_ETRAX_LED_G_NET0); - crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out); - if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) { - ret += crisv32_io_get_name(&crisv32_led_net0_red, - CONFIG_ETRAX_LED_R_NET0); - crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out); - } else - crisv32_led_net0_red = dummy_led; -#endif - - ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G); - ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R); - ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G); - ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R); - - crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out); - - return ret; -} - -__initcall(crisv32_io_init); - -int crisv32_io_get(struct crisv32_iopin *iopin, - unsigned int port, unsigned int pin) -{ - if (port > NBR_OF_PORTS) - return -EINVAL; - if (port > crisv32_ioports[port].pin_count) - return -EINVAL; - - iopin->bit = 1 << pin; - iopin->port = &crisv32_ioports[port]; - - if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio)) - return -EIO; - - return 0; -} - -int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name) -{ - int port; - int pin; - - if (toupper(*name) == 'P') - name++; - - if (toupper(*name) < 'A' || toupper(*name) > 'E') - return -EINVAL; - - port = toupper(*name) - 'A'; - name++; - pin = simple_strtoul(name, NULL, 10); - - if (pin < 0 || pin > crisv32_ioports[port].pin_count) - return -EINVAL; - - iopin->bit = 1 << pin; - iopin->port = &crisv32_ioports[port]; - - if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio)) - return -EIO; - - return 0; -} - -#ifdef CONFIG_PCI -/* PCI I/O access stuff */ -struct cris_io_operations *cris_iops = NULL; -EXPORT_SYMBOL(cris_iops); -#endif - diff --git a/kernel/arch/cris/arch-v32/mach-fs/Kconfig b/kernel/arch/cris/arch-v32/mach-fs/Kconfig index 774de82ab..7d1ab972b 100644 --- a/kernel/arch/cris/arch-v32/mach-fs/Kconfig +++ b/kernel/arch/cris/arch-v32/mach-fs/Kconfig @@ -192,25 +192,6 @@ config ETRAX_DEF_GIO_PE_OUT Configures the initial data for the general port E bits. Most products should use 00000 here. -config ETRAX_DEF_GIO_PV_OE - hex "GIO_PV_OE" - depends on ETRAX_VIRTUAL_GPIO - default "0000" - help - Configures the direction of virtual general port V bits. 1 is out, - 0 is in. This is often totally different depending on the product - used. These bits are used for all kinds of stuff. If you don't know - what to use, it is always safe to put all as inputs, although - floating inputs isn't good. - -config ETRAX_DEF_GIO_PV_OUT - hex "GIO_PV_OUT" - depends on ETRAX_VIRTUAL_GPIO - default "0000" - help - Configures the initial data for the virtual general port V bits. - Most products should use 0000 here. - endmenu endif diff --git a/kernel/arch/cris/arch-v32/mach-fs/Makefile b/kernel/arch/cris/arch-v32/mach-fs/Makefile index 18a227196..0cc6eebac 100644 --- a/kernel/arch/cris/arch-v32/mach-fs/Makefile +++ b/kernel/arch/cris/arch-v32/mach-fs/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := dma.o pinmux.o io.o arbiter.o +obj-y := dma.o pinmux.o arbiter.o clean: diff --git a/kernel/arch/cris/arch-v32/mach-fs/io.c b/kernel/arch/cris/arch-v32/mach-fs/io.c deleted file mode 100644 index a6958661f..000000000 --- a/kernel/arch/cris/arch-v32/mach-fs/io.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Helper functions for I/O pins. - * - * Copyright (c) 2004-2007 Axis Communications AB. - */ - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/ctype.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <asm/io.h> -#include <mach/pinmux.h> -#include <hwregs/gio_defs.h> - -#ifndef DEBUG -#define DEBUG(x) -#endif - -struct crisv32_ioport crisv32_ioports[] = { - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din), - 8 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din), - 18 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din), - 18 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pd_din), - 18 - }, - { - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_oe), - (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_dout), - (unsigned long *)REG_ADDR(gio, regi_gio, r_pe_din), - 18 - } -}; - -#define NBR_OF_PORTS ARRAY_SIZE(crisv32_ioports) - -struct crisv32_iopin crisv32_led_net0_green; -struct crisv32_iopin crisv32_led_net0_red; -struct crisv32_iopin crisv32_led_net1_green; -struct crisv32_iopin crisv32_led_net1_red; -struct crisv32_iopin crisv32_led2_green; -struct crisv32_iopin crisv32_led2_red; -struct crisv32_iopin crisv32_led3_green; -struct crisv32_iopin crisv32_led3_red; - -/* Dummy port used when green LED and red LED is on the same bit */ -static unsigned long io_dummy; -static struct crisv32_ioport dummy_port = { - &io_dummy, - &io_dummy, - &io_dummy, - 18 -}; -static struct crisv32_iopin dummy_led = { - &dummy_port, - 0 -}; - -static int __init crisv32_io_init(void) -{ - int ret = 0; - - u32 i; - - /* Locks *should* be dynamically initialized. */ - for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++) - spin_lock_init(&crisv32_ioports[i].lock); - spin_lock_init(&dummy_port.lock); - - /* Initialize LEDs */ -#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO)) - ret += - crisv32_io_get_name(&crisv32_led_net0_green, - CONFIG_ETRAX_LED_G_NET0); - crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out); - if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) { - ret += - crisv32_io_get_name(&crisv32_led_net0_red, - CONFIG_ETRAX_LED_R_NET0); - crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out); - } else - crisv32_led_net0_red = dummy_led; -#endif - -#ifdef CONFIG_ETRAX_NBR_LED_GRP_TWO - ret += - crisv32_io_get_name(&crisv32_led_net1_green, - CONFIG_ETRAX_LED_G_NET1); - crisv32_io_set_dir(&crisv32_led_net1_green, crisv32_io_dir_out); - if (strcmp(CONFIG_ETRAX_LED_G_NET1, CONFIG_ETRAX_LED_R_NET1)) { - crisv32_io_get_name(&crisv32_led_net1_red, - CONFIG_ETRAX_LED_R_NET1); - crisv32_io_set_dir(&crisv32_led_net1_red, crisv32_io_dir_out); - } else - crisv32_led_net1_red = dummy_led; -#endif - - ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G); - ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R); - ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G); - ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R); - - crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out); - crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out); - - return ret; -} - -__initcall(crisv32_io_init); - -int crisv32_io_get(struct crisv32_iopin *iopin, - unsigned int port, unsigned int pin) -{ - if (port > NBR_OF_PORTS) - return -EINVAL; - if (port > crisv32_ioports[port].pin_count) - return -EINVAL; - - iopin->bit = 1 << pin; - iopin->port = &crisv32_ioports[port]; - - /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */ - /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */ - if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio)) - return -EIO; - DEBUG(printk(KERN_DEBUG "crisv32_io_get: Allocated pin %d on port %d\n", - pin, port)); - - return 0; -} - -int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name) -{ - int port; - int pin; - - if (toupper(*name) == 'P') - name++; - - if (toupper(*name) < 'A' || toupper(*name) > 'E') - return -EINVAL; - - port = toupper(*name) - 'A'; - name++; - pin = simple_strtoul(name, NULL, 10); - - if (pin < 0 || pin > crisv32_ioports[port].pin_count) - return -EINVAL; - - iopin->bit = 1 << pin; - iopin->port = &crisv32_ioports[port]; - - /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */ - /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */ - if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio)) - return -EIO; - - DEBUG(printk(KERN_DEBUG - "crisv32_io_get_name: Allocated pin %d on port %d\n", - pin, port)); - - return 0; -} - -#ifdef CONFIG_PCI -/* PCI I/O access stuff */ -struct cris_io_operations *cris_iops = NULL; -EXPORT_SYMBOL(cris_iops); -#endif diff --git a/kernel/arch/cris/arch-v32/mach-fs/pinmux.c b/kernel/arch/cris/arch-v32/mach-fs/pinmux.c index 05a04708b..d8a3a3c43 100644 --- a/kernel/arch/cris/arch-v32/mach-fs/pinmux.c +++ b/kernel/arch/cris/arch-v32/mach-fs/pinmux.c @@ -46,6 +46,8 @@ static int __crisv32_pinmux_alloc(int port, int first_pin, int last_pin, pins[port][i] = mode; crisv32_pinmux_set(port); + + return 0; } static int crisv32_pinmux_init(void) @@ -93,6 +95,7 @@ int crisv32_pinmux_alloc_fixed(enum fixed_function function) int ret = -EINVAL; char saved[sizeof pins]; unsigned long flags; + reg_pinmux_rw_hwprot hwprot; spin_lock_irqsave(&pinmux_lock, flags); @@ -101,7 +104,7 @@ int crisv32_pinmux_alloc_fixed(enum fixed_function function) crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */ - reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); + hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); switch (function) { case pinmux_ser1: @@ -227,6 +230,7 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function) int ret = -EINVAL; char saved[sizeof pins]; unsigned long flags; + reg_pinmux_rw_hwprot hwprot; spin_lock_irqsave(&pinmux_lock, flags); @@ -235,7 +239,7 @@ int crisv32_pinmux_dealloc_fixed(enum fixed_function function) crisv32_pinmux_init(); /* Must be done before we read rw_hwprot */ - reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); + hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); switch (function) { case pinmux_ser1: diff --git a/kernel/arch/cris/arch-v32/mm/intmem.c b/kernel/arch/cris/arch-v32/mm/intmem.c index 1b17d92ce..9ef56092a 100644 --- a/kernel/arch/cris/arch-v32/mm/intmem.c +++ b/kernel/arch/cris/arch-v32/mm/intmem.c @@ -145,6 +145,5 @@ unsigned long crisv32_intmem_virt_to_phys(void* addr) (unsigned long)intmem_virtual + MEM_INTMEM_START + RESERVED_SIZE); } - -module_init(crisv32_intmem_init); +device_initcall(crisv32_intmem_init); |