diff options
Diffstat (limited to 'drivers/misc')
33 files changed, 4290 insertions, 259 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 2d6423c2d193..5664696f2d3a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -63,7 +63,7 @@ config AD525X_DPOT_SPI | |||
| 63 | 63 | ||
| 64 | config ATMEL_PWM | 64 | config ATMEL_PWM |
| 65 | tristate "Atmel AT32/AT91 PWM support" | 65 | tristate "Atmel AT32/AT91 PWM support" |
| 66 | depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 | 66 | depends on HAVE_CLK |
| 67 | help | 67 | help |
| 68 | This option enables device driver support for the PWM channels | 68 | This option enables device driver support for the PWM channels |
| 69 | on certain Atmel processors. Pulse Width Modulation is used for | 69 | on certain Atmel processors. Pulse Width Modulation is used for |
| @@ -472,7 +472,7 @@ config BMP085 | |||
| 472 | module will be called bmp085. | 472 | module will be called bmp085. |
| 473 | 473 | ||
| 474 | config PCH_PHUB | 474 | config PCH_PHUB |
| 475 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB" | 475 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB" |
| 476 | depends on PCI | 476 | depends on PCI |
| 477 | help | 477 | help |
| 478 | This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of | 478 | This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of |
| @@ -480,12 +480,13 @@ config PCH_PHUB | |||
| 480 | processor. The Topcliff has MAC address and Option ROM data in SROM. | 480 | processor. The Topcliff has MAC address and Option ROM data in SROM. |
| 481 | This driver can access MAC address and Option ROM data in SROM. | 481 | This driver can access MAC address and Option ROM data in SROM. |
| 482 | 482 | ||
| 483 | This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ | 483 | This driver also can be used for LAPIS Semiconductor's IOH, |
| 484 | Output Hub), ML7213 and ML7223. | 484 | ML7213/ML7223/ML7831. |
| 485 | ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is | 485 | ML7213 which is for IVI(In-Vehicle Infotainment) use. |
| 486 | for MP(Media Phone) use. | 486 | ML7223 IOH is for MP(Media Phone) use. |
| 487 | ML7213/ML7223 is companion chip for Intel Atom E6xx series. | 487 | ML7831 IOH is for general purpose use. |
| 488 | ML7213/ML7223 is completely compatible for Intel EG20T PCH. | 488 | ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. |
| 489 | ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. | ||
| 489 | 490 | ||
| 490 | To compile this driver as a module, choose M here: the module will | 491 | To compile this driver as a module, choose M here: the module will |
| 491 | be called pch_phub. | 492 | be called pch_phub. |
| @@ -506,5 +507,6 @@ source "drivers/misc/iwmc3200top/Kconfig" | |||
| 506 | source "drivers/misc/ti-st/Kconfig" | 507 | source "drivers/misc/ti-st/Kconfig" |
| 507 | source "drivers/misc/lis3lv02d/Kconfig" | 508 | source "drivers/misc/lis3lv02d/Kconfig" |
| 508 | source "drivers/misc/carma/Kconfig" | 509 | source "drivers/misc/carma/Kconfig" |
| 510 | source "drivers/misc/altera-stapl/Kconfig" | ||
| 509 | 511 | ||
| 510 | endif # MISC_DEVICES | 512 | endif # MISC_DEVICES |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 8f3efb68a141..b26495a02554 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
| @@ -47,3 +47,4 @@ obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o | |||
| 47 | obj-y += lis3lv02d/ | 47 | obj-y += lis3lv02d/ |
| 48 | obj-y += carma/ | 48 | obj-y += carma/ |
| 49 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o | 49 | obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o |
| 50 | obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ | ||
diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 35903154ca2e..2208a9d52622 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/pwm.h> | 10 | #include <linux/pwm.h> |
| 11 | #include <linux/mfd/ab8500.h> | 11 | #include <linux/mfd/ab8500.h> |
| 12 | #include <linux/mfd/abx500.h> | 12 | #include <linux/mfd/abx500.h> |
| 13 | #include <linux/module.h> | ||
| 13 | 14 | ||
| 14 | /* | 15 | /* |
| 15 | * PWM Out generators | 16 | * PWM Out generators |
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index 4ff73c215746..a39e0555df63 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c | |||
| @@ -98,6 +98,7 @@ static const struct i2c_device_id ad_dpot_id[] = { | |||
| 98 | {"ad5282", AD5282_ID}, | 98 | {"ad5282", AD5282_ID}, |
| 99 | {"adn2860", ADN2860_ID}, | 99 | {"adn2860", ADN2860_ID}, |
| 100 | {"ad5273", AD5273_ID}, | 100 | {"ad5273", AD5273_ID}, |
| 101 | {"ad5161", AD5161_ID}, | ||
| 101 | {"ad5171", AD5171_ID}, | 102 | {"ad5171", AD5171_ID}, |
| 102 | {"ad5170", AD5170_ID}, | 103 | {"ad5170", AD5170_ID}, |
| 103 | {"ad5172", AD5172_ID}, | 104 | {"ad5172", AD5172_ID}, |
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h index a662f5987b68..82b2cb77ae19 100644 --- a/drivers/misc/ad525x_dpot.h +++ b/drivers/misc/ad525x_dpot.h | |||
| @@ -100,7 +100,7 @@ enum dpot_devid { | |||
| 100 | AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), | 100 | AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27), |
| 101 | AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, | 101 | AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, |
| 102 | BRDAC0, 7, 28), | 102 | BRDAC0, 7, 28), |
| 103 | AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT, | 103 | AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT, |
| 104 | BRDAC0, 8, 29), | 104 | BRDAC0, 8, 29), |
| 105 | AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT, | 105 | AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT, |
| 106 | BRDAC0 | BRDAC1, 8, 30), | 106 | BRDAC0 | BRDAC1, 8, 30), |
diff --git a/drivers/misc/altera-stapl/Kconfig b/drivers/misc/altera-stapl/Kconfig new file mode 100644 index 000000000000..7f01d8e93992 --- /dev/null +++ b/drivers/misc/altera-stapl/Kconfig | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | comment "Altera FPGA firmware download module" | ||
| 2 | |||
| 3 | config ALTERA_STAPL | ||
| 4 | tristate "Altera FPGA firmware download module" | ||
| 5 | depends on I2C | ||
| 6 | default n | ||
| 7 | help | ||
| 8 | An Altera FPGA module. Say Y when you want to support this tool. | ||
diff --git a/drivers/misc/altera-stapl/Makefile b/drivers/misc/altera-stapl/Makefile new file mode 100644 index 000000000000..055f61ee781a --- /dev/null +++ b/drivers/misc/altera-stapl/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o | ||
| 2 | |||
| 3 | obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o | ||
diff --git a/drivers/misc/altera-stapl/altera-comp.c b/drivers/misc/altera-stapl/altera-comp.c new file mode 100644 index 000000000000..49b103bedaaf --- /dev/null +++ b/drivers/misc/altera-stapl/altera-comp.c | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | /* | ||
| 2 | * altera-comp.c | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010 NetUP Inc. | ||
| 8 | * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include "altera-exprt.h" | ||
| 28 | |||
| 29 | #define SHORT_BITS 16 | ||
| 30 | #define CHAR_BITS 8 | ||
| 31 | #define DATA_BLOB_LENGTH 3 | ||
| 32 | #define MATCH_DATA_LENGTH 8192 | ||
| 33 | #define ALTERA_REQUEST_SIZE 1024 | ||
| 34 | #define ALTERA_BUFFER_SIZE (MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE) | ||
| 35 | |||
| 36 | static u32 altera_bits_req(u32 n) | ||
| 37 | { | ||
| 38 | u32 result = SHORT_BITS; | ||
| 39 | |||
| 40 | if (n == 0) | ||
| 41 | result = 1; | ||
| 42 | else { | ||
| 43 | /* Look for the highest non-zero bit position */ | ||
| 44 | while ((n & (1 << (SHORT_BITS - 1))) == 0) { | ||
| 45 | n <<= 1; | ||
| 46 | --result; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | return result; | ||
| 51 | } | ||
| 52 | |||
| 53 | static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail, | ||
| 54 | u32 *in_index) | ||
| 55 | { | ||
| 56 | u32 result = 0; | ||
| 57 | u32 shift = 0; | ||
| 58 | u32 databyte = 0; | ||
| 59 | |||
| 60 | while (bits > 0) { | ||
| 61 | databyte = buffer[*in_index]; | ||
| 62 | result |= (((databyte >> (CHAR_BITS - *bits_avail)) | ||
| 63 | & (0xff >> (CHAR_BITS - *bits_avail))) << shift); | ||
| 64 | |||
| 65 | if (bits <= *bits_avail) { | ||
| 66 | result &= (0xffff >> (SHORT_BITS - (bits + shift))); | ||
| 67 | *bits_avail -= bits; | ||
| 68 | bits = 0; | ||
| 69 | } else { | ||
| 70 | ++(*in_index); | ||
| 71 | shift += *bits_avail; | ||
| 72 | bits -= *bits_avail; | ||
| 73 | *bits_avail = CHAR_BITS; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | return result; | ||
| 78 | } | ||
| 79 | |||
| 80 | u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version) | ||
| 81 | { | ||
| 82 | u32 i, j, data_length = 0L; | ||
| 83 | u32 offset, length; | ||
| 84 | u32 match_data_length = MATCH_DATA_LENGTH; | ||
| 85 | u32 bits_avail = CHAR_BITS; | ||
| 86 | u32 in_index = 0L; | ||
| 87 | |||
| 88 | if (version > 0) | ||
| 89 | --match_data_length; | ||
| 90 | |||
| 91 | for (i = 0; i < out_length; ++i) | ||
| 92 | out[i] = 0; | ||
| 93 | |||
| 94 | /* Read number of bytes in data. */ | ||
| 95 | for (i = 0; i < sizeof(in_length); ++i) { | ||
| 96 | data_length = data_length | ( | ||
| 97 | altera_read_packed(in, | ||
| 98 | CHAR_BITS, | ||
| 99 | &bits_avail, | ||
| 100 | &in_index) << (i * CHAR_BITS)); | ||
| 101 | } | ||
| 102 | |||
| 103 | if (data_length > out_length) { | ||
| 104 | data_length = 0L; | ||
| 105 | return data_length; | ||
| 106 | } | ||
| 107 | |||
| 108 | i = 0; | ||
| 109 | while (i < data_length) { | ||
| 110 | /* A 0 bit indicates literal data. */ | ||
| 111 | if (altera_read_packed(in, 1, &bits_avail, | ||
| 112 | &in_index) == 0) { | ||
| 113 | for (j = 0; j < DATA_BLOB_LENGTH; ++j) { | ||
| 114 | if (i < data_length) { | ||
| 115 | out[i] = (u8)altera_read_packed(in, | ||
| 116 | CHAR_BITS, | ||
| 117 | &bits_avail, | ||
| 118 | &in_index); | ||
| 119 | i++; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } else { | ||
| 123 | /* A 1 bit indicates offset/length to follow. */ | ||
| 124 | offset = altera_read_packed(in, altera_bits_req((s16) | ||
| 125 | (i > match_data_length ? | ||
| 126 | match_data_length : i)), | ||
| 127 | &bits_avail, | ||
| 128 | &in_index); | ||
| 129 | length = altera_read_packed(in, CHAR_BITS, | ||
| 130 | &bits_avail, | ||
| 131 | &in_index); | ||
| 132 | for (j = 0; j < length; ++j) { | ||
| 133 | if (i < data_length) { | ||
| 134 | out[i] = out[i - offset]; | ||
| 135 | i++; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | return data_length; | ||
| 142 | } | ||
diff --git a/drivers/misc/altera-stapl/altera-exprt.h b/drivers/misc/altera-stapl/altera-exprt.h new file mode 100644 index 000000000000..39c38d84a670 --- /dev/null +++ b/drivers/misc/altera-stapl/altera-exprt.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * altera-exprt.h | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010 NetUP Inc. | ||
| 8 | * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #ifndef ALTERA_EXPRT_H | ||
| 27 | #define ALTERA_EXPRT_H | ||
| 28 | |||
| 29 | |||
| 30 | u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version); | ||
| 31 | int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo); | ||
| 32 | |||
| 33 | #endif /* ALTERA_EXPRT_H */ | ||
diff --git a/drivers/misc/altera-stapl/altera-jtag.c b/drivers/misc/altera-stapl/altera-jtag.c new file mode 100644 index 000000000000..f4bf20096972 --- /dev/null +++ b/drivers/misc/altera-stapl/altera-jtag.c | |||
| @@ -0,0 +1,1021 @@ | |||
| 1 | /* | ||
| 2 | * altera-jtag.c | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010 NetUP Inc. | ||
| 8 | * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/firmware.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <misc/altera.h> | ||
| 30 | #include "altera-exprt.h" | ||
| 31 | #include "altera-jtag.h" | ||
| 32 | |||
| 33 | #define alt_jtag_io(a, b, c)\ | ||
| 34 | astate->config->jtag_io(astate->config->dev, a, b, c); | ||
| 35 | |||
| 36 | #define alt_malloc(a) kzalloc(a, GFP_KERNEL); | ||
| 37 | |||
| 38 | /* | ||
| 39 | * This structure shows, for each JTAG state, which state is reached after | ||
| 40 | * a single TCK clock cycle with TMS high or TMS low, respectively. This | ||
| 41 | * describes all possible state transitions in the JTAG state machine. | ||
| 42 | */ | ||
| 43 | struct altera_jtag_machine { | ||
| 44 | enum altera_jtag_state tms_high; | ||
| 45 | enum altera_jtag_state tms_low; | ||
| 46 | }; | ||
| 47 | |||
| 48 | static const struct altera_jtag_machine altera_transitions[] = { | ||
| 49 | /* RESET */ { RESET, IDLE }, | ||
| 50 | /* IDLE */ { DRSELECT, IDLE }, | ||
| 51 | /* DRSELECT */ { IRSELECT, DRCAPTURE }, | ||
| 52 | /* DRCAPTURE */ { DREXIT1, DRSHIFT }, | ||
| 53 | /* DRSHIFT */ { DREXIT1, DRSHIFT }, | ||
| 54 | /* DREXIT1 */ { DRUPDATE, DRPAUSE }, | ||
| 55 | /* DRPAUSE */ { DREXIT2, DRPAUSE }, | ||
| 56 | /* DREXIT2 */ { DRUPDATE, DRSHIFT }, | ||
| 57 | /* DRUPDATE */ { DRSELECT, IDLE }, | ||
| 58 | /* IRSELECT */ { RESET, IRCAPTURE }, | ||
| 59 | /* IRCAPTURE */ { IREXIT1, IRSHIFT }, | ||
| 60 | /* IRSHIFT */ { IREXIT1, IRSHIFT }, | ||
| 61 | /* IREXIT1 */ { IRUPDATE, IRPAUSE }, | ||
| 62 | /* IRPAUSE */ { IREXIT2, IRPAUSE }, | ||
| 63 | /* IREXIT2 */ { IRUPDATE, IRSHIFT }, | ||
| 64 | /* IRUPDATE */ { DRSELECT, IDLE } | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* | ||
| 68 | * This table contains the TMS value to be used to take the NEXT STEP on | ||
| 69 | * the path to the desired state. The array index is the current state, | ||
| 70 | * and the bit position is the desired endstate. To find out which state | ||
| 71 | * is used as the intermediate state, look up the TMS value in the | ||
| 72 | * altera_transitions[] table. | ||
| 73 | */ | ||
| 74 | static const u16 altera_jtag_path_map[16] = { | ||
| 75 | /* RST RTI SDRS CDR SDR E1DR PDR E2DR */ | ||
| 76 | 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF, | ||
| 77 | /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */ | ||
| 78 | 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* Flag bits for alt_jtag_io() function */ | ||
| 82 | #define TMS_HIGH 1 | ||
| 83 | #define TMS_LOW 0 | ||
| 84 | #define TDI_HIGH 1 | ||
| 85 | #define TDI_LOW 0 | ||
| 86 | #define READ_TDO 1 | ||
| 87 | #define IGNORE_TDO 0 | ||
| 88 | |||
| 89 | int altera_jinit(struct altera_state *astate) | ||
| 90 | { | ||
| 91 | struct altera_jtag *js = &astate->js; | ||
| 92 | |||
| 93 | /* initial JTAG state is unknown */ | ||
| 94 | js->jtag_state = ILLEGAL_JTAG_STATE; | ||
| 95 | |||
| 96 | /* initialize to default state */ | ||
| 97 | js->drstop_state = IDLE; | ||
| 98 | js->irstop_state = IDLE; | ||
| 99 | js->dr_pre = 0; | ||
| 100 | js->dr_post = 0; | ||
| 101 | js->ir_pre = 0; | ||
| 102 | js->ir_post = 0; | ||
| 103 | js->dr_length = 0; | ||
| 104 | js->ir_length = 0; | ||
| 105 | |||
| 106 | js->dr_pre_data = NULL; | ||
| 107 | js->dr_post_data = NULL; | ||
| 108 | js->ir_pre_data = NULL; | ||
| 109 | js->ir_post_data = NULL; | ||
| 110 | js->dr_buffer = NULL; | ||
| 111 | js->ir_buffer = NULL; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state) | ||
| 117 | { | ||
| 118 | js->drstop_state = state; | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state) | ||
| 124 | { | ||
| 125 | js->irstop_state = state; | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | int altera_set_dr_pre(struct altera_jtag *js, | ||
| 131 | u32 count, u32 start_index, | ||
| 132 | u8 *preamble_data) | ||
| 133 | { | ||
| 134 | int status = 0; | ||
| 135 | u32 i; | ||
| 136 | u32 j; | ||
| 137 | |||
| 138 | if (count > js->dr_pre) { | ||
| 139 | kfree(js->dr_pre_data); | ||
| 140 | js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3); | ||
| 141 | if (js->dr_pre_data == NULL) | ||
| 142 | status = -ENOMEM; | ||
| 143 | else | ||
| 144 | js->dr_pre = count; | ||
| 145 | } else | ||
| 146 | js->dr_pre = count; | ||
| 147 | |||
| 148 | if (status == 0) { | ||
| 149 | for (i = 0; i < count; ++i) { | ||
| 150 | j = i + start_index; | ||
| 151 | |||
| 152 | if (preamble_data == NULL) | ||
| 153 | js->dr_pre_data[i >> 3] |= (1 << (i & 7)); | ||
| 154 | else { | ||
| 155 | if (preamble_data[j >> 3] & (1 << (j & 7))) | ||
| 156 | js->dr_pre_data[i >> 3] |= | ||
| 157 | (1 << (i & 7)); | ||
| 158 | else | ||
| 159 | js->dr_pre_data[i >> 3] &= | ||
| 160 | ~(u32)(1 << (i & 7)); | ||
| 161 | |||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | return status; | ||
| 167 | } | ||
| 168 | |||
| 169 | int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 170 | u8 *preamble_data) | ||
| 171 | { | ||
| 172 | int status = 0; | ||
| 173 | u32 i; | ||
| 174 | u32 j; | ||
| 175 | |||
| 176 | if (count > js->ir_pre) { | ||
| 177 | kfree(js->ir_pre_data); | ||
| 178 | js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3); | ||
| 179 | if (js->ir_pre_data == NULL) | ||
| 180 | status = -ENOMEM; | ||
| 181 | else | ||
| 182 | js->ir_pre = count; | ||
| 183 | |||
| 184 | } else | ||
| 185 | js->ir_pre = count; | ||
| 186 | |||
| 187 | if (status == 0) { | ||
| 188 | for (i = 0; i < count; ++i) { | ||
| 189 | j = i + start_index; | ||
| 190 | if (preamble_data == NULL) | ||
| 191 | js->ir_pre_data[i >> 3] |= (1 << (i & 7)); | ||
| 192 | else { | ||
| 193 | if (preamble_data[j >> 3] & (1 << (j & 7))) | ||
| 194 | js->ir_pre_data[i >> 3] |= | ||
| 195 | (1 << (i & 7)); | ||
| 196 | else | ||
| 197 | js->ir_pre_data[i >> 3] &= | ||
| 198 | ~(u32)(1 << (i & 7)); | ||
| 199 | |||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | return status; | ||
| 205 | } | ||
| 206 | |||
| 207 | int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 208 | u8 *postamble_data) | ||
| 209 | { | ||
| 210 | int status = 0; | ||
| 211 | u32 i; | ||
| 212 | u32 j; | ||
| 213 | |||
| 214 | if (count > js->dr_post) { | ||
| 215 | kfree(js->dr_post_data); | ||
| 216 | js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3); | ||
| 217 | |||
| 218 | if (js->dr_post_data == NULL) | ||
| 219 | status = -ENOMEM; | ||
| 220 | else | ||
| 221 | js->dr_post = count; | ||
| 222 | |||
| 223 | } else | ||
| 224 | js->dr_post = count; | ||
| 225 | |||
| 226 | if (status == 0) { | ||
| 227 | for (i = 0; i < count; ++i) { | ||
| 228 | j = i + start_index; | ||
| 229 | |||
| 230 | if (postamble_data == NULL) | ||
| 231 | js->dr_post_data[i >> 3] |= (1 << (i & 7)); | ||
| 232 | else { | ||
| 233 | if (postamble_data[j >> 3] & (1 << (j & 7))) | ||
| 234 | js->dr_post_data[i >> 3] |= | ||
| 235 | (1 << (i & 7)); | ||
| 236 | else | ||
| 237 | js->dr_post_data[i >> 3] &= | ||
| 238 | ~(u32)(1 << (i & 7)); | ||
| 239 | |||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | return status; | ||
| 245 | } | ||
| 246 | |||
| 247 | int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 248 | u8 *postamble_data) | ||
| 249 | { | ||
| 250 | int status = 0; | ||
| 251 | u32 i; | ||
| 252 | u32 j; | ||
| 253 | |||
| 254 | if (count > js->ir_post) { | ||
| 255 | kfree(js->ir_post_data); | ||
| 256 | js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3); | ||
| 257 | if (js->ir_post_data == NULL) | ||
| 258 | status = -ENOMEM; | ||
| 259 | else | ||
| 260 | js->ir_post = count; | ||
| 261 | |||
| 262 | } else | ||
| 263 | js->ir_post = count; | ||
| 264 | |||
| 265 | if (status != 0) | ||
| 266 | return status; | ||
| 267 | |||
| 268 | for (i = 0; i < count; ++i) { | ||
| 269 | j = i + start_index; | ||
| 270 | |||
| 271 | if (postamble_data == NULL) | ||
| 272 | js->ir_post_data[i >> 3] |= (1 << (i & 7)); | ||
| 273 | else { | ||
| 274 | if (postamble_data[j >> 3] & (1 << (j & 7))) | ||
| 275 | js->ir_post_data[i >> 3] |= (1 << (i & 7)); | ||
| 276 | else | ||
| 277 | js->ir_post_data[i >> 3] &= | ||
| 278 | ~(u32)(1 << (i & 7)); | ||
| 279 | |||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | return status; | ||
| 284 | } | ||
| 285 | |||
| 286 | static void altera_jreset_idle(struct altera_state *astate) | ||
| 287 | { | ||
| 288 | struct altera_jtag *js = &astate->js; | ||
| 289 | int i; | ||
| 290 | /* Go to Test Logic Reset (no matter what the starting state may be) */ | ||
| 291 | for (i = 0; i < 5; ++i) | ||
| 292 | alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); | ||
| 293 | |||
| 294 | /* Now step to Run Test / Idle */ | ||
| 295 | alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); | ||
| 296 | js->jtag_state = IDLE; | ||
| 297 | } | ||
| 298 | |||
| 299 | int altera_goto_jstate(struct altera_state *astate, | ||
| 300 | enum altera_jtag_state state) | ||
| 301 | { | ||
| 302 | struct altera_jtag *js = &astate->js; | ||
| 303 | int tms; | ||
| 304 | int count = 0; | ||
| 305 | int status = 0; | ||
| 306 | |||
| 307 | if (js->jtag_state == ILLEGAL_JTAG_STATE) | ||
| 308 | /* initialize JTAG chain to known state */ | ||
| 309 | altera_jreset_idle(astate); | ||
| 310 | |||
| 311 | if (js->jtag_state == state) { | ||
| 312 | /* | ||
| 313 | * We are already in the desired state. | ||
| 314 | * If it is a stable state, loop here. | ||
| 315 | * Otherwise do nothing (no clock cycles). | ||
| 316 | */ | ||
| 317 | if ((state == IDLE) || (state == DRSHIFT) || | ||
| 318 | (state == DRPAUSE) || (state == IRSHIFT) || | ||
| 319 | (state == IRPAUSE)) { | ||
| 320 | alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); | ||
| 321 | } else if (state == RESET) | ||
| 322 | alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); | ||
| 323 | |||
| 324 | } else { | ||
| 325 | while ((js->jtag_state != state) && (count < 9)) { | ||
| 326 | /* Get TMS value to take a step toward desired state */ | ||
| 327 | tms = (altera_jtag_path_map[js->jtag_state] & | ||
| 328 | (1 << state)) | ||
| 329 | ? TMS_HIGH : TMS_LOW; | ||
| 330 | |||
| 331 | /* Take a step */ | ||
| 332 | alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); | ||
| 333 | |||
| 334 | if (tms) | ||
| 335 | js->jtag_state = | ||
| 336 | altera_transitions[js->jtag_state].tms_high; | ||
| 337 | else | ||
| 338 | js->jtag_state = | ||
| 339 | altera_transitions[js->jtag_state].tms_low; | ||
| 340 | |||
| 341 | ++count; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | if (js->jtag_state != state) | ||
| 346 | status = -EREMOTEIO; | ||
| 347 | |||
| 348 | return status; | ||
| 349 | } | ||
| 350 | |||
| 351 | int altera_wait_cycles(struct altera_state *astate, | ||
| 352 | s32 cycles, | ||
| 353 | enum altera_jtag_state wait_state) | ||
| 354 | { | ||
| 355 | struct altera_jtag *js = &astate->js; | ||
| 356 | int tms; | ||
| 357 | s32 count; | ||
| 358 | int status = 0; | ||
| 359 | |||
| 360 | if (js->jtag_state != wait_state) | ||
| 361 | status = altera_goto_jstate(astate, wait_state); | ||
| 362 | |||
| 363 | if (status == 0) { | ||
| 364 | /* | ||
| 365 | * Set TMS high to loop in RESET state | ||
| 366 | * Set TMS low to loop in any other stable state | ||
| 367 | */ | ||
| 368 | tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW; | ||
| 369 | |||
| 370 | for (count = 0L; count < cycles; count++) | ||
| 371 | alt_jtag_io(tms, TDI_LOW, IGNORE_TDO); | ||
| 372 | |||
| 373 | } | ||
| 374 | |||
| 375 | return status; | ||
| 376 | } | ||
| 377 | |||
| 378 | int altera_wait_msecs(struct altera_state *astate, | ||
| 379 | s32 microseconds, enum altera_jtag_state wait_state) | ||
| 380 | /* | ||
| 381 | * Causes JTAG hardware to sit in the specified stable | ||
| 382 | * state for the specified duration of real time. If | ||
| 383 | * no JTAG operations have been performed yet, then only | ||
| 384 | * a delay is performed. This permits the WAIT USECS | ||
| 385 | * statement to be used in VECTOR programs without causing | ||
| 386 | * any JTAG operations. | ||
| 387 | * Returns 0 for success, else appropriate error code. | ||
| 388 | */ | ||
| 389 | { | ||
| 390 | struct altera_jtag *js = &astate->js; | ||
| 391 | int status = 0; | ||
| 392 | |||
| 393 | if ((js->jtag_state != ILLEGAL_JTAG_STATE) && | ||
| 394 | (js->jtag_state != wait_state)) | ||
| 395 | status = altera_goto_jstate(astate, wait_state); | ||
| 396 | |||
| 397 | if (status == 0) | ||
| 398 | /* Wait for specified time interval */ | ||
| 399 | udelay(microseconds); | ||
| 400 | |||
| 401 | return status; | ||
| 402 | } | ||
| 403 | |||
| 404 | static void altera_concatenate_data(u8 *buffer, | ||
| 405 | u8 *preamble_data, | ||
| 406 | u32 preamble_count, | ||
| 407 | u8 *target_data, | ||
| 408 | u32 start_index, | ||
| 409 | u32 target_count, | ||
| 410 | u8 *postamble_data, | ||
| 411 | u32 postamble_count) | ||
| 412 | /* | ||
| 413 | * Copies preamble data, target data, and postamble data | ||
| 414 | * into one buffer for IR or DR scans. | ||
| 415 | */ | ||
| 416 | { | ||
| 417 | u32 i, j, k; | ||
| 418 | |||
| 419 | for (i = 0L; i < preamble_count; ++i) { | ||
| 420 | if (preamble_data[i >> 3L] & (1L << (i & 7L))) | ||
| 421 | buffer[i >> 3L] |= (1L << (i & 7L)); | ||
| 422 | else | ||
| 423 | buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); | ||
| 424 | |||
| 425 | } | ||
| 426 | |||
| 427 | j = start_index; | ||
| 428 | k = preamble_count + target_count; | ||
| 429 | for (; i < k; ++i, ++j) { | ||
| 430 | if (target_data[j >> 3L] & (1L << (j & 7L))) | ||
| 431 | buffer[i >> 3L] |= (1L << (i & 7L)); | ||
| 432 | else | ||
| 433 | buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); | ||
| 434 | |||
| 435 | } | ||
| 436 | |||
| 437 | j = 0L; | ||
| 438 | k = preamble_count + target_count + postamble_count; | ||
| 439 | for (; i < k; ++i, ++j) { | ||
| 440 | if (postamble_data[j >> 3L] & (1L << (j & 7L))) | ||
| 441 | buffer[i >> 3L] |= (1L << (i & 7L)); | ||
| 442 | else | ||
| 443 | buffer[i >> 3L] &= ~(u32)(1L << (i & 7L)); | ||
| 444 | |||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 448 | static int alt_jtag_drscan(struct altera_state *astate, | ||
| 449 | int start_state, | ||
| 450 | int count, | ||
| 451 | u8 *tdi, | ||
| 452 | u8 *tdo) | ||
| 453 | { | ||
| 454 | int i = 0; | ||
| 455 | int tdo_bit = 0; | ||
| 456 | int status = 1; | ||
| 457 | |||
| 458 | /* First go to DRSHIFT state */ | ||
| 459 | switch (start_state) { | ||
| 460 | case 0: /* IDLE */ | ||
| 461 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 462 | alt_jtag_io(0, 0, 0); /* DRCAPTURE */ | ||
| 463 | alt_jtag_io(0, 0, 0); /* DRSHIFT */ | ||
| 464 | break; | ||
| 465 | |||
| 466 | case 1: /* DRPAUSE */ | ||
| 467 | alt_jtag_io(1, 0, 0); /* DREXIT2 */ | ||
| 468 | alt_jtag_io(1, 0, 0); /* DRUPDATE */ | ||
| 469 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 470 | alt_jtag_io(0, 0, 0); /* DRCAPTURE */ | ||
| 471 | alt_jtag_io(0, 0, 0); /* DRSHIFT */ | ||
| 472 | break; | ||
| 473 | |||
| 474 | case 2: /* IRPAUSE */ | ||
| 475 | alt_jtag_io(1, 0, 0); /* IREXIT2 */ | ||
| 476 | alt_jtag_io(1, 0, 0); /* IRUPDATE */ | ||
| 477 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 478 | alt_jtag_io(0, 0, 0); /* DRCAPTURE */ | ||
| 479 | alt_jtag_io(0, 0, 0); /* DRSHIFT */ | ||
| 480 | break; | ||
| 481 | |||
| 482 | default: | ||
| 483 | status = 0; | ||
| 484 | } | ||
| 485 | |||
| 486 | if (status) { | ||
| 487 | /* loop in the SHIFT-DR state */ | ||
| 488 | for (i = 0; i < count; i++) { | ||
| 489 | tdo_bit = alt_jtag_io( | ||
| 490 | (i == count - 1), | ||
| 491 | tdi[i >> 3] & (1 << (i & 7)), | ||
| 492 | (tdo != NULL)); | ||
| 493 | |||
| 494 | if (tdo != NULL) { | ||
| 495 | if (tdo_bit) | ||
| 496 | tdo[i >> 3] |= (1 << (i & 7)); | ||
| 497 | else | ||
| 498 | tdo[i >> 3] &= ~(u32)(1 << (i & 7)); | ||
| 499 | |||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | alt_jtag_io(0, 0, 0); /* DRPAUSE */ | ||
| 504 | } | ||
| 505 | |||
| 506 | return status; | ||
| 507 | } | ||
| 508 | |||
| 509 | static int alt_jtag_irscan(struct altera_state *astate, | ||
| 510 | int start_state, | ||
| 511 | int count, | ||
| 512 | u8 *tdi, | ||
| 513 | u8 *tdo) | ||
| 514 | { | ||
| 515 | int i = 0; | ||
| 516 | int tdo_bit = 0; | ||
| 517 | int status = 1; | ||
| 518 | |||
| 519 | /* First go to IRSHIFT state */ | ||
| 520 | switch (start_state) { | ||
| 521 | case 0: /* IDLE */ | ||
| 522 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 523 | alt_jtag_io(1, 0, 0); /* IRSELECT */ | ||
| 524 | alt_jtag_io(0, 0, 0); /* IRCAPTURE */ | ||
| 525 | alt_jtag_io(0, 0, 0); /* IRSHIFT */ | ||
| 526 | break; | ||
| 527 | |||
| 528 | case 1: /* DRPAUSE */ | ||
| 529 | alt_jtag_io(1, 0, 0); /* DREXIT2 */ | ||
| 530 | alt_jtag_io(1, 0, 0); /* DRUPDATE */ | ||
| 531 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 532 | alt_jtag_io(1, 0, 0); /* IRSELECT */ | ||
| 533 | alt_jtag_io(0, 0, 0); /* IRCAPTURE */ | ||
| 534 | alt_jtag_io(0, 0, 0); /* IRSHIFT */ | ||
| 535 | break; | ||
| 536 | |||
| 537 | case 2: /* IRPAUSE */ | ||
| 538 | alt_jtag_io(1, 0, 0); /* IREXIT2 */ | ||
| 539 | alt_jtag_io(1, 0, 0); /* IRUPDATE */ | ||
| 540 | alt_jtag_io(1, 0, 0); /* DRSELECT */ | ||
| 541 | alt_jtag_io(1, 0, 0); /* IRSELECT */ | ||
| 542 | alt_jtag_io(0, 0, 0); /* IRCAPTURE */ | ||
| 543 | alt_jtag_io(0, 0, 0); /* IRSHIFT */ | ||
| 544 | break; | ||
| 545 | |||
| 546 | default: | ||
| 547 | status = 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | if (status) { | ||
| 551 | /* loop in the SHIFT-IR state */ | ||
| 552 | for (i = 0; i < count; i++) { | ||
| 553 | tdo_bit = alt_jtag_io( | ||
| 554 | (i == count - 1), | ||
| 555 | tdi[i >> 3] & (1 << (i & 7)), | ||
| 556 | (tdo != NULL)); | ||
| 557 | if (tdo != NULL) { | ||
| 558 | if (tdo_bit) | ||
| 559 | tdo[i >> 3] |= (1 << (i & 7)); | ||
| 560 | else | ||
| 561 | tdo[i >> 3] &= ~(u32)(1 << (i & 7)); | ||
| 562 | |||
| 563 | } | ||
| 564 | } | ||
| 565 | |||
| 566 | alt_jtag_io(0, 0, 0); /* IRPAUSE */ | ||
| 567 | } | ||
| 568 | |||
| 569 | return status; | ||
| 570 | } | ||
| 571 | |||
| 572 | static void altera_extract_target_data(u8 *buffer, | ||
| 573 | u8 *target_data, | ||
| 574 | u32 start_index, | ||
| 575 | u32 preamble_count, | ||
| 576 | u32 target_count) | ||
| 577 | /* | ||
| 578 | * Copies target data from scan buffer, filtering out | ||
| 579 | * preamble and postamble data. | ||
| 580 | */ | ||
| 581 | { | ||
| 582 | u32 i; | ||
| 583 | u32 j; | ||
| 584 | u32 k; | ||
| 585 | |||
| 586 | j = preamble_count; | ||
| 587 | k = start_index + target_count; | ||
| 588 | for (i = start_index; i < k; ++i, ++j) { | ||
| 589 | if (buffer[j >> 3] & (1 << (j & 7))) | ||
| 590 | target_data[i >> 3] |= (1 << (i & 7)); | ||
| 591 | else | ||
| 592 | target_data[i >> 3] &= ~(u32)(1 << (i & 7)); | ||
| 593 | |||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | int altera_irscan(struct altera_state *astate, | ||
| 598 | u32 count, | ||
| 599 | u8 *tdi_data, | ||
| 600 | u32 start_index) | ||
| 601 | /* Shifts data into instruction register */ | ||
| 602 | { | ||
| 603 | struct altera_jtag *js = &astate->js; | ||
| 604 | int start_code = 0; | ||
| 605 | u32 alloc_chars = 0; | ||
| 606 | u32 shift_count = js->ir_pre + count + js->ir_post; | ||
| 607 | int status = 0; | ||
| 608 | enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; | ||
| 609 | |||
| 610 | switch (js->jtag_state) { | ||
| 611 | case ILLEGAL_JTAG_STATE: | ||
| 612 | case RESET: | ||
| 613 | case IDLE: | ||
| 614 | start_code = 0; | ||
| 615 | start_state = IDLE; | ||
| 616 | break; | ||
| 617 | |||
| 618 | case DRSELECT: | ||
| 619 | case DRCAPTURE: | ||
| 620 | case DRSHIFT: | ||
| 621 | case DREXIT1: | ||
| 622 | case DRPAUSE: | ||
| 623 | case DREXIT2: | ||
| 624 | case DRUPDATE: | ||
| 625 | start_code = 1; | ||
| 626 | start_state = DRPAUSE; | ||
| 627 | break; | ||
| 628 | |||
| 629 | case IRSELECT: | ||
| 630 | case IRCAPTURE: | ||
| 631 | case IRSHIFT: | ||
| 632 | case IREXIT1: | ||
| 633 | case IRPAUSE: | ||
| 634 | case IREXIT2: | ||
| 635 | case IRUPDATE: | ||
| 636 | start_code = 2; | ||
| 637 | start_state = IRPAUSE; | ||
| 638 | break; | ||
| 639 | |||
| 640 | default: | ||
| 641 | status = -EREMOTEIO; | ||
| 642 | break; | ||
| 643 | } | ||
| 644 | |||
| 645 | if (status == 0) | ||
| 646 | if (js->jtag_state != start_state) | ||
| 647 | status = altera_goto_jstate(astate, start_state); | ||
| 648 | |||
| 649 | if (status == 0) { | ||
| 650 | if (shift_count > js->ir_length) { | ||
| 651 | alloc_chars = (shift_count + 7) >> 3; | ||
| 652 | kfree(js->ir_buffer); | ||
| 653 | js->ir_buffer = (u8 *)alt_malloc(alloc_chars); | ||
| 654 | if (js->ir_buffer == NULL) | ||
| 655 | status = -ENOMEM; | ||
| 656 | else | ||
| 657 | js->ir_length = alloc_chars * 8; | ||
| 658 | |||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | if (status == 0) { | ||
| 663 | /* | ||
| 664 | * Copy preamble data, IR data, | ||
| 665 | * and postamble data into a buffer | ||
| 666 | */ | ||
| 667 | altera_concatenate_data(js->ir_buffer, | ||
| 668 | js->ir_pre_data, | ||
| 669 | js->ir_pre, | ||
| 670 | tdi_data, | ||
| 671 | start_index, | ||
| 672 | count, | ||
| 673 | js->ir_post_data, | ||
| 674 | js->ir_post); | ||
| 675 | /* Do the IRSCAN */ | ||
| 676 | alt_jtag_irscan(astate, | ||
| 677 | start_code, | ||
| 678 | shift_count, | ||
| 679 | js->ir_buffer, | ||
| 680 | NULL); | ||
| 681 | |||
| 682 | /* alt_jtag_irscan() always ends in IRPAUSE state */ | ||
| 683 | js->jtag_state = IRPAUSE; | ||
| 684 | } | ||
| 685 | |||
| 686 | if (status == 0) | ||
| 687 | if (js->irstop_state != IRPAUSE) | ||
| 688 | status = altera_goto_jstate(astate, js->irstop_state); | ||
| 689 | |||
| 690 | |||
| 691 | return status; | ||
| 692 | } | ||
| 693 | |||
| 694 | int altera_swap_ir(struct altera_state *astate, | ||
| 695 | u32 count, | ||
| 696 | u8 *in_data, | ||
| 697 | u32 in_index, | ||
| 698 | u8 *out_data, | ||
| 699 | u32 out_index) | ||
| 700 | /* Shifts data into instruction register, capturing output data */ | ||
| 701 | { | ||
| 702 | struct altera_jtag *js = &astate->js; | ||
| 703 | int start_code = 0; | ||
| 704 | u32 alloc_chars = 0; | ||
| 705 | u32 shift_count = js->ir_pre + count + js->ir_post; | ||
| 706 | int status = 0; | ||
| 707 | enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; | ||
| 708 | |||
| 709 | switch (js->jtag_state) { | ||
| 710 | case ILLEGAL_JTAG_STATE: | ||
| 711 | case RESET: | ||
| 712 | case IDLE: | ||
| 713 | start_code = 0; | ||
| 714 | start_state = IDLE; | ||
| 715 | break; | ||
| 716 | |||
| 717 | case DRSELECT: | ||
| 718 | case DRCAPTURE: | ||
| 719 | case DRSHIFT: | ||
| 720 | case DREXIT1: | ||
| 721 | case DRPAUSE: | ||
| 722 | case DREXIT2: | ||
| 723 | case DRUPDATE: | ||
| 724 | start_code = 1; | ||
| 725 | start_state = DRPAUSE; | ||
| 726 | break; | ||
| 727 | |||
| 728 | case IRSELECT: | ||
| 729 | case IRCAPTURE: | ||
| 730 | case IRSHIFT: | ||
| 731 | case IREXIT1: | ||
| 732 | case IRPAUSE: | ||
| 733 | case IREXIT2: | ||
| 734 | case IRUPDATE: | ||
| 735 | start_code = 2; | ||
| 736 | start_state = IRPAUSE; | ||
| 737 | break; | ||
| 738 | |||
| 739 | default: | ||
| 740 | status = -EREMOTEIO; | ||
| 741 | break; | ||
| 742 | } | ||
| 743 | |||
| 744 | if (status == 0) | ||
| 745 | if (js->jtag_state != start_state) | ||
| 746 | status = altera_goto_jstate(astate, start_state); | ||
| 747 | |||
| 748 | if (status == 0) { | ||
| 749 | if (shift_count > js->ir_length) { | ||
| 750 | alloc_chars = (shift_count + 7) >> 3; | ||
| 751 | kfree(js->ir_buffer); | ||
| 752 | js->ir_buffer = (u8 *)alt_malloc(alloc_chars); | ||
| 753 | if (js->ir_buffer == NULL) | ||
| 754 | status = -ENOMEM; | ||
| 755 | else | ||
| 756 | js->ir_length = alloc_chars * 8; | ||
| 757 | |||
| 758 | } | ||
| 759 | } | ||
| 760 | |||
| 761 | if (status == 0) { | ||
| 762 | /* | ||
| 763 | * Copy preamble data, IR data, | ||
| 764 | * and postamble data into a buffer | ||
| 765 | */ | ||
| 766 | altera_concatenate_data(js->ir_buffer, | ||
| 767 | js->ir_pre_data, | ||
| 768 | js->ir_pre, | ||
| 769 | in_data, | ||
| 770 | in_index, | ||
| 771 | count, | ||
| 772 | js->ir_post_data, | ||
| 773 | js->ir_post); | ||
| 774 | |||
| 775 | /* Do the IRSCAN */ | ||
| 776 | alt_jtag_irscan(astate, | ||
| 777 | start_code, | ||
| 778 | shift_count, | ||
| 779 | js->ir_buffer, | ||
| 780 | js->ir_buffer); | ||
| 781 | |||
| 782 | /* alt_jtag_irscan() always ends in IRPAUSE state */ | ||
| 783 | js->jtag_state = IRPAUSE; | ||
| 784 | } | ||
| 785 | |||
| 786 | if (status == 0) | ||
| 787 | if (js->irstop_state != IRPAUSE) | ||
| 788 | status = altera_goto_jstate(astate, js->irstop_state); | ||
| 789 | |||
| 790 | |||
| 791 | if (status == 0) | ||
| 792 | /* Now extract the returned data from the buffer */ | ||
| 793 | altera_extract_target_data(js->ir_buffer, | ||
| 794 | out_data, out_index, | ||
| 795 | js->ir_pre, count); | ||
| 796 | |||
| 797 | return status; | ||
| 798 | } | ||
| 799 | |||
| 800 | int altera_drscan(struct altera_state *astate, | ||
| 801 | u32 count, | ||
| 802 | u8 *tdi_data, | ||
| 803 | u32 start_index) | ||
| 804 | /* Shifts data into data register (ignoring output data) */ | ||
| 805 | { | ||
| 806 | struct altera_jtag *js = &astate->js; | ||
| 807 | int start_code = 0; | ||
| 808 | u32 alloc_chars = 0; | ||
| 809 | u32 shift_count = js->dr_pre + count + js->dr_post; | ||
| 810 | int status = 0; | ||
| 811 | enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; | ||
| 812 | |||
| 813 | switch (js->jtag_state) { | ||
| 814 | case ILLEGAL_JTAG_STATE: | ||
| 815 | case RESET: | ||
| 816 | case IDLE: | ||
| 817 | start_code = 0; | ||
| 818 | start_state = IDLE; | ||
| 819 | break; | ||
| 820 | |||
| 821 | case DRSELECT: | ||
| 822 | case DRCAPTURE: | ||
| 823 | case DRSHIFT: | ||
| 824 | case DREXIT1: | ||
| 825 | case DRPAUSE: | ||
| 826 | case DREXIT2: | ||
| 827 | case DRUPDATE: | ||
| 828 | start_code = 1; | ||
| 829 | start_state = DRPAUSE; | ||
| 830 | break; | ||
| 831 | |||
| 832 | case IRSELECT: | ||
| 833 | case IRCAPTURE: | ||
| 834 | case IRSHIFT: | ||
| 835 | case IREXIT1: | ||
| 836 | case IRPAUSE: | ||
| 837 | case IREXIT2: | ||
| 838 | case IRUPDATE: | ||
| 839 | start_code = 2; | ||
| 840 | start_state = IRPAUSE; | ||
| 841 | break; | ||
| 842 | |||
| 843 | default: | ||
| 844 | status = -EREMOTEIO; | ||
| 845 | break; | ||
| 846 | } | ||
| 847 | |||
| 848 | if (status == 0) | ||
| 849 | if (js->jtag_state != start_state) | ||
| 850 | status = altera_goto_jstate(astate, start_state); | ||
| 851 | |||
| 852 | if (status == 0) { | ||
| 853 | if (shift_count > js->dr_length) { | ||
| 854 | alloc_chars = (shift_count + 7) >> 3; | ||
| 855 | kfree(js->dr_buffer); | ||
| 856 | js->dr_buffer = (u8 *)alt_malloc(alloc_chars); | ||
| 857 | if (js->dr_buffer == NULL) | ||
| 858 | status = -ENOMEM; | ||
| 859 | else | ||
| 860 | js->dr_length = alloc_chars * 8; | ||
| 861 | |||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 865 | if (status == 0) { | ||
| 866 | /* | ||
| 867 | * Copy preamble data, DR data, | ||
| 868 | * and postamble data into a buffer | ||
| 869 | */ | ||
| 870 | altera_concatenate_data(js->dr_buffer, | ||
| 871 | js->dr_pre_data, | ||
| 872 | js->dr_pre, | ||
| 873 | tdi_data, | ||
| 874 | start_index, | ||
| 875 | count, | ||
| 876 | js->dr_post_data, | ||
| 877 | js->dr_post); | ||
| 878 | /* Do the DRSCAN */ | ||
| 879 | alt_jtag_drscan(astate, start_code, shift_count, | ||
| 880 | js->dr_buffer, NULL); | ||
| 881 | /* alt_jtag_drscan() always ends in DRPAUSE state */ | ||
| 882 | js->jtag_state = DRPAUSE; | ||
| 883 | } | ||
| 884 | |||
| 885 | if (status == 0) | ||
| 886 | if (js->drstop_state != DRPAUSE) | ||
| 887 | status = altera_goto_jstate(astate, js->drstop_state); | ||
| 888 | |||
| 889 | return status; | ||
| 890 | } | ||
| 891 | |||
| 892 | int altera_swap_dr(struct altera_state *astate, u32 count, | ||
| 893 | u8 *in_data, u32 in_index, | ||
| 894 | u8 *out_data, u32 out_index) | ||
| 895 | /* Shifts data into data register, capturing output data */ | ||
| 896 | { | ||
| 897 | struct altera_jtag *js = &astate->js; | ||
| 898 | int start_code = 0; | ||
| 899 | u32 alloc_chars = 0; | ||
| 900 | u32 shift_count = js->dr_pre + count + js->dr_post; | ||
| 901 | int status = 0; | ||
| 902 | enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE; | ||
| 903 | |||
| 904 | switch (js->jtag_state) { | ||
| 905 | case ILLEGAL_JTAG_STATE: | ||
| 906 | case RESET: | ||
| 907 | case IDLE: | ||
| 908 | start_code = 0; | ||
| 909 | start_state = IDLE; | ||
| 910 | break; | ||
| 911 | |||
| 912 | case DRSELECT: | ||
| 913 | case DRCAPTURE: | ||
| 914 | case DRSHIFT: | ||
| 915 | case DREXIT1: | ||
| 916 | case DRPAUSE: | ||
| 917 | case DREXIT2: | ||
| 918 | case DRUPDATE: | ||
| 919 | start_code = 1; | ||
| 920 | start_state = DRPAUSE; | ||
| 921 | break; | ||
| 922 | |||
| 923 | case IRSELECT: | ||
| 924 | case IRCAPTURE: | ||
| 925 | case IRSHIFT: | ||
| 926 | case IREXIT1: | ||
| 927 | case IRPAUSE: | ||
| 928 | case IREXIT2: | ||
| 929 | case IRUPDATE: | ||
| 930 | start_code = 2; | ||
| 931 | start_state = IRPAUSE; | ||
| 932 | break; | ||
| 933 | |||
| 934 | default: | ||
| 935 | status = -EREMOTEIO; | ||
| 936 | break; | ||
| 937 | } | ||
| 938 | |||
| 939 | if (status == 0) | ||
| 940 | if (js->jtag_state != start_state) | ||
| 941 | status = altera_goto_jstate(astate, start_state); | ||
| 942 | |||
| 943 | if (status == 0) { | ||
| 944 | if (shift_count > js->dr_length) { | ||
| 945 | alloc_chars = (shift_count + 7) >> 3; | ||
| 946 | kfree(js->dr_buffer); | ||
| 947 | js->dr_buffer = (u8 *)alt_malloc(alloc_chars); | ||
| 948 | |||
| 949 | if (js->dr_buffer == NULL) | ||
| 950 | status = -ENOMEM; | ||
| 951 | else | ||
| 952 | js->dr_length = alloc_chars * 8; | ||
| 953 | |||
| 954 | } | ||
| 955 | } | ||
| 956 | |||
| 957 | if (status == 0) { | ||
| 958 | /* | ||
| 959 | * Copy preamble data, DR data, | ||
| 960 | * and postamble data into a buffer | ||
| 961 | */ | ||
| 962 | altera_concatenate_data(js->dr_buffer, | ||
| 963 | js->dr_pre_data, | ||
| 964 | js->dr_pre, | ||
| 965 | in_data, | ||
| 966 | in_index, | ||
| 967 | count, | ||
| 968 | js->dr_post_data, | ||
| 969 | js->dr_post); | ||
| 970 | |||
| 971 | /* Do the DRSCAN */ | ||
| 972 | alt_jtag_drscan(astate, | ||
| 973 | start_code, | ||
| 974 | shift_count, | ||
| 975 | js->dr_buffer, | ||
| 976 | js->dr_buffer); | ||
| 977 | |||
| 978 | /* alt_jtag_drscan() always ends in DRPAUSE state */ | ||
| 979 | js->jtag_state = DRPAUSE; | ||
| 980 | } | ||
| 981 | |||
| 982 | if (status == 0) | ||
| 983 | if (js->drstop_state != DRPAUSE) | ||
| 984 | status = altera_goto_jstate(astate, js->drstop_state); | ||
| 985 | |||
| 986 | if (status == 0) | ||
| 987 | /* Now extract the returned data from the buffer */ | ||
| 988 | altera_extract_target_data(js->dr_buffer, | ||
| 989 | out_data, | ||
| 990 | out_index, | ||
| 991 | js->dr_pre, | ||
| 992 | count); | ||
| 993 | |||
| 994 | return status; | ||
| 995 | } | ||
| 996 | |||
| 997 | void altera_free_buffers(struct altera_state *astate) | ||
| 998 | { | ||
| 999 | struct altera_jtag *js = &astate->js; | ||
| 1000 | /* If the JTAG interface was used, reset it to TLR */ | ||
| 1001 | if (js->jtag_state != ILLEGAL_JTAG_STATE) | ||
| 1002 | altera_jreset_idle(astate); | ||
| 1003 | |||
| 1004 | kfree(js->dr_pre_data); | ||
| 1005 | js->dr_pre_data = NULL; | ||
| 1006 | |||
| 1007 | kfree(js->dr_post_data); | ||
| 1008 | js->dr_post_data = NULL; | ||
| 1009 | |||
| 1010 | kfree(js->dr_buffer); | ||
| 1011 | js->dr_buffer = NULL; | ||
| 1012 | |||
| 1013 | kfree(js->ir_pre_data); | ||
| 1014 | js->ir_pre_data = NULL; | ||
| 1015 | |||
| 1016 | kfree(js->ir_post_data); | ||
| 1017 | js->ir_post_data = NULL; | ||
| 1018 | |||
| 1019 | kfree(js->ir_buffer); | ||
| 1020 | js->ir_buffer = NULL; | ||
| 1021 | } | ||
diff --git a/drivers/misc/altera-stapl/altera-jtag.h b/drivers/misc/altera-stapl/altera-jtag.h new file mode 100644 index 000000000000..2f97e36a2fbc --- /dev/null +++ b/drivers/misc/altera-stapl/altera-jtag.h | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | /* | ||
| 2 | * altera-jtag.h | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010 NetUP Inc. | ||
| 8 | * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #ifndef ALTERA_JTAG_H | ||
| 27 | #define ALTERA_JTAG_H | ||
| 28 | |||
| 29 | /* Function Prototypes */ | ||
| 30 | enum altera_jtag_state { | ||
| 31 | ILLEGAL_JTAG_STATE = -1, | ||
| 32 | RESET = 0, | ||
| 33 | IDLE = 1, | ||
| 34 | DRSELECT = 2, | ||
| 35 | DRCAPTURE = 3, | ||
| 36 | DRSHIFT = 4, | ||
| 37 | DREXIT1 = 5, | ||
| 38 | DRPAUSE = 6, | ||
| 39 | DREXIT2 = 7, | ||
| 40 | DRUPDATE = 8, | ||
| 41 | IRSELECT = 9, | ||
| 42 | IRCAPTURE = 10, | ||
| 43 | IRSHIFT = 11, | ||
| 44 | IREXIT1 = 12, | ||
| 45 | IRPAUSE = 13, | ||
| 46 | IREXIT2 = 14, | ||
| 47 | IRUPDATE = 15 | ||
| 48 | |||
| 49 | }; | ||
| 50 | |||
| 51 | struct altera_jtag { | ||
| 52 | /* Global variable to store the current JTAG state */ | ||
| 53 | enum altera_jtag_state jtag_state; | ||
| 54 | |||
| 55 | /* Store current stop-state for DR and IR scan commands */ | ||
| 56 | enum altera_jtag_state drstop_state; | ||
| 57 | enum altera_jtag_state irstop_state; | ||
| 58 | |||
| 59 | /* Store current padding values */ | ||
| 60 | u32 dr_pre; | ||
| 61 | u32 dr_post; | ||
| 62 | u32 ir_pre; | ||
| 63 | u32 ir_post; | ||
| 64 | u32 dr_length; | ||
| 65 | u32 ir_length; | ||
| 66 | u8 *dr_pre_data; | ||
| 67 | u8 *dr_post_data; | ||
| 68 | u8 *ir_pre_data; | ||
| 69 | u8 *ir_post_data; | ||
| 70 | u8 *dr_buffer; | ||
| 71 | u8 *ir_buffer; | ||
| 72 | }; | ||
| 73 | |||
| 74 | #define ALTERA_STACK_SIZE 128 | ||
| 75 | #define ALTERA_MESSAGE_LENGTH 1024 | ||
| 76 | |||
| 77 | struct altera_state { | ||
| 78 | struct altera_config *config; | ||
| 79 | struct altera_jtag js; | ||
| 80 | char msg_buff[ALTERA_MESSAGE_LENGTH + 1]; | ||
| 81 | long stack[ALTERA_STACK_SIZE]; | ||
| 82 | }; | ||
| 83 | |||
| 84 | int altera_jinit(struct altera_state *astate); | ||
| 85 | int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state); | ||
| 86 | int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state); | ||
| 87 | int altera_set_dr_pre(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 88 | u8 *preamble_data); | ||
| 89 | int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 90 | u8 *preamble_data); | ||
| 91 | int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 92 | u8 *postamble_data); | ||
| 93 | int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index, | ||
| 94 | u8 *postamble_data); | ||
| 95 | int altera_goto_jstate(struct altera_state *astate, | ||
| 96 | enum altera_jtag_state state); | ||
| 97 | int altera_wait_cycles(struct altera_state *astate, s32 cycles, | ||
| 98 | enum altera_jtag_state wait_state); | ||
| 99 | int altera_wait_msecs(struct altera_state *astate, s32 microseconds, | ||
| 100 | enum altera_jtag_state wait_state); | ||
| 101 | int altera_irscan(struct altera_state *astate, u32 count, | ||
| 102 | u8 *tdi_data, u32 start_index); | ||
| 103 | int altera_swap_ir(struct altera_state *astate, | ||
| 104 | u32 count, u8 *in_data, | ||
| 105 | u32 in_index, u8 *out_data, | ||
| 106 | u32 out_index); | ||
| 107 | int altera_drscan(struct altera_state *astate, u32 count, | ||
| 108 | u8 *tdi_data, u32 start_index); | ||
| 109 | int altera_swap_dr(struct altera_state *astate, u32 count, | ||
| 110 | u8 *in_data, u32 in_index, | ||
| 111 | u8 *out_data, u32 out_index); | ||
| 112 | void altera_free_buffers(struct altera_state *astate); | ||
| 113 | #endif /* ALTERA_JTAG_H */ | ||
diff --git a/drivers/misc/altera-stapl/altera-lpt.c b/drivers/misc/altera-stapl/altera-lpt.c new file mode 100644 index 000000000000..91456a03612d --- /dev/null +++ b/drivers/misc/altera-stapl/altera-lpt.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * altera-lpt.c | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010 NetUP Inc. | ||
| 8 | * Copyright (C) 2010 Abylay Ospan <aospan@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include "altera-exprt.h" | ||
| 29 | |||
| 30 | static int lpt_hardware_initialized; | ||
| 31 | |||
| 32 | static void byteblaster_write(int port, int data) | ||
| 33 | { | ||
| 34 | outb((u8)data, (u16)(port + 0x378)); | ||
| 35 | }; | ||
| 36 | |||
| 37 | static int byteblaster_read(int port) | ||
| 38 | { | ||
| 39 | int data = 0; | ||
| 40 | data = inb((u16)(port + 0x378)); | ||
| 41 | return data & 0xff; | ||
| 42 | }; | ||
| 43 | |||
| 44 | int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo) | ||
| 45 | { | ||
| 46 | int data = 0; | ||
| 47 | int tdo = 0; | ||
| 48 | int initial_lpt_ctrl = 0; | ||
| 49 | |||
| 50 | if (!lpt_hardware_initialized) { | ||
| 51 | initial_lpt_ctrl = byteblaster_read(2); | ||
| 52 | byteblaster_write(2, (initial_lpt_ctrl | 0x02) & 0xdf); | ||
| 53 | lpt_hardware_initialized = 1; | ||
| 54 | } | ||
| 55 | |||
| 56 | data = ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0)); | ||
| 57 | |||
| 58 | byteblaster_write(0, data); | ||
| 59 | |||
| 60 | if (read_tdo) { | ||
| 61 | tdo = byteblaster_read(1); | ||
| 62 | tdo = ((tdo & 0x80) ? 0 : 1); | ||
| 63 | } | ||
| 64 | |||
| 65 | byteblaster_write(0, data | 0x01); | ||
| 66 | |||
| 67 | byteblaster_write(0, data); | ||
| 68 | |||
| 69 | return tdo; | ||
| 70 | } | ||
diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c new file mode 100644 index 000000000000..24272e022bec --- /dev/null +++ b/drivers/misc/altera-stapl/altera.c | |||
| @@ -0,0 +1,2537 @@ | |||
| 1 | /* | ||
| 2 | * altera.c | ||
| 3 | * | ||
| 4 | * altera FPGA driver | ||
| 5 | * | ||
| 6 | * Copyright (C) Altera Corporation 1998-2001 | ||
| 7 | * Copyright (C) 2010,2011 NetUP Inc. | ||
| 8 | * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * | ||
| 19 | * GNU General Public License for more details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <asm/unaligned.h> | ||
| 27 | #include <linux/ctype.h> | ||
| 28 | #include <linux/string.h> | ||
| 29 | #include <linux/firmware.h> | ||
| 30 | #include <linux/slab.h> | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <misc/altera.h> | ||
| 33 | #include "altera-exprt.h" | ||
| 34 | #include "altera-jtag.h" | ||
| 35 | |||
| 36 | static int debug = 1; | ||
| 37 | module_param(debug, int, 0644); | ||
| 38 | MODULE_PARM_DESC(debug, "enable debugging information"); | ||
| 39 | |||
| 40 | MODULE_DESCRIPTION("altera FPGA kernel module"); | ||
| 41 | MODULE_AUTHOR("Igor M. Liplianin <liplianin@netup.ru>"); | ||
| 42 | MODULE_LICENSE("GPL"); | ||
| 43 | |||
| 44 | #define dprintk(args...) \ | ||
| 45 | if (debug) { \ | ||
| 46 | printk(KERN_DEBUG args); \ | ||
| 47 | } | ||
| 48 | |||
| 49 | enum altera_fpga_opcode { | ||
| 50 | OP_NOP = 0, | ||
| 51 | OP_DUP, | ||
| 52 | OP_SWP, | ||
| 53 | OP_ADD, | ||
| 54 | OP_SUB, | ||
| 55 | OP_MULT, | ||
| 56 | OP_DIV, | ||
| 57 | OP_MOD, | ||
| 58 | OP_SHL, | ||
| 59 | OP_SHR, | ||
| 60 | OP_NOT, | ||
| 61 | OP_AND, | ||
| 62 | OP_OR, | ||
| 63 | OP_XOR, | ||
| 64 | OP_INV, | ||
| 65 | OP_GT, | ||
| 66 | OP_LT, | ||
| 67 | OP_RET, | ||
| 68 | OP_CMPS, | ||
| 69 | OP_PINT, | ||
| 70 | OP_PRNT, | ||
| 71 | OP_DSS, | ||
| 72 | OP_DSSC, | ||
| 73 | OP_ISS, | ||
| 74 | OP_ISSC, | ||
| 75 | OP_DPR = 0x1c, | ||
| 76 | OP_DPRL, | ||
| 77 | OP_DPO, | ||
| 78 | OP_DPOL, | ||
| 79 | OP_IPR, | ||
| 80 | OP_IPRL, | ||
| 81 | OP_IPO, | ||
| 82 | OP_IPOL, | ||
| 83 | OP_PCHR, | ||
| 84 | OP_EXIT, | ||
| 85 | OP_EQU, | ||
| 86 | OP_POPT, | ||
| 87 | OP_ABS = 0x2c, | ||
| 88 | OP_BCH0, | ||
| 89 | OP_PSH0 = 0x2f, | ||
| 90 | OP_PSHL = 0x40, | ||
| 91 | OP_PSHV, | ||
| 92 | OP_JMP, | ||
| 93 | OP_CALL, | ||
| 94 | OP_NEXT, | ||
| 95 | OP_PSTR, | ||
| 96 | OP_SINT = 0x47, | ||
| 97 | OP_ST, | ||
| 98 | OP_ISTP, | ||
| 99 | OP_DSTP, | ||
| 100 | OP_SWPN, | ||
| 101 | OP_DUPN, | ||
| 102 | OP_POPV, | ||
| 103 | OP_POPE, | ||
| 104 | OP_POPA, | ||
| 105 | OP_JMPZ, | ||
| 106 | OP_DS, | ||
| 107 | OP_IS, | ||
| 108 | OP_DPRA, | ||
| 109 | OP_DPOA, | ||
| 110 | OP_IPRA, | ||
| 111 | OP_IPOA, | ||
| 112 | OP_EXPT, | ||
| 113 | OP_PSHE, | ||
| 114 | OP_PSHA, | ||
| 115 | OP_DYNA, | ||
| 116 | OP_EXPV = 0x5c, | ||
| 117 | OP_COPY = 0x80, | ||
| 118 | OP_REVA, | ||
| 119 | OP_DSC, | ||
| 120 | OP_ISC, | ||
| 121 | OP_WAIT, | ||
| 122 | OP_VS, | ||
| 123 | OP_CMPA = 0xc0, | ||
| 124 | OP_VSC, | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct altera_procinfo { | ||
| 128 | char *name; | ||
| 129 | u8 attrs; | ||
| 130 | struct altera_procinfo *next; | ||
| 131 | }; | ||
| 132 | |||
| 133 | /* This function checks if enough parameters are available on the stack. */ | ||
| 134 | static int altera_check_stack(int stack_ptr, int count, int *status) | ||
| 135 | { | ||
| 136 | if (stack_ptr < count) { | ||
| 137 | *status = -EOVERFLOW; | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | return 1; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void altera_export_int(char *key, s32 value) | ||
| 145 | { | ||
| 146 | dprintk("Export: key = \"%s\", value = %d\n", key, value); | ||
| 147 | } | ||
| 148 | |||
| 149 | #define HEX_LINE_CHARS 72 | ||
| 150 | #define HEX_LINE_BITS (HEX_LINE_CHARS * 4) | ||
| 151 | |||
| 152 | static void altera_export_bool_array(char *key, u8 *data, s32 count) | ||
| 153 | { | ||
| 154 | char string[HEX_LINE_CHARS + 1]; | ||
| 155 | s32 i, offset; | ||
| 156 | u32 size, line, lines, linebits, value, j, k; | ||
| 157 | |||
| 158 | if (count > HEX_LINE_BITS) { | ||
| 159 | dprintk("Export: key = \"%s\", %d bits, value = HEX\n", | ||
| 160 | key, count); | ||
| 161 | lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS; | ||
| 162 | |||
| 163 | for (line = 0; line < lines; ++line) { | ||
| 164 | if (line < (lines - 1)) { | ||
| 165 | linebits = HEX_LINE_BITS; | ||
| 166 | size = HEX_LINE_CHARS; | ||
| 167 | offset = count - ((line + 1) * HEX_LINE_BITS); | ||
| 168 | } else { | ||
| 169 | linebits = | ||
| 170 | count - ((lines - 1) * HEX_LINE_BITS); | ||
| 171 | size = (linebits + 3) / 4; | ||
| 172 | offset = 0L; | ||
| 173 | } | ||
| 174 | |||
| 175 | string[size] = '\0'; | ||
| 176 | j = size - 1; | ||
| 177 | value = 0; | ||
| 178 | |||
| 179 | for (k = 0; k < linebits; ++k) { | ||
| 180 | i = k + offset; | ||
| 181 | if (data[i >> 3] & (1 << (i & 7))) | ||
| 182 | value |= (1 << (i & 3)); | ||
| 183 | if ((i & 3) == 3) { | ||
| 184 | sprintf(&string[j], "%1x", value); | ||
| 185 | value = 0; | ||
| 186 | --j; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | if ((k & 3) > 0) | ||
| 190 | sprintf(&string[j], "%1x", value); | ||
| 191 | |||
| 192 | dprintk("%s\n", string); | ||
| 193 | } | ||
| 194 | |||
| 195 | } else { | ||
| 196 | size = (count + 3) / 4; | ||
| 197 | string[size] = '\0'; | ||
| 198 | j = size - 1; | ||
| 199 | value = 0; | ||
| 200 | |||
| 201 | for (i = 0; i < count; ++i) { | ||
| 202 | if (data[i >> 3] & (1 << (i & 7))) | ||
| 203 | value |= (1 << (i & 3)); | ||
| 204 | if ((i & 3) == 3) { | ||
| 205 | sprintf(&string[j], "%1x", value); | ||
| 206 | value = 0; | ||
| 207 | --j; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | if ((i & 3) > 0) | ||
| 211 | sprintf(&string[j], "%1x", value); | ||
| 212 | |||
| 213 | dprintk("Export: key = \"%s\", %d bits, value = HEX %s\n", | ||
| 214 | key, count, string); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | static int altera_execute(struct altera_state *astate, | ||
| 219 | u8 *p, | ||
| 220 | s32 program_size, | ||
| 221 | s32 *error_address, | ||
| 222 | int *exit_code, | ||
| 223 | int *format_version) | ||
| 224 | { | ||
| 225 | struct altera_config *aconf = astate->config; | ||
| 226 | char *msg_buff = astate->msg_buff; | ||
| 227 | long *stack = astate->stack; | ||
| 228 | int status = 0; | ||
| 229 | u32 first_word = 0L; | ||
| 230 | u32 action_table = 0L; | ||
| 231 | u32 proc_table = 0L; | ||
| 232 | u32 str_table = 0L; | ||
| 233 | u32 sym_table = 0L; | ||
| 234 | u32 data_sect = 0L; | ||
| 235 | u32 code_sect = 0L; | ||
| 236 | u32 debug_sect = 0L; | ||
| 237 | u32 action_count = 0L; | ||
| 238 | u32 proc_count = 0L; | ||
| 239 | u32 sym_count = 0L; | ||
| 240 | long *vars = NULL; | ||
| 241 | s32 *var_size = NULL; | ||
| 242 | char *attrs = NULL; | ||
| 243 | u8 *proc_attributes = NULL; | ||
| 244 | u32 pc; | ||
| 245 | u32 opcode_address; | ||
| 246 | u32 args[3]; | ||
| 247 | u32 opcode; | ||
| 248 | u32 name_id; | ||
| 249 | u8 charbuf[4]; | ||
| 250 | long long_tmp; | ||
| 251 | u32 variable_id; | ||
| 252 | u8 *charptr_tmp; | ||
| 253 | u8 *charptr_tmp2; | ||
| 254 | long *longptr_tmp; | ||
| 255 | int version = 0; | ||
| 256 | int delta = 0; | ||
| 257 | int stack_ptr = 0; | ||
| 258 | u32 arg_count; | ||
| 259 | int done = 0; | ||
| 260 | int bad_opcode = 0; | ||
| 261 | u32 count; | ||
| 262 | u32 index; | ||
| 263 | u32 index2; | ||
| 264 | s32 long_count; | ||
| 265 | s32 long_idx; | ||
| 266 | s32 long_idx2; | ||
| 267 | u32 i; | ||
| 268 | u32 j; | ||
| 269 | u32 uncomp_size; | ||
| 270 | u32 offset; | ||
| 271 | u32 value; | ||
| 272 | int current_proc = 0; | ||
| 273 | int reverse; | ||
| 274 | |||
| 275 | char *name; | ||
| 276 | |||
| 277 | dprintk("%s\n", __func__); | ||
| 278 | |||
| 279 | /* Read header information */ | ||
| 280 | if (program_size > 52L) { | ||
| 281 | first_word = get_unaligned_be32(&p[0]); | ||
| 282 | version = (first_word & 1L); | ||
| 283 | *format_version = version + 1; | ||
| 284 | delta = version * 8; | ||
| 285 | |||
| 286 | action_table = get_unaligned_be32(&p[4]); | ||
| 287 | proc_table = get_unaligned_be32(&p[8]); | ||
| 288 | str_table = get_unaligned_be32(&p[4 + delta]); | ||
| 289 | sym_table = get_unaligned_be32(&p[16 + delta]); | ||
| 290 | data_sect = get_unaligned_be32(&p[20 + delta]); | ||
| 291 | code_sect = get_unaligned_be32(&p[24 + delta]); | ||
| 292 | debug_sect = get_unaligned_be32(&p[28 + delta]); | ||
| 293 | action_count = get_unaligned_be32(&p[40 + delta]); | ||
| 294 | proc_count = get_unaligned_be32(&p[44 + delta]); | ||
| 295 | sym_count = get_unaligned_be32(&p[48 + (2 * delta)]); | ||
| 296 | } | ||
| 297 | |||
| 298 | if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) { | ||
| 299 | done = 1; | ||
| 300 | status = -EIO; | ||
| 301 | goto exit_done; | ||
| 302 | } | ||
| 303 | |||
| 304 | if (sym_count <= 0) | ||
| 305 | goto exit_done; | ||
| 306 | |||
| 307 | vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL); | ||
| 308 | |||
| 309 | if (vars == NULL) | ||
| 310 | status = -ENOMEM; | ||
| 311 | |||
| 312 | if (status == 0) { | ||
| 313 | var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL); | ||
| 314 | |||
| 315 | if (var_size == NULL) | ||
| 316 | status = -ENOMEM; | ||
| 317 | } | ||
| 318 | |||
| 319 | if (status == 0) { | ||
| 320 | attrs = kzalloc(sym_count, GFP_KERNEL); | ||
| 321 | |||
| 322 | if (attrs == NULL) | ||
| 323 | status = -ENOMEM; | ||
| 324 | } | ||
| 325 | |||
| 326 | if ((status == 0) && (version > 0)) { | ||
| 327 | proc_attributes = kzalloc(proc_count, GFP_KERNEL); | ||
| 328 | |||
| 329 | if (proc_attributes == NULL) | ||
| 330 | status = -ENOMEM; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (status != 0) | ||
| 334 | goto exit_done; | ||
| 335 | |||
| 336 | delta = version * 2; | ||
| 337 | |||
| 338 | for (i = 0; i < sym_count; ++i) { | ||
| 339 | offset = (sym_table + ((11 + delta) * i)); | ||
| 340 | |||
| 341 | value = get_unaligned_be32(&p[offset + 3 + delta]); | ||
| 342 | |||
| 343 | attrs[i] = p[offset]; | ||
| 344 | |||
| 345 | /* | ||
| 346 | * use bit 7 of attribute byte to indicate that | ||
| 347 | * this buffer was dynamically allocated | ||
| 348 | * and should be freed later | ||
| 349 | */ | ||
| 350 | attrs[i] &= 0x7f; | ||
| 351 | |||
| 352 | var_size[i] = get_unaligned_be32(&p[offset + 7 + delta]); | ||
| 353 | |||
| 354 | /* | ||
| 355 | * Attribute bits: | ||
| 356 | * bit 0: 0 = read-only, 1 = read-write | ||
| 357 | * bit 1: 0 = not compressed, 1 = compressed | ||
| 358 | * bit 2: 0 = not initialized, 1 = initialized | ||
| 359 | * bit 3: 0 = scalar, 1 = array | ||
| 360 | * bit 4: 0 = Boolean, 1 = integer | ||
| 361 | * bit 5: 0 = declared variable, | ||
| 362 | * 1 = compiler created temporary variable | ||
| 363 | */ | ||
| 364 | |||
| 365 | if ((attrs[i] & 0x0c) == 0x04) | ||
| 366 | /* initialized scalar variable */ | ||
| 367 | vars[i] = value; | ||
| 368 | else if ((attrs[i] & 0x1e) == 0x0e) { | ||
| 369 | /* initialized compressed Boolean array */ | ||
| 370 | uncomp_size = get_unaligned_le32(&p[data_sect + value]); | ||
| 371 | |||
| 372 | /* allocate a buffer for the uncompressed data */ | ||
| 373 | vars[i] = (long)kzalloc(uncomp_size, GFP_KERNEL); | ||
| 374 | if (vars[i] == 0L) | ||
| 375 | status = -ENOMEM; | ||
| 376 | else { | ||
| 377 | /* set flag so buffer will be freed later */ | ||
| 378 | attrs[i] |= 0x80; | ||
| 379 | |||
| 380 | /* uncompress the data */ | ||
| 381 | if (altera_shrink(&p[data_sect + value], | ||
| 382 | var_size[i], | ||
| 383 | (u8 *)vars[i], | ||
| 384 | uncomp_size, | ||
| 385 | version) != uncomp_size) | ||
| 386 | /* decompression failed */ | ||
| 387 | status = -EIO; | ||
| 388 | else | ||
| 389 | var_size[i] = uncomp_size * 8L; | ||
| 390 | |||
| 391 | } | ||
| 392 | } else if ((attrs[i] & 0x1e) == 0x0c) { | ||
| 393 | /* initialized Boolean array */ | ||
| 394 | vars[i] = value + data_sect + (long)p; | ||
| 395 | } else if ((attrs[i] & 0x1c) == 0x1c) { | ||
| 396 | /* initialized integer array */ | ||
| 397 | vars[i] = value + data_sect; | ||
| 398 | } else if ((attrs[i] & 0x0c) == 0x08) { | ||
| 399 | /* uninitialized array */ | ||
| 400 | |||
| 401 | /* flag attrs so that memory is freed */ | ||
| 402 | attrs[i] |= 0x80; | ||
| 403 | |||
| 404 | if (var_size[i] > 0) { | ||
| 405 | u32 size; | ||
| 406 | |||
| 407 | if (attrs[i] & 0x10) | ||
| 408 | /* integer array */ | ||
| 409 | size = (var_size[i] * sizeof(s32)); | ||
| 410 | else | ||
| 411 | /* Boolean array */ | ||
| 412 | size = ((var_size[i] + 7L) / 8L); | ||
| 413 | |||
| 414 | vars[i] = (long)kzalloc(size, GFP_KERNEL); | ||
| 415 | |||
| 416 | if (vars[i] == 0) { | ||
| 417 | status = -ENOMEM; | ||
| 418 | } else { | ||
| 419 | /* zero out memory */ | ||
| 420 | for (j = 0; j < size; ++j) | ||
| 421 | ((u8 *)(vars[i]))[j] = 0; | ||
| 422 | |||
| 423 | } | ||
| 424 | } else | ||
| 425 | vars[i] = 0; | ||
| 426 | |||
| 427 | } else | ||
| 428 | vars[i] = 0; | ||
| 429 | |||
| 430 | } | ||
| 431 | |||
| 432 | exit_done: | ||
| 433 | if (status != 0) | ||
| 434 | done = 1; | ||
| 435 | |||
| 436 | altera_jinit(astate); | ||
| 437 | |||
| 438 | pc = code_sect; | ||
| 439 | msg_buff[0] = '\0'; | ||
| 440 | |||
| 441 | /* | ||
| 442 | * For JBC version 2, we will execute the procedures corresponding to | ||
| 443 | * the selected ACTION | ||
| 444 | */ | ||
| 445 | if (version > 0) { | ||
| 446 | if (aconf->action == NULL) { | ||
| 447 | status = -EINVAL; | ||
| 448 | done = 1; | ||
| 449 | } else { | ||
| 450 | int action_found = 0; | ||
| 451 | for (i = 0; (i < action_count) && !action_found; ++i) { | ||
| 452 | name_id = get_unaligned_be32(&p[action_table + | ||
| 453 | (12 * i)]); | ||
| 454 | |||
| 455 | name = &p[str_table + name_id]; | ||
| 456 | |||
| 457 | if (strnicmp(aconf->action, name, strlen(name)) == 0) { | ||
| 458 | action_found = 1; | ||
| 459 | current_proc = | ||
| 460 | get_unaligned_be32(&p[action_table + | ||
| 461 | (12 * i) + 8]); | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | if (!action_found) { | ||
| 466 | status = -EINVAL; | ||
| 467 | done = 1; | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | if (status == 0) { | ||
| 472 | int first_time = 1; | ||
| 473 | i = current_proc; | ||
| 474 | while ((i != 0) || first_time) { | ||
| 475 | first_time = 0; | ||
| 476 | /* check procedure attribute byte */ | ||
| 477 | proc_attributes[i] = | ||
| 478 | (p[proc_table + | ||
| 479 | (13 * i) + 8] & | ||
| 480 | 0x03); | ||
| 481 | |||
| 482 | /* | ||
| 483 | * BIT0 - OPTIONAL | ||
| 484 | * BIT1 - RECOMMENDED | ||
| 485 | * BIT6 - FORCED OFF | ||
| 486 | * BIT7 - FORCED ON | ||
| 487 | */ | ||
| 488 | |||
| 489 | i = get_unaligned_be32(&p[proc_table + | ||
| 490 | (13 * i) + 4]); | ||
| 491 | } | ||
| 492 | |||
| 493 | /* | ||
| 494 | * Set current_proc to the first procedure | ||
| 495 | * to be executed | ||
| 496 | */ | ||
| 497 | i = current_proc; | ||
| 498 | while ((i != 0) && | ||
| 499 | ((proc_attributes[i] == 1) || | ||
| 500 | ((proc_attributes[i] & 0xc0) == 0x40))) { | ||
| 501 | i = get_unaligned_be32(&p[proc_table + | ||
| 502 | (13 * i) + 4]); | ||
| 503 | } | ||
| 504 | |||
| 505 | if ((i != 0) || ((i == 0) && (current_proc == 0) && | ||
| 506 | ((proc_attributes[0] != 1) && | ||
| 507 | ((proc_attributes[0] & 0xc0) != 0x40)))) { | ||
| 508 | current_proc = i; | ||
| 509 | pc = code_sect + | ||
| 510 | get_unaligned_be32(&p[proc_table + | ||
| 511 | (13 * i) + 9]); | ||
| 512 | if ((pc < code_sect) || (pc >= debug_sect)) | ||
| 513 | status = -ERANGE; | ||
| 514 | } else | ||
| 515 | /* there are no procedures to execute! */ | ||
| 516 | done = 1; | ||
| 517 | |||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | msg_buff[0] = '\0'; | ||
| 522 | |||
| 523 | while (!done) { | ||
| 524 | opcode = (p[pc] & 0xff); | ||
| 525 | opcode_address = pc; | ||
| 526 | ++pc; | ||
| 527 | |||
| 528 | if (debug > 1) | ||
| 529 | printk("opcode: %02x\n", opcode); | ||
| 530 | |||
| 531 | arg_count = (opcode >> 6) & 3; | ||
| 532 | for (i = 0; i < arg_count; ++i) { | ||
| 533 | args[i] = get_unaligned_be32(&p[pc]); | ||
| 534 | pc += 4; | ||
| 535 | } | ||
| 536 | |||
| 537 | switch (opcode) { | ||
| 538 | case OP_NOP: | ||
| 539 | break; | ||
| 540 | case OP_DUP: | ||
| 541 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 542 | stack[stack_ptr] = stack[stack_ptr - 1]; | ||
| 543 | ++stack_ptr; | ||
| 544 | } | ||
| 545 | break; | ||
| 546 | case OP_SWP: | ||
| 547 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 548 | long_tmp = stack[stack_ptr - 2]; | ||
| 549 | stack[stack_ptr - 2] = stack[stack_ptr - 1]; | ||
| 550 | stack[stack_ptr - 1] = long_tmp; | ||
| 551 | } | ||
| 552 | break; | ||
| 553 | case OP_ADD: | ||
| 554 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 555 | --stack_ptr; | ||
| 556 | stack[stack_ptr - 1] += stack[stack_ptr]; | ||
| 557 | } | ||
| 558 | break; | ||
| 559 | case OP_SUB: | ||
| 560 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 561 | --stack_ptr; | ||
| 562 | stack[stack_ptr - 1] -= stack[stack_ptr]; | ||
| 563 | } | ||
| 564 | break; | ||
| 565 | case OP_MULT: | ||
| 566 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 567 | --stack_ptr; | ||
| 568 | stack[stack_ptr - 1] *= stack[stack_ptr]; | ||
| 569 | } | ||
| 570 | break; | ||
| 571 | case OP_DIV: | ||
| 572 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 573 | --stack_ptr; | ||
| 574 | stack[stack_ptr - 1] /= stack[stack_ptr]; | ||
| 575 | } | ||
| 576 | break; | ||
| 577 | case OP_MOD: | ||
| 578 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 579 | --stack_ptr; | ||
| 580 | stack[stack_ptr - 1] %= stack[stack_ptr]; | ||
| 581 | } | ||
| 582 | break; | ||
| 583 | case OP_SHL: | ||
| 584 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 585 | --stack_ptr; | ||
| 586 | stack[stack_ptr - 1] <<= stack[stack_ptr]; | ||
| 587 | } | ||
| 588 | break; | ||
| 589 | case OP_SHR: | ||
| 590 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 591 | --stack_ptr; | ||
| 592 | stack[stack_ptr - 1] >>= stack[stack_ptr]; | ||
| 593 | } | ||
| 594 | break; | ||
| 595 | case OP_NOT: | ||
| 596 | if (altera_check_stack(stack_ptr, 1, &status)) | ||
| 597 | stack[stack_ptr - 1] ^= (-1L); | ||
| 598 | |||
| 599 | break; | ||
| 600 | case OP_AND: | ||
| 601 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 602 | --stack_ptr; | ||
| 603 | stack[stack_ptr - 1] &= stack[stack_ptr]; | ||
| 604 | } | ||
| 605 | break; | ||
| 606 | case OP_OR: | ||
| 607 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 608 | --stack_ptr; | ||
| 609 | stack[stack_ptr - 1] |= stack[stack_ptr]; | ||
| 610 | } | ||
| 611 | break; | ||
| 612 | case OP_XOR: | ||
| 613 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 614 | --stack_ptr; | ||
| 615 | stack[stack_ptr - 1] ^= stack[stack_ptr]; | ||
| 616 | } | ||
| 617 | break; | ||
| 618 | case OP_INV: | ||
| 619 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 620 | break; | ||
| 621 | stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L; | ||
| 622 | break; | ||
| 623 | case OP_GT: | ||
| 624 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 625 | break; | ||
| 626 | --stack_ptr; | ||
| 627 | stack[stack_ptr - 1] = | ||
| 628 | (stack[stack_ptr - 1] > stack[stack_ptr]) ? | ||
| 629 | 1L : 0L; | ||
| 630 | |||
| 631 | break; | ||
| 632 | case OP_LT: | ||
| 633 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 634 | break; | ||
| 635 | --stack_ptr; | ||
| 636 | stack[stack_ptr - 1] = | ||
| 637 | (stack[stack_ptr - 1] < stack[stack_ptr]) ? | ||
| 638 | 1L : 0L; | ||
| 639 | |||
| 640 | break; | ||
| 641 | case OP_RET: | ||
| 642 | if ((version > 0) && (stack_ptr == 0)) { | ||
| 643 | /* | ||
| 644 | * We completed one of the main procedures | ||
| 645 | * of an ACTION. | ||
| 646 | * Find the next procedure | ||
| 647 | * to be executed and jump to it. | ||
| 648 | * If there are no more procedures, then EXIT. | ||
| 649 | */ | ||
| 650 | i = get_unaligned_be32(&p[proc_table + | ||
| 651 | (13 * current_proc) + 4]); | ||
| 652 | while ((i != 0) && | ||
| 653 | ((proc_attributes[i] == 1) || | ||
| 654 | ((proc_attributes[i] & 0xc0) == 0x40))) | ||
| 655 | i = get_unaligned_be32(&p[proc_table + | ||
| 656 | (13 * i) + 4]); | ||
| 657 | |||
| 658 | if (i == 0) { | ||
| 659 | /* no procedures to execute! */ | ||
| 660 | done = 1; | ||
| 661 | *exit_code = 0; /* success */ | ||
| 662 | } else { | ||
| 663 | current_proc = i; | ||
| 664 | pc = code_sect + get_unaligned_be32( | ||
| 665 | &p[proc_table + | ||
| 666 | (13 * i) + 9]); | ||
| 667 | if ((pc < code_sect) || | ||
| 668 | (pc >= debug_sect)) | ||
| 669 | status = -ERANGE; | ||
| 670 | } | ||
| 671 | |||
| 672 | } else | ||
| 673 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 674 | pc = stack[--stack_ptr] + code_sect; | ||
| 675 | if ((pc <= code_sect) || | ||
| 676 | (pc >= debug_sect)) | ||
| 677 | status = -ERANGE; | ||
| 678 | |||
| 679 | } | ||
| 680 | |||
| 681 | break; | ||
| 682 | case OP_CMPS: | ||
| 683 | /* | ||
| 684 | * Array short compare | ||
| 685 | * ...stack 0 is source 1 value | ||
| 686 | * ...stack 1 is source 2 value | ||
| 687 | * ...stack 2 is mask value | ||
| 688 | * ...stack 3 is count | ||
| 689 | */ | ||
| 690 | if (altera_check_stack(stack_ptr, 4, &status)) { | ||
| 691 | s32 a = stack[--stack_ptr]; | ||
| 692 | s32 b = stack[--stack_ptr]; | ||
| 693 | long_tmp = stack[--stack_ptr]; | ||
| 694 | count = stack[stack_ptr - 1]; | ||
| 695 | |||
| 696 | if ((count < 1) || (count > 32)) | ||
| 697 | status = -ERANGE; | ||
| 698 | else { | ||
| 699 | long_tmp &= ((-1L) >> (32 - count)); | ||
| 700 | |||
| 701 | stack[stack_ptr - 1] = | ||
| 702 | ((a & long_tmp) == (b & long_tmp)) | ||
| 703 | ? 1L : 0L; | ||
| 704 | } | ||
| 705 | } | ||
| 706 | break; | ||
| 707 | case OP_PINT: | ||
| 708 | /* | ||
| 709 | * PRINT add integer | ||
| 710 | * ...stack 0 is integer value | ||
| 711 | */ | ||
| 712 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 713 | break; | ||
| 714 | sprintf(&msg_buff[strlen(msg_buff)], | ||
| 715 | "%ld", stack[--stack_ptr]); | ||
| 716 | break; | ||
| 717 | case OP_PRNT: | ||
| 718 | /* PRINT finish */ | ||
| 719 | if (debug) | ||
| 720 | printk(msg_buff, "\n"); | ||
| 721 | |||
| 722 | msg_buff[0] = '\0'; | ||
| 723 | break; | ||
| 724 | case OP_DSS: | ||
| 725 | /* | ||
| 726 | * DRSCAN short | ||
| 727 | * ...stack 0 is scan data | ||
| 728 | * ...stack 1 is count | ||
| 729 | */ | ||
| 730 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 731 | break; | ||
| 732 | long_tmp = stack[--stack_ptr]; | ||
| 733 | count = stack[--stack_ptr]; | ||
| 734 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 735 | status = altera_drscan(astate, count, charbuf, 0); | ||
| 736 | break; | ||
| 737 | case OP_DSSC: | ||
| 738 | /* | ||
| 739 | * DRSCAN short with capture | ||
| 740 | * ...stack 0 is scan data | ||
| 741 | * ...stack 1 is count | ||
| 742 | */ | ||
| 743 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 744 | break; | ||
| 745 | long_tmp = stack[--stack_ptr]; | ||
| 746 | count = stack[stack_ptr - 1]; | ||
| 747 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 748 | status = altera_swap_dr(astate, count, charbuf, | ||
| 749 | 0, charbuf, 0); | ||
| 750 | stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); | ||
| 751 | break; | ||
| 752 | case OP_ISS: | ||
| 753 | /* | ||
| 754 | * IRSCAN short | ||
| 755 | * ...stack 0 is scan data | ||
| 756 | * ...stack 1 is count | ||
| 757 | */ | ||
| 758 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 759 | break; | ||
| 760 | long_tmp = stack[--stack_ptr]; | ||
| 761 | count = stack[--stack_ptr]; | ||
| 762 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 763 | status = altera_irscan(astate, count, charbuf, 0); | ||
| 764 | break; | ||
| 765 | case OP_ISSC: | ||
| 766 | /* | ||
| 767 | * IRSCAN short with capture | ||
| 768 | * ...stack 0 is scan data | ||
| 769 | * ...stack 1 is count | ||
| 770 | */ | ||
| 771 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 772 | break; | ||
| 773 | long_tmp = stack[--stack_ptr]; | ||
| 774 | count = stack[stack_ptr - 1]; | ||
| 775 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 776 | status = altera_swap_ir(astate, count, charbuf, | ||
| 777 | 0, charbuf, 0); | ||
| 778 | stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]); | ||
| 779 | break; | ||
| 780 | case OP_DPR: | ||
| 781 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 782 | break; | ||
| 783 | count = stack[--stack_ptr]; | ||
| 784 | status = altera_set_dr_pre(&astate->js, count, 0, NULL); | ||
| 785 | break; | ||
| 786 | case OP_DPRL: | ||
| 787 | /* | ||
| 788 | * DRPRE with literal data | ||
| 789 | * ...stack 0 is count | ||
| 790 | * ...stack 1 is literal data | ||
| 791 | */ | ||
| 792 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 793 | break; | ||
| 794 | count = stack[--stack_ptr]; | ||
| 795 | long_tmp = stack[--stack_ptr]; | ||
| 796 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 797 | status = altera_set_dr_pre(&astate->js, count, 0, | ||
| 798 | charbuf); | ||
| 799 | break; | ||
| 800 | case OP_DPO: | ||
| 801 | /* | ||
| 802 | * DRPOST | ||
| 803 | * ...stack 0 is count | ||
| 804 | */ | ||
| 805 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 806 | count = stack[--stack_ptr]; | ||
| 807 | status = altera_set_dr_post(&astate->js, count, | ||
| 808 | 0, NULL); | ||
| 809 | } | ||
| 810 | break; | ||
| 811 | case OP_DPOL: | ||
| 812 | /* | ||
| 813 | * DRPOST with literal data | ||
| 814 | * ...stack 0 is count | ||
| 815 | * ...stack 1 is literal data | ||
| 816 | */ | ||
| 817 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 818 | break; | ||
| 819 | count = stack[--stack_ptr]; | ||
| 820 | long_tmp = stack[--stack_ptr]; | ||
| 821 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 822 | status = altera_set_dr_post(&astate->js, count, 0, | ||
| 823 | charbuf); | ||
| 824 | break; | ||
| 825 | case OP_IPR: | ||
| 826 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 827 | count = stack[--stack_ptr]; | ||
| 828 | status = altera_set_ir_pre(&astate->js, count, | ||
| 829 | 0, NULL); | ||
| 830 | } | ||
| 831 | break; | ||
| 832 | case OP_IPRL: | ||
| 833 | /* | ||
| 834 | * IRPRE with literal data | ||
| 835 | * ...stack 0 is count | ||
| 836 | * ...stack 1 is literal data | ||
| 837 | */ | ||
| 838 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 839 | count = stack[--stack_ptr]; | ||
| 840 | long_tmp = stack[--stack_ptr]; | ||
| 841 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 842 | status = altera_set_ir_pre(&astate->js, count, | ||
| 843 | 0, charbuf); | ||
| 844 | } | ||
| 845 | break; | ||
| 846 | case OP_IPO: | ||
| 847 | /* | ||
| 848 | * IRPOST | ||
| 849 | * ...stack 0 is count | ||
| 850 | */ | ||
| 851 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 852 | count = stack[--stack_ptr]; | ||
| 853 | status = altera_set_ir_post(&astate->js, count, | ||
| 854 | 0, NULL); | ||
| 855 | } | ||
| 856 | break; | ||
| 857 | case OP_IPOL: | ||
| 858 | /* | ||
| 859 | * IRPOST with literal data | ||
| 860 | * ...stack 0 is count | ||
| 861 | * ...stack 1 is literal data | ||
| 862 | */ | ||
| 863 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 864 | break; | ||
| 865 | count = stack[--stack_ptr]; | ||
| 866 | long_tmp = stack[--stack_ptr]; | ||
| 867 | put_unaligned_le32(long_tmp, &charbuf[0]); | ||
| 868 | status = altera_set_ir_post(&astate->js, count, 0, | ||
| 869 | charbuf); | ||
| 870 | break; | ||
| 871 | case OP_PCHR: | ||
| 872 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 873 | u8 ch; | ||
| 874 | count = strlen(msg_buff); | ||
| 875 | ch = (char) stack[--stack_ptr]; | ||
| 876 | if ((ch < 1) || (ch > 127)) { | ||
| 877 | /* | ||
| 878 | * character code out of range | ||
| 879 | * instead of flagging an error, | ||
| 880 | * force the value to 127 | ||
| 881 | */ | ||
| 882 | ch = 127; | ||
| 883 | } | ||
| 884 | msg_buff[count] = ch; | ||
| 885 | msg_buff[count + 1] = '\0'; | ||
| 886 | } | ||
| 887 | break; | ||
| 888 | case OP_EXIT: | ||
| 889 | if (altera_check_stack(stack_ptr, 1, &status)) | ||
| 890 | *exit_code = stack[--stack_ptr]; | ||
| 891 | |||
| 892 | done = 1; | ||
| 893 | break; | ||
| 894 | case OP_EQU: | ||
| 895 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 896 | break; | ||
| 897 | --stack_ptr; | ||
| 898 | stack[stack_ptr - 1] = | ||
| 899 | (stack[stack_ptr - 1] == stack[stack_ptr]) ? | ||
| 900 | 1L : 0L; | ||
| 901 | break; | ||
| 902 | case OP_POPT: | ||
| 903 | if (altera_check_stack(stack_ptr, 1, &status)) | ||
| 904 | --stack_ptr; | ||
| 905 | |||
| 906 | break; | ||
| 907 | case OP_ABS: | ||
| 908 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 909 | break; | ||
| 910 | if (stack[stack_ptr - 1] < 0) | ||
| 911 | stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1]; | ||
| 912 | |||
| 913 | break; | ||
| 914 | case OP_BCH0: | ||
| 915 | /* | ||
| 916 | * Batch operation 0 | ||
| 917 | * SWP | ||
| 918 | * SWPN 7 | ||
| 919 | * SWP | ||
| 920 | * SWPN 6 | ||
| 921 | * DUPN 8 | ||
| 922 | * SWPN 2 | ||
| 923 | * SWP | ||
| 924 | * DUPN 6 | ||
| 925 | * DUPN 6 | ||
| 926 | */ | ||
| 927 | |||
| 928 | /* SWP */ | ||
| 929 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 930 | long_tmp = stack[stack_ptr - 2]; | ||
| 931 | stack[stack_ptr - 2] = stack[stack_ptr - 1]; | ||
| 932 | stack[stack_ptr - 1] = long_tmp; | ||
| 933 | } | ||
| 934 | |||
| 935 | /* SWPN 7 */ | ||
| 936 | index = 7 + 1; | ||
| 937 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 938 | long_tmp = stack[stack_ptr - index]; | ||
| 939 | stack[stack_ptr - index] = stack[stack_ptr - 1]; | ||
| 940 | stack[stack_ptr - 1] = long_tmp; | ||
| 941 | } | ||
| 942 | |||
| 943 | /* SWP */ | ||
| 944 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 945 | long_tmp = stack[stack_ptr - 2]; | ||
| 946 | stack[stack_ptr - 2] = stack[stack_ptr - 1]; | ||
| 947 | stack[stack_ptr - 1] = long_tmp; | ||
| 948 | } | ||
| 949 | |||
| 950 | /* SWPN 6 */ | ||
| 951 | index = 6 + 1; | ||
| 952 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 953 | long_tmp = stack[stack_ptr - index]; | ||
| 954 | stack[stack_ptr - index] = stack[stack_ptr - 1]; | ||
| 955 | stack[stack_ptr - 1] = long_tmp; | ||
| 956 | } | ||
| 957 | |||
| 958 | /* DUPN 8 */ | ||
| 959 | index = 8 + 1; | ||
| 960 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 961 | stack[stack_ptr] = stack[stack_ptr - index]; | ||
| 962 | ++stack_ptr; | ||
| 963 | } | ||
| 964 | |||
| 965 | /* SWPN 2 */ | ||
| 966 | index = 2 + 1; | ||
| 967 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 968 | long_tmp = stack[stack_ptr - index]; | ||
| 969 | stack[stack_ptr - index] = stack[stack_ptr - 1]; | ||
| 970 | stack[stack_ptr - 1] = long_tmp; | ||
| 971 | } | ||
| 972 | |||
| 973 | /* SWP */ | ||
| 974 | if (altera_check_stack(stack_ptr, 2, &status)) { | ||
| 975 | long_tmp = stack[stack_ptr - 2]; | ||
| 976 | stack[stack_ptr - 2] = stack[stack_ptr - 1]; | ||
| 977 | stack[stack_ptr - 1] = long_tmp; | ||
| 978 | } | ||
| 979 | |||
| 980 | /* DUPN 6 */ | ||
| 981 | index = 6 + 1; | ||
| 982 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 983 | stack[stack_ptr] = stack[stack_ptr - index]; | ||
| 984 | ++stack_ptr; | ||
| 985 | } | ||
| 986 | |||
| 987 | /* DUPN 6 */ | ||
| 988 | index = 6 + 1; | ||
| 989 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 990 | stack[stack_ptr] = stack[stack_ptr - index]; | ||
| 991 | ++stack_ptr; | ||
| 992 | } | ||
| 993 | break; | ||
| 994 | case OP_PSH0: | ||
| 995 | stack[stack_ptr++] = 0; | ||
| 996 | break; | ||
| 997 | case OP_PSHL: | ||
| 998 | stack[stack_ptr++] = (s32) args[0]; | ||
| 999 | break; | ||
| 1000 | case OP_PSHV: | ||
| 1001 | stack[stack_ptr++] = vars[args[0]]; | ||
| 1002 | break; | ||
| 1003 | case OP_JMP: | ||
| 1004 | pc = args[0] + code_sect; | ||
| 1005 | if ((pc < code_sect) || (pc >= debug_sect)) | ||
| 1006 | status = -ERANGE; | ||
| 1007 | break; | ||
| 1008 | case OP_CALL: | ||
| 1009 | stack[stack_ptr++] = pc; | ||
| 1010 | pc = args[0] + code_sect; | ||
| 1011 | if ((pc < code_sect) || (pc >= debug_sect)) | ||
| 1012 | status = -ERANGE; | ||
| 1013 | break; | ||
| 1014 | case OP_NEXT: | ||
| 1015 | /* | ||
| 1016 | * Process FOR / NEXT loop | ||
| 1017 | * ...argument 0 is variable ID | ||
| 1018 | * ...stack 0 is step value | ||
| 1019 | * ...stack 1 is end value | ||
| 1020 | * ...stack 2 is top address | ||
| 1021 | */ | ||
| 1022 | if (altera_check_stack(stack_ptr, 3, &status)) { | ||
| 1023 | s32 step = stack[stack_ptr - 1]; | ||
| 1024 | s32 end = stack[stack_ptr - 2]; | ||
| 1025 | s32 top = stack[stack_ptr - 3]; | ||
| 1026 | s32 iterator = vars[args[0]]; | ||
| 1027 | int break_out = 0; | ||
| 1028 | |||
| 1029 | if (step < 0) { | ||
| 1030 | if (iterator <= end) | ||
| 1031 | break_out = 1; | ||
| 1032 | } else if (iterator >= end) | ||
| 1033 | break_out = 1; | ||
| 1034 | |||
| 1035 | if (break_out) { | ||
| 1036 | stack_ptr -= 3; | ||
| 1037 | } else { | ||
| 1038 | vars[args[0]] = iterator + step; | ||
| 1039 | pc = top + code_sect; | ||
| 1040 | if ((pc < code_sect) || | ||
| 1041 | (pc >= debug_sect)) | ||
| 1042 | status = -ERANGE; | ||
| 1043 | } | ||
| 1044 | } | ||
| 1045 | break; | ||
| 1046 | case OP_PSTR: | ||
| 1047 | /* | ||
| 1048 | * PRINT add string | ||
| 1049 | * ...argument 0 is string ID | ||
| 1050 | */ | ||
| 1051 | count = strlen(msg_buff); | ||
| 1052 | strlcpy(&msg_buff[count], | ||
| 1053 | &p[str_table + args[0]], | ||
| 1054 | ALTERA_MESSAGE_LENGTH - count); | ||
| 1055 | break; | ||
| 1056 | case OP_SINT: | ||
| 1057 | /* | ||
| 1058 | * STATE intermediate state | ||
| 1059 | * ...argument 0 is state code | ||
| 1060 | */ | ||
| 1061 | status = altera_goto_jstate(astate, args[0]); | ||
| 1062 | break; | ||
| 1063 | case OP_ST: | ||
| 1064 | /* | ||
| 1065 | * STATE final state | ||
| 1066 | * ...argument 0 is state code | ||
| 1067 | */ | ||
| 1068 | status = altera_goto_jstate(astate, args[0]); | ||
| 1069 | break; | ||
| 1070 | case OP_ISTP: | ||
| 1071 | /* | ||
| 1072 | * IRSTOP state | ||
| 1073 | * ...argument 0 is state code | ||
| 1074 | */ | ||
| 1075 | status = altera_set_irstop(&astate->js, args[0]); | ||
| 1076 | break; | ||
| 1077 | case OP_DSTP: | ||
| 1078 | /* | ||
| 1079 | * DRSTOP state | ||
| 1080 | * ...argument 0 is state code | ||
| 1081 | */ | ||
| 1082 | status = altera_set_drstop(&astate->js, args[0]); | ||
| 1083 | break; | ||
| 1084 | |||
| 1085 | case OP_SWPN: | ||
| 1086 | /* | ||
| 1087 | * Exchange top with Nth stack value | ||
| 1088 | * ...argument 0 is 0-based stack entry | ||
| 1089 | * to swap with top element | ||
| 1090 | */ | ||
| 1091 | index = (args[0]) + 1; | ||
| 1092 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 1093 | long_tmp = stack[stack_ptr - index]; | ||
| 1094 | stack[stack_ptr - index] = stack[stack_ptr - 1]; | ||
| 1095 | stack[stack_ptr - 1] = long_tmp; | ||
| 1096 | } | ||
| 1097 | break; | ||
| 1098 | case OP_DUPN: | ||
| 1099 | /* | ||
| 1100 | * Duplicate Nth stack value | ||
| 1101 | * ...argument 0 is 0-based stack entry to duplicate | ||
| 1102 | */ | ||
| 1103 | index = (args[0]) + 1; | ||
| 1104 | if (altera_check_stack(stack_ptr, index, &status)) { | ||
| 1105 | stack[stack_ptr] = stack[stack_ptr - index]; | ||
| 1106 | ++stack_ptr; | ||
| 1107 | } | ||
| 1108 | break; | ||
| 1109 | case OP_POPV: | ||
| 1110 | /* | ||
| 1111 | * Pop stack into scalar variable | ||
| 1112 | * ...argument 0 is variable ID | ||
| 1113 | * ...stack 0 is value | ||
| 1114 | */ | ||
| 1115 | if (altera_check_stack(stack_ptr, 1, &status)) | ||
| 1116 | vars[args[0]] = stack[--stack_ptr]; | ||
| 1117 | |||
| 1118 | break; | ||
| 1119 | case OP_POPE: | ||
| 1120 | /* | ||
| 1121 | * Pop stack into integer array element | ||
| 1122 | * ...argument 0 is variable ID | ||
| 1123 | * ...stack 0 is array index | ||
| 1124 | * ...stack 1 is value | ||
| 1125 | */ | ||
| 1126 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1127 | break; | ||
| 1128 | variable_id = args[0]; | ||
| 1129 | |||
| 1130 | /* | ||
| 1131 | * If variable is read-only, | ||
| 1132 | * convert to writable array | ||
| 1133 | */ | ||
| 1134 | if ((version > 0) && | ||
| 1135 | ((attrs[variable_id] & 0x9c) == 0x1c)) { | ||
| 1136 | /* Allocate a writable buffer for this array */ | ||
| 1137 | count = var_size[variable_id]; | ||
| 1138 | long_tmp = vars[variable_id]; | ||
| 1139 | longptr_tmp = kzalloc(count * sizeof(long), | ||
| 1140 | GFP_KERNEL); | ||
| 1141 | vars[variable_id] = (long)longptr_tmp; | ||
| 1142 | |||
| 1143 | if (vars[variable_id] == 0) { | ||
| 1144 | status = -ENOMEM; | ||
| 1145 | break; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | /* copy previous contents into buffer */ | ||
| 1149 | for (i = 0; i < count; ++i) { | ||
| 1150 | longptr_tmp[i] = | ||
| 1151 | get_unaligned_be32(&p[long_tmp]); | ||
| 1152 | long_tmp += sizeof(long); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | /* | ||
| 1156 | * set bit 7 - buffer was | ||
| 1157 | * dynamically allocated | ||
| 1158 | */ | ||
| 1159 | attrs[variable_id] |= 0x80; | ||
| 1160 | |||
| 1161 | /* clear bit 2 - variable is writable */ | ||
| 1162 | attrs[variable_id] &= ~0x04; | ||
| 1163 | attrs[variable_id] |= 0x01; | ||
| 1164 | |||
| 1165 | } | ||
| 1166 | |||
| 1167 | /* check that variable is a writable integer array */ | ||
| 1168 | if ((attrs[variable_id] & 0x1c) != 0x18) | ||
| 1169 | status = -ERANGE; | ||
| 1170 | else { | ||
| 1171 | longptr_tmp = (long *)vars[variable_id]; | ||
| 1172 | |||
| 1173 | /* pop the array index */ | ||
| 1174 | index = stack[--stack_ptr]; | ||
| 1175 | |||
| 1176 | /* pop the value and store it into the array */ | ||
| 1177 | longptr_tmp[index] = stack[--stack_ptr]; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | break; | ||
| 1181 | case OP_POPA: | ||
| 1182 | /* | ||
| 1183 | * Pop stack into Boolean array | ||
| 1184 | * ...argument 0 is variable ID | ||
| 1185 | * ...stack 0 is count | ||
| 1186 | * ...stack 1 is array index | ||
| 1187 | * ...stack 2 is value | ||
| 1188 | */ | ||
| 1189 | if (!altera_check_stack(stack_ptr, 3, &status)) | ||
| 1190 | break; | ||
| 1191 | variable_id = args[0]; | ||
| 1192 | |||
| 1193 | /* | ||
| 1194 | * If variable is read-only, | ||
| 1195 | * convert to writable array | ||
| 1196 | */ | ||
| 1197 | if ((version > 0) && | ||
| 1198 | ((attrs[variable_id] & 0x9c) == 0x0c)) { | ||
| 1199 | /* Allocate a writable buffer for this array */ | ||
| 1200 | long_tmp = | ||
| 1201 | (var_size[variable_id] + 7L) >> 3L; | ||
| 1202 | charptr_tmp2 = (u8 *)vars[variable_id]; | ||
| 1203 | charptr_tmp = | ||
| 1204 | kzalloc(long_tmp, GFP_KERNEL); | ||
| 1205 | vars[variable_id] = (long)charptr_tmp; | ||
| 1206 | |||
| 1207 | if (vars[variable_id] == 0) { | ||
| 1208 | status = -ENOMEM; | ||
| 1209 | break; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | /* zero the buffer */ | ||
| 1213 | for (long_idx = 0L; | ||
| 1214 | long_idx < long_tmp; | ||
| 1215 | ++long_idx) { | ||
| 1216 | charptr_tmp[long_idx] = 0; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | /* copy previous contents into buffer */ | ||
| 1220 | for (long_idx = 0L; | ||
| 1221 | long_idx < var_size[variable_id]; | ||
| 1222 | ++long_idx) { | ||
| 1223 | long_idx2 = long_idx; | ||
| 1224 | |||
| 1225 | if (charptr_tmp2[long_idx2 >> 3] & | ||
| 1226 | (1 << (long_idx2 & 7))) { | ||
| 1227 | charptr_tmp[long_idx >> 3] |= | ||
| 1228 | (1 << (long_idx & 7)); | ||
| 1229 | } | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | /* | ||
| 1233 | * set bit 7 - buffer was | ||
| 1234 | * dynamically allocated | ||
| 1235 | */ | ||
| 1236 | attrs[variable_id] |= 0x80; | ||
| 1237 | |||
| 1238 | /* clear bit 2 - variable is writable */ | ||
| 1239 | attrs[variable_id] &= ~0x04; | ||
| 1240 | attrs[variable_id] |= 0x01; | ||
| 1241 | |||
| 1242 | } | ||
| 1243 | |||
| 1244 | /* | ||
| 1245 | * check that variable is | ||
| 1246 | * a writable Boolean array | ||
| 1247 | */ | ||
| 1248 | if ((attrs[variable_id] & 0x1c) != 0x08) { | ||
| 1249 | status = -ERANGE; | ||
| 1250 | break; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | charptr_tmp = (u8 *)vars[variable_id]; | ||
| 1254 | |||
| 1255 | /* pop the count (number of bits to copy) */ | ||
| 1256 | long_count = stack[--stack_ptr]; | ||
| 1257 | |||
| 1258 | /* pop the array index */ | ||
| 1259 | long_idx = stack[--stack_ptr]; | ||
| 1260 | |||
| 1261 | reverse = 0; | ||
| 1262 | |||
| 1263 | if (version > 0) { | ||
| 1264 | /* | ||
| 1265 | * stack 0 = array right index | ||
| 1266 | * stack 1 = array left index | ||
| 1267 | */ | ||
| 1268 | |||
| 1269 | if (long_idx > long_count) { | ||
| 1270 | reverse = 1; | ||
| 1271 | long_tmp = long_count; | ||
| 1272 | long_count = 1 + long_idx - | ||
| 1273 | long_count; | ||
| 1274 | long_idx = long_tmp; | ||
| 1275 | |||
| 1276 | /* reverse POPA is not supported */ | ||
| 1277 | status = -ERANGE; | ||
| 1278 | break; | ||
| 1279 | } else | ||
| 1280 | long_count = 1 + long_count - | ||
| 1281 | long_idx; | ||
| 1282 | |||
| 1283 | } | ||
| 1284 | |||
| 1285 | /* pop the data */ | ||
| 1286 | long_tmp = stack[--stack_ptr]; | ||
| 1287 | |||
| 1288 | if (long_count < 1) { | ||
| 1289 | status = -ERANGE; | ||
| 1290 | break; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | for (i = 0; i < long_count; ++i) { | ||
| 1294 | if (long_tmp & (1L << (s32) i)) | ||
| 1295 | charptr_tmp[long_idx >> 3L] |= | ||
| 1296 | (1L << (long_idx & 7L)); | ||
| 1297 | else | ||
| 1298 | charptr_tmp[long_idx >> 3L] &= | ||
| 1299 | ~(1L << (long_idx & 7L)); | ||
| 1300 | |||
| 1301 | ++long_idx; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | break; | ||
| 1305 | case OP_JMPZ: | ||
| 1306 | /* | ||
| 1307 | * Pop stack and branch if zero | ||
| 1308 | * ...argument 0 is address | ||
| 1309 | * ...stack 0 is condition value | ||
| 1310 | */ | ||
| 1311 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 1312 | if (stack[--stack_ptr] == 0) { | ||
| 1313 | pc = args[0] + code_sect; | ||
| 1314 | if ((pc < code_sect) || | ||
| 1315 | (pc >= debug_sect)) | ||
| 1316 | status = -ERANGE; | ||
| 1317 | } | ||
| 1318 | } | ||
| 1319 | break; | ||
| 1320 | case OP_DS: | ||
| 1321 | case OP_IS: | ||
| 1322 | /* | ||
| 1323 | * DRSCAN | ||
| 1324 | * IRSCAN | ||
| 1325 | * ...argument 0 is scan data variable ID | ||
| 1326 | * ...stack 0 is array index | ||
| 1327 | * ...stack 1 is count | ||
| 1328 | */ | ||
| 1329 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1330 | break; | ||
| 1331 | long_idx = stack[--stack_ptr]; | ||
| 1332 | long_count = stack[--stack_ptr]; | ||
| 1333 | reverse = 0; | ||
| 1334 | if (version > 0) { | ||
| 1335 | /* | ||
| 1336 | * stack 0 = array right index | ||
| 1337 | * stack 1 = array left index | ||
| 1338 | * stack 2 = count | ||
| 1339 | */ | ||
| 1340 | long_tmp = long_count; | ||
| 1341 | long_count = stack[--stack_ptr]; | ||
| 1342 | |||
| 1343 | if (long_idx > long_tmp) { | ||
| 1344 | reverse = 1; | ||
| 1345 | long_idx = long_tmp; | ||
| 1346 | } | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1350 | |||
| 1351 | if (reverse) { | ||
| 1352 | /* | ||
| 1353 | * allocate a buffer | ||
| 1354 | * and reverse the data order | ||
| 1355 | */ | ||
| 1356 | charptr_tmp2 = charptr_tmp; | ||
| 1357 | charptr_tmp = kzalloc((long_count >> 3) + 1, | ||
| 1358 | GFP_KERNEL); | ||
| 1359 | if (charptr_tmp == NULL) { | ||
| 1360 | status = -ENOMEM; | ||
| 1361 | break; | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | long_tmp = long_idx + long_count - 1; | ||
| 1365 | long_idx2 = 0; | ||
| 1366 | while (long_idx2 < long_count) { | ||
| 1367 | if (charptr_tmp2[long_tmp >> 3] & | ||
| 1368 | (1 << (long_tmp & 7))) | ||
| 1369 | charptr_tmp[long_idx2 >> 3] |= | ||
| 1370 | (1 << (long_idx2 & 7)); | ||
| 1371 | else | ||
| 1372 | charptr_tmp[long_idx2 >> 3] &= | ||
| 1373 | ~(1 << (long_idx2 & 7)); | ||
| 1374 | |||
| 1375 | --long_tmp; | ||
| 1376 | ++long_idx2; | ||
| 1377 | } | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | if (opcode == 0x51) /* DS */ | ||
| 1381 | status = altera_drscan(astate, long_count, | ||
| 1382 | charptr_tmp, long_idx); | ||
| 1383 | else /* IS */ | ||
| 1384 | status = altera_irscan(astate, long_count, | ||
| 1385 | charptr_tmp, long_idx); | ||
| 1386 | |||
| 1387 | if (reverse) | ||
| 1388 | kfree(charptr_tmp); | ||
| 1389 | |||
| 1390 | break; | ||
| 1391 | case OP_DPRA: | ||
| 1392 | /* | ||
| 1393 | * DRPRE with array data | ||
| 1394 | * ...argument 0 is variable ID | ||
| 1395 | * ...stack 0 is array index | ||
| 1396 | * ...stack 1 is count | ||
| 1397 | */ | ||
| 1398 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1399 | break; | ||
| 1400 | index = stack[--stack_ptr]; | ||
| 1401 | count = stack[--stack_ptr]; | ||
| 1402 | |||
| 1403 | if (version > 0) | ||
| 1404 | /* | ||
| 1405 | * stack 0 = array right index | ||
| 1406 | * stack 1 = array left index | ||
| 1407 | */ | ||
| 1408 | count = 1 + count - index; | ||
| 1409 | |||
| 1410 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1411 | status = altera_set_dr_pre(&astate->js, count, index, | ||
| 1412 | charptr_tmp); | ||
| 1413 | break; | ||
| 1414 | case OP_DPOA: | ||
| 1415 | /* | ||
| 1416 | * DRPOST with array data | ||
| 1417 | * ...argument 0 is variable ID | ||
| 1418 | * ...stack 0 is array index | ||
| 1419 | * ...stack 1 is count | ||
| 1420 | */ | ||
| 1421 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1422 | break; | ||
| 1423 | index = stack[--stack_ptr]; | ||
| 1424 | count = stack[--stack_ptr]; | ||
| 1425 | |||
| 1426 | if (version > 0) | ||
| 1427 | /* | ||
| 1428 | * stack 0 = array right index | ||
| 1429 | * stack 1 = array left index | ||
| 1430 | */ | ||
| 1431 | count = 1 + count - index; | ||
| 1432 | |||
| 1433 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1434 | status = altera_set_dr_post(&astate->js, count, index, | ||
| 1435 | charptr_tmp); | ||
| 1436 | break; | ||
| 1437 | case OP_IPRA: | ||
| 1438 | /* | ||
| 1439 | * IRPRE with array data | ||
| 1440 | * ...argument 0 is variable ID | ||
| 1441 | * ...stack 0 is array index | ||
| 1442 | * ...stack 1 is count | ||
| 1443 | */ | ||
| 1444 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1445 | break; | ||
| 1446 | index = stack[--stack_ptr]; | ||
| 1447 | count = stack[--stack_ptr]; | ||
| 1448 | |||
| 1449 | if (version > 0) | ||
| 1450 | /* | ||
| 1451 | * stack 0 = array right index | ||
| 1452 | * stack 1 = array left index | ||
| 1453 | */ | ||
| 1454 | count = 1 + count - index; | ||
| 1455 | |||
| 1456 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1457 | status = altera_set_ir_pre(&astate->js, count, index, | ||
| 1458 | charptr_tmp); | ||
| 1459 | |||
| 1460 | break; | ||
| 1461 | case OP_IPOA: | ||
| 1462 | /* | ||
| 1463 | * IRPOST with array data | ||
| 1464 | * ...argument 0 is variable ID | ||
| 1465 | * ...stack 0 is array index | ||
| 1466 | * ...stack 1 is count | ||
| 1467 | */ | ||
| 1468 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1469 | break; | ||
| 1470 | index = stack[--stack_ptr]; | ||
| 1471 | count = stack[--stack_ptr]; | ||
| 1472 | |||
| 1473 | if (version > 0) | ||
| 1474 | /* | ||
| 1475 | * stack 0 = array right index | ||
| 1476 | * stack 1 = array left index | ||
| 1477 | */ | ||
| 1478 | count = 1 + count - index; | ||
| 1479 | |||
| 1480 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1481 | status = altera_set_ir_post(&astate->js, count, index, | ||
| 1482 | charptr_tmp); | ||
| 1483 | |||
| 1484 | break; | ||
| 1485 | case OP_EXPT: | ||
| 1486 | /* | ||
| 1487 | * EXPORT | ||
| 1488 | * ...argument 0 is string ID | ||
| 1489 | * ...stack 0 is integer expression | ||
| 1490 | */ | ||
| 1491 | if (altera_check_stack(stack_ptr, 1, &status)) { | ||
| 1492 | name = &p[str_table + args[0]]; | ||
| 1493 | long_tmp = stack[--stack_ptr]; | ||
| 1494 | altera_export_int(name, long_tmp); | ||
| 1495 | } | ||
| 1496 | break; | ||
| 1497 | case OP_PSHE: | ||
| 1498 | /* | ||
| 1499 | * Push integer array element | ||
| 1500 | * ...argument 0 is variable ID | ||
| 1501 | * ...stack 0 is array index | ||
| 1502 | */ | ||
| 1503 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 1504 | break; | ||
| 1505 | variable_id = args[0]; | ||
| 1506 | index = stack[stack_ptr - 1]; | ||
| 1507 | |||
| 1508 | /* check variable type */ | ||
| 1509 | if ((attrs[variable_id] & 0x1f) == 0x19) { | ||
| 1510 | /* writable integer array */ | ||
| 1511 | longptr_tmp = (long *)vars[variable_id]; | ||
| 1512 | stack[stack_ptr - 1] = longptr_tmp[index]; | ||
| 1513 | } else if ((attrs[variable_id] & 0x1f) == 0x1c) { | ||
| 1514 | /* read-only integer array */ | ||
| 1515 | long_tmp = vars[variable_id] + | ||
| 1516 | (index * sizeof(long)); | ||
| 1517 | stack[stack_ptr - 1] = | ||
| 1518 | get_unaligned_be32(&p[long_tmp]); | ||
| 1519 | } else | ||
| 1520 | status = -ERANGE; | ||
| 1521 | |||
| 1522 | break; | ||
| 1523 | case OP_PSHA: | ||
| 1524 | /* | ||
| 1525 | * Push Boolean array | ||
| 1526 | * ...argument 0 is variable ID | ||
| 1527 | * ...stack 0 is count | ||
| 1528 | * ...stack 1 is array index | ||
| 1529 | */ | ||
| 1530 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1531 | break; | ||
| 1532 | variable_id = args[0]; | ||
| 1533 | |||
| 1534 | /* check that variable is a Boolean array */ | ||
| 1535 | if ((attrs[variable_id] & 0x18) != 0x08) { | ||
| 1536 | status = -ERANGE; | ||
| 1537 | break; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | charptr_tmp = (u8 *)vars[variable_id]; | ||
| 1541 | |||
| 1542 | /* pop the count (number of bits to copy) */ | ||
| 1543 | count = stack[--stack_ptr]; | ||
| 1544 | |||
| 1545 | /* pop the array index */ | ||
| 1546 | index = stack[stack_ptr - 1]; | ||
| 1547 | |||
| 1548 | if (version > 0) | ||
| 1549 | /* | ||
| 1550 | * stack 0 = array right index | ||
| 1551 | * stack 1 = array left index | ||
| 1552 | */ | ||
| 1553 | count = 1 + count - index; | ||
| 1554 | |||
| 1555 | if ((count < 1) || (count > 32)) { | ||
| 1556 | status = -ERANGE; | ||
| 1557 | break; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | long_tmp = 0L; | ||
| 1561 | |||
| 1562 | for (i = 0; i < count; ++i) | ||
| 1563 | if (charptr_tmp[(i + index) >> 3] & | ||
| 1564 | (1 << ((i + index) & 7))) | ||
| 1565 | long_tmp |= (1L << i); | ||
| 1566 | |||
| 1567 | stack[stack_ptr - 1] = long_tmp; | ||
| 1568 | |||
| 1569 | break; | ||
| 1570 | case OP_DYNA: | ||
| 1571 | /* | ||
| 1572 | * Dynamically change size of array | ||
| 1573 | * ...argument 0 is variable ID | ||
| 1574 | * ...stack 0 is new size | ||
| 1575 | */ | ||
| 1576 | if (!altera_check_stack(stack_ptr, 1, &status)) | ||
| 1577 | break; | ||
| 1578 | variable_id = args[0]; | ||
| 1579 | long_tmp = stack[--stack_ptr]; | ||
| 1580 | |||
| 1581 | if (long_tmp > var_size[variable_id]) { | ||
| 1582 | var_size[variable_id] = long_tmp; | ||
| 1583 | |||
| 1584 | if (attrs[variable_id] & 0x10) | ||
| 1585 | /* allocate integer array */ | ||
| 1586 | long_tmp *= sizeof(long); | ||
| 1587 | else | ||
| 1588 | /* allocate Boolean array */ | ||
| 1589 | long_tmp = (long_tmp + 7) >> 3; | ||
| 1590 | |||
| 1591 | /* | ||
| 1592 | * If the buffer was previously allocated, | ||
| 1593 | * free it | ||
| 1594 | */ | ||
| 1595 | if (attrs[variable_id] & 0x80) { | ||
| 1596 | kfree((void *)vars[variable_id]); | ||
| 1597 | vars[variable_id] = 0; | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | /* | ||
| 1601 | * Allocate a new buffer | ||
| 1602 | * of the requested size | ||
| 1603 | */ | ||
| 1604 | vars[variable_id] = (long) | ||
| 1605 | kzalloc(long_tmp, GFP_KERNEL); | ||
| 1606 | |||
| 1607 | if (vars[variable_id] == 0) { | ||
| 1608 | status = -ENOMEM; | ||
| 1609 | break; | ||
| 1610 | } | ||
| 1611 | |||
| 1612 | /* | ||
| 1613 | * Set the attribute bit to indicate that | ||
| 1614 | * this buffer was dynamically allocated and | ||
| 1615 | * should be freed later | ||
| 1616 | */ | ||
| 1617 | attrs[variable_id] |= 0x80; | ||
| 1618 | |||
| 1619 | /* zero out memory */ | ||
| 1620 | count = ((var_size[variable_id] + 7L) / | ||
| 1621 | 8L); | ||
| 1622 | charptr_tmp = (u8 *)(vars[variable_id]); | ||
| 1623 | for (index = 0; index < count; ++index) | ||
| 1624 | charptr_tmp[index] = 0; | ||
| 1625 | |||
| 1626 | } | ||
| 1627 | |||
| 1628 | break; | ||
| 1629 | case OP_EXPV: | ||
| 1630 | /* | ||
| 1631 | * Export Boolean array | ||
| 1632 | * ...argument 0 is string ID | ||
| 1633 | * ...stack 0 is variable ID | ||
| 1634 | * ...stack 1 is array right index | ||
| 1635 | * ...stack 2 is array left index | ||
| 1636 | */ | ||
| 1637 | if (!altera_check_stack(stack_ptr, 3, &status)) | ||
| 1638 | break; | ||
| 1639 | if (version == 0) { | ||
| 1640 | /* EXPV is not supported in JBC 1.0 */ | ||
| 1641 | bad_opcode = 1; | ||
| 1642 | break; | ||
| 1643 | } | ||
| 1644 | name = &p[str_table + args[0]]; | ||
| 1645 | variable_id = stack[--stack_ptr]; | ||
| 1646 | long_idx = stack[--stack_ptr];/* right indx */ | ||
| 1647 | long_idx2 = stack[--stack_ptr];/* left indx */ | ||
| 1648 | |||
| 1649 | if (long_idx > long_idx2) { | ||
| 1650 | /* reverse indices not supported */ | ||
| 1651 | status = -ERANGE; | ||
| 1652 | break; | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | long_count = 1 + long_idx2 - long_idx; | ||
| 1656 | |||
| 1657 | charptr_tmp = (u8 *)vars[variable_id]; | ||
| 1658 | charptr_tmp2 = NULL; | ||
| 1659 | |||
| 1660 | if ((long_idx & 7L) != 0) { | ||
| 1661 | s32 k = long_idx; | ||
| 1662 | charptr_tmp2 = | ||
| 1663 | kzalloc(((long_count + 7L) / 8L), | ||
| 1664 | GFP_KERNEL); | ||
| 1665 | if (charptr_tmp2 == NULL) { | ||
| 1666 | status = -ENOMEM; | ||
| 1667 | break; | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | for (i = 0; i < long_count; ++i) { | ||
| 1671 | if (charptr_tmp[k >> 3] & | ||
| 1672 | (1 << (k & 7))) | ||
| 1673 | charptr_tmp2[i >> 3] |= | ||
| 1674 | (1 << (i & 7)); | ||
| 1675 | else | ||
| 1676 | charptr_tmp2[i >> 3] &= | ||
| 1677 | ~(1 << (i & 7)); | ||
| 1678 | |||
| 1679 | ++k; | ||
| 1680 | } | ||
| 1681 | charptr_tmp = charptr_tmp2; | ||
| 1682 | |||
| 1683 | } else if (long_idx != 0) | ||
| 1684 | charptr_tmp = &charptr_tmp[long_idx >> 3]; | ||
| 1685 | |||
| 1686 | altera_export_bool_array(name, charptr_tmp, | ||
| 1687 | long_count); | ||
| 1688 | |||
| 1689 | /* free allocated buffer */ | ||
| 1690 | if ((long_idx & 7L) != 0) | ||
| 1691 | kfree(charptr_tmp2); | ||
| 1692 | |||
| 1693 | break; | ||
| 1694 | case OP_COPY: { | ||
| 1695 | /* | ||
| 1696 | * Array copy | ||
| 1697 | * ...argument 0 is dest ID | ||
| 1698 | * ...argument 1 is source ID | ||
| 1699 | * ...stack 0 is count | ||
| 1700 | * ...stack 1 is dest index | ||
| 1701 | * ...stack 2 is source index | ||
| 1702 | */ | ||
| 1703 | s32 copy_count; | ||
| 1704 | s32 copy_index; | ||
| 1705 | s32 copy_index2; | ||
| 1706 | s32 destleft; | ||
| 1707 | s32 src_count; | ||
| 1708 | s32 dest_count; | ||
| 1709 | int src_reverse = 0; | ||
| 1710 | int dest_reverse = 0; | ||
| 1711 | |||
| 1712 | if (!altera_check_stack(stack_ptr, 3, &status)) | ||
| 1713 | break; | ||
| 1714 | |||
| 1715 | copy_count = stack[--stack_ptr]; | ||
| 1716 | copy_index = stack[--stack_ptr]; | ||
| 1717 | copy_index2 = stack[--stack_ptr]; | ||
| 1718 | reverse = 0; | ||
| 1719 | |||
| 1720 | if (version > 0) { | ||
| 1721 | /* | ||
| 1722 | * stack 0 = source right index | ||
| 1723 | * stack 1 = source left index | ||
| 1724 | * stack 2 = destination right index | ||
| 1725 | * stack 3 = destination left index | ||
| 1726 | */ | ||
| 1727 | destleft = stack[--stack_ptr]; | ||
| 1728 | |||
| 1729 | if (copy_count > copy_index) { | ||
| 1730 | src_reverse = 1; | ||
| 1731 | reverse = 1; | ||
| 1732 | src_count = 1 + copy_count - copy_index; | ||
| 1733 | /* copy_index = source start index */ | ||
| 1734 | } else { | ||
| 1735 | src_count = 1 + copy_index - copy_count; | ||
| 1736 | /* source start index */ | ||
| 1737 | copy_index = copy_count; | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | if (copy_index2 > destleft) { | ||
| 1741 | dest_reverse = 1; | ||
| 1742 | reverse = !reverse; | ||
| 1743 | dest_count = 1 + copy_index2 - destleft; | ||
| 1744 | /* destination start index */ | ||
| 1745 | copy_index2 = destleft; | ||
| 1746 | } else | ||
| 1747 | dest_count = 1 + destleft - copy_index2; | ||
| 1748 | |||
| 1749 | copy_count = (src_count < dest_count) ? | ||
| 1750 | src_count : dest_count; | ||
| 1751 | |||
| 1752 | if ((src_reverse || dest_reverse) && | ||
| 1753 | (src_count != dest_count)) | ||
| 1754 | /* | ||
| 1755 | * If either the source or destination | ||
| 1756 | * is reversed, we can't tolerate | ||
| 1757 | * a length mismatch, because we | ||
| 1758 | * "left justify" arrays when copying. | ||
| 1759 | * This won't work correctly | ||
| 1760 | * with reversed arrays. | ||
| 1761 | */ | ||
| 1762 | status = -ERANGE; | ||
| 1763 | |||
| 1764 | } | ||
| 1765 | |||
| 1766 | count = copy_count; | ||
| 1767 | index = copy_index; | ||
| 1768 | index2 = copy_index2; | ||
| 1769 | |||
| 1770 | /* | ||
| 1771 | * If destination is a read-only array, | ||
| 1772 | * allocate a buffer and convert it to a writable array | ||
| 1773 | */ | ||
| 1774 | variable_id = args[1]; | ||
| 1775 | if ((version > 0) && | ||
| 1776 | ((attrs[variable_id] & 0x9c) == 0x0c)) { | ||
| 1777 | /* Allocate a writable buffer for this array */ | ||
| 1778 | long_tmp = | ||
| 1779 | (var_size[variable_id] + 7L) >> 3L; | ||
| 1780 | charptr_tmp2 = (u8 *)vars[variable_id]; | ||
| 1781 | charptr_tmp = | ||
| 1782 | kzalloc(long_tmp, GFP_KERNEL); | ||
| 1783 | vars[variable_id] = (long)charptr_tmp; | ||
| 1784 | |||
| 1785 | if (vars[variable_id] == 0) { | ||
| 1786 | status = -ENOMEM; | ||
| 1787 | break; | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | /* zero the buffer */ | ||
| 1791 | for (long_idx = 0L; long_idx < long_tmp; | ||
| 1792 | ++long_idx) | ||
| 1793 | charptr_tmp[long_idx] = 0; | ||
| 1794 | |||
| 1795 | /* copy previous contents into buffer */ | ||
| 1796 | for (long_idx = 0L; | ||
| 1797 | long_idx < var_size[variable_id]; | ||
| 1798 | ++long_idx) { | ||
| 1799 | long_idx2 = long_idx; | ||
| 1800 | |||
| 1801 | if (charptr_tmp2[long_idx2 >> 3] & | ||
| 1802 | (1 << (long_idx2 & 7))) | ||
| 1803 | charptr_tmp[long_idx >> 3] |= | ||
| 1804 | (1 << (long_idx & 7)); | ||
| 1805 | |||
| 1806 | } | ||
| 1807 | |||
| 1808 | /* | ||
| 1809 | set bit 7 - buffer was dynamically allocated */ | ||
| 1810 | attrs[variable_id] |= 0x80; | ||
| 1811 | |||
| 1812 | /* clear bit 2 - variable is writable */ | ||
| 1813 | attrs[variable_id] &= ~0x04; | ||
| 1814 | attrs[variable_id] |= 0x01; | ||
| 1815 | } | ||
| 1816 | |||
| 1817 | charptr_tmp = (u8 *)vars[args[1]]; | ||
| 1818 | charptr_tmp2 = (u8 *)vars[args[0]]; | ||
| 1819 | |||
| 1820 | /* check if destination is a writable Boolean array */ | ||
| 1821 | if ((attrs[args[1]] & 0x1c) != 0x08) { | ||
| 1822 | status = -ERANGE; | ||
| 1823 | break; | ||
| 1824 | } | ||
| 1825 | |||
| 1826 | if (count < 1) { | ||
| 1827 | status = -ERANGE; | ||
| 1828 | break; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | if (reverse) | ||
| 1832 | index2 += (count - 1); | ||
| 1833 | |||
| 1834 | for (i = 0; i < count; ++i) { | ||
| 1835 | if (charptr_tmp2[index >> 3] & | ||
| 1836 | (1 << (index & 7))) | ||
| 1837 | charptr_tmp[index2 >> 3] |= | ||
| 1838 | (1 << (index2 & 7)); | ||
| 1839 | else | ||
| 1840 | charptr_tmp[index2 >> 3] &= | ||
| 1841 | ~(1 << (index2 & 7)); | ||
| 1842 | |||
| 1843 | ++index; | ||
| 1844 | if (reverse) | ||
| 1845 | --index2; | ||
| 1846 | else | ||
| 1847 | ++index2; | ||
| 1848 | } | ||
| 1849 | |||
| 1850 | break; | ||
| 1851 | } | ||
| 1852 | case OP_DSC: | ||
| 1853 | case OP_ISC: { | ||
| 1854 | /* | ||
| 1855 | * DRSCAN with capture | ||
| 1856 | * IRSCAN with capture | ||
| 1857 | * ...argument 0 is scan data variable ID | ||
| 1858 | * ...argument 1 is capture variable ID | ||
| 1859 | * ...stack 0 is capture index | ||
| 1860 | * ...stack 1 is scan data index | ||
| 1861 | * ...stack 2 is count | ||
| 1862 | */ | ||
| 1863 | s32 scan_right, scan_left; | ||
| 1864 | s32 capture_count = 0; | ||
| 1865 | s32 scan_count = 0; | ||
| 1866 | s32 capture_index; | ||
| 1867 | s32 scan_index; | ||
| 1868 | |||
| 1869 | if (!altera_check_stack(stack_ptr, 3, &status)) | ||
| 1870 | break; | ||
| 1871 | |||
| 1872 | capture_index = stack[--stack_ptr]; | ||
| 1873 | scan_index = stack[--stack_ptr]; | ||
| 1874 | |||
| 1875 | if (version > 0) { | ||
| 1876 | /* | ||
| 1877 | * stack 0 = capture right index | ||
| 1878 | * stack 1 = capture left index | ||
| 1879 | * stack 2 = scan right index | ||
| 1880 | * stack 3 = scan left index | ||
| 1881 | * stack 4 = count | ||
| 1882 | */ | ||
| 1883 | scan_right = stack[--stack_ptr]; | ||
| 1884 | scan_left = stack[--stack_ptr]; | ||
| 1885 | capture_count = 1 + scan_index - capture_index; | ||
| 1886 | scan_count = 1 + scan_left - scan_right; | ||
| 1887 | scan_index = scan_right; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | long_count = stack[--stack_ptr]; | ||
| 1891 | /* | ||
| 1892 | * If capture array is read-only, allocate a buffer | ||
| 1893 | * and convert it to a writable array | ||
| 1894 | */ | ||
| 1895 | variable_id = args[1]; | ||
| 1896 | if ((version > 0) && | ||
| 1897 | ((attrs[variable_id] & 0x9c) == 0x0c)) { | ||
| 1898 | /* Allocate a writable buffer for this array */ | ||
| 1899 | long_tmp = | ||
| 1900 | (var_size[variable_id] + 7L) >> 3L; | ||
| 1901 | charptr_tmp2 = (u8 *)vars[variable_id]; | ||
| 1902 | charptr_tmp = | ||
| 1903 | kzalloc(long_tmp, GFP_KERNEL); | ||
| 1904 | vars[variable_id] = (long)charptr_tmp; | ||
| 1905 | |||
| 1906 | if (vars[variable_id] == 0) { | ||
| 1907 | status = -ENOMEM; | ||
| 1908 | break; | ||
| 1909 | } | ||
| 1910 | |||
| 1911 | /* zero the buffer */ | ||
| 1912 | for (long_idx = 0L; long_idx < long_tmp; | ||
| 1913 | ++long_idx) | ||
| 1914 | charptr_tmp[long_idx] = 0; | ||
| 1915 | |||
| 1916 | /* copy previous contents into buffer */ | ||
| 1917 | for (long_idx = 0L; | ||
| 1918 | long_idx < var_size[variable_id]; | ||
| 1919 | ++long_idx) { | ||
| 1920 | long_idx2 = long_idx; | ||
| 1921 | |||
| 1922 | if (charptr_tmp2[long_idx2 >> 3] & | ||
| 1923 | (1 << (long_idx2 & 7))) | ||
| 1924 | charptr_tmp[long_idx >> 3] |= | ||
| 1925 | (1 << (long_idx & 7)); | ||
| 1926 | |||
| 1927 | } | ||
| 1928 | |||
| 1929 | /* | ||
| 1930 | * set bit 7 - buffer was | ||
| 1931 | * dynamically allocated | ||
| 1932 | */ | ||
| 1933 | attrs[variable_id] |= 0x80; | ||
| 1934 | |||
| 1935 | /* clear bit 2 - variable is writable */ | ||
| 1936 | attrs[variable_id] &= ~0x04; | ||
| 1937 | attrs[variable_id] |= 0x01; | ||
| 1938 | |||
| 1939 | } | ||
| 1940 | |||
| 1941 | charptr_tmp = (u8 *)vars[args[0]]; | ||
| 1942 | charptr_tmp2 = (u8 *)vars[args[1]]; | ||
| 1943 | |||
| 1944 | if ((version > 0) && | ||
| 1945 | ((long_count > capture_count) || | ||
| 1946 | (long_count > scan_count))) { | ||
| 1947 | status = -ERANGE; | ||
| 1948 | break; | ||
| 1949 | } | ||
| 1950 | |||
| 1951 | /* | ||
| 1952 | * check that capture array | ||
| 1953 | * is a writable Boolean array | ||
| 1954 | */ | ||
| 1955 | if ((attrs[args[1]] & 0x1c) != 0x08) { | ||
| 1956 | status = -ERANGE; | ||
| 1957 | break; | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | if (status == 0) { | ||
| 1961 | if (opcode == 0x82) /* DSC */ | ||
| 1962 | status = altera_swap_dr(astate, | ||
| 1963 | long_count, | ||
| 1964 | charptr_tmp, | ||
| 1965 | scan_index, | ||
| 1966 | charptr_tmp2, | ||
| 1967 | capture_index); | ||
| 1968 | else /* ISC */ | ||
| 1969 | status = altera_swap_ir(astate, | ||
| 1970 | long_count, | ||
| 1971 | charptr_tmp, | ||
| 1972 | scan_index, | ||
| 1973 | charptr_tmp2, | ||
| 1974 | capture_index); | ||
| 1975 | |||
| 1976 | } | ||
| 1977 | |||
| 1978 | break; | ||
| 1979 | } | ||
| 1980 | case OP_WAIT: | ||
| 1981 | /* | ||
| 1982 | * WAIT | ||
| 1983 | * ...argument 0 is wait state | ||
| 1984 | * ...argument 1 is end state | ||
| 1985 | * ...stack 0 is cycles | ||
| 1986 | * ...stack 1 is microseconds | ||
| 1987 | */ | ||
| 1988 | if (!altera_check_stack(stack_ptr, 2, &status)) | ||
| 1989 | break; | ||
| 1990 | long_tmp = stack[--stack_ptr]; | ||
| 1991 | |||
| 1992 | if (long_tmp != 0L) | ||
| 1993 | status = altera_wait_cycles(astate, long_tmp, | ||
| 1994 | args[0]); | ||
| 1995 | |||
| 1996 | long_tmp = stack[--stack_ptr]; | ||
| 1997 | |||
| 1998 | if ((status == 0) && (long_tmp != 0L)) | ||
| 1999 | status = altera_wait_msecs(astate, | ||
| 2000 | long_tmp, | ||
| 2001 | args[0]); | ||
| 2002 | |||
| 2003 | if ((status == 0) && (args[1] != args[0])) | ||
| 2004 | status = altera_goto_jstate(astate, | ||
| 2005 | args[1]); | ||
| 2006 | |||
| 2007 | if (version > 0) { | ||
| 2008 | --stack_ptr; /* throw away MAX cycles */ | ||
| 2009 | --stack_ptr; /* throw away MAX microseconds */ | ||
| 2010 | } | ||
| 2011 | break; | ||
| 2012 | case OP_CMPA: { | ||
| 2013 | /* | ||
| 2014 | * Array compare | ||
| 2015 | * ...argument 0 is source 1 ID | ||
| 2016 | * ...argument 1 is source 2 ID | ||
| 2017 | * ...argument 2 is mask ID | ||
| 2018 | * ...stack 0 is source 1 index | ||
| 2019 | * ...stack 1 is source 2 index | ||
| 2020 | * ...stack 2 is mask index | ||
| 2021 | * ...stack 3 is count | ||
| 2022 | */ | ||
| 2023 | s32 a, b; | ||
| 2024 | u8 *source1 = (u8 *)vars[args[0]]; | ||
| 2025 | u8 *source2 = (u8 *)vars[args[1]]; | ||
| 2026 | u8 *mask = (u8 *)vars[args[2]]; | ||
| 2027 | u32 index1; | ||
| 2028 | u32 index2; | ||
| 2029 | u32 mask_index; | ||
| 2030 | |||
| 2031 | if (!altera_check_stack(stack_ptr, 4, &status)) | ||
| 2032 | break; | ||
| 2033 | |||
| 2034 | index1 = stack[--stack_ptr]; | ||
| 2035 | index2 = stack[--stack_ptr]; | ||
| 2036 | mask_index = stack[--stack_ptr]; | ||
| 2037 | long_count = stack[--stack_ptr]; | ||
| 2038 | |||
| 2039 | if (version > 0) { | ||
| 2040 | /* | ||
| 2041 | * stack 0 = source 1 right index | ||
| 2042 | * stack 1 = source 1 left index | ||
| 2043 | * stack 2 = source 2 right index | ||
| 2044 | * stack 3 = source 2 left index | ||
| 2045 | * stack 4 = mask right index | ||
| 2046 | * stack 5 = mask left index | ||
| 2047 | */ | ||
| 2048 | s32 mask_right = stack[--stack_ptr]; | ||
| 2049 | s32 mask_left = stack[--stack_ptr]; | ||
| 2050 | /* source 1 count */ | ||
| 2051 | a = 1 + index2 - index1; | ||
| 2052 | /* source 2 count */ | ||
| 2053 | b = 1 + long_count - mask_index; | ||
| 2054 | a = (a < b) ? a : b; | ||
| 2055 | /* mask count */ | ||
| 2056 | b = 1 + mask_left - mask_right; | ||
| 2057 | a = (a < b) ? a : b; | ||
| 2058 | /* source 2 start index */ | ||
| 2059 | index2 = mask_index; | ||
| 2060 | /* mask start index */ | ||
| 2061 | mask_index = mask_right; | ||
| 2062 | long_count = a; | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | long_tmp = 1L; | ||
| 2066 | |||
| 2067 | if (long_count < 1) | ||
| 2068 | status = -ERANGE; | ||
| 2069 | else { | ||
| 2070 | count = long_count; | ||
| 2071 | |||
| 2072 | for (i = 0; i < count; ++i) { | ||
| 2073 | if (mask[mask_index >> 3] & | ||
| 2074 | (1 << (mask_index & 7))) { | ||
| 2075 | a = source1[index1 >> 3] & | ||
| 2076 | (1 << (index1 & 7)) | ||
| 2077 | ? 1 : 0; | ||
| 2078 | b = source2[index2 >> 3] & | ||
| 2079 | (1 << (index2 & 7)) | ||
| 2080 | ? 1 : 0; | ||
| 2081 | |||
| 2082 | if (a != b) /* failure */ | ||
| 2083 | long_tmp = 0L; | ||
| 2084 | } | ||
| 2085 | ++index1; | ||
| 2086 | ++index2; | ||
| 2087 | ++mask_index; | ||
| 2088 | } | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | stack[stack_ptr++] = long_tmp; | ||
| 2092 | |||
| 2093 | break; | ||
| 2094 | } | ||
| 2095 | default: | ||
| 2096 | /* Unrecognized opcode -- ERROR! */ | ||
| 2097 | bad_opcode = 1; | ||
| 2098 | break; | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | if (bad_opcode) | ||
| 2102 | status = -ENOSYS; | ||
| 2103 | |||
| 2104 | if ((stack_ptr < 0) || (stack_ptr >= ALTERA_STACK_SIZE)) | ||
| 2105 | status = -EOVERFLOW; | ||
| 2106 | |||
| 2107 | if (status != 0) { | ||
| 2108 | done = 1; | ||
| 2109 | *error_address = (s32)(opcode_address - code_sect); | ||
| 2110 | } | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | altera_free_buffers(astate); | ||
| 2114 | |||
| 2115 | /* Free all dynamically allocated arrays */ | ||
| 2116 | if ((attrs != NULL) && (vars != NULL)) | ||
| 2117 | for (i = 0; i < sym_count; ++i) | ||
| 2118 | if (attrs[i] & 0x80) | ||
| 2119 | kfree((void *)vars[i]); | ||
| 2120 | |||
| 2121 | kfree(vars); | ||
| 2122 | kfree(var_size); | ||
| 2123 | kfree(attrs); | ||
| 2124 | kfree(proc_attributes); | ||
| 2125 | |||
| 2126 | return status; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | static int altera_get_note(u8 *p, s32 program_size, | ||
| 2130 | s32 *offset, char *key, char *value, int length) | ||
| 2131 | /* | ||
| 2132 | * Gets key and value of NOTE fields in the JBC file. | ||
| 2133 | * Can be called in two modes: if offset pointer is NULL, | ||
| 2134 | * then the function searches for note fields which match | ||
| 2135 | * the key string provided. If offset is not NULL, then | ||
| 2136 | * the function finds the next note field of any key, | ||
| 2137 | * starting at the offset specified by the offset pointer. | ||
| 2138 | * Returns 0 for success, else appropriate error code | ||
| 2139 | */ | ||
| 2140 | { | ||
| 2141 | int status = -ENODATA; | ||
| 2142 | u32 note_strings = 0L; | ||
| 2143 | u32 note_table = 0L; | ||
| 2144 | u32 note_count = 0L; | ||
| 2145 | u32 first_word = 0L; | ||
| 2146 | int version = 0; | ||
| 2147 | int delta = 0; | ||
| 2148 | char *key_ptr; | ||
| 2149 | char *value_ptr; | ||
| 2150 | int i; | ||
| 2151 | |||
| 2152 | /* Read header information */ | ||
| 2153 | if (program_size > 52L) { | ||
| 2154 | first_word = get_unaligned_be32(&p[0]); | ||
| 2155 | version = (first_word & 1L); | ||
| 2156 | delta = version * 8; | ||
| 2157 | |||
| 2158 | note_strings = get_unaligned_be32(&p[8 + delta]); | ||
| 2159 | note_table = get_unaligned_be32(&p[12 + delta]); | ||
| 2160 | note_count = get_unaligned_be32(&p[44 + (2 * delta)]); | ||
| 2161 | } | ||
| 2162 | |||
| 2163 | if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) | ||
| 2164 | return -EIO; | ||
| 2165 | |||
| 2166 | if (note_count <= 0L) | ||
| 2167 | return status; | ||
| 2168 | |||
| 2169 | if (offset == NULL) { | ||
| 2170 | /* | ||
| 2171 | * We will search for the first note with a specific key, | ||
| 2172 | * and return only the value | ||
| 2173 | */ | ||
| 2174 | for (i = 0; (i < note_count) && | ||
| 2175 | (status != 0); ++i) { | ||
| 2176 | key_ptr = &p[note_strings + | ||
| 2177 | get_unaligned_be32( | ||
| 2178 | &p[note_table + (8 * i)])]; | ||
| 2179 | if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) && | ||
| 2180 | (key != NULL)) { | ||
| 2181 | status = 0; | ||
| 2182 | |||
| 2183 | value_ptr = &p[note_strings + | ||
| 2184 | get_unaligned_be32( | ||
| 2185 | &p[note_table + (8 * i) + 4])]; | ||
| 2186 | |||
| 2187 | if (value != NULL) | ||
| 2188 | strlcpy(value, value_ptr, length); | ||
| 2189 | |||
| 2190 | } | ||
| 2191 | } | ||
| 2192 | } else { | ||
| 2193 | /* | ||
| 2194 | * We will search for the next note, regardless of the key, | ||
| 2195 | * and return both the value and the key | ||
| 2196 | */ | ||
| 2197 | |||
| 2198 | i = *offset; | ||
| 2199 | |||
| 2200 | if ((i >= 0) && (i < note_count)) { | ||
| 2201 | status = 0; | ||
| 2202 | |||
| 2203 | if (key != NULL) | ||
| 2204 | strlcpy(key, &p[note_strings + | ||
| 2205 | get_unaligned_be32( | ||
| 2206 | &p[note_table + (8 * i)])], | ||
| 2207 | length); | ||
| 2208 | |||
| 2209 | if (value != NULL) | ||
| 2210 | strlcpy(value, &p[note_strings + | ||
| 2211 | get_unaligned_be32( | ||
| 2212 | &p[note_table + (8 * i) + 4])], | ||
| 2213 | length); | ||
| 2214 | |||
| 2215 | *offset = i + 1; | ||
| 2216 | } | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | return status; | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | static int altera_check_crc(u8 *p, s32 program_size) | ||
| 2223 | { | ||
| 2224 | int status = 0; | ||
| 2225 | u16 local_expected = 0, | ||
| 2226 | local_actual = 0, | ||
| 2227 | shift_reg = 0xffff; | ||
| 2228 | int bit, feedback; | ||
| 2229 | u8 databyte; | ||
| 2230 | u32 i; | ||
| 2231 | u32 crc_section = 0L; | ||
| 2232 | u32 first_word = 0L; | ||
| 2233 | int version = 0; | ||
| 2234 | int delta = 0; | ||
| 2235 | |||
| 2236 | if (program_size > 52L) { | ||
| 2237 | first_word = get_unaligned_be32(&p[0]); | ||
| 2238 | version = (first_word & 1L); | ||
| 2239 | delta = version * 8; | ||
| 2240 | |||
| 2241 | crc_section = get_unaligned_be32(&p[32 + delta]); | ||
| 2242 | } | ||
| 2243 | |||
| 2244 | if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) | ||
| 2245 | status = -EIO; | ||
| 2246 | |||
| 2247 | if (crc_section >= program_size) | ||
| 2248 | status = -EIO; | ||
| 2249 | |||
| 2250 | if (status == 0) { | ||
| 2251 | local_expected = (u16)get_unaligned_be16(&p[crc_section]); | ||
| 2252 | |||
| 2253 | for (i = 0; i < crc_section; ++i) { | ||
| 2254 | databyte = p[i]; | ||
| 2255 | for (bit = 0; bit < 8; bit++) { | ||
| 2256 | feedback = (databyte ^ shift_reg) & 0x01; | ||
| 2257 | shift_reg >>= 1; | ||
| 2258 | if (feedback) | ||
| 2259 | shift_reg ^= 0x8408; | ||
| 2260 | |||
| 2261 | databyte >>= 1; | ||
| 2262 | } | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | local_actual = (u16)~shift_reg; | ||
| 2266 | |||
| 2267 | if (local_expected != local_actual) | ||
| 2268 | status = -EILSEQ; | ||
| 2269 | |||
| 2270 | } | ||
| 2271 | |||
| 2272 | if (debug || status) { | ||
| 2273 | switch (status) { | ||
| 2274 | case 0: | ||
| 2275 | printk(KERN_INFO "%s: CRC matched: %04x\n", __func__, | ||
| 2276 | local_actual); | ||
| 2277 | break; | ||
| 2278 | case -EILSEQ: | ||
| 2279 | printk(KERN_ERR "%s: CRC mismatch: expected %04x, " | ||
| 2280 | "actual %04x\n", __func__, local_expected, | ||
| 2281 | local_actual); | ||
| 2282 | break; | ||
| 2283 | case -ENODATA: | ||
| 2284 | printk(KERN_ERR "%s: expected CRC not found, " | ||
| 2285 | "actual CRC = %04x\n", __func__, | ||
| 2286 | local_actual); | ||
| 2287 | break; | ||
| 2288 | case -EIO: | ||
| 2289 | printk(KERN_ERR "%s: error: format isn't " | ||
| 2290 | "recognized.\n", __func__); | ||
| 2291 | break; | ||
| 2292 | default: | ||
| 2293 | printk(KERN_ERR "%s: CRC function returned error " | ||
| 2294 | "code %d\n", __func__, status); | ||
| 2295 | break; | ||
| 2296 | } | ||
| 2297 | } | ||
| 2298 | |||
| 2299 | return status; | ||
| 2300 | } | ||
| 2301 | |||
| 2302 | static int altera_get_file_info(u8 *p, | ||
| 2303 | s32 program_size, | ||
| 2304 | int *format_version, | ||
| 2305 | int *action_count, | ||
| 2306 | int *procedure_count) | ||
| 2307 | { | ||
| 2308 | int status = -EIO; | ||
| 2309 | u32 first_word = 0; | ||
| 2310 | int version = 0; | ||
| 2311 | |||
| 2312 | if (program_size <= 52L) | ||
| 2313 | return status; | ||
| 2314 | |||
| 2315 | first_word = get_unaligned_be32(&p[0]); | ||
| 2316 | |||
| 2317 | if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L)) { | ||
| 2318 | status = 0; | ||
| 2319 | |||
| 2320 | version = (first_word & 1L); | ||
| 2321 | *format_version = version + 1; | ||
| 2322 | |||
| 2323 | if (version > 0) { | ||
| 2324 | *action_count = get_unaligned_be32(&p[48]); | ||
| 2325 | *procedure_count = get_unaligned_be32(&p[52]); | ||
| 2326 | } | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | return status; | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | static int altera_get_act_info(u8 *p, | ||
| 2333 | s32 program_size, | ||
| 2334 | int index, | ||
| 2335 | char **name, | ||
| 2336 | char **description, | ||
| 2337 | struct altera_procinfo **proc_list) | ||
| 2338 | { | ||
| 2339 | int status = -EIO; | ||
| 2340 | struct altera_procinfo *procptr = NULL; | ||
| 2341 | struct altera_procinfo *tmpptr = NULL; | ||
| 2342 | u32 first_word = 0L; | ||
| 2343 | u32 action_table = 0L; | ||
| 2344 | u32 proc_table = 0L; | ||
| 2345 | u32 str_table = 0L; | ||
| 2346 | u32 note_strings = 0L; | ||
| 2347 | u32 action_count = 0L; | ||
| 2348 | u32 proc_count = 0L; | ||
| 2349 | u32 act_name_id = 0L; | ||
| 2350 | u32 act_desc_id = 0L; | ||
| 2351 | u32 act_proc_id = 0L; | ||
| 2352 | u32 act_proc_name = 0L; | ||
| 2353 | u8 act_proc_attribute = 0; | ||
| 2354 | |||
| 2355 | if (program_size <= 52L) | ||
| 2356 | return status; | ||
| 2357 | /* Read header information */ | ||
| 2358 | first_word = get_unaligned_be32(&p[0]); | ||
| 2359 | |||
| 2360 | if (first_word != 0x4A414D01L) | ||
| 2361 | return status; | ||
| 2362 | |||
| 2363 | action_table = get_unaligned_be32(&p[4]); | ||
| 2364 | proc_table = get_unaligned_be32(&p[8]); | ||
| 2365 | str_table = get_unaligned_be32(&p[12]); | ||
| 2366 | note_strings = get_unaligned_be32(&p[16]); | ||
| 2367 | action_count = get_unaligned_be32(&p[48]); | ||
| 2368 | proc_count = get_unaligned_be32(&p[52]); | ||
| 2369 | |||
| 2370 | if (index >= action_count) | ||
| 2371 | return status; | ||
| 2372 | |||
| 2373 | act_name_id = get_unaligned_be32(&p[action_table + (12 * index)]); | ||
| 2374 | act_desc_id = get_unaligned_be32(&p[action_table + (12 * index) + 4]); | ||
| 2375 | act_proc_id = get_unaligned_be32(&p[action_table + (12 * index) + 8]); | ||
| 2376 | |||
| 2377 | *name = &p[str_table + act_name_id]; | ||
| 2378 | |||
| 2379 | if (act_desc_id < (note_strings - str_table)) | ||
| 2380 | *description = &p[str_table + act_desc_id]; | ||
| 2381 | |||
| 2382 | do { | ||
| 2383 | act_proc_name = get_unaligned_be32( | ||
| 2384 | &p[proc_table + (13 * act_proc_id)]); | ||
| 2385 | act_proc_attribute = | ||
| 2386 | (p[proc_table + (13 * act_proc_id) + 8] & 0x03); | ||
| 2387 | |||
| 2388 | procptr = | ||
| 2389 | kzalloc(sizeof(struct altera_procinfo), | ||
| 2390 | GFP_KERNEL); | ||
| 2391 | |||
| 2392 | if (procptr == NULL) | ||
| 2393 | status = -ENOMEM; | ||
| 2394 | else { | ||
| 2395 | procptr->name = &p[str_table + act_proc_name]; | ||
| 2396 | procptr->attrs = act_proc_attribute; | ||
| 2397 | procptr->next = NULL; | ||
| 2398 | |||
| 2399 | /* add record to end of linked list */ | ||
| 2400 | if (*proc_list == NULL) | ||
| 2401 | *proc_list = procptr; | ||
| 2402 | else { | ||
| 2403 | tmpptr = *proc_list; | ||
| 2404 | while (tmpptr->next != NULL) | ||
| 2405 | tmpptr = tmpptr->next; | ||
| 2406 | tmpptr->next = procptr; | ||
| 2407 | } | ||
| 2408 | } | ||
| 2409 | |||
| 2410 | act_proc_id = get_unaligned_be32( | ||
| 2411 | &p[proc_table + (13 * act_proc_id) + 4]); | ||
| 2412 | } while ((act_proc_id != 0) && (act_proc_id < proc_count)); | ||
| 2413 | |||
| 2414 | return status; | ||
| 2415 | } | ||
| 2416 | |||
| 2417 | int altera_init(struct altera_config *config, const struct firmware *fw) | ||
| 2418 | { | ||
| 2419 | struct altera_state *astate = NULL; | ||
| 2420 | struct altera_procinfo *proc_list = NULL; | ||
| 2421 | struct altera_procinfo *procptr = NULL; | ||
| 2422 | char *key = NULL; | ||
| 2423 | char *value = NULL; | ||
| 2424 | char *action_name = NULL; | ||
| 2425 | char *description = NULL; | ||
| 2426 | int exec_result = 0; | ||
| 2427 | int exit_code = 0; | ||
| 2428 | int format_version = 0; | ||
| 2429 | int action_count = 0; | ||
| 2430 | int procedure_count = 0; | ||
| 2431 | int index = 0; | ||
| 2432 | s32 offset = 0L; | ||
| 2433 | s32 error_address = 0L; | ||
| 2434 | int retval = 0; | ||
| 2435 | |||
| 2436 | key = kzalloc(33, GFP_KERNEL); | ||
| 2437 | if (!key) { | ||
| 2438 | retval = -ENOMEM; | ||
| 2439 | goto out; | ||
| 2440 | } | ||
| 2441 | value = kzalloc(257, GFP_KERNEL); | ||
| 2442 | if (!value) { | ||
| 2443 | retval = -ENOMEM; | ||
| 2444 | goto free_key; | ||
| 2445 | } | ||
| 2446 | astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL); | ||
| 2447 | if (!astate) { | ||
| 2448 | retval = -ENOMEM; | ||
| 2449 | goto free_value; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | astate->config = config; | ||
| 2453 | if (!astate->config->jtag_io) { | ||
| 2454 | dprintk(KERN_INFO "%s: using byteblaster!\n", __func__); | ||
| 2455 | astate->config->jtag_io = netup_jtag_io_lpt; | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | altera_check_crc((u8 *)fw->data, fw->size); | ||
| 2459 | |||
| 2460 | if (debug) { | ||
| 2461 | altera_get_file_info((u8 *)fw->data, fw->size, &format_version, | ||
| 2462 | &action_count, &procedure_count); | ||
| 2463 | printk(KERN_INFO "%s: File format is %s ByteCode format\n", | ||
| 2464 | __func__, (format_version == 2) ? "Jam STAPL" : | ||
| 2465 | "pre-standardized Jam 1.1"); | ||
| 2466 | while (altera_get_note((u8 *)fw->data, fw->size, | ||
| 2467 | &offset, key, value, 256) == 0) | ||
| 2468 | printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n", | ||
| 2469 | __func__, key, value); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | if (debug && (format_version == 2) && (action_count > 0)) { | ||
| 2473 | printk(KERN_INFO "%s: Actions available:\n", __func__); | ||
| 2474 | for (index = 0; index < action_count; ++index) { | ||
| 2475 | altera_get_act_info((u8 *)fw->data, fw->size, | ||
| 2476 | index, &action_name, | ||
| 2477 | &description, | ||
| 2478 | &proc_list); | ||
| 2479 | |||
| 2480 | if (description == NULL) | ||
| 2481 | printk(KERN_INFO "%s: %s\n", | ||
| 2482 | __func__, | ||
| 2483 | action_name); | ||
| 2484 | else | ||
| 2485 | printk(KERN_INFO "%s: %s \"%s\"\n", | ||
| 2486 | __func__, | ||
| 2487 | action_name, | ||
| 2488 | description); | ||
| 2489 | |||
| 2490 | procptr = proc_list; | ||
| 2491 | while (procptr != NULL) { | ||
| 2492 | if (procptr->attrs != 0) | ||
| 2493 | printk(KERN_INFO "%s: %s (%s)\n", | ||
| 2494 | __func__, | ||
| 2495 | procptr->name, | ||
| 2496 | (procptr->attrs == 1) ? | ||
| 2497 | "optional" : "recommended"); | ||
| 2498 | |||
| 2499 | proc_list = procptr->next; | ||
| 2500 | kfree(procptr); | ||
| 2501 | procptr = proc_list; | ||
| 2502 | } | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | printk(KERN_INFO "\n"); | ||
| 2506 | } | ||
| 2507 | |||
| 2508 | exec_result = altera_execute(astate, (u8 *)fw->data, fw->size, | ||
| 2509 | &error_address, &exit_code, &format_version); | ||
| 2510 | |||
| 2511 | if (exit_code) | ||
| 2512 | exec_result = -EREMOTEIO; | ||
| 2513 | |||
| 2514 | if ((format_version == 2) && (exec_result == -EINVAL)) { | ||
| 2515 | if (astate->config->action == NULL) | ||
| 2516 | printk(KERN_ERR "%s: error: no action specified for " | ||
| 2517 | "Jam STAPL file.\nprogram terminated.\n", | ||
| 2518 | __func__); | ||
| 2519 | else | ||
| 2520 | printk(KERN_ERR "%s: error: action \"%s\"" | ||
| 2521 | " is not supported " | ||
| 2522 | "for this Jam STAPL file.\n" | ||
| 2523 | "Program terminated.\n", __func__, | ||
| 2524 | astate->config->action); | ||
| 2525 | |||
| 2526 | } else if (exec_result) | ||
| 2527 | printk(KERN_ERR "%s: error %d\n", __func__, exec_result); | ||
| 2528 | |||
| 2529 | kfree(astate); | ||
| 2530 | free_value: | ||
| 2531 | kfree(value); | ||
| 2532 | free_key: | ||
| 2533 | kfree(key); | ||
| 2534 | out: | ||
| 2535 | return retval; | ||
| 2536 | } | ||
| 2537 | EXPORT_SYMBOL(altera_init); | ||
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 769a4e8e10dc..5bb187781074 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
| 17 | #include <linux/atmel-ssc.h> | 17 | #include <linux/atmel-ssc.h> |
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/module.h> | ||
| 19 | 20 | ||
| 20 | /* Serialize access to ssc_list and user count */ | 21 | /* Serialize access to ssc_list and user count */ |
| 21 | static DEFINE_SPINLOCK(user_lock); | 22 | static DEFINE_SPINLOCK(user_lock); |
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c index a844810b50f6..4bcfc3759734 100644 --- a/drivers/misc/atmel_tclib.c +++ b/drivers/misc/atmel_tclib.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| 8 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
| 9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
| 10 | #include <linux/export.h> | ||
| 10 | 11 | ||
| 11 | /* Number of bytes to reserve for the iomem resource */ | 12 | /* Number of bytes to reserve for the iomem resource */ |
| 12 | #define ATMEL_TC_IOMEM_SIZE 256 | 13 | #define ATMEL_TC_IOMEM_SIZE 256 |
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 82fe2d067827..bfeea9ba702e 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/module.h> | ||
| 25 | 26 | ||
| 26 | #define BH1780_REG_CONTROL 0x80 | 27 | #define BH1780_REG_CONTROL 0x80 |
| 27 | #define BH1780_REG_PARTID 0x8A | 28 | #define BH1780_REG_PARTID 0x8A |
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c index 7ce6065dc20e..eb5cd28bc6d8 100644 --- a/drivers/misc/carma/carma-fpga-program.c +++ b/drivers/misc/carma/carma-fpga-program.c | |||
| @@ -945,8 +945,7 @@ static int fpga_of_remove(struct platform_device *op) | |||
| 945 | /* CTL-CPLD Version Register */ | 945 | /* CTL-CPLD Version Register */ |
| 946 | #define CTL_CPLD_VERSION 0x2000 | 946 | #define CTL_CPLD_VERSION 0x2000 |
| 947 | 947 | ||
| 948 | static int fpga_of_probe(struct platform_device *op, | 948 | static int fpga_of_probe(struct platform_device *op) |
| 949 | const struct of_device_id *match) | ||
| 950 | { | 949 | { |
| 951 | struct device_node *of_node = op->dev.of_node; | 950 | struct device_node *of_node = op->dev.of_node; |
| 952 | struct device *this_device; | 951 | struct device *this_device; |
| @@ -1107,7 +1106,7 @@ static struct of_device_id fpga_of_match[] = { | |||
| 1107 | {}, | 1106 | {}, |
| 1108 | }; | 1107 | }; |
| 1109 | 1108 | ||
| 1110 | static struct of_platform_driver fpga_of_driver = { | 1109 | static struct platform_driver fpga_of_driver = { |
| 1111 | .probe = fpga_of_probe, | 1110 | .probe = fpga_of_probe, |
| 1112 | .remove = fpga_of_remove, | 1111 | .remove = fpga_of_remove, |
| 1113 | .driver = { | 1112 | .driver = { |
| @@ -1124,12 +1123,12 @@ static struct of_platform_driver fpga_of_driver = { | |||
| 1124 | static int __init fpga_init(void) | 1123 | static int __init fpga_init(void) |
| 1125 | { | 1124 | { |
| 1126 | led_trigger_register_simple("fpga", &ledtrig_fpga); | 1125 | led_trigger_register_simple("fpga", &ledtrig_fpga); |
| 1127 | return of_register_platform_driver(&fpga_of_driver); | 1126 | return platform_driver_register(&fpga_of_driver); |
| 1128 | } | 1127 | } |
| 1129 | 1128 | ||
| 1130 | static void __exit fpga_exit(void) | 1129 | static void __exit fpga_exit(void) |
| 1131 | { | 1130 | { |
| 1132 | of_unregister_platform_driver(&fpga_of_driver); | 1131 | platform_driver_unregister(&fpga_of_driver); |
| 1133 | led_trigger_unregister_simple(ledtrig_fpga); | 1132 | led_trigger_unregister_simple(ledtrig_fpga); |
| 1134 | } | 1133 | } |
| 1135 | 1134 | ||
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c index 3965821fef17..14e974b2a781 100644 --- a/drivers/misc/carma/carma-fpga.c +++ b/drivers/misc/carma/carma-fpga.c | |||
| @@ -1249,8 +1249,7 @@ static bool dma_filter(struct dma_chan *chan, void *data) | |||
| 1249 | return true; | 1249 | return true; |
| 1250 | } | 1250 | } |
| 1251 | 1251 | ||
| 1252 | static int data_of_probe(struct platform_device *op, | 1252 | static int data_of_probe(struct platform_device *op) |
| 1253 | const struct of_device_id *match) | ||
| 1254 | { | 1253 | { |
| 1255 | struct device_node *of_node = op->dev.of_node; | 1254 | struct device_node *of_node = op->dev.of_node; |
| 1256 | struct device *this_device; | 1255 | struct device *this_device; |
| @@ -1401,7 +1400,7 @@ static struct of_device_id data_of_match[] = { | |||
| 1401 | {}, | 1400 | {}, |
| 1402 | }; | 1401 | }; |
| 1403 | 1402 | ||
| 1404 | static struct of_platform_driver data_of_driver = { | 1403 | static struct platform_driver data_of_driver = { |
| 1405 | .probe = data_of_probe, | 1404 | .probe = data_of_probe, |
| 1406 | .remove = data_of_remove, | 1405 | .remove = data_of_remove, |
| 1407 | .driver = { | 1406 | .driver = { |
| @@ -1417,12 +1416,12 @@ static struct of_platform_driver data_of_driver = { | |||
| 1417 | 1416 | ||
| 1418 | static int __init data_init(void) | 1417 | static int __init data_init(void) |
| 1419 | { | 1418 | { |
| 1420 | return of_register_platform_driver(&data_of_driver); | 1419 | return platform_driver_register(&data_of_driver); |
| 1421 | } | 1420 | } |
| 1422 | 1421 | ||
| 1423 | static void __exit data_exit(void) | 1422 | static void __exit data_exit(void) |
| 1424 | { | 1423 | { |
| 1425 | of_unregister_platform_driver(&data_of_driver); | 1424 | platform_driver_unregister(&data_of_driver); |
| 1426 | } | 1425 | } |
| 1427 | 1426 | ||
| 1428 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | 1427 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); |
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig index 26cf12ca7f50..701edf658970 100644 --- a/drivers/misc/eeprom/Kconfig +++ b/drivers/misc/eeprom/Kconfig | |||
| @@ -85,7 +85,7 @@ config EEPROM_93XX46 | |||
| 85 | 85 | ||
| 86 | config EEPROM_DIGSY_MTC_CFG | 86 | config EEPROM_DIGSY_MTC_CFG |
| 87 | bool "DigsyMTC display configuration EEPROMs device" | 87 | bool "DigsyMTC display configuration EEPROMs device" |
| 88 | depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO | 88 | depends on GPIO_MPC5200 && SPI_GPIO |
| 89 | help | 89 | help |
| 90 | This option enables access to display configuration EEPROMs | 90 | This option enables access to display configuration EEPROMs |
| 91 | on digsy_mtc board. You have to additionally select Microwire | 91 | on digsy_mtc board. You have to additionally select Microwire |
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c index 27dc0d21aafa..f6586d53e1a3 100644 --- a/drivers/misc/fsa9480.c +++ b/drivers/misc/fsa9480.c | |||
| @@ -400,7 +400,8 @@ static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw) | |||
| 400 | return ret; | 400 | return ret; |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | device_init_wakeup(&client->dev, pdata->wakeup); | 403 | if (pdata) |
| 404 | device_init_wakeup(&client->dev, pdata->wakeup); | ||
| 404 | } | 405 | } |
| 405 | 406 | ||
| 406 | return 0; | 407 | return 0; |
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 8cebec5e85ee..3f7ad83ed740 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
| @@ -102,6 +102,7 @@ | |||
| 102 | #include <linux/nmi.h> | 102 | #include <linux/nmi.h> |
| 103 | #include <linux/delay.h> | 103 | #include <linux/delay.h> |
| 104 | #include <linux/kthread.h> | 104 | #include <linux/kthread.h> |
| 105 | #include <linux/module.h> | ||
| 105 | 106 | ||
| 106 | #define v1printk(a...) do { \ | 107 | #define v1printk(a...) do { \ |
| 107 | if (verbose) \ | 108 | if (verbose) \ |
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index b928bc14e97b..29d12a70eb1b 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c | |||
| @@ -163,7 +163,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) | |||
| 163 | int i; | 163 | int i; |
| 164 | 164 | ||
| 165 | if (lis3->blkread) { | 165 | if (lis3->blkread) { |
| 166 | if (lis3_dev.whoami == WAI_12B) { | 166 | if (lis3->whoami == WAI_12B) { |
| 167 | u16 data[3]; | 167 | u16 data[3]; |
| 168 | lis3->blkread(lis3, OUTX_L, 6, (u8 *)data); | 168 | lis3->blkread(lis3, OUTX_L, 6, (u8 *)data); |
| 169 | for (i = 0; i < 3; i++) | 169 | for (i = 0; i < 3; i++) |
| @@ -195,18 +195,30 @@ static int lis3_8_rates[2] = {100, 400}; | |||
| 195 | static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; | 195 | static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; |
| 196 | 196 | ||
| 197 | /* ODR is Output Data Rate */ | 197 | /* ODR is Output Data Rate */ |
| 198 | static int lis3lv02d_get_odr(void) | 198 | static int lis3lv02d_get_odr(struct lis3lv02d *lis3) |
| 199 | { | 199 | { |
| 200 | u8 ctrl; | 200 | u8 ctrl; |
| 201 | int shift; | 201 | int shift; |
| 202 | 202 | ||
| 203 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | 203 | lis3->read(lis3, CTRL_REG1, &ctrl); |
| 204 | ctrl &= lis3_dev.odr_mask; | 204 | ctrl &= lis3->odr_mask; |
| 205 | shift = ffs(lis3_dev.odr_mask) - 1; | 205 | shift = ffs(lis3->odr_mask) - 1; |
| 206 | return lis3_dev.odrs[(ctrl >> shift)]; | 206 | return lis3->odrs[(ctrl >> shift)]; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static int lis3lv02d_set_odr(int rate) | 209 | static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3) |
| 210 | { | ||
| 211 | int div = lis3lv02d_get_odr(lis3); | ||
| 212 | |||
| 213 | if (WARN_ONCE(div == 0, "device returned spurious data")) | ||
| 214 | return -ENXIO; | ||
| 215 | |||
| 216 | /* LIS3 power on delay is quite long */ | ||
| 217 | msleep(lis3->pwron_delay / div); | ||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int lis3lv02d_set_odr(struct lis3lv02d *lis3, int rate) | ||
| 210 | { | 222 | { |
| 211 | u8 ctrl; | 223 | u8 ctrl; |
| 212 | int i, len, shift; | 224 | int i, len, shift; |
| @@ -214,14 +226,14 @@ static int lis3lv02d_set_odr(int rate) | |||
| 214 | if (!rate) | 226 | if (!rate) |
| 215 | return -EINVAL; | 227 | return -EINVAL; |
| 216 | 228 | ||
| 217 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); | 229 | lis3->read(lis3, CTRL_REG1, &ctrl); |
| 218 | ctrl &= ~lis3_dev.odr_mask; | 230 | ctrl &= ~lis3->odr_mask; |
| 219 | len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */ | 231 | len = 1 << hweight_long(lis3->odr_mask); /* # of possible values */ |
| 220 | shift = ffs(lis3_dev.odr_mask) - 1; | 232 | shift = ffs(lis3->odr_mask) - 1; |
| 221 | 233 | ||
| 222 | for (i = 0; i < len; i++) | 234 | for (i = 0; i < len; i++) |
| 223 | if (lis3_dev.odrs[i] == rate) { | 235 | if (lis3->odrs[i] == rate) { |
| 224 | lis3_dev.write(&lis3_dev, CTRL_REG1, | 236 | lis3->write(lis3, CTRL_REG1, |
| 225 | ctrl | (i << shift)); | 237 | ctrl | (i << shift)); |
| 226 | return 0; | 238 | return 0; |
| 227 | } | 239 | } |
| @@ -240,12 +252,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | |||
| 240 | mutex_lock(&lis3->mutex); | 252 | mutex_lock(&lis3->mutex); |
| 241 | 253 | ||
| 242 | irq_cfg = lis3->irq_cfg; | 254 | irq_cfg = lis3->irq_cfg; |
| 243 | if (lis3_dev.whoami == WAI_8B) { | 255 | if (lis3->whoami == WAI_8B) { |
| 244 | lis3->data_ready_count[IRQ_LINE0] = 0; | 256 | lis3->data_ready_count[IRQ_LINE0] = 0; |
| 245 | lis3->data_ready_count[IRQ_LINE1] = 0; | 257 | lis3->data_ready_count[IRQ_LINE1] = 0; |
| 246 | 258 | ||
| 247 | /* Change interrupt cfg to data ready for selftest */ | 259 | /* Change interrupt cfg to data ready for selftest */ |
| 248 | atomic_inc(&lis3_dev.wake_thread); | 260 | atomic_inc(&lis3->wake_thread); |
| 249 | lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY; | 261 | lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY; |
| 250 | lis3->read(lis3, CTRL_REG3, &ctrl_reg_data); | 262 | lis3->read(lis3, CTRL_REG3, &ctrl_reg_data); |
| 251 | lis3->write(lis3, CTRL_REG3, (ctrl_reg_data & | 263 | lis3->write(lis3, CTRL_REG3, (ctrl_reg_data & |
| @@ -253,12 +265,12 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | |||
| 253 | (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); | 265 | (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); |
| 254 | } | 266 | } |
| 255 | 267 | ||
| 256 | if (lis3_dev.whoami == WAI_3DC) { | 268 | if (lis3->whoami == WAI_3DC) { |
| 257 | ctlreg = CTRL_REG4; | 269 | ctlreg = CTRL_REG4; |
| 258 | selftest = CTRL4_ST0; | 270 | selftest = CTRL4_ST0; |
| 259 | } else { | 271 | } else { |
| 260 | ctlreg = CTRL_REG1; | 272 | ctlreg = CTRL_REG1; |
| 261 | if (lis3_dev.whoami == WAI_12B) | 273 | if (lis3->whoami == WAI_12B) |
| 262 | selftest = CTRL1_ST; | 274 | selftest = CTRL1_ST; |
| 263 | else | 275 | else |
| 264 | selftest = CTRL1_STP; | 276 | selftest = CTRL1_STP; |
| @@ -266,7 +278,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | |||
| 266 | 278 | ||
| 267 | lis3->read(lis3, ctlreg, ®); | 279 | lis3->read(lis3, ctlreg, ®); |
| 268 | lis3->write(lis3, ctlreg, (reg | selftest)); | 280 | lis3->write(lis3, ctlreg, (reg | selftest)); |
| 269 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | 281 | ret = lis3lv02d_get_pwron_wait(lis3); |
| 282 | if (ret) | ||
| 283 | goto fail; | ||
| 270 | 284 | ||
| 271 | /* Read directly to avoid axis remap */ | 285 | /* Read directly to avoid axis remap */ |
| 272 | x = lis3->read_data(lis3, OUTX); | 286 | x = lis3->read_data(lis3, OUTX); |
| @@ -275,7 +289,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | |||
| 275 | 289 | ||
| 276 | /* back to normal settings */ | 290 | /* back to normal settings */ |
| 277 | lis3->write(lis3, ctlreg, reg); | 291 | lis3->write(lis3, ctlreg, reg); |
| 278 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | 292 | ret = lis3lv02d_get_pwron_wait(lis3); |
| 293 | if (ret) | ||
| 294 | goto fail; | ||
| 279 | 295 | ||
| 280 | results[0] = x - lis3->read_data(lis3, OUTX); | 296 | results[0] = x - lis3->read_data(lis3, OUTX); |
| 281 | results[1] = y - lis3->read_data(lis3, OUTY); | 297 | results[1] = y - lis3->read_data(lis3, OUTY); |
| @@ -283,9 +299,9 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) | |||
| 283 | 299 | ||
| 284 | ret = 0; | 300 | ret = 0; |
| 285 | 301 | ||
| 286 | if (lis3_dev.whoami == WAI_8B) { | 302 | if (lis3->whoami == WAI_8B) { |
| 287 | /* Restore original interrupt configuration */ | 303 | /* Restore original interrupt configuration */ |
| 288 | atomic_dec(&lis3_dev.wake_thread); | 304 | atomic_dec(&lis3->wake_thread); |
| 289 | lis3->write(lis3, CTRL_REG3, ctrl_reg_data); | 305 | lis3->write(lis3, CTRL_REG3, ctrl_reg_data); |
| 290 | lis3->irq_cfg = irq_cfg; | 306 | lis3->irq_cfg = irq_cfg; |
| 291 | 307 | ||
| @@ -363,8 +379,9 @@ void lis3lv02d_poweroff(struct lis3lv02d *lis3) | |||
| 363 | } | 379 | } |
| 364 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); | 380 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); |
| 365 | 381 | ||
| 366 | void lis3lv02d_poweron(struct lis3lv02d *lis3) | 382 | int lis3lv02d_poweron(struct lis3lv02d *lis3) |
| 367 | { | 383 | { |
| 384 | int err; | ||
| 368 | u8 reg; | 385 | u8 reg; |
| 369 | 386 | ||
| 370 | lis3->init(lis3); | 387 | lis3->init(lis3); |
| @@ -375,42 +392,50 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3) | |||
| 375 | * both have been read. So the value read will always be correct. | 392 | * both have been read. So the value read will always be correct. |
| 376 | * Set BOOT bit to refresh factory tuning values. | 393 | * Set BOOT bit to refresh factory tuning values. |
| 377 | */ | 394 | */ |
| 378 | lis3->read(lis3, CTRL_REG2, ®); | 395 | if (lis3->pdata) { |
| 379 | if (lis3->whoami == WAI_12B) | 396 | lis3->read(lis3, CTRL_REG2, ®); |
| 380 | reg |= CTRL2_BDU | CTRL2_BOOT; | 397 | if (lis3->whoami == WAI_12B) |
| 381 | else | 398 | reg |= CTRL2_BDU | CTRL2_BOOT; |
| 382 | reg |= CTRL2_BOOT_8B; | 399 | else |
| 383 | lis3->write(lis3, CTRL_REG2, reg); | 400 | reg |= CTRL2_BOOT_8B; |
| 401 | lis3->write(lis3, CTRL_REG2, reg); | ||
| 402 | } | ||
| 384 | 403 | ||
| 385 | /* LIS3 power on delay is quite long */ | 404 | err = lis3lv02d_get_pwron_wait(lis3); |
| 386 | msleep(lis3->pwron_delay / lis3lv02d_get_odr()); | 405 | if (err) |
| 406 | return err; | ||
| 387 | 407 | ||
| 388 | if (lis3->reg_ctrl) | 408 | if (lis3->reg_ctrl) |
| 389 | lis3_context_restore(lis3); | 409 | lis3_context_restore(lis3); |
| 410 | |||
| 411 | return 0; | ||
| 390 | } | 412 | } |
| 391 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | 413 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); |
| 392 | 414 | ||
| 393 | 415 | ||
| 394 | static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev) | 416 | static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev) |
| 395 | { | 417 | { |
| 418 | struct lis3lv02d *lis3 = pidev->private; | ||
| 396 | int x, y, z; | 419 | int x, y, z; |
| 397 | 420 | ||
| 398 | mutex_lock(&lis3_dev.mutex); | 421 | mutex_lock(&lis3->mutex); |
| 399 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); | 422 | lis3lv02d_get_xyz(lis3, &x, &y, &z); |
| 400 | input_report_abs(pidev->input, ABS_X, x); | 423 | input_report_abs(pidev->input, ABS_X, x); |
| 401 | input_report_abs(pidev->input, ABS_Y, y); | 424 | input_report_abs(pidev->input, ABS_Y, y); |
| 402 | input_report_abs(pidev->input, ABS_Z, z); | 425 | input_report_abs(pidev->input, ABS_Z, z); |
| 403 | input_sync(pidev->input); | 426 | input_sync(pidev->input); |
| 404 | mutex_unlock(&lis3_dev.mutex); | 427 | mutex_unlock(&lis3->mutex); |
| 405 | } | 428 | } |
| 406 | 429 | ||
| 407 | static void lis3lv02d_joystick_open(struct input_polled_dev *pidev) | 430 | static void lis3lv02d_joystick_open(struct input_polled_dev *pidev) |
| 408 | { | 431 | { |
| 409 | if (lis3_dev.pm_dev) | 432 | struct lis3lv02d *lis3 = pidev->private; |
| 410 | pm_runtime_get_sync(lis3_dev.pm_dev); | 433 | |
| 434 | if (lis3->pm_dev) | ||
| 435 | pm_runtime_get_sync(lis3->pm_dev); | ||
| 411 | 436 | ||
| 412 | if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev) | 437 | if (lis3->pdata && lis3->whoami == WAI_8B && lis3->idev) |
| 413 | atomic_set(&lis3_dev.wake_thread, 1); | 438 | atomic_set(&lis3->wake_thread, 1); |
| 414 | /* | 439 | /* |
| 415 | * Update coordinates for the case where poll interval is 0 and | 440 | * Update coordinates for the case where poll interval is 0 and |
| 416 | * the chip in running purely under interrupt control | 441 | * the chip in running purely under interrupt control |
| @@ -420,14 +445,18 @@ static void lis3lv02d_joystick_open(struct input_polled_dev *pidev) | |||
| 420 | 445 | ||
| 421 | static void lis3lv02d_joystick_close(struct input_polled_dev *pidev) | 446 | static void lis3lv02d_joystick_close(struct input_polled_dev *pidev) |
| 422 | { | 447 | { |
| 423 | atomic_set(&lis3_dev.wake_thread, 0); | 448 | struct lis3lv02d *lis3 = pidev->private; |
| 424 | if (lis3_dev.pm_dev) | 449 | |
| 425 | pm_runtime_put(lis3_dev.pm_dev); | 450 | atomic_set(&lis3->wake_thread, 0); |
| 451 | if (lis3->pm_dev) | ||
| 452 | pm_runtime_put(lis3->pm_dev); | ||
| 426 | } | 453 | } |
| 427 | 454 | ||
| 428 | static irqreturn_t lis302dl_interrupt(int irq, void *dummy) | 455 | static irqreturn_t lis302dl_interrupt(int irq, void *data) |
| 429 | { | 456 | { |
| 430 | if (!test_bit(0, &lis3_dev.misc_opened)) | 457 | struct lis3lv02d *lis3 = data; |
| 458 | |||
| 459 | if (!test_bit(0, &lis3->misc_opened)) | ||
| 431 | goto out; | 460 | goto out; |
| 432 | 461 | ||
| 433 | /* | 462 | /* |
| @@ -435,12 +464,12 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) | |||
| 435 | * the lid is closed. This leads to interrupts as soon as a little move | 464 | * the lid is closed. This leads to interrupts as soon as a little move |
| 436 | * is done. | 465 | * is done. |
| 437 | */ | 466 | */ |
| 438 | atomic_inc(&lis3_dev.count); | 467 | atomic_inc(&lis3->count); |
| 439 | 468 | ||
| 440 | wake_up_interruptible(&lis3_dev.misc_wait); | 469 | wake_up_interruptible(&lis3->misc_wait); |
| 441 | kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); | 470 | kill_fasync(&lis3->async_queue, SIGIO, POLL_IN); |
| 442 | out: | 471 | out: |
| 443 | if (atomic_read(&lis3_dev.wake_thread)) | 472 | if (atomic_read(&lis3->wake_thread)) |
| 444 | return IRQ_WAKE_THREAD; | 473 | return IRQ_WAKE_THREAD; |
| 445 | return IRQ_HANDLED; | 474 | return IRQ_HANDLED; |
| 446 | } | 475 | } |
| @@ -512,28 +541,37 @@ static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data) | |||
| 512 | 541 | ||
| 513 | static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | 542 | static int lis3lv02d_misc_open(struct inode *inode, struct file *file) |
| 514 | { | 543 | { |
| 515 | if (test_and_set_bit(0, &lis3_dev.misc_opened)) | 544 | struct lis3lv02d *lis3 = container_of(file->private_data, |
| 545 | struct lis3lv02d, miscdev); | ||
| 546 | |||
| 547 | if (test_and_set_bit(0, &lis3->misc_opened)) | ||
| 516 | return -EBUSY; /* already open */ | 548 | return -EBUSY; /* already open */ |
| 517 | 549 | ||
| 518 | if (lis3_dev.pm_dev) | 550 | if (lis3->pm_dev) |
| 519 | pm_runtime_get_sync(lis3_dev.pm_dev); | 551 | pm_runtime_get_sync(lis3->pm_dev); |
| 520 | 552 | ||
| 521 | atomic_set(&lis3_dev.count, 0); | 553 | atomic_set(&lis3->count, 0); |
| 522 | return 0; | 554 | return 0; |
| 523 | } | 555 | } |
| 524 | 556 | ||
| 525 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) | 557 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) |
| 526 | { | 558 | { |
| 527 | fasync_helper(-1, file, 0, &lis3_dev.async_queue); | 559 | struct lis3lv02d *lis3 = container_of(file->private_data, |
| 528 | clear_bit(0, &lis3_dev.misc_opened); /* release the device */ | 560 | struct lis3lv02d, miscdev); |
| 529 | if (lis3_dev.pm_dev) | 561 | |
| 530 | pm_runtime_put(lis3_dev.pm_dev); | 562 | fasync_helper(-1, file, 0, &lis3->async_queue); |
| 563 | clear_bit(0, &lis3->misc_opened); /* release the device */ | ||
| 564 | if (lis3->pm_dev) | ||
| 565 | pm_runtime_put(lis3->pm_dev); | ||
| 531 | return 0; | 566 | return 0; |
| 532 | } | 567 | } |
| 533 | 568 | ||
| 534 | static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | 569 | static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, |
| 535 | size_t count, loff_t *pos) | 570 | size_t count, loff_t *pos) |
| 536 | { | 571 | { |
| 572 | struct lis3lv02d *lis3 = container_of(file->private_data, | ||
| 573 | struct lis3lv02d, miscdev); | ||
| 574 | |||
| 537 | DECLARE_WAITQUEUE(wait, current); | 575 | DECLARE_WAITQUEUE(wait, current); |
| 538 | u32 data; | 576 | u32 data; |
| 539 | unsigned char byte_data; | 577 | unsigned char byte_data; |
| @@ -542,10 +580,10 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
| 542 | if (count < 1) | 580 | if (count < 1) |
| 543 | return -EINVAL; | 581 | return -EINVAL; |
| 544 | 582 | ||
| 545 | add_wait_queue(&lis3_dev.misc_wait, &wait); | 583 | add_wait_queue(&lis3->misc_wait, &wait); |
| 546 | while (true) { | 584 | while (true) { |
| 547 | set_current_state(TASK_INTERRUPTIBLE); | 585 | set_current_state(TASK_INTERRUPTIBLE); |
| 548 | data = atomic_xchg(&lis3_dev.count, 0); | 586 | data = atomic_xchg(&lis3->count, 0); |
| 549 | if (data) | 587 | if (data) |
| 550 | break; | 588 | break; |
| 551 | 589 | ||
| @@ -575,22 +613,28 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
| 575 | 613 | ||
| 576 | out: | 614 | out: |
| 577 | __set_current_state(TASK_RUNNING); | 615 | __set_current_state(TASK_RUNNING); |
| 578 | remove_wait_queue(&lis3_dev.misc_wait, &wait); | 616 | remove_wait_queue(&lis3->misc_wait, &wait); |
| 579 | 617 | ||
| 580 | return retval; | 618 | return retval; |
| 581 | } | 619 | } |
| 582 | 620 | ||
| 583 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) | 621 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) |
| 584 | { | 622 | { |
| 585 | poll_wait(file, &lis3_dev.misc_wait, wait); | 623 | struct lis3lv02d *lis3 = container_of(file->private_data, |
| 586 | if (atomic_read(&lis3_dev.count)) | 624 | struct lis3lv02d, miscdev); |
| 625 | |||
| 626 | poll_wait(file, &lis3->misc_wait, wait); | ||
| 627 | if (atomic_read(&lis3->count)) | ||
| 587 | return POLLIN | POLLRDNORM; | 628 | return POLLIN | POLLRDNORM; |
| 588 | return 0; | 629 | return 0; |
| 589 | } | 630 | } |
| 590 | 631 | ||
| 591 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) | 632 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) |
| 592 | { | 633 | { |
| 593 | return fasync_helper(fd, file, on, &lis3_dev.async_queue); | 634 | struct lis3lv02d *lis3 = container_of(file->private_data, |
| 635 | struct lis3lv02d, miscdev); | ||
| 636 | |||
| 637 | return fasync_helper(fd, file, on, &lis3->async_queue); | ||
| 594 | } | 638 | } |
| 595 | 639 | ||
| 596 | static const struct file_operations lis3lv02d_misc_fops = { | 640 | static const struct file_operations lis3lv02d_misc_fops = { |
| @@ -603,85 +647,80 @@ static const struct file_operations lis3lv02d_misc_fops = { | |||
| 603 | .fasync = lis3lv02d_misc_fasync, | 647 | .fasync = lis3lv02d_misc_fasync, |
| 604 | }; | 648 | }; |
| 605 | 649 | ||
| 606 | static struct miscdevice lis3lv02d_misc_device = { | 650 | int lis3lv02d_joystick_enable(struct lis3lv02d *lis3) |
| 607 | .minor = MISC_DYNAMIC_MINOR, | ||
| 608 | .name = "freefall", | ||
| 609 | .fops = &lis3lv02d_misc_fops, | ||
| 610 | }; | ||
| 611 | |||
| 612 | int lis3lv02d_joystick_enable(void) | ||
| 613 | { | 651 | { |
| 614 | struct input_dev *input_dev; | 652 | struct input_dev *input_dev; |
| 615 | int err; | 653 | int err; |
| 616 | int max_val, fuzz, flat; | 654 | int max_val, fuzz, flat; |
| 617 | int btns[] = {BTN_X, BTN_Y, BTN_Z}; | 655 | int btns[] = {BTN_X, BTN_Y, BTN_Z}; |
| 618 | 656 | ||
| 619 | if (lis3_dev.idev) | 657 | if (lis3->idev) |
| 620 | return -EINVAL; | 658 | return -EINVAL; |
| 621 | 659 | ||
| 622 | lis3_dev.idev = input_allocate_polled_device(); | 660 | lis3->idev = input_allocate_polled_device(); |
| 623 | if (!lis3_dev.idev) | 661 | if (!lis3->idev) |
| 624 | return -ENOMEM; | 662 | return -ENOMEM; |
| 625 | 663 | ||
| 626 | lis3_dev.idev->poll = lis3lv02d_joystick_poll; | 664 | lis3->idev->poll = lis3lv02d_joystick_poll; |
| 627 | lis3_dev.idev->open = lis3lv02d_joystick_open; | 665 | lis3->idev->open = lis3lv02d_joystick_open; |
| 628 | lis3_dev.idev->close = lis3lv02d_joystick_close; | 666 | lis3->idev->close = lis3lv02d_joystick_close; |
| 629 | lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL; | 667 | lis3->idev->poll_interval = MDPS_POLL_INTERVAL; |
| 630 | lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN; | 668 | lis3->idev->poll_interval_min = MDPS_POLL_MIN; |
| 631 | lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX; | 669 | lis3->idev->poll_interval_max = MDPS_POLL_MAX; |
| 632 | input_dev = lis3_dev.idev->input; | 670 | lis3->idev->private = lis3; |
| 671 | input_dev = lis3->idev->input; | ||
| 633 | 672 | ||
| 634 | input_dev->name = "ST LIS3LV02DL Accelerometer"; | 673 | input_dev->name = "ST LIS3LV02DL Accelerometer"; |
| 635 | input_dev->phys = DRIVER_NAME "/input0"; | 674 | input_dev->phys = DRIVER_NAME "/input0"; |
| 636 | input_dev->id.bustype = BUS_HOST; | 675 | input_dev->id.bustype = BUS_HOST; |
| 637 | input_dev->id.vendor = 0; | 676 | input_dev->id.vendor = 0; |
| 638 | input_dev->dev.parent = &lis3_dev.pdev->dev; | 677 | input_dev->dev.parent = &lis3->pdev->dev; |
| 639 | 678 | ||
| 640 | set_bit(EV_ABS, input_dev->evbit); | 679 | set_bit(EV_ABS, input_dev->evbit); |
| 641 | max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY; | 680 | max_val = (lis3->mdps_max_val * lis3->scale) / LIS3_ACCURACY; |
| 642 | if (lis3_dev.whoami == WAI_12B) { | 681 | if (lis3->whoami == WAI_12B) { |
| 643 | fuzz = LIS3_DEFAULT_FUZZ_12B; | 682 | fuzz = LIS3_DEFAULT_FUZZ_12B; |
| 644 | flat = LIS3_DEFAULT_FLAT_12B; | 683 | flat = LIS3_DEFAULT_FLAT_12B; |
| 645 | } else { | 684 | } else { |
| 646 | fuzz = LIS3_DEFAULT_FUZZ_8B; | 685 | fuzz = LIS3_DEFAULT_FUZZ_8B; |
| 647 | flat = LIS3_DEFAULT_FLAT_8B; | 686 | flat = LIS3_DEFAULT_FLAT_8B; |
| 648 | } | 687 | } |
| 649 | fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY; | 688 | fuzz = (fuzz * lis3->scale) / LIS3_ACCURACY; |
| 650 | flat = (flat * lis3_dev.scale) / LIS3_ACCURACY; | 689 | flat = (flat * lis3->scale) / LIS3_ACCURACY; |
| 651 | 690 | ||
| 652 | input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat); | 691 | input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat); |
| 653 | input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat); | 692 | input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat); |
| 654 | input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat); | 693 | input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat); |
| 655 | 694 | ||
| 656 | lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns); | 695 | lis3->mapped_btns[0] = lis3lv02d_get_axis(abs(lis3->ac.x), btns); |
| 657 | lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns); | 696 | lis3->mapped_btns[1] = lis3lv02d_get_axis(abs(lis3->ac.y), btns); |
| 658 | lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns); | 697 | lis3->mapped_btns[2] = lis3lv02d_get_axis(abs(lis3->ac.z), btns); |
| 659 | 698 | ||
| 660 | err = input_register_polled_device(lis3_dev.idev); | 699 | err = input_register_polled_device(lis3->idev); |
| 661 | if (err) { | 700 | if (err) { |
| 662 | input_free_polled_device(lis3_dev.idev); | 701 | input_free_polled_device(lis3->idev); |
| 663 | lis3_dev.idev = NULL; | 702 | lis3->idev = NULL; |
| 664 | } | 703 | } |
| 665 | 704 | ||
| 666 | return err; | 705 | return err; |
| 667 | } | 706 | } |
| 668 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable); | 707 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable); |
| 669 | 708 | ||
| 670 | void lis3lv02d_joystick_disable(void) | 709 | void lis3lv02d_joystick_disable(struct lis3lv02d *lis3) |
| 671 | { | 710 | { |
| 672 | if (lis3_dev.irq) | 711 | if (lis3->irq) |
| 673 | free_irq(lis3_dev.irq, &lis3_dev); | 712 | free_irq(lis3->irq, lis3); |
| 674 | if (lis3_dev.pdata && lis3_dev.pdata->irq2) | 713 | if (lis3->pdata && lis3->pdata->irq2) |
| 675 | free_irq(lis3_dev.pdata->irq2, &lis3_dev); | 714 | free_irq(lis3->pdata->irq2, lis3); |
| 676 | 715 | ||
| 677 | if (!lis3_dev.idev) | 716 | if (!lis3->idev) |
| 678 | return; | 717 | return; |
| 679 | 718 | ||
| 680 | if (lis3_dev.irq) | 719 | if (lis3->irq) |
| 681 | misc_deregister(&lis3lv02d_misc_device); | 720 | misc_deregister(&lis3->miscdev); |
| 682 | input_unregister_polled_device(lis3_dev.idev); | 721 | input_unregister_polled_device(lis3->idev); |
| 683 | input_free_polled_device(lis3_dev.idev); | 722 | input_free_polled_device(lis3->idev); |
| 684 | lis3_dev.idev = NULL; | 723 | lis3->idev = NULL; |
| 685 | } | 724 | } |
| 686 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); | 725 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); |
| 687 | 726 | ||
| @@ -706,6 +745,7 @@ static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3) | |||
| 706 | static ssize_t lis3lv02d_selftest_show(struct device *dev, | 745 | static ssize_t lis3lv02d_selftest_show(struct device *dev, |
| 707 | struct device_attribute *attr, char *buf) | 746 | struct device_attribute *attr, char *buf) |
| 708 | { | 747 | { |
| 748 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); | ||
| 709 | s16 values[3]; | 749 | s16 values[3]; |
| 710 | 750 | ||
| 711 | static const char ok[] = "OK"; | 751 | static const char ok[] = "OK"; |
| @@ -713,8 +753,8 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev, | |||
| 713 | static const char irq[] = "FAIL_IRQ"; | 753 | static const char irq[] = "FAIL_IRQ"; |
| 714 | const char *res; | 754 | const char *res; |
| 715 | 755 | ||
| 716 | lis3lv02d_sysfs_poweron(&lis3_dev); | 756 | lis3lv02d_sysfs_poweron(lis3); |
| 717 | switch (lis3lv02d_selftest(&lis3_dev, values)) { | 757 | switch (lis3lv02d_selftest(lis3, values)) { |
| 718 | case SELFTEST_FAIL: | 758 | case SELFTEST_FAIL: |
| 719 | res = fail; | 759 | res = fail; |
| 720 | break; | 760 | break; |
| @@ -733,33 +773,37 @@ static ssize_t lis3lv02d_selftest_show(struct device *dev, | |||
| 733 | static ssize_t lis3lv02d_position_show(struct device *dev, | 773 | static ssize_t lis3lv02d_position_show(struct device *dev, |
| 734 | struct device_attribute *attr, char *buf) | 774 | struct device_attribute *attr, char *buf) |
| 735 | { | 775 | { |
| 776 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); | ||
| 736 | int x, y, z; | 777 | int x, y, z; |
| 737 | 778 | ||
| 738 | lis3lv02d_sysfs_poweron(&lis3_dev); | 779 | lis3lv02d_sysfs_poweron(lis3); |
| 739 | mutex_lock(&lis3_dev.mutex); | 780 | mutex_lock(&lis3->mutex); |
| 740 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); | 781 | lis3lv02d_get_xyz(lis3, &x, &y, &z); |
| 741 | mutex_unlock(&lis3_dev.mutex); | 782 | mutex_unlock(&lis3->mutex); |
| 742 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 783 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
| 743 | } | 784 | } |
| 744 | 785 | ||
| 745 | static ssize_t lis3lv02d_rate_show(struct device *dev, | 786 | static ssize_t lis3lv02d_rate_show(struct device *dev, |
| 746 | struct device_attribute *attr, char *buf) | 787 | struct device_attribute *attr, char *buf) |
| 747 | { | 788 | { |
| 748 | lis3lv02d_sysfs_poweron(&lis3_dev); | 789 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); |
| 749 | return sprintf(buf, "%d\n", lis3lv02d_get_odr()); | 790 | |
| 791 | lis3lv02d_sysfs_poweron(lis3); | ||
| 792 | return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3)); | ||
| 750 | } | 793 | } |
| 751 | 794 | ||
| 752 | static ssize_t lis3lv02d_rate_set(struct device *dev, | 795 | static ssize_t lis3lv02d_rate_set(struct device *dev, |
| 753 | struct device_attribute *attr, const char *buf, | 796 | struct device_attribute *attr, const char *buf, |
| 754 | size_t count) | 797 | size_t count) |
| 755 | { | 798 | { |
| 799 | struct lis3lv02d *lis3 = dev_get_drvdata(dev); | ||
| 756 | unsigned long rate; | 800 | unsigned long rate; |
| 757 | 801 | ||
| 758 | if (strict_strtoul(buf, 0, &rate)) | 802 | if (strict_strtoul(buf, 0, &rate)) |
| 759 | return -EINVAL; | 803 | return -EINVAL; |
| 760 | 804 | ||
| 761 | lis3lv02d_sysfs_poweron(&lis3_dev); | 805 | lis3lv02d_sysfs_poweron(lis3); |
| 762 | if (lis3lv02d_set_odr(rate)) | 806 | if (lis3lv02d_set_odr(lis3, rate)) |
| 763 | return -EINVAL; | 807 | return -EINVAL; |
| 764 | 808 | ||
| 765 | return count; | 809 | return count; |
| @@ -788,6 +832,7 @@ static int lis3lv02d_add_fs(struct lis3lv02d *lis3) | |||
| 788 | if (IS_ERR(lis3->pdev)) | 832 | if (IS_ERR(lis3->pdev)) |
| 789 | return PTR_ERR(lis3->pdev); | 833 | return PTR_ERR(lis3->pdev); |
| 790 | 834 | ||
| 835 | platform_set_drvdata(lis3->pdev, lis3); | ||
| 791 | return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); | 836 | return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); |
| 792 | } | 837 | } |
| 793 | 838 | ||
| @@ -801,7 +846,7 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3) | |||
| 801 | 846 | ||
| 802 | /* SYSFS may have left chip running. Turn off if necessary */ | 847 | /* SYSFS may have left chip running. Turn off if necessary */ |
| 803 | if (!pm_runtime_suspended(lis3->pm_dev)) | 848 | if (!pm_runtime_suspended(lis3->pm_dev)) |
| 804 | lis3lv02d_poweroff(&lis3_dev); | 849 | lis3lv02d_poweroff(lis3); |
| 805 | 850 | ||
| 806 | pm_runtime_disable(lis3->pm_dev); | 851 | pm_runtime_disable(lis3->pm_dev); |
| 807 | pm_runtime_set_suspended(lis3->pm_dev); | 852 | pm_runtime_set_suspended(lis3->pm_dev); |
| @@ -811,24 +856,24 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3) | |||
| 811 | } | 856 | } |
| 812 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | 857 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); |
| 813 | 858 | ||
| 814 | static void lis3lv02d_8b_configure(struct lis3lv02d *dev, | 859 | static void lis3lv02d_8b_configure(struct lis3lv02d *lis3, |
| 815 | struct lis3lv02d_platform_data *p) | 860 | struct lis3lv02d_platform_data *p) |
| 816 | { | 861 | { |
| 817 | int err; | 862 | int err; |
| 818 | int ctrl2 = p->hipass_ctrl; | 863 | int ctrl2 = p->hipass_ctrl; |
| 819 | 864 | ||
| 820 | if (p->click_flags) { | 865 | if (p->click_flags) { |
| 821 | dev->write(dev, CLICK_CFG, p->click_flags); | 866 | lis3->write(lis3, CLICK_CFG, p->click_flags); |
| 822 | dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit); | 867 | lis3->write(lis3, CLICK_TIMELIMIT, p->click_time_limit); |
| 823 | dev->write(dev, CLICK_LATENCY, p->click_latency); | 868 | lis3->write(lis3, CLICK_LATENCY, p->click_latency); |
| 824 | dev->write(dev, CLICK_WINDOW, p->click_window); | 869 | lis3->write(lis3, CLICK_WINDOW, p->click_window); |
| 825 | dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf); | 870 | lis3->write(lis3, CLICK_THSZ, p->click_thresh_z & 0xf); |
| 826 | dev->write(dev, CLICK_THSY_X, | 871 | lis3->write(lis3, CLICK_THSY_X, |
| 827 | (p->click_thresh_x & 0xf) | | 872 | (p->click_thresh_x & 0xf) | |
| 828 | (p->click_thresh_y << 4)); | 873 | (p->click_thresh_y << 4)); |
| 829 | 874 | ||
| 830 | if (dev->idev) { | 875 | if (lis3->idev) { |
| 831 | struct input_dev *input_dev = lis3_dev.idev->input; | 876 | struct input_dev *input_dev = lis3->idev->input; |
| 832 | input_set_capability(input_dev, EV_KEY, BTN_X); | 877 | input_set_capability(input_dev, EV_KEY, BTN_X); |
| 833 | input_set_capability(input_dev, EV_KEY, BTN_Y); | 878 | input_set_capability(input_dev, EV_KEY, BTN_Y); |
| 834 | input_set_capability(input_dev, EV_KEY, BTN_Z); | 879 | input_set_capability(input_dev, EV_KEY, BTN_Z); |
| @@ -836,22 +881,22 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev, | |||
| 836 | } | 881 | } |
| 837 | 882 | ||
| 838 | if (p->wakeup_flags) { | 883 | if (p->wakeup_flags) { |
| 839 | dev->write(dev, FF_WU_CFG_1, p->wakeup_flags); | 884 | lis3->write(lis3, FF_WU_CFG_1, p->wakeup_flags); |
| 840 | dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f); | 885 | lis3->write(lis3, FF_WU_THS_1, p->wakeup_thresh & 0x7f); |
| 841 | /* pdata value + 1 to keep this backward compatible*/ | 886 | /* pdata value + 1 to keep this backward compatible*/ |
| 842 | dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1); | 887 | lis3->write(lis3, FF_WU_DURATION_1, p->duration1 + 1); |
| 843 | ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/ | 888 | ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/ |
| 844 | } | 889 | } |
| 845 | 890 | ||
| 846 | if (p->wakeup_flags2) { | 891 | if (p->wakeup_flags2) { |
| 847 | dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2); | 892 | lis3->write(lis3, FF_WU_CFG_2, p->wakeup_flags2); |
| 848 | dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f); | 893 | lis3->write(lis3, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f); |
| 849 | /* pdata value + 1 to keep this backward compatible*/ | 894 | /* pdata value + 1 to keep this backward compatible*/ |
| 850 | dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1); | 895 | lis3->write(lis3, FF_WU_DURATION_2, p->duration2 + 1); |
| 851 | ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/ | 896 | ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/ |
| 852 | } | 897 | } |
| 853 | /* Configure hipass filters */ | 898 | /* Configure hipass filters */ |
| 854 | dev->write(dev, CTRL_REG2, ctrl2); | 899 | lis3->write(lis3, CTRL_REG2, ctrl2); |
| 855 | 900 | ||
| 856 | if (p->irq2) { | 901 | if (p->irq2) { |
| 857 | err = request_threaded_irq(p->irq2, | 902 | err = request_threaded_irq(p->irq2, |
| @@ -859,7 +904,7 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev, | |||
| 859 | lis302dl_interrupt_thread2_8b, | 904 | lis302dl_interrupt_thread2_8b, |
| 860 | IRQF_TRIGGER_RISING | IRQF_ONESHOT | | 905 | IRQF_TRIGGER_RISING | IRQF_ONESHOT | |
| 861 | (p->irq_flags2 & IRQF_TRIGGER_MASK), | 906 | (p->irq_flags2 & IRQF_TRIGGER_MASK), |
| 862 | DRIVER_NAME, &lis3_dev); | 907 | DRIVER_NAME, lis3); |
| 863 | if (err < 0) | 908 | if (err < 0) |
| 864 | pr_err("No second IRQ. Limited functionality\n"); | 909 | pr_err("No second IRQ. Limited functionality\n"); |
| 865 | } | 910 | } |
| @@ -869,93 +914,97 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev, | |||
| 869 | * Initialise the accelerometer and the various subsystems. | 914 | * Initialise the accelerometer and the various subsystems. |
| 870 | * Should be rather independent of the bus system. | 915 | * Should be rather independent of the bus system. |
| 871 | */ | 916 | */ |
| 872 | int lis3lv02d_init_device(struct lis3lv02d *dev) | 917 | int lis3lv02d_init_device(struct lis3lv02d *lis3) |
| 873 | { | 918 | { |
| 874 | int err; | 919 | int err; |
| 875 | irq_handler_t thread_fn; | 920 | irq_handler_t thread_fn; |
| 876 | int irq_flags = 0; | 921 | int irq_flags = 0; |
| 877 | 922 | ||
| 878 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); | 923 | lis3->whoami = lis3lv02d_read_8(lis3, WHO_AM_I); |
| 879 | 924 | ||
| 880 | switch (dev->whoami) { | 925 | switch (lis3->whoami) { |
| 881 | case WAI_12B: | 926 | case WAI_12B: |
| 882 | pr_info("12 bits sensor found\n"); | 927 | pr_info("12 bits sensor found\n"); |
| 883 | dev->read_data = lis3lv02d_read_12; | 928 | lis3->read_data = lis3lv02d_read_12; |
| 884 | dev->mdps_max_val = 2048; | 929 | lis3->mdps_max_val = 2048; |
| 885 | dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B; | 930 | lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_12B; |
| 886 | dev->odrs = lis3_12_rates; | 931 | lis3->odrs = lis3_12_rates; |
| 887 | dev->odr_mask = CTRL1_DF0 | CTRL1_DF1; | 932 | lis3->odr_mask = CTRL1_DF0 | CTRL1_DF1; |
| 888 | dev->scale = LIS3_SENSITIVITY_12B; | 933 | lis3->scale = LIS3_SENSITIVITY_12B; |
| 889 | dev->regs = lis3_wai12_regs; | 934 | lis3->regs = lis3_wai12_regs; |
| 890 | dev->regs_size = ARRAY_SIZE(lis3_wai12_regs); | 935 | lis3->regs_size = ARRAY_SIZE(lis3_wai12_regs); |
| 891 | break; | 936 | break; |
| 892 | case WAI_8B: | 937 | case WAI_8B: |
| 893 | pr_info("8 bits sensor found\n"); | 938 | pr_info("8 bits sensor found\n"); |
| 894 | dev->read_data = lis3lv02d_read_8; | 939 | lis3->read_data = lis3lv02d_read_8; |
| 895 | dev->mdps_max_val = 128; | 940 | lis3->mdps_max_val = 128; |
| 896 | dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; | 941 | lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; |
| 897 | dev->odrs = lis3_8_rates; | 942 | lis3->odrs = lis3_8_rates; |
| 898 | dev->odr_mask = CTRL1_DR; | 943 | lis3->odr_mask = CTRL1_DR; |
| 899 | dev->scale = LIS3_SENSITIVITY_8B; | 944 | lis3->scale = LIS3_SENSITIVITY_8B; |
| 900 | dev->regs = lis3_wai8_regs; | 945 | lis3->regs = lis3_wai8_regs; |
| 901 | dev->regs_size = ARRAY_SIZE(lis3_wai8_regs); | 946 | lis3->regs_size = ARRAY_SIZE(lis3_wai8_regs); |
| 902 | break; | 947 | break; |
| 903 | case WAI_3DC: | 948 | case WAI_3DC: |
| 904 | pr_info("8 bits 3DC sensor found\n"); | 949 | pr_info("8 bits 3DC sensor found\n"); |
| 905 | dev->read_data = lis3lv02d_read_8; | 950 | lis3->read_data = lis3lv02d_read_8; |
| 906 | dev->mdps_max_val = 128; | 951 | lis3->mdps_max_val = 128; |
| 907 | dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; | 952 | lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B; |
| 908 | dev->odrs = lis3_3dc_rates; | 953 | lis3->odrs = lis3_3dc_rates; |
| 909 | dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; | 954 | lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; |
| 910 | dev->scale = LIS3_SENSITIVITY_8B; | 955 | lis3->scale = LIS3_SENSITIVITY_8B; |
| 911 | break; | 956 | break; |
| 912 | default: | 957 | default: |
| 913 | pr_err("unknown sensor type 0x%X\n", dev->whoami); | 958 | pr_err("unknown sensor type 0x%X\n", lis3->whoami); |
| 914 | return -EINVAL; | 959 | return -EINVAL; |
| 915 | } | 960 | } |
| 916 | 961 | ||
| 917 | dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs), | 962 | lis3->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs), |
| 918 | sizeof(lis3_wai12_regs)), GFP_KERNEL); | 963 | sizeof(lis3_wai12_regs)), GFP_KERNEL); |
| 919 | 964 | ||
| 920 | if (dev->reg_cache == NULL) { | 965 | if (lis3->reg_cache == NULL) { |
| 921 | printk(KERN_ERR DRIVER_NAME "out of memory\n"); | 966 | printk(KERN_ERR DRIVER_NAME "out of memory\n"); |
| 922 | return -ENOMEM; | 967 | return -ENOMEM; |
| 923 | } | 968 | } |
| 924 | 969 | ||
| 925 | mutex_init(&dev->mutex); | 970 | mutex_init(&lis3->mutex); |
| 926 | atomic_set(&dev->wake_thread, 0); | 971 | atomic_set(&lis3->wake_thread, 0); |
| 927 | 972 | ||
| 928 | lis3lv02d_add_fs(dev); | 973 | lis3lv02d_add_fs(lis3); |
| 929 | lis3lv02d_poweron(dev); | 974 | err = lis3lv02d_poweron(lis3); |
| 975 | if (err) { | ||
| 976 | lis3lv02d_remove_fs(lis3); | ||
| 977 | return err; | ||
| 978 | } | ||
| 930 | 979 | ||
| 931 | if (dev->pm_dev) { | 980 | if (lis3->pm_dev) { |
| 932 | pm_runtime_set_active(dev->pm_dev); | 981 | pm_runtime_set_active(lis3->pm_dev); |
| 933 | pm_runtime_enable(dev->pm_dev); | 982 | pm_runtime_enable(lis3->pm_dev); |
| 934 | } | 983 | } |
| 935 | 984 | ||
| 936 | if (lis3lv02d_joystick_enable()) | 985 | if (lis3lv02d_joystick_enable(lis3)) |
| 937 | pr_err("joystick initialization failed\n"); | 986 | pr_err("joystick initialization failed\n"); |
| 938 | 987 | ||
| 939 | /* passing in platform specific data is purely optional and only | 988 | /* passing in platform specific data is purely optional and only |
| 940 | * used by the SPI transport layer at the moment */ | 989 | * used by the SPI transport layer at the moment */ |
| 941 | if (dev->pdata) { | 990 | if (lis3->pdata) { |
| 942 | struct lis3lv02d_platform_data *p = dev->pdata; | 991 | struct lis3lv02d_platform_data *p = lis3->pdata; |
| 943 | 992 | ||
| 944 | if (dev->whoami == WAI_8B) | 993 | if (lis3->whoami == WAI_8B) |
| 945 | lis3lv02d_8b_configure(dev, p); | 994 | lis3lv02d_8b_configure(lis3, p); |
| 946 | 995 | ||
| 947 | irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK; | 996 | irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK; |
| 948 | 997 | ||
| 949 | dev->irq_cfg = p->irq_cfg; | 998 | lis3->irq_cfg = p->irq_cfg; |
| 950 | if (p->irq_cfg) | 999 | if (p->irq_cfg) |
| 951 | dev->write(dev, CTRL_REG3, p->irq_cfg); | 1000 | lis3->write(lis3, CTRL_REG3, p->irq_cfg); |
| 952 | 1001 | ||
| 953 | if (p->default_rate) | 1002 | if (p->default_rate) |
| 954 | lis3lv02d_set_odr(p->default_rate); | 1003 | lis3lv02d_set_odr(lis3, p->default_rate); |
| 955 | } | 1004 | } |
| 956 | 1005 | ||
| 957 | /* bail if we did not get an IRQ from the bus layer */ | 1006 | /* bail if we did not get an IRQ from the bus layer */ |
| 958 | if (!dev->irq) { | 1007 | if (!lis3->irq) { |
| 959 | pr_debug("No IRQ. Disabling /dev/freefall\n"); | 1008 | pr_debug("No IRQ. Disabling /dev/freefall\n"); |
| 960 | goto out; | 1009 | goto out; |
| 961 | } | 1010 | } |
| @@ -971,23 +1020,27 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) | |||
| 971 | * io-apic is not configurable (and generates a warning) but I keep it | 1020 | * io-apic is not configurable (and generates a warning) but I keep it |
| 972 | * in case of support for other hardware. | 1021 | * in case of support for other hardware. |
| 973 | */ | 1022 | */ |
| 974 | if (dev->pdata && dev->whoami == WAI_8B) | 1023 | if (lis3->pdata && lis3->whoami == WAI_8B) |
| 975 | thread_fn = lis302dl_interrupt_thread1_8b; | 1024 | thread_fn = lis302dl_interrupt_thread1_8b; |
| 976 | else | 1025 | else |
| 977 | thread_fn = NULL; | 1026 | thread_fn = NULL; |
| 978 | 1027 | ||
| 979 | err = request_threaded_irq(dev->irq, lis302dl_interrupt, | 1028 | err = request_threaded_irq(lis3->irq, lis302dl_interrupt, |
| 980 | thread_fn, | 1029 | thread_fn, |
| 981 | IRQF_TRIGGER_RISING | IRQF_ONESHOT | | 1030 | IRQF_TRIGGER_RISING | IRQF_ONESHOT | |
| 982 | irq_flags, | 1031 | irq_flags, |
| 983 | DRIVER_NAME, &lis3_dev); | 1032 | DRIVER_NAME, lis3); |
| 984 | 1033 | ||
| 985 | if (err < 0) { | 1034 | if (err < 0) { |
| 986 | pr_err("Cannot get IRQ\n"); | 1035 | pr_err("Cannot get IRQ\n"); |
| 987 | goto out; | 1036 | goto out; |
| 988 | } | 1037 | } |
| 989 | 1038 | ||
| 990 | if (misc_register(&lis3lv02d_misc_device)) | 1039 | lis3->miscdev.minor = MISC_DYNAMIC_MINOR; |
| 1040 | lis3->miscdev.name = "freefall"; | ||
| 1041 | lis3->miscdev.fops = &lis3lv02d_misc_fops; | ||
| 1042 | |||
| 1043 | if (misc_register(&lis3->miscdev)) | ||
| 991 | pr_err("misc_register failed\n"); | 1044 | pr_err("misc_register failed\n"); |
| 992 | out: | 1045 | out: |
| 993 | return 0; | 1046 | return 0; |
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h index a1939589eb2c..2b1482ad3f16 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.h +++ b/drivers/misc/lis3lv02d/lis3lv02d.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/input-polldev.h> | 22 | #include <linux/input-polldev.h> |
| 23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
| 24 | #include <linux/miscdevice.h> | ||
| 24 | 25 | ||
| 25 | /* | 26 | /* |
| 26 | * This driver tries to support the "digital" accelerometer chips from | 27 | * This driver tries to support the "digital" accelerometer chips from |
| @@ -273,6 +274,8 @@ struct lis3lv02d { | |||
| 273 | struct fasync_struct *async_queue; /* queue for the misc device */ | 274 | struct fasync_struct *async_queue; /* queue for the misc device */ |
| 274 | wait_queue_head_t misc_wait; /* Wait queue for the misc device */ | 275 | wait_queue_head_t misc_wait; /* Wait queue for the misc device */ |
| 275 | unsigned long misc_opened; /* bit0: whether the device is open */ | 276 | unsigned long misc_opened; /* bit0: whether the device is open */ |
| 277 | struct miscdevice miscdev; | ||
| 278 | |||
| 276 | int data_ready_count[2]; | 279 | int data_ready_count[2]; |
| 277 | atomic_t wake_thread; | 280 | atomic_t wake_thread; |
| 278 | unsigned char irq_cfg; | 281 | unsigned char irq_cfg; |
| @@ -282,10 +285,10 @@ struct lis3lv02d { | |||
| 282 | }; | 285 | }; |
| 283 | 286 | ||
| 284 | int lis3lv02d_init_device(struct lis3lv02d *lis3); | 287 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |
| 285 | int lis3lv02d_joystick_enable(void); | 288 | int lis3lv02d_joystick_enable(struct lis3lv02d *lis3); |
| 286 | void lis3lv02d_joystick_disable(void); | 289 | void lis3lv02d_joystick_disable(struct lis3lv02d *lis3); |
| 287 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); | 290 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); |
| 288 | void lis3lv02d_poweron(struct lis3lv02d *lis3); | 291 | int lis3lv02d_poweron(struct lis3lv02d *lis3); |
| 289 | int lis3lv02d_remove_fs(struct lis3lv02d *lis3); | 292 | int lis3lv02d_remove_fs(struct lis3lv02d *lis3); |
| 290 | 293 | ||
| 291 | extern struct lis3lv02d lis3_dev; | 294 | extern struct lis3lv02d lis3_dev; |
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c index b20dfb4522d2..c02fea029dcf 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c | |||
| @@ -79,8 +79,7 @@ static int lis3_i2c_init(struct lis3lv02d *lis3) | |||
| 79 | u8 reg; | 79 | u8 reg; |
| 80 | int ret; | 80 | int ret; |
| 81 | 81 | ||
| 82 | if (lis3->reg_ctrl) | 82 | lis3_reg_ctrl(lis3, LIS3_REG_ON); |
| 83 | lis3_reg_ctrl(lis3, LIS3_REG_ON); | ||
| 84 | 83 | ||
| 85 | lis3->read(lis3, WHO_AM_I, ®); | 84 | lis3->read(lis3, WHO_AM_I, ®); |
| 86 | if (reg != lis3->whoami) | 85 | if (reg != lis3->whoami) |
| @@ -106,10 +105,6 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, | |||
| 106 | struct lis3lv02d_platform_data *pdata = client->dev.platform_data; | 105 | struct lis3lv02d_platform_data *pdata = client->dev.platform_data; |
| 107 | 106 | ||
| 108 | if (pdata) { | 107 | if (pdata) { |
| 109 | /* Regulator control is optional */ | ||
| 110 | if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL) | ||
| 111 | lis3_dev.reg_ctrl = lis3_reg_ctrl; | ||
| 112 | |||
| 113 | if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && | 108 | if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && |
| 114 | (i2c_check_functionality(client->adapter, | 109 | (i2c_check_functionality(client->adapter, |
| 115 | I2C_FUNC_SMBUS_I2C_BLOCK))) | 110 | I2C_FUNC_SMBUS_I2C_BLOCK))) |
| @@ -131,15 +126,13 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, | |||
| 131 | goto fail; | 126 | goto fail; |
| 132 | } | 127 | } |
| 133 | 128 | ||
| 134 | if (lis3_dev.reg_ctrl) { | 129 | lis3_dev.regulators[0].supply = reg_vdd; |
| 135 | lis3_dev.regulators[0].supply = reg_vdd; | 130 | lis3_dev.regulators[1].supply = reg_vdd_io; |
| 136 | lis3_dev.regulators[1].supply = reg_vdd_io; | 131 | ret = regulator_bulk_get(&client->dev, |
| 137 | ret = regulator_bulk_get(&client->dev, | 132 | ARRAY_SIZE(lis3_dev.regulators), |
| 138 | ARRAY_SIZE(lis3_dev.regulators), | 133 | lis3_dev.regulators); |
| 139 | lis3_dev.regulators); | 134 | if (ret < 0) |
| 140 | if (ret < 0) | 135 | goto fail; |
| 141 | goto fail; | ||
| 142 | } | ||
| 143 | 136 | ||
| 144 | lis3_dev.pdata = pdata; | 137 | lis3_dev.pdata = pdata; |
| 145 | lis3_dev.bus_priv = client; | 138 | lis3_dev.bus_priv = client; |
| @@ -153,16 +146,19 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client, | |||
| 153 | i2c_set_clientdata(client, &lis3_dev); | 146 | i2c_set_clientdata(client, &lis3_dev); |
| 154 | 147 | ||
| 155 | /* Provide power over the init call */ | 148 | /* Provide power over the init call */ |
| 156 | if (lis3_dev.reg_ctrl) | 149 | lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON); |
| 157 | lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON); | ||
| 158 | 150 | ||
| 159 | ret = lis3lv02d_init_device(&lis3_dev); | 151 | ret = lis3lv02d_init_device(&lis3_dev); |
| 160 | 152 | ||
| 161 | if (lis3_dev.reg_ctrl) | 153 | lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF); |
| 162 | lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF); | ||
| 163 | 154 | ||
| 164 | if (ret == 0) | 155 | if (ret) |
| 165 | return 0; | 156 | goto fail2; |
| 157 | return 0; | ||
| 158 | |||
| 159 | fail2: | ||
| 160 | regulator_bulk_free(ARRAY_SIZE(lis3_dev.regulators), | ||
| 161 | lis3_dev.regulators); | ||
| 166 | fail: | 162 | fail: |
| 167 | if (pdata && pdata->release_resources) | 163 | if (pdata && pdata->release_resources) |
| 168 | pdata->release_resources(); | 164 | pdata->release_resources(); |
| @@ -177,12 +173,11 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client) | |||
| 177 | if (pdata && pdata->release_resources) | 173 | if (pdata && pdata->release_resources) |
| 178 | pdata->release_resources(); | 174 | pdata->release_resources(); |
| 179 | 175 | ||
| 180 | lis3lv02d_joystick_disable(); | 176 | lis3lv02d_joystick_disable(lis3); |
| 181 | lis3lv02d_remove_fs(&lis3_dev); | 177 | lis3lv02d_remove_fs(&lis3_dev); |
| 182 | 178 | ||
| 183 | if (lis3_dev.reg_ctrl) | 179 | regulator_bulk_free(ARRAY_SIZE(lis3->regulators), |
| 184 | regulator_bulk_free(ARRAY_SIZE(lis3->regulators), | 180 | lis3_dev.regulators); |
| 185 | lis3_dev.regulators); | ||
| 186 | return 0; | 181 | return 0; |
| 187 | } | 182 | } |
| 188 | 183 | ||
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c index c1f8a8fbf694..b2c1be12d16f 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c | |||
| @@ -83,7 +83,7 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi) | |||
| 83 | static int __devexit lis302dl_spi_remove(struct spi_device *spi) | 83 | static int __devexit lis302dl_spi_remove(struct spi_device *spi) |
| 84 | { | 84 | { |
| 85 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); | 85 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); |
| 86 | lis3lv02d_joystick_disable(); | 86 | lis3lv02d_joystick_disable(lis3); |
| 87 | lis3lv02d_poweroff(lis3); | 87 | lis3lv02d_poweroff(lis3); |
| 88 | 88 | ||
| 89 | return lis3lv02d_remove_fs(&lis3_dev); | 89 | return lis3lv02d_remove_fs(&lis3_dev); |
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 0fd7e77bee29..10fc4785dba7 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. | 2 | * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
| @@ -41,10 +41,10 @@ | |||
| 41 | #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset | 41 | #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset |
| 42 | (Intel EG20T PCH)*/ | 42 | (Intel EG20T PCH)*/ |
| 43 | #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address | 43 | #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address |
| 44 | offset(OKI SEMICONDUCTOR ML7213) | 44 | offset(LAPIS Semicon ML7213) |
| 45 | */ | 45 | */ |
| 46 | #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address | 46 | #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address |
| 47 | offset(OKI SEMICONDUCTOR ML7223) | 47 | offset(LAPIS Semicon ML7223) |
| 48 | */ | 48 | */ |
| 49 | 49 | ||
| 50 | /* MAX number of INT_REDUCE_CONTROL registers */ | 50 | /* MAX number of INT_REDUCE_CONTROL registers */ |
| @@ -73,6 +73,9 @@ | |||
| 73 | #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */ | 73 | #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB 0x8012 /* for Bus-m */ |
| 74 | #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */ | 74 | #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB 0x8002 /* for Bus-n */ |
| 75 | 75 | ||
| 76 | /* Macros for ML7831 */ | ||
| 77 | #define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801 | ||
| 78 | |||
| 76 | /* SROM ACCESS Macro */ | 79 | /* SROM ACCESS Macro */ |
| 77 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) | 80 | #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1)) |
| 78 | 81 | ||
| @@ -90,6 +93,7 @@ | |||
| 90 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C | 93 | #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C |
| 91 | #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 | 94 | #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 |
| 92 | #define CLKCFG_REG_OFFSET 0x500 | 95 | #define CLKCFG_REG_OFFSET 0x500 |
| 96 | #define FUNCSEL_REG_OFFSET 0x508 | ||
| 93 | 97 | ||
| 94 | #define PCH_PHUB_OROM_SIZE 15360 | 98 | #define PCH_PHUB_OROM_SIZE 15360 |
| 95 | 99 | ||
| @@ -108,11 +112,13 @@ | |||
| 108 | * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val | 112 | * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val |
| 109 | * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val | 113 | * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val |
| 110 | * @clkcfg_reg: CLK CFG register val | 114 | * @clkcfg_reg: CLK CFG register val |
| 115 | * @funcsel_reg: Function select register value | ||
| 111 | * @pch_phub_base_address: Register base address | 116 | * @pch_phub_base_address: Register base address |
| 112 | * @pch_phub_extrom_base_address: external rom base address | 117 | * @pch_phub_extrom_base_address: external rom base address |
| 113 | * @pch_mac_start_address: MAC address area start address | 118 | * @pch_mac_start_address: MAC address area start address |
| 114 | * @pch_opt_rom_start_address: Option ROM start address | 119 | * @pch_opt_rom_start_address: Option ROM start address |
| 115 | * @ioh_type: Save IOH type | 120 | * @ioh_type: Save IOH type |
| 121 | * @pdev: pointer to pci device struct | ||
| 116 | */ | 122 | */ |
| 117 | struct pch_phub_reg { | 123 | struct pch_phub_reg { |
| 118 | u32 phub_id_reg; | 124 | u32 phub_id_reg; |
| @@ -128,11 +134,13 @@ struct pch_phub_reg { | |||
| 128 | u32 intpin_reg_wpermit_reg3; | 134 | u32 intpin_reg_wpermit_reg3; |
| 129 | u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; | 135 | u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; |
| 130 | u32 clkcfg_reg; | 136 | u32 clkcfg_reg; |
| 137 | u32 funcsel_reg; | ||
| 131 | void __iomem *pch_phub_base_address; | 138 | void __iomem *pch_phub_base_address; |
| 132 | void __iomem *pch_phub_extrom_base_address; | 139 | void __iomem *pch_phub_extrom_base_address; |
| 133 | u32 pch_mac_start_address; | 140 | u32 pch_mac_start_address; |
| 134 | u32 pch_opt_rom_start_address; | 141 | u32 pch_opt_rom_start_address; |
| 135 | int ioh_type; | 142 | int ioh_type; |
| 143 | struct pci_dev *pdev; | ||
| 136 | }; | 144 | }; |
| 137 | 145 | ||
| 138 | /* SROM SPEC for MAC address assignment offset */ | 146 | /* SROM SPEC for MAC address assignment offset */ |
| @@ -211,6 +219,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev) | |||
| 211 | __func__, i, chip->int_reduce_control_reg[i]); | 219 | __func__, i, chip->int_reduce_control_reg[i]); |
| 212 | } | 220 | } |
| 213 | chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); | 221 | chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); |
| 222 | if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) | ||
| 223 | chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET); | ||
| 214 | } | 224 | } |
| 215 | 225 | ||
| 216 | /* pch_phub_restore_reg_conf - restore register configuration */ | 226 | /* pch_phub_restore_reg_conf - restore register configuration */ |
| @@ -271,6 +281,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev) | |||
| 271 | } | 281 | } |
| 272 | 282 | ||
| 273 | iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); | 283 | iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); |
| 284 | if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) | ||
| 285 | iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET); | ||
| 274 | } | 286 | } |
| 275 | 287 | ||
| 276 | /** | 288 | /** |
| @@ -464,7 +476,7 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data) | |||
| 464 | int retval; | 476 | int retval; |
| 465 | int i; | 477 | int i; |
| 466 | 478 | ||
| 467 | if (chip->ioh_type == 1) /* EG20T */ | 479 | if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/ |
| 468 | retval = pch_phub_gbe_serial_rom_conf(chip); | 480 | retval = pch_phub_gbe_serial_rom_conf(chip); |
| 469 | else /* ML7223 */ | 481 | else /* ML7223 */ |
| 470 | retval = pch_phub_gbe_serial_rom_conf_mp(chip); | 482 | retval = pch_phub_gbe_serial_rom_conf_mp(chip); |
| @@ -491,6 +503,7 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |||
| 491 | unsigned int orom_size; | 503 | unsigned int orom_size; |
| 492 | int ret; | 504 | int ret; |
| 493 | int err; | 505 | int err; |
| 506 | ssize_t rom_size; | ||
| 494 | 507 | ||
| 495 | struct pch_phub_reg *chip = | 508 | struct pch_phub_reg *chip = |
| 496 | dev_get_drvdata(container_of(kobj, struct device, kobj)); | 509 | dev_get_drvdata(container_of(kobj, struct device, kobj)); |
| @@ -502,6 +515,10 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |||
| 502 | } | 515 | } |
| 503 | 516 | ||
| 504 | /* Get Rom signature */ | 517 | /* Get Rom signature */ |
| 518 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | ||
| 519 | if (!chip->pch_phub_extrom_base_address) | ||
| 520 | goto exrom_map_err; | ||
| 521 | |||
| 505 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address, | 522 | pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address, |
| 506 | (unsigned char *)&rom_signature); | 523 | (unsigned char *)&rom_signature); |
| 507 | rom_signature &= 0xff; | 524 | rom_signature &= 0xff; |
| @@ -532,10 +549,13 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj, | |||
| 532 | goto return_err; | 549 | goto return_err; |
| 533 | } | 550 | } |
| 534 | return_ok: | 551 | return_ok: |
| 552 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 535 | mutex_unlock(&pch_phub_mutex); | 553 | mutex_unlock(&pch_phub_mutex); |
| 536 | return addr_offset; | 554 | return addr_offset; |
| 537 | 555 | ||
| 538 | return_err: | 556 | return_err: |
| 557 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 558 | exrom_map_err: | ||
| 539 | mutex_unlock(&pch_phub_mutex); | 559 | mutex_unlock(&pch_phub_mutex); |
| 540 | return_err_nomutex: | 560 | return_err_nomutex: |
| 541 | return err; | 561 | return err; |
| @@ -548,6 +568,7 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | |||
| 548 | int err; | 568 | int err; |
| 549 | unsigned int addr_offset; | 569 | unsigned int addr_offset; |
| 550 | int ret; | 570 | int ret; |
| 571 | ssize_t rom_size; | ||
| 551 | struct pch_phub_reg *chip = | 572 | struct pch_phub_reg *chip = |
| 552 | dev_get_drvdata(container_of(kobj, struct device, kobj)); | 573 | dev_get_drvdata(container_of(kobj, struct device, kobj)); |
| 553 | 574 | ||
| @@ -564,6 +585,12 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | |||
| 564 | goto return_ok; | 585 | goto return_ok; |
| 565 | } | 586 | } |
| 566 | 587 | ||
| 588 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | ||
| 589 | if (!chip->pch_phub_extrom_base_address) { | ||
| 590 | err = -ENOMEM; | ||
| 591 | goto exrom_map_err; | ||
| 592 | } | ||
| 593 | |||
| 567 | for (addr_offset = 0; addr_offset < count; addr_offset++) { | 594 | for (addr_offset = 0; addr_offset < count; addr_offset++) { |
| 568 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) | 595 | if (PCH_PHUB_OROM_SIZE < off + addr_offset) |
| 569 | goto return_ok; | 596 | goto return_ok; |
| @@ -578,10 +605,14 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj, | |||
| 578 | } | 605 | } |
| 579 | 606 | ||
| 580 | return_ok: | 607 | return_ok: |
| 608 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 581 | mutex_unlock(&pch_phub_mutex); | 609 | mutex_unlock(&pch_phub_mutex); |
| 582 | return addr_offset; | 610 | return addr_offset; |
| 583 | 611 | ||
| 584 | return_err: | 612 | return_err: |
| 613 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 614 | |||
| 615 | exrom_map_err: | ||
| 585 | mutex_unlock(&pch_phub_mutex); | 616 | mutex_unlock(&pch_phub_mutex); |
| 586 | return err; | 617 | return err; |
| 587 | } | 618 | } |
| @@ -591,17 +622,23 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, | |||
| 591 | { | 622 | { |
| 592 | u8 mac[8]; | 623 | u8 mac[8]; |
| 593 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | 624 | struct pch_phub_reg *chip = dev_get_drvdata(dev); |
| 625 | ssize_t rom_size; | ||
| 626 | |||
| 627 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | ||
| 628 | if (!chip->pch_phub_extrom_base_address) | ||
| 629 | return -ENOMEM; | ||
| 594 | 630 | ||
| 595 | pch_phub_read_gbe_mac_addr(chip, mac); | 631 | pch_phub_read_gbe_mac_addr(chip, mac); |
| 632 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 596 | 633 | ||
| 597 | return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", | 634 | return sprintf(buf, "%pM\n", mac); |
| 598 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); | ||
| 599 | } | 635 | } |
| 600 | 636 | ||
| 601 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, | 637 | static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, |
| 602 | const char *buf, size_t count) | 638 | const char *buf, size_t count) |
| 603 | { | 639 | { |
| 604 | u8 mac[6]; | 640 | u8 mac[6]; |
| 641 | ssize_t rom_size; | ||
| 605 | struct pch_phub_reg *chip = dev_get_drvdata(dev); | 642 | struct pch_phub_reg *chip = dev_get_drvdata(dev); |
| 606 | 643 | ||
| 607 | if (count != 18) | 644 | if (count != 18) |
| @@ -611,7 +648,12 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, | |||
| 611 | (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3], | 648 | (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3], |
| 612 | (u32 *)&mac[4], (u32 *)&mac[5]); | 649 | (u32 *)&mac[4], (u32 *)&mac[5]); |
| 613 | 650 | ||
| 651 | chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size); | ||
| 652 | if (!chip->pch_phub_extrom_base_address) | ||
| 653 | return -ENOMEM; | ||
| 654 | |||
| 614 | pch_phub_write_gbe_mac_addr(chip, mac); | 655 | pch_phub_write_gbe_mac_addr(chip, mac); |
| 656 | pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address); | ||
| 615 | 657 | ||
| 616 | return count; | 658 | return count; |
| 617 | } | 659 | } |
| @@ -634,7 +676,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
| 634 | int retval; | 676 | int retval; |
| 635 | 677 | ||
| 636 | int ret; | 678 | int ret; |
| 637 | ssize_t rom_size; | ||
| 638 | struct pch_phub_reg *chip; | 679 | struct pch_phub_reg *chip; |
| 639 | 680 | ||
| 640 | chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL); | 681 | chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL); |
| @@ -671,19 +712,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
| 671 | "in pch_phub_base_address variable is %p\n", __func__, | 712 | "in pch_phub_base_address variable is %p\n", __func__, |
| 672 | chip->pch_phub_base_address); | 713 | chip->pch_phub_base_address); |
| 673 | 714 | ||
| 674 | if (id->driver_data != 3) { | 715 | chip->pdev = pdev; /* Save pci device struct */ |
| 675 | chip->pch_phub_extrom_base_address =\ | ||
| 676 | pci_map_rom(pdev, &rom_size); | ||
| 677 | if (chip->pch_phub_extrom_base_address == 0) { | ||
| 678 | dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__); | ||
| 679 | ret = -ENOMEM; | ||
| 680 | goto err_pci_map; | ||
| 681 | } | ||
| 682 | dev_dbg(&pdev->dev, "%s : " | ||
| 683 | "pci_map_rom SUCCESS and value in " | ||
| 684 | "pch_phub_extrom_base_address variable is %p\n", | ||
| 685 | __func__, chip->pch_phub_extrom_base_address); | ||
| 686 | } | ||
| 687 | 716 | ||
| 688 | if (id->driver_data == 1) { /* EG20T PCH */ | 717 | if (id->driver_data == 1) { /* EG20T PCH */ |
| 689 | const char *board_name; | 718 | const char *board_name; |
| @@ -757,6 +786,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, | |||
| 757 | chip->pch_opt_rom_start_address =\ | 786 | chip->pch_opt_rom_start_address =\ |
| 758 | PCH_PHUB_ROM_START_ADDR_ML7223; | 787 | PCH_PHUB_ROM_START_ADDR_ML7223; |
| 759 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; | 788 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223; |
| 789 | } else if (id->driver_data == 5) { /* ML7831 */ | ||
| 790 | retval = sysfs_create_file(&pdev->dev.kobj, | ||
| 791 | &dev_attr_pch_mac.attr); | ||
| 792 | if (retval) | ||
| 793 | goto err_sysfs_create; | ||
| 794 | |||
| 795 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr); | ||
| 796 | if (retval) | ||
| 797 | goto exit_bin_attr; | ||
| 798 | |||
| 799 | /* set the prefech value */ | ||
| 800 | iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14); | ||
| 801 | /* set the interrupt delay value */ | ||
| 802 | iowrite32(0x25, chip->pch_phub_base_address + 0x44); | ||
| 803 | chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T; | ||
| 804 | chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T; | ||
| 760 | } | 805 | } |
| 761 | 806 | ||
| 762 | chip->ioh_type = id->driver_data; | 807 | chip->ioh_type = id->driver_data; |
| @@ -767,8 +812,6 @@ exit_bin_attr: | |||
| 767 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | 812 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); |
| 768 | 813 | ||
| 769 | err_sysfs_create: | 814 | err_sysfs_create: |
| 770 | pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address); | ||
| 771 | err_pci_map: | ||
| 772 | pci_iounmap(pdev, chip->pch_phub_base_address); | 815 | pci_iounmap(pdev, chip->pch_phub_base_address); |
| 773 | err_pci_iomap: | 816 | err_pci_iomap: |
| 774 | pci_release_regions(pdev); | 817 | pci_release_regions(pdev); |
| @@ -786,7 +829,6 @@ static void __devexit pch_phub_remove(struct pci_dev *pdev) | |||
| 786 | 829 | ||
| 787 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); | 830 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr); |
| 788 | sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr); | 831 | sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr); |
| 789 | pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address); | ||
| 790 | pci_iounmap(pdev, chip->pch_phub_base_address); | 832 | pci_iounmap(pdev, chip->pch_phub_base_address); |
| 791 | pci_release_regions(pdev); | 833 | pci_release_regions(pdev); |
| 792 | pci_disable_device(pdev); | 834 | pci_disable_device(pdev); |
| @@ -841,6 +883,7 @@ static struct pci_device_id pch_phub_pcidev_id[] = { | |||
| 841 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, | 883 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2, }, |
| 842 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, | 884 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3, }, |
| 843 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, | 885 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4, }, |
| 886 | { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5, }, | ||
| 844 | { } | 887 | { } |
| 845 | }; | 888 | }; |
| 846 | MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); | 889 | MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id); |
| @@ -867,5 +910,5 @@ static void __exit pch_phub_pci_exit(void) | |||
| 867 | module_init(pch_phub_pci_init); | 910 | module_init(pch_phub_pci_init); |
| 868 | module_exit(pch_phub_pci_exit); | 911 | module_exit(pch_phub_pci_exit); |
| 869 | 912 | ||
| 870 | MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"); | 913 | MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB"); |
| 871 | MODULE_LICENSE("GPL"); | 914 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 06df1877ad0f..0b56e3f43573 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c | |||
| @@ -165,6 +165,11 @@ static void pti_write_to_aperture(struct pti_masterchannel *mc, | |||
| 165 | static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc, | 165 | static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc, |
| 166 | const char *thread_name) | 166 | const char *thread_name) |
| 167 | { | 167 | { |
| 168 | /* | ||
| 169 | * Since we access the comm member in current's task_struct, we only | ||
| 170 | * need to be as large as what 'comm' in that structure is. | ||
| 171 | */ | ||
| 172 | char comm[TASK_COMM_LEN]; | ||
| 168 | struct pti_masterchannel mccontrol = {.master = CONTROL_ID, | 173 | struct pti_masterchannel mccontrol = {.master = CONTROL_ID, |
| 169 | .channel = 0}; | 174 | .channel = 0}; |
| 170 | const char *thread_name_p; | 175 | const char *thread_name_p; |
| @@ -172,13 +177,6 @@ static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc, | |||
| 172 | u8 control_frame[CONTROL_FRAME_LEN]; | 177 | u8 control_frame[CONTROL_FRAME_LEN]; |
| 173 | 178 | ||
| 174 | if (!thread_name) { | 179 | if (!thread_name) { |
| 175 | /* | ||
| 176 | * Since we access the comm member in current's task_struct, | ||
| 177 | * we only need to be as large as what 'comm' in that | ||
| 178 | * structure is. | ||
| 179 | */ | ||
| 180 | char comm[TASK_COMM_LEN]; | ||
| 181 | |||
| 182 | if (!in_interrupt()) | 180 | if (!in_interrupt()) |
| 183 | get_task_comm(comm, current); | 181 | get_task_comm(comm, current); |
| 184 | else | 182 | else |
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index 9e9bddaa95ae..913de07e577c 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| 32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
| 33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
| 34 | #include <linux/export.h> | ||
| 34 | #include <asm/io_apic.h> | 35 | #include <asm/io_apic.h> |
| 35 | #include "gru.h" | 36 | #include "gru.h" |
| 36 | #include "grulib.h" | 37 | #include "grulib.h" |
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c index cfbddbef11de..43d073bc1d9c 100644 --- a/drivers/misc/spear13xx_pcie_gadget.c +++ b/drivers/misc/spear13xx_pcie_gadget.c | |||
| @@ -903,6 +903,6 @@ static void __exit spear_pcie_gadget_exit(void) | |||
| 903 | } | 903 | } |
| 904 | module_exit(spear_pcie_gadget_exit); | 904 | module_exit(spear_pcie_gadget_exit); |
| 905 | 905 | ||
| 906 | MODULE_ALIAS("pcie-gadget-spear"); | 906 | MODULE_ALIAS("platform:pcie-gadget-spear"); |
| 907 | MODULE_AUTHOR("Pratyush Anand"); | 907 | MODULE_AUTHOR("Pratyush Anand"); |
| 908 | MODULE_LICENSE("GPL"); | 908 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 3a3580566dfc..43ef8d162f2d 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #include <linux/skbuff.h> | 36 | #include <linux/skbuff.h> |
| 37 | #include <linux/ti_wilink_st.h> | 37 | #include <linux/ti_wilink_st.h> |
| 38 | #include <linux/module.h> | ||
| 38 | 39 | ||
| 39 | 40 | ||
| 40 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ | 41 | #define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ |
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index a6ef18259da0..ba2479022670 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/tifm.h> | 12 | #include <linux/tifm.h> |
| 13 | #include <linux/dma-mapping.h> | 13 | #include <linux/dma-mapping.h> |
| 14 | #include <linux/module.h> | ||
| 14 | 15 | ||
| 15 | #define DRIVER_NAME "tifm_7xx1" | 16 | #define DRIVER_NAME "tifm_7xx1" |
| 16 | #define DRIVER_VERSION "0.8" | 17 | #define DRIVER_VERSION "0.8" |
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 44d4475a09dd..0bd5349b0422 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/idr.h> | 15 | #include <linux/idr.h> |
| 16 | #include <linux/module.h> | ||
| 16 | 17 | ||
| 17 | #define DRIVER_NAME "tifm_core" | 18 | #define DRIVER_NAME "tifm_core" |
| 18 | #define DRIVER_VERSION "0.8" | 19 | #define DRIVER_VERSION "0.8" |
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index 053d36caf955..cd41d403c9df 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c | |||
| @@ -151,7 +151,7 @@ MODULE_LICENSE("GPL"); | |||
| 151 | struct vmballoon_stats { | 151 | struct vmballoon_stats { |
| 152 | unsigned int timer; | 152 | unsigned int timer; |
| 153 | 153 | ||
| 154 | /* allocation statustics */ | 154 | /* allocation statistics */ |
| 155 | unsigned int alloc; | 155 | unsigned int alloc; |
| 156 | unsigned int alloc_fail; | 156 | unsigned int alloc_fail; |
| 157 | unsigned int sleep_alloc; | 157 | unsigned int sleep_alloc; |
| @@ -412,6 +412,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep) | |||
| 412 | gfp_t flags; | 412 | gfp_t flags; |
| 413 | unsigned int hv_status; | 413 | unsigned int hv_status; |
| 414 | bool locked = false; | 414 | bool locked = false; |
| 415 | flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP; | ||
| 415 | 416 | ||
| 416 | do { | 417 | do { |
| 417 | if (!can_sleep) | 418 | if (!can_sleep) |
| @@ -419,7 +420,6 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep) | |||
| 419 | else | 420 | else |
| 420 | STATS_INC(b->stats.sleep_alloc); | 421 | STATS_INC(b->stats.sleep_alloc); |
| 421 | 422 | ||
| 422 | flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP; | ||
| 423 | page = alloc_page(flags); | 423 | page = alloc_page(flags); |
| 424 | if (!page) { | 424 | if (!page) { |
| 425 | if (!can_sleep) | 425 | if (!can_sleep) |
