Commit 3aebd34b authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 2c0c86d5 5dc2db05
Atmel AT25 eeprom EEPROMs (SPI) compatible with Atmel at25.
Required properties: Required properties:
- compatible : "atmel,at25". - compatible : "atmel,at25".
- reg : chip select number - reg : chip select number
- spi-max-frequency : max spi frequency to use - 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,byte-len : total eeprom size in bytes
- at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h - at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h
- at25,page-size : size of the eeprom page - at25,page-size : size of the eeprom page
Examples: Additional compatible properties are also allowed.
at25@0 {
compatible = "atmel,at25"; Example:
at25@0 {
compatible = "atmel,at25", "st,m95256";
reg = <0> reg = <0>
spi-max-frequency = <5000000>; spi-max-frequency = <5000000>;
spi-cpha;
spi-cpol;
at25,byte-len = <0x8000>; pagesize = <64>;
at25,addr-mode = <2>; size = <32768>;
at25,page-size = <64>; address-width = <16>;
}; };
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>;
};
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 ...@@ -4,7 +4,8 @@ Kernel driver lis3lv02d
Supported chips: Supported chips:
* STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision) * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
* STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and
LIS331DLH (16 bits)
Authors: Authors:
Yan Burman <burman.yan@gmail.com> Yan Burman <burman.yan@gmail.com>
......
...@@ -418,8 +418,8 @@ config APPLICOM ...@@ -418,8 +418,8 @@ config APPLICOM
If unsure, say N. If unsure, say N.
config SONYPI config SONYPI
tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" tristate "Sony Vaio Programmable I/O Control Device support"
depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT depends on X86 && PCI && INPUT && !64BIT
---help--- ---help---
This driver enables access to the Sony Programmable I/O Control This driver enables access to the Sony Programmable I/O Control
Device which can be found in many (all ?) Sony Vaio laptops. Device which can be found in many (all ?) Sony Vaio laptops.
...@@ -566,7 +566,7 @@ source "drivers/char/tpm/Kconfig" ...@@ -566,7 +566,7 @@ source "drivers/char/tpm/Kconfig"
config TELCLOCK config TELCLOCK
tristate "Telecom clock driver for ATCA SBC" tristate "Telecom clock driver for ATCA SBC"
depends on EXPERIMENTAL && X86 depends on X86
default n default n
help help
The telecom clock device is specific to the MPCBL0010 and MPCBL0050 The telecom clock device is specific to the MPCBL0010 and MPCBL0050
......
...@@ -826,7 +826,7 @@ static int __init mmtimer_init(void) ...@@ -826,7 +826,7 @@ static int __init mmtimer_init(void)
/* Allocate list of node ptrs to mmtimer_t's */ /* Allocate list of node ptrs to mmtimer_t's */
timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL); 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", printk(KERN_ERR "%s: failed to allocate memory for device\n",
MMTIMER_NAME); MMTIMER_NAME);
goto out3; goto out3;
...@@ -848,7 +848,6 @@ static int __init mmtimer_init(void) ...@@ -848,7 +848,6 @@ static int __init mmtimer_init(void)
return 0; return 0;
out3: out3:
kfree(timers);
misc_deregister(&mmtimer_miscdev); misc_deregister(&mmtimer_miscdev);
out2: out2:
free_irq(SGI_MMTIMER_VECTOR, NULL); free_irq(SGI_MMTIMER_VECTOR, NULL);
......
...@@ -93,9 +93,9 @@ int button_del_callback (void (*callback) (void)) ...@@ -93,9 +93,9 @@ int button_del_callback (void (*callback) (void))
button_callback_list [lp].count = 0; button_callback_list [lp].count = 0;
callback_count--; callback_count--;
return 0; return 0;
}; }
lp--; lp--;
}; }
return -EINVAL; return -EINVAL;
} }
......
...@@ -891,6 +891,14 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) ...@@ -891,6 +891,14 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
int work = 0; int work = 0;
struct mgsl_icount *icount = &info->icount; 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) { if (tcd) {
/* early termination, get FIFO count from RBCL register */ /* early termination, get FIFO count from RBCL register */
fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); 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) ...@@ -980,7 +988,7 @@ static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty)
else else
#endif #endif
{ {
if (tty->stopped || tty->hw_stopped) { if (tty && (tty->stopped || tty->hw_stopped)) {
tx_stop(info); tx_stop(info);
return; return;
} }
...@@ -1000,7 +1008,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) ...@@ -1000,7 +1008,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty)
if (!info->tx_active) if (!info->tx_active)
return; return;
} else { } else {
if (tty->stopped || tty->hw_stopped) { if (tty && (tty->stopped || tty->hw_stopped)) {
tx_stop(info); tx_stop(info);
return; return;
} }
...@@ -1050,12 +1058,11 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) ...@@ -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->status_event_wait_q);
wake_up_interruptible(&info->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 (tty->hw_stopped) {
if (info->serial_signals & SerialSignal_CTS) { if (info->serial_signals & SerialSignal_CTS) {
if (debug_level >= DEBUG_LEVEL_ISR) if (debug_level >= DEBUG_LEVEL_ISR)
printk("CTS tx start..."); printk("CTS tx start...");
if (tty)
tty->hw_stopped = 0; tty->hw_stopped = 0;
tx_start(info, tty); tx_start(info, tty);
info->pending_bh |= BH_TRANSMIT; info->pending_bh |= BH_TRANSMIT;
...@@ -1065,7 +1072,6 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) ...@@ -1065,7 +1072,6 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
if (!(info->serial_signals & SerialSignal_CTS)) { if (!(info->serial_signals & SerialSignal_CTS)) {
if (debug_level >= DEBUG_LEVEL_ISR) if (debug_level >= DEBUG_LEVEL_ISR)
printk("CTS tx stop..."); printk("CTS tx stop...");
if (tty)
tty->hw_stopped = 1; tty->hw_stopped = 1;
tx_stop(info); tx_stop(info);
} }
......
...@@ -783,7 +783,8 @@ static int __init ppdev_init (void) ...@@ -783,7 +783,8 @@ static int __init ppdev_init (void)
err = PTR_ERR(ppdev_class); err = PTR_ERR(ppdev_class);
goto out_chrdev; 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"); printk (KERN_WARNING CHRDEV ": unable to register with parport\n");
goto out_class; goto out_class;
} }
......
...@@ -411,7 +411,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) ...@@ -411,7 +411,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
case RTC_IRQP_READ: case RTC_IRQP_READ:
case RTC_IRQP_SET: case RTC_IRQP_SET:
return -EINVAL; return -EINVAL;
}; }
} }
#endif #endif
......
...@@ -784,8 +784,10 @@ static int __init tlclk_init(void) ...@@ -784,8 +784,10 @@ static int __init tlclk_init(void)
} }
tlclk_major = ret; tlclk_major = ret;
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
if (!alarm_events) if (!alarm_events) {
ret = -ENOMEM;
goto out1; goto out1;
}
/* Read telecom clock IRQ number (Set by BIOS) */ /* Read telecom clock IRQ number (Set by BIOS) */
if (!request_region(TLCLK_BASE, 8, "telco_clock")) { if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
......
...@@ -1941,7 +1941,17 @@ static int __init init(void) ...@@ -1941,7 +1941,17 @@ static int __init init(void)
INIT_LIST_HEAD(&pdrvdata.consoles); INIT_LIST_HEAD(&pdrvdata.consoles);
INIT_LIST_HEAD(&pdrvdata.portdevs); 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) static void __exit fini(void)
......
...@@ -105,7 +105,7 @@ config ATMEL_TCB_CLKSRC_BLOCK ...@@ -105,7 +105,7 @@ config ATMEL_TCB_CLKSRC_BLOCK
config IBM_ASM config IBM_ASM
tristate "Device driver for IBM RSA service processor" tristate "Device driver for IBM RSA service processor"
depends on X86 && PCI && INPUT && EXPERIMENTAL depends on X86 && PCI && INPUT
---help--- ---help---
This option enables device driver support for in-band access to the This option enables device driver support for in-band access to the
IBM RSA (Condor) service processor in eServer xSeries systems. IBM RSA (Condor) service processor in eServer xSeries systems.
...@@ -162,8 +162,8 @@ config SGI_IOC4 ...@@ -162,8 +162,8 @@ config SGI_IOC4
Otherwise say N. Otherwise say N.
config TIFM_CORE config TIFM_CORE
tristate "TI Flash Media interface support (EXPERIMENTAL)" tristate "TI Flash Media interface support"
depends on EXPERIMENTAL && PCI depends on PCI
help help
If you want support for Texas Instruments(R) Flash Media adapters If you want support for Texas Instruments(R) Flash Media adapters
you should select this option and then also choose an appropriate you should select this option and then also choose an appropriate
...@@ -178,8 +178,8 @@ config TIFM_CORE ...@@ -178,8 +178,8 @@ config TIFM_CORE
be called tifm_core. be called tifm_core.
config TIFM_7XX1 config TIFM_7XX1
tristate "TI Flash Media PCI74xx/PCI76xx host adapter support (EXPERIMENTAL)" tristate "TI Flash Media PCI74xx/PCI76xx host adapter support"
depends on PCI && TIFM_CORE && EXPERIMENTAL depends on PCI && TIFM_CORE
default TIFM_CORE default TIFM_CORE
help help
This option enables support for Texas Instruments(R) PCI74xx and This option enables support for Texas Instruments(R) PCI74xx and
...@@ -192,7 +192,7 @@ config TIFM_7XX1 ...@@ -192,7 +192,7 @@ config TIFM_7XX1
config ICS932S401 config ICS932S401
tristate "Integrated Circuits ICS932S401" tristate "Integrated Circuits ICS932S401"
depends on I2C && EXPERIMENTAL depends on I2C
help help
If you say yes here you get support for the Integrated Circuits If you say yes here you get support for the Integrated Circuits
ICS932S401 clock control chips. ICS932S401 clock control chips.
...@@ -398,7 +398,7 @@ config EP93XX_PWM ...@@ -398,7 +398,7 @@ config EP93XX_PWM
config DS1682 config DS1682
tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
depends on I2C && EXPERIMENTAL depends on I2C
help help
If you say yes here you get support for Dallas Semiconductor If you say yes here you get support for Dallas Semiconductor
DS1682 Total Elapsed Time Recorder. DS1682 Total Elapsed Time Recorder.
......
...@@ -57,12 +57,6 @@ static int bmp085_i2c_remove(struct i2c_client *client) ...@@ -57,12 +57,6 @@ static int bmp085_i2c_remove(struct i2c_client *client)
return bmp085_remove(&client->dev); 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[] = { static const struct i2c_device_id bmp085_id[] = {
{ BMP085_NAME, 0 }, { BMP085_NAME, 0 },
{ "bmp180", 0 }, { "bmp180", 0 },
...@@ -74,7 +68,6 @@ static struct i2c_driver bmp085_i2c_driver = { ...@@ -74,7 +68,6 @@ static struct i2c_driver bmp085_i2c_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = BMP085_NAME, .name = BMP085_NAME,
.of_match_table = bmp085_of_match
}, },
.id_table = bmp085_id, .id_table = bmp085_id,
.probe = bmp085_i2c_probe, .probe = bmp085_i2c_probe,
......
...@@ -73,19 +73,8 @@ static struct spi_driver bmp085_spi_driver = { ...@@ -73,19 +73,8 @@ static struct spi_driver bmp085_spi_driver = {
.remove = __devexit_p(bmp085_spi_remove) .remove = __devexit_p(bmp085_spi_remove)
}; };
static int __init bmp085_spi_init(void) module_spi_driver(bmp085_spi_driver);
{
return spi_register_driver(&bmp085_spi_driver);
}
static void __exit bmp085_spi_exit(void)
{
spi_unregister_driver(&bmp085_spi_driver);
}
MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>"); MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
MODULE_DESCRIPTION("BMP085 SPI bus driver"); MODULE_DESCRIPTION("BMP085 SPI bus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(bmp085_spi_init);
module_exit(bmp085_spi_exit);
...@@ -3,8 +3,7 @@ ...@@ -3,8 +3,7 @@
# #
menuconfig C2PORT menuconfig C2PORT
tristate "Silicon Labs C2 port support (EXPERIMENTAL)" tristate "Silicon Labs C2 port support"
depends on EXPERIMENTAL
default n default n
help help
This option enables support for Silicon Labs C2 port used to This option enables support for Silicon Labs C2 port used to
...@@ -22,7 +21,7 @@ menuconfig C2PORT ...@@ -22,7 +21,7 @@ menuconfig C2PORT
if C2PORT if C2PORT
config C2PORT_DURAMAR_2150 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 depends on X86
default n default n
help help
......
...@@ -978,7 +978,6 @@ static int fpga_of_probe(struct platform_device *op) ...@@ -978,7 +978,6 @@ static int fpga_of_probe(struct platform_device *op)
dev_set_drvdata(priv->dev, priv); dev_set_drvdata(priv->dev, priv);
dma_cap_zero(mask); dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask); dma_cap_set(DMA_MEMCPY, mask);
dma_cap_set(DMA_INTERRUPT, mask);
dma_cap_set(DMA_SLAVE, mask); dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_SG, mask); dma_cap_set(DMA_SG, mask);
......
...@@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf) ...@@ -666,7 +666,7 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
src = SYS_FPGA_BLOCK; src = SYS_FPGA_BLOCK;
tx = chan->device->device_prep_dma_memcpy(chan, dst, src, tx = chan->device->device_prep_dma_memcpy(chan, dst, src,
REG_BLOCK_SIZE, REG_BLOCK_SIZE,
DMA_PREP_INTERRUPT); 0);
if (!tx) { if (!tx) {
dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n"); dev_err(priv->dev, "unable to prep SYS-FPGA DMA\n");
return -ENOMEM; return -ENOMEM;
......
...@@ -50,7 +50,7 @@ config EEPROM_LEGACY ...@@ -50,7 +50,7 @@ config EEPROM_LEGACY
config EEPROM_MAX6875 config EEPROM_MAX6875
tristate "Maxim MAX6874/5 power supply supervisor" tristate "Maxim MAX6874/5 power supply supervisor"
depends on I2C && EXPERIMENTAL depends on I2C
help help
If you say yes here you get read-only support for the user EEPROM of If you say yes here you get read-only support for the user EEPROM of
the Maxim MAX6874/5 EEPROM-programmable, quad power-supply 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, ...@@ -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) static int at25_probe(struct spi_device *spi)
{ {
struct at25_data *at25 = NULL; struct at25_data *at25 = NULL;
...@@ -314,33 +369,11 @@ static int at25_probe(struct spi_device *spi) ...@@ -314,33 +369,11 @@ static int at25_probe(struct spi_device *spi)
/* Chip description */ /* Chip description */
if (!spi->dev.platform_data) { if (!spi->dev.platform_data) {
if (np) { if (np) {
u32 val; err = at25_np_to_chip(&spi->dev, np, &chip);
if (err)
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");
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; goto fail;
}
chip.page_size = (u16)val;
} else { } else {
dev_dbg(&spi->dev, "no chip description\n"); dev_err(&spi->dev, "Error: no chip description\n");
err = -ENODEV; err = -ENODEV;
goto fail; goto fail;
} }
......
...@@ -736,7 +736,14 @@ static void ilo_remove(struct pci_dev *pdev) ...@@ -736,7 +736,14 @@ static void ilo_remove(struct pci_dev *pdev)
free_irq(pdev->irq, ilo_hw); free_irq(pdev->irq, ilo_hw);
ilo_unmap_device(pdev, ilo_hw); ilo_unmap_device(pdev, ilo_hw);
pci_release_regions(pdev); 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); kfree(ilo_hw);
ilo_hwdev[(minor / max_ccb)] = 0; ilo_hwdev[(minor / max_ccb)] = 0;
} }
...@@ -826,7 +833,7 @@ static int __devinit ilo_probe(struct pci_dev *pdev, ...@@ -826,7 +833,7 @@ static int __devinit ilo_probe(struct pci_dev *pdev,
free_regions: free_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
disable: disable:
pci_disable_device(pdev); /* pci_disable_device(pdev); see comment in ilo_remove */
free: free:
kfree(ilo_hw); kfree(ilo_hw);
out: out:
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/of_device.h>
#include "lis3lv02d.h" #include "lis3lv02d.h"
#define DRIVER_NAME "lis3lv02d" #define DRIVER_NAME "lis3lv02d"
...@@ -80,6 +81,15 @@ ...@@ -80,6 +81,15 @@
#define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024) #define LIS3_SENSITIVITY_12B ((LIS3_ACCURACY * 1000) / 1024)
#define LIS3_SENSITIVITY_8B (18 * LIS3_ACCURACY) #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_FUZZ_12B 3
#define LIS3_DEFAULT_FLAT_12B 3 #define LIS3_DEFAULT_FLAT_12B 3
#define LIS3_DEFAULT_FUZZ_8B 1 #define LIS3_DEFAULT_FUZZ_8B 1
...@@ -135,6 +145,19 @@ static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg) ...@@ -135,6 +145,19 @@ static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
return (s16)((hi << 8) | lo); 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 * lis3lv02d_get_axis - For the given axis, give the value converted
* @axis: 1,2,3 - can also be negative * @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) ...@@ -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_12_rates[4] = {40, 160, 640, 2560};
static int lis3_8_rates[2] = {100, 400}; 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_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 */ /* ODR is Output Data Rate */
static int lis3lv02d_get_odr(struct lis3lv02d *lis3) static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
...@@ -267,7 +291,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) ...@@ -267,7 +291,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY)); (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; ctlreg = CTRL_REG4;
selftest = CTRL4_ST0; selftest = CTRL4_ST0;
} else { } else {
...@@ -398,9 +422,17 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3) ...@@ -398,9 +422,17 @@ int lis3lv02d_poweron(struct lis3lv02d *lis3)
lis3->read(lis3, CTRL_REG2, &reg); lis3->read(lis3, CTRL_REG2, &reg);
if (lis3->whoami == WAI_12B) if (lis3->whoami == WAI_12B)
reg |= CTRL2_BDU | CTRL2_BOOT; reg |= CTRL2_BDU | CTRL2_BOOT;
else if (lis3->whoami == WAI_3DLH)
reg |= CTRL2_BOOT_3DLH;
else else
reg |= CTRL2_BOOT_8B; reg |= CTRL2_BOOT_8B;
lis3->write(lis3, CTRL_REG2, reg); lis3->write(lis3, CTRL_REG2, reg);
if (lis3->whoami == WAI_3DLH) {
lis3->read(lis3, CTRL_REG4, &reg);
reg |= CTRL4_BDU;
lis3->write(lis3, CTRL_REG4, reg);
}
} }
err = lis3lv02d_get_pwron_wait(lis3); err = lis3lv02d_get_pwron_wait(lis3);
...@@ -912,6 +944,154 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *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. * Initialise the accelerometer and the various subsystems.
* Should be rather independent of the bus system. * Should be rather independent of the bus system.
...@@ -956,6 +1136,16 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3) ...@@ -956,6 +1136,16 @@ int lis3lv02d_init_device(struct lis3lv02d *lis3)
lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3; lis3->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
lis3->scale = LIS3_SENSITIVITY_8B; lis3->scale = LIS3_SENSITIVITY_8B;
break; 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: default:
pr_err("unknown sensor type 0x%X\n", lis3->whoami); pr_err("unknown sensor type 0x%X\n", lis3->whoami);
return -EINVAL; return -EINVAL;
......
...@@ -26,12 +26,12 @@ ...@@ -26,12 +26,12 @@
/* /*
* This driver tries to support the "digital" accelerometer chips from * This driver tries to support the "digital" accelerometer chips from
* STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL, * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
* LIS35DE, or LIS202DL. They are very similar in terms of programming, with * LIS331DLH, LIS35DE, or LIS202DL. They are very similar in terms of
* almost the same registers. In addition to differing on physical properties, * programming, with almost the same registers. In addition to differing
* they differ on the number of axes (2/3), precision (8/12 bits), and special * on physical properties, they differ on the number of axes (2/3),
* features (freefall detection, click...). Unfortunately, not all the * precision (8/12 bits), and special features (freefall detection,
* differences can be probed via a register. * click...). Unfortunately, not all the differences can be probed via
* They can be connected either via I²C or SPI. * a register. They can be connected either via I²C or SPI.
*/ */
#include <linux/lis3lv02d.h> #include <linux/lis3lv02d.h>
...@@ -96,12 +96,22 @@ enum lis3lv02d_reg { ...@@ -96,12 +96,22 @@ enum lis3lv02d_reg {
}; };
enum lis3_who_am_i { enum lis3_who_am_i {
WAI_3DLH = 0x32, /* 16 bits: LIS331DLH */
WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */ WAI_3DC = 0x33, /* 8 bits: LIS3DC, HP3DC */
WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */ WAI_12B = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */ WAI_8B = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */ WAI_6B = 0x52, /* 6 bits: LIS331DLF - not supported */
}; };
enum lis3_type {
LIS3LV02D,
LIS3DC,
HP3DC,
LIS2302D,
LIS331DLF,
LIS331DLH,
};
enum lis3lv02d_ctrl1_12b { enum lis3lv02d_ctrl1_12b {
CTRL1_Xen = 0x01, CTRL1_Xen = 0x01,
CTRL1_Yen = 0x02, CTRL1_Yen = 0x02,
...@@ -129,6 +139,27 @@ enum lis3lv02d_ctrl1_3dc { ...@@ -129,6 +139,27 @@ enum lis3lv02d_ctrl1_3dc {
CTRL1_ODR3 = 0x80, 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 { enum lis3lv02d_ctrl2 {
CTRL2_DAS = 0x01, CTRL2_DAS = 0x01,
CTRL2_SIM = 0x02, CTRL2_SIM = 0x02,
...@@ -279,9 +310,14 @@ struct lis3lv02d { ...@@ -279,9 +310,14 @@ struct lis3lv02d {
int data_ready_count[2]; int data_ready_count[2];
atomic_t wake_thread; atomic_t wake_thread;
unsigned char irq_cfg; unsigned char irq_cfg;
unsigned int shift_adj;
struct lis3lv02d_platform_data *pdata; /* for passing board config */ struct lis3lv02d_platform_data *pdata; /* for passing board config */
struct mutex mutex; /* Serialize poll and selftest */ struct mutex mutex; /* Serialize poll and selftest */
#ifdef CONFIG_OF
struct device_node *of_node;
#endif
}; };
int lis3lv02d_init_device(struct lis3lv02d *lis3); int lis3lv02d_init_device(struct lis3lv02d *lis3);
...@@ -290,5 +326,6 @@ void lis3lv02d_joystick_disable(struct lis3lv02d *lis3); ...@@ -290,5 +326,6 @@ void lis3lv02d_joystick_disable(struct lis3lv02d *lis3);
void lis3lv02d_poweroff(struct lis3lv02d *lis3); void lis3lv02d_poweroff(struct lis3lv02d *lis3);
int lis3lv02d_poweron(struct lis3lv02d *lis3); int lis3lv02d_poweron(struct lis3lv02d *lis3);
int lis3lv02d_remove_fs(struct lis3lv02d *lis3); int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
int lis3lv02d_init_dt(struct lis3lv02d *lis3);
extern struct lis3lv02d lis3_dev; extern struct lis3lv02d lis3_dev;
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include "lis3lv02d.h" #include "lis3lv02d.h"
#define DRV_NAME "lis3lv02d_i2c" #define DRV_NAME "lis3lv02d_i2c"
...@@ -90,7 +94,11 @@ static int lis3_i2c_init(struct lis3lv02d *lis3) ...@@ -90,7 +94,11 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
if (ret < 0) if (ret < 0)
return ret; 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; reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
return lis3->write(lis3, CTRL_REG1, reg); return lis3->write(lis3, CTRL_REG1, reg);
} }
...@@ -98,12 +106,30 @@ static int lis3_i2c_init(struct lis3lv02d *lis3) ...@@ -98,12 +106,30 @@ static int lis3_i2c_init(struct lis3lv02d *lis3)
static union axis_conversion lis3lv02d_axis_map = static union axis_conversion lis3lv02d_axis_map =
{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } }; { .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, static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
int ret = 0; int ret = 0;
struct lis3lv02d_platform_data *pdata = client->dev.platform_data; 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) {
if ((pdata->driver_features & LIS3_USE_BLOCK_READ) && if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
(i2c_check_functionality(client->adapter, (i2c_check_functionality(client->adapter,
...@@ -231,7 +257,8 @@ static int lis3_i2c_runtime_resume(struct device *dev) ...@@ -231,7 +257,8 @@ static int lis3_i2c_runtime_resume(struct device *dev)
#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM_RUNTIME */
static const struct i2c_device_id lis3lv02d_id[] = { 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 = { ...@@ -250,6 +277,7 @@ static struct i2c_driver lis3lv02d_i2c_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &lis3_pm_ops, .pm = &lis3_pm_ops,
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
}, },
.probe = lis3lv02d_i2c_probe, .probe = lis3lv02d_i2c_probe,
.remove = __devexit_p(lis3lv02d_i2c_remove), .remove = __devexit_p(lis3lv02d_i2c_remove),
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include "lis3lv02d.h" #include "lis3lv02d.h"
...@@ -58,6 +61,14 @@ static int lis3_spi_init(struct lis3lv02d *lis3) ...@@ -58,6 +61,14 @@ static int lis3_spi_init(struct lis3lv02d *lis3)
static union axis_conversion lis3lv02d_axis_normal = static union axis_conversion lis3lv02d_axis_normal =
{ .as_array = { 1, 2, 3 } }; { .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) static int __devinit lis302dl_spi_probe(struct spi_device *spi)
{ {
int ret; int ret;
...@@ -75,6 +86,15 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi) ...@@ -75,6 +86,15 @@ static int __devinit lis302dl_spi_probe(struct spi_device *spi)
lis3_dev.irq = spi->irq; lis3_dev.irq = spi->irq;
lis3_dev.ac = lis3lv02d_axis_normal; lis3_dev.ac = lis3lv02d_axis_normal;
lis3_dev.pdata = spi->dev.platform_data; 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); spi_set_drvdata(spi, &lis3_dev);
return lis3lv02d_init_device(&lis3_dev); return lis3lv02d_init_device(&lis3_dev);
...@@ -121,6 +141,7 @@ static struct spi_driver lis302dl_spi_driver = { ...@@ -121,6 +141,7 @@ static struct spi_driver lis302dl_spi_driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &lis3lv02d_spi_pm, .pm = &lis3lv02d_spi_pm,
.of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
}, },
.probe = lis302dl_spi_probe, .probe = lis302dl_spi_probe,
.remove = __devexit_p(lis302dl_spi_remove), .remove = __devexit_p(lis302dl_spi_remove),
......
config INTEL_MEI config INTEL_MEI
tristate "Intel Management Engine Interface (Intel MEI)" tristate "Intel Management Engine Interface (Intel MEI)"
depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE depends on X86 && PCI && WATCHDOG_CORE
help help
The Intel Management Engine (Intel ME) provides Manageability, The Intel Management Engine (Intel ME) provides Manageability,
Security and Media services for system containing Intel chipsets. Security and Media services for system containing Intel chipsets.
......
...@@ -73,14 +73,15 @@ ...@@ -73,14 +73,15 @@
#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */ #define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */ #define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */ #define MEI_DEV_ID_CPT_1 0x1C3A /* Couger Point */
#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */ #define MEI_DEV_ID_PBG_1 0x1D3A /* C600/X79 Patsburg */
#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_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 * MEI HW Section
*/ */
......
...@@ -24,6 +24,25 @@ ...@@ -24,6 +24,25 @@
#include "interface.h" #include "interface.h"
#include <linux/mei.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, const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
0xa8, 0x46, 0xe0, 0xff, 0x65, 0xa8, 0x46, 0xe0, 0xff, 0x65,
0x81, 0x4c); 0x81, 0x4c);
...@@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) ...@@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev)
mutex_init(&dev->device_lock); mutex_init(&dev->device_lock);
init_waitqueue_head(&dev->wait_recvd_msg); init_waitqueue_head(&dev->wait_recvd_msg);
init_waitqueue_head(&dev->wait_stop_wd); 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->iamthif_state = MEI_IAMTHIF_IDLE;
dev->wd_interface_reg = false; dev->wd_interface_reg = false;
...@@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev) ...@@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev)
} }
if (err <= 0 && !dev->recvd_msg) { if (err <= 0 && !dev->recvd_msg) {
dev->mei_state = MEI_DISABLED; dev->dev_state = MEI_DEV_DISABLED;
dev_dbg(&dev->pdev->dev, dev_dbg(&dev->pdev->dev,
"wait_event_interruptible_timeout failed" "wait_event_interruptible_timeout failed"
"on wait for ME to turn on ME_RDY.\n"); "on wait for ME to turn on ME_RDY.\n");
...@@ -192,7 +211,7 @@ int mei_hw_init(struct mei_device *dev) ...@@ -192,7 +211,7 @@ int mei_hw_init(struct mei_device *dev)
if (!(((dev->host_hw_state & H_RDY) == H_RDY) && if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { ((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, dev_dbg(&dev->pdev->dev,
"host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
dev->host_hw_state, dev->me_hw_state); dev->host_hw_state, dev->me_hw_state);
...@@ -258,15 +277,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -258,15 +277,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
struct mei_cl_cb *cb_next = NULL; struct mei_cl_cb *cb_next = NULL;
bool unexpected; bool unexpected;
if (dev->mei_state == MEI_RECOVERING_FROM_RESET) { if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
dev->need_reset = true; dev->need_reset = true;
return; return;
} }
unexpected = (dev->mei_state != MEI_INITIALIZING && unexpected = (dev->dev_state != MEI_DEV_INITIALIZING &&
dev->mei_state != MEI_DISABLED && dev->dev_state != MEI_DEV_DISABLED &&
dev->mei_state != MEI_POWER_DOWN && dev->dev_state != MEI_DEV_POWER_DOWN &&
dev->mei_state != MEI_POWER_UP); dev->dev_state != MEI_DEV_POWER_UP);
dev->host_hw_state = mei_hcsr_read(dev); dev->host_hw_state = mei_hcsr_read(dev);
...@@ -285,10 +304,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -285,10 +304,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->need_reset = false; dev->need_reset = false;
if (dev->mei_state != MEI_INITIALIZING) { if (dev->dev_state != MEI_DEV_INITIALIZING) {
if (dev->mei_state != MEI_DISABLED && if (dev->dev_state != MEI_DEV_DISABLED &&
dev->mei_state != MEI_POWER_DOWN) dev->dev_state != MEI_DEV_POWER_DOWN)
dev->mei_state = MEI_RESETING; dev->dev_state = MEI_DEV_RESETING;
list_for_each_entry_safe(cl_pos, list_for_each_entry_safe(cl_pos,
cl_next, &dev->file_list, link) { cl_next, &dev->file_list, link) {
...@@ -311,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -311,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->me_clients_num = 0; dev->me_clients_num = 0;
dev->rd_msg_hdr = 0; dev->rd_msg_hdr = 0;
dev->stop = false;
dev->wd_pending = false; dev->wd_pending = false;
/* update the state of the registers after reset */ /* update the state of the registers after reset */
...@@ -322,7 +340,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) ...@@ -322,7 +340,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
dev->host_hw_state, dev->me_hw_state); dev->host_hw_state, dev->me_hw_state);
if (unexpected) 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 */ /* Wake up all readings so they can be interrupted */
list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 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) ...@@ -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, if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
mei_hdr->length)) { mei_hdr->length)) {
dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); 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); mei_reset(dev, 1);
} }
dev->init_clients_state = MEI_START_MESSAGE; dev->init_clients_state = MEI_START_MESSAGE;
...@@ -403,7 +422,7 @@ void mei_host_enum_clients_message(struct mei_device *dev) ...@@ -403,7 +422,7 @@ void mei_host_enum_clients_message(struct mei_device *dev)
host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
mei_hdr->length)) { 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"); dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1); mei_reset(dev, 1);
} }
...@@ -444,7 +463,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) ...@@ -444,7 +463,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
sizeof(struct mei_me_client), GFP_KERNEL); sizeof(struct mei_me_client), GFP_KERNEL);
if (!clients) { if (!clients) {
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); 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); mei_reset(dev, 1);
return ; return ;
} }
...@@ -490,7 +509,7 @@ int mei_host_client_properties(struct mei_device *dev) ...@@ -490,7 +509,7 @@ int mei_host_client_properties(struct mei_device *dev)
if (mei_write_message(dev, mei_header, if (mei_write_message(dev, mei_header,
(unsigned char *)host_cli_req, (unsigned char *)host_cli_req,
mei_header->length)) { 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"); dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
mei_reset(dev, 1); mei_reset(dev, 1);
return -EIO; return -EIO;
...@@ -522,12 +541,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) ...@@ -522,12 +541,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
priv->dev = 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) 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) { dev->me_clients[i].props.protocol_name) == 0) {
res = i; res = i;
break; break;
...@@ -538,35 +557,35 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) ...@@ -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 * sets client_id in mei_file_private if found
* @dev: the device structure * @dev: the device structure
* @priv: private file structure to set client_id in * @cl: private file structure to set client_id in
* @cguid: searched guid of ME client * @cuuid: searched uuid of ME client
* @client_id: id of host client to be set in file private structure * @client_id: id of host client to be set in file private structure
* *
* returns ME client index * returns ME client index
*/ */
u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
const uuid_le *cguid, u8 client_id) const uuid_le *cuuid, u8 host_cl_id)
{ {
int i; int i;
if (!dev || !priv || !cguid) if (!dev || !cl || !cuuid)
return 0; return -EINVAL;
/* check for valid client id */ /* check for valid client id */
i = mei_find_me_client_index(dev, *cguid); i = mei_me_cl_by_uuid(dev, cuuid);
if (i >= 0) { if (i >= 0) {
priv->me_client_id = dev->me_clients[i].client_id; cl->me_client_id = dev->me_clients[i].client_id;
priv->state = MEI_FILE_CONNECTING; cl->state = MEI_FILE_CONNECTING;
priv->host_client_id = client_id; 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 (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, ...@@ -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) void mei_host_init_iamthif(struct mei_device *dev)
{ {
u8 i; int i;
unsigned char *msg_buf; unsigned char *msg_buf;
mei_cl_init(&dev->iamthif_cl, dev); mei_cl_init(&dev->iamthif_cl, dev);
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
/* find ME amthi client */ /* 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); &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"); dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
return; return;
} }
......
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
#include "mei_dev.h" #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, void mei_read_slots(struct mei_device *dev,
unsigned char *buffer, unsigned char *buffer,
...@@ -64,7 +56,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl); ...@@ -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_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); int mei_wd_host_init(struct mei_device *dev);
/* /*
* mei_watchdog_register - Registering watchdog interface * mei_watchdog_register - Registering watchdog interface
......
...@@ -221,17 +221,10 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, ...@@ -221,17 +221,10 @@ static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
cl->status = 0; cl->status = 0;
list_del(&cb_pos->cb_list); list_del(&cb_pos->cb_list);
dev_dbg(&dev->pdev->dev, dev_dbg(&dev->pdev->dev,
"completed read host client = %d," "completed read H cl = %d, ME cl = %d, length = %lu\n",
"ME client = %d, "
"data length = %lu\n",
cl->host_client_id, cl->host_client_id,
cl->me_client_id, cl->me_client_id,
cb_pos->information); 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, list_add_tail(&cb_pos->cb_list,
&complete_list->mei_cb.cb_list); &complete_list->mei_cb.cb_list);
} }
...@@ -633,7 +626,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, ...@@ -633,7 +626,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
if (version_res->host_version_supported) { if (version_res->host_version_supported) {
dev->version.major_version = HBM_MAJOR_VERSION; dev->version.major_version = HBM_MAJOR_VERSION;
dev->version.minor_version = HBM_MINOR_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_state == MEI_START_MESSAGE) {
dev->init_clients_timer = 0; dev->init_clients_timer = 0;
mei_host_enum_clients_message(dev); mei_host_enum_clients_message(dev);
...@@ -707,7 +700,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *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 dev->me_clients[dev->me_client_presentation_num].props
= props_res->client_properties; = props_res->client_properties;
if (dev->mei_state == MEI_INIT_CLIENTS && if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
dev->init_clients_state == dev->init_clients_state ==
MEI_CLIENT_PROPERTIES_MESSAGE) { MEI_CLIENT_PROPERTIES_MESSAGE) {
dev->me_client_index++; dev->me_client_index++;
...@@ -734,7 +727,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, ...@@ -734,7 +727,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
* Client ID 2 - Reserved for AMTHI * Client ID 2 - Reserved for AMTHI
*/ */
bitmap_set(dev->host_clients_map, 0, 3); 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, /* if wd initialization fails, initialization the AMTHI client,
* otherwise the AMTHI client will be initialized after the WD client connect response * 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, ...@@ -759,7 +752,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
case HOST_ENUM_RES_CMD: case HOST_ENUM_RES_CMD:
enum_res = (struct hbm_host_enum_response *) mei_msg; enum_res = (struct hbm_host_enum_response *) mei_msg;
memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 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_state == MEI_ENUM_CLIENTS_MESSAGE) {
dev->init_clients_timer = 0; dev->init_clients_timer = 0;
dev->me_client_presentation_num = 0; dev->me_client_presentation_num = 0;
...@@ -776,7 +769,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, ...@@ -776,7 +769,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
break; break;
case HOST_STOP_RES_CMD: 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"); dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
mei_reset(dev, 1); mei_reset(dev, 1);
break; break;
...@@ -1224,10 +1217,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, ...@@ -1224,10 +1217,9 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
} }
} }
if (dev->stop && !dev->wd_pending) { if (dev->wd_state == MEI_WD_STOPPING) {
dev->wd_stopped = true; dev->wd_state = MEI_WD_IDLE;
wake_up_interruptible(&dev->wait_stop_wd); wake_up_interruptible(&dev->wait_stop_wd);
return 0;
} }
if (dev->extra_write_index) { if (dev->extra_write_index) {
...@@ -1240,7 +1232,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, ...@@ -1240,7 +1232,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
*slots -= dev->extra_write_index; *slots -= dev->extra_write_index;
dev->extra_write_index = 0; dev->extra_write_index = 0;
} }
if (dev->mei_state == MEI_ENABLED) { if (dev->dev_state == MEI_DEV_ENABLED) {
if (dev->wd_pending && if (dev->wd_pending &&
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
if (mei_wd_send(dev)) if (mei_wd_send(dev))
...@@ -1250,14 +1242,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, ...@@ -1250,14 +1242,12 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
dev->wd_pending = false; dev->wd_pending = false;
if (dev->wd_timeout) if (dev->wd_state == MEI_WD_RUNNING)
*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); *slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
else 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 */ /* complete control write list CB */
dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
...@@ -1361,8 +1351,8 @@ void mei_timer(struct work_struct *work) ...@@ -1361,8 +1351,8 @@ void mei_timer(struct work_struct *work)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
if (dev->mei_state == MEI_INIT_CLIENTS) { if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
if (dev->init_clients_timer) { if (dev->init_clients_timer) {
if (--dev->init_clients_timer == 0) { if (--dev->init_clients_timer == 0) {
dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n", 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) ...@@ -1484,8 +1474,8 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
/* check if ME wants a reset */ /* check if ME wants a reset */
if ((dev->me_hw_state & ME_RDY_HRA) == 0 && if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
dev->mei_state != MEI_RESETING && dev->dev_state != MEI_DEV_RESETING &&
dev->mei_state != MEI_INITIALIZING) { dev->dev_state != MEI_DEV_INITIALIZING) {
dev_dbg(&dev->pdev->dev, "FW not ready.\n"); dev_dbg(&dev->pdev->dev, "FW not ready.\n");
mei_reset(dev, 1); mei_reset(dev, 1);
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
...@@ -1498,7 +1488,7 @@ irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) ...@@ -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_dbg(&dev->pdev->dev, "we need to start the dev.\n");
dev->host_hw_state |= (H_IE | H_IG | H_RDY); dev->host_hw_state |= (H_IE | H_IG | H_RDY);
mei_hcsr_set(dev); 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"); dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
/* link is established /* link is established
* start sending messages. * start sending messages.
......
...@@ -38,7 +38,31 @@ ...@@ -38,7 +38,31 @@
#include <linux/mei.h> #include <linux/mei.h>
#include "interface.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 * mei_ioctl_connect_client - the connect to fw client IOCTL function
...@@ -84,7 +108,7 @@ int mei_ioctl_connect_client(struct file *file, ...@@ -84,7 +108,7 @@ int mei_ioctl_connect_client(struct file *file,
cb->major_file_operations = MEI_IOCTL; cb->major_file_operations = MEI_IOCTL;
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV; rets = -ENODEV;
goto end; goto end;
} }
...@@ -95,7 +119,7 @@ int mei_ioctl_connect_client(struct file *file, ...@@ -95,7 +119,7 @@ int mei_ioctl_connect_client(struct file *file,
} }
/* find ME client we're trying to connect to */ /* 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) { if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
cl->me_client_id = dev->me_clients[i].client_id; cl->me_client_id = dev->me_clients[i].client_id;
cl->state = MEI_FILE_CONNECTING; cl->state = MEI_FILE_CONNECTING;
...@@ -273,19 +297,12 @@ int amthi_read(struct mei_device *dev, struct file *file, ...@@ -273,19 +297,12 @@ int amthi_read(struct mei_device *dev, struct file *file,
return -ETIMEDOUT; return -ETIMEDOUT;
} }
for (i = 0; i < dev->me_clients_num; i++) { i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
if (dev->me_clients[i].client_id ==
dev->iamthif_cl.me_client_id)
break;
}
if (i == dev->me_clients_num) { if (i < 0) {
dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
return -ENODEV; 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"); dev_dbg(&dev->pdev->dev, "checking amthi data\n");
cb = find_amthi_read_list_entry(dev, file); cb = find_amthi_read_list_entry(dev, file);
...@@ -316,8 +333,7 @@ int amthi_read(struct mei_device *dev, struct file *file, ...@@ -316,8 +333,7 @@ int amthi_read(struct mei_device *dev, struct file *file,
dev->iamthif_timer = 0; dev->iamthif_timer = 0;
if (cb) { if (cb) {
timeout = cb->read_time + timeout = cb->read_time + msecs_to_jiffies(IAMTHIF_READ_TIMER);
msecs_to_jiffies(IAMTHIF_READ_TIMER);
dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
timeout); timeout);
...@@ -386,7 +402,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl) ...@@ -386,7 +402,7 @@ int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
if (cl->state != MEI_FILE_CONNECTED) if (cl->state != MEI_FILE_CONNECTED)
return -ENODEV; return -ENODEV;
if (dev->mei_state != MEI_ENABLED) if (dev->dev_state != MEI_DEV_ENABLED)
return -ENODEV; return -ENODEV;
dev_dbg(&dev->pdev->dev, "check if read is pending.\n"); 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) ...@@ -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", dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
cl->host_client_id, cl->me_client_id); cl->host_client_id, cl->me_client_id);
i = mei_me_cl_by_id(dev, cl->me_client_id);
for (i = 0; i < dev->me_clients_num; i++) { if (i < 0) {
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) {
rets = -ENODEV; rets = -ENODEV;
goto unlock; goto unlock;
} }
......
...@@ -41,11 +41,8 @@ ...@@ -41,11 +41,8 @@
#include <linux/mei.h> #include <linux/mei.h>
#include "interface.h" #include "interface.h"
static const char mei_driver_name[] = "mei"; /* AMT device is a singleton on the platform */
static struct pci_dev *mei_pdev;
/* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */
struct pci_dev *mei_device;
/* mei_pci_tbl - PCI Device ID Table */ /* mei_pci_tbl - PCI Device ID Table */
static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = { static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
...@@ -80,6 +77,8 @@ 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_1)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)}, {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_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 */ /* required last entry */
{0, } {0, }
...@@ -220,10 +219,10 @@ static int mei_open(struct inode *inode, struct file *file) ...@@ -220,10 +219,10 @@ static int mei_open(struct inode *inode, struct file *file)
int err; int err;
err = -ENODEV; err = -ENODEV;
if (!mei_device) if (!mei_pdev)
goto out; goto out;
dev = pci_get_drvdata(mei_device); dev = pci_get_drvdata(mei_pdev);
if (!dev) if (!dev)
goto out; goto out;
...@@ -234,18 +233,24 @@ static int mei_open(struct inode *inode, struct file *file) ...@@ -234,18 +233,24 @@ static int mei_open(struct inode *inode, struct file *file)
goto out_unlock; goto out_unlock;
err = -ENODEV; err = -ENODEV;
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n", dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED dev_state = %s\n",
dev->mei_state); mei_dev_state_str(dev->dev_state));
goto out_unlock; goto out_unlock;
} }
err = -EMFILE; 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; goto out_unlock;
}
cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); 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; goto out_unlock;
}
cl->host_client_id = cl_id; cl->host_client_id = cl_id;
...@@ -386,17 +391,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, ...@@ -386,17 +391,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
dev = cl->dev; dev = cl->dev;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV; rets = -ENODEV;
goto out; goto out;
} }
if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) { if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
/* Do not allow to read watchdog client */ /* 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) { if (i >= 0) {
struct mei_me_client *me_client = &dev->me_clients[i]; struct mei_me_client *me_client = &dev->me_clients[i];
if (cl->me_client_id == me_client->client_id) { if (cl->me_client_id == me_client->client_id) {
rets = -EBADF; rets = -EBADF;
goto out; goto out;
...@@ -541,7 +545,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, ...@@ -541,7 +545,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
return -ENODEV; return -ENODEV;
} }
...@@ -616,26 +620,16 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, ...@@ -616,26 +620,16 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -ENOMEM; rets = -ENOMEM;
goto unlock_dev; goto unlock_dev;
} }
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV; rets = -ENODEV;
goto unlock_dev; goto unlock_dev;
} }
for (i = 0; i < dev->me_clients_num; i++) { i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id);
if (dev->me_clients[i].client_id == if (i < 0) {
dev->iamthif_cl.me_client_id)
break;
}
if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
rets = -ENODEV; rets = -ENODEV;
goto unlock_dev; goto unlock_dev;
} }
if (i == dev->me_clients_num || if (length > dev->me_clients[i].props.max_msg_length ||
(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 ||
length <= 0) { length <= 0) {
rets = -EMSGSIZE; rets = -EMSGSIZE;
goto unlock_dev; goto unlock_dev;
...@@ -688,16 +682,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, ...@@ -688,16 +682,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
cl->me_client_id); cl->me_client_id);
goto unlock_dev; goto unlock_dev;
} }
for (i = 0; i < dev->me_clients_num; i++) { i = mei_me_cl_by_id(dev, cl->me_client_id);
if (dev->me_clients[i].client_id == if (i < 0) {
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) {
rets = -ENODEV; rets = -ENODEV;
goto unlock_dev; goto unlock_dev;
} }
...@@ -790,7 +776,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data) ...@@ -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); dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV; rets = -ENODEV;
goto out; goto out;
} }
...@@ -869,7 +855,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) ...@@ -869,7 +855,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) if (dev->dev_state != MEI_DEV_ENABLED)
goto out; goto out;
...@@ -966,7 +952,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -966,7 +952,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
goto end; goto end;
} }
if (mei_device) { if (mei_pdev) {
err = -EEXIST; err = -EEXIST;
goto end; goto end;
} }
...@@ -979,7 +965,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -979,7 +965,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* set PCI host mastering */ /* set PCI host mastering */
pci_set_master(pdev); pci_set_master(pdev);
/* pci request regions for mei driver */ /* pci request regions for mei driver */
err = pci_request_regions(pdev, mei_driver_name); err = pci_request_regions(pdev, KBUILD_MODNAME);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to get pci regions.\n"); dev_err(&pdev->dev, "failed to get pci regions.\n");
goto disable_device; goto disable_device;
...@@ -1004,12 +990,12 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -1004,12 +990,12 @@ static int __devinit mei_probe(struct pci_dev *pdev,
err = request_threaded_irq(pdev->irq, err = request_threaded_irq(pdev->irq,
NULL, NULL,
mei_interrupt_thread_handler, mei_interrupt_thread_handler,
IRQF_ONESHOT, mei_driver_name, dev); IRQF_ONESHOT, KBUILD_MODNAME, dev);
else else
err = request_threaded_irq(pdev->irq, err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler, mei_interrupt_quick_handler,
mei_interrupt_thread_handler, mei_interrupt_thread_handler,
IRQF_SHARED, mei_driver_name, dev); IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) { if (err) {
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n", dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
...@@ -1027,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -1027,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
if (err) if (err)
goto release_irq; goto release_irq;
mei_device = pdev; mei_pdev = pdev;
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
...@@ -1072,7 +1058,7 @@ static void __devexit mei_remove(struct pci_dev *pdev) ...@@ -1072,7 +1058,7 @@ static void __devexit mei_remove(struct pci_dev *pdev)
{ {
struct mei_device *dev; struct mei_device *dev;
if (mei_device != pdev) if (mei_pdev != pdev)
return; return;
dev = pci_get_drvdata(pdev); dev = pci_get_drvdata(pdev);
...@@ -1081,9 +1067,11 @@ static void __devexit mei_remove(struct pci_dev *pdev) ...@@ -1081,9 +1067,11 @@ static void __devexit mei_remove(struct pci_dev *pdev)
mutex_lock(&dev->device_lock); 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) { if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
...@@ -1136,12 +1124,15 @@ static int mei_pci_suspend(struct device *device) ...@@ -1136,12 +1124,15 @@ static int mei_pci_suspend(struct device *device)
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
cancel_delayed_work(&dev->timer_work);
/* Stop watchdog if exists */ /* Stop watchdog if exists */
err = mei_wd_stop(dev, true); err = mei_wd_stop(dev);
/* Set new mei state */ /* Set new mei state */
if (dev->mei_state == MEI_ENABLED || if (dev->dev_state == MEI_DEV_ENABLED ||
dev->mei_state == MEI_RECOVERING_FROM_RESET) { dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
dev->mei_state = MEI_POWER_DOWN; dev->dev_state = MEI_DEV_POWER_DOWN;
mei_reset(dev, 0); mei_reset(dev, 0);
} }
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
...@@ -1169,12 +1160,12 @@ static int mei_pci_resume(struct device *device) ...@@ -1169,12 +1160,12 @@ static int mei_pci_resume(struct device *device)
err = request_threaded_irq(pdev->irq, err = request_threaded_irq(pdev->irq,
NULL, NULL,
mei_interrupt_thread_handler, mei_interrupt_thread_handler,
IRQF_ONESHOT, mei_driver_name, dev); IRQF_ONESHOT, KBUILD_MODNAME, dev);
else else
err = request_threaded_irq(pdev->irq, err = request_threaded_irq(pdev->irq,
mei_interrupt_quick_handler, mei_interrupt_quick_handler,
mei_interrupt_thread_handler, mei_interrupt_thread_handler,
IRQF_SHARED, mei_driver_name, dev); IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) { if (err) {
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
...@@ -1183,7 +1174,7 @@ static int mei_pci_resume(struct device *device) ...@@ -1183,7 +1174,7 @@ static int mei_pci_resume(struct device *device)
} }
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
dev->mei_state = MEI_POWER_UP; dev->dev_state = MEI_DEV_POWER_UP;
mei_reset(dev, 1); mei_reset(dev, 1);
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
...@@ -1201,7 +1192,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume); ...@@ -1201,7 +1192,7 @@ static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
* PCI driver structure * PCI driver structure
*/ */
static struct pci_driver mei_driver = { static struct pci_driver mei_driver = {
.name = mei_driver_name, .name = KBUILD_MODNAME,
.id_table = mei_pci_tbl, .id_table = mei_pci_tbl,
.probe = mei_probe, .probe = mei_probe,
.remove = __devexit_p(mei_remove), .remove = __devexit_p(mei_remove),
......
...@@ -25,18 +25,20 @@ ...@@ -25,18 +25,20 @@
/* /*
* watch dog definition * watch dog definition
*/ */
#define MEI_WATCHDOG_DATA_SIZE 16 #define MEI_WD_HDR_SIZE 4
#define MEI_START_WD_DATA_SIZE 20 #define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE
#define MEI_WD_PARAMS_SIZE 4 #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_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) #define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
/*
* MEI PCI Device object
*/
extern struct pci_dev *mei_device;
/* /*
* AMTHI Client UUID * AMTHI Client UUID
...@@ -53,20 +55,22 @@ extern const uuid_le mei_wd_guid; ...@@ -53,20 +55,22 @@ extern const uuid_le mei_wd_guid;
*/ */
extern const u8 mei_wd_state_independence_msg[3][4]; 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 * Number of File descriptors/handles
* that can be opened to the driver. * 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 AMTHI
* minus internal client for Watchdog * 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 */ /* File state */
enum file_state { enum file_state {
...@@ -78,17 +82,19 @@ enum file_state { ...@@ -78,17 +82,19 @@ enum file_state {
}; };
/* MEI device states */ /* MEI device states */
enum mei_states { enum mei_dev_state {
MEI_INITIALIZING = 0, MEI_DEV_INITIALIZING = 0,
MEI_INIT_CLIENTS, MEI_DEV_INIT_CLIENTS,
MEI_ENABLED, MEI_DEV_ENABLED,
MEI_RESETING, MEI_DEV_RESETING,
MEI_DISABLED, MEI_DEV_DISABLED,
MEI_RECOVERING_FROM_RESET, MEI_DEV_RECOVERING_FROM_RESET,
MEI_POWER_DOWN, MEI_DEV_POWER_DOWN,
MEI_POWER_UP MEI_DEV_POWER_UP
}; };
const char *mei_dev_state_str(int state);
/* init clients states*/ /* init clients states*/
enum mei_init_clients_states { enum mei_init_clients_states {
MEI_START_MESSAGE = 0, MEI_START_MESSAGE = 0,
...@@ -113,6 +119,12 @@ enum mei_file_transaction_states { ...@@ -113,6 +119,12 @@ enum mei_file_transaction_states {
MEI_READ_COMPLETE MEI_READ_COMPLETE
}; };
enum mei_wd_states {
MEI_WD_IDLE,
MEI_WD_RUNNING,
MEI_WD_STOPPING,
};
/* MEI CB */ /* MEI CB */
enum mei_cb_major_types { enum mei_cb_major_types {
MEI_READ = 0, MEI_READ = 0,
...@@ -128,7 +140,7 @@ enum mei_cb_major_types { ...@@ -128,7 +140,7 @@ enum mei_cb_major_types {
struct mei_message_data { struct mei_message_data {
u32 size; u32 size;
unsigned char *data; unsigned char *data;
} __packed; };
struct mei_cl_cb { struct mei_cl_cb {
...@@ -218,10 +230,9 @@ struct mei_device { ...@@ -218,10 +230,9 @@ struct mei_device {
/* /*
* mei device states * mei device states
*/ */
enum mei_states mei_state; enum mei_dev_state dev_state;
enum mei_init_clients_states init_clients_state; enum mei_init_clients_states init_clients_state;
u16 init_clients_timer; u16 init_clients_timer;
bool stop;
bool need_reset; bool need_reset;
u32 extra_write_index; u32 extra_write_index;
...@@ -241,12 +252,11 @@ struct mei_device { ...@@ -241,12 +252,11 @@ struct mei_device {
bool mei_host_buffer_is_empty; bool mei_host_buffer_is_empty;
struct mei_cl wd_cl; struct mei_cl wd_cl;
enum mei_wd_states wd_state;
bool wd_interface_reg; bool wd_interface_reg;
bool wd_pending; bool wd_pending;
bool wd_stopped; u16 wd_timeout;
bool wd_bypass; /* if false, don't refresh watchdog ME client */ unsigned char wd_data[MEI_WD_START_MSG_SIZE];
u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
unsigned char wd_data[MEI_START_WD_DATA_SIZE];
struct file *iamthif_file_object; struct file *iamthif_file_object;
...@@ -279,9 +289,10 @@ void mei_host_init_iamthif(struct mei_device *dev); ...@@ -279,9 +289,10 @@ void mei_host_init_iamthif(struct mei_device *dev);
void mei_allocate_me_clients_storage(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, int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl,
struct mei_cl *priv, const uuid_le *cguid, u8 host_client_id);
const uuid_le *cguid, u8 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 * MEI IO List Functions
...@@ -348,7 +359,6 @@ void mei_run_next_iamthif_cmd(struct mei_device *dev); ...@@ -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); 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 * Register Access Function
......
...@@ -48,8 +48,8 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, ...@@ -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) static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
{ {
dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", 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_start_wd_params, MEI_WD_HDR_SIZE);
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16)); memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16));
} }
/** /**
...@@ -66,10 +66,11 @@ int mei_wd_host_init(struct mei_device *dev) ...@@ -66,10 +66,11 @@ int mei_wd_host_init(struct mei_device *dev)
/* look for WD client and connect to it */ /* look for WD client and connect to it */
dev->wd_cl.state = MEI_FILE_DISCONNECTED; 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 */ /* 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); &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
dev_dbg(&dev->pdev->dev, "wd: check client\n"); dev_dbg(&dev->pdev->dev, "wd: check client\n");
...@@ -108,10 +109,10 @@ int mei_wd_send(struct mei_device *dev) ...@@ -108,10 +109,10 @@ int mei_wd_send(struct mei_device *dev)
mei_hdr->msg_complete = 1; mei_hdr->msg_complete = 1;
mei_hdr->reserved = 0; mei_hdr->reserved = 0;
if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE)) if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE))
mei_hdr->length = MEI_START_WD_DATA_SIZE; mei_hdr->length = MEI_WD_START_MSG_SIZE;
else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE)) else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE))
mei_hdr->length = MEI_WD_PARAMS_SIZE; mei_hdr->length = MEI_WD_STOP_MSG_SIZE;
else else
return -EINVAL; return -EINVAL;
...@@ -128,18 +129,17 @@ int mei_wd_send(struct mei_device *dev) ...@@ -128,18 +129,17 @@ int mei_wd_send(struct mei_device *dev)
* -EIO when message send fails * -EIO when message send fails
* -EINVAL when invalid message is to be sent * -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; int ret;
u16 wd_timeout = dev->wd_timeout;
cancel_delayed_work(&dev->timer_work); if (dev->wd_cl.state != MEI_FILE_CONNECTED ||
if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout) dev->wd_state != MEI_WD_RUNNING)
return 0; return 0;
dev->wd_timeout = 0; memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE);
memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
dev->stop = true; dev->wd_state = MEI_WD_STOPPING;
ret = mei_flow_ctrl_creds(dev, &dev->wd_cl); ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
if (ret < 0) if (ret < 0)
...@@ -161,13 +161,14 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) ...@@ -161,13 +161,14 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
} else { } else {
dev->wd_pending = true; dev->wd_pending = true;
} }
dev->wd_stopped = false;
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
ret = wait_event_interruptible_timeout(dev->wait_stop_wd, 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); 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); dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
ret = 0; ret = 0;
} else { } else {
...@@ -177,9 +178,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) ...@@ -177,9 +178,6 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
"wd: stop failed to complete ret=%d.\n", ret); "wd: stop failed to complete ret=%d.\n", ret);
} }
if (preserve)
dev->wd_timeout = wd_timeout;
out: out:
return ret; return ret;
} }
...@@ -196,16 +194,16 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) ...@@ -196,16 +194,16 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
int err = -ENODEV; int err = -ENODEV;
struct mei_device *dev; struct mei_device *dev;
dev = pci_get_drvdata(mei_device); dev = watchdog_get_drvdata(wd_dev);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->dev_state != MEI_DEV_ENABLED) {
dev_dbg(&dev->pdev->dev, dev_dbg(&dev->pdev->dev,
"wd: mei_state != MEI_ENABLED mei_state = %d\n", "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n",
dev->mei_state); mei_dev_state_str(dev->dev_state));
goto end_unlock; goto end_unlock;
} }
...@@ -233,13 +231,13 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) ...@@ -233,13 +231,13 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
static int mei_wd_ops_stop(struct watchdog_device *wd_dev) static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
{ {
struct mei_device *dev; struct mei_device *dev;
dev = pci_get_drvdata(mei_device);
dev = watchdog_get_drvdata(wd_dev);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
mei_wd_stop(dev, false); mei_wd_stop(dev);
mutex_unlock(&dev->device_lock); mutex_unlock(&dev->device_lock);
return 0; return 0;
...@@ -256,8 +254,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) ...@@ -256,8 +254,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
{ {
int ret = 0; int ret = 0;
struct mei_device *dev; struct mei_device *dev;
dev = pci_get_drvdata(mei_device);
dev = watchdog_get_drvdata(wd_dev);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
...@@ -269,6 +267,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) ...@@ -269,6 +267,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
goto end; goto end;
} }
dev->wd_state = MEI_WD_RUNNING;
/* Check if we can send the ping to HW*/ /* Check if we can send the ping to HW*/
if (dev->mei_host_buffer_is_empty && if (dev->mei_host_buffer_is_empty &&
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
...@@ -309,13 +309,13 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) ...@@ -309,13 +309,13 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout) static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
{ {
struct mei_device *dev; struct mei_device *dev;
dev = pci_get_drvdata(mei_device);
dev = watchdog_get_drvdata(wd_dev);
if (!dev) if (!dev)
return -ENODEV; return -ENODEV;
/* Check Timeout value */ /* 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; return -EINVAL;
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
...@@ -341,36 +341,41 @@ static const struct watchdog_ops wd_ops = { ...@@ -341,36 +341,41 @@ static const struct watchdog_ops wd_ops = {
}; };
static const struct watchdog_info wd_info = { static const struct watchdog_info wd_info = {
.identity = INTEL_AMT_WATCHDOG_ID, .identity = INTEL_AMT_WATCHDOG_ID,
.options = WDIOF_KEEPALIVEPING | WDIOF_ALARMONLY, .options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_ALARMONLY,
}; };
static struct watchdog_device amt_wd_dev = { static struct watchdog_device amt_wd_dev = {
.info = &wd_info, .info = &wd_info,
.ops = &wd_ops, .ops = &wd_ops,
.timeout = AMT_WD_DEFAULT_TIMEOUT, .timeout = MEI_WD_DEFAULT_TIMEOUT,
.min_timeout = AMT_WD_MIN_TIMEOUT, .min_timeout = MEI_WD_MIN_TIMEOUT,
.max_timeout = AMT_WD_MAX_TIMEOUT, .max_timeout = MEI_WD_MAX_TIMEOUT,
}; };
void mei_watchdog_register(struct mei_device *dev) 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)) { if (watchdog_register_device(&amt_wd_dev)) {
dev_err(&dev->pdev->dev, dev_err(&dev->pdev->dev,
"wd: unable to register watchdog device.\n"); "wd: unable to register watchdog device.\n");
dev->wd_interface_reg = false; dev->wd_interface_reg = false;
} else { return;
}
dev_dbg(&dev->pdev->dev, dev_dbg(&dev->pdev->dev,
"wd: successfully register watchdog interface.\n"); "wd: successfully register watchdog interface.\n");
dev->wd_interface_reg = true; dev->wd_interface_reg = true;
} watchdog_set_drvdata(&amt_wd_dev, dev);
} }
void mei_watchdog_unregister(struct mei_device *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); watchdog_unregister_device(&amt_wd_dev);
dev->wd_interface_reg = false; dev->wd_interface_reg = false;
} }
......
...@@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev, ...@@ -699,7 +699,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
chip->pch_phub_base_address = pci_iomap(pdev, 1, 0); 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__); dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
ret = -ENOMEM; ret = -ENOMEM;
goto err_pci_iomap; goto err_pci_iomap;
...@@ -893,18 +893,7 @@ static struct pci_driver pch_phub_driver = { ...@@ -893,18 +893,7 @@ static struct pci_driver pch_phub_driver = {
.resume = pch_phub_resume .resume = pch_phub_resume
}; };
static int __init pch_phub_pci_init(void) module_pci_driver(pch_phub_driver);
{
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_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB"); MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -30,11 +30,13 @@ ...@@ -30,11 +30,13 @@
#include <linux/ti_wilink_st.h> #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, /* function pointer pointing to either,
* st_kim_recv during registration to receive fw download responses * st_kim_recv during registration to receive fw download responses
* st_int_recv after registration to receive proto stack 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, 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, ...@@ -100,7 +102,7 @@ int st_int_write(struct st_data_s *st_gdata,
* push the skb received to relevant * push the skb received to relevant
* protocol stacks * 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); 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) ...@@ -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 * This function is being called with spin lock held, protocol drivers are
* only expected to complete their waits and do nothing more than that. * 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; unsigned char i = 0;
pr_info(" %s ", __func__); pr_info(" %s ", __func__);
...@@ -379,7 +381,7 @@ void st_int_recv(void *disc_data, ...@@ -379,7 +381,7 @@ void st_int_recv(void *disc_data,
* completely, return that skb which has the pending data. * completely, return that skb which has the pending data.
* In normal cases, return top of txq. * 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; struct sk_buff *returning_skb;
...@@ -401,7 +403,7 @@ struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata) ...@@ -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 * txq and waitq needs protection since the other contexts
* may be sending data, waking up chip. * 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; unsigned long flags = 0;
......
...@@ -63,10 +63,27 @@ static struct platform_device *st_get_plat_device(int id) ...@@ -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 * in case of error don't complete so that waiting for proper
* response times out * 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; 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("no proper response during fw download");
pr_err("data6 %x", skb->data[5]); pr_err("data6 %x", skb->data[5]);
kfree_skb(skb); kfree_skb(skb);
...@@ -119,7 +136,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len) ...@@ -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 * have been observed to come in bursts of different
* tty_receive and hence the logic * 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 *data, long count)
{ {
const unsigned char *ptr; const unsigned char *ptr;
...@@ -207,16 +224,19 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) ...@@ -207,16 +224,19 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return -EIO; return -EIO;
} }
if (!wait_for_completion_timeout if (!wait_for_completion_interruptible_timeout(
(&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) { &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
pr_err(" waiting for ver info- timed out "); pr_err(" waiting for ver info- timed out ");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
INIT_COMPLETION(kim_gdata->kim_rcvd); INIT_COMPLETION(kim_gdata->kim_rcvd);
/* the positions 12 & 13 in the response buffer provide with the
* chip, major & minor numbers
*/
version = version =
MAKEWORD(kim_gdata->resp_buffer[13], MAKEWORD(kim_gdata->resp_buffer[12],
kim_gdata->resp_buffer[14]); kim_gdata->resp_buffer[13]);
chip = (version & 0x7C00) >> 10; chip = (version & 0x7C00) >> 10;
min_ver = (version & 0x007F); min_ver = (version & 0x007F);
maj_ver = (version & 0x0380) >> 7; maj_ver = (version & 0x0380) >> 7;
...@@ -236,7 +256,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name) ...@@ -236,7 +256,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
return 0; 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; unsigned char *nxt_action, *cur_action;
cur_action = *ptr; cur_action = *ptr;
...@@ -370,8 +390,8 @@ static long download_firmware(struct kim_data_s *kim_gdata) ...@@ -370,8 +390,8 @@ static long download_firmware(struct kim_data_s *kim_gdata)
break; break;
case ACTION_WAIT_EVENT: /* wait */ case ACTION_WAIT_EVENT: /* wait */
pr_debug("W"); pr_debug("W");
if (!wait_for_completion_timeout if (!wait_for_completion_interruptible_timeout(
(&kim_gdata->kim_rcvd, &kim_gdata->kim_rcvd,
msecs_to_jiffies(CMD_RESP_TIME))) { msecs_to_jiffies(CMD_RESP_TIME))) {
pr_err("response timeout during fw download "); pr_err("response timeout during fw download ");
/* timed out */ /* timed out */
...@@ -410,16 +430,10 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count) ...@@ -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 st_data_s *st_gdata = (struct st_data_s *)disc_data;
struct kim_data_s *kim_gdata = st_gdata->kim_data; struct kim_data_s *kim_gdata = st_gdata->kim_data;
/* copy to local buffer */ /* proceed to gather all data and distinguish read fw version response
if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) { * from other fw responses when data gathering is complete
/* must be the read_ver_cmd */ */
memcpy(kim_gdata->resp_buffer, data, count);
complete_all(&kim_gdata->kim_rcvd);
return;
} else {
kim_int_recv(kim_gdata, data, count); kim_int_recv(kim_gdata, data, count);
/* either completes or times out */
}
return; return;
} }
...@@ -454,11 +468,6 @@ long st_kim_start(void *kim_data) ...@@ -454,11 +468,6 @@ long st_kim_start(void *kim_data)
if (pdata->chip_enable) if (pdata->chip_enable)
pdata->chip_enable(kim_gdata); 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 */ /* re-initialize the completion */
INIT_COMPLETION(kim_gdata->ldisc_installed); INIT_COMPLETION(kim_gdata->ldisc_installed);
/* send notification to UIM */ /* send notification to UIM */
...@@ -467,8 +476,8 @@ long st_kim_start(void *kim_data) ...@@ -467,8 +476,8 @@ long st_kim_start(void *kim_data)
sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
NULL, "install"); NULL, "install");
/* wait for ldisc to be installed */ /* wait for ldisc to be installed */
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, err = wait_for_completion_interruptible_timeout(
msecs_to_jiffies(LDISC_TIME)); &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
if (!err) { if (!err) {
/* ldisc installation timeout, /* ldisc installation timeout,
* flush uart, power cycle BT_EN */ * flush uart, power cycle BT_EN */
...@@ -500,8 +509,7 @@ long st_kim_start(void *kim_data) ...@@ -500,8 +509,7 @@ long st_kim_start(void *kim_data)
* (b) upon failure to either install ldisc or download firmware. * (b) upon failure to either install ldisc or download firmware.
* The function is responsible to (a) notify UIM about un-installation, * The function is responsible to (a) notify UIM about un-installation,
* (b) flush UART if the ldisc was installed. * (b) flush UART if the ldisc was installed.
* (c) reset BT_EN - pull down nshutdown at the end. * (c) invoke platform's chip disabling routine.
* (d) invoke platform's chip disabling routine.
*/ */
long st_kim_stop(void *kim_data) long st_kim_stop(void *kim_data)
{ {
...@@ -526,20 +534,13 @@ 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"); sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
/* wait for ldisc to be un-installed */ /* wait for ldisc to be un-installed */
err = wait_for_completion_timeout(&kim_gdata->ldisc_installed, err = wait_for_completion_interruptible_timeout(
msecs_to_jiffies(LDISC_TIME)); &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
if (!err) { /* timeout */ if (!err) { /* timeout */
pr_err(" timed out waiting for ldisc to be un-installed"); 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 */ /* platform specific disable */
if (pdata->chip_disable) if (pdata->chip_disable)
pdata->chip_disable(kim_gdata); pdata->chip_disable(kim_gdata);
...@@ -701,7 +702,7 @@ static const struct file_operations list_debugfs_fops = { ...@@ -701,7 +702,7 @@ static const struct file_operations list_debugfs_fops = {
* board-*.c file * board-*.c file
*/ */
struct dentry *kim_debugfs_dir; static struct dentry *kim_debugfs_dir;
static int kim_probe(struct platform_device *pdev) static int kim_probe(struct platform_device *pdev)
{ {
long status; long status;
...@@ -731,20 +732,6 @@ static int kim_probe(struct platform_device *pdev) ...@@ -731,20 +732,6 @@ static int kim_probe(struct platform_device *pdev)
/* refer to itself */ /* refer to itself */
kim_gdata->core_data->kim_data = kim_gdata; 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 /* get reference of pdev for request_firmware
*/ */
kim_gdata->kim_pdev = pdev; kim_gdata->kim_pdev = pdev;
...@@ -780,18 +767,10 @@ static int kim_probe(struct platform_device *pdev) ...@@ -780,18 +767,10 @@ static int kim_probe(struct platform_device *pdev)
static int kim_remove(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; struct kim_data_s *kim_gdata;
kim_gdata = dev_get_drvdata(&pdev->dev); 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); debugfs_remove_recursive(kim_debugfs_dir);
sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
pr_info("sysfs entries removed"); pr_info("sysfs entries removed");
...@@ -804,7 +783,7 @@ static int kim_remove(struct platform_device *pdev) ...@@ -804,7 +783,7 @@ static int kim_remove(struct platform_device *pdev)
return 0; 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; 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) ...@@ -814,7 +793,7 @@ int kim_suspend(struct platform_device *pdev, pm_message_t state)
return -EOPNOTSUPP; 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; struct ti_st_plat_data *pdata = pdev->dev.platform_data;
......
...@@ -434,21 +434,9 @@ static struct pci_driver tifm_7xx1_driver = { ...@@ -434,21 +434,9 @@ static struct pci_driver tifm_7xx1_driver = {
.resume = tifm_7xx1_resume, .resume = tifm_7xx1_resume,
}; };
static int __init tifm_7xx1_init(void) module_pci_driver(tifm_7xx1_driver);
{
return pci_register_driver(&tifm_7xx1_driver);
}
static void __exit tifm_7xx1_exit(void)
{
pci_unregister_driver(&tifm_7xx1_driver);
}
MODULE_AUTHOR("Alex Dubov"); MODULE_AUTHOR("Alex Dubov");
MODULE_DESCRIPTION("TI FlashMedia host driver"); MODULE_DESCRIPTION("TI FlashMedia host driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl); MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl);
MODULE_VERSION(DRIVER_VERSION); MODULE_VERSION(DRIVER_VERSION);
module_init(tifm_7xx1_init);
module_exit(tifm_7xx1_exit);
...@@ -60,7 +60,6 @@ config W1_MASTER_GPIO ...@@ -60,7 +60,6 @@ config W1_MASTER_GPIO
config HDQ_MASTER_OMAP config HDQ_MASTER_OMAP
tristate "OMAP HDQ driver" tristate "OMAP HDQ driver"
depends on ARCH_OMAP2PLUS
help help
Say Y here if you want support for the 1-wire or HDQ Interface Say Y here if you want support for the 1-wire or HDQ Interface
on an OMAP processor. on an OMAP processor.
......
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include "../w1.h" #include "../w1.h"
#include "../w1_int.h" #include "../w1_int.h"
...@@ -73,11 +70,11 @@ struct hdq_data { ...@@ -73,11 +70,11 @@ struct hdq_data {
}; };
static int __devinit omap_hdq_probe(struct platform_device *pdev); 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 = { static struct platform_driver omap_hdq_driver = {
.probe = omap_hdq_probe, .probe = omap_hdq_probe,
.remove = omap_hdq_remove, .remove = __devexit_p(omap_hdq_remove),
.driver = { .driver = {
.name = "omap_hdq", .name = "omap_hdq",
}, },
...@@ -538,39 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte) ...@@ -538,39 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
hdq_data->init_trans = 0; hdq_data->init_trans = 0;
mutex_unlock(&hdq_data->hdq_mutex); mutex_unlock(&hdq_data->hdq_mutex);
} }
return;
} }
static int __devinit omap_hdq_probe(struct platform_device *pdev) static int __devinit omap_hdq_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
struct hdq_data *hdq_data; struct hdq_data *hdq_data;
struct resource *res; struct resource *res;
int ret, irq; int ret, irq;
u8 rev; u8 rev;
hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
if (!hdq_data) { if (!hdq_data) {
dev_dbg(&pdev->dev, "unable to allocate memory\n"); dev_dbg(&pdev->dev, "unable to allocate memory\n");
ret = -ENOMEM; return -ENOMEM;
goto err_kmalloc;
} }
hdq_data->dev = &pdev->dev; hdq_data->dev = dev;
platform_set_drvdata(pdev, hdq_data); platform_set_drvdata(pdev, hdq_data);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_dbg(&pdev->dev, "unable to get resource\n"); dev_dbg(&pdev->dev, "unable to get resource\n");
ret = -ENXIO; return -ENXIO;
goto err_resource;
} }
hdq_data->hdq_base = ioremap(res->start, SZ_4K); hdq_data->hdq_base = devm_request_and_ioremap(dev, res);
if (!hdq_data->hdq_base) { if (!hdq_data->hdq_base) {
dev_dbg(&pdev->dev, "ioremap failed\n"); dev_dbg(&pdev->dev, "ioremap failed\n");
ret = -EINVAL; return -ENOMEM;
goto err_ioremap;
} }
hdq_data->hdq_usecount = 0; hdq_data->hdq_usecount = 0;
...@@ -591,7 +584,8 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev) ...@@ -591,7 +584,8 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
goto err_irq; 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) { if (ret < 0) {
dev_dbg(&pdev->dev, "could not request irq\n"); dev_dbg(&pdev->dev, "could not request irq\n");
goto err_irq; goto err_irq;
...@@ -616,19 +610,10 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev) ...@@ -616,19 +610,10 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
err_w1: err_w1:
pm_runtime_disable(&pdev->dev); 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; 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); struct hdq_data *hdq_data = platform_get_drvdata(pdev);
...@@ -644,27 +629,11 @@ static int omap_hdq_remove(struct platform_device *pdev) ...@@ -644,27 +629,11 @@ static int omap_hdq_remove(struct platform_device *pdev)
/* remove module dependency */ /* remove module dependency */
pm_runtime_disable(&pdev->dev); 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; return 0;
} }
static int __init module_platform_driver(omap_hdq_driver);
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_param(w1_id, int, S_IRUSR); module_param(w1_id, int, S_IRUSR);
MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/w1-gpio.h> #include <linux/w1-gpio.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include "../w1.h" #include "../w1.h"
#include "../w1_int.h" #include "../w1_int.h"
...@@ -42,12 +44,55 @@ static u8 w1_gpio_read_bit(void *data) ...@@ -42,12 +44,55 @@ static u8 w1_gpio_read_bit(void *data)
return gpio_get_value(pdata->pin) ? 1 : 0; 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) static int __init w1_gpio_probe(struct platform_device *pdev)
{ {
struct w1_bus_master *master; struct w1_bus_master *master;
struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; struct w1_gpio_platform_data *pdata;
int err; int err;
err = w1_gpio_probe_dt(pdev);
if (err < 0)
return err;
pdata = pdev->dev.platform_data;
if (!pdata) if (!pdata)
return -ENXIO; return -ENXIO;
...@@ -59,6 +104,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev) ...@@ -59,6 +104,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
if (err) if (err)
goto free_master; 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->data = pdata;
master->read_bit = w1_gpio_read_bit; master->read_bit = w1_gpio_read_bit;
...@@ -72,15 +124,21 @@ static int __init w1_gpio_probe(struct platform_device *pdev) ...@@ -72,15 +124,21 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
err = w1_add_master_device(master); err = w1_add_master_device(master);
if (err) if (err)
goto free_gpio; goto free_gpio_ext_pu;
if (pdata->enable_external_pullup) if (pdata->enable_external_pullup)
pdata->enable_external_pullup(1); 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); platform_set_drvdata(pdev, master);
return 0; return 0;
free_gpio_ext_pu:
if (gpio_is_valid(pdata->ext_pullup_enable_pin))
gpio_free(pdata->ext_pullup_enable_pin);
free_gpio: free_gpio:
gpio_free(pdata->pin); gpio_free(pdata->pin);
free_master: free_master:
...@@ -97,6 +155,9 @@ static int __exit w1_gpio_remove(struct platform_device *pdev) ...@@ -97,6 +155,9 @@ static int __exit w1_gpio_remove(struct platform_device *pdev)
if (pdata->enable_external_pullup) if (pdata->enable_external_pullup)
pdata->enable_external_pullup(0); 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); w1_remove_master_device(master);
gpio_free(pdata->pin); gpio_free(pdata->pin);
kfree(master); kfree(master);
...@@ -135,6 +196,7 @@ static struct platform_driver w1_gpio_driver = { ...@@ -135,6 +196,7 @@ static struct platform_driver w1_gpio_driver = {
.driver = { .driver = {
.name = "w1-gpio", .name = "w1-gpio",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(w1_gpio_dt_ids),
}, },
.remove = __exit_p(w1_gpio_remove), .remove = __exit_p(w1_gpio_remove),
.suspend = w1_gpio_suspend, .suspend = w1_gpio_suspend,
......
...@@ -281,9 +281,10 @@ struct kim_data_s { ...@@ -281,9 +281,10 @@ struct kim_data_s {
long st_kim_start(void *); long st_kim_start(void *);
long st_kim_stop(void *); long st_kim_stop(void *);
void st_kim_recv(void *, const unsigned char *, long count);
void st_kim_complete(void *); void st_kim_complete(void *);
void kim_st_list_protocols(struct st_data_s *, void *); void kim_st_list_protocols(struct st_data_s *, void *);
void st_kim_recv(void *, const unsigned char *, long);
/* /*
* BTS headers * BTS headers
......
...@@ -19,6 +19,7 @@ struct w1_gpio_platform_data { ...@@ -19,6 +19,7 @@ struct w1_gpio_platform_data {
unsigned int pin; unsigned int pin;
unsigned int is_open_drain:1; unsigned int is_open_drain:1;
void (*enable_external_pullup)(int enable); void (*enable_external_pullup)(int enable);
unsigned int ext_pullup_enable_pin;
}; };
#endif /* _LINUX_W1_GPIO_H */ #endif /* _LINUX_W1_GPIO_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment