提交 fb09bafd 编写于 作者: L Linus Torvalds

Merge tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging tree changes from Greg Kroah-Hartman:
 "Here is the big staging tree pull request for the 3.5-rc1 merge
  window.

  Loads of changes here, and we just narrowly added more lines than we
  added:
   622 files changed, 28356 insertions(+), 26059 deletions(-)

  But, good news is that there is a number of subsystems that moved out
  of the staging tree, to their respective "real" portions of the
  kernel.

  Code that moved out was:
	- iio core code
	- mei driver
	- vme core and bridge drivers

  There was one broken network driver that moved into staging as a step
  before it is removed from the tree (pc300), and there was a few new
  drivers added to the tree:
	- new iio drivers
	- gdm72xx wimax USB driver
	- ipack subsystem and 2 drivers

  All of the movements around have acks from the various subsystem
  maintainers, and all of this has been in the linux-next tree for a
  while.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

Fixed up various trivial conflicts, along with a non-trivial one found
in -next and pointed out by Olof Johanssen: a clean - but incorrect -
merge of the arch/arm/boot/dts/at91sam9g20.dtsi file.  Fix up manually
as per Stephen Rothwell.

* tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (536 commits)
  Staging: bcm: Remove two unused variables from Adapter.h
  Staging: bcm: Removes the volatile type definition from Adapter.h
  Staging: bcm: Rename all "INT" to "int" in Adapter.h
  Staging: bcm: Fix warning: __packed vs. __attribute__((packed)) in Adapter.h
  Staging: bcm: Correctly format all comments in Adapter.h
  Staging: bcm: Fix all whitespace issues in Adapter.h
  Staging: bcm: Properly format braces in Adapter.h
  Staging: ipack/bridges/tpci200: remove unneeded casts
  Staging: ipack/bridges/tpci200: remove TPCI200_SHORTNAME constant
  Staging: ipack: remove board_name and bus_name fields from struct ipack_device
  Staging: ipack: improve the register of a bus and a device in the bus.
  staging: comedi: cleanup all the comedi_driver 'detach' functions
  staging: comedi: remove all 'default N' in Kconfig
  staging: line6/config.h: Delete unused header
  staging: gdm72xx depends on NET
  staging: gdm72xx: Set up parent link in sysfs for gdm72xx devices
  staging: drm/omap: initial dmabuf/prime import support
  staging: drm/omap: dmabuf/prime mmap support
  pstore/ram: Add ECC support
  pstore/ram: Switch to persistent_ram routines
  ...
