char/misc driver merge for 3.7-rc1
Here is the "big" char/misc driver tree update for the 3.7-rc1 merge window. Nothing major, just a number of driver updates and fixes, all of which have been in the linux-next releases for a while now either in my tree, or in Andrew's (the lis3l driver changes came from his tree last week). Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iEYEABECAAYFAlBp3pcACgkQMUfUDdst+ymLswCcDYG9RkRcEdYwT5bOm1zM4IVl WM0AoLKfC86g6xe4MdS7zROJn7ep/9qu =zAHk -----END PGP SIGNATURE----- Merge tag 'char-misc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc driver merge from Greg Kroah-Hartman: "Here is the "big" char/misc driver tree update for the 3.7-rc1 merge window. Nothing major, just a number of driver updates and fixes, all of which have been in the linux-next releases for a while now either in my tree, or in Andrew's (the lis3l driver changes came from his tree last week). Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'char-misc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (52 commits) drivers/misc/lis3lv02d/lis3lv02d_i2c.c: add lis3lv02d device tree init drivers/misc/lis3lv02d/lis3lv02d_spi.c: add lis3lv02d device tree init drivers/misc/lis3lv02d: remove lis3lv02d driver DT init drivers/misc/lis3lv02d/lis3lv02d_spi.c: add DT matching table passthru code drivers/misc/lis3lv02d: add generic DT matching code lis3lv02d: fix some comments specific to lis331dlh driver MISC: hpilo, remove pci_disable_device pcmcia: synclink_cs: fix potential tty NULL dereference drivers/char/mmtimer.c: Remove useless kfree drivers/char: removes unnecessary semicolon char/misc: remove CONFIG_EXPERIMENTAL dependencies mei: don't print buffer as a string mei: struct mei_message_data doesn't have to be packed mei: add error messages for open count errors misc: use module_spi_driver tifm: use module_pci_driver misc/at25, dt: Improve at25 SPI eeprom device tree bindings. mei: add lynx point pci device ids mei: fix max number of open handles mei: rename struct pci_dev *mei_device to mei_pdev ...
This commit is contained in:
commit
3aebd34b12
|
@ -1,21 +1,35 @@
|
|||
Atmel AT25 eeprom
|
||||
EEPROMs (SPI) compatible with Atmel at25.
|
||||
|
||||
Required properties:
|
||||
- compatible : "atmel,at25".
|
||||
- reg : chip select number
|
||||
- spi-max-frequency : max spi frequency to use
|
||||
- pagesize : size of the eeprom page
|
||||
- size : total eeprom size in bytes
|
||||
- address-width : number of address bits (one of 8, 16, or 24)
|
||||
|
||||
Optional properties:
|
||||
- spi-cpha : SPI shifted clock phase, as per spi-bus bindings.
|
||||
- spi-cpol : SPI inverse clock polarity, as per spi-bus bindings.
|
||||
- read-only : this parameter-less property disables writes to the eeprom
|
||||
|
||||
Obsolete legacy properties are can be used in place of "size", "pagesize",
|
||||
"address-width", and "read-only":
|
||||
- at25,byte-len : total eeprom size in bytes
|
||||
- at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h
|
||||
- at25,page-size : size of the eeprom page
|
||||
|
||||
Examples:
|
||||
Additional compatible properties are also allowed.
|
||||
|
||||
Example:
|
||||
at25@0 {
|
||||
compatible = "atmel,at25";
|
||||
compatible = "atmel,at25", "st,m95256";
|
||||
reg = <0>
|
||||
spi-max-frequency = <5000000>;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
|
||||
at25,byte-len = <0x8000>;
|
||||
at25,addr-mode = <2>;
|
||||
at25,page-size = <64>;
|
||||
pagesize = <64>;
|
||||
size = <32768>;
|
||||
address-width = <16>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
LIS302 accelerometer devicetree bindings
|
||||
|
||||
This device is matched via its bus drivers, and has a number of properties
|
||||
that apply in on the generic device (independent from the bus).
|
||||
|
||||
|
||||
Required properties for the SPI bindings:
|
||||
- compatible: should be set to "st,lis3lv02d_spi"
|
||||
- reg: the chipselect index
|
||||
- spi-max-frequency: maximal bus speed, should be set to 1000000 unless
|
||||
constrained by external circuitry
|
||||
- interrupts: the interrupt generated by the device
|
||||
|
||||
Required properties for the I2C bindings:
|
||||
- compatible: should be set to "st,lis3lv02d"
|
||||
- reg: i2c slave address
|
||||
- Vdd-supply: The input supply for Vdd
|
||||
- Vdd_IO-supply: The input supply for Vdd_IO
|
||||
|
||||
|
||||
Optional properties for all bus drivers:
|
||||
|
||||
- st,click-single-{x,y,z}: if present, tells the device to issue an
|
||||
interrupt on single click events on the
|
||||
x/y/z axis.
|
||||
- st,click-double-{x,y,z}: if present, tells the device to issue an
|
||||
interrupt on double click events on the
|
||||
x/y/z axis.
|
||||
- st,click-thresh-{x,y,z}: set the x/y/z axis threshold
|
||||
- st,click-click-time-limit: click time limit, from 0 to 127.5msec
|
||||
with step of 0.5 msec
|
||||
- st,click-latency: click latency, from 0 to 255 msec with
|
||||
step of 1 msec.
|
||||
- st,click-window: click window, from 0 to 255 msec with
|
||||
step of 1 msec.
|
||||
- st,irq{1,2}-disable: disable IRQ 1/2
|
||||
- st,irq{1,2}-ff-wu-1: raise IRQ 1/2 on FF_WU_1 condition
|
||||
- st,irq{1,2}-ff-wu-2: raise IRQ 1/2 on FF_WU_2 condition
|
||||
- st,irq{1,2}-data-ready: raise IRQ 1/2 on data ready contition
|
||||
- st,irq{1,2}-click: raise IRQ 1/2 on click condition
|
||||
- st,irq-open-drain: consider IRQ lines open-drain
|
||||
- st,irq-active-low: make IRQ lines active low
|
||||
- st,wu-duration-1: duration register for Free-Fall/Wake-Up
|
||||
interrupt 1
|
||||
- st,wu-duration-2: duration register for Free-Fall/Wake-Up
|
||||
interrupt 2
|
||||
- st,wakeup-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for
|
||||
upper/lower limit
|
||||
- st,highpass-cutoff-hz=: 1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of
|
||||
highpass cut-off frequency
|
||||
- st,hipass{1,2}-disable: disable highpass 1/2.
|
||||
- st,default-rate=: set the default rate
|
||||
- st,axis-{x,y,z}=: set the axis to map to the three coordinates
|
||||
- st,{min,max}-limit-{x,y,z} set the min/max limits for x/y/z axis
|
||||
(used by self-test)
|
||||
|
||||
|
||||
Example for a SPI device node:
|
||||
|
||||
lis302@0 {
|
||||
compatible = "st,lis302dl-spi";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <104 0>;
|
||||
|
||||
st,click-single-x;
|
||||
st,click-single-y;
|
||||
st,click-single-z;
|
||||
st,click-thresh-x = <10>;
|
||||
st,click-thresh-y = <10>;
|
||||
st,click-thresh-z = <10>;
|
||||
st,irq1-click;
|
||||
st,irq2-click;
|
||||
st,wakeup-x-lo;
|
||||
st,wakeup-x-hi;
|
||||
st,wakeup-y-lo;
|
||||
st,wakeup-y-hi;
|
||||
st,wakeup-z-lo;
|
||||
st,wakeup-z-hi;
|
||||
};
|
||||
|
||||
Example for a I2C device node:
|
||||
|
||||
lis331dlh: lis331dlh@18 {
|
||||
compatible = "st,lis331dlh", "st,lis3lv02d";
|
||||
reg = <0x18>;
|
||||
Vdd-supply = <&lis3_reg>;
|
||||
Vdd_IO-supply = <&lis3_reg>;
|
||||
|
||||
st,click-single-x;
|
||||
st,click-single-y;
|
||||
st,click-single-z;
|
||||
st,click-thresh-x = <10>;
|
||||
st,click-thresh-y = <10>;
|
||||
st,click-thresh-z = <10>;
|
||||
st,irq1-click;
|
||||
st,irq2-click;
|
||||
st,wakeup-x-lo;
|
||||
st,wakeup-x-hi;
|
||||
st,wakeup-y-lo;
|
||||
st,wakeup-y-hi;
|
||||
st,wakeup-z-lo;
|
||||
st,wakeup-z-hi;
|
||||
st,min-limit-x = <120>;
|
||||
st,min-limit-y = <120>;
|
||||
st,min-limit-z = <140>;
|
||||
st,max-limit-x = <550>;
|
||||
st,max-limit-y = <550>;
|
||||
st,max-limit-z = <750>;
|
||||
};
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
w1-gpio devicetree bindings
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "w1-gpio"
|
||||
- gpios: one or two GPIO specs:
|
||||
- the first one is used as data I/O pin
|
||||
- the second one is optional. If specified, it is used as
|
||||
enable pin for an external pin pullup.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- linux,open-drain: if specified, the data pin is considered in
|
||||
open-drain mode.
|
||||
|
||||
Examples:
|
||||
|
||||
onewire@0 {
|
||||
compatible = "w1-gpio";
|
||||
gpios = <&gpio 126 0>, <&gpio 105 0>;
|
||||
};
|
||||
|
|
@ -4,7 +4,8 @@ Kernel driver lis3lv02d
|
|||
Supported chips:
|
||||
|
||||
* STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
|
||||
* STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
|
||||
* STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and
|
||||
LIS331DLH (16 bits)
|
||||
|
||||
Authors:
|
||||
Yan Burman <burman.yan@gmail.com>
|
||||
|
|
|
@ -418,8 +418,8 @@ config APPLICOM
|
|||
If unsure, say N.
|
||||
|
||||
config SONYPI
|
||||
tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT
|
||||
tristate "Sony Vaio Programmable I/O Control Device support"
|
||||
depends on X86 && PCI && INPUT && !64BIT
|
||||
---help---
|
||||
This driver enables access to the Sony Programmable I/O Control
|
||||
Device which can be found in many (all ?) Sony Vaio laptops.
|
||||
|
@ -566,7 +566,7 @@ source "drivers/char/tpm/Kconfig"
|
|||
|
||||
config TELCLOCK
|
||||
tristate "Telecom clock driver for ATCA SBC"
|
||||
depends on EXPERIMENTAL && X86
|
||||
depends on X86
|
||||
default n
|
||||
help
|
||||
The telecom clock device is specific to the MPCBL0010 and MPCBL0050
|
||||
|
|
|
@ -826,7 +826,7 @@ static int __init mmtimer_init(void)
|
|||
|
||||
/* Allocate list of node ptrs to mmtimer_t's */
|
||||
timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL);
|
||||
if (timers == NULL) {
|
||||
if (!timers) {
|
||||
printk(KERN_ERR "%s: failed to allocate memory for device\n",
|
||||
MMTIMER_NAME);
|
||||
goto out3;
|
||||
|
@ -848,7 +848,6 @@ static int __init mmtimer_init(void)
|
|||
return 0;
|
||||
|
||||
out3:
|
||||
kfree(timers);
|
||||
misc_deregister(&mmtimer_miscdev);
|
||||
out2:
|
||||
free_irq(SGI_MMTIMER_VECTOR, NULL);
|
||||
|
|
|
@ -93,9 +93,9 @@ int button_del_callback (void (*callback) (void))
|
|||
button_callback_list [lp].count = 0;
|
||||
callback_count--;
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
lp--;
|
||||
};
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -891,6 +891,14 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
|
|||
int work = 0;
|
||||
struct mgsl_icount *icount = &info->icount;
|
||||
|
||||
if (!tty) {
|
||||
/* tty is not available anymore */
|
||||
issue_command(info, CHA, CMD_RXRESET);
|
||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
||||
printk("%s(%d):rx_ready_async(tty=NULL)\n",__FILE__,__LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcd) {
|
||||
/* early termination, get FIFO count from RBCL register */
|
||||
fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);
|
||||
|
@ -980,7 +988,7 @@ static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
if (tty->stopped || tty->hw_stopped) {
|
||||
if (tty && (tty->stopped || tty->hw_stopped)) {
|
||||
tx_stop(info);
|
||||
return;
|
||||
}
|
||||
|
@ -1000,7 +1008,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty)
|
|||
if (!info->tx_active)
|
||||
return;
|
||||
} else {
|
||||
if (tty->stopped || tty->hw_stopped) {
|
||||
if (tty && (tty->stopped || tty->hw_stopped)) {
|
||||
tx_stop(info);
|
||||
return;
|
||||
}
|
||||
|
@ -1050,12 +1058,11 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
|
|||
wake_up_interruptible(&info->status_event_wait_q);
|
||||
wake_up_interruptible(&info->event_wait_q);
|
||||
|
||||
if (info->port.flags & ASYNC_CTS_FLOW) {
|
||||
if (tty && (info->port.flags & ASYNC_CTS_FLOW)) {
|
||||
if (tty->hw_stopped) {
|
||||
if (info->serial_signals & SerialSignal_CTS) {
|
||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
||||
printk("CTS tx start...");
|
||||
if (tty)
|
||||
tty->hw_stopped = 0;
|
||||
tx_start(info, tty);
|
||||
info->pending_bh |= BH_TRANSMIT;
|
||||
|
@ -1065,7 +1072,6 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
|
|||
if (!(info->serial_signals & SerialSignal_CTS)) {
|
||||
if (debug_level >= DEBUG_LEVEL_ISR)
|
||||
printk("CTS tx stop...");
|
||||
if (tty)
|
||||
tty->hw_stopped = 1;
|
||||
tx_stop(info);
|
||||
}
|
||||
|
|
|
@ -783,7 +783,8 @@ static int __init ppdev_init (void)
|
|||
err = PTR_ERR(ppdev_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
if (parport_register_driver(&pp_driver)) {
|
||||
err = parport_register_driver(&pp_driver);
|
||||
if (err < 0) {
|
||||
printk (KERN_WARNING CHRDEV ": unable to register with parport\n");
|
||||
goto out_class;
|
||||
}
|
||||
|
|
|
@ -411,7 +411,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
|
|||
case RTC_IRQP_READ:
|
||||
case RTC_IRQP_SET:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -784,8 +784,10 @@ static int __init tlclk_init(void)
|
|||
}
|
||||
tlclk_major = ret;
|
||||
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
|
||||
if (!alarm_events)
|
||||
if (!alarm_events) {
|
||||
ret = -ENOMEM;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* Read telecom clock IRQ number (Set by BIOS) */
|
||||
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
|
||||
|
|
|
@ -1941,7 +1941,17 @@ static int __init init(void)
|
|||
INIT_LIST_HEAD(&pdrvdata.consoles);
|
||||
INIT_LIST_HEAD(&pdrvdata.portdevs);
|
||||
|
||||
return register_virtio_driver(&virtio_console);
|
||||
err = register_virtio_driver(&virtio_console);
|
||||
if (err < 0) {
|
||||
pr_err("Error %d registering virtio driver\n", err);
|
||||
goto free;
|
||||
}
|
||||
return 0;
|
||||
free:
|
||||
if (pdrvdata.debugfs_dir)
|
||||
debugfs_remove_recursive(pdrvdata.debugfs_dir);
|
||||
class_destroy(pdrvdata.class);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
|
|
|
@ -105,7 +105,7 @@ config ATMEL_TCB_CLKSRC_BLOCK
|
|||
|
||||
config IBM_ASM
|
||||
tristate "Device driver for IBM RSA service processor"
|
||||
depends on X86 && PCI && INPUT && EXPERIMENTAL
|
||||
depends on X86 && PCI && INPUT
|
||||
---help---
|
||||
This option enables device driver support for in-band access to the
|
||||
IBM RSA (Condor) service processor in eServer xSeries systems.
|
||||
|
@ -162,8 +162,8 @@ config SGI_IOC4
|
|||
Otherwise say N.
|
||||
|
||||
config TIFM_CORE
|
||||
tristate "TI Flash Media interface support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && PCI
|
||||
tristate "TI Flash Media interface support"
|
||||
depends on PCI
|
||||
help
|
||||
If you want support for Texas Instruments(R) Flash Media adapters
|
||||
you should select this option and then also choose an appropriate
|
||||
|
@ -178,8 +178,8 @@ config TIFM_CORE
|
|||
be called tifm_core.
|
||||
|
||||
config TIFM_7XX1
|
||||
tristate "TI Flash Media PCI74xx/PCI76xx host adapter support (EXPERIMENTAL)"
|
||||
depends on PCI && TIFM_CORE && EXPERIMENTAL
|
||||
tristate "TI Flash Media PCI74xx/PCI76xx host adapter support"
|
||||
depends on PCI && TIFM_CORE
|
||||
default TIFM_CORE
|
||||
help
|
||||
This option enables support for Texas Instruments(R) PCI74xx and
|
||||
|
@ -192,7 +192,7 @@ config TIFM_7XX1
|
|||
|
||||
config ICS932S401
|
||||
tristate "Integrated Circuits ICS932S401"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the Integrated Circuits
|
||||
ICS932S401 clock control chips.
|
||||
|
@ -398,7 +398,7 @@ config EP93XX_PWM
|
|||
|
||||
config DS1682
|
||||
tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1682 Total Elapsed Time Recorder.
|
||||
|
|
|
@ -57,12 +57,6 @@ static int bmp085_i2c_remove(struct i2c_client *client)
|
|||
return bmp085_remove(&client->dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id bmp085_of_match[] = {
|
||||
{ .compatible = "bosch,bmp085", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bmp085_of_match);
|
||||
|
||||
static const struct i2c_device_id bmp085_id[] = {
|
||||
{ BMP085_NAME, 0 },
|
||||
{ "bmp180", 0 },
|
||||
|
@ -74,7 +68,6 @@ static struct i2c_driver bmp085_i2c_driver = {
|
|||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = BMP085_NAME,
|
||||
.of_match_table = bmp085_of_match
|
||||
},
|
||||
.id_table = bmp085_id,
|
||||
.probe = bmp085_i2c_probe,
|
||||
|
|
|
@ -73,19 +73,8 @@ static struct spi_driver bmp085_spi_driver = {
|
|||
.remove = __devexit_p(bmp085_spi_remove)
|
||||
};
|
||||
|
||||
static int __init bmp085_spi_init(void)
|
||||
{
|
||||
return spi_register_driver(&bmp085_spi_driver);
|
||||
}
|
||||
|
||||
static void __exit bmp085_spi_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&bmp085_spi_driver);
|
||||
}
|
||||
module_spi_driver(bmp085_spi_driver);
|
||||
|
||||
MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
|
||||
MODULE_DESCRIPTION("BMP085 SPI bus driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(bmp085_spi_init);
|
||||
module_exit(bmp085_spi_exit);
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#
|
||||
|
||||
menuconfig C2PORT
|
||||
tristate "Silicon Labs C2 port support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
tristate "Silicon Labs C2 port support"
|
||||
default n
|
||||
help
|
||||
This option enables support for Silicon Labs C2 port used to
|
||||
|
@ -22,7 +21,7 @@ menuconfig C2PORT
|
|||
if C2PORT
|
||||
|
||||
config C2PORT_DURAMAR_2150
|
||||
tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)"
|
||||
tristate "C2 port support for Eurotech's Duramar 2150"
|
||||
depends on X86
|
||||
default n
|
||||
help
|
||||
|
|
|
@ -978,7 +978,6 @@ static int fpga_of_probe(struct platform_device *op)
|
|||
dev_set_drvdata(priv->dev, priv);
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_MEMCPY, mask);
|
||||
dma_cap_set(DMA_INTERRUPT, mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
dma_cap_set(DMA_SG, mask);
|
||||
|
||||
|
|
|
@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
|
|||
src = SYS_FPGA_BLOCK;
|
||||
tx = chan->device->device_prep_dma_memcpy(chan, dst, src,
|
||||
REG_BLOCK_SIZE,
|
||||
DMA_PREP_INTERRUPT);
|
||||
0);
|
||||
if (!tx) {
|
||||
dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -50,7 +50,7 @@ config EEPROM_LEGACY
|
|||
|
||||
config EEPROM_MAX6875
|
||||
tristate "Maxim MAX6874/5 power supply supervisor"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get read-only support for the user EEPROM of
|
||||
the Maxim MAX6874/5 EEPROM-programmable, quad power-supply
|
||||
|
|
|
@ -302,6 +302,61 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int at25_np_to_chip(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct spi_eeprom *chip)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
memset(chip, 0, sizeof(*chip));
|
||||
strncpy(chip->name, np->name, sizeof(chip->name));
|
||||
|
||||
if (of_property_read_u32(np, "size", &val) == 0 ||
|
||||
of_property_read_u32(np, "at25,byte-len", &val) == 0) {
|
||||
chip->byte_len = val;
|
||||
} else {
|
||||
dev_err(dev, "Error: missing \"size\" property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "pagesize", &val) == 0 ||
|
||||
of_property_read_u32(np, "at25,page-size", &val) == 0) {
|
||||
chip->page_size = (u16)val;
|
||||
} else {
|
||||
dev_err(dev, "Error: missing \"pagesize\" property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) {
|
||||
chip->flags = (u16)val;
|
||||
} else {
|
||||
if (of_property_read_u32(np, "address-width", &val)) {
|
||||
dev_err(dev,
|
||||
"Error: missing \"address-width\" property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
switch (val) {
|
||||
case 8:
|
||||
chip->flags |= EE_ADDR1;
|
||||
break;
|
||||
case 16:
|
||||
chip->flags |= EE_ADDR2;
|
||||
break;
|
||||
case 24:
|
||||
chip->flags |= EE_ADDR3;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev,
|
||||
"Error: bad \"address-width\" property: %u\n",
|
||||
val);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (of_find_property(np, "read-only", NULL))
|
||||
chip->flags |= EE_READONLY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at25_probe(struct spi_device *spi)
|
||||
{
|
||||
struct at25_data *at25 = NULL;
|
||||
|
@ -314,33 +369,11 @@ static int at25_probe(struct spi_device *spi)
|
|||
/* Chip description */
|
||||
if (!spi->dev.platform_data) {
|
||||
if (np) {
|
||||
u32 val;
|
||||
|
||||
memset(&chip, 0, sizeof(chip));
|
||||
strncpy(chip.name, np->name, 10);
|
||||
|
||||
err = of_property_read_u32(np, "at25,byte-len", &val);
|
||||
if (err) {
|
||||
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||
err = at25_np_to_chip(&spi->dev, np, &chip);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
chip.byte_len = val;
|
||||
|
||||
err = of_property_read_u32(np, "at25,addr-mode", &val);
|
||||
if (err) {
|
||||
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||
goto fail;
|
||||
}
|
||||
chip.flags = (u16)val;
|
||||
|
||||
err = of_property_read_u32(np, "at25,page-size", &val);
|
||||
if (err) {
|
||||
dev_dbg(&spi->dev, "invalid chip dt description\n");
|
||||
goto fail;
|
||||
}
|
||||
chip.page_size = (u16)val;
|
||||
} else {
|
||||
dev_dbg(&spi->dev, "no chip description\n");
|
||||
dev_err(&spi->dev, "Error: no chip description\n");
|
||||
err = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -736,7 +736,14 @@ static void ilo_remove(struct pci_dev *pdev)
|
|||
free_irq(pdev->irq, ilo_hw);
|
||||
ilo_unmap_device(pdev, ilo_hw);
|
||||
pci_release_regions(pdev);
|
||||
pci_disable_device(pdev);
|
||||
/*
|
||||
* pci_disable_device(pdev) used to be here. But this PCI device has
|
||||
* two functions with interrupt lines connected to a single pin. The
|
||||
* other one is a USB host controller. So when we disable the PIN here
|
||||
* e.g. by rmmod hpilo, the controller stops working. It is because
|
||||
* the interrupt link is disabled in ACPI since it is not refcounted
|
||||
* yet. See acpi_pci_link_free_irq called from acpi_pci_irq_disable.
|
||||
*/
|
||||
kfree(ilo_hw);
|
||||
ilo_hwdev[(minor / max_ccb)] = 0;
|
||||
}
|
||||
|
@ -826,7 +833,7 @@ unmap:
|
|||
free_regions:
|
||||
pci_release_regions(pdev);
|
||||
disable:
|
||||
pci_disable_device(pdev);
|
||||
/* pci_disable_device(pdev); see comment in ilo_remove */
|
||||
free:
|
||||
kfree(ilo_hw);
|
||||
out:
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/miscdevice.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "lis3lv02d.h"
|
||||
|
||||
#define DRIVER_NAME "lis3lv02d"
|
||||
|
@ -80,6 +81,15 @@
|
|||
#define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024)
|
||||
#define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY)
|
||||
|
||||
/*
|
||||
* LIS331DLH spec says 1LSBs corresponds 4G/4096 -> 1LSB is 1000/1024 mG.
|
||||
* Below macros defines sensitivity values for +/-2G. Dataout bits for
|
||||
* +/-2G range is 12 bits so 4 bits adjustment must be done to get 12bit
|
||||
* data from 16bit value. Currently this driver supports only 2G range.
|
||||
*/
|
||||
#define LIS3DLH_SENSITIVITY_2G ((LIS3_ACCURACY * 1000) / 1024)
|
||||
#define SHIFT_ADJ_2G 4
|
||||
|
||||
#define LIS3_DEFAULT_FUZZ_12B 3
|
||||
#define LIS3_DEFAULT_FLAT_12B 3
|
||||
#define LIS3_DEFAULT_FUZZ_8B 1
|
||||
|
@ -135,6 +145,19 @@ static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
|
|||
return (s16)((hi << 8) | lo);
|
||||
}
|
||||
|
||||
/* 12bits for 2G range, 13 bits for 4G range and 14 bits for 8G range */
|
||||
static s16 lis331dlh_read_data(struct lis3lv02d *lis3, int reg)
|
||||
{
|
||||
u8 lo, hi;
|
||||
int v;
|
||||
|
||||
lis3->read(lis3, reg - 1, &lo);
|
||||
lis3->read(lis3, reg, &hi);
|
||||
v = (int) ((hi << 8) | lo);
|
||||
|
||||
return (s16) v >> lis3->shift_adj;
|
||||
}
|
||||
|
||||
/**
|
||||
* lis3lv02d_get_axis - For the given axis, give the value converted
|
||||
* @axis: 1,2,3 - can also be negative
|
||||
|
@ -195,6 +218,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
|
|||
static int lis3_12_rates[4] = {40, 160, 640, 2560};
|
||||
static int lis3_8_rates[2] = {100, 400};
|
||||
static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
|
||||
static int lis3_3dlh_rates[4] = {50, 100, 400, 1000};
|
||||
|
||||
/* ODR is Output Data Rate */
|
||||
static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
|
||||
|
@ -267,7 +291,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
|
|||
(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
|
||||
}
|
||||
|
||||
if (lis3->whoami == WAI_3DC) {
|
||||
if ((lis3->whoami == WAI_3DC) || (lis3->whoami == WAI_3DLH)) {
|
||||
ctlreg = CTRL_REG4;
|
||||
selftest = CTRL4_ST0;
|
||||
} else {
|
||||
|
@ -398,9 +422,17 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3)
|
|||
lis3->read(lis3, CTRL_REG2, ®);
|
||||
if (lis3->whoami == WAI_12B)
|
||||
reg |= CTRL2_BDU | CTRL2_BOOT;
|
||||
else if (lis3->whoami == WAI_3DLH)
|
||||
reg |= CTRL2_BOOT_3DLH;
|
||||
else
|
||||
reg |= CTRL2_BOOT_8B;
|
||||
lis3->write(lis3, CTRL_REG2, reg);
|
||||
|
||||
if (lis3->whoami == WAI_3DLH) {
|
||||
lis3->read(lis3, CTRL_REG4, ®);
|
||||
reg |= CTRL4_BDU;
|
||||
lis3->write(lis3, CTRL_REG4, reg);
|
||||
}
|
||||
}
|
||||
|
||||
err = lis3lv02d_get_pwron_wait(lis3);
|
||||
|
@ -912,6 +944,154 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *lis3,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int lis3lv02d_init_dt(struct lis3lv02d *lis3)
|
||||
{
|
||||
struct lis3lv02d_platform_data *pdata;
|
||||
struct device_node *np = lis3->of_node;
|
||||
u32 val;
|
||||
|
||||
if (!lis3->of_node)
|
||||
return 0;
|
||||
|
||||
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_get_property(np, "st,click-single-x", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_SINGLE_X;
|
||||
if (of_get_property(np, "st,click-double-x", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_DOUBLE_X;
|
||||
|
||||
if (of_get_property(np, "st,click-single-y", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_SINGLE_Y;
|
||||
if (of_get_property(np, "st,click-double-y", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_DOUBLE_Y;
|
||||
|
||||
if (of_get_property(np, "st,click-single-z", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_SINGLE_Z;
|
||||
if (of_get_property(np, "st,click-double-z", NULL))
|
||||
pdata->click_flags |= LIS3_CLICK_DOUBLE_Z;
|
||||
|
||||
if (!of_property_read_u32(np, "st,click-threshold-x", &val))
|
||||
pdata->click_thresh_x = val;
|
||||
if (!of_property_read_u32(np, "st,click-threshold-y", &val))
|
||||
pdata->click_thresh_y = val;
|
||||
if (!of_property_read_u32(np, "st,click-threshold-z", &val))
|
||||
pdata->click_thresh_z = val;
|
||||
|
||||
if (!of_property_read_u32(np, "st,click-time-limit", &val))
|
||||
pdata->click_time_limit = val;
|
||||
if (!of_property_read_u32(np, "st,click-latency", &val))
|
||||
pdata->click_latency = val;
|
||||
if (!of_property_read_u32(np, "st,click-window", &val))
|
||||
pdata->click_window = val;
|
||||
|
||||
if (of_get_property(np, "st,irq1-disable", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ1_DISABLE;
|
||||
if (of_get_property(np, "st,irq1-ff-wu-1", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ1_FF_WU_1;
|
||||
if (of_get_property(np, "st,irq1-ff-wu-2", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ1_FF_WU_2;
|
||||
if (of_get_property(np, "st,irq1-data-ready", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ1_DATA_READY;
|
||||
if (of_get_property(np, "st,irq1-click", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ1_CLICK;
|
||||
|
||||
if (of_get_property(np, "st,irq2-disable", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ2_DISABLE;
|
||||
if (of_get_property(np, "st,irq2-ff-wu-1", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ2_FF_WU_1;
|
||||
if (of_get_property(np, "st,irq2-ff-wu-2", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ2_FF_WU_2;
|
||||
if (of_get_property(np, "st,irq2-data-ready", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ2_DATA_READY;
|
||||
if (of_get_property(np, "st,irq2-click", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ2_CLICK;
|
||||
|
||||
if (of_get_property(np, "st,irq-open-drain", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ_OPEN_DRAIN;
|
||||
if (of_get_property(np, "st,irq-active-low", NULL))
|
||||
pdata->irq_cfg |= LIS3_IRQ_ACTIVE_LOW;
|
||||
|
||||
if (!of_property_read_u32(np, "st,wu-duration-1", &val))
|
||||
pdata->duration1 = val;
|
||||
if (!of_property_read_u32(np, "st,wu-duration-2", &val))
|
||||
pdata->duration2 = val;
|
||||
|
||||
if (of_get_property(np, "st,wakeup-x-lo", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_X_LO;
|
||||
if (of_get_property(np, "st,wakeup-x-hi", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_X_HI;
|
||||
if (of_get_property(np, "st,wakeup-y-lo", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_Y_LO;
|
||||
if (of_get_property(np, "st,wakeup-y-hi", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_Y_HI;
|
||||
if (of_get_property(np, "st,wakeup-z-lo", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO;
|
||||
if (of_get_property(np, "st,wakeup-z-hi", NULL))
|
||||
pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI;
|
||||
|
||||
if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) {
|
||||
switch (val) {
|
||||
case 1:
|
||||
pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_1HZ;
|
||||
break;
|
||||
case 2:
|
||||
pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_2HZ;
|
||||
break;
|
||||
case 4:
|
||||
pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_4HZ;
|
||||
break;
|
||||
case 8:
|
||||
pdata->hipass_ctrl = LIS3_HIPASS_CUTFF_8HZ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (of_get_property(np, "st,hipass1-disable", NULL))
|
||||
pdata->hipass_ctrl |= LIS3_HIPASS1_DISABLE;
|
||||
if (of_get_property(np, "st,hipass2-disable", NULL))
|
||||
pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE;
|
||||
|
||||
if (of_get_property(np, "st,axis-x", &val))
|
||||
pdata->axis_x = val;
|
||||
if (of_get_property(np, "st,axis-y", &val))
|
||||
pdata->axis_y = val;
|
||||
if (of_get_property(np, "st,axis-z", &val))
|
||||
pdata->axis_z = val;
|
||||
|
||||
if (of_get_property(np, "st,default-rate", NULL))
|
||||
pdata->default_rate = val;
|
||||
|
||||
if (of_get_property(np, "st,min-limit-x", &val))
|
||||
pdata->st_min_limits[0] = val;
|
||||
if (of_get_property(np, "st,min-limit-y", &val))
|
||||
pdata->st_min_limits[1] = val;
|
||||
if (of_get_property(np, "st,min-limit-z", &val))
|
||||
pdata->st_min_limits[2] = val;
|
||||
|
||||
if (of_get_property(np, "st,max-limit-x", &val))
|
||||
pdata->st_max_limits[0] = val;
|
||||
if (of_get_property(np, "st,max-limit-y", &val))
|
||||
pdata->st_max_limits[1] = val;
|
||||
if (of_get_property(np, "st,max-limit-z", &val))
|
||||
pdata->st_max_limits[2] = val;
|
||||
|
||||
|
||||
lis3->pdata = pdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int lis3lv02d_init_dt(struct lis3lv02d *lis3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL_GPL(lis3lv02d_init_dt);
|
||||
|
||||
/*
|
||||
* Initialise the accelerometer and the various subsystems.
|
||||
* Should be rather independent of the bus system.
|
||||
|
@ -956,6 +1136,16 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3)
|
|||
lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
|
||||
lis3->scale = LIS3_SENSITIVITY_8B;
|
||||
break;
|
||||
case WAI_3DLH:
|
||||
pr_info("16 bits lis331dlh sensor found\n");
|
||||
lis3->read_data = lis331dlh_read_data;
|
||||
lis3->mdps_max_val = 2048; /* 12 bits for 2G */
|
||||
lis3->shift_adj = SHIFT_ADJ_2G;
|
||||
lis3->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
|
||||
lis3->odrs = lis3_3dlh_rates;
|
||||
lis3->odr_mask = CTRL1_DR0 | CTRL1_DR1;
|
||||
lis3->scale = LIS3DLH_SENSITIVITY_2G;
|
||||
break;
|
||||
default:
|
||||
pr_err("unknown sensor type 0x%X\n", lis3->whoami);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
/*
|
||||
* This driver tries to support the "digital" accelerometer chips from
|
||||
* STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
|
||||
* LIS35DE, or LIS202DL. They are very similar in terms of programming, with
|
||||
* almost the same registers. In addition to differing on physical properties,
|
||||
* they differ on the number of axes (2/3), precision (8/12 bits), and special
|
||||
* features (freefall detection, click...). Unfortunately, not all the
|
||||
* differences can be probed via a register.
|
||||
* They can be connected either via I²C or SPI.
|
||||
* LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of
|
||||
* programming, with almost the same registers. In addition to differing
|
||||
* on physical properties, they differ on the number of axes (2/3),
|
||||
* precision (8/12 bits), and special features (freefall detection,
|
||||
* click...). Unfortunately, not all the differences can be probed via
|
||||
* a register. They can be connected either via I²C or SPI.
|
||||
*/
|
||||
|
||||
#include <linux/lis3lv02d.h>
|
||||
|
@ -96,12 +96,22 @@ enum lis3lv02d_reg {
|
|||
};
|
||||
|
||||
enum lis3_who_am_i {
|
||||
WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */
|
||||
WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */
|
||||
WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
|
||||
WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
|
||||
WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */
|
||||
};
|
||||
|
||||
enum lis3_type {
|
||||
LIS3LV02D,
|
||||
LIS3DC,
|
||||
HP3DC,
|
||||
LIS2302D,
|
||||
LIS331DLF,
|
||||
LIS331DLH,
|
||||
};
|
||||
|
||||
enum lis3lv02d_ctrl1_12b {
|
||||
CTRL1_Xen = 0x01,
|
||||
CTRL1_Yen = 0x02,
|
||||
|
@ -129,6 +139,27 @@ enum lis3lv02d_ctrl1_3dc {
|
|||
CTRL1_ODR3 = 0x80,
|
||||
};
|
||||
|
||||
enum lis331dlh_ctrl1 {
|
||||
CTRL1_DR0 = 0x08,
|
||||
CTRL1_DR1 = 0x10,
|
||||
CTRL1_PM0 = 0x20,
|
||||
CTRL1_PM1 = 0x40,
|
||||
CTRL1_PM2 = 0x80,
|
||||
};
|
||||
|
||||
enum lis331dlh_ctrl2 {
|
||||
CTRL2_HPEN1 = 0x04,
|
||||
CTRL2_HPEN2 = 0x08,
|
||||
CTRL2_FDS_3DLH = 0x10,
|
||||
CTRL2_BOOT_3DLH = 0x80,
|
||||
};
|
||||
|
||||
enum lis331dlh_ctrl4 {
|
||||
CTRL4_STSIGN = 0x08,
|
||||
CTRL4_BLE = 0x40,
|
||||
CTRL4_BDU = 0x80,
|
||||
};
|
||||
|
||||
enum lis3lv02d_ctrl2 {
|
||||
CTRL2_DAS = 0x01,
|
||||
CTRL2_SIM = 0x02,
|
||||
|
@ -279,9 +310,14 @@ struct lis3lv02d {
|
|||
int data_ready_count[2];
|
||||
atomic_t wake_thread;
|
||||
unsigned char irq_cfg;
|
||||
unsigned int shift_adj;
|
||||
|
||||
struct lis3lv02d_platform_data *pdata; /* for passing board config */
|
||||
struct mutex mutex; /* Serialize poll and selftest */
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
struct device_node *of_node;
|
||||
#endif
|
||||
};
|
||||
|
||||
int lis3lv02d_init_device(struct lis3lv02d *lis3);
|
||||
|
@ -290,5 +326,6 @@ void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
|
|||
void lis3lv02d_poweroff(struct lis3lv02d *lis3);
|
||||
int lis3lv02d_poweron(struct lis3lv02d *lis3);
|
||||
int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
|
||||
int lis3lv02d_init_dt(struct lis3lv02d *lis3);
|
||||
|
||||
extern struct lis3lv02d lis3_dev;
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "lis3lv02d.h"
|
||||
|
||||
#define DRV_NAME "lis3lv02d_i2c"
|
||||
|
@ -90,7 +94,11 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (lis3->whoami == WAI_3DLH)
|
||||
reg |= CTRL1_PM0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
|
||||
else
|
||||
reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
|
||||
|
||||
return lis3->write(lis3, CTRL_REG1, reg);
|
||||
}
|
||||
|
||||
|
@ -98,12 +106,30 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
|
|||
static union axis_conversion lis3lv02d_axis_map =
|
||||
{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
|
||||
{ .compatible = "st,lis3lv02d" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lis3lv02d_i2c_dt_ids);
|
||||
#endif
|
||||
|
||||
static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_match_device(lis3lv02d_i2c_dt_ids, &client->dev)) {
|
||||
lis3_dev.of_node = client->dev.of_node;
|
||||
ret = lis3lv02d_init_dt(&lis3_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pdata = lis3_dev.pdata;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pdata) {
|
||||
if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
|
||||
(i2c_check_functionality(client->adapter,
|
||||
|
@ -231,7 +257,8 @@ static int lis3_i2c_runtime_resume(struct device *dev)
|
|||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
||||
static const struct i2c_device_id lis3lv02d_id[] = {
|
||||
{"lis3lv02d", 0 },
|
||||
{"lis3lv02d", LIS3LV02D},
|
||||
{"lis331dlh", LIS331DLH},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -250,6 +277,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
|
|||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &lis3_pm_ops,
|
||||
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
|
||||
},
|
||||
.probe = lis3lv02d_i2c_probe,
|
||||
.remove = __devexit_p(lis3lv02d_i2c_remove),
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "lis3lv02d.h"
|
||||
|
||||
|
@ -58,6 +61,14 @@ static int lis3_spi_init(struct lis3lv02d *lis3)
|
|||
static union axis_conversion lis3lv02d_axis_normal =
|
||||
{ .as_array = { 1, 2, 3 } };
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id lis302dl_spi_dt_ids[] = {
|
||||
{ .compatible = "st,lis302dl-spi" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
|
||||
#endif
|
||||
|
||||
static int __devinit lis302dl_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
|
@ -75,6 +86,15 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
|
|||
lis3_dev.irq = spi->irq;
|
||||
lis3_dev.ac = lis3lv02d_axis_normal;
|
||||
lis3_dev.pdata = spi->dev.platform_data;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_match_device(lis302dl_spi_dt_ids, &spi->dev)) {
|
||||
lis3_dev.of_node = spi->dev.of_node;
|
||||
ret = lis3lv02d_init_dt(&lis3_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
spi_set_drvdata(spi, &lis3_dev);
|
||||
|
||||
return lis3lv02d_init_device(&lis3_dev);
|
||||
|
@ -121,6 +141,7 @@ static struct spi_driver lis302dl_spi_driver = {
|
|||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &lis3lv02d_spi_pm,
|
||||
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
|
||||
},
|
||||
.probe = lis302dl_spi_probe,
|
||||
.remove = __devexit_p(lis302dl_spi_remove),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config INTEL_MEI
|
||||
tristate "Intel Management Engine Interface (Intel MEI)"
|
||||
depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE
|
||||
depends on X86 && PCI && WATCHDOG_CORE
|
||||
help
|
||||
The Intel Management Engine (Intel ME) provides Manageability,
|
||||
Security and Media services for system containing Intel chipsets.
|
||||
|
|
|
@ -73,14 +73,15 @@
|
|||
#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
|
||||
#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
|
||||
|
||||
#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */
|
||||
#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */
|
||||
|
||||
#define MEI_DEV_ID_PPT_1 0x1E3A /* Pantherpoint PPT */
|
||||
#define MEI_DEV_ID_PPT_2 0x1CBA /* Pantherpoint PPT */
|
||||
#define MEI_DEV_ID_PPT_3 0x1DBA /* Pantherpoint PPT */
|
||||
#define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */
|
||||
#define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */
|
||||
|
||||
#define MEI_DEV_ID_PPT_1 0x1E3A /* Panther Point */
|
||||
#define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */
|
||||
#define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */
|
||||
|
||||
#define MEI_DEV_ID_LPT 0x8C3A /* Lynx Point */
|
||||
#define MEI_DEV_ID_LPT_LP 0x9C3A /* Lynx Point LP */
|
||||
/*
|
||||
* MEI HW Section
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,25 @@
|
|||
#include "interface.h"
|
||||
#include <linux/mei.h>
|
||||
|
||||
const char *mei_dev_state_str(int state)
|
||||
{
|
||||
#define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state
|
||||
switch (state) {
|
||||
MEI_DEV_STATE(INITIALIZING);
|
||||
MEI_DEV_STATE(INIT_CLIENTS);
|
||||
MEI_DEV_STATE(ENABLED);
|
||||
MEI_DEV_STATE(RESETING);
|
||||
MEI_DEV_STATE(DISABLED);
|
||||
MEI_DEV_STATE(RECOVERING_FROM_RESET);
|
||||
MEI_DEV_STATE(POWER_DOWN);
|
||||
MEI_DEV_STATE(POWER_UP);
|
||||
default:
|
||||
return "unkown";
|
||||
}
|
||||
#undef MEI_DEV_STATE
|
||||
}
|
||||
|
||||
|
||||
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
|
||||
0xa8, 0x46, 0xe0, 0xff, 0x65,
|
||||
0x81, 0x4c);
|
||||
|
@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
|
|||
mutex_init(&dev->device_lock);
|
||||
init_waitqueue_head(&dev->wait_recvd_msg);
|
||||
init_waitqueue_head(&dev->wait_stop_wd);
|
||||
dev->mei_state = MEI_INITIALIZING;
|
||||
dev->dev_state = MEI_DEV_INITIALIZING;
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
dev->wd_interface_reg = false;
|
||||
|
||||
|
@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev)
|
|||
}
|
||||
|
||||
if (err <= 0 && !dev->recvd_msg) {
|
||||
dev->mei_state = MEI_DISABLED;
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"wait_event_interruptible_timeout failed"
|
||||
"on wait for ME to turn on ME_RDY.\n");
|
||||
|
@ -192,7 +211,7 @@ int mei_hw_init(struct mei_device *dev)
|
|||
|
||||
if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
|
||||
((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
|
||||
dev->mei_state = MEI_DISABLED;
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
|
||||
dev->host_hw_state, dev->me_hw_state);
|
||||
|
@ -258,15 +277,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
|||
struct mei_cl_cb *cb_next = NULL;
|
||||
bool unexpected;
|
||||
|
||||
if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
|
||||
if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
|
||||
dev->need_reset = true;
|
||||
return;
|
||||
}
|
||||
|
||||
unexpected = (dev->mei_state != MEI_INITIALIZING &&
|
||||
dev->mei_state != MEI_DISABLED &&
|
||||
dev->mei_state != MEI_POWER_DOWN &&
|
||||
dev->mei_state != MEI_POWER_UP);
|
||||
unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
|
||||
dev->dev_state != MEI_DEV_DISABLED &&
|
||||
dev->dev_state != MEI_DEV_POWER_DOWN &&
|
||||
dev->dev_state != MEI_DEV_POWER_UP);
|
||||
|
||||
dev->host_hw_state = mei_hcsr_read(dev);
|
||||
|
||||
|
@ -285,10 +304,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
|||
|
||||
dev->need_reset = false;
|
||||
|
||||
if (dev->mei_state != MEI_INITIALIZING) {
|
||||
if (dev->mei_state != MEI_DISABLED &&
|
||||
dev->mei_state != MEI_POWER_DOWN)
|
||||
dev->mei_state = MEI_RESETING;
|
||||
if (dev->dev_state != MEI_DEV_INITIALIZING) {
|
||||
if (dev->dev_state != MEI_DEV_DISABLED &&
|
||||
dev->dev_state != MEI_DEV_POWER_DOWN)
|
||||
dev->dev_state = MEI_DEV_RESETING;
|
||||
|
||||
list_for_each_entry_safe(cl_pos,
|
||||
cl_next, &dev->file_list, link) {
|
||||
|
@ -311,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
|||
|
||||
dev->me_clients_num = 0;
|
||||
dev->rd_msg_hdr = 0;
|
||||
dev->stop = false;
|
||||
dev->wd_pending = false;
|
||||
|
||||
/* update the state of the registers after reset */
|
||||
|
@ -322,7 +340,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
|||
dev->host_hw_state, dev->me_hw_state);
|
||||
|
||||
if (unexpected)
|
||||
dev_warn(&dev->pdev->dev, "unexpected reset.\n");
|
||||
dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
|
||||
mei_dev_state_str(dev->dev_state));
|
||||
|
||||
/* Wake up all readings so they can be interrupted */
|
||||
list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
|
||||
|
@ -371,7 +390,7 @@ void mei_host_start_message(struct mei_device *dev)
|
|||
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
|
||||
mei_hdr->length)) {
|
||||
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
|
||||
dev->mei_state = MEI_RESETING;
|
||||
dev->dev_state = MEI_DEV_RESETING;
|
||||
mei_reset(dev, 1);
|
||||
}
|
||||
dev->init_clients_state = MEI_START_MESSAGE;
|
||||
|
@ -403,7 +422,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
|
|||
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
|
||||
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
|
||||
mei_hdr->length)) {
|
||||
dev->mei_state = MEI_RESETING;
|
||||
dev->dev_state = MEI_DEV_RESETING;
|
||||
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
|
||||
mei_reset(dev, 1);
|
||||
}
|
||||
|
@ -444,7 +463,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
|
|||
sizeof(struct mei_me_client), GFP_KERNEL);
|
||||
if (!clients) {
|
||||
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
|
||||
dev->mei_state = MEI_RESETING;
|
||||
dev->dev_state = MEI_DEV_RESETING;
|
||||
mei_reset(dev, 1);
|
||||
return ;
|
||||
}
|
||||
|
@ -490,7 +509,7 @@ int mei_host_client_properties(struct mei_device *dev)
|
|||
if (mei_write_message(dev, mei_header,
|
||||
(unsigned char *)host_cli_req,
|
||||
mei_header->length)) {
|
||||
dev->mei_state = MEI_RESETING;
|
||||
dev->dev_state = MEI_DEV_RESETING;
|
||||
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
|
||||
mei_reset(dev, 1);
|
||||
return -EIO;
|
||||
|
@ -522,12 +541,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
|
|||
priv->dev = dev;
|
||||
}
|
||||
|
||||
int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
|
||||
int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid)
|
||||
{
|
||||
int i, res = -1;
|
||||
int i, res = -ENOENT;
|
||||
|
||||
for (i = 0; i < dev->me_clients_num; ++i)
|
||||
if (uuid_le_cmp(cuuid,
|
||||
if (uuid_le_cmp(*cuuid,
|
||||
dev->me_clients[i].props.protocol_name) == 0) {
|
||||
res = i;
|
||||
break;
|
||||
|
@ -538,35 +557,35 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
|
|||
|
||||
|
||||
/**
|
||||
* mei_find_me_client_update_filext - searches for ME client guid
|
||||
* mei_me_cl_update_filext - searches for ME client guid
|
||||
* sets client_id in mei_file_private if found
|
||||
* @dev: the device structure
|
||||
* @priv: private file structure to set client_id in
|
||||
* @cguid: searched guid of ME client
|
||||
* @cl: private file structure to set client_id in
|
||||
* @cuuid: searched uuid of ME client
|
||||
* @client_id: id of host client to be set in file private structure
|
||||
*
|
||||
* returns ME client index
|
||||
*/
|
||||
u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
|
||||
const uuid_le *cguid, u8 client_id)
|
||||
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
|
||||
const uuid_le *cuuid, u8 host_cl_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dev || !priv || !cguid)
|
||||
return 0;
|
||||
if (!dev || !cl || !cuuid)
|
||||
return -EINVAL;
|
||||
|
||||
/* check for valid client id */
|
||||
i = mei_find_me_client_index(dev, *cguid);
|
||||
i = mei_me_cl_by_uuid(dev, cuuid);
|
||||
if (i >= 0) {
|
||||
priv->me_client_id = dev->me_clients[i].client_id;
|
||||
priv->state = MEI_FILE_CONNECTING;
|
||||
priv->host_client_id = client_id;
|
||||
cl->me_client_id = dev->me_clients[i].client_id;
|
||||
cl->state = MEI_FILE_CONNECTING;
|
||||
cl->host_client_id = host_cl_id;
|
||||
|
||||
list_add_tail(&priv->link, &dev->file_list);
|
||||
list_add_tail(&cl->link, &dev->file_list);
|
||||
return (u8)i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -577,16 +596,16 @@ u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
|
|||
*/
|
||||
void mei_host_init_iamthif(struct mei_device *dev)
|
||||
{
|
||||
u8 i;
|
||||
int i;
|
||||
unsigned char *msg_buf;
|
||||
|
||||
mei_cl_init(&dev->iamthif_cl, dev);
|
||||
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
|
||||
|
||||
/* find ME amthi client */
|
||||
i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl,
|
||||
i = mei_me_cl_update_filext(dev, &dev->iamthif_cl,
|
||||
&mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
|
||||
if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) {
|
||||
if (i < 0) {
|
||||
dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,14 +23,6 @@
|
|||
#include "mei_dev.h"
|
||||
|
||||
|
||||
#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */
|
||||
#define AMT_WD_MIN_TIMEOUT 120 /* seconds */
|
||||
#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */
|
||||
|
||||
#define MEI_WATCHDOG_DATA_SIZE 16
|
||||
#define MEI_START_WD_DATA_SIZE 20
|
||||
#define MEI_WD_PARAMS_SIZE 4
|
||||
|
||||
|
||||
void mei_read_slots(struct mei_device *dev,
|
||||
unsigned char *buffer,
|
||||
|
@ -64,7 +56,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
|
|||
|
||||
|
||||
int mei_wd_send(struct mei_device *dev);
|
||||
int mei_wd_stop(struct mei_device *dev, bool preserve);
|
||||
int mei_wd_stop(struct mei_device *dev);
|
||||
int mei_wd_host_init(struct mei_device *dev);
|
||||
/*
|
||||
* mei_watchdog_register - Registering watchdog interface
|
||||
|
|
|
@ -221,17 +221,10 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
|
|||
cl->status = 0;
|
||||
list_del(&cb_pos->cb_list);
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"completed read host client = %d,"
|
||||
"ME client = %d, "
|
||||
"data length = %lu\n",
|
||||
"completed read H cl = %d, ME cl = %d, length = %lu\n",
|
||||
cl->host_client_id,
|
||||
cl->me_client_id,
|
||||
cb_pos->information);
|
||||
|
||||
*(cb_pos->response_buffer.data +
|
||||
cb_pos->information) = '\0';
|
||||
dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n",
|
||||
cb_pos->response_buffer.data);
|
||||
list_add_tail(&cb_pos->cb_list,
|
||||
&complete_list->mei_cb.cb_list);
|
||||
}
|
||||
|
@ -633,7 +626,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
|||
if (version_res->host_version_supported) {
|
||||
dev->version.major_version = HBM_MAJOR_VERSION;
|
||||
dev->version.minor_version = HBM_MINOR_VERSION;
|
||||
if (dev->mei_state == MEI_INIT_CLIENTS &&
|
||||
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
|
||||
dev->init_clients_state == MEI_START_MESSAGE) {
|
||||
dev->init_clients_timer = 0;
|
||||
mei_host_enum_clients_message(dev);
|
||||
|
@ -707,7 +700,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
|||
dev->me_clients[dev->me_client_presentation_num].props
|
||||
= props_res->client_properties;
|
||||
|
||||
if (dev->mei_state == MEI_INIT_CLIENTS &&
|
||||
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
|
||||
dev->init_clients_state ==
|
||||
MEI_CLIENT_PROPERTIES_MESSAGE) {
|
||||
dev->me_client_index++;
|
||||
|
@ -734,7 +727,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
|||
* Client ID 2 - Reserved for AMTHI
|
||||
*/
|
||||
bitmap_set(dev->host_clients_map, 0, 3);
|
||||
dev->mei_state = MEI_ENABLED;
|
||||
dev->dev_state = MEI_DEV_ENABLED;
|
||||
|
||||
/* if wd initialization fails, initialization the AMTHI client,
|
||||
* otherwise the AMTHI client will be initialized after the WD client connect response
|
||||
|
@ -759,7 +752,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
|||
case HOST_ENUM_RES_CMD:
|
||||
enum_res = (struct hbm_host_enum_response *) mei_msg;
|
||||
memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
|
||||
if (dev->mei_state == MEI_INIT_CLIENTS &&
|
||||
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
|
||||
dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
|
||||
dev->init_clients_timer = 0;
|
||||
dev->me_client_presentation_num = 0;
|
||||
|
@ -776,7 +769,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
|
|||
break;
|
||||
|
||||
case HOST_STOP_RES_CMD:
|
||||
dev->mei_state = MEI_DISABLED;
|
||||
dev->dev_state = MEI_DEV_DISABLED;
|
||||
dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
|
||||
mei_reset(dev, 1);
|
||||
break;
|
||||
|
@ -1224,10 +1217,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
|||
}
|
||||
}
|
||||
|
||||
if (dev->stop && !dev->wd_pending) {
|
||||
dev->wd_stopped = true;
|
||||
if (dev->wd_state == MEI_WD_STOPPING) {
|
||||
dev->wd_state = MEI_WD_IDLE;
|
||||
wake_up_interruptible(&dev->wait_stop_wd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dev->extra_write_index) {
|
||||
|
@ -1240,7 +1232,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
|||
*slots -= dev->extra_write_index;
|
||||
dev->extra_write_index = 0;
|
||||
}
|
||||
if (dev->mei_state == MEI_ENABLED) {
|
||||
if (dev->dev_state == MEI_DEV_ENABLED) {
|
||||
if (dev->wd_pending &&
|
||||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||
if (mei_wd_send(dev))
|
||||
|
@ -1250,14 +1242,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
|
|||
|
||||
dev->wd_pending = false;
|
||||
|
||||
if (dev->wd_timeout)
|
||||
*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);
|
||||
if (dev->wd_state == MEI_WD_RUNNING)
|
||||
*slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
|
||||
else
|
||||
*slots -= mei_data2slots(MEI_WD_PARAMS_SIZE);
|
||||
*slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
|
||||
}
|
||||
}
|
||||
if (dev->stop)
|
||||
return -ENODEV;
|
||||
|
||||
/* complete control write list CB */
|
||||
dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
|
||||
|
@ -1361,8 +1351,8 @@ void mei_timer(struct work_struct *work)
|
|||
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->mei_state == MEI_INIT_CLIENTS) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
|
||||
if (dev->init_clients_timer) {
|
||||
if (--dev->init_clients_timer == 0) {
|
||||
dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
|
||||
|
@ -1484,8 +1474,8 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
|
|||
|
||||
/* check if ME wants a reset */
|
||||
if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
|
||||
dev->mei_state != MEI_RESETING &&
|
||||
dev->mei_state != MEI_INITIALIZING) {
|
||||
dev->dev_state != MEI_DEV_RESETING &&
|
||||
dev->dev_state != MEI_DEV_INITIALIZING) {
|
||||
dev_dbg(&dev->pdev->dev, "FW not ready.\n");
|
||||
mei_reset(dev, 1);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
@ -1498,7 +1488,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
|
|||
dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
|
||||
dev->host_hw_state |= (H_IE | H_IG | H_RDY);
|
||||
mei_hcsr_set(dev);
|
||||
dev->mei_state = MEI_INIT_CLIENTS;
|
||||
dev->dev_state = MEI_DEV_INIT_CLIENTS;
|
||||
dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
|
||||
/* link is established
|
||||
* start sending messages.
|
||||
|
|
|
@ -38,7 +38,31 @@
|
|||
#include <linux/mei.h>
|
||||
#include "interface.h"
|
||||
|
||||
/**
|
||||
* mei_me_cl_by_id return index to me_clients for client_id
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @client_id: me client id
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*
|
||||
* returns index on success, -ENOENT on failure.
|
||||
*/
|
||||
|
||||
int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->me_clients_num; i++)
|
||||
if (dev->me_clients[i].client_id == client_id)
|
||||
break;
|
||||
if (WARN_ON(dev->me_clients[i].client_id != client_id))
|
||||
return -ENOENT;
|
||||
|
||||
if (i == dev->me_clients_num)
|
||||
return -ENOENT;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_ioctl_connect_client - the connect to fw client IOCTL function
|
||||
|
@ -84,7 +108,7 @@ int mei_ioctl_connect_client(struct file *file,
|
|||
|
||||
cb->major_file_operations = MEI_IOCTL;
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
rets = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
@ -95,7 +119,7 @@ int mei_ioctl_connect_client(struct file *file,
|
|||
}
|
||||
|
||||
/* find ME client we're trying to connect to */
|
||||
i = mei_find_me_client_index(dev, data->in_client_uuid);
|
||||
i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
|
||||
if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
|
||||
cl->me_client_id = dev->me_clients[i].client_id;
|
||||
cl->state = MEI_FILE_CONNECTING;
|
||||
|
@ -273,19 +297,12 @@ int amthi_read(struct mei_device *dev, struct file *file,
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->me_clients_num; i++) {
|
||||
if (dev->me_clients[i].client_id ==
|
||||
dev->iamthif_cl.me_client_id)
|
||||
break;
|
||||
}
|
||||
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
|
||||
|
||||
if (i == dev->me_clients_num) {
|
||||
if (i < 0) {
|
||||
dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id))
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "checking amthi data\n");
|
||||
cb = find_amthi_read_list_entry(dev, file);
|
||||
|
||||
|
@ -316,8 +333,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
|
|||
dev->iamthif_timer = 0;
|
||||
|
||||
if (cb) {
|
||||
timeout = cb->read_time +
|
||||
msecs_to_jiffies(IAMTHIF_READ_TIMER);
|
||||
timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
|
||||
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
|
||||
timeout);
|
||||
|
||||
|
@ -386,7 +402,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
|
|||
if (cl->state != MEI_FILE_CONNECTED)
|
||||
return -ENODEV;
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED)
|
||||
if (dev->dev_state != MEI_DEV_ENABLED)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
|
||||
|
@ -401,19 +417,8 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
|
|||
|
||||
dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
|
||||
cl->host_client_id, cl->me_client_id);
|
||||
|
||||
for (i = 0; i < dev->me_clients_num; i++) {
|
||||
if (dev->me_clients[i].client_id == cl->me_client_id)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
|
||||
rets = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (i == dev->me_clients_num) {
|
||||
i = mei_me_cl_by_id(dev, cl->me_client_id);
|
||||
if (i < 0) {
|
||||
rets = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
|
|
@ -41,11 +41,8 @@
|
|||
#include <linux/mei.h>
|
||||
#include "interface.h"
|
||||
|
||||
static const char mei_driver_name[] = "mei";
|
||||
|
||||
/* The device pointer */
|
||||
/* Currently this driver works as long as there is only a single AMT device. */
|
||||
struct pci_dev *mei_device;
|
||||
/* AMT device is a singleton on the platform */
|
||||
static struct pci_dev *mei_pdev;
|
||||
|
||||
/* mei_pci_tbl - PCI Device ID Table */
|
||||
static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
|
||||
|
@ -80,6 +77,8 @@ static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
|
|||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
|
||||
|
||||
/* required last entry */
|
||||
{0, }
|
||||
|
@ -220,10 +219,10 @@ static int mei_open(struct inode *inode, struct file *file)
|
|||
int err;
|
||||
|
||||
err = -ENODEV;
|
||||
if (!mei_device)
|
||||
if (!mei_pdev)
|
||||
goto out;
|
||||
|
||||
dev = pci_get_drvdata(mei_device);
|
||||
dev = pci_get_drvdata(mei_pdev);
|
||||
if (!dev)
|
||||
goto out;
|
||||
|
||||
|
@ -234,18 +233,24 @@ static int mei_open(struct inode *inode, struct file *file)
|
|||
goto out_unlock;
|
||||
|
||||
err = -ENODEV;
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
|
||||
dev->mei_state);
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED dev_state = %s\n",
|
||||
mei_dev_state_str(dev->dev_state));
|
||||
goto out_unlock;
|
||||
}
|
||||
err = -EMFILE;
|
||||
if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT)
|
||||
if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
|
||||
dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
|
||||
MEI_MAX_OPEN_HANDLE_COUNT);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
|
||||
if (cl_id >= MEI_CLIENTS_MAX)
|
||||
if (cl_id >= MEI_CLIENTS_MAX) {
|
||||
dev_err(&dev->pdev->dev, "client_id exceded %d",
|
||||
MEI_CLIENTS_MAX) ;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
cl->host_client_id = cl_id;
|
||||
|
||||
|
@ -386,17 +391,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
|
|||
dev = cl->dev;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
|
||||
/* Do not allow to read watchdog client */
|
||||
i = mei_find_me_client_index(dev, mei_wd_guid);
|
||||
i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
|
||||
if (i >= 0) {
|
||||
struct mei_me_client *me_client = &dev->me_clients[i];
|
||||
|
||||
if (cl->me_client_id == me_client->client_id) {
|
||||
rets = -EBADF;
|
||||
goto out;
|
||||
|
@ -541,7 +545,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
mutex_unlock(&dev->device_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -616,26 +620,16 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
rets = -ENOMEM;
|
||||
goto unlock_dev;
|
||||
}
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
rets = -ENODEV;
|
||||
goto unlock_dev;
|
||||
}
|
||||
for (i = 0; i < dev->me_clients_num; i++) {
|
||||
if (dev->me_clients[i].client_id ==
|
||||
dev->iamthif_cl.me_client_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
|
||||
i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
|
||||
if (i < 0) {
|
||||
rets = -ENODEV;
|
||||
goto unlock_dev;
|
||||
}
|
||||
if (i == dev->me_clients_num ||
|
||||
(dev->me_clients[i].client_id !=
|
||||
dev->iamthif_cl.me_client_id)) {
|
||||
rets = -ENODEV;
|
||||
goto unlock_dev;
|
||||
} else if (length > dev->me_clients[i].props.max_msg_length ||
|
||||
if (length > dev->me_clients[i].props.max_msg_length ||
|
||||
length <= 0) {
|
||||
rets = -EMSGSIZE;
|
||||
goto unlock_dev;
|
||||
|
@ -688,16 +682,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
cl->me_client_id);
|
||||
goto unlock_dev;
|
||||
}
|
||||
for (i = 0; i < dev->me_clients_num; i++) {
|
||||
if (dev->me_clients[i].client_id ==
|
||||
cl->me_client_id)
|
||||
break;
|
||||
}
|
||||
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
|
||||
rets = -ENODEV;
|
||||
goto unlock_dev;
|
||||
}
|
||||
if (i == dev->me_clients_num) {
|
||||
i = mei_me_cl_by_id(dev, cl->me_client_id);
|
||||
if (i < 0) {
|
||||
rets = -ENODEV;
|
||||
goto unlock_dev;
|
||||
}
|
||||
|
@ -790,7 +776,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
|
|||
dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
@ -869,7 +855,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
|
|||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED)
|
||||
if (dev->dev_state != MEI_DEV_ENABLED)
|
||||
goto out;
|
||||
|
||||
|
||||
|
@ -966,7 +952,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (mei_device) {
|
||||
if (mei_pdev) {
|
||||
err = -EEXIST;
|
||||
goto end;
|
||||
}
|
||||
|
@ -979,7 +965,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
/* set PCI host mastering */
|
||||
pci_set_master(pdev);
|
||||
/* pci request regions for mei driver */
|
||||
err = pci_request_regions(pdev, mei_driver_name);
|
||||
err = pci_request_regions(pdev, KBUILD_MODNAME);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to get pci regions.\n");
|
||||
goto disable_device;
|
||||
|
@ -1004,12 +990,12 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
err = request_threaded_irq(pdev->irq,
|
||||
NULL,
|
||||
mei_interrupt_thread_handler,
|
||||
IRQF_ONESHOT, mei_driver_name, dev);
|
||||
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||
else
|
||||
err = request_threaded_irq(pdev->irq,
|
||||
mei_interrupt_quick_handler,
|
||||
mei_interrupt_thread_handler,
|
||||
IRQF_SHARED, mei_driver_name, dev);
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
|
||||
|
@ -1027,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
if (err)
|
||||
goto release_irq;
|
||||
|
||||
mei_device = pdev;
|
||||
mei_pdev = pdev;
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
|
||||
|
@ -1072,7 +1058,7 @@ static void __devexit mei_remove(struct pci_dev *pdev)
|
|||
{
|
||||
struct mei_device *dev;
|
||||
|
||||
if (mei_device != pdev)
|
||||
if (mei_pdev != pdev)
|
||||
return;
|
||||
|
||||
dev = pci_get_drvdata(pdev);
|
||||
|
@ -1081,9 +1067,11 @@ static void __devexit mei_remove(struct pci_dev *pdev)
|
|||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
mei_wd_stop(dev, false);
|
||||
cancel_delayed_work(&dev->timer_work);
|
||||
|
||||
mei_device = NULL;
|
||||
mei_wd_stop(dev);
|
||||
|
||||
mei_pdev = NULL;
|
||||
|
||||
if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
|
||||
dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
|
||||
|
@ -1136,12 +1124,15 @@ static int mei_pci_suspend(struct device *device)
|
|||
if (!dev)
|
||||
return -ENODEV;
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
cancel_delayed_work(&dev->timer_work);
|
||||
|
||||
/* Stop watchdog if exists */
|
||||
err = mei_wd_stop(dev, true);
|
||||
err = mei_wd_stop(dev);
|
||||
/* Set new mei state */
|
||||
if (dev->mei_state == MEI_ENABLED ||
|
||||
dev->mei_state == MEI_RECOVERING_FROM_RESET) {
|
||||
dev->mei_state = MEI_POWER_DOWN;
|
||||
if (dev->dev_state == MEI_DEV_ENABLED ||
|
||||
dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
|
||||
dev->dev_state = MEI_DEV_POWER_DOWN;
|
||||
mei_reset(dev, 0);
|
||||
}
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
@ -1169,12 +1160,12 @@ static int mei_pci_resume(struct device *device)
|
|||
err = request_threaded_irq(pdev->irq,
|
||||
NULL,
|
||||
mei_interrupt_thread_handler,
|
||||
IRQF_ONESHOT, mei_driver_name, dev);
|
||||
IRQF_ONESHOT, KBUILD_MODNAME, dev);
|
||||
else
|
||||
err = request_threaded_irq(pdev->irq,
|
||||
mei_interrupt_quick_handler,
|
||||
mei_interrupt_thread_handler,
|
||||
IRQF_SHARED, mei_driver_name, dev);
|
||||
IRQF_SHARED, KBUILD_MODNAME, dev);
|
||||
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
|
||||
|
@ -1183,7 +1174,7 @@ static int mei_pci_resume(struct device *device)
|
|||
}
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
dev->mei_state = MEI_POWER_UP;
|
||||
dev->dev_state = MEI_DEV_POWER_UP;
|
||||
mei_reset(dev, 1);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
|
@ -1201,7 +1192,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
|
|||
* PCI driver structure
|
||||
*/
|
||||
static struct pci_driver mei_driver = {
|
||||
.name = mei_driver_name,
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = mei_pci_tbl,
|
||||
.probe = mei_probe,
|
||||
.remove = __devexit_p(mei_remove),
|
||||
|
|
|
@ -25,18 +25,20 @@
|
|||
/*
|
||||
* watch dog definition
|
||||
*/
|
||||
#define MEI_WATCHDOG_DATA_SIZE 16
|
||||
#define MEI_START_WD_DATA_SIZE 20
|
||||
#define MEI_WD_PARAMS_SIZE 4
|
||||
#define MEI_WD_HDR_SIZE 4
|
||||
#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE
|
||||
#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16)
|
||||
|
||||
#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */
|
||||
#define MEI_WD_MIN_TIMEOUT 120 /* seconds */
|
||||
#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */
|
||||
|
||||
#define MEI_WD_STOP_TIMEOUT 10 /* msecs */
|
||||
|
||||
#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
|
||||
|
||||
#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
|
||||
|
||||
/*
|
||||
* MEI PCI Device object
|
||||
*/
|
||||
extern struct pci_dev *mei_device;
|
||||
|
||||
|
||||
/*
|
||||
* AMTHI Client UUID
|
||||
|
@ -53,20 +55,22 @@ extern const uuid_le mei_wd_guid;
|
|||
*/
|
||||
extern const u8 mei_wd_state_independence_msg[3][4];
|
||||
|
||||
/*
|
||||
* Number of Maximum MEI Clients
|
||||
*/
|
||||
#define MEI_CLIENTS_MAX 256
|
||||
|
||||
/*
|
||||
* Number of File descriptors/handles
|
||||
* that can be opened to the driver.
|
||||
*
|
||||
* Limit to 253: 255 Total Clients
|
||||
* Limit to 253: 256 Total Clients
|
||||
* minus internal client for MEI Bus Messags
|
||||
* minus internal client for AMTHI
|
||||
* minus internal client for Watchdog
|
||||
*/
|
||||
#define MEI_MAX_OPEN_HANDLE_COUNT 253
|
||||
#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 3)
|
||||
|
||||
/*
|
||||
* Number of Maximum MEI Clients
|
||||
*/
|
||||
#define MEI_CLIENTS_MAX 255
|
||||
|
||||
/* File state */
|
||||
enum file_state {
|
||||
|
@ -78,17 +82,19 @@ enum file_state {
|
|||
};
|
||||
|
||||
/* MEI device states */
|
||||
enum mei_states {
|
||||
MEI_INITIALIZING = 0,
|
||||
MEI_INIT_CLIENTS,
|
||||
MEI_ENABLED,
|
||||
MEI_RESETING,
|
||||
MEI_DISABLED,
|
||||
MEI_RECOVERING_FROM_RESET,
|
||||
MEI_POWER_DOWN,
|
||||
MEI_POWER_UP
|
||||
enum mei_dev_state {
|
||||
MEI_DEV_INITIALIZING = 0,
|
||||
MEI_DEV_INIT_CLIENTS,
|
||||
MEI_DEV_ENABLED,
|
||||
MEI_DEV_RESETING,
|
||||
MEI_DEV_DISABLED,
|
||||
MEI_DEV_RECOVERING_FROM_RESET,
|
||||
MEI_DEV_POWER_DOWN,
|
||||
MEI_DEV_POWER_UP
|
||||
};
|
||||
|
||||
const char *mei_dev_state_str(int state);
|
||||
|
||||
/* init clients states*/
|
||||
enum mei_init_clients_states {
|
||||
MEI_START_MESSAGE = 0,
|
||||
|
@ -113,6 +119,12 @@ enum mei_file_transaction_states {
|
|||
MEI_READ_COMPLETE
|
||||
};
|
||||
|
||||
enum mei_wd_states {
|
||||
MEI_WD_IDLE,
|
||||
MEI_WD_RUNNING,
|
||||
MEI_WD_STOPPING,
|
||||
};
|
||||
|
||||
/* MEI CB */
|
||||
enum mei_cb_major_types {
|
||||
MEI_READ = 0,
|
||||
|
@ -128,7 +140,7 @@ enum mei_cb_major_types {
|
|||
struct mei_message_data {
|
||||
u32 size;
|
||||
unsigned char *data;
|
||||
} __packed;
|
||||
};
|
||||
|
||||
|
||||
struct mei_cl_cb {
|
||||
|
@ -218,10 +230,9 @@ struct mei_device {
|
|||
/*
|
||||
* mei device states
|
||||
*/
|
||||
enum mei_states mei_state;
|
||||
enum mei_dev_state dev_state;
|
||||
enum mei_init_clients_states init_clients_state;
|
||||
u16 init_clients_timer;
|
||||
bool stop;
|
||||
bool need_reset;
|
||||
|
||||
u32 extra_write_index;
|
||||
|
@ -241,12 +252,11 @@ struct mei_device {
|
|||
bool mei_host_buffer_is_empty;
|
||||
|
||||
struct mei_cl wd_cl;
|
||||
enum mei_wd_states wd_state;
|
||||
bool wd_interface_reg;
|
||||
bool wd_pending;
|
||||
bool wd_stopped;
|
||||
bool wd_bypass; /* if false, don't refresh watchdog ME client */
|
||||
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
|
||||
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
|
||||
u16 wd_timeout;
|
||||
unsigned char wd_data[MEI_WD_START_MSG_SIZE];
|
||||
|
||||
|
||||
struct file *iamthif_file_object;
|
||||
|
@ -279,9 +289,10 @@ void mei_host_init_iamthif(struct mei_device *dev);
|
|||
void mei_allocate_me_clients_storage(struct mei_device *dev);
|
||||
|
||||
|
||||
u8 mei_find_me_client_update_filext(struct mei_device *dev,
|
||||
struct mei_cl *priv,
|
||||
const uuid_le *cguid, u8 client_id);
|
||||
int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
|
||||
const uuid_le *cguid, u8 host_client_id);
|
||||
int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid);
|
||||
int mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
|
||||
|
||||
/*
|
||||
* MEI IO List Functions
|
||||
|
@ -348,7 +359,6 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev);
|
|||
|
||||
void mei_free_cb_private(struct mei_cl_cb *priv_cb);
|
||||
|
||||
int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
|
||||
|
||||
/*
|
||||
* Register Access Function
|
||||
|
|
|
@ -48,8 +48,8 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
|
|||
static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||
{
|
||||
dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout);
|
||||
memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
|
||||
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
|
||||
memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE);
|
||||
memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,10 +66,11 @@ int mei_wd_host_init(struct mei_device *dev)
|
|||
|
||||
/* look for WD client and connect to it */
|
||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
||||
dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT;
|
||||
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
|
||||
dev->wd_state = MEI_WD_IDLE;
|
||||
|
||||
/* find ME WD client */
|
||||
mei_find_me_client_update_filext(dev, &dev->wd_cl,
|
||||
mei_me_cl_update_filext(dev, &dev->wd_cl,
|
||||
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "wd: check client\n");
|
||||
|
@ -108,10 +109,10 @@ int mei_wd_send(struct mei_device *dev)
|
|||
mei_hdr->msg_complete = 1;
|
||||
mei_hdr->reserved = 0;
|
||||
|
||||
if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE))
|
||||
mei_hdr->length = MEI_START_WD_DATA_SIZE;
|
||||
else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE))
|
||||
mei_hdr->length = MEI_WD_PARAMS_SIZE;
|
||||
if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE))
|
||||
mei_hdr->length = MEI_WD_START_MSG_SIZE;
|
||||
else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
|
||||
mei_hdr->length = MEI_WD_STOP_MSG_SIZE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -128,18 +129,17 @@ int mei_wd_send(struct mei_device *dev)
|
|||
* -EIO when message send fails
|
||||
* -EINVAL when invalid message is to be sent
|
||||
*/
|
||||
int mei_wd_stop(struct mei_device *dev, bool preserve)
|
||||
int mei_wd_stop(struct mei_device *dev)
|
||||
{
|
||||
int ret;
|
||||
u16 wd_timeout = dev->wd_timeout;
|
||||
|
||||
cancel_delayed_work(&dev->timer_work);
|
||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
|
||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED ||
|
||||
dev->wd_state != MEI_WD_RUNNING)
|
||||
return 0;
|
||||
|
||||
dev->wd_timeout = 0;
|
||||
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
|
||||
dev->stop = true;
|
||||
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE);
|
||||
|
||||
dev->wd_state = MEI_WD_STOPPING;
|
||||
|
||||
ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
|
||||
if (ret < 0)
|
||||
|
@ -161,13 +161,14 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
|||
} else {
|
||||
dev->wd_pending = true;
|
||||
}
|
||||
dev->wd_stopped = false;
|
||||
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
|
||||
dev->wd_stopped, 10 * HZ);
|
||||
dev->wd_state == MEI_WD_IDLE,
|
||||
msecs_to_jiffies(MEI_WD_STOP_TIMEOUT));
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (dev->wd_stopped) {
|
||||
if (dev->wd_state == MEI_WD_IDLE) {
|
||||
dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
|
||||
ret = 0;
|
||||
} else {
|
||||
|
@ -177,9 +178,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
|||
"wd: stop failed to complete ret=%d.\n", ret);
|
||||
}
|
||||
|
||||
if (preserve)
|
||||
dev->wd_timeout = wd_timeout;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -196,16 +194,16 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
|
|||
int err = -ENODEV;
|
||||
struct mei_device *dev;
|
||||
|
||||
dev = pci_get_drvdata(mei_device);
|
||||
dev = watchdog_get_drvdata(wd_dev);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
if (dev->dev_state != MEI_DEV_ENABLED) {
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"wd: mei_state != MEI_ENABLED mei_state = %d\n",
|
||||
dev->mei_state);
|
||||
"wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n",
|
||||
mei_dev_state_str(dev->dev_state));
|
||||
goto end_unlock;
|
||||
}
|
||||
|
||||
|
@ -233,13 +231,13 @@ end_unlock:
|
|||
static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
dev = pci_get_drvdata(mei_device);
|
||||
|
||||
dev = watchdog_get_drvdata(wd_dev);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
mei_wd_stop(dev, false);
|
||||
mei_wd_stop(dev);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
return 0;
|
||||
|
@ -256,8 +254,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
|||
{
|
||||
int ret = 0;
|
||||
struct mei_device *dev;
|
||||
dev = pci_get_drvdata(mei_device);
|
||||
|
||||
dev = watchdog_get_drvdata(wd_dev);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -269,6 +267,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
|||
goto end;
|
||||
}
|
||||
|
||||
dev->wd_state = MEI_WD_RUNNING;
|
||||
|
||||
/* Check if we can send the ping to HW*/
|
||||
if (dev->mei_host_buffer_is_empty &&
|
||||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||
|
@ -309,13 +309,13 @@ end:
|
|||
static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
dev = pci_get_drvdata(mei_device);
|
||||
|
||||
dev = watchdog_get_drvdata(wd_dev);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Check Timeout value */
|
||||
if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT)
|
||||
if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
@ -341,36 +341,41 @@ static const struct watchdog_ops wd_ops = {
|
|||
};
|
||||
static const struct watchdog_info wd_info = {
|
||||
.identity = INTEL_AMT_WATCHDOG_ID,
|
||||
.options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY,
|
||||
.options = WDIOF_KEEPALIVEPING |
|
||||
WDIOF_SETTIMEOUT |
|
||||
WDIOF_ALARMONLY,
|
||||
};
|
||||
|
||||
static struct watchdog_device amt_wd_dev = {
|
||||
.info = &wd_info,
|
||||
.ops = &wd_ops,
|
||||
.timeout = AMT_WD_DEFAULT_TIMEOUT,
|
||||
.min_timeout = AMT_WD_MIN_TIMEOUT,
|
||||
.max_timeout = AMT_WD_MAX_TIMEOUT,
|
||||
.timeout = MEI_WD_DEFAULT_TIMEOUT,
|
||||
.min_timeout = MEI_WD_MIN_TIMEOUT,
|
||||
.max_timeout = MEI_WD_MAX_TIMEOUT,
|
||||
};
|
||||
|
||||
|
||||
void mei_watchdog_register(struct mei_device *dev)
|
||||
{
|
||||
dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
|
||||
|
||||
if (watchdog_register_device(&amt_wd_dev)) {
|
||||
dev_err(&dev->pdev->dev,
|
||||
"wd: unable to register watchdog device.\n");
|
||||
dev->wd_interface_reg = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"wd: successfully register watchdog interface.\n");
|
||||
dev->wd_interface_reg = true;
|
||||
}
|
||||
watchdog_set_drvdata(&amt_wd_dev, dev);
|
||||
}
|
||||
|
||||
void mei_watchdog_unregister(struct mei_device *dev)
|
||||
{
|
||||
if (dev->wd_interface_reg)
|
||||
if (!dev->wd_interface_reg)
|
||||
return;
|
||||
|
||||
watchdog_set_drvdata(&amt_wd_dev, NULL);
|
||||
watchdog_unregister_device(&amt_wd_dev);
|
||||
dev->wd_interface_reg = false;
|
||||
}
|
||||
|
|
|
@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
|
|||
chip->pch_phub_base_address = pci_iomap(pdev, 1, 0);
|
||||
|
||||
|
||||
if (chip->pch_phub_base_address == 0) {
|
||||
if (chip->pch_phub_base_address == NULL) {
|
||||
dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto err_pci_iomap;
|
||||
|
@ -893,18 +893,7 @@ static struct pci_driver pch_phub_driver = {
|
|||
.resume = pch_phub_resume
|
||||
};
|
||||
|
||||
static int __init pch_phub_pci_init(void)
|
||||
{
|
||||
return pci_register_driver(&pch_phub_driver);
|
||||
}
|
||||
|
||||
static void __exit pch_phub_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&pch_phub_driver);
|
||||
}
|
||||
|
||||
module_init(pch_phub_pci_init);
|
||||
module_exit(pch_phub_pci_exit);
|
||||
module_pci_driver(pch_phub_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
|
||||
#include <linux/ti_wilink_st.h>
|
||||
|
||||
extern void st_kim_recv(void *, const unsigned char *, long);
|
||||
void st_int_recv(void *, const unsigned char *, long);
|
||||
/* function pointer pointing to either,
|
||||
* st_kim_recv during registration to receive fw download responses
|
||||
* st_int_recv after registration to receive proto stack responses
|
||||
*/
|
||||
void (*st_recv) (void*, const unsigned char*, long);
|
||||
static void (*st_recv) (void *, const unsigned char *, long);
|
||||
|
||||
/********************************************************************/
|
||||
static void add_channel_to_table(struct st_data_s *st_gdata,
|
||||
|
@ -100,7 +102,7 @@ int st_int_write(struct st_data_s *st_gdata,
|
|||
* push the skb received to relevant
|
||||
* protocol stacks
|
||||
*/
|
||||
void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
|
||||
static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
|
||||
{
|
||||
pr_debug(" %s(prot:%d) ", __func__, chnl_id);
|
||||
|
||||
|
@ -140,7 +142,7 @@ void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
|
|||
* This function is being called with spin lock held, protocol drivers are
|
||||
* only expected to complete their waits and do nothing more than that.
|
||||
*/
|
||||
void st_reg_complete(struct st_data_s *st_gdata, char err)
|
||||
static void st_reg_complete(struct st_data_s *st_gdata, char err)
|
||||
{
|
||||
unsigned char i = 0;
|
||||
pr_info(" %s ", __func__);
|
||||
|
@ -379,7 +381,7 @@ done:
|
|||
* completely, return that skb which has the pending data.
|
||||
* In normal cases, return top of txq.
|
||||
*/
|
||||
struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
|
||||
static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
|
||||
{
|
||||
struct sk_buff *returning_skb;
|
||||
|
||||
|
@ -401,7 +403,7 @@ struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
|
|||
* txq and waitq needs protection since the other contexts
|
||||
* may be sending data, waking up chip.
|
||||
*/
|
||||
void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
|
||||
static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
|
|
|
@ -63,10 +63,27 @@ static struct platform_device *st_get_plat_device(int id)
|
|||
* in case of error don't complete so that waiting for proper
|
||||
* response times out
|
||||
*/
|
||||
void validate_firmware_response(struct kim_data_s *kim_gdata)
|
||||
static void validate_firmware_response(struct kim_data_s *kim_gdata)
|
||||
{
|
||||
struct sk_buff *skb = kim_gdata->rx_skb;
|
||||
if (unlikely(skb->data[5] != 0)) {
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
/* these magic numbers are the position in the response buffer which
|
||||
* allows us to distinguish whether the response is for the read
|
||||
* version info. command
|
||||
*/
|
||||
if (skb->data[2] == 0x01 && skb->data[3] == 0x01 &&
|
||||
skb->data[4] == 0x10 && skb->data[5] == 0x00) {
|
||||
/* fw version response */
|
||||
memcpy(kim_gdata->resp_buffer,
|
||||
kim_gdata->rx_skb->data,
|
||||
kim_gdata->rx_skb->len);
|
||||
complete_all(&kim_gdata->kim_rcvd);
|
||||
kim_gdata->rx_state = ST_W4_PACKET_TYPE;
|
||||
kim_gdata->rx_skb = NULL;
|
||||
kim_gdata->rx_count = 0;
|
||||
} else if (unlikely(skb->data[5] != 0)) {
|
||||
pr_err("no proper response during fw download");
|
||||
pr_err("data6 %x", skb->data[5]);
|
||||
kfree_skb(skb);
|
||||
|
@ -119,7 +136,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
|
|||
* have been observed to come in bursts of different
|
||||
* tty_receive and hence the logic
|
||||
*/
|
||||
void kim_int_recv(struct kim_data_s *kim_gdata,
|
||||
static void kim_int_recv(struct kim_data_s *kim_gdata,
|
||||
const unsigned char *data, long count)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
|
@ -207,16 +224,19 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (!wait_for_completion_timeout
|
||||
(&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
|
||||
if (!wait_for_completion_interruptible_timeout(
|
||||
&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
|
||||
pr_err(" waiting for ver info- timed out ");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
INIT_COMPLETION(kim_gdata->kim_rcvd);
|
||||
/* the positions 12 & 13 in the response buffer provide with the
|
||||
* chip, major & minor numbers
|
||||
*/
|
||||
|
||||
version =
|
||||
MAKEWORD(kim_gdata->resp_buffer[13],
|
||||
kim_gdata->resp_buffer[14]);
|
||||
MAKEWORD(kim_gdata->resp_buffer[12],
|
||||
kim_gdata->resp_buffer[13]);
|
||||
chip = (version & 0x7C00) >> 10;
|
||||
min_ver = (version & 0x007F);
|
||||
maj_ver = (version & 0x0380) >> 7;
|
||||
|
@ -236,7 +256,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void skip_change_remote_baud(unsigned char **ptr, long *len)
|
||||
static void skip_change_remote_baud(unsigned char **ptr, long *len)
|
||||
{
|
||||
unsigned char *nxt_action, *cur_action;
|
||||
cur_action = *ptr;
|
||||
|
@ -370,8 +390,8 @@ static long download_firmware(struct kim_data_s *kim_gdata)
|
|||
break;
|
||||
case ACTION_WAIT_EVENT: /* wait */
|
||||
pr_debug("W");
|
||||
if (!wait_for_completion_timeout
|
||||
(&kim_gdata->kim_rcvd,
|
||||
if (!wait_for_completion_interruptible_timeout(
|
||||
&kim_gdata->kim_rcvd,
|
||||
msecs_to_jiffies(CMD_RESP_TIME))) {
|
||||
pr_err("response timeout during fw download ");
|
||||
/* timed out */
|
||||
|
@ -410,16 +430,10 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count)
|
|||
struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
|
||||
struct kim_data_s *kim_gdata = st_gdata->kim_data;
|
||||
|
||||
/* copy to local buffer */
|
||||
if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) {
|
||||
/* must be the read_ver_cmd */
|
||||
memcpy(kim_gdata->resp_buffer, data, count);
|
||||
complete_all(&kim_gdata->kim_rcvd);
|
||||
return;
|
||||
} else {
|
||||
/* proceed to gather all data and distinguish read fw version response
|
||||
* from other fw responses when data gathering is complete
|
||||
*/
|
||||
kim_int_recv(kim_gdata, data, count);
|
||||
/* either completes or times out */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -454,11 +468,6 @@ long st_kim_start(void *kim_data)
|
|||
if (pdata->chip_enable)
|
||||
pdata->chip_enable(kim_gdata);
|
||||
|
||||
/* Configure BT nShutdown to HIGH state */
|
||||
gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
|
||||
mdelay(5); /* FIXME: a proper toggle */
|
||||
gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
|
||||
mdelay(100);
|
||||
/* re-initialize the completion */
|
||||
INIT_COMPLETION(kim_gdata->ldisc_installed);
|
||||
/* send notification to UIM */
|
||||
|
@ -467,8 +476,8 @@ long st_kim_start(void *kim_data)
|
|||
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
|
||||
NULL, "install");
|
||||
/* wait for ldisc to be installed */
|
||||
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
|
||||
msecs_to_jiffies(LDISC_TIME));
|
||||
err = wait_for_completion_interruptible_timeout(
|
||||
&kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
|
||||
if (!err) {
|
||||
/* ldisc installation timeout,
|
||||
* flush uart, power cycle BT_EN */
|
||||
|
@ -500,8 +509,7 @@ long st_kim_start(void *kim_data)
|
|||
* (b) upon failure to either install ldisc or download firmware.
|
||||
* The function is responsible to (a) notify UIM about un-installation,
|
||||
* (b) flush UART if the ldisc was installed.
|
||||
* (c) reset BT_EN - pull down nshutdown at the end.
|
||||
* (d) invoke platform's chip disabling routine.
|
||||
* (c) invoke platform's chip disabling routine.
|
||||
*/
|
||||
long st_kim_stop(void *kim_data)
|
||||
{
|
||||
|
@ -526,20 +534,13 @@ long st_kim_stop(void *kim_data)
|
|||
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
|
||||
|
||||
/* wait for ldisc to be un-installed */
|
||||
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
|
||||
msecs_to_jiffies(LDISC_TIME));
|
||||
err = wait_for_completion_interruptible_timeout(
|
||||
&kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
|
||||
if (!err) { /* timeout */
|
||||
pr_err(" timed out waiting for ldisc to be un-installed");
|
||||
return -ETIMEDOUT;
|
||||
err = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* By default configure BT nShutdown to LOW state */
|
||||
gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
|
||||
mdelay(1);
|
||||
gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
|
||||
mdelay(1);
|
||||
gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
|
||||
|
||||
/* platform specific disable */
|
||||
if (pdata->chip_disable)
|
||||
pdata->chip_disable(kim_gdata);
|
||||
|
@ -701,7 +702,7 @@ static const struct file_operations list_debugfs_fops = {
|
|||
* board-*.c file
|
||||
*/
|
||||
|
||||
struct dentry *kim_debugfs_dir;
|
||||
static struct dentry *kim_debugfs_dir;
|
||||
static int kim_probe(struct platform_device *pdev)
|
||||
{
|
||||
long status;
|
||||
|
@ -731,20 +732,6 @@ static int kim_probe(struct platform_device *pdev)
|
|||
/* refer to itself */
|
||||
kim_gdata->core_data->kim_data = kim_gdata;
|
||||
|
||||
/* Claim the chip enable nShutdown gpio from the system */
|
||||
kim_gdata->nshutdown = pdata->nshutdown_gpio;
|
||||
status = gpio_request(kim_gdata->nshutdown, "kim");
|
||||
if (unlikely(status)) {
|
||||
pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Configure nShutdown GPIO as output=0 */
|
||||
status = gpio_direction_output(kim_gdata->nshutdown, 0);
|
||||
if (unlikely(status)) {
|
||||
pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
|
||||
return status;
|
||||
}
|
||||
/* get reference of pdev for request_firmware
|
||||
*/
|
||||
kim_gdata->kim_pdev = pdev;
|
||||
|
@ -780,18 +767,10 @@ static int kim_probe(struct platform_device *pdev)
|
|||
|
||||
static int kim_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* free the GPIOs requested */
|
||||
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
|
||||
struct kim_data_s *kim_gdata;
|
||||
|
||||
kim_gdata = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
/* Free the Bluetooth/FM/GPIO
|
||||
* nShutdown gpio from the system
|
||||
*/
|
||||
gpio_free(pdata->nshutdown_gpio);
|
||||
pr_info("nshutdown GPIO Freed");
|
||||
|
||||
debugfs_remove_recursive(kim_debugfs_dir);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
|
||||
pr_info("sysfs entries removed");
|
||||
|
@ -804,7 +783,7 @@ static int kim_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kim_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
static int kim_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
|
@ -814,7 +793,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int kim_resume(struct platform_device *pdev)
|
||||
static int kim_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct ti_st_plat_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
|
|
|
@ -434,21 +434,9 @@ static struct pci_driver tifm_7xx1_driver = {
|
|||
.resume = tifm_7xx1_resume,
|
||||
};
|
||||
|
||||
static int __init tifm_7xx1_init(void)
|
||||
{
|
||||
return pci_register_driver(&tifm_7xx1_driver);
|
||||
}
|
||||
|
||||
static void __exit tifm_7xx1_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&tifm_7xx1_driver);
|
||||
}
|
||||
|
||||
module_pci_driver(tifm_7xx1_driver);
|
||||
MODULE_AUTHOR("Alex Dubov");
|
||||
MODULE_DESCRIPTION("TI FlashMedia host driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl);
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
|
||||
module_init(tifm_7xx1_init);
|
||||
module_exit(tifm_7xx1_exit);
|
||||
|
|
|
@ -60,7 +60,6 @@ config W1_MASTER_GPIO
|
|||
|
||||
config HDQ_MASTER_OMAP
|
||||
tristate "OMAP HDQ driver"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
help
|
||||
Say Y here if you want support for the 1-wire or HDQ Interface
|
||||
on an OMAP processor.
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "../w1.h"
|
||||
#include "../w1_int.h"
|
||||
|
||||
|
@ -73,11 +70,11 @@ struct hdq_data {
|
|||
};
|
||||
|
||||
static int __devinit omap_hdq_probe(struct platform_device *pdev);
|
||||
static int omap_hdq_remove(struct platform_device *pdev);
|
||||
static int __devexit omap_hdq_remove(struct platform_device *pdev);
|
||||
|
||||
static struct platform_driver omap_hdq_driver = {
|
||||
.probe = omap_hdq_probe,
|
||||
.remove = omap_hdq_remove,
|
||||
.remove = __devexit_p(omap_hdq_remove),
|
||||
.driver = {
|
||||
.name = "omap_hdq",
|
||||
},
|
||||
|
@ -538,39 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
|
|||
hdq_data->init_trans = 0;
|
||||
mutex_unlock(&hdq_data->hdq_mutex);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int __devinit omap_hdq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct hdq_data *hdq_data;
|
||||
struct resource *res;
|
||||
int ret, irq;
|
||||
u8 rev;
|
||||
|
||||
hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL);
|
||||
hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
|
||||
if (!hdq_data) {
|
||||
dev_dbg(&pdev->dev, "unable to allocate memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_kmalloc;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdq_data->dev = &pdev->dev;
|
||||
hdq_data->dev = dev;
|
||||
platform_set_drvdata(pdev, hdq_data);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_dbg(&pdev->dev, "unable to get resource\n");
|
||||
ret = -ENXIO;
|
||||
goto err_resource;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
hdq_data->hdq_base = ioremap(res->start, SZ_4K);
|
||||
hdq_data->hdq_base = devm_request_and_ioremap(dev, res);
|
||||
if (!hdq_data->hdq_base) {
|
||||
dev_dbg(&pdev->dev, "ioremap failed\n");
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdq_data->hdq_usecount = 0;
|
||||
|
@ -591,7 +584,8 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
|
|||
goto err_irq;
|
||||
}
|
||||
|
||||
ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data);
|
||||
ret = devm_request_irq(dev, irq, hdq_isr, IRQF_DISABLED,
|
||||
"omap_hdq", hdq_data);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&pdev->dev, "could not request irq\n");
|
||||
goto err_irq;
|
||||
|
@ -616,19 +610,10 @@ err_irq:
|
|||
err_w1:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
iounmap(hdq_data->hdq_base);
|
||||
|
||||
err_ioremap:
|
||||
err_resource:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(hdq_data);
|
||||
|
||||
err_kmalloc:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int omap_hdq_remove(struct platform_device *pdev)
|
||||
static int __devexit omap_hdq_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct hdq_data *hdq_data = platform_get_drvdata(pdev);
|
||||
|
||||
|
@ -644,27 +629,11 @@ static int omap_hdq_remove(struct platform_device *pdev)
|
|||
|
||||
/* remove module dependency */
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
free_irq(INT_24XX_HDQ_IRQ, hdq_data);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
iounmap(hdq_data->hdq_base);
|
||||
kfree(hdq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
omap_hdq_init(void)
|
||||
{
|
||||
return platform_driver_register(&omap_hdq_driver);
|
||||
}
|
||||
module_init(omap_hdq_init);
|
||||
|
||||
static void __exit
|
||||
omap_hdq_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&omap_hdq_driver);
|
||||
}
|
||||
module_exit(omap_hdq_exit);
|
||||
module_platform_driver(omap_hdq_driver);
|
||||
|
||||
module_param(w1_id, int, S_IRUSR);
|
||||
MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/w1-gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include "../w1.h"
|
||||
#include "../w1_int.h"
|
||||
|
@ -42,12 +44,55 @@ static u8 w1_gpio_read_bit(void *data)
|
|||
return gpio_get_value(pdata->pin) ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id w1_gpio_dt_ids[] = {
|
||||
{ .compatible = "w1-gpio" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
|
||||
|
||||
static int w1_gpio_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(w1_gpio_dt_ids, &pdev->dev);
|
||||
|
||||
if (!of_id)
|
||||
return 0;
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_get_property(np, "linux,open-drain", NULL))
|
||||
pdata->is_open_drain = 1;
|
||||
|
||||
pdata->pin = of_get_gpio(np, 0);
|
||||
pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
|
||||
pdev->dev.platform_data = pdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int w1_gpio_probe_dt(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init w1_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct w1_bus_master *master;
|
||||
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct w1_gpio_platform_data *pdata;
|
||||
int err;
|
||||
|
||||
err = w1_gpio_probe_dt(pdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
|
||||
if (!pdata)
|
||||
return -ENXIO;
|
||||
|
||||
|
@ -59,6 +104,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
goto free_master;
|
||||
|
||||
if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
|
||||
err = gpio_request_one(pdata->ext_pullup_enable_pin,
|
||||
GPIOF_INIT_LOW, "w1 pullup");
|
||||
if (err < 0)
|
||||
goto free_gpio;
|
||||
}
|
||||
|
||||
master->data = pdata;
|
||||
master->read_bit = w1_gpio_read_bit;
|
||||
|
||||
|
@ -72,15 +124,21 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
|
|||
|
||||
err = w1_add_master_device(master);
|
||||
if (err)
|
||||
goto free_gpio;
|
||||
goto free_gpio_ext_pu;
|
||||
|
||||
if (pdata->enable_external_pullup)
|
||||
pdata->enable_external_pullup(1);
|
||||
|
||||
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||
gpio_set_value(pdata->ext_pullup_enable_pin, 1);
|
||||
|
||||
platform_set_drvdata(pdev, master);
|
||||
|
||||
return 0;
|
||||
|
||||
free_gpio_ext_pu:
|
||||
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||
gpio_free(pdata->ext_pullup_enable_pin);
|
||||
free_gpio:
|
||||
gpio_free(pdata->pin);
|
||||
free_master:
|
||||
|
@ -97,6 +155,9 @@ static int __exit w1_gpio_remove(struct platform_device *pdev)
|
|||
if (pdata->enable_external_pullup)
|
||||
pdata->enable_external_pullup(0);
|
||||
|
||||
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
|
||||
gpio_set_value(pdata->ext_pullup_enable_pin, 0);
|
||||
|
||||
w1_remove_master_device(master);
|
||||
gpio_free(pdata->pin);
|
||||
kfree(master);
|
||||
|
@ -135,6 +196,7 @@ static struct platform_driver w1_gpio_driver = {
|
|||
.driver = {
|
||||
.name = "w1-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(w1_gpio_dt_ids),
|
||||
},
|
||||
.remove = __exit_p(w1_gpio_remove),
|
||||
.suspend = w1_gpio_suspend,
|
||||
|
|
|
@ -281,9 +281,10 @@ struct kim_data_s {
|
|||
long st_kim_start(void *);
|
||||
long st_kim_stop(void *);
|
||||
|
||||
void st_kim_recv(void *, const unsigned char *, long count);
|
||||
void st_kim_complete(void *);
|
||||
void kim_st_list_protocols(struct st_data_s *, void *);
|
||||
void st_kim_recv(void *, const unsigned char *, long);
|
||||
|
||||
|
||||
/*
|
||||
* BTS headers
|
||||
|
|
|
@ -19,6 +19,7 @@ struct w1_gpio_platform_data {
|
|||
unsigned int pin;
|
||||
unsigned int is_open_drain:1;
|
||||
void (*enable_external_pullup)(int enable);
|
||||
unsigned int ext_pullup_enable_pin;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_W1_GPIO_H */
|
||||
|
|
Loading…
Reference in New Issue