...@@ -108,7 +108,7 @@ Description: ...@@ -108,7 +108,7 @@ Description:
physically equivalent inputs when non differential readings are physically equivalent inputs when non differential readings are
separately available. In differential only parts, then all that separately available. In differential only parts, then all that
is required is a consistent labeling. Units after application is required is a consistent labeling. Units after application
of scale and offset are nanofarads.. of scale and offset are nanofarads.
What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw
...@@ -119,7 +119,7 @@ KernelVersion: 2.6.35 ...@@ -119,7 +119,7 @@ KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
Raw (unscaled no bias removal etc) temperature measurement. Raw (unscaled no bias removal etc) temperature measurement.
It an axis is specified it generally means that the temperature If an axis is specified it generally means that the temperature
sensor is associated with one part of a compound device (e.g. sensor is associated with one part of a compound device (e.g.
a gyroscope axis). Units after application of scale and offset a gyroscope axis). Units after application of scale and offset
are milli degrees Celsuis. are milli degrees Celsuis.
...@@ -232,7 +232,7 @@ Description: ...@@ -232,7 +232,7 @@ Description:
If known for a device, scale to be applied to <type>Y[_name]_raw If known for a device, scale to be applied to <type>Y[_name]_raw
post addition of <type>[Y][_name]_offset in order to obtain the post addition of <type>[Y][_name]_offset in order to obtain the
measured value in <type> units as specified in measured value in <type> units as specified in
<type>[Y][_name]_raw documentation.. If shared across all in <type>[Y][_name]_raw documentation. If shared across all in
channels then Y and <x|y|z> are not present and the value is channels then Y and <x|y|z> are not present and the value is
called <type>[Y][_name]_scale. The peak modifier means this called <type>[Y][_name]_scale. The peak modifier means this
value is applied to <type>Y[_name]_peak_raw values. value is applied to <type>Y[_name]_peak_raw values.
...@@ -243,6 +243,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias ...@@ -243,6 +243,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
KernelVersion: 2.6.35 KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
...@@ -258,6 +260,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale ...@@ -258,6 +260,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
KernelVersion: 2.6.35 KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
...@@ -276,6 +280,13 @@ Description: ...@@ -276,6 +280,13 @@ Description:
If a discrete set of scale values are available, they If a discrete set of scale values are available, they
are listed in this attribute. are listed in this attribute.
What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
Hardware applied gain factor. If shared across all channels,
<type>_hardwaregain is used.
What: /sys/.../in_accel_filter_low_pass_3db_frequency What: /sys/.../in_accel_filter_low_pass_3db_frequency
What: /sys/.../in_magn_filter_low_pass_3db_frequency What: /sys/.../in_magn_filter_low_pass_3db_frequency
What: /sys/.../in_anglvel_filter_low_pass_3db_frequency What: /sys/.../in_anglvel_filter_low_pass_3db_frequency
...@@ -453,10 +464,14 @@ What: /sys/.../events/in_magn_z_raw_thresh_rising_value ...@@ -453,10 +464,14 @@ What: /sys/.../events/in_magn_z_raw_thresh_rising_value
What: /sys/.../events/in_magn_z_raw_thresh_falling_value What: /sys/.../events/in_magn_z_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value
What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_raw_thresh_rising_value
What: /sys/.../events/in_voltageY_raw_thresh_falling_value What: /sys/.../events/in_voltageY_raw_thresh_falling_value
What: /sys/.../events/in_voltageY_raw_thresh_falling_value What: /sys/.../events/in_tempY_raw_thresh_rising_value
What: /sys/.../events/in_tempY_raw_thresh_falling_value
What: /sys/.../events/in_tempY_raw_thresh_falling_value What: /sys/.../events/in_tempY_raw_thresh_falling_value
What: /sys/.../events/in_illuminance0_thresh_falling_value
what: /sys/.../events/in_illuminance0_thresh_rising_value
what: /sys/.../events/in_proximity0_thresh_falling_value
what: /sys/.../events/in_proximity0_thresh_rising_value
KernelVersion: 2.6.37 KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
...@@ -490,9 +505,9 @@ What: /sys/.../events/in_magn_z_raw_roc_rising_value ...@@ -490,9 +505,9 @@ What: /sys/.../events/in_magn_z_raw_roc_rising_value
What: /sys/.../events/in_magn_z_raw_roc_falling_value What: /sys/.../events/in_magn_z_raw_roc_falling_value
What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value
What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value
What: /sys/.../events/in_voltageY_raw_roc_rising_value
What: /sys/.../events/in_voltageY_raw_roc_falling_value What: /sys/.../events/in_voltageY_raw_roc_falling_value
What: /sys/.../events/in_voltageY_raw_roc_falling_value What: /sys/.../events/in_tempY_raw_roc_rising_value
What: /sys/.../events/in_tempY_raw_roc_falling_value
What: /sys/.../events/in_tempY_raw_roc_falling_value What: /sys/.../events/in_tempY_raw_roc_falling_value
KernelVersion: 2.6.37 KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
...@@ -556,6 +571,8 @@ What: /sys/.../events/in_tempY_thresh_falling_period ...@@ -556,6 +571,8 @@ What: /sys/.../events/in_tempY_thresh_falling_period
What: /sys/.../events/in_tempY_roc_rising_period What: /sys/.../events/in_tempY_roc_rising_period
What: /sys/.../events/in_tempY_roc_falling_period What: /sys/.../events/in_tempY_roc_falling_period
What: /sys/.../events/in_accel_x&y&z_mag_falling_period What: /sys/.../events/in_accel_x&y&z_mag_falling_period
What: /sys/.../events/in_intensity0_thresh_period
What: /sys/.../events/in_proximity0_thresh_period
KernelVersion: 2.6.37 KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org Contact: linux-iio@vger.kernel.org
Description: Description:
...@@ -718,24 +735,3 @@ Contact: linux-iio@vger.kernel.org ...@@ -718,24 +735,3 @@ Contact: linux-iio@vger.kernel.org
Description: Description:
This attribute is used to read the amount of quadrature error This attribute is used to read the amount of quadrature error
present in the device at a given time. present in the device at a given time.
What: /sys/.../iio:deviceX/ac_excitation_en
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
This attribute, if available, is used to enable the AC
excitation mode found on some converters. In ac excitation mode,
the polarity of the excitation voltage is reversed on
alternate cycles, to eliminate DC errors.
What: /sys/.../iio:deviceX/bridge_switch_en
KernelVersion: 3.1.0
Contact: linux-iio@vger.kernel.org
Description:
This attribute, if available, is used to close or open the
bridge power down switch found on some converters.
In bridge applications, such as strain gauges and load cells,
the bridge itself consumes the majority of the current in the
system. To minimize the current consumption of the system,
the bridge can be disconnected (when it is not being used
using the bridge_switch_en attribute.
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \ obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \ filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
pcmcia/ spi/ timers/ watchdog/src/ pcmcia/ spi/ timers/ watchdog/src/ misc-devices/mei/
* AT91's Analog to Digital Converter (ADC)
Required properties:
- compatible: Should be "atmel,at91sam9260-adc"
- reg: Should contain ADC registers location and length
- interrupts: Should contain the IRQ line for the ADC
- atmel,adc-channel-base: Offset of the first channel data register
- atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
device
- atmel,adc-drdy-mask: Mask of the DRDY interruption in the ADC
- atmel,adc-num-channels: Number of channels available in the ADC
- atmel,adc-startup-time: Startup Time of the ADC in microseconds as
defined in the datasheet
- atmel,adc-status-register: Offset of the Interrupt Status Register
- atmel,adc-trigger-register: Offset of the Trigger Register
- atmel,adc-vref: Reference voltage in millivolts for the conversions
Optional properties:
- atmel,adc-use-external: Boolean to enable of external triggers
Optional trigger Nodes:
- Required properties:
* trigger-name: Name of the trigger exposed to the user
* trigger-value: Value to put in the Trigger register
to activate this trigger
- Optional properties:
* trigger-external: Is the trigger an external trigger?
Examples:
adc0: adc@fffb0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffb0000 0x100>;
interrupts = <20 4>;
atmel,adc-channel-base = <0x30>;
atmel,adc-channels-used = <0xff>;
atmel,adc-drdy-mask = <0x10000>;
atmel,adc-num-channels = <8>;
atmel,adc-startup-time = <40>;
atmel,adc-status-register = <0x1c>;
atmel,adc-trigger-register = <0x08>;
atmel,adc-use-external;
atmel,adc-vref = <3300>;
trigger@0 {
trigger-name = "external-rising";
trigger-value = <0x1>;
trigger-external;
};
trigger@1 {
trigger-name = "external-falling";
trigger-value = <0x2>;
trigger-external;
};
trigger@2 {
trigger-name = "external-any";
trigger-value = <0x3>;
trigger-external;
};
trigger@3 {
trigger-name = "continuous";
trigger-value = <0x6>;
};
};
* NXP LPC32xx SoC ADC controller
Required properties:
- compatible: must be "nxp,lpc3220-adc"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: The ADC interrupt
Example:
adc@40048000 {
compatible = "nxp,lpc3220-adc";
reg = <0x40048000 0x1000>;
interrupt-parent = <&mic>;
interrupts = <39 0>;
};
* ST SPEAr ADC device driver
Required properties:
- compatible: Should be "st,spear600-adc"
- reg: Address and length of the register set for the device
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the ADC interrupt
- sampling-frequency: Default sampling frequency
Optional properties:
- vref-external: External voltage reference in milli-volts. If omitted
the internal voltage reference will be used.
- average-samples: Number of samples to generate an average value. If
omitted, single data conversion will be used.
Examples:
adc: adc@d8200000 {
compatible = "st,spear600-adc";
reg = <0xd8200000 0x1000>;
interrupt-parent = <&vic1>;
interrupts = <6>;
sampling-frequency = <5000000>;
vref-external = <2500>; /* 2.5V VRef */
};
...@@ -120,6 +120,7 @@ Code Seq#(hex) Include File Comments ...@@ -120,6 +120,7 @@ Code Seq#(hex) Include File Comments
'G' 00-0F linux/gigaset_dev.h conflict! 'G' 00-0F linux/gigaset_dev.h conflict!
'H' 00-7F linux/hiddev.h conflict! 'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict! 'H' 00-0F linux/hidraw.h conflict!
'H' 01 linux/mei.h conflict!
'H' 00-0F sound/asound.h conflict! 'H' 00-0F sound/asound.h conflict!
'H' 20-40 sound/asound_fm.h conflict! 'H' 20-40 sound/asound_fm.h conflict!
'H' 80-8F sound/sfnt_info.h conflict! 'H' 80-8F sound/sfnt_info.h conflict!
......
# kbuild trick to avoid linker error. Can be omitted if a module is built.
obj- := dummy.o
# List of programs to build
hostprogs-y := mei-amt-version
HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include
# Tell kbuild to always build the programs
always := $(hostprogs-y)
TODO:
- Cleanup and split the timer function
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <bits/wordsize.h> #include <bits/wordsize.h>
#include "mei.h" #include <linux/mei.h>
/***************************************************************************** /*****************************************************************************
* Intel Management Engine Interface * Intel Management Engine Interface
......
...@@ -3,7 +3,7 @@ Ramoops oops/panic logger ...@@ -3,7 +3,7 @@ Ramoops oops/panic logger
Sergiu Iordache <sergiu@chromium.org> Sergiu Iordache <sergiu@chromium.org>
Updated: 8 August 2011 Updated: 17 November 2011
0. Introduction 0. Introduction
...@@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics. ...@@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics.
The module uses a counter to record multiple dumps but the counter gets reset The module uses a counter to record multiple dumps but the counter gets reset
on restart (i.e. new dumps after the restart will overwrite old ones). on restart (i.e. new dumps after the restart will overwrite old ones).
Ramoops also supports software ECC protection of persistent memory regions.
This might be useful when a hardware reset was used to bring the machine back
to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
corrupt, but usually it is restorable.
2. Setting the parameters 2. Setting the parameters
Setting the ramoops parameters can be done in 2 different manners: Setting the ramoops parameters can be done in 2 different manners:
...@@ -38,7 +43,7 @@ Setting the ramoops parameters can be done in 2 different manners: ...@@ -38,7 +43,7 @@ Setting the ramoops parameters can be done in 2 different manners:
2. Use a platform device and set the platform data. The parameters can then 2. Use a platform device and set the platform data. The parameters can then
be set through that platform data. An example of doing that is: be set through that platform data. An example of doing that is:
#include <linux/ramoops.h> #include <linux/pstore_ram.h>
[...] [...]
static struct ramoops_platform_data ramoops_data = { static struct ramoops_platform_data ramoops_data = {
...@@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = { ...@@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = {
.mem_address = <...>, .mem_address = <...>,
.record_size = <...>, .record_size = <...>,
.dump_oops = <...>, .dump_oops = <...>,
.ecc = <...>,
}; };
static struct platform_device ramoops_dev = { static struct platform_device ramoops_dev = {
...@@ -71,6 +77,6 @@ timestamp and a new line. The dump then continues with the actual data. ...@@ -71,6 +77,6 @@ timestamp and a new line. The dump then continues with the actual data.
4. Reading the data 4. Reading the data
The dump data can be read from memory (through /dev/mem or other means). The dump data can be read from the pstore filesystem. The format for these
Getting the module parameters, which are needed in order to parse the data, can files is "dmesg-ramoops-N", where N is the record number in memory. To delete
be done through /sys/module/ramoops/parameters/* . a stored record from RAM, simply unlink the respective pstore file.
...@@ -3406,6 +3406,7 @@ IIO SUBSYSTEM AND DRIVERS ...@@ -3406,6 +3406,7 @@ IIO SUBSYSTEM AND DRIVERS
M: Jonathan Cameron <jic23@cam.ac.uk> M: Jonathan Cameron <jic23@cam.ac.uk>
L: linux-iio@vger.kernel.org L: linux-iio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/iio/
F: drivers/staging/iio/ F: drivers/staging/iio/
IKANOS/ADI EAGLE ADSL USB DRIVER IKANOS/ADI EAGLE ADSL USB DRIVER
...@@ -3625,6 +3626,14 @@ S: Supported ...@@ -3625,6 +3626,14 @@ S: Supported
W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
F: drivers/net/wireless/iwmc3200wifi/ F: drivers/net/wireless/iwmc3200wifi/
INTEL MANAGEMENT ENGINE (mei)
M: Tomas Winkler <tomas.winkler@intel.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: include/linux/mei.h
F: drivers/misc/mei/*
F: Documentation/mei/*
IOC3 ETHERNET DRIVER IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org> M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@linux-mips.org L: linux-mips@linux-mips.org
...@@ -7350,6 +7359,18 @@ S: Maintained ...@@ -7350,6 +7359,18 @@ S: Maintained
F: drivers/vlynq/vlynq.c F: drivers/vlynq/vlynq.c
F: include/linux/vlynq.h F: include/linux/vlynq.h
VME SUBSYSTEM
M: Martyn Welch <martyn.welch@ge.com>
M: Manohar Vanga <manohar.vanga@cern.ch>
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: devel@driverdev.osuosl.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
F: Documentation/vme_api.txt
F: drivers/staging/vme/
F: drivers/vme/
F: include/linux/vme*
VMWARE VMXNET3 ETHERNET DRIVER VMWARE VMXNET3 ETHERNET DRIVER
M: Shreyas Bhatewara <sbhatewara@vmware.com> M: Shreyas Bhatewara <sbhatewara@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com> M: "VMware, Inc." <pv-drivers@vmware.com>
......
...@@ -199,6 +199,43 @@ ...@@ -199,6 +199,43 @@
interrupts = <25 4>; interrupts = <25 4>;
status = "disabled"; status = "disabled";
}; };
adc0: adc@fffb0000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xfffb0000 0x100>;
interrupts = <20 4>;
atmel,adc-use-external-triggers;
atmel,adc-channels-used = <0xff>;
atmel,adc-vref = <3300>;
atmel,adc-num-channels = <8>;
atmel,adc-startup-time = <40>;
atmel,adc-channel-base = <0x30>;
atmel,adc-drdy-mask = <0x10000>;
atmel,adc-status-register = <0x1c>;
atmel,adc-trigger-register = <0x08>;
trigger@0 {
trigger-name = "external-rising";
trigger-value = <0x1>;
trigger-external;
};
trigger@1 {
trigger-name = "external-falling";
trigger-value = <0x2>;
trigger-external;
};
trigger@2 {
trigger-name = "external-any";
trigger-value = <0x3>;
trigger-external;
};
trigger@3 {
trigger-name = "continuous";
trigger-value = <0x6>;
};
};
}; };
nand0: nand@40000000 { nand0: nand@40000000 {
......
...@@ -190,6 +190,44 @@ ...@@ -190,6 +190,44 @@
interrupts = <27 4>; interrupts = <27 4>;
status = "disabled"; status = "disabled";
}; };
adc0: adc@f804c000 {
compatible = "atmel,at91sam9260-adc";
reg = <0xf804c000 0x100>;
interrupts = <19 4>;
atmel,adc-use-external;
atmel,adc-channels-used = <0xffff>;
atmel,adc-vref = <3300>;
atmel,adc-num-channels = <12>;
atmel,adc-startup-time = <40>;
atmel,adc-channel-base = <0x50>;
atmel,adc-drdy-mask = <0x1000000>;
atmel,adc-status-register = <0x30>;
atmel,adc-trigger-register = <0xc0>;
trigger@0 {
trigger-name = "external-rising";
trigger-value = <0x1>;
trigger-external;
};
trigger@1 {
trigger-name = "external-falling";
trigger-value = <0x2>;
trigger-external;
};
trigger@2 {
trigger-name = "external-any";
trigger-value = <0x3>;
trigger-external;
};
trigger@3 {
trigger-name = "continuous";
trigger-value = <0x6>;
};
};
}; };
nand0: nand@40000000 { nand0: nand@40000000 {
......
...@@ -55,6 +55,13 @@ static struct clk adc_clk = { ...@@ -55,6 +55,13 @@ static struct clk adc_clk = {
.pmc_mask = 1 << AT91SAM9260_ID_ADC, .pmc_mask = 1 << AT91SAM9260_ID_ADC,
.type = CLK_TYPE_PERIPHERAL, .type = CLK_TYPE_PERIPHERAL,
}; };
static struct clk adc_op_clk = {
.name = "adc_op_clk",
.type = CLK_TYPE_PERIPHERAL,
.rate_hz = 5000000,
};
static struct clk usart0_clk = { static struct clk usart0_clk = {
.name = "usart0_clk", .name = "usart0_clk",
.pmc_mask = 1 << AT91SAM9260_ID_US0, .pmc_mask = 1 << AT91SAM9260_ID_US0,
...@@ -166,6 +173,7 @@ static struct clk *periph_clocks[] __initdata = { ...@@ -166,6 +173,7 @@ static struct clk *periph_clocks[] __initdata = {
&pioB_clk, &pioB_clk,
&pioC_clk, &pioC_clk,
&adc_clk, &adc_clk,
&adc_op_clk,
&usart0_clk, &usart0_clk,
&usart1_clk, &usart1_clk,
&usart2_clk, &usart2_clk,
......
...@@ -17,12 +17,15 @@ ...@@ -17,12 +17,15 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/platform_data/at91_adc.h>
#include <mach/board.h> #include <mach/board.h>
#include <mach/cpu.h> #include <mach/cpu.h>
#include <mach/at91sam9260.h> #include <mach/at91sam9260.h>
#include <mach/at91sam9260_matrix.h> #include <mach/at91sam9260_matrix.h>
#include <mach/at91_matrix.h> #include <mach/at91_matrix.h>
#include <mach/at91sam9_smc.h> #include <mach/at91sam9_smc.h>
#include <mach/at91_adc.h>
#include "generic.h" #include "generic.h"
...@@ -1340,6 +1343,93 @@ void __init at91_add_device_cf(struct at91_cf_data *data) ...@@ -1340,6 +1343,93 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
void __init at91_add_device_cf(struct at91_cf_data * data) {} void __init at91_add_device_cf(struct at91_cf_data * data) {}
#endif #endif
/* --------------------------------------------------------------------
* ADCs
* -------------------------------------------------------------------- */
#if IS_ENABLED(CONFIG_AT91_ADC)
static struct at91_adc_data adc_data;
static struct resource adc_resources[] = {
[0] = {
.start = AT91SAM9260_BASE_ADC,
.end = AT91SAM9260_BASE_ADC + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9260_ID_ADC,
.end = AT91SAM9260_ID_ADC,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device at91_adc_device = {
.name = "at91_adc",
.id = -1,
.dev = {
.platform_data = &adc_data,
},
.resource = adc_resources,
.num_resources = ARRAY_SIZE(adc_resources),
};
static struct at91_adc_trigger at91_adc_triggers[] = {
[0] = {
.name = "timer-counter-0",
.value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN,
},
[1] = {
.name = "timer-counter-1",
.value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN,
},
[2] = {
.name = "timer-counter-2",
.value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN,
},
[3] = {
.name = "external",
.value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN,
.is_external = true,
},
};
static struct at91_adc_reg_desc at91_adc_register_g20 = {
.channel_base = AT91_ADC_CHR(0),
.drdy_mask = AT91_ADC_DRDY,
.status_register = AT91_ADC_SR,
.trigger_register = AT91_ADC_MR,
};
void __init at91_add_device_adc(struct at91_adc_data *data)
{
if (!data)
return;
if (test_bit(0, &data->channels_used))
at91_set_A_periph(AT91_PIN_PC0, 0);
if (test_bit(1, &data->channels_used))
at91_set_A_periph(AT91_PIN_PC1, 0);
if (test_bit(2, &data->channels_used))
at91_set_A_periph(AT91_PIN_PC2, 0);
if (test_bit(3, &data->channels_used))
at91_set_A_periph(AT91_PIN_PC3, 0);
if (data->use_external_triggers)
at91_set_A_periph(AT91_PIN_PA22, 0);
data->num_channels = 4;
data->startup_time = 10;
data->registers = &at91_adc_register_g20;
data->trigger_number = 4;
data->trigger_list = at91_adc_triggers;
adc_data = *data;
platform_device_register(&at91_adc_device);
}
#else
void __init at91_add_device_adc(struct at91_adc_data *data) {}
#endif
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* /*
* These devices are always present and don't need any board-specific * These devices are always present and don't need any board-specific
......
...@@ -176,6 +176,12 @@ static struct clk vdec_clk = { ...@@ -176,6 +176,12 @@ static struct clk vdec_clk = {
.type = CLK_TYPE_PERIPHERAL, .type = CLK_TYPE_PERIPHERAL,
}; };
static struct clk adc_op_clk = {
.name = "adc_op_clk",
.type = CLK_TYPE_PERIPHERAL,
.rate_hz = 13200000,
};
static struct clk *periph_clocks[] __initdata = { static struct clk *periph_clocks[] __initdata = {
&pioA_clk, &pioA_clk,
&pioB_clk, &pioB_clk,
...@@ -204,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = { ...@@ -204,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
&isi_clk, &isi_clk,
&udphs_clk, &udphs_clk,
&mmc1_clk, &mmc1_clk,
&adc_op_clk,
// irq0 // irq0
}; };
...@@ -242,6 +249,8 @@ static struct clk_lookup periph_clocks_lookups[] = { ...@@ -242,6 +249,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
CLKDEV_CON_ID("pioC", &pioC_clk), CLKDEV_CON_ID("pioC", &pioC_clk),
CLKDEV_CON_ID("pioD", &pioDE_clk), CLKDEV_CON_ID("pioD", &pioDE_clk),
CLKDEV_CON_ID("pioE", &pioDE_clk), CLKDEV_CON_ID("pioE", &pioDE_clk),
/* Fake adc clock */
CLKDEV_CON_ID("adc_clk", &tsc_clk),
}; };
static struct clk_lookup usart_clocks_lookups[] = { static struct clk_lookup usart_clocks_lookups[] = {
......
...@@ -19,9 +19,12 @@ ...@@ -19,9 +19,12 @@
#include <linux/i2c-gpio.h> #include <linux/i2c-gpio.h>
#include <linux/atmel-mci.h> #include <linux/atmel-mci.h>
#include <linux/platform_data/at91_adc.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/atmel_lcdc.h> #include <video/atmel_lcdc.h>
#include <mach/at91_adc.h>
#include <mach/board.h> #include <mach/board.h>
#include <mach/at91sam9g45.h> #include <mach/at91sam9g45.h>
#include <mach/at91sam9g45_matrix.h> #include <mach/at91sam9g45_matrix.h>
...@@ -1181,6 +1184,104 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {} ...@@ -1181,6 +1184,104 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
#endif #endif
/* --------------------------------------------------------------------
* ADC
* -------------------------------------------------------------------- */
#if IS_ENABLED(CONFIG_AT91_ADC)
static struct at91_adc_data adc_data;
static struct resource adc_resources[] = {
[0] = {
.start = AT91SAM9G45_BASE_TSC,
.end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9G45_ID_TSC,
.end = AT91SAM9G45_ID_TSC,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device at91_adc_device = {
.name = "at91_adc",
.id = -1,
.dev = {
.platform_data = &adc_data,
},
.resource = adc_resources,
.num_resources = ARRAY_SIZE(adc_resources),
};
static struct at91_adc_trigger at91_adc_triggers[] = {
[0] = {
.name = "external-rising",
.value = 1,
.is_external = true,
},
[1] = {
.name = "external-falling",
.value = 2,
.is_external = true,
},
[2] = {
.name = "external-any",
.value = 3,
.is_external = true,
},
[3] = {
.name = "continuous",
.value = 6,
.is_external = false,
},
};
static struct at91_adc_reg_desc at91_adc_register_g45 = {
.channel_base = AT91_ADC_CHR(0),
.drdy_mask = AT91_ADC_DRDY,
.status_register = AT91_ADC_SR,
.trigger_register = 0x08,
};
void __init at91_add_device_adc(struct at91_adc_data *data)
{
if (!data)
return;
if (test_bit(0, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD20, 0);
if (test_bit(1, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD21, 0);
if (test_bit(2, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD22, 0);
if (test_bit(3, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD23, 0);
if (test_bit(4, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD24, 0);
if (test_bit(5, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD25, 0);
if (test_bit(6, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD26, 0);
if (test_bit(7, &data->channels_used))
at91_set_gpio_input(AT91_PIN_PD27, 0);
if (data->use_external_triggers)
at91_set_A_periph(AT91_PIN_PD28, 0);
data->num_channels = 8;
data->startup_time = 40;
data->registers = &at91_adc_register_g45;
data->trigger_number = 4;
data->trigger_list = at91_adc_triggers;
adc_data = *data;
platform_device_register(&at91_adc_device);
}
#else
void __init at91_add_device_adc(struct at91_adc_data *data) {}
#endif
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* RTT * RTT
* -------------------------------------------------------------------- */ * -------------------------------------------------------------------- */
......
...@@ -120,6 +120,11 @@ static struct clk adc_clk = { ...@@ -120,6 +120,11 @@ static struct clk adc_clk = {
.pmc_mask = 1 << AT91SAM9X5_ID_ADC, .pmc_mask = 1 << AT91SAM9X5_ID_ADC,
.type = CLK_TYPE_PERIPHERAL, .type = CLK_TYPE_PERIPHERAL,
}; };
static struct clk adc_op_clk = {
.name = "adc_op_clk",
.type = CLK_TYPE_PERIPHERAL,
.rate_hz = 5000000,
};
static struct clk dma0_clk = { static struct clk dma0_clk = {
.name = "dma0_clk", .name = "dma0_clk",
.pmc_mask = 1 << AT91SAM9X5_ID_DMA0, .pmc_mask = 1 << AT91SAM9X5_ID_DMA0,
...@@ -205,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = { ...@@ -205,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
&tcb0_clk, &tcb0_clk,
&pwm_clk, &pwm_clk,
&adc_clk, &adc_clk,
&adc_op_clk,
&dma0_clk, &dma0_clk,
&dma1_clk, &dma1_clk,
&uhphs_clk, &uhphs_clk,
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/platform_data/at91_adc.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -304,6 +306,16 @@ static void __init ek_add_device_buttons(void) ...@@ -304,6 +306,16 @@ static void __init ek_add_device_buttons(void)
static void __init ek_add_device_buttons(void) {} static void __init ek_add_device_buttons(void) {}
#endif #endif
/*
* ADCs
*/
static struct at91_adc_data ek_adc_data = {
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
.use_external_triggers = true,
.vref = 3300,
};
#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE) #if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
static struct regulator_consumer_supply ek_audio_consumer_supplies[] = { static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
REGULATOR_SUPPLY("AVDD", "0-001b"), REGULATOR_SUPPLY("AVDD", "0-001b"),
...@@ -389,6 +401,8 @@ static void __init ek_board_init(void) ...@@ -389,6 +401,8 @@ static void __init ek_board_init(void)
ek_add_device_gpio_leds(); ek_add_device_gpio_leds();
/* Push Buttons */ /* Push Buttons */
ek_add_device_buttons(); ek_add_device_buttons();
/* ADCs */
at91_add_device_adc(&ek_adc_data);
/* PCK0 provides MCLK to the WM8731 */ /* PCK0 provides MCLK to the WM8731 */
at91_set_B_periph(AT91_PIN_PC1, 0); at91_set_B_periph(AT91_PIN_PC1, 0);
/* SSC (for WM8731) */ /* SSC (for WM8731) */
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <linux/atmel-mci.h> #include <linux/atmel-mci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_data/at91_adc.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <video/atmel_lcdc.h> #include <video/atmel_lcdc.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
...@@ -305,6 +307,14 @@ static struct at91_tsadcc_data ek_tsadcc_data = { ...@@ -305,6 +307,14 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
.ts_sample_hold_time = 0x0a, .ts_sample_hold_time = 0x0a,
}; };
/*
* ADCs
*/
static struct at91_adc_data ek_adc_data = {
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
.use_external_triggers = true,
.vref = 3300,
};
/* /*
* GPIO Buttons * GPIO Buttons
...@@ -476,6 +486,8 @@ static void __init ek_board_init(void) ...@@ -476,6 +486,8 @@ static void __init ek_board_init(void)
at91_add_device_lcdc(&ek_lcdc_data); at91_add_device_lcdc(&ek_lcdc_data);
/* Touch Screen */ /* Touch Screen */
at91_add_device_tsadcc(&ek_tsadcc_data); at91_add_device_tsadcc(&ek_tsadcc_data);
/* ADC */
at91_add_device_adc(&ek_adc_data);
/* Push Buttons */ /* Push Buttons */
ek_add_device_buttons(); ek_add_device_buttons();
/* AC97 */ /* AC97 */
......
...@@ -144,4 +144,8 @@ source "drivers/extcon/Kconfig" ...@@ -144,4 +144,8 @@ source "drivers/extcon/Kconfig"
source "drivers/memory/Kconfig" source "drivers/memory/Kconfig"
source "drivers/iio/Kconfig"
source "drivers/vme/Kconfig"
endmenu endmenu
...@@ -136,3 +136,5 @@ obj-$(CONFIG_HYPERV) += hv/ ...@@ -136,3 +136,5 @@ obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_PM_DEVFREQ) += devfreq/ obj-$(CONFIG_PM_DEVFREQ) += devfreq/
obj-$(CONFIG_EXTCON) += extcon/ obj-$(CONFIG_EXTCON) += extcon/
obj-$(CONFIG_MEMORY) += memory/ obj-$(CONFIG_MEMORY) += memory/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_VME_BUS) += vme/
...@@ -585,14 +585,6 @@ config DEVPORT ...@@ -585,14 +585,6 @@ config DEVPORT
source "drivers/s390/char/Kconfig" source "drivers/s390/char/Kconfig"
config RAMOOPS
tristate "Log panic/oops to a RAM buffer"
depends on HAS_IOMEM
default n
help
This enables panic and oops messages to be logged to a circular
buffer in RAM where it can be read back at some later point.
config MSM_SMD_PKT config MSM_SMD_PKT
bool "Enable device interface for some SMD packet ports" bool "Enable device interface for some SMD packet ports"
default n default n
......
...@@ -58,7 +58,6 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o ...@@ -58,7 +58,6 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
obj-$(CONFIG_TCG_TPM) += tpm/ obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_RAMOOPS) += ramoops.o
obj-$(CONFIG_JS_RTC) += js-rtc.o obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o js-rtc-y = rtc.o
......
#
# Industrial I/O subsytem configuration
#
menuconfig IIO
tristate "Industrial I/O support"
depends on GENERIC_HARDIRQS
help
The industrial I/O subsystem provides a unified framework for
drivers for many different types of embedded sensors using a
number of different physical interfaces (i2c, spi, etc). See
Documentation/iio for more information.
if IIO
config IIO_BUFFER
bool "Enable buffer support within IIO"
help
Provide core support for various buffer based data
acquisition methods.
if IIO_BUFFER
config IIO_KFIFO_BUF
select IIO_TRIGGER
tristate "Industrial I/O buffering based on kfifo"
help
A simple fifo based on kfifo. Use this if you want a fifo
rather than a ring buffer. Note that this currently provides
no buffer events so it is up to userspace to work out how
often to read from the buffer.
endif # IIO_BUFFER
config IIO_TRIGGER
boolean "Enable triggered sampling support"
help
Provides IIO core support for triggers. Currently these
are used to initialize capture of samples to push into
ring buffers. The triggers are effectively a 'capture
data now' interrupt.
config IIO_CONSUMERS_PER_TRIGGER
int "Maximum number of consumers per trigger"
depends on IIO_TRIGGER
default "2"
help
This value controls the maximum number of consumers that a
given trigger may handle. Default is 2.
source "drivers/iio/adc/Kconfig"
source "drivers/iio/amplifiers/Kconfig"
endif # IIO
#
# Makefile for the industrial I/O core.
#
obj-$(CONFIG_IIO) += industrialio.o
industrialio-y := industrialio-core.o industrialio-event.o inkern.o
industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
obj-y += adc/
obj-y += amplifiers/
#
# ADC drivers
#
menu "Analog to digital converters"
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
select IIO_BUFFER
select IIO_KFIFO_BUF
select IIO_TRIGGER
select SYSFS
help
Say yes here to build support for Atmel AT91 ADC.
endmenu
#
# Makefile for IIO ADC drivers
#
obj-$(CONFIG_AT91_ADC) += at91_adc.o
/*
* Driver for the ADC present in the Atmel AT91 evaluation boards.
*
* Copyright 2011 Free Electrons
*
* Licensed under the GPLv2 or later.
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/platform_data/at91_adc.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <mach/at91_adc.h>
#define AT91_ADC_CHAN(st, ch) \
(st->registers->channel_base + (ch * 4))
#define at91_adc_readl(st, reg) \
(readl_relaxed(st->reg_base + reg))
#define at91_adc_writel(st, reg, val) \
(writel_relaxed(val, st->reg_base + reg))
struct at91_adc_state {
struct clk *adc_clk;
u16 *buffer;
unsigned long channels_mask;
struct clk *clk;
bool done;
int irq;
bool irq_enabled;
u16 last_value;
struct mutex lock;
u8 num_channels;
void __iomem *reg_base;
struct at91_adc_reg_desc *registers;
u8 startup_time;
struct iio_trigger **trig;
struct at91_adc_trigger *trigger_list;
u32 trigger_number;
bool use_external;
u32 vref_mv;
wait_queue_head_t wq_data_avail;
};
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *idev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(idev);
struct iio_buffer *buffer = idev->buffer;
int i, j = 0;
for (i = 0; i < idev->masklength; i++) {
if (!test_bit(i, idev->active_scan_mask))
continue;
st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i));
j++;
}
if (idev->scan_timestamp) {
s64 *timestamp = (s64 *)((u8 *)st->buffer +
ALIGN(j, sizeof(s64)));
*timestamp = pf->timestamp;
}
buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp);
iio_trigger_notify_done(idev->trig);
st->irq_enabled = true;
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_ADC_LCDR);
enable_irq(st->irq);
return IRQ_HANDLED;
}
static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
{
struct iio_dev *idev = private;
struct at91_adc_state *st = iio_priv(idev);
u32 status = at91_adc_readl(st, st->registers->status_register);
if (!(status & st->registers->drdy_mask))
return IRQ_HANDLED;
if (iio_buffer_enabled(idev)) {
disable_irq_nosync(irq);
st->irq_enabled = false;
iio_trigger_poll(idev->trig, iio_get_time_ns());
} else {
st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
st->done = true;
wake_up_interruptible(&st->wq_data_avail);
}
return IRQ_HANDLED;
}
static int at91_adc_channel_init(struct iio_dev *idev)
{
struct at91_adc_state *st = iio_priv(idev);
struct iio_chan_spec *chan_array, *timestamp;
int bit, idx = 0;
idev->num_channels = bitmap_weight(&st->channels_mask,
st->num_channels) + 1;
chan_array = devm_kzalloc(&idev->dev,
((idev->num_channels + 1) *
sizeof(struct iio_chan_spec)),
GFP_KERNEL);
if (!chan_array)
return -ENOMEM;
for_each_set_bit(bit, &st->channels_mask, st->num_channels) {
struct iio_chan_spec *chan = chan_array + idx;
chan->type = IIO_VOLTAGE;
chan->indexed = 1;
chan->channel = bit;
chan->scan_index = idx;
chan->scan_type.sign = 'u';
chan->scan_type.realbits = 10;
chan->scan_type.storagebits = 16;
chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
IIO_CHAN_INFO_RAW_SEPARATE_BIT;
idx++;
}
timestamp = chan_array + idx;
timestamp->type = IIO_TIMESTAMP;
timestamp->channel = -1;
timestamp->scan_index = idx;
timestamp->scan_type.sign = 's';
timestamp->scan_type.realbits = 64;
timestamp->scan_type.storagebits = 64;
idev->channels = chan_array;
return idev->num_channels;
}
static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev,
struct at91_adc_trigger *triggers,
const char *trigger_name)
{
struct at91_adc_state *st = iio_priv(idev);
u8 value = 0;
int i;
for (i = 0; i < st->trigger_number; i++) {
char *name = kasprintf(GFP_KERNEL,
"%s-dev%d-%s",
idev->name,
idev->id,
triggers[i].name);
if (!name)
return -ENOMEM;
if (strcmp(trigger_name, name) == 0) {
value = triggers[i].value;
kfree(name);
break;
}
kfree(name);
}
return value;
}
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
{
struct iio_dev *idev = trig->private_data;
struct at91_adc_state *st = iio_priv(idev);
struct iio_buffer *buffer = idev->buffer;
struct at91_adc_reg_desc *reg = st->registers;
u32 status = at91_adc_readl(st, reg->trigger_register);
u8 value;
u8 bit;
value = at91_adc_get_trigger_value_by_name(idev,
st->trigger_list,
idev->trig->name);
if (value == 0)
return -EINVAL;
if (state) {
st->buffer = kmalloc(idev->scan_bytes, GFP_KERNEL);
if (st->buffer == NULL)
return -ENOMEM;
at91_adc_writel(st, reg->trigger_register,
status | value);
for_each_set_bit(bit, buffer->scan_mask,
st->num_channels) {
struct iio_chan_spec const *chan = idev->channels + bit;
at91_adc_writel(st, AT91_ADC_CHER,
AT91_ADC_CH(chan->channel));
}
at91_adc_writel(st, AT91_ADC_IER, reg->drdy_mask);
} else {
at91_adc_writel(st, AT91_ADC_IDR, reg->drdy_mask);
at91_adc_writel(st, reg->trigger_register,
status & ~value);
for_each_set_bit(bit, buffer->scan_mask,
st->num_channels) {
struct iio_chan_spec const *chan = idev->channels + bit;
at91_adc_writel(st, AT91_ADC_CHDR,
AT91_ADC_CH(chan->channel));
}
kfree(st->buffer);
}
return 0;
}
static const struct iio_trigger_ops at91_adc_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = &at91_adc_configure_trigger,
};
static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev,
struct at91_adc_trigger *trigger)
{
struct iio_trigger *trig;
int ret;
trig = iio_trigger_alloc("%s-dev%d-%s", idev->name,
idev->id, trigger->name);
if (trig == NULL)
return NULL;
trig->dev.parent = idev->dev.parent;
trig->private_data = idev;
trig->ops = &at91_adc_trigger_ops;
ret = iio_trigger_register(trig);
if (ret)
return NULL;
return trig;
}
static int at91_adc_trigger_init(struct iio_dev *idev)
{
struct at91_adc_state *st = iio_priv(idev);
int i, ret;
st->trig = devm_kzalloc(&idev->dev,
st->trigger_number * sizeof(st->trig),
GFP_KERNEL);
if (st->trig == NULL) {
ret = -ENOMEM;
goto error_ret;
}
for (i = 0; i < st->trigger_number; i++) {
if (st->trigger_list[i].is_external && !(st->use_external))
continue;
st->trig[i] = at91_adc_allocate_trigger(idev,
st->trigger_list + i);
if (st->trig[i] == NULL) {
dev_err(&idev->dev,
"Could not allocate trigger %d\n", i);
ret = -ENOMEM;
goto error_trigger;
}
}
return 0;
error_trigger:
for (i--; i >= 0; i--) {
iio_trigger_unregister(st->trig[i]);
iio_trigger_free(st->trig[i]);
}
error_ret:
return ret;
}
static void at91_adc_trigger_remove(struct iio_dev *idev)
{
struct at91_adc_state *st = iio_priv(idev);
int i;
for (i = 0; i < st->trigger_number; i++) {
iio_trigger_unregister(st->trig[i]);
iio_trigger_free(st->trig[i]);
}
}
static const struct iio_buffer_setup_ops at91_adc_buffer_ops = {
.preenable = &iio_sw_buffer_preenable,
.postenable = &iio_triggered_buffer_postenable,
.predisable = &iio_triggered_buffer_predisable,
};
static int at91_adc_buffer_init(struct iio_dev *idev)
{
int ret;
idev->buffer = iio_kfifo_allocate(idev);
if (!idev->buffer) {
ret = -ENOMEM;
goto error_ret;
}
idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
&at91_adc_trigger_handler,
IRQF_ONESHOT,
idev,
"%s-consumer%d",
idev->name,
idev->id);
if (idev->pollfunc == NULL) {
ret = -ENOMEM;
goto error_pollfunc;
}
idev->setup_ops = &at91_adc_buffer_ops;
idev->modes |= INDIO_BUFFER_TRIGGERED;
ret = iio_buffer_register(idev,
idev->channels,
idev->num_channels);
if (ret)
goto error_register;
return 0;
error_register:
iio_dealloc_pollfunc(idev->pollfunc);
error_pollfunc:
iio_kfifo_free(idev->buffer);
error_ret:
return ret;
}
static void at91_adc_buffer_remove(struct iio_dev *idev)
{
iio_buffer_unregister(idev);
iio_dealloc_pollfunc(idev->pollfunc);
iio_kfifo_free(idev->buffer);
}
static int at91_adc_read_raw(struct iio_dev *idev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct at91_adc_state *st = iio_priv(idev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&st->lock);
at91_adc_writel(st, AT91_ADC_CHER,
AT91_ADC_CH(chan->channel));
at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask);
at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START);
ret = wait_event_interruptible_timeout(st->wq_data_avail,
st->done,
msecs_to_jiffies(1000));
if (ret == 0)
return -ETIMEDOUT;
else if (ret < 0)
return ret;
*val = st->last_value;
at91_adc_writel(st, AT91_ADC_CHDR,
AT91_ADC_CH(chan->channel));
at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask);
st->last_value = 0;
st->done = false;
mutex_unlock(&st->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = (st->vref_mv * 1000) >> chan->scan_type.realbits;
*val2 = 0;
return IIO_VAL_INT_PLUS_MICRO;
default:
break;
}
return -EINVAL;
}
static int at91_adc_probe_dt(struct at91_adc_state *st,
struct platform_device *pdev)
{
struct iio_dev *idev = iio_priv_to_dev(st);
struct device_node *node = pdev->dev.of_node;
struct device_node *trig_node;
int i = 0, ret;
u32 prop;
if (!node)
return -EINVAL;
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->channels_mask = prop;
if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) {
dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->num_channels = prop;
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->startup_time = prop;
if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->vref_mv = prop;
st->registers = devm_kzalloc(&idev->dev,
sizeof(struct at91_adc_reg_desc),
GFP_KERNEL);
if (!st->registers) {
dev_err(&idev->dev, "Could not allocate register memory.\n");
ret = -ENOMEM;
goto error_ret;
}
if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) {
dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->registers->channel_base = prop;
if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) {
dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->registers->drdy_mask = prop;
if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) {
dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->registers->status_register = prop;
if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) {
dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
st->registers->trigger_register = prop;
st->trigger_number = of_get_child_count(node);
st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
sizeof(struct at91_adc_trigger),
GFP_KERNEL);
if (!st->trigger_list) {
dev_err(&idev->dev, "Could not allocate trigger list memory.\n");
ret = -ENOMEM;
goto error_ret;
}
for_each_child_of_node(node, trig_node) {
struct at91_adc_trigger *trig = st->trigger_list + i;
const char *name;
if (of_property_read_string(trig_node, "trigger-name", &name)) {
dev_err(&idev->dev, "Missing trigger-name property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
trig->name = name;
if (of_property_read_u32(trig_node, "trigger-value", &prop)) {
dev_err(&idev->dev, "Missing trigger-value property in the DT.\n");
ret = -EINVAL;
goto error_ret;
}
trig->value = prop;
trig->is_external = of_property_read_bool(trig_node, "trigger-external");
i++;
}
return 0;
error_ret:
return ret;
}
static int at91_adc_probe_pdata(struct at91_adc_state *st,
struct platform_device *pdev)
{
struct at91_adc_data *pdata = pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
st->use_external = pdata->use_external_triggers;
st->vref_mv = pdata->vref;
st->channels_mask = pdata->channels_used;
st->num_channels = pdata->num_channels;
st->startup_time = pdata->startup_time;
st->trigger_number = pdata->trigger_number;
st->trigger_list = pdata->trigger_list;
st->registers = pdata->registers;
return 0;
}
static const struct iio_info at91_adc_info = {
.driver_module = THIS_MODULE,
.read_raw = &at91_adc_read_raw,
};
static int __devinit at91_adc_probe(struct platform_device *pdev)
{
unsigned int prsc, mstrclk, ticks, adc_clk;
int ret;
struct iio_dev *idev;
struct at91_adc_state *st;
struct resource *res;
idev = iio_device_alloc(sizeof(struct at91_adc_state));
if (idev == NULL) {
ret = -ENOMEM;
goto error_ret;
}
st = iio_priv(idev);
if (pdev->dev.of_node)
ret = at91_adc_probe_dt(st, pdev);
else
ret = at91_adc_probe_pdata(st, pdev);
if (ret) {
dev_err(&pdev->dev, "No platform data available.\n");
ret = -EINVAL;
goto error_free_device;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "No resource defined\n");
ret = -ENXIO;
goto error_ret;
}
platform_set_drvdata(pdev, idev);
idev->dev.parent = &pdev->dev;
idev->name = dev_name(&pdev->dev);
idev->modes = INDIO_DIRECT_MODE;
idev->info = &at91_adc_info;
st->irq = platform_get_irq(pdev, 0);
if (st->irq < 0) {
dev_err(&pdev->dev, "No IRQ ID is designated\n");
ret = -ENODEV;
goto error_free_device;
}
if (!request_mem_region(res->start, resource_size(res),
"AT91 adc registers")) {
dev_err(&pdev->dev, "Resources are unavailable.\n");
ret = -EBUSY;
goto error_free_device;
}
st->reg_base = ioremap(res->start, resource_size(res));
if (!st->reg_base) {
dev_err(&pdev->dev, "Failed to map registers.\n");
ret = -ENOMEM;
goto error_release_mem;
}
/*
* Disable all IRQs before setting up the handler
*/
at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST);
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
ret = request_irq(st->irq,
at91_adc_eoc_trigger,
0,
pdev->dev.driver->name,
idev);
if (ret) {
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
goto error_unmap_reg;
}
st->clk = clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "Failed to get the clock.\n");
ret = PTR_ERR(st->clk);
goto error_free_irq;
}
ret = clk_prepare(st->clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the clock.\n");
goto error_free_clk;
}
ret = clk_enable(st->clk);
if (ret) {
dev_err(&pdev->dev, "Could not enable the clock.\n");
goto error_unprepare_clk;
}
st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
if (IS_ERR(st->adc_clk)) {
dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
ret = PTR_ERR(st->clk);
goto error_disable_clk;
}
ret = clk_prepare(st->adc_clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
goto error_free_adc_clk;
}
ret = clk_enable(st->adc_clk);
if (ret) {
dev_err(&pdev->dev, "Could not enable the ADC clock.\n");
goto error_unprepare_adc_clk;
}
/*
* Prescaler rate computation using the formula from the Atmel's
* datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being
* specified by the electrical characteristics of the board.
*/
mstrclk = clk_get_rate(st->clk);
adc_clk = clk_get_rate(st->adc_clk);
prsc = (mstrclk / (2 * adc_clk)) - 1;
if (!st->startup_time) {
dev_err(&pdev->dev, "No startup time available.\n");
ret = -EINVAL;
goto error_disable_adc_clk;
}
/*
* Number of ticks needed to cover the startup time of the ADC as
* defined in the electrical characteristics of the board, divided by 8.
* The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
*/
ticks = round_up((st->startup_time * adc_clk /
1000000) - 1, 8) / 8;
at91_adc_writel(st, AT91_ADC_MR,
(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
/* Setup the ADC channels available on the board */
ret = at91_adc_channel_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
goto error_disable_adc_clk;
}
init_waitqueue_head(&st->wq_data_avail);
mutex_init(&st->lock);
ret = at91_adc_buffer_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
goto error_disable_adc_clk;
}
ret = at91_adc_trigger_init(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
goto error_unregister_buffer;
}
ret = iio_device_register(idev);
if (ret < 0) {
dev_err(&pdev->dev, "Couldn't register the device.\n");
goto error_remove_triggers;
}
return 0;
error_remove_triggers:
at91_adc_trigger_remove(idev);
error_unregister_buffer:
at91_adc_buffer_remove(idev);
error_disable_adc_clk:
clk_disable(st->adc_clk);
error_unprepare_adc_clk:
clk_unprepare(st->adc_clk);
error_free_adc_clk:
clk_put(st->adc_clk);
error_disable_clk:
clk_disable(st->clk);
error_unprepare_clk:
clk_unprepare(st->clk);
error_free_clk:
clk_put(st->clk);
error_free_irq:
free_irq(st->irq, idev);
error_unmap_reg:
iounmap(st->reg_base);
error_release_mem:
release_mem_region(res->start, resource_size(res));
error_free_device:
iio_device_free(idev);
error_ret:
return ret;
}
static int __devexit at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *idev = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct at91_adc_state *st = iio_priv(idev);
iio_device_unregister(idev);
at91_adc_trigger_remove(idev);
at91_adc_buffer_remove(idev);
clk_disable_unprepare(st->adc_clk);
clk_put(st->adc_clk);
clk_disable(st->clk);
clk_unprepare(st->clk);
clk_put(st->clk);
free_irq(st->irq, idev);
iounmap(st->reg_base);
release_mem_region(res->start, resource_size(res));
iio_device_free(idev);
return 0;
}
static const struct of_device_id at91_adc_dt_ids[] = {
{ .compatible = "atmel,at91sam9260-adc" },
{},
};
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
.remove = __devexit_p(at91_adc_remove),
.driver = {
.name = "at91_adc",
.of_match_table = of_match_ptr(at91_adc_dt_ids),
},
};
module_platform_driver(at91_adc_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Atmel AT91 ADC Driver");
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
#
# Gain Amplifiers, etc.
#
menu "Amplifiers"
config AD8366
tristate "Analog Devices AD8366 VGA"
depends on SPI
select BITREVERSE
help
Say yes here to build support for Analog Devices AD8366
SPI Dual-Digital Variable Gain Amplifier (VGA).
To compile this driver as a module, choose M here: the
module will be called ad8366.
endmenu
#
# Makefile iio/amplifiers
#
obj-$(CONFIG_AD8366) += ad8366.o
/*
* AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA)
*
* Copyright 2012 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/bitrev.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
struct ad8366_state {
struct spi_device *spi;
struct regulator *reg;
unsigned char ch[2];
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
unsigned char data[2] ____cacheline_aligned;
};
static int ad8366_write(struct iio_dev *indio_dev,
unsigned char ch_a, char unsigned ch_b)
{
struct ad8366_state *st = iio_priv(indio_dev);
int ret;
ch_a = bitrev8(ch_a & 0x3F);
ch_b = bitrev8(ch_b & 0x3F);
st->data[0] = ch_b >> 4;
st->data[1] = (ch_b << 4) | (ch_a >> 2);
ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data));
if (ret < 0)
dev_err(&indio_dev->dev, "write failed (%d)", ret);
return ret;
}
static int ad8366_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct ad8366_state *st = iio_priv(indio_dev);
int ret;
unsigned code;
mutex_lock(&indio_dev->mlock);
switch (m) {
case IIO_CHAN_INFO_HARDWAREGAIN:
code = st->ch[chan->channel];
/* Values in dB */
code = code * 253 + 4500;
*val = code / 1000;
*val2 = (code % 1000) * 1000;
ret = IIO_VAL_INT_PLUS_MICRO_DB;
break;
default:
ret = -EINVAL;
}
mutex_unlock(&indio_dev->mlock);
return ret;
};
static int ad8366_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
struct ad8366_state *st = iio_priv(indio_dev);
unsigned code;
int ret;
if (val < 0 || val2 < 0)
return -EINVAL;
/* Values in dB */
code = (((u8)val * 1000) + ((u32)val2 / 1000));
if (code > 20500 || code < 4500)
return -EINVAL;
code = (code - 4500) / 253;
mutex_lock(&indio_dev->mlock);
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
st->ch[chan->channel] = code;
ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&indio_dev->mlock);
return ret;
}
static const struct iio_info ad8366_info = {
.read_raw = &ad8366_read_raw,
.write_raw = &ad8366_write_raw,
.driver_module = THIS_MODULE,
};
#define AD8366_CHAN(_channel) { \
.type = IIO_VOLTAGE, \
.output = 1, \
.indexed = 1, \
.channel = _channel, \
.info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\
}
static const struct iio_chan_spec ad8366_channels[] = {
AD8366_CHAN(0),
AD8366_CHAN(1),
};
static int __devinit ad8366_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct ad8366_state *st;
int ret;
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
goto error_put_reg;
}
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad8366_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad8366_channels;
indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto error_disable_reg;
ad8366_write(indio_dev, 0 , 0);
return 0;
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_put_reg:
if (!IS_ERR(st->reg))
regulator_put(st->reg);
iio_device_free(indio_dev);
return ret;
}
static int __devexit ad8366_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad8366_state *st = iio_priv(indio_dev);
struct regulator *reg = st->reg;
iio_device_unregister(indio_dev);
if (!IS_ERR(reg)) {
regulator_disable(reg);
regulator_put(reg);
}
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id ad8366_id[] = {
{"ad8366", 0},
{}
};
static struct spi_driver ad8366_driver = {
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
.probe = ad8366_probe,
.remove = __devexit_p(ad8366_remove),
.id_table = ad8366_id,
};
module_spi_driver(ad8366_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Analog Devices AD8366 VGA");
MODULE_LICENSE("GPL v2");
...@@ -12,6 +12,12 @@ ...@@ -12,6 +12,12 @@
#ifndef _IIO_CORE_H_ #ifndef _IIO_CORE_H_
#define _IIO_CORE_H_ #define _IIO_CORE_H_
#include <linux/kernel.h>
#include <linux/device.h>
struct iio_chan_spec;
struct iio_dev;
int __iio_add_chan_devattr(const char *postfix, int __iio_add_chan_devattr(const char *postfix,
struct iio_chan_spec const *chan, struct iio_chan_spec const *chan,
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/poll.h> #include <linux/poll.h>
#include "iio.h" #include <linux/iio/iio.h>
#include "iio_core.h" #include "iio_core.h"
#include "sysfs.h" #include <linux/iio/sysfs.h>
#include "buffer.h" #include <linux/iio/buffer.h>
static const char * const iio_endian_prefix[] = { static const char * const iio_endian_prefix[] = {
[IIO_BE] = "be", [IIO_BE] = "be",
...@@ -105,7 +105,7 @@ static ssize_t iio_scan_el_show(struct device *dev, ...@@ -105,7 +105,7 @@ static ssize_t iio_scan_el_show(struct device *dev,
char *buf) char *buf)
{ {
int ret; int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
ret = test_bit(to_iio_dev_attr(attr)->address, ret = test_bit(to_iio_dev_attr(attr)->address,
indio_dev->buffer->scan_mask); indio_dev->buffer->scan_mask);
...@@ -124,13 +124,15 @@ static ssize_t iio_scan_el_store(struct device *dev, ...@@ -124,13 +124,15 @@ static ssize_t iio_scan_el_store(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
int ret = 0; int ret;
bool state; bool state;
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer; struct iio_buffer *buffer = indio_dev->buffer;
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
state = !(buf[0] == '0'); ret = strtobool(buf, &state);
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY; ret = -EBUSY;
...@@ -160,7 +162,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev, ...@@ -160,7 +162,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp); return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp);
} }
...@@ -169,17 +171,21 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, ...@@ -169,17 +171,21 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
int ret = 0; int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
bool state; bool state;
state = !(buf[0] == '0'); ret = strtobool(buf, &state);
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
if (iio_buffer_enabled(indio_dev)) { if (iio_buffer_enabled(indio_dev)) {
ret = -EBUSY; ret = -EBUSY;
goto error_ret; goto error_ret;
} }
indio_dev->buffer->scan_timestamp = state; indio_dev->buffer->scan_timestamp = state;
indio_dev->scan_timestamp = state;
error_ret: error_ret:
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
...@@ -291,7 +297,7 @@ int iio_buffer_register(struct iio_dev *indio_dev, ...@@ -291,7 +297,7 @@ int iio_buffer_register(struct iio_dev *indio_dev,
goto error_cleanup_dynamic; goto error_cleanup_dynamic;
attrcount += ret; attrcount += ret;
if (channels[i].type == IIO_TIMESTAMP) if (channels[i].type == IIO_TIMESTAMP)
buffer->scan_index_timestamp = indio_dev->scan_index_timestamp =
channels[i].scan_index; channels[i].scan_index;
} }
if (indio_dev->masklength && buffer->scan_mask == NULL) { if (indio_dev->masklength && buffer->scan_mask == NULL) {
...@@ -346,7 +352,7 @@ ssize_t iio_buffer_read_length(struct device *dev, ...@@ -346,7 +352,7 @@ ssize_t iio_buffer_read_length(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer; struct iio_buffer *buffer = indio_dev->buffer;
if (buffer->access->get_length) if (buffer->access->get_length)
...@@ -364,7 +370,7 @@ ssize_t iio_buffer_write_length(struct device *dev, ...@@ -364,7 +370,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
{ {
int ret; int ret;
ulong val; ulong val;
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer; struct iio_buffer *buffer = indio_dev->buffer;
ret = strict_strtoul(buf, 10, &val); ret = strict_strtoul(buf, 10, &val);
...@@ -397,7 +403,7 @@ ssize_t iio_buffer_store_enable(struct device *dev, ...@@ -397,7 +403,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
int ret; int ret;
bool requested_state, current_state; bool requested_state, current_state;
int previous_mode; int previous_mode;
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_buffer *buffer = indio_dev->buffer; struct iio_buffer *buffer = indio_dev->buffer;
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
...@@ -483,7 +489,7 @@ ssize_t iio_buffer_show_enable(struct device *dev, ...@@ -483,7 +489,7 @@ ssize_t iio_buffer_show_enable(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev)); return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
} }
EXPORT_SYMBOL(iio_buffer_show_enable); EXPORT_SYMBOL(iio_buffer_show_enable);
...@@ -503,30 +509,41 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, ...@@ -503,30 +509,41 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
return NULL; return NULL;
} }
int iio_sw_buffer_preenable(struct iio_dev *indio_dev) static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
bool timestamp)
{ {
struct iio_buffer *buffer = indio_dev->buffer;
const struct iio_chan_spec *ch; const struct iio_chan_spec *ch;
unsigned bytes = 0; unsigned bytes = 0;
int length, i; int length, i;
dev_dbg(&indio_dev->dev, "%s\n", __func__);
/* How much space will the demuxed element take? */ /* How much space will the demuxed element take? */
for_each_set_bit(i, buffer->scan_mask, for_each_set_bit(i, mask,
indio_dev->masklength) { indio_dev->masklength) {
ch = iio_find_channel_from_si(indio_dev, i); ch = iio_find_channel_from_si(indio_dev, i);
length = ch->scan_type.storagebits/8; length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length); bytes = ALIGN(bytes, length);
bytes += length; bytes += length;
} }
if (buffer->scan_timestamp) { if (timestamp) {
ch = iio_find_channel_from_si(indio_dev, ch = iio_find_channel_from_si(indio_dev,
buffer->scan_index_timestamp); indio_dev->scan_index_timestamp);
length = ch->scan_type.storagebits/8; length = ch->scan_type.storagebits / 8;
bytes = ALIGN(bytes, length); bytes = ALIGN(bytes, length);
bytes += length; bytes += length;
} }
buffer->access->set_bytes_per_datum(buffer, bytes); return bytes;
}
int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer = indio_dev->buffer;
dev_dbg(&indio_dev->dev, "%s\n", __func__);
/* How much space will the demuxed element take? */
indio_dev->scan_bytes =
iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
buffer->scan_timestamp);
buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
/* What scan mask do we actually have ?*/ /* What scan mask do we actually have ?*/
if (indio_dev->available_scan_masks) if (indio_dev->available_scan_masks)
...@@ -638,19 +655,25 @@ int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data, ...@@ -638,19 +655,25 @@ int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
} }
EXPORT_SYMBOL_GPL(iio_push_to_buffer); EXPORT_SYMBOL_GPL(iio_push_to_buffer);
static void iio_buffer_demux_free(struct iio_buffer *buffer)
{
struct iio_demux_table *p, *q;
list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
list_del(&p->l);
kfree(p);
}
}
int iio_update_demux(struct iio_dev *indio_dev) int iio_update_demux(struct iio_dev *indio_dev)
{ {
const struct iio_chan_spec *ch; const struct iio_chan_spec *ch;
struct iio_buffer *buffer = indio_dev->buffer; struct iio_buffer *buffer = indio_dev->buffer;
int ret, in_ind = -1, out_ind, length; int ret, in_ind = -1, out_ind, length;
unsigned in_loc = 0, out_loc = 0; unsigned in_loc = 0, out_loc = 0;
struct iio_demux_table *p, *q; struct iio_demux_table *p;
/* Clear out any old demux */ /* Clear out any old demux */
list_for_each_entry_safe(p, q, &buffer->demux_list, l) { iio_buffer_demux_free(buffer);
list_del(&p->l);
kfree(p);
}
kfree(buffer->demux_bounce); kfree(buffer->demux_bounce);
buffer->demux_bounce = NULL; buffer->demux_bounce = NULL;
...@@ -704,7 +727,7 @@ int iio_update_demux(struct iio_dev *indio_dev) ...@@ -704,7 +727,7 @@ int iio_update_demux(struct iio_dev *indio_dev)
goto error_clear_mux_table; goto error_clear_mux_table;
} }
ch = iio_find_channel_from_si(indio_dev, ch = iio_find_channel_from_si(indio_dev,
buffer->scan_index_timestamp); indio_dev->scan_index_timestamp);
length = ch->scan_type.storagebits/8; length = ch->scan_type.storagebits/8;
if (out_loc % length) if (out_loc % length)
out_loc += length - out_loc % length; out_loc += length - out_loc % length;
...@@ -725,10 +748,8 @@ int iio_update_demux(struct iio_dev *indio_dev) ...@@ -725,10 +748,8 @@ int iio_update_demux(struct iio_dev *indio_dev)
return 0; return 0;
error_clear_mux_table: error_clear_mux_table:
list_for_each_entry_safe(p, q, &buffer->demux_list, l) { iio_buffer_demux_free(buffer);
list_del(&p->l);
kfree(p);
}
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(iio_update_demux); EXPORT_SYMBOL_GPL(iio_update_demux);
...@@ -23,11 +23,11 @@ ...@@ -23,11 +23,11 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/anon_inodes.h> #include <linux/anon_inodes.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include "iio.h" #include <linux/iio/iio.h>
#include "iio_core.h" #include "iio_core.h"
#include "iio_core_trigger.h" #include "iio_core_trigger.h"
#include "sysfs.h" #include <linux/iio/sysfs.h>
#include "events.h" #include <linux/iio/events.h>
/* IDA to assign each registered device a unique id*/ /* IDA to assign each registered device a unique id*/
static DEFINE_IDA(iio_ida); static DEFINE_IDA(iio_ida);
...@@ -42,11 +42,6 @@ EXPORT_SYMBOL(iio_bus_type); ...@@ -42,11 +42,6 @@ EXPORT_SYMBOL(iio_bus_type);
static struct dentry *iio_debugfs_dentry; static struct dentry *iio_debugfs_dentry;
static const char * const iio_data_type_name[] = {
[IIO_RAW] = "raw",
[IIO_PROCESSED] = "input",
};
static const char * const iio_direction[] = { static const char * const iio_direction[] = {
[0] = "in", [0] = "in",
[1] = "out", [1] = "out",
...@@ -68,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = { ...@@ -68,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_ANGL] = "angl", [IIO_ANGL] = "angl",
[IIO_TIMESTAMP] = "timestamp", [IIO_TIMESTAMP] = "timestamp",
[IIO_CAPACITANCE] = "capacitance", [IIO_CAPACITANCE] = "capacitance",
[IIO_ALTVOLTAGE] = "altvoltage",
}; };
static const char * const iio_modifier_names[] = { static const char * const iio_modifier_names[] = {
...@@ -80,6 +76,8 @@ static const char * const iio_modifier_names[] = { ...@@ -80,6 +76,8 @@ static const char * const iio_modifier_names[] = {
/* relies on pairs of these shared then separate */ /* relies on pairs of these shared then separate */
static const char * const iio_chan_info_postfix[] = { static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_RAW] = "raw",
[IIO_CHAN_INFO_PROCESSED] = "input",
[IIO_CHAN_INFO_SCALE] = "scale", [IIO_CHAN_INFO_SCALE] = "scale",
[IIO_CHAN_INFO_OFFSET] = "offset", [IIO_CHAN_INFO_OFFSET] = "offset",
[IIO_CHAN_INFO_CALIBSCALE] = "calibscale", [IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
...@@ -90,6 +88,10 @@ static const char * const iio_chan_info_postfix[] = { ...@@ -90,6 +88,10 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
= "filter_low_pass_3db_frequency", = "filter_low_pass_3db_frequency",
[IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
[IIO_CHAN_INFO_FREQUENCY] = "frequency",
[IIO_CHAN_INFO_PHASE] = "phase",
[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
}; };
const struct iio_chan_spec const struct iio_chan_spec
...@@ -151,14 +153,6 @@ static void __exit iio_exit(void) ...@@ -151,14 +153,6 @@ static void __exit iio_exit(void)
} }
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
static int iio_debugfs_open(struct inode *inode, struct file *file)
{
if (inode->i_private)
file->private_data = inode->i_private;
return 0;
}
static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -217,7 +211,7 @@ static ssize_t iio_debugfs_write_reg(struct file *file, ...@@ -217,7 +211,7 @@ static ssize_t iio_debugfs_write_reg(struct file *file,
} }
static const struct file_operations iio_debugfs_reg_fops = { static const struct file_operations iio_debugfs_reg_fops = {
.open = iio_debugfs_open, .open = simple_open,
.read = iio_debugfs_read_reg, .read = iio_debugfs_read_reg,
.write = iio_debugfs_write_reg, .write = iio_debugfs_write_reg,
}; };
...@@ -234,15 +228,12 @@ static int iio_device_register_debugfs(struct iio_dev *indio_dev) ...@@ -234,15 +228,12 @@ static int iio_device_register_debugfs(struct iio_dev *indio_dev)
if (indio_dev->info->debugfs_reg_access == NULL) if (indio_dev->info->debugfs_reg_access == NULL)
return 0; return 0;
if (IS_ERR(iio_debugfs_dentry)) if (!iio_debugfs_dentry)
return 0; return 0;
indio_dev->debugfs_dentry = indio_dev->debugfs_dentry =
debugfs_create_dir(dev_name(&indio_dev->dev), debugfs_create_dir(dev_name(&indio_dev->dev),
iio_debugfs_dentry); iio_debugfs_dentry);
if (IS_ERR(indio_dev->debugfs_dentry))
return PTR_ERR(indio_dev->debugfs_dentry);
if (indio_dev->debugfs_dentry == NULL) { if (indio_dev->debugfs_dentry == NULL) {
dev_warn(indio_dev->dev.parent, dev_warn(indio_dev->dev.parent,
"Failed to create debugfs directory\n"); "Failed to create debugfs directory\n");
...@@ -274,13 +265,13 @@ static ssize_t iio_read_channel_ext_info(struct device *dev, ...@@ -274,13 +265,13 @@ static ssize_t iio_read_channel_ext_info(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
const struct iio_chan_spec_ext_info *ext_info; const struct iio_chan_spec_ext_info *ext_info;
ext_info = &this_attr->c->ext_info[this_attr->address]; ext_info = &this_attr->c->ext_info[this_attr->address];
return ext_info->read(indio_dev, this_attr->c, buf); return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf);
} }
static ssize_t iio_write_channel_ext_info(struct device *dev, static ssize_t iio_write_channel_ext_info(struct device *dev,
...@@ -288,42 +279,50 @@ static ssize_t iio_write_channel_ext_info(struct device *dev, ...@@ -288,42 +279,50 @@ static ssize_t iio_write_channel_ext_info(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
const struct iio_chan_spec_ext_info *ext_info; const struct iio_chan_spec_ext_info *ext_info;
ext_info = &this_attr->c->ext_info[this_attr->address]; ext_info = &this_attr->c->ext_info[this_attr->address];
return ext_info->write(indio_dev, this_attr->c, buf, len); return ext_info->write(indio_dev, ext_info->private,
this_attr->c, buf, len);
} }
static ssize_t iio_read_channel_info(struct device *dev, static ssize_t iio_read_channel_info(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, val2; int val, val2;
bool scale_db = false;
int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
&val, &val2, this_attr->address); &val, &val2, this_attr->address);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (ret == IIO_VAL_INT) switch (ret) {
case IIO_VAL_INT:
return sprintf(buf, "%d\n", val); return sprintf(buf, "%d\n", val);
else if (ret == IIO_VAL_INT_PLUS_MICRO) { case IIO_VAL_INT_PLUS_MICRO_DB:
scale_db = true;
case IIO_VAL_INT_PLUS_MICRO:
if (val2 < 0) if (val2 < 0)
return sprintf(buf, "-%d.%06u\n", val, -val2); return sprintf(buf, "-%d.%06u%s\n", val, -val2,
scale_db ? " dB" : "");
else else
return sprintf(buf, "%d.%06u\n", val, val2); return sprintf(buf, "%d.%06u%s\n", val, val2,
} else if (ret == IIO_VAL_INT_PLUS_NANO) { scale_db ? " dB" : "");
case IIO_VAL_INT_PLUS_NANO:
if (val2 < 0) if (val2 < 0)
return sprintf(buf, "-%d.%09u\n", val, -val2); return sprintf(buf, "-%d.%09u\n", val, -val2);
else else
return sprintf(buf, "%d.%09u\n", val, val2); return sprintf(buf, "%d.%09u\n", val, val2);
} else default:
return 0; return 0;
}
} }
static ssize_t iio_write_channel_info(struct device *dev, static ssize_t iio_write_channel_info(struct device *dev,
...@@ -331,7 +330,7 @@ static ssize_t iio_write_channel_info(struct device *dev, ...@@ -331,7 +330,7 @@ static ssize_t iio_write_channel_info(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret, integer = 0, fract = 0, fract_mult = 100000; int ret, integer = 0, fract = 0, fract_mult = 100000;
bool integer_part = true, negative = false; bool integer_part = true, negative = false;
...@@ -575,25 +574,12 @@ int __iio_add_chan_devattr(const char *postfix, ...@@ -575,25 +574,12 @@ int __iio_add_chan_devattr(const char *postfix,
static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan) struct iio_chan_spec const *chan)
{ {
int ret, i, attrcount = 0; int ret, attrcount = 0;
int i;
const struct iio_chan_spec_ext_info *ext_info; const struct iio_chan_spec_ext_info *ext_info;
if (chan->channel < 0) if (chan->channel < 0)
return 0; return 0;
ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
chan,
&iio_read_channel_info,
(chan->output ?
&iio_write_channel_info : NULL),
0,
0,
&indio_dev->dev,
&indio_dev->channel_attr_list);
if (ret)
goto error_ret;
attrcount++;
for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
chan, chan,
...@@ -652,7 +638,7 @@ static ssize_t iio_show_dev_name(struct device *dev, ...@@ -652,7 +638,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%s\n", indio_dev->name); return sprintf(buf, "%s\n", indio_dev->name);
} }
...@@ -738,7 +724,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) ...@@ -738,7 +724,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
static void iio_dev_release(struct device *device) static void iio_dev_release(struct device *device)
{ {
struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); struct iio_dev *indio_dev = dev_to_iio_dev(device);
cdev_del(&indio_dev->chrdev); cdev_del(&indio_dev->chrdev);
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_trigger_consumer(indio_dev);
...@@ -752,7 +738,7 @@ static struct device_type iio_dev_type = { ...@@ -752,7 +738,7 @@ static struct device_type iio_dev_type = {
.release = iio_dev_release, .release = iio_dev_release,
}; };
struct iio_dev *iio_allocate_device(int sizeof_priv) struct iio_dev *iio_device_alloc(int sizeof_priv)
{ {
struct iio_dev *dev; struct iio_dev *dev;
size_t alloc_size; size_t alloc_size;
...@@ -788,16 +774,16 @@ struct iio_dev *iio_allocate_device(int sizeof_priv) ...@@ -788,16 +774,16 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
return dev; return dev;
} }
EXPORT_SYMBOL(iio_allocate_device); EXPORT_SYMBOL(iio_device_alloc);
void iio_free_device(struct iio_dev *dev) void iio_device_free(struct iio_dev *dev)
{ {
if (dev) { if (dev) {
ida_simple_remove(&iio_ida, dev->id); ida_simple_remove(&iio_ida, dev->id);
kfree(dev); kfree(dev);
} }
} }
EXPORT_SYMBOL(iio_free_device); EXPORT_SYMBOL(iio_device_free);
/** /**
* iio_chrdev_open() - chrdev file open for buffer access and ioctls * iio_chrdev_open() - chrdev file open for buffer access and ioctls
......
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/wait.h> #include <linux/wait.h>
#include "iio.h" #include <linux/iio/iio.h>
#include "iio_core.h" #include "iio_core.h"
#include "sysfs.h" #include <linux/iio/sysfs.h>
#include "events.h" #include <linux/iio/events.h>
/** /**
* struct iio_event_interface - chrdev interface for an event line * struct iio_event_interface - chrdev interface for an event line
...@@ -186,7 +186,7 @@ static ssize_t iio_ev_state_store(struct device *dev, ...@@ -186,7 +186,7 @@ static ssize_t iio_ev_state_store(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret; int ret;
bool val; bool val;
...@@ -205,7 +205,7 @@ static ssize_t iio_ev_state_show(struct device *dev, ...@@ -205,7 +205,7 @@ static ssize_t iio_ev_state_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val = indio_dev->info->read_event_config(indio_dev, int val = indio_dev->info->read_event_config(indio_dev,
this_attr->address); this_attr->address);
...@@ -220,7 +220,7 @@ static ssize_t iio_ev_value_show(struct device *dev, ...@@ -220,7 +220,7 @@ static ssize_t iio_ev_value_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int val, ret; int val, ret;
...@@ -237,7 +237,7 @@ static ssize_t iio_ev_value_store(struct device *dev, ...@@ -237,7 +237,7 @@ static ssize_t iio_ev_value_store(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
unsigned long val; unsigned long val;
int ret; int ret;
......
...@@ -15,11 +15,11 @@ ...@@ -15,11 +15,11 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "iio.h" #include <linux/iio/iio.h>
#include "trigger.h" #include <linux/iio/trigger.h>
#include "iio_core.h" #include "iio_core.h"
#include "iio_core_trigger.h" #include "iio_core_trigger.h"
#include "trigger_consumer.h" #include <linux/iio/trigger_consumer.h>
/* RFC - Question of approach /* RFC - Question of approach
* Make the common case (single sensor single trigger) * Make the common case (single sensor single trigger)
...@@ -310,7 +310,7 @@ static ssize_t iio_trigger_read_current(struct device *dev, ...@@ -310,7 +310,7 @@ static ssize_t iio_trigger_read_current(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
if (indio_dev->trig) if (indio_dev->trig)
return sprintf(buf, "%s\n", indio_dev->trig->name); return sprintf(buf, "%s\n", indio_dev->trig->name);
...@@ -329,7 +329,7 @@ static ssize_t iio_trigger_write_current(struct device *dev, ...@@ -329,7 +329,7 @@ static ssize_t iio_trigger_write_current(struct device *dev,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct iio_dev *indio_dev = dev_get_drvdata(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct iio_trigger *oldtrig = indio_dev->trig; struct iio_trigger *oldtrig = indio_dev->trig;
struct iio_trigger *trig; struct iio_trigger *trig;
int ret; int ret;
...@@ -360,9 +360,9 @@ static ssize_t iio_trigger_write_current(struct device *dev, ...@@ -360,9 +360,9 @@ static ssize_t iio_trigger_write_current(struct device *dev,
indio_dev->trig = trig; indio_dev->trig = trig;
if (oldtrig && indio_dev->trig != oldtrig) if (oldtrig && indio_dev->trig != oldtrig)
iio_put_trigger(oldtrig); iio_trigger_put(oldtrig);
if (indio_dev->trig) if (indio_dev->trig)
iio_get_trigger(indio_dev->trig); iio_trigger_get(indio_dev->trig);
return len; return len;
} }
...@@ -426,7 +426,7 @@ static void iio_trig_subirqunmask(struct irq_data *d) ...@@ -426,7 +426,7 @@ static void iio_trig_subirqunmask(struct irq_data *d)
trig->subirqs[d->irq - trig->subirq_base].enabled = true; trig->subirqs[d->irq - trig->subirq_base].enabled = true;
} }
struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
{ {
va_list vargs; va_list vargs;
struct iio_trigger *trig; struct iio_trigger *trig;
...@@ -472,14 +472,14 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) ...@@ -472,14 +472,14 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
} }
return trig; return trig;
} }
EXPORT_SYMBOL(iio_allocate_trigger); EXPORT_SYMBOL(iio_trigger_alloc);
void iio_free_trigger(struct iio_trigger *trig) void iio_trigger_free(struct iio_trigger *trig)
{ {
if (trig) if (trig)
put_device(&trig->dev); put_device(&trig->dev);
} }
EXPORT_SYMBOL(iio_free_trigger); EXPORT_SYMBOL(iio_trigger_free);
void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
{ {
...@@ -491,7 +491,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev) ...@@ -491,7 +491,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
{ {
/* Clean up and associated but not attached triggers references */ /* Clean up and associated but not attached triggers references */
if (indio_dev->trig) if (indio_dev->trig)
iio_put_trigger(indio_dev->trig); iio_trigger_put(indio_dev->trig);
} }
int iio_triggered_buffer_postenable(struct iio_dev *indio_dev) int iio_triggered_buffer_postenable(struct iio_dev *indio_dev)
......
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include "iio.h" #include <linux/iio/iio.h>
#include "iio_core.h" #include "iio_core.h"
#include "machine.h" #include <linux/iio/machine.h>
#include "driver.h" #include <linux/iio/driver.h>
#include "consumer.h" #include <linux/iio/consumer.h>
struct iio_map_internal { struct iio_map_internal {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/iio/kfifo_buf.h>
#include "kfifo_buf.h"
struct iio_kfifo { struct iio_kfifo {
struct iio_buffer buffer; struct iio_buffer buffer;
......
...@@ -516,4 +516,5 @@ source "drivers/misc/ti-st/Kconfig" ...@@ -516,4 +516,5 @@ source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig" source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/carma/Kconfig" source "drivers/misc/carma/Kconfig"
source "drivers/misc/altera-stapl/Kconfig" source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
endmenu endmenu
...@@ -50,3 +50,4 @@ obj-y += lis3lv02d/ ...@@ -50,3 +50,4 @@ obj-y += lis3lv02d/
obj-y += carma/ obj-y += carma/
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "mei_dev.h" #include "mei_dev.h"
#include "hw.h" #include "hw.h"
#include "interface.h" #include "interface.h"
#include "mei.h" #include <linux/mei.h>
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,
...@@ -200,7 +200,7 @@ int mei_hw_init(struct mei_device *dev) ...@@ -200,7 +200,7 @@ int mei_hw_init(struct mei_device *dev)
if (!(dev->me_hw_state & ME_RDY_HRA)) if (!(dev->me_hw_state & ME_RDY_HRA))
dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n"); dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
printk(KERN_ERR "mei: link layer initialization failed.\n"); dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include "mei_dev.h" #include "mei_dev.h"
#include "mei.h" #include <linux/mei.h>
#include "interface.h" #include "interface.h"
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#ifndef _MEI_INTERFACE_H_ #ifndef _MEI_INTERFACE_H_
#define _MEI_INTERFACE_H_ #define _MEI_INTERFACE_H_
#include "mei.h" #include <linux/mei.h>
#include "mei_dev.h" #include "mei_dev.h"
...@@ -51,8 +51,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl); ...@@ -51,8 +51,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, bool preserve);
bool mei_wd_host_init(struct mei_device *dev); int mei_wd_host_init(struct mei_device *dev);
void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
/* /*
* mei_watchdog_register - Registering watchdog interface * mei_watchdog_register - Registering watchdog interface
* once we got connection to the WD Client * once we got connection to the WD Client
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include "mei_dev.h" #include "mei_dev.h"
#include "mei.h" #include <linux/mei.h>
#include "hw.h" #include "hw.h"
#include "interface.h" #include "interface.h"
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "mei_dev.h" #include "mei_dev.h"
#include "hw.h" #include "hw.h"
#include "mei.h" #include <linux/mei.h>
#include "interface.h" #include "interface.h"
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* *
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -36,19 +38,10 @@ ...@@ -36,19 +38,10 @@
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include "mei_dev.h" #include "mei_dev.h"
#include "mei.h" #include <linux/mei.h>
#include "interface.h" #include "interface.h"
static const char mei_driver_name[] = "mei";
#define MEI_READ_TIMEOUT 45
#define MEI_DRIVER_NAME "mei"
#define MEI_DEV_NAME "mei"
/*
* mei driver strings
*/
static char mei_driver_name[] = MEI_DRIVER_NAME;
static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
/* The device pointer */ /* The device pointer */
/* Currently this driver works as long as there is only a single AMT device. */ /* Currently this driver works as long as there is only a single AMT device. */
...@@ -931,7 +924,7 @@ static const struct file_operations mei_fops = { ...@@ -931,7 +924,7 @@ static const struct file_operations mei_fops = {
* Misc Device Struct * Misc Device Struct
*/ */
static struct miscdevice mei_misc_device = { static struct miscdevice mei_misc_device = {
.name = MEI_DRIVER_NAME, .name = "mei",
.fops = &mei_fops, .fops = &mei_fops,
.minor = MISC_DYNAMIC_MINOR, .minor = MISC_DYNAMIC_MINOR,
}; };
...@@ -958,7 +951,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -958,7 +951,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* enable pci dev */ /* enable pci dev */
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
printk(KERN_ERR "mei: Failed to enable pci device.\n"); dev_err(&pdev->dev, "failed to enable pci device.\n");
goto end; goto end;
} }
/* set PCI host mastering */ /* set PCI host mastering */
...@@ -966,7 +959,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -966,7 +959,7 @@ static int __devinit mei_probe(struct pci_dev *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, mei_driver_name);
if (err) { if (err) {
printk(KERN_ERR "mei: Failed to get pci regions.\n"); dev_err(&pdev->dev, "failed to get pci regions.\n");
goto disable_device; goto disable_device;
} }
/* allocates and initializes the mei dev structure */ /* allocates and initializes the mei dev structure */
...@@ -978,7 +971,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -978,7 +971,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
/* mapping IO device memory */ /* mapping IO device memory */
dev->mem_addr = pci_iomap(pdev, 0, 0); dev->mem_addr = pci_iomap(pdev, 0, 0);
if (!dev->mem_addr) { if (!dev->mem_addr) {
printk(KERN_ERR "mei: mapping I/O device memory failure.\n"); dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
err = -ENOMEM; err = -ENOMEM;
goto free_device; goto free_device;
} }
...@@ -997,13 +990,13 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -997,13 +990,13 @@ static int __devinit mei_probe(struct pci_dev *pdev,
IRQF_SHARED, mei_driver_name, dev); IRQF_SHARED, mei_driver_name, dev);
if (err) { if (err) {
printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n", dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
pdev->irq); pdev->irq);
goto unmap_memory; goto unmap_memory;
} }
INIT_DELAYED_WORK(&dev->timer_work, mei_timer); INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
if (mei_hw_init(dev)) { if (mei_hw_init(dev)) {
printk(KERN_ERR "mei: Init hw failure.\n"); dev_err(&pdev->dev, "init hw failure.\n");
err = -ENODEV; err = -ENODEV;
goto release_irq; goto release_irq;
} }
...@@ -1020,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -1020,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
mutex_unlock(&mei_mutex); mutex_unlock(&mei_mutex);
pr_debug("mei: Driver initialization successful.\n"); pr_debug("initialization successful.\n");
return 0; return 0;
...@@ -1041,7 +1034,7 @@ static int __devinit mei_probe(struct pci_dev *pdev, ...@@ -1041,7 +1034,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
pci_disable_device(pdev); pci_disable_device(pdev);
end: end:
mutex_unlock(&mei_mutex); mutex_unlock(&mei_mutex);
printk(KERN_ERR "mei: Driver initialization failed.\n"); dev_err(&pdev->dev, "initialization failed.\n");
return err; return err;
} }
...@@ -1160,8 +1153,8 @@ static int mei_pci_resume(struct device *device) ...@@ -1160,8 +1153,8 @@ static int mei_pci_resume(struct device *device)
IRQF_SHARED, mei_driver_name, dev); IRQF_SHARED, mei_driver_name, dev);
if (err) { if (err) {
printk(KERN_ERR "mei: Request_irq failure. irq = %d\n", dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
pdev->irq); pdev->irq);
return err; return err;
} }
...@@ -1204,11 +1197,11 @@ static int __init mei_init_module(void) ...@@ -1204,11 +1197,11 @@ static int __init mei_init_module(void)
{ {
int ret; int ret;
pr_debug("mei: %s\n", mei_driver_string); pr_debug("loading.\n");
/* init pci module */ /* init pci module */
ret = pci_register_driver(&mei_driver); ret = pci_register_driver(&mei_driver);
if (ret < 0) if (ret < 0)
printk(KERN_ERR "mei: Error registering driver.\n"); pr_err("error registering driver.\n");
return ret; return ret;
} }
...@@ -1226,7 +1219,7 @@ static void __exit mei_exit_module(void) ...@@ -1226,7 +1219,7 @@ static void __exit mei_exit_module(void)
misc_deregister(&mei_misc_device); misc_deregister(&mei_misc_device);
pci_unregister_driver(&mei_driver); pci_unregister_driver(&mei_driver);
pr_debug("mei: Driver unloaded successfully.\n"); pr_debug("unloaded successfully.\n");
} }
module_exit(mei_exit_module); module_exit(mei_exit_module);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/watchdog.h> #include <linux/watchdog.h>
#include "mei.h" #include <linux/mei.h>
#include "hw.h" #include "hw.h"
/* /*
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "mei_dev.h" #include "mei_dev.h"
#include "hw.h" #include "hw.h"
#include "interface.h" #include "interface.h"
#include "mei.h" #include <linux/mei.h>
static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
...@@ -45,23 +45,22 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, ...@@ -45,23 +45,22 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x9D, 0xA9, 0x15, 0x14, 0xCB,
0x32, 0xAB); 0x32, 0xAB);
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, "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_PARAMS_SIZE);
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
&timeout, sizeof(u16));
} }
/** /**
* host_init_wd - mei initialization wd. * host_init_wd - mei initialization wd.
* *
* @dev: the device structure * @dev: the device structure
* returns -ENENT if wd client cannot be found
* -EIO if write has failed
*/ */
bool mei_wd_host_init(struct mei_device *dev) int mei_wd_host_init(struct mei_device *dev)
{ {
bool ret = false;
mei_cl_init(&dev->wd_cl, dev); mei_cl_init(&dev->wd_cl, dev);
/* look for WD client and connect to it */ /* look for WD client and connect to it */
...@@ -72,25 +71,21 @@ bool mei_wd_host_init(struct mei_device *dev) ...@@ -72,25 +71,21 @@ bool mei_wd_host_init(struct mei_device *dev)
mei_find_me_client_update_filext(dev, &dev->wd_cl, mei_find_me_client_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, "check wd_cl\n"); dev_dbg(&dev->pdev->dev, "wd: check client\n");
if (MEI_FILE_CONNECTING == dev->wd_cl.state) { if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
if (mei_connect(dev, &dev->wd_cl)) { dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n"); return -ENOENT;
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
dev->wd_cl.host_client_id = 0;
ret = false;
goto end;
} else {
dev->wd_cl.timer_count = CONNECT_TIMEOUT;
}
} else {
dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
ret = false;
goto end;
} }
end: if (mei_connect(dev, &dev->wd_cl)) {
return ret; dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
dev->wd_cl.host_client_id = 0;
return -EIO;
}
dev->wd_cl.timer_count = CONNECT_TIMEOUT;
return 0;
} }
/** /**
...@@ -159,7 +154,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) ...@@ -159,7 +154,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
if (ret) if (ret)
goto out; goto out;
} else { } else {
dev_dbg(&dev->pdev->dev, "send stop WD failed\n"); dev_err(&dev->pdev->dev, "wd: send stop failed\n");
} }
dev->wd_pending = false; dev->wd_pending = false;
...@@ -173,13 +168,13 @@ int mei_wd_stop(struct mei_device *dev, bool preserve) ...@@ -173,13 +168,13 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
dev->wd_stopped, 10 * HZ); dev->wd_stopped, 10 * HZ);
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->wd_stopped) { if (dev->wd_stopped) {
dev_dbg(&dev->pdev->dev, "stop wd complete ret=%d.\n", ret); dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
ret = 0; ret = 0;
} else { } else {
if (!ret) if (!ret)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
dev_warn(&dev->pdev->dev, dev_warn(&dev->pdev->dev,
"stop wd failed to complete ret=%d.\n", ret); "wd: stop failed to complete ret=%d.\n", ret);
} }
if (preserve) if (preserve)
...@@ -208,13 +203,15 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev) ...@@ -208,13 +203,15 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->mei_state != MEI_ENABLED) { if (dev->mei_state != MEI_ENABLED) {
dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n", dev_dbg(&dev->pdev->dev,
dev->mei_state); "wd: mei_state != MEI_ENABLED mei_state = %d\n",
dev->mei_state);
goto end_unlock; goto end_unlock;
} }
if (dev->wd_cl.state != MEI_FILE_CONNECTED) { if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client\n"); dev_dbg(&dev->pdev->dev,
"MEI Driver is not connected to Watchdog Client\n");
goto end_unlock; goto end_unlock;
} }
...@@ -267,7 +264,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) ...@@ -267,7 +264,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
mutex_lock(&dev->device_lock); mutex_lock(&dev->device_lock);
if (dev->wd_cl.state != MEI_FILE_CONNECTED) { if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
dev_dbg(&dev->pdev->dev, "wd is not connected.\n"); dev_err(&dev->pdev->dev, "wd: not connected.\n");
ret = -ENODEV; ret = -ENODEV;
goto end; goto end;
} }
...@@ -277,16 +274,17 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) ...@@ -277,16 +274,17 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
dev->mei_host_buffer_is_empty = false; dev->mei_host_buffer_is_empty = false;
dev_dbg(&dev->pdev->dev, "sending watchdog ping\n"); dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
if (mei_wd_send(dev)) { if (mei_wd_send(dev)) {
dev_dbg(&dev->pdev->dev, "wd send failed.\n"); dev_err(&dev->pdev->dev, "wd: send failed.\n");
ret = -EIO; ret = -EIO;
goto end; goto end;
} }
if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) { if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
dev_dbg(&dev->pdev->dev, "mei_flow_ctrl_reduce() failed.\n"); dev_err(&dev->pdev->dev,
"wd: mei_flow_ctrl_reduce() failed.\n");
ret = -EIO; ret = -EIO;
goto end; goto end;
} }
...@@ -346,7 +344,7 @@ static const struct watchdog_info wd_info = { ...@@ -346,7 +344,7 @@ static const struct watchdog_info wd_info = {
.options = WDIOF_KEEPALIVEPING, .options = WDIOF_KEEPALIVEPING,
}; };
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 = AMT_WD_DEFAULT_TIMEOUT,
...@@ -362,10 +360,12 @@ void mei_watchdog_register(struct mei_device *dev) ...@@ -362,10 +360,12 @@ void mei_watchdog_register(struct mei_device *dev)
dev->wd_due_counter = !!dev->wd_timeout; dev->wd_due_counter = !!dev->wd_timeout;
if (watchdog_register_device(&amt_wd_dev)) { if (watchdog_register_device(&amt_wd_dev)) {
dev_err(&dev->pdev->dev, "unable to register watchdog device.\n"); dev_err(&dev->pdev->dev,
"wd: unable to register watchdog device.\n");
dev->wd_interface_reg = false; dev->wd_interface_reg = false;
} else { } else {
dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n"); dev_dbg(&dev->pdev->dev,
"wd: successfully register watchdog interface.\n");
dev->wd_interface_reg = true; dev->wd_interface_reg = true;
} }
} }
......
...@@ -203,37 +203,6 @@ config WANXL_BUILD_FIRMWARE ...@@ -203,37 +203,6 @@ config WANXL_BUILD_FIRMWARE
You should never need this option, say N. You should never need this option, say N.
config PC300
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
depends on HDLC && PCI && BROKEN
---help---
This driver is broken because of struct tty_driver change.
Driver for the Cyclades-PC300 synchronous communication boards.
These boards provide synchronous serial interfaces to your
Linux box (interfaces currently available are RS-232/V.35, X.21 and
T1/E1). If you wish to support Multilink PPP, please select the
option later and read the file README.mlppp provided by PC300
package.
To compile this as a module, choose M here: the module
will be called pc300.
If unsure, say N.
config PC300_MLPPP
bool "Cyclades-PC300 MLPPP support"
depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
help
Multilink PPP over the PC300 synchronous communication boards.
comment "Cyclades-PC300 MLPPP support is disabled."
depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
comment "Refer to the file README.mlppp, provided by PC300 package."
depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
config PC300TOO config PC300TOO
tristate "Cyclades PC300 RSV/X21 alternative support" tristate "Cyclades PC300 RSV/X21 alternative support"
depends on HDLC && PCI depends on HDLC && PCI
......
...@@ -17,10 +17,6 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o ...@@ -17,10 +17,6 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
pc300-y := pc300_drv.o
pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
pc300-objs := $(pc300-y)
obj-$(CONFIG_HOSTESS_SV11) += z85230.o hostess_sv11.o obj-$(CONFIG_HOSTESS_SV11) += z85230.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021) += z85230.o sealevel.o obj-$(CONFIG_SEALEVEL_4021) += z85230.o sealevel.o
obj-$(CONFIG_COSA) += cosa.o obj-$(CONFIG_COSA) += cosa.o
...@@ -35,7 +31,6 @@ obj-$(CONFIG_SDLA) += sdla.o ...@@ -35,7 +31,6 @@ obj-$(CONFIG_SDLA) += sdla.o
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
obj-$(CONFIG_LAPBETHER) += lapbether.o obj-$(CONFIG_LAPBETHER) += lapbether.o
obj-$(CONFIG_SBNI) += sbni.o obj-$(CONFIG_SBNI) += sbni.o
obj-$(CONFIG_PC300) += pc300.o
obj-$(CONFIG_N2) += n2.o obj-$(CONFIG_N2) += n2.o
obj-$(CONFIG_C101) += c101.o obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_WANXL) += wanxl.o
......
...@@ -24,8 +24,6 @@ menuconfig STAGING ...@@ -24,8 +24,6 @@ menuconfig STAGING
if STAGING if STAGING
source "drivers/staging/serial/Kconfig"
source "drivers/staging/et131x/Kconfig" source "drivers/staging/et131x/Kconfig"
source "drivers/staging/slicoss/Kconfig" source "drivers/staging/slicoss/Kconfig"
...@@ -72,8 +70,6 @@ source "drivers/staging/vt6655/Kconfig" ...@@ -72,8 +70,6 @@ source "drivers/staging/vt6655/Kconfig"
source "drivers/staging/vt6656/Kconfig" source "drivers/staging/vt6656/Kconfig"
source "drivers/staging/vme/Kconfig"
source "drivers/staging/sep/Kconfig" source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig" source "drivers/staging/iio/Kconfig"
...@@ -114,12 +110,12 @@ source "drivers/staging/cptm1217/Kconfig" ...@@ -114,12 +110,12 @@ source "drivers/staging/cptm1217/Kconfig"
source "drivers/staging/ste_rmi4/Kconfig" source "drivers/staging/ste_rmi4/Kconfig"
source "drivers/staging/mei/Kconfig"
source "drivers/staging/nvec/Kconfig" source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig" source "drivers/staging/media/Kconfig"
source "drivers/staging/net/Kconfig"
source "drivers/staging/omapdrm/Kconfig" source "drivers/staging/omapdrm/Kconfig"
source "drivers/staging/android/Kconfig" source "drivers/staging/android/Kconfig"
...@@ -132,4 +128,8 @@ source "drivers/staging/ozwpan/Kconfig" ...@@ -132,4 +128,8 @@ source "drivers/staging/ozwpan/Kconfig"
source "drivers/staging/ccg/Kconfig" source "drivers/staging/ccg/Kconfig"
source "drivers/staging/ipack/Kconfig"
source "drivers/staging/gdm72xx/Kconfig"
endif # STAGING endif # STAGING
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
# fix for build system bug... # fix for build system bug...
obj-$(CONFIG_STAGING) += staging.o obj-$(CONFIG_STAGING) += staging.o
obj-y += serial/
obj-y += media/ obj-y += media/
obj-y += net/
obj-$(CONFIG_ET131X) += et131x/ obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_USBIP_CORE) += usbip/ obj-$(CONFIG_USBIP_CORE) += usbip/
...@@ -29,6 +29,7 @@ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ ...@@ -29,6 +29,7 @@ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_IPACK_BUS) += ipack/
obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_ZRAM) += zram/ obj-$(CONFIG_ZRAM) += zram/
...@@ -49,7 +50,6 @@ obj-$(CONFIG_FT1000) += ft1000/ ...@@ -49,7 +50,6 @@ obj-$(CONFIG_FT1000) += ft1000/
obj-$(CONFIG_SPEAKUP) += speakup/ obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_DRM_OMAP) += omapdrm/
obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_ANDROID) += android/
...@@ -57,3 +57,4 @@ obj-$(CONFIG_PHONE) += telephony/ ...@@ -57,3 +57,4 @@ obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_RAMSTER) += ramster/
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
obj-$(CONFIG_USB_G_CCG) += ccg/ obj-$(CONFIG_USB_G_CCG) += ccg/
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
...@@ -25,17 +25,9 @@ config ANDROID_LOGGER ...@@ -25,17 +25,9 @@ config ANDROID_LOGGER
tristate "Android log driver" tristate "Android log driver"
default n default n
config ANDROID_PERSISTENT_RAM
bool
depends on HAVE_MEMBLOCK
select REED_SOLOMON
select REED_SOLOMON_ENC8
select REED_SOLOMON_DEC8
config ANDROID_RAM_CONSOLE config ANDROID_RAM_CONSOLE
bool "Android RAM buffer console" bool "Android RAM buffer console"
depends on !S390 && !UML && HAVE_MEMBLOCK depends on !S390 && !UML && HAVE_MEMBLOCK && PSTORE_RAM=y
select ANDROID_PERSISTENT_RAM
default n default n
config ANDROID_TIMED_OUTPUT config ANDROID_TIMED_OUTPUT
...@@ -53,31 +45,15 @@ config ANDROID_LOW_MEMORY_KILLER ...@@ -53,31 +45,15 @@ config ANDROID_LOW_MEMORY_KILLER
---help--- ---help---
Register processes to be killed when memory is low Register processes to be killed when memory is low
config ANDROID_INTF_ALARM config ANDROID_INTF_ALARM_DEV
bool "Android alarm driver" bool "Android alarm driver"
depends on RTC_CLASS depends on RTC_CLASS
default n default n
help help
Provides non-wakeup and rtc backed wakeup alarms based on rtc or Provides non-wakeup and rtc backed wakeup alarms based on rtc or
elapsed realtime, and a non-wakeup alarm on the monotonic clock. elapsed realtime, and a non-wakeup alarm on the monotonic clock.
Also provides an interface to set the wall time which must be used Also exports the alarm interface to user-space.
for elapsed realtime to work.
config ANDROID_INTF_ALARM_DEV
bool "Android alarm device"
depends on ANDROID_INTF_ALARM
default y
help
Exports the alarm interface to user-space.
config ANDROID_ALARM_OLDDRV_COMPAT
bool "Android Alarm compatability with old drivers"
depends on ANDROID_INTF_ALARM
default n
help
Provides preprocessor alias to aid compatability with
older out-of-tree drivers that use the Android Alarm
in-kernel API. This will be removed eventually.
endif # if ANDROID endif # if ANDROID
endmenu endmenu
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
obj-$(CONFIG_ASHMEM) += ashmem.o obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_LOGGER) += logger.o obj-$(CONFIG_ANDROID_LOGGER) += logger.o
obj-$(CONFIG_ANDROID_PERSISTENT_RAM) += persistent_ram.o
obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
...@@ -22,19 +22,9 @@ ...@@ -22,19 +22,9 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/alarmtimer.h>
#include "android_alarm.h" #include "android_alarm.h"
/* XXX - Hack out wakelocks, while they are out of tree */
struct wake_lock {
int i;
};
#define wake_lock(x)
#define wake_lock_timeout(x, y)
#define wake_unlock(x)
#define WAKE_LOCK_SUSPEND 0
#define wake_lock_init(x, y, z) ((x)->i = 1)
#define wake_lock_destroy(x)
#define ANDROID_ALARM_PRINT_INFO (1U << 0) #define ANDROID_ALARM_PRINT_INFO (1U << 0)
#define ANDROID_ALARM_PRINT_IO (1U << 1) #define ANDROID_ALARM_PRINT_IO (1U << 1)
#define ANDROID_ALARM_PRINT_INT (1U << 2) #define ANDROID_ALARM_PRINT_INT (1U << 2)
...@@ -54,19 +44,65 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); ...@@ -54,19 +44,65 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
ANDROID_ALARM_RTC_WAKEUP_MASK | \ ANDROID_ALARM_RTC_WAKEUP_MASK | \
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
/* support old usespace code */ /* support old userspace code */
#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ #define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) #define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
static int alarm_opened; static int alarm_opened;
static DEFINE_SPINLOCK(alarm_slock); static DEFINE_SPINLOCK(alarm_slock);
static struct wake_lock alarm_wake_lock; static struct wakeup_source alarm_wake_lock;
static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
static uint32_t alarm_pending; static uint32_t alarm_pending;
static uint32_t alarm_enabled; static uint32_t alarm_enabled;
static uint32_t wait_pending; static uint32_t wait_pending;
static struct android_alarm alarms[ANDROID_ALARM_TYPE_COUNT]; struct devalarm {
union {
struct hrtimer hrt;
struct alarm alrm;
} u;
enum android_alarm_type type;
};
static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
static int is_wakeup(enum android_alarm_type type)
{
if (type == ANDROID_ALARM_RTC_WAKEUP ||
type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP)
return 1;
return 0;
}
static void devalarm_start(struct devalarm *alrm, ktime_t exp)
{
if (is_wakeup(alrm->type))
alarm_start(&alrm->u.alrm, exp);
else
hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
}
static int devalarm_try_to_cancel(struct devalarm *alrm)
{
int ret;
if (is_wakeup(alrm->type))
ret = alarm_try_to_cancel(&alrm->u.alrm);
else
ret = hrtimer_try_to_cancel(&alrm->u.hrt);
return ret;
}
static void devalarm_cancel(struct devalarm *alrm)
{
if (is_wakeup(alrm->type))
alarm_cancel(&alrm->u.alrm);
else
hrtimer_cancel(&alrm->u.hrt);
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ {
...@@ -75,6 +111,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -75,6 +111,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct timespec new_alarm_time; struct timespec new_alarm_time;
struct timespec new_rtc_time; struct timespec new_rtc_time;
struct timespec tmp_time; struct timespec tmp_time;
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
uint32_t alarm_type_mask = 1U << alarm_type; uint32_t alarm_type_mask = 1U << alarm_type;
...@@ -101,11 +139,11 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -101,11 +139,11 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case ANDROID_ALARM_CLEAR(0): case ANDROID_ALARM_CLEAR(0):
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
pr_alarm(IO, "alarm %d clear\n", alarm_type); pr_alarm(IO, "alarm %d clear\n", alarm_type);
android_alarm_try_to_cancel(&alarms[alarm_type]); devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) { if (alarm_pending) {
alarm_pending &= ~alarm_type_mask; alarm_pending &= ~alarm_type_mask;
if (!alarm_pending && !wait_pending) if (!alarm_pending && !wait_pending)
wake_unlock(&alarm_wake_lock); __pm_relax(&alarm_wake_lock);
} }
alarm_enabled &= ~alarm_type_mask; alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
...@@ -132,8 +170,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -132,8 +170,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
new_alarm_time.tv_sec, new_alarm_time.tv_nsec); new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
alarm_enabled |= alarm_type_mask; alarm_enabled |= alarm_type_mask;
android_alarm_start_range(&alarms[alarm_type], devalarm_start(&alarms[alarm_type],
timespec_to_ktime(new_alarm_time),
timespec_to_ktime(new_alarm_time)); timespec_to_ktime(new_alarm_time));
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
...@@ -144,7 +181,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -144,7 +181,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
pr_alarm(IO, "alarm wait\n"); pr_alarm(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) { if (!alarm_pending && wait_pending) {
wake_unlock(&alarm_wake_lock); __pm_relax(&alarm_wake_lock);
wait_pending = 0; wait_pending = 0;
} }
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
...@@ -163,7 +200,13 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -163,7 +200,13 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rv = -EFAULT; rv = -EFAULT;
goto err1; goto err1;
} }
rv = android_alarm_set_rtc(new_rtc_time); rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(&new_rtc_time);
if (rv < 0)
goto err1;
if (rtc_dev)
rv = rtc_set_time(rtc_dev, &new_rtc_tm);
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
wake_up(&alarm_wait_queue); wake_up(&alarm_wait_queue);
...@@ -179,8 +222,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -179,8 +222,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break; break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
case ANDROID_ALARM_ELAPSED_REALTIME: case ANDROID_ALARM_ELAPSED_REALTIME:
tmp_time = get_monotonic_boottime(&tmp_time);
ktime_to_timespec(alarm_get_elapsed_realtime());
break; break;
case ANDROID_ALARM_TYPE_COUNT: case ANDROID_ALARM_TYPE_COUNT:
case ANDROID_ALARM_SYSTEMTIME: case ANDROID_ALARM_SYSTEMTIME:
...@@ -224,14 +266,14 @@ static int alarm_release(struct inode *inode, struct file *file) ...@@ -224,14 +266,14 @@ static int alarm_release(struct inode *inode, struct file *file)
alarm_enabled &= ~alarm_type_mask; alarm_enabled &= ~alarm_type_mask;
} }
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
android_alarm_cancel(&alarms[i]); devalarm_cancel(&alarms[i]);
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
} }
if (alarm_pending | wait_pending) { if (alarm_pending | wait_pending) {
if (alarm_pending) if (alarm_pending)
pr_alarm(INFO, "alarm_release: clear " pr_alarm(INFO, "alarm_release: clear "
"pending alarms %x\n", alarm_pending); "pending alarms %x\n", alarm_pending);
wake_unlock(&alarm_wake_lock); __pm_relax(&alarm_wake_lock);
wait_pending = 0; wait_pending = 0;
alarm_pending = 0; alarm_pending = 0;
} }
...@@ -241,15 +283,15 @@ static int alarm_release(struct inode *inode, struct file *file) ...@@ -241,15 +283,15 @@ static int alarm_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static void alarm_triggered(struct android_alarm *alarm) static void devalarm_triggered(struct devalarm *alarm)
{ {
unsigned long flags; unsigned long flags;
uint32_t alarm_type_mask = 1U << alarm->type; uint32_t alarm_type_mask = 1U << alarm->type;
pr_alarm(INT, "alarm_triggered type %d\n", alarm->type); pr_alarm(INT, "devalarm_triggered type %d\n", alarm->type);
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
if (alarm_enabled & alarm_type_mask) { if (alarm_enabled & alarm_type_mask) {
wake_lock_timeout(&alarm_wake_lock, 5 * HZ); __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */
alarm_enabled &= ~alarm_type_mask; alarm_enabled &= ~alarm_type_mask;
alarm_pending |= alarm_type_mask; alarm_pending |= alarm_type_mask;
wake_up(&alarm_wait_queue); wake_up(&alarm_wait_queue);
...@@ -257,6 +299,25 @@ static void alarm_triggered(struct android_alarm *alarm) ...@@ -257,6 +299,25 @@ static void alarm_triggered(struct android_alarm *alarm)
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
} }
static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt)
{
struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
devalarm_triggered(devalrm);
return HRTIMER_NORESTART;
}
static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm,
ktime_t now)
{
struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
devalarm_triggered(devalrm);
return ALARMTIMER_NORESTART;
}
static const struct file_operations alarm_fops = { static const struct file_operations alarm_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.unlocked_ioctl = alarm_ioctl, .unlocked_ioctl = alarm_ioctl,
...@@ -279,17 +340,31 @@ static int __init alarm_dev_init(void) ...@@ -279,17 +340,31 @@ static int __init alarm_dev_init(void)
if (err) if (err)
return err; return err;
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm,
android_alarm_init(&alarms[i], i, alarm_triggered); ALARM_REALTIME, devalarm_alarmhandler);
wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt,
CLOCK_REALTIME, HRTIMER_MODE_ABS);
alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm,
ALARM_BOOTTIME, devalarm_alarmhandler);
hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt,
CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
alarms[i].type = i;
if (!is_wakeup(i))
alarms[i].u.hrt.function = devalarm_hrthandler;
}
wakeup_source_init(&alarm_wake_lock, "alarm");
return 0; return 0;
} }
static void __exit alarm_dev_exit(void) static void __exit alarm_dev_exit(void)
{ {
misc_deregister(&alarm_device); misc_deregister(&alarm_device);
wake_lock_destroy(&alarm_wake_lock); wakeup_source_trash(&alarm_wake_lock);
} }
module_init(alarm_dev_init); module_init(alarm_dev_init);
......
/* drivers/rtc/alarm.c
*
* Copyright (C) 2007-2009 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/time.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include "android_alarm.h"
/* XXX - Hack out wakelocks, while they are out of tree */
struct wake_lock {
int i;
};
#define wake_lock(x)
#define wake_lock_timeout(x, y)
#define wake_unlock(x)
#define WAKE_LOCK_SUSPEND 0
#define wake_lock_init(x, y, z) ((x)->i = 1)
#define wake_lock_destroy(x)
#define ANDROID_ALARM_PRINT_ERROR (1U << 0)
#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
#define ANDROID_ALARM_PRINT_TSET (1U << 2)
#define ANDROID_ALARM_PRINT_CALL (1U << 3)
#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4)
#define ANDROID_ALARM_PRINT_INT (1U << 5)
#define ANDROID_ALARM_PRINT_FLOW (1U << 6)
static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \
ANDROID_ALARM_PRINT_INIT_STATUS;
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
#define pr_alarm(debug_level_mask, args...) \
do { \
if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \
pr_info(args); \
} \
} while (0)
#define ANDROID_ALARM_WAKEUP_MASK ( \
ANDROID_ALARM_RTC_WAKEUP_MASK | \
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
/* support old usespace code */
#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
struct alarm_queue {
struct rb_root alarms;
struct rb_node *first;
struct hrtimer timer;
ktime_t delta;
bool stopped;
ktime_t stopped_time;
};
static struct rtc_device *alarm_rtc_dev;
static DEFINE_SPINLOCK(alarm_slock);
static DEFINE_MUTEX(alarm_setrtc_mutex);
static struct wake_lock alarm_rtc_wake_lock;
static struct platform_device *alarm_platform_dev;
struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT];
static bool suspended;
static void update_timer_locked(struct alarm_queue *base, bool head_removed)
{
struct android_alarm *alarm;
bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
if (base->stopped) {
pr_alarm(FLOW, "changed alarm while setting the wall time\n");
return;
}
if (is_wakeup && !suspended && head_removed)
wake_unlock(&alarm_rtc_wake_lock);
if (!base->first)
return;
alarm = container_of(base->first, struct android_alarm, node);
pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n",
alarm->type, alarm->function, ktime_to_ns(alarm->expires));
if (is_wakeup && suspended) {
pr_alarm(FLOW, "changed alarm while suspened\n");
wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
return;
}
hrtimer_try_to_cancel(&base->timer);
base->timer.node.expires = ktime_add(base->delta, alarm->expires);
base->timer._softexpires = ktime_add(base->delta, alarm->softexpires);
hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS);
}
static void alarm_enqueue_locked(struct android_alarm *alarm)
{
struct alarm_queue *base = &alarms[alarm->type];
struct rb_node **link = &base->alarms.rb_node;
struct rb_node *parent = NULL;
struct android_alarm *entry;
int leftmost = 1;
bool was_first = false;
pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n",
alarm->type, alarm->function, ktime_to_ns(alarm->expires));
if (base->first == &alarm->node) {
base->first = rb_next(&alarm->node);
was_first = true;
}
if (!RB_EMPTY_NODE(&alarm->node)) {
rb_erase(&alarm->node, &base->alarms);
RB_CLEAR_NODE(&alarm->node);
}
while (*link) {
parent = *link;
entry = rb_entry(parent, struct android_alarm, node);
/*
* We dont care about collisions. Nodes with
* the same expiry time stay together.
*/
if (alarm->expires.tv64 < entry->expires.tv64) {
link = &(*link)->rb_left;
} else {
link = &(*link)->rb_right;
leftmost = 0;
}
}
if (leftmost)
base->first = &alarm->node;
if (leftmost || was_first)
update_timer_locked(base, was_first);
rb_link_node(&alarm->node, parent, link);
rb_insert_color(&alarm->node, &base->alarms);
}
/**
* android_alarm_init - initialize an alarm
* @alarm: the alarm to be initialized
* @type: the alarm type to be used
* @function: alarm callback function
*/
void android_alarm_init(struct android_alarm *alarm,
enum android_alarm_type type, void (*function)(struct android_alarm *))
{
RB_CLEAR_NODE(&alarm->node);
alarm->type = type;
alarm->function = function;
pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function);
}
/**
* android_alarm_start_range - (re)start an alarm
* @alarm: the alarm to be added
* @start: earliest expiry time
* @end: expiry time
*/
void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
ktime_t end)
{
unsigned long flags;
spin_lock_irqsave(&alarm_slock, flags);
alarm->softexpires = start;
alarm->expires = end;
alarm_enqueue_locked(alarm);
spin_unlock_irqrestore(&alarm_slock, flags);
}
/**
* android_alarm_try_to_cancel - try to deactivate an alarm
* @alarm: alarm to stop
*
* Returns:
* 0 when the alarm was not active
* 1 when the alarm was active
* -1 when the alarm may currently be excuting the callback function and
* cannot be stopped (it may also be inactive)
*/
int android_alarm_try_to_cancel(struct android_alarm *alarm)
{
struct alarm_queue *base = &alarms[alarm->type];
unsigned long flags;
bool first = false;
int ret = 0;
spin_lock_irqsave(&alarm_slock, flags);
if (!RB_EMPTY_NODE(&alarm->node)) {
pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n",
alarm->type, alarm->function,
ktime_to_ns(alarm->expires));
ret = 1;
if (base->first == &alarm->node) {
base->first = rb_next(&alarm->node);
first = true;
}
rb_erase(&alarm->node, &base->alarms);
RB_CLEAR_NODE(&alarm->node);
if (first)
update_timer_locked(base, true);
} else
pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n",
alarm->type, alarm->function);
spin_unlock_irqrestore(&alarm_slock, flags);
if (!ret && hrtimer_callback_running(&base->timer))
ret = -1;
return ret;
}
/**
* android_alarm_cancel - cancel an alarm and wait for the handler to finish.
* @alarm: the alarm to be cancelled
*
* Returns:
* 0 when the alarm was not active
* 1 when the alarm was active
*/
int android_alarm_cancel(struct android_alarm *alarm)
{
for (;;) {
int ret = android_alarm_try_to_cancel(alarm);
if (ret >= 0)
return ret;
cpu_relax();
}
}
/**
* alarm_set_rtc - set the kernel and rtc walltime
* @new_time: timespec value containing the new time
*/
int android_alarm_set_rtc(struct timespec new_time)
{
int i;
int ret;
unsigned long flags;
struct rtc_time rtc_new_rtc_time;
struct timespec tmp_time;
rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time);
pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
new_time.tv_sec, new_time.tv_nsec,
rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
rtc_new_rtc_time.tm_mday,
rtc_new_rtc_time.tm_year + 1900);
mutex_lock(&alarm_setrtc_mutex);
spin_lock_irqsave(&alarm_slock, flags);
wake_lock(&alarm_rtc_wake_lock);
getnstimeofday(&tmp_time);
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
hrtimer_try_to_cancel(&alarms[i].timer);
alarms[i].stopped = true;
alarms[i].stopped_time = timespec_to_ktime(tmp_time);
}
alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta,
timespec_to_ktime(timespec_sub(tmp_time, new_time)));
spin_unlock_irqrestore(&alarm_slock, flags);
ret = do_settimeofday(&new_time);
spin_lock_irqsave(&alarm_slock, flags);
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
alarms[i].stopped = false;
update_timer_locked(&alarms[i], false);
}
spin_unlock_irqrestore(&alarm_slock, flags);
if (ret < 0) {
pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n");
goto err;
}
if (!alarm_rtc_dev) {
pr_alarm(ERROR,
"alarm_set_rtc: no RTC, time will be lost on reboot\n");
goto err;
}
ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
if (ret < 0)
pr_alarm(ERROR, "alarm_set_rtc: "
"Failed to set RTC, time will be lost on reboot\n");
err:
wake_unlock(&alarm_rtc_wake_lock);
mutex_unlock(&alarm_setrtc_mutex);
return ret;
}
/**
* alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format
*
* returns the time in ktime_t format
*/
ktime_t alarm_get_elapsed_realtime(void)
{
ktime_t now;
unsigned long flags;
struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME];
spin_lock_irqsave(&alarm_slock, flags);
now = base->stopped ? base->stopped_time : ktime_get_real();
now = ktime_sub(now, base->delta);
spin_unlock_irqrestore(&alarm_slock, flags);
return now;
}
static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
{
struct alarm_queue *base;
struct android_alarm *alarm;
unsigned long flags;
ktime_t now;
spin_lock_irqsave(&alarm_slock, flags);
base = container_of(timer, struct alarm_queue, timer);
now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer);
now = ktime_sub(now, base->delta);
pr_alarm(INT, "alarm_timer_triggered type %ld at %lld\n",
base - alarms, ktime_to_ns(now));
while (base->first) {
alarm = container_of(base->first, struct android_alarm, node);
if (alarm->softexpires.tv64 > now.tv64) {
pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n",
alarm->function, ktime_to_ns(alarm->expires),
ktime_to_ns(alarm->softexpires));
break;
}
base->first = rb_next(&alarm->node);
rb_erase(&alarm->node, &base->alarms);
RB_CLEAR_NODE(&alarm->node);
pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n",
alarm->type, alarm->function,
ktime_to_ns(alarm->expires),
ktime_to_ns(alarm->softexpires));
spin_unlock_irqrestore(&alarm_slock, flags);
alarm->function(alarm);
spin_lock_irqsave(&alarm_slock, flags);
}
if (!base->first)
pr_alarm(FLOW, "no more alarms of type %ld\n", base - alarms);
update_timer_locked(base, true);
spin_unlock_irqrestore(&alarm_slock, flags);
return HRTIMER_NORESTART;
}
static void alarm_triggered_func(void *p)
{
struct rtc_device *rtc = alarm_rtc_dev;
if (!(rtc->irq_data & RTC_AF))
return;
pr_alarm(INT, "rtc alarm triggered\n");
wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
}
static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
{
int err = 0;
unsigned long flags;
struct rtc_wkalrm rtc_alarm;
struct rtc_time rtc_current_rtc_time;
unsigned long rtc_current_time;
unsigned long rtc_alarm_time;
struct timespec rtc_delta;
struct timespec wall_time;
struct alarm_queue *wakeup_queue = NULL;
struct alarm_queue *tmp_queue = NULL;
pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event);
spin_lock_irqsave(&alarm_slock, flags);
suspended = true;
spin_unlock_irqrestore(&alarm_slock, flags);
hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
hrtimer_cancel(&alarms[
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
if (tmp_queue->first)
wakeup_queue = tmp_queue;
tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
if (tmp_queue->first && (!wakeup_queue ||
hrtimer_get_expires(&tmp_queue->timer).tv64 <
hrtimer_get_expires(&wakeup_queue->timer).tv64))
wakeup_queue = tmp_queue;
if (wakeup_queue) {
rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
getnstimeofday(&wall_time);
rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
set_normalized_timespec(&rtc_delta,
wall_time.tv_sec - rtc_current_time,
wall_time.tv_nsec);
rtc_alarm_time = timespec_sub(ktime_to_timespec(
hrtimer_get_expires(&wakeup_queue->timer)),
rtc_delta).tv_sec;
rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time);
rtc_alarm.enabled = 1;
rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
pr_alarm(SUSPEND,
"rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n",
rtc_alarm_time, rtc_current_time,
rtc_delta.tv_sec, rtc_delta.tv_nsec);
if (rtc_current_time + 1 >= rtc_alarm_time) {
pr_alarm(SUSPEND, "alarm about to go off\n");
memset(&rtc_alarm, 0, sizeof(rtc_alarm));
rtc_alarm.enabled = 0;
rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
spin_lock_irqsave(&alarm_slock, flags);
suspended = false;
wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ);
update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP],
false);
update_timer_locked(&alarms[
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
err = -EBUSY;
spin_unlock_irqrestore(&alarm_slock, flags);
}
}
return err;
}
static int alarm_resume(struct platform_device *pdev)
{
struct rtc_wkalrm alarm;
unsigned long flags;
pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
memset(&alarm, 0, sizeof(alarm));
alarm.enabled = 0;
rtc_set_alarm(alarm_rtc_dev, &alarm);
spin_lock_irqsave(&alarm_slock, flags);
suspended = false;
update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
false);
spin_unlock_irqrestore(&alarm_slock, flags);
return 0;
}
static struct rtc_task alarm_rtc_task = {
.func = alarm_triggered_func
};
static int rtc_alarm_add_device(struct device *dev,
struct class_interface *class_intf)
{
int err;
struct rtc_device *rtc = to_rtc_device(dev);
mutex_lock(&alarm_setrtc_mutex);
if (alarm_rtc_dev) {
err = -EBUSY;
goto err1;
}
alarm_platform_dev =
platform_device_register_simple("alarm", -1, NULL, 0);
if (IS_ERR(alarm_platform_dev)) {
err = PTR_ERR(alarm_platform_dev);
goto err2;
}
err = rtc_irq_register(rtc, &alarm_rtc_task);
if (err)
goto err3;
alarm_rtc_dev = rtc;
pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name);
mutex_unlock(&alarm_setrtc_mutex);
return 0;
err3:
platform_device_unregister(alarm_platform_dev);
err2:
err1:
mutex_unlock(&alarm_setrtc_mutex);
return err;
}
static void rtc_alarm_remove_device(struct device *dev,
struct class_interface *class_intf)
{
if (dev == &alarm_rtc_dev->dev) {
pr_alarm(INIT_STATUS, "lost rtc device for alarms");
rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task);
platform_device_unregister(alarm_platform_dev);
alarm_rtc_dev = NULL;
}
}
static struct class_interface rtc_alarm_interface = {
.add_dev = &rtc_alarm_add_device,
.remove_dev = &rtc_alarm_remove_device,
};
static struct platform_driver alarm_driver = {
.suspend = alarm_suspend,
.resume = alarm_resume,
.driver = {
.name = "alarm"
}
};
static int __init alarm_late_init(void)
{
unsigned long flags;
struct timespec tmp_time, system_time;
/* this needs to run after the rtc is read at boot */
spin_lock_irqsave(&alarm_slock, flags);
/* We read the current rtc and system time so we can later calulate
* elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
* (rtc - (boot_rtc - boot_systemtime))
*/
getnstimeofday(&tmp_time);
ktime_get_ts(&system_time);
alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
timespec_to_ktime(timespec_sub(tmp_time, system_time));
spin_unlock_irqrestore(&alarm_slock, flags);
return 0;
}
static int __init alarm_driver_init(void)
{
int err;
int i;
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
hrtimer_init(&alarms[i].timer,
CLOCK_REALTIME, HRTIMER_MODE_ABS);
alarms[i].timer.function = alarm_timer_triggered;
}
hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer,
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered;
err = platform_driver_register(&alarm_driver);
if (err < 0)
goto err1;
wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
rtc_alarm_interface.class = rtc_class;
err = class_interface_register(&rtc_alarm_interface);
if (err < 0)
goto err2;
return 0;
err2:
wake_lock_destroy(&alarm_rtc_wake_lock);
platform_driver_unregister(&alarm_driver);
err1:
return err;
}
static void __exit alarm_exit(void)
{
class_interface_unregister(&rtc_alarm_interface);
wake_lock_destroy(&alarm_rtc_wake_lock);
platform_driver_unregister(&alarm_driver);
}
late_initcall(alarm_late_init);
module_init(alarm_driver_init);
module_exit(alarm_exit);
...@@ -33,65 +33,6 @@ enum android_alarm_type { ...@@ -33,65 +33,6 @@ enum android_alarm_type {
/* ANDROID_ALARM_TIME_CHANGE = 16 */ /* ANDROID_ALARM_TIME_CHANGE = 16 */
}; };
#ifdef __KERNEL__
#include <linux/ktime.h>
#include <linux/rbtree.h>
/*
* The alarm interface is similar to the hrtimer interface but adds support
* for wakeup from suspend. It also adds an elapsed realtime clock that can
* be used for periodic timers that need to keep runing while the system is
* suspended and not be disrupted when the wall time is set.
*/
/**
* struct alarm - the basic alarm structure
* @node: red black tree node for time ordered insertion
* @type: alarm type. rtc/elapsed-realtime/systemtime, wakeup/non-wakeup.
* @softexpires: the absolute earliest expiry time of the alarm.
* @expires: the absolute expiry time.
* @function: alarm expiry callback function
*
* The alarm structure must be initialized by alarm_init()
*
*/
struct android_alarm {
struct rb_node node;
enum android_alarm_type type;
ktime_t softexpires;
ktime_t expires;
void (*function)(struct android_alarm *);
};
void android_alarm_init(struct android_alarm *alarm,
enum android_alarm_type type, void (*function)(struct android_alarm *));
void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
ktime_t end);
int android_alarm_try_to_cancel(struct android_alarm *alarm);
int android_alarm_cancel(struct android_alarm *alarm);
ktime_t alarm_get_elapsed_realtime(void);
/* set rtc while preserving elapsed realtime */
int android_alarm_set_rtc(const struct timespec ts);
#ifdef CONFIG_ANDROID_ALARM_OLDDRV_COMPAT
/*
* Some older drivers depend on the old API,
* so provide compatability macros for now.
*/
#define alarm android_alarm
#define alarm_init(x, y, z) android_alarm_init(x, y, z)
#define alarm_start_range(x, y, z) android_alarm_start_range(x, y, z)
#define alarm_try_to_cancel(x) android_alarm_try_to_cancel(x)
#define alarm_cancel(x) android_alarm_cancel(x)
#define alarm_set_rtc(x) android_alarm_set_rtc(x)
#endif
#endif
enum android_alarm_return_flags { enum android_alarm_return_flags {
ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
......
...@@ -53,17 +53,17 @@ struct flat_binder_object { ...@@ -53,17 +53,17 @@ struct flat_binder_object {
/* 8 bytes of data. */ /* 8 bytes of data. */
union { union {
void *binder; /* local object */ void __user *binder; /* local object */
signed long handle; /* remote object */ signed long handle; /* remote object */
}; };
/* extra data associated with local object */ /* extra data associated with local object */
void *cookie; void __user *cookie;
}; };
/* /*
* On 64-bit platforms where user code may run in 32-bits the driver must * On 64-bit platforms where user code may run in 32-bits the driver must
* translate the buffer (and local binder) addresses apropriately. * translate the buffer (and local binder) addresses appropriately.
*/ */
struct binder_write_read { struct binder_write_read {
...@@ -139,9 +139,9 @@ struct binder_transaction_data { ...@@ -139,9 +139,9 @@ struct binder_transaction_data {
union { union {
struct { struct {
/* transaction data */ /* transaction data */
const void *buffer; const void __user *buffer;
/* offsets from buffer to flat_binder_object structs */ /* offsets from buffer to flat_binder_object structs */
const void *offsets; const void __user *offsets;
} ptr; } ptr;
uint8_t buf[8]; uint8_t buf[8];
} data; } data;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/vmalloc.h>
#include "logger.h" #include "logger.h"
#include <asm/ioctls.h> #include <asm/ioctls.h>
...@@ -45,8 +46,12 @@ struct logger_log { ...@@ -45,8 +46,12 @@ struct logger_log {
size_t w_off; /* current write head offset */ size_t w_off; /* current write head offset */
size_t head; /* new readers start here */ size_t head; /* new readers start here */
size_t size; /* size of the log */ size_t size; /* size of the log */
struct list_head logs; /* list of log channels (myself)*/
}; };
static LIST_HEAD(log_list);
/* /*
* struct logger_reader - a logging device open for reading * struct logger_reader - a logging device open for reading
* *
...@@ -60,9 +65,9 @@ struct logger_reader { ...@@ -60,9 +65,9 @@ struct logger_reader {
}; };
/* logger_offset - returns index 'n' into the log via (optimized) modulus */ /* logger_offset - returns index 'n' into the log via (optimized) modulus */
size_t logger_offset(struct logger_log *log, size_t n) static size_t logger_offset(struct logger_log *log, size_t n)
{ {
return n & (log->size-1); return n & (log->size - 1);
} }
...@@ -348,7 +353,7 @@ static ssize_t do_write_log_from_user(struct logger_log *log, ...@@ -348,7 +353,7 @@ static ssize_t do_write_log_from_user(struct logger_log *log,
* writev(), and aio_write(). Writes are our fast path, and we try to optimize * writev(), and aio_write(). Writes are our fast path, and we try to optimize
* them above all else. * them above all else.
*/ */
ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov, static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t ppos) unsigned long nr_segs, loff_t ppos)
{ {
struct logger_log *log = file_get_log(iocb->ki_filp); struct logger_log *log = file_get_log(iocb->ki_filp);
...@@ -408,7 +413,15 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -408,7 +413,15 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
return ret; return ret;
} }
static struct logger_log *get_log_from_minor(int); static struct logger_log *get_log_from_minor(int minor)
{
struct logger_log *log;
list_for_each_entry(log, &log_list, logs)
if (log->misc.minor == minor)
return log;
return NULL;
}
/* /*
* logger_open - the log's open() file operation * logger_open - the log's open() file operation
...@@ -565,80 +578,84 @@ static const struct file_operations logger_fops = { ...@@ -565,80 +578,84 @@ static const struct file_operations logger_fops = {
}; };
/* /*
* Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which * Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
* must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than * and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
* LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
*/ */
#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \ static int __init create_log(char *log_name, int size)
static unsigned char _buf_ ## VAR[SIZE]; \ {
static struct logger_log VAR = { \ int ret = 0;
.buffer = _buf_ ## VAR, \ struct logger_log *log;
.misc = { \ unsigned char *buffer;
.minor = MISC_DYNAMIC_MINOR, \
.name = NAME, \
.fops = &logger_fops, \
.parent = NULL, \
}, \
.wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
.readers = LIST_HEAD_INIT(VAR .readers), \
.mutex = __MUTEX_INITIALIZER(VAR .mutex), \
.w_off = 0, \
.head = 0, \
.size = SIZE, \
};
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024) buffer = vmalloc(size);
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024) if (buffer == NULL)
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024) return -ENOMEM;
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)
static struct logger_log *get_log_from_minor(int minor) log = kzalloc(sizeof(struct logger_log), GFP_KERNEL);
{ if (log == NULL) {
if (log_main.misc.minor == minor) ret = -ENOMEM;
return &log_main; goto out_free_buffer;
if (log_events.misc.minor == minor) }
return &log_events; log->buffer = buffer;
if (log_radio.misc.minor == minor)
return &log_radio;
if (log_system.misc.minor == minor)
return &log_system;
return NULL;
}
static int __init init_log(struct logger_log *log) log->misc.minor = MISC_DYNAMIC_MINOR;
{ log->misc.name = kstrdup(log_name, GFP_KERNEL);
int ret; if (log->misc.name == NULL) {
ret = -ENOMEM;
goto out_free_log;
}
log->misc.fops = &logger_fops;
log->misc.parent = NULL;
init_waitqueue_head(&log->wq);
INIT_LIST_HEAD(&log->readers);
mutex_init(&log->mutex);
log->w_off = 0;
log->head = 0;
log->size = size;
INIT_LIST_HEAD(&log->logs);
list_add_tail(&log->logs, &log_list);
/* finally, initialize the misc device for this log */
ret = misc_register(&log->misc); ret = misc_register(&log->misc);
if (unlikely(ret)) { if (unlikely(ret)) {
printk(KERN_ERR "logger: failed to register misc " printk(KERN_ERR "logger: failed to register misc "
"device for log '%s'!\n", log->misc.name); "device for log '%s'!\n", log->misc.name);
return ret; goto out_free_log;
} }
printk(KERN_INFO "logger: created %luK log '%s'\n", printk(KERN_INFO "logger: created %luK log '%s'\n",
(unsigned long) log->size >> 10, log->misc.name); (unsigned long) log->size >> 10, log->misc.name);
return 0; return 0;
out_free_log:
kfree(log);
out_free_buffer:
vfree(buffer);
return ret;
} }
static int __init logger_init(void) static int __init logger_init(void)
{ {
int ret; int ret;
ret = init_log(&log_main); ret = create_log(LOGGER_LOG_MAIN, 256*1024);
if (unlikely(ret)) if (unlikely(ret))
goto out; goto out;
ret = init_log(&log_events); ret = create_log(LOGGER_LOG_EVENTS, 256*1024);
if (unlikely(ret)) if (unlikely(ret))
goto out; goto out;
ret = init_log(&log_radio); ret = create_log(LOGGER_LOG_RADIO, 256*1024);
if (unlikely(ret)) if (unlikely(ret))
goto out; goto out;
ret = init_log(&log_system); ret = create_log(LOGGER_LOG_SYSTEM, 256*1024);
if (unlikely(ret)) if (unlikely(ret))
goto out; goto out;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/io.h> #include <linux/io.h>
#include "persistent_ram.h" #include <linux/pstore_ram.h>
#include "ram_console.h" #include "ram_console.h"
static struct persistent_ram_zone *ram_console_zone; static struct persistent_ram_zone *ram_console_zone;
......
...@@ -99,6 +99,7 @@ EXPORT_SYMBOL_GPL(timed_output_dev_register); ...@@ -99,6 +99,7 @@ EXPORT_SYMBOL_GPL(timed_output_dev_register);
void timed_output_dev_unregister(struct timed_output_dev *tdev) void timed_output_dev_unregister(struct timed_output_dev *tdev)
{ {
tdev->enable(tdev, 0);
device_remove_file(tdev->dev, &dev_attr_enable); device_remove_file(tdev->dev, &dev_attr_enable);
device_destroy(timed_output_class, MKDEV(0, tdev->index)); device_destroy(timed_output_class, MKDEV(0, tdev->index));
dev_set_drvdata(tdev->dev, NULL); dev_set_drvdata(tdev->dev, NULL);
......
此差异已折叠。
...@@ -1115,20 +1115,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) ...@@ -1115,20 +1115,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{ {
case DDR_80_MHZ: case DDR_80_MHZ:
psDDRSetting = asT3LP_DDRSetting80MHz; psDDRSetting = asT3LP_DDRSetting80MHz;
RegCount = (sizeof(asT3LP_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3LP_DDRSetting80MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break; break;
case DDR_100_MHZ: case DDR_100_MHZ:
psDDRSetting = asT3LP_DDRSetting100MHz; psDDRSetting = asT3LP_DDRSetting100MHz;
RegCount = (sizeof(asT3LP_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3LP_DDRSetting100MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break; break;
case DDR_133_MHZ: case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE; bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LP_DDRSetting133MHz; psDDRSetting = asT3LP_DDRSetting133MHz;
RegCount = (sizeof(asT3LP_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3LP_DDRSetting133MHz);
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break; break;
...@@ -1146,20 +1146,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) ...@@ -1146,20 +1146,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{ {
case DDR_80_MHZ: case DDR_80_MHZ:
psDDRSetting = asT3LPB_DDRSetting80MHz; psDDRSetting = asT3LPB_DDRSetting80MHz;
RegCount=(sizeof(asT3LPB_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); RegCount=ARRAY_SIZE(asT3LPB_DDRSetting80MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break; break;
case DDR_100_MHZ: case DDR_100_MHZ:
psDDRSetting = asT3LPB_DDRSetting100MHz; psDDRSetting = asT3LPB_DDRSetting100MHz;
RegCount = (sizeof(asT3LPB_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3LPB_DDRSetting100MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break; break;
case DDR_133_MHZ: case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE; bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LPB_DDRSetting133MHz; psDDRSetting = asT3LPB_DDRSetting133MHz;
RegCount = (sizeof(asT3LPB_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3LPB_DDRSetting133MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break; break;
...@@ -1167,7 +1167,7 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) ...@@ -1167,7 +1167,7 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
case DDR_160_MHZ: case DDR_160_MHZ:
bOverrideSelfRefresh = TRUE; bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3LPB_DDRSetting160MHz; psDDRSetting = asT3LPB_DDRSetting160MHz;
RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SET_NODE); RegCount = ARRAY_SIZE(asT3LPB_DDRSetting160MHz);
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ; RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ; psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
...@@ -1181,19 +1181,19 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) ...@@ -1181,19 +1181,19 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{ {
case DDR_80_MHZ: case DDR_80_MHZ:
psDDRSetting = asT3_DDRSetting80MHz; psDDRSetting = asT3_DDRSetting80MHz;
RegCount = (sizeof(asT3_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3_DDRSetting80MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break; break;
case DDR_100_MHZ: case DDR_100_MHZ:
psDDRSetting = asT3_DDRSetting100MHz; psDDRSetting = asT3_DDRSetting100MHz;
RegCount = (sizeof(asT3_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3_DDRSetting100MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break; break;
case DDR_133_MHZ: case DDR_133_MHZ:
psDDRSetting = asT3_DDRSetting133MHz; psDDRSetting = asT3_DDRSetting133MHz;
RegCount = (sizeof(asT3_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3_DDRSetting133MHz);
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
break; break;
...@@ -1207,20 +1207,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter) ...@@ -1207,20 +1207,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
{ {
case DDR_80_MHZ: case DDR_80_MHZ:
psDDRSetting = asT3B_DDRSetting80MHz; psDDRSetting = asT3B_DDRSetting80MHz;
RegCount = (sizeof(asT3B_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3B_DDRSetting80MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
break; break;
case DDR_100_MHZ: case DDR_100_MHZ:
psDDRSetting = asT3B_DDRSetting100MHz; psDDRSetting = asT3B_DDRSetting100MHz;
RegCount = (sizeof(asT3B_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3B_DDRSetting100MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
break; break;
case DDR_133_MHZ: case DDR_133_MHZ:
bOverrideSelfRefresh = TRUE; bOverrideSelfRefresh = TRUE;
psDDRSetting = asT3B_DDRSetting133MHz; psDDRSetting = asT3B_DDRSetting133MHz;
RegCount = (sizeof(asT3B_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); RegCount = ARRAY_SIZE(asT3B_DDRSetting133MHz);
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
break; break;
......
此差异已折叠。
...@@ -835,7 +835,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter) ...@@ -835,7 +835,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
Bcm_kill_all_URBs(psIntfAdapter); Bcm_kill_all_URBs(psIntfAdapter);
/* Reset the UMA-B Device */ /* Reset the UMA-B Device */
if (ps_adapter->chip_id >= T3LPB) { if (ps_adapter->chip_id >= T3LPB) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n"); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Resetting UMA-B\n");
retval = usb_reset_device(psIntfAdapter->udev); retval = usb_reset_device(psIntfAdapter->udev);
psIntfAdapter->psAdapter->StopAllXaction = FALSE; psIntfAdapter->psAdapter->StopAllXaction = FALSE;
......
此差异已折叠。
...@@ -465,7 +465,7 @@ ...@@ -465,7 +465,7 @@
/* only relevant to kernel modules. */ /* only relevant to kernel modules. */
#define COMEDI_CB_EOS 1 /* end of scan */ #define COMEDI_CB_EOS 1 /* end of scan */
#define COMEDI_CB_EOA 2 /* end of acquisition */ #define COMEDI_CB_EOA 2 /* end of acquisition/output */
#define COMEDI_CB_BLOCK 4 /* data has arrived: #define COMEDI_CB_BLOCK 4 /* data has arrived:
* wakes up read() / write() */ * wakes up read() / write() */
#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */ #define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
......
此差异已折叠。
此差异已折叠。
...@@ -209,36 +209,23 @@ static int aio_aio12_8_attach(struct comedi_device *dev, ...@@ -209,36 +209,23 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
return 0; return 0;
} }
static int aio_aio12_8_detach(struct comedi_device *dev) static void aio_aio12_8_detach(struct comedi_device *dev)
{ {
subdev_8255_cleanup(dev, &dev->subdevices[2]); subdev_8255_cleanup(dev, &dev->subdevices[2]);
if (dev->iobase) if (dev->iobase)
release_region(dev->iobase, 24); release_region(dev->iobase, 24);
return 0;
} }
static struct comedi_driver driver_aio_aio12_8 = { static struct comedi_driver aio_aio12_8_driver = {
.driver_name = "aio_aio12_8", .driver_name = "aio_aio12_8",
.module = THIS_MODULE, .module = THIS_MODULE,
.attach = aio_aio12_8_attach, .attach = aio_aio12_8_attach,
.detach = aio_aio12_8_detach, .detach = aio_aio12_8_detach,
.board_name = &board_types[0].name, .board_name = &board_types[0].name,
.num_names = 1, .num_names = ARRAY_SIZE(board_types),
.offset = sizeof(struct aio12_8_boardtype), .offset = sizeof(struct aio12_8_boardtype),
}; };
module_comedi_driver(aio_aio12_8_driver);
static int __init driver_aio_aio12_8_init_module(void)
{
return comedi_driver_register(&driver_aio_aio12_8);
}
static void __exit driver_aio_aio12_8_cleanup_module(void)
{
comedi_driver_unregister(&driver_aio_aio12_8);
}
module_init(driver_aio_aio12_8_init_module);
module_exit(driver_aio_aio12_8_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_DESCRIPTION("Comedi low-level driver");
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册