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

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

Pull staging tree update from Greg KH:
 "Here's the large staging tree merge for 3.11-rc1

  Huge thing here is the Lustre client code.  Unfortunatly, due to it
  not building properly on a wide variety of different architectures
  (this was production code???), it is currently disabled from the build
  so as to not annoy people.

  Other than Lustre, there are loads of comedi patches, working to clean
  up that subsystem, iio updates and new drivers, and a load of cleanups
  from the OPW applicants in their quest to get a summer internship.

  All of these have been in the linux-next releases for a while (hence
  the Lustre code being disabled)"

Fixed up trivial conflict in drivers/staging/serqt_usb2/serqt_usb2.c due
to independent renamings in the staging driver cleanup and the USB
tree..

* tag 'staging-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (868 commits)
  Revert "Revert "Revert "staging/lustre: drop CONFIG_BROKEN dependency"""
  staging: rtl8192u: fix line length in r819xU_phy.h
  staging: rtl8192u: rename variables in r819xU_phy.h
  staging: rtl8192u: fix comments in r819xU_phy.h
  staging: rtl8192u: fix whitespace in r819xU_phy.h
  staging: rtl8192u: fix newlines in r819xU_phy.c
  staging: comedi: unioxx5: use comedi_alloc_spriv()
  staging: comedi: unioxx5: fix unioxx5_detach()
  silicom: checkpatch: errors caused by macros
  Staging: silicom: remove the board_t typedef in bpctl_mod.c
  Staging: silicom: capitalize labels in the bp_media_type enum
  Staging: silicom: remove bp_media_type enum typedef
  staging: rtl8192u: replace msleep(1) with usleep_range() in r819xU_phy.c
  staging: rtl8192u: rename dwRegRead and rtStatus in r819xU_phy.c
  staging: rtl8192u: replace __FUNCTION__ in r819xU_phy.c
  staging: rtl8192u: limit line size in r819xU_phy.c
  zram: allow request end to coincide with disksize
  staging: drm/imx: use generic irq chip unused field to block out invalid irqs
  staging: drm/imx: use generic irqchip
  staging: drm/imx: ipu-dmfc: use defines for ipu channel numbers
  ...
......@@ -690,45 +690,45 @@ Description:
Actually start the buffer capture up. Will start trigger
if first device and appropriate.
What: /sys/bus/iio/devices/iio:deviceX/buffer/scan_elements
What: /sys/bus/iio/devices/iio:deviceX/scan_elements
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Directory containing interfaces for elements that will be
captured for a single triggered sample set in the buffer.
What: /sys/.../buffer/scan_elements/in_accel_x_en
What: /sys/.../buffer/scan_elements/in_accel_y_en
What: /sys/.../buffer/scan_elements/in_accel_z_en
What: /sys/.../buffer/scan_elements/in_anglvel_x_en
What: /sys/.../buffer/scan_elements/in_anglvel_y_en
What: /sys/.../buffer/scan_elements/in_anglvel_z_en
What: /sys/.../buffer/scan_elements/in_magn_x_en
What: /sys/.../buffer/scan_elements/in_magn_y_en
What: /sys/.../buffer/scan_elements/in_magn_z_en
What: /sys/.../buffer/scan_elements/in_timestamp_en
What: /sys/.../buffer/scan_elements/in_voltageY_supply_en
What: /sys/.../buffer/scan_elements/in_voltageY_en
What: /sys/.../buffer/scan_elements/in_voltageY-voltageZ_en
What: /sys/.../buffer/scan_elements/in_incli_x_en
What: /sys/.../buffer/scan_elements/in_incli_y_en
What: /sys/.../buffer/scan_elements/in_pressureY_en
What: /sys/.../buffer/scan_elements/in_pressure_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_x_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_y_en
What: /sys/.../iio:deviceX/scan_elements/in_accel_z_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_en
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_en
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_en
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en
What: /sys/.../iio:deviceX/scan_elements/in_pressure_en
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
Scan element control for triggered data capture.
What: /sys/.../buffer/scan_elements/in_accel_type
What: /sys/.../buffer/scan_elements/in_anglvel_type
What: /sys/.../buffer/scan_elements/in_magn_type
What: /sys/.../buffer/scan_elements/in_incli_type
What: /sys/.../buffer/scan_elements/in_voltageY_type
What: /sys/.../buffer/scan_elements/in_voltage_type
What: /sys/.../buffer/scan_elements/in_voltageY_supply_type
What: /sys/.../buffer/scan_elements/in_timestamp_type
What: /sys/.../buffer/scan_elements/in_pressureY_type
What: /sys/.../buffer/scan_elements/in_pressure_type
What: /sys/.../iio:deviceX/scan_elements/in_accel_type
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_type
What: /sys/.../iio:deviceX/scan_elements/in_magn_type
What: /sys/.../iio:deviceX/scan_elements/in_incli_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type
What: /sys/.../iio:deviceX/scan_elements/in_voltage_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type
What: /sys/.../iio:deviceX/scan_elements/in_pressure_type
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......@@ -752,29 +752,29 @@ Description:
For other storage combinations this attribute will be extended
appropriately.
What: /sys/.../buffer/scan_elements/in_accel_type_available
What: /sys/.../iio:deviceX/scan_elements/in_accel_type_available
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
If the type parameter can take one of a small set of values,
this attribute lists them.
What: /sys/.../buffer/scan_elements/in_voltageY_index
What: /sys/.../buffer/scan_elements/in_voltageY_supply_index
What: /sys/.../buffer/scan_elements/in_accel_x_index
What: /sys/.../buffer/scan_elements/in_accel_y_index
What: /sys/.../buffer/scan_elements/in_accel_z_index
What: /sys/.../buffer/scan_elements/in_anglvel_x_index
What: /sys/.../buffer/scan_elements/in_anglvel_y_index
What: /sys/.../buffer/scan_elements/in_anglvel_z_index
What: /sys/.../buffer/scan_elements/in_magn_x_index
What: /sys/.../buffer/scan_elements/in_magn_y_index
What: /sys/.../buffer/scan_elements/in_magn_z_index
What: /sys/.../buffer/scan_elements/in_incli_x_index
What: /sys/.../buffer/scan_elements/in_incli_y_index
What: /sys/.../buffer/scan_elements/in_timestamp_index
What: /sys/.../buffer/scan_elements/in_pressureY_index
What: /sys/.../buffer/scan_elements/in_pressure_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_x_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_y_index
What: /sys/.../iio:deviceX/scan_elements/in_anglvel_z_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_x_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_y_index
What: /sys/.../iio:deviceX/scan_elements/in_magn_z_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_index
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_index
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_index
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_index
What: /sys/.../iio:deviceX/scan_elements/in_pressure_index
KernelVersion: 2.6.37
Contact: linux-iio@vger.kernel.org
Description:
......
Analog Devices AD7303 DAC device driver
Required properties:
- compatible: Must be "adi,ad7303"
- reg: SPI chip select number for the device
- spi-max-frequency: Max SPI frequency to use (< 30000000)
- Vdd-supply: Phandle to the Vdd power supply
Optional properties:
- REF-supply: Phandle to the external reference voltage supply. This should
only be set if there is an external reference voltage connected to the REF
pin. If the property is not set Vdd/2 is used as the reference voltage.
Example:
ad7303@4 {
compatible = "adi,ad7303";
reg = <4>;
spi-max-frequency = <10000000>;
Vdd-supply = <&vdd_supply>;
adi,use-external-reference;
REF-supply = <&vref_supply>;
};
Analog Devices ADF4350/ADF4351 device driver
Required properties:
- compatible: Should be one of
* "adi,adf4350": When using the ADF4350 device
* "adi,adf4351": When using the ADF4351 device
- reg: SPI chip select numbert for the device
- spi-max-frequency: Max SPI frequency to use (< 20000000)
- clocks: From common clock binding. Clock is phandle to clock for
ADF435x Reference Clock (CLKIN).
Optional properties:
- gpios: GPIO Lock detect - If set with a valid phandle and GPIO number,
pll lock state is tested upon read.
- adi,channel-spacing: Channel spacing in Hz (influences MODULUS).
- adi,power-up-frequency: If set in Hz the PLL tunes to
the desired frequency on probe.
- adi,reference-div-factor: If set the driver skips dynamic calculation
and uses this default value instead.
- adi,reference-doubler-enable: Enables reference doubler.
- adi,reference-div2-enable: Enables reference divider.
- adi,phase-detector-polarity-positive-enable: Enables positive phase
detector polarity. Default = negative.
- adi,lock-detect-precision-6ns-enable: Enables 6ns lock detect precision.
Default = 10ns.
- adi,lock-detect-function-integer-n-enable: Enables lock detect
for integer-N mode. Default = factional-N mode.
- adi,charge-pump-current: Charge pump current in mA.
Default = 2500mA.
- adi,muxout-select: On chip multiplexer output selection.
Valid values for the multiplexer output are:
0: Three-State Output (default)
1: DVDD
2: DGND
3: R-Counter output
4: N-Divider output
5: Analog lock detect
6: Digital lock detect
- adi,low-spur-mode-enable: Enables low spur mode.
Default = Low noise mode.
- adi,cycle-slip-reduction-enable: Enables cycle slip reduction.
- adi,charge-cancellation-enable: Enabled charge pump
charge cancellation for integer-N modes.
- adi,anti-backlash-3ns-enable: Enables 3ns antibacklash pulse width
for integer-N modes.
- adi,band-select-clock-mode-high-enable: Enables faster band
selection logic.
- adi,12bit-clk-divider: Clock divider value used when
adi,12bit-clkdiv-mode != 0
- adi,clk-divider-mode:
Valid values for the clkdiv mode are:
0: Clock divider off (default)
1: Fast lock enable
2: Phase resync enable
- adi,aux-output-enable: Enables auxiliary RF output.
- adi,aux-output-fundamental-enable: Selects fundamental VCO output on
the auxiliary RF output. Default = Output of RF dividers.
- adi,mute-till-lock-enable: Enables Mute-Till-Lock-Detect function.
- adi,output-power: Output power selection.
Valid values for the power mode are:
0: -4dBm (default)
1: -1dBm
2: +2dBm
3: +5dBm
- adi,aux-output-power: Auxiliary output power selection.
Valid values for the power mode are:
0: -4dBm (default)
1: -1dBm
2: +2dBm
3: +5dBm
Example:
lo_pll0_rx_adf4351: adf4351-rx-lpc@4 {
compatible = "adi,adf4351";
reg = <4>;
spi-max-frequency = <10000000>;
clocks = <&clk0_ad9523 9>;
clock-names = "clkin";
adi,channel-spacing = <10000>;
adi,power-up-frequency = <2400000000>;
adi,phase-detector-polarity-positive-enable;
adi,charge-pump-current = <2500>;
adi,output-power = <3>;
adi,mute-till-lock-enable;
};
* AsahiKASEI AK8975 magnetometer sensor
Required properties:
- compatible : should be "asahi-kasei,ak8975"
- reg : the I2C address of the magnetometer
Optional properties:
- gpios : should be device tree identifier of the magnetometer DRDY pin
Example:
ak8975@0c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
gpios = <&gpj0 7 0>;
};
Device-Tree bindings for LVDS Display Bridge (ldb)
LVDS Display Bridge
===================
The LVDS Display Bridge device tree node contains up to two lvds-channel
nodes describing each of the two LVDS encoder channels of the bridge.
Required properties:
- #address-cells : should be <1>
- #size-cells : should be <0>
- compatible : should be "fsl,imx53-ldb" or "fsl,imx6q-ldb".
Both LDB versions are similar, but i.MX6 has an additional
multiplexer in the front to select any of the four IPU display
interfaces as input for each LVDS channel.
- gpr : should be <&gpr> on i.MX53 and i.MX6q.
The phandle points to the iomuxc-gpr region containing the LVDS
control register.
- clocks, clock-names : phandles to the LDB divider and selector clocks and to
the display interface selector clocks, as described in
Documentation/devicetree/bindings/clock/clock-bindings.txt
The following clocks are expected on i.MX53:
"di0_pll" - LDB LVDS channel 0 mux
"di1_pll" - LDB LVDS channel 1 mux
"di0" - LDB LVDS channel 0 gate
"di1" - LDB LVDS channel 1 gate
"di0_sel" - IPU1 DI0 mux
"di1_sel" - IPU1 DI1 mux
On i.MX6q the following additional clocks are needed:
"di2_sel" - IPU2 DI0 mux
"di3_sel" - IPU2 DI1 mux
The needed clock numbers for each are documented in
Documentation/devicetree/bindings/clock/imx5-clock.txt, and in
Documentation/devicetree/bindings/clock/imx6q-clock.txt.
Optional properties:
- pinctrl-names : should be "default" on i.MX53, not used on i.MX6q
- pinctrl-0 : a phandle pointing to LVDS pin settings on i.MX53,
not used on i.MX6q
- fsl,dual-channel : boolean. if it exists, only LVDS channel 0 should
be configured - one input will be distributed on both outputs in dual
channel mode
LVDS Channel
============
Each LVDS Channel has to contain a display-timings node that describes the
video timings for the connected LVDS display. For detailed information, also
have a look at Documentation/devicetree/bindings/video/display-timing.txt.
Required properties:
- reg : should be <0> or <1>
- crtcs : a list of phandles with index pointing to the IPU display interfaces
that can be used as video source for this channel.
- fsl,data-mapping : should be "spwg" or "jeida"
This describes how the color bits are laid out in the
serialized LVDS signal.
- fsl,data-width : should be <18> or <24>
example:
gpr: iomuxc-gpr@53fa8000 {
/* ... */
};
ldb: ldb@53fa8008 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx53-ldb";
gpr = <&gpr>;
clocks = <&clks 122>, <&clks 120>,
<&clks 115>, <&clks 116>,
<&clks 123>, <&clks 85>;
clock-names = "di0_pll", "di1_pll",
"di0_sel", "di1_sel",
"di0", "di1";
lvds-channel@0 {
reg = <0>;
crtcs = <&ipu 0>;
fsl,data-mapping = "spwg";
fsl,data-width = <24>;
display-timings {
/* ... */
};
};
lvds-channel@1 {
reg = <1>;
crtcs = <&ipu 1>;
fsl,data-mapping = "spwg";
fsl,data-width = <24>;
display-timings {
/* ... */
};
};
};
......@@ -7783,7 +7783,7 @@ F: drivers/staging/media/solo6x10/
STAGING - SPEAKUP CONSOLE SPEECH DRIVER
M: William Hubbs <w.d.hubbs@gmail.com>
M: Chris Brannon <chris@the-brannons.com>
M: Kirk Reiser <kirk@braille.uwo.ca>
M: Kirk Reiser <kirk@reisers.ca>
M: Samuel Thibault <samuel.thibault@ens-lyon.org>
L: speakup@braille.uwo.ca
W: http://www.linux-speakup.org/
......
......@@ -70,5 +70,9 @@ source "drivers/iio/gyro/Kconfig"
source "drivers/iio/imu/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig"
if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig"
endif #IIO_TRIGGER
source "drivers/iio/pressure/Kconfig"
endif # IIO
......@@ -21,3 +21,5 @@ obj-y += frequency/
obj-y += imu/
obj-y += light/
obj-y += magnetometer/
obj-y += trigger/
obj-y += pressure/
......@@ -28,7 +28,6 @@ config IIO_ST_ACCEL_3AXIS
select IIO_ST_ACCEL_I2C_3AXIS if (I2C)
select IIO_ST_ACCEL_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_ACCEL_BUFFER if (IIO_TRIGGERED_BUFFER)
help
Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
......
......@@ -26,6 +26,8 @@
#include <linux/iio/common/st_sensors.h>
#include "st_accel.h"
#define ST_ACCEL_NUMBER_DATA_CHANNELS 3
/* DEFAULT VALUE FOR SENSORS */
#define ST_ACCEL_DEFAULT_OUT_X_L_ADDR 0x28
#define ST_ACCEL_DEFAULT_OUT_Y_L_ADDR 0x2a
......@@ -125,22 +127,34 @@
#define ST_ACCEL_3_MULTIREAD_BIT false
static const struct iio_chan_spec st_accel_12bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 12, 16,
ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 12, 16,
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 12, 16,
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
static const struct iio_chan_spec st_accel_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
......@@ -442,6 +456,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
if (err < 0)
goto st_accel_common_probe_error;
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor->multi_read_bit;
indio_dev->channels = adata->sensor->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
......
......@@ -133,6 +133,16 @@ config MAX1363
max11646, max11647) Provides direct access via sysfs and buffered
data via the iio dev interface.
config MCP320X
tristate "Microchip Technology MCP3204/08"
depends on SPI
help
Say yes here to build support for Microchip Technology's MCP3204 or
MCP3208 analog to digital converter.
This driver can also be built as a module. If so, the module will be
called mcp320x.
config TI_ADC081C
tristate "Texas Instruments ADC081C021/027"
depends on I2C
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
......@@ -774,11 +774,13 @@ static int at91_adc_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id at91_adc_dt_ids[] = {
{ .compatible = "atmel,at91sam9260-adc" },
{},
};
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
#endif
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
......
......@@ -270,16 +270,16 @@ static int exynos_adc_probe(struct platform_device *pdev)
info = iio_priv(indio_dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
info->regs = devm_request_and_ioremap(&pdev->dev, mem);
if (!info->regs) {
ret = -ENOMEM;
info->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->regs)) {
ret = PTR_ERR(info->regs);
goto err_iio;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->enable_reg = devm_request_and_ioremap(&pdev->dev, mem);
if (!info->enable_reg) {
ret = -ENOMEM;
info->enable_reg = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(info->enable_reg)) {
ret = PTR_ERR(info->enable_reg);
goto err_iio;
}
......
......@@ -660,7 +660,7 @@ static ssize_t max1363_monitor_store_freq(struct device *dev,
unsigned long val;
bool found = false;
ret = strict_strtoul(buf, 10, &val);
ret = kstrtoul(buf, 10, &val);
if (ret)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++)
......
/*
* Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com>
*
* Driver for Microchip Technology's MCP3204 and MCP3208 ADC chips.
* Datasheet can be found here:
* http://ww1.microchip.com/downloads/en/devicedoc/21298c.pdf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
#define MCP_SINGLE_ENDED (1 << 3)
#define MCP_START_BIT (1 << 4)
enum {
mcp3204,
mcp3208,
};
struct mcp320x {
struct spi_device *spi;
struct spi_message msg;
struct spi_transfer transfer[2];
u8 tx_buf;
u8 rx_buf[2];
struct regulator *reg;
struct mutex lock;
};
static int mcp320x_adc_conversion(struct mcp320x *adc, u8 msg)
{
int ret;
adc->tx_buf = msg;
ret = spi_sync(adc->spi, &adc->msg);
if (ret < 0)
return ret;
return ((adc->rx_buf[0] & 0x3f) << 6) |
(adc->rx_buf[1] >> 2);
}
static int mcp320x_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long mask)
{
struct mcp320x *adc = iio_priv(indio_dev);
int ret = -EINVAL;
mutex_lock(&adc->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (channel->differential)
ret = mcp320x_adc_conversion(adc,
MCP_START_BIT | channel->address);
else
ret = mcp320x_adc_conversion(adc,
MCP_START_BIT | MCP_SINGLE_ENDED |
channel->address);
if (ret < 0)
goto out;
*val = ret;
ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
/* Digital output code = (4096 * Vin) / Vref */
ret = regulator_get_voltage(adc->reg);
if (ret < 0)
goto out;
*val = ret / 1000;
*val2 = 12;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
default:
break;
}
out:
mutex_unlock(&adc->lock);
return ret;
}
#define MCP320X_VOLTAGE_CHANNEL(num) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num), \
.address = (num), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (num * 2), \
.channel2 = (num * 2 + 1), \
.address = (num * 2), \
.differential = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec mcp3204_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
};
static const struct iio_chan_spec mcp3208_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
MCP320X_VOLTAGE_CHANNEL(4),
MCP320X_VOLTAGE_CHANNEL(5),
MCP320X_VOLTAGE_CHANNEL(6),
MCP320X_VOLTAGE_CHANNEL(7),
MCP320X_VOLTAGE_CHANNEL_DIFF(0),
MCP320X_VOLTAGE_CHANNEL_DIFF(1),
MCP320X_VOLTAGE_CHANNEL_DIFF(2),
MCP320X_VOLTAGE_CHANNEL_DIFF(3),
};
static const struct iio_info mcp320x_info = {
.read_raw = mcp320x_read_raw,
.driver_module = THIS_MODULE,
};
struct mcp3208_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
};
static const struct mcp3208_chip_info mcp3208_chip_infos[] = {
[mcp3204] = {
.channels = mcp3204_channels,
.num_channels = ARRAY_SIZE(mcp3204_channels)
},
[mcp3208] = {
.channels = mcp3208_channels,
.num_channels = ARRAY_SIZE(mcp3208_channels)
},
};
static int mcp320x_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct mcp320x *adc;
const struct mcp3208_chip_info *chip_info;
int ret;
indio_dev = iio_device_alloc(sizeof(*adc));
if (!indio_dev)
return -ENOMEM;
adc = iio_priv(indio_dev);
adc->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp320x_info;
chip_info = &mcp3208_chip_infos[spi_get_device_id(spi)->driver_data];
indio_dev->channels = chip_info->channels;
indio_dev->num_channels = chip_info->num_channels;
adc->transfer[0].tx_buf = &adc->tx_buf;
adc->transfer[0].len = sizeof(adc->tx_buf);
adc->transfer[1].rx_buf = adc->rx_buf;
adc->transfer[1].len = sizeof(adc->rx_buf);
spi_message_init_with_transfers(&adc->msg, adc->transfer,
ARRAY_SIZE(adc->transfer));
adc->reg = regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->reg)) {
ret = PTR_ERR(adc->reg);
goto iio_free;
}
ret = regulator_enable(adc->reg);
if (ret < 0)
goto reg_free;
mutex_init(&adc->lock);
ret = iio_device_register(indio_dev);
if (ret < 0)
goto reg_disable;
return 0;
reg_disable:
regulator_disable(adc->reg);
reg_free:
regulator_put(adc->reg);
iio_free:
iio_device_free(indio_dev);
return ret;
}
static int mcp320x_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct mcp320x *adc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
regulator_disable(adc->reg);
regulator_put(adc->reg);
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id mcp320x_id[] = {
{ "mcp3204", mcp3204 },
{ "mcp3208", mcp3208 },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp320x_id);
static struct spi_driver mcp320x_driver = {
.driver = {
.name = "mcp320x",
.owner = THIS_MODULE,
},
.probe = mcp320x_probe,
.remove = mcp320x_remove,
.id_table = mcp320x_id,
};
module_spi_driver(mcp320x_driver);
MODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>");
MODULE_DESCRIPTION("Microchip Technology MCP3204/08");
MODULE_LICENSE("GPL v2");
......@@ -24,11 +24,20 @@
int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
{
u8 *addr;
int i, n = 0, len;
u8 addr[ST_SENSORS_NUMBER_DATA_CHANNELS];
struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int num_data_channels = sdata->num_data_channels;
unsigned int byte_for_channel =
indio_dev->channels[0].scan_type.storagebits >> 3;
for (i = 0; i < ST_SENSORS_NUMBER_DATA_CHANNELS; i++) {
addr = kmalloc(num_data_channels, GFP_KERNEL);
if (!addr) {
len = -ENOMEM;
goto st_sensors_get_buffer_element_error;
}
for (i = 0; i < num_data_channels; i++) {
if (test_bit(i, indio_dev->active_scan_mask)) {
addr[n] = indio_dev->channels[i].address;
n++;
......@@ -37,52 +46,58 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
switch (n) {
case 1:
len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
addr[0], ST_SENSORS_BYTE_FOR_CHANNEL, buf,
sdata->multiread_bit);
addr[0], byte_for_channel, buf, sdata->multiread_bit);
break;
case 2:
if ((addr[1] - addr[0]) == ST_SENSORS_BYTE_FOR_CHANNEL) {
if ((addr[1] - addr[0]) == byte_for_channel) {
len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, addr[0],
ST_SENSORS_BYTE_FOR_CHANNEL*n,
buf, sdata->multiread_bit);
sdata->dev, addr[0], byte_for_channel * n,
buf, sdata->multiread_bit);
} else {
u8 rx_array[ST_SENSORS_BYTE_FOR_CHANNEL*
ST_SENSORS_NUMBER_DATA_CHANNELS];
u8 *rx_array;
rx_array = kmalloc(byte_for_channel * num_data_channels,
GFP_KERNEL);
if (!rx_array) {
len = -ENOMEM;
goto st_sensors_free_memory;
}
len = sdata->tf->read_multiple_byte(&sdata->tb,
sdata->dev, addr[0],
ST_SENSORS_BYTE_FOR_CHANNEL*
ST_SENSORS_NUMBER_DATA_CHANNELS,
byte_for_channel * num_data_channels,
rx_array, sdata->multiread_bit);
if (len < 0)
goto read_data_channels_error;
if (len < 0) {
kfree(rx_array);
goto st_sensors_free_memory;
}
for (i = 0; i < n * ST_SENSORS_NUMBER_DATA_CHANNELS;
i++) {
for (i = 0; i < n * num_data_channels; i++) {
if (i < n)
buf[i] = rx_array[i];
else
buf[i] = rx_array[n + i];
}
len = ST_SENSORS_BYTE_FOR_CHANNEL*n;
kfree(rx_array);
len = byte_for_channel * n;
}
break;
case 3:
len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
addr[0], ST_SENSORS_BYTE_FOR_CHANNEL*
ST_SENSORS_NUMBER_DATA_CHANNELS,
addr[0], byte_for_channel * num_data_channels,
buf, sdata->multiread_bit);
break;
default:
len = -EINVAL;
goto read_data_channels_error;
goto st_sensors_free_memory;
}
if (len != ST_SENSORS_BYTE_FOR_CHANNEL*n) {
if (len != byte_for_channel * n) {
len = -EIO;
goto read_data_channels_error;
goto st_sensors_free_memory;
}
read_data_channels_error:
st_sensors_free_memory:
kfree(addr);
st_sensors_get_buffer_element_error:
return len;
}
EXPORT_SYMBOL(st_sensors_get_buffer_element);
......
......@@ -20,6 +20,11 @@
#define ST_SENSORS_WAI_ADDRESS 0x0f
static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
{
return ((s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8);
}
static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
u8 reg_addr, u8 mask, u8 data)
{
......@@ -112,7 +117,8 @@ static int st_sensors_match_fs(struct st_sensors *sensor,
return ret;
}
static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
static int st_sensors_set_fullscale(struct iio_dev *indio_dev,
unsigned int fs)
{
int err, i = 0;
struct st_sensor_data *sdata = iio_priv(indio_dev);
......@@ -273,21 +279,33 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
u8 ch_addr, int *data)
struct iio_chan_spec const *ch, int *data)
{
int err;
u8 outdata[ST_SENSORS_BYTE_FOR_CHANNEL];
u8 *outdata;
struct st_sensor_data *sdata = iio_priv(indio_dev);
unsigned int byte_for_channel = ch->scan_type.storagebits >> 3;
outdata = kmalloc(byte_for_channel, GFP_KERNEL);
if (!outdata) {
err = -EINVAL;
goto st_sensors_read_axis_data_error;
}
err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
ch_addr, ST_SENSORS_BYTE_FOR_CHANNEL,
ch->address, byte_for_channel,
outdata, sdata->multiread_bit);
if (err < 0)
goto read_error;
goto st_sensors_free_memory;
*data = (s16)get_unaligned_le16(outdata);
if (byte_for_channel == 2)
*data = (s16)get_unaligned_le16(outdata);
else if (byte_for_channel == 3)
*data = (s32)st_sensors_get_unaligned_le24(outdata);
read_error:
st_sensors_free_memory:
kfree(outdata);
st_sensors_read_axis_data_error:
return err;
}
......@@ -307,7 +325,7 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
goto read_error;
msleep((sdata->sensor->bootime * 1000) / sdata->odr);
err = st_sensors_read_axis_data(indio_dev, ch->address, val);
err = st_sensors_read_axis_data(indio_dev, ch, val);
if (err < 0)
goto read_error;
......
......@@ -130,6 +130,16 @@ config AD5686
To compile this driver as a module, choose M here: the
module will be called ad5686.
config AD7303
tristate "Analog Devices Analog Devices AD7303 DAC driver"
depends on SPI
help
Say yes here to build support for Analog Devices AD7303 Digital to Analog
Converters (DAC).
To compile this driver as module choose M here: the module will be called
ad7303.
config MAX517
tristate "Maxim MAX517/518/519 DAC driver"
depends on I2C
......
......@@ -14,5 +14,6 @@ obj-$(CONFIG_AD5755) += ad5755.o
obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MCP4725) += mcp4725.o
/*
* AD7303 Digital to analog converters driver
*
* Copyright 2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/platform_data/ad7303.h>
#define AD7303_CFG_EXTERNAL_VREF BIT(15)
#define AD7303_CFG_POWER_DOWN(ch) BIT(11 + (ch))
#define AD7303_CFG_ADDR_OFFSET 10
#define AD7303_CMD_UPDATE_DAC (0x3 << 8)
/**
* struct ad7303_state - driver instance specific data
* @spi: the device for this driver instance
* @config: cached config register value
* @dac_cache: current DAC raw value (chip does not support readback)
* @data: spi transfer buffer
*/
struct ad7303_state {
struct spi_device *spi;
uint16_t config;
uint8_t dac_cache[2];
struct regulator *vdd_reg;
struct regulator *vref_reg;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
*/
__be16 data ____cacheline_aligned;
};
static int ad7303_write(struct ad7303_state *st, unsigned int chan,
uint8_t val)
{
st->data = cpu_to_be16(AD7303_CMD_UPDATE_DAC |
(chan << AD7303_CFG_ADDR_OFFSET) |
st->config | val);
return spi_write(st->spi, &st->data, sizeof(st->data));
}
static ssize_t ad7303_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
struct ad7303_state *st = iio_priv(indio_dev);
return sprintf(buf, "%d\n", (bool)(st->config &
AD7303_CFG_POWER_DOWN(chan->channel)));
}
static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
size_t len)
{
struct ad7303_state *st = iio_priv(indio_dev);
bool pwr_down;
int ret;
ret = strtobool(buf, &pwr_down);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
if (pwr_down)
st->config |= AD7303_CFG_POWER_DOWN(chan->channel);
else
st->config &= ~AD7303_CFG_POWER_DOWN(chan->channel);
/* There is no noop cmd which allows us to only update the powerdown
* mode, so just write one of the DAC channels again */
ad7303_write(st, chan->channel, st->dac_cache[chan->channel]);
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
static int ad7303_get_vref(struct ad7303_state *st,
struct iio_chan_spec const *chan)
{
int ret;
if (st->config & AD7303_CFG_EXTERNAL_VREF)
return regulator_get_voltage(st->vref_reg);
ret = regulator_get_voltage(st->vdd_reg);
if (ret < 0)
return ret;
return ret / 2;
}
static int ad7303_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct ad7303_state *st = iio_priv(indio_dev);
int vref_uv;
switch (info) {
case IIO_CHAN_INFO_RAW:
*val = st->dac_cache[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
vref_uv = ad7303_get_vref(st, chan);
if (vref_uv < 0)
return vref_uv;
*val = 2 * vref_uv / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
return -EINVAL;
}
static int ad7303_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
struct ad7303_state *st = iio_priv(indio_dev);
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
ret = ad7303_write(st, chan->address, val);
if (ret == 0)
st->dac_cache[chan->channel] = val;
mutex_unlock(&indio_dev->mlock);
break;
default:
ret = -EINVAL;
}
return ret;
}
static const struct iio_info ad7303_info = {
.read_raw = ad7303_read_raw,
.write_raw = ad7303_write_raw,
.driver_module = THIS_MODULE,
};
static const struct iio_chan_spec_ext_info ad7303_ext_info[] = {
{
.name = "powerdown",
.read = ad7303_read_dac_powerdown,
.write = ad7303_write_dac_powerdown,
},
{ },
};
#define AD7303_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.address = (chan), \
.scan_type = { \
.sign = 'u', \
.realbits = '8', \
.storagebits = '8', \
.shift = '0', \
}, \
.ext_info = ad7303_ext_info, \
}
static const struct iio_chan_spec ad7303_channels[] = {
AD7303_CHANNEL(0),
AD7303_CHANNEL(1),
};
static int ad7303_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev;
struct ad7303_state *st;
bool ext_ref;
int ret;
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->vdd_reg = regulator_get(&spi->dev, "Vdd");
if (IS_ERR(st->vdd_reg)) {
ret = PTR_ERR(st->vdd_reg);
goto err_free;
}
ret = regulator_enable(st->vdd_reg);
if (ret)
goto err_put_vdd_reg;
if (spi->dev.of_node) {
ext_ref = of_property_read_bool(spi->dev.of_node,
"REF-supply");
} else {
struct ad7303_platform_data *pdata = spi->dev.platform_data;
if (pdata && pdata->use_external_ref)
ext_ref = true;
else
ext_ref = false;
}
if (ext_ref) {
st->vref_reg = regulator_get(&spi->dev, "REF");
if (IS_ERR(st->vref_reg))
goto err_disable_vdd_reg;
ret = regulator_enable(st->vref_reg);
if (ret)
goto err_put_vref_reg;
st->config |= AD7303_CFG_EXTERNAL_VREF;
}
indio_dev->dev.parent = &spi->dev;
indio_dev->name = id->name;
indio_dev->info = &ad7303_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = ad7303_channels;
indio_dev->num_channels = ARRAY_SIZE(ad7303_channels);
ret = iio_device_register(indio_dev);
if (ret)
goto err_disable_vref_reg;
return 0;
err_disable_vref_reg:
if (st->vref_reg)
regulator_disable(st->vref_reg);
err_put_vref_reg:
if (st->vref_reg)
regulator_put(st->vref_reg);
err_disable_vdd_reg:
regulator_disable(st->vdd_reg);
err_put_vdd_reg:
regulator_put(st->vdd_reg);
err_free:
iio_device_free(indio_dev);
return ret;
}
static int ad7303_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ad7303_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (st->vref_reg) {
regulator_disable(st->vref_reg);
regulator_put(st->vref_reg);
}
regulator_disable(st->vdd_reg);
regulator_put(st->vdd_reg);
iio_device_free(indio_dev);
return 0;
}
static const struct spi_device_id ad7303_spi_ids[] = {
{ "ad7303", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, ad7303_spi_ids);
static struct spi_driver ad7303_driver = {
.driver = {
.name = "ad7303",
.owner = THIS_MODULE,
},
.probe = ad7303_probe,
.remove = ad7303_remove,
.id_table = ad7303_spi_ids,
};
module_spi_driver(ad7303_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices AD7303 DAC driver");
MODULE_LICENSE("GPL v2");
/*
* ADF4350/ADF4351 SPI Wideband Synthesizer driver
*
* Copyright 2012 Analog Devices Inc.
* Copyright 2012-2013 Analog Devices Inc.
*
* Licensed under the GPL-2.
*/
......@@ -17,6 +17,9 @@
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <asm/div64.h>
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -33,6 +36,7 @@ struct adf4350_state {
struct spi_device *spi;
struct regulator *reg;
struct adf4350_platform_data *pdata;
struct clk *clk;
unsigned long clkin;
unsigned long chspc; /* Channel Spacing */
unsigned long fpfd; /* Phase Frequency Detector */
......@@ -43,7 +47,7 @@ struct adf4350_state {
unsigned r4_rf_div_sel;
unsigned long regs[6];
unsigned long regs_hw[6];
unsigned long long freq_req;
/*
* DMA (thus cache coherency maintenance) requires the
* transfer buffers to live in their own cache lines.
......@@ -52,7 +56,6 @@ struct adf4350_state {
};
static struct adf4350_platform_data default_pdata = {
.clkin = 122880000,
.channel_spacing = 10000,
.r2_user_settings = ADF4350_REG2_PD_POLARITY_POS |
ADF4350_REG2_CHARGE_PUMP_CURR_uA(2500),
......@@ -235,6 +238,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)
ADF4350_REG4_MUTE_TILL_LOCK_EN));
st->regs[ADF4350_REG5] = ADF4350_REG5_LD_PIN_MODE_DIGITAL;
st->freq_req = freq;
return adf4350_sync_config(st);
}
......@@ -246,6 +250,7 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev,
{
struct adf4350_state *st = iio_priv(indio_dev);
unsigned long long readin;
unsigned long tmp;
int ret;
ret = kstrtoull(buf, 10, &readin);
......@@ -258,10 +263,23 @@ static ssize_t adf4350_write(struct iio_dev *indio_dev,
ret = adf4350_set_freq(st, readin);
break;
case ADF4350_FREQ_REFIN:
if (readin > ADF4350_MAX_FREQ_REFIN)
if (readin > ADF4350_MAX_FREQ_REFIN) {
ret = -EINVAL;
else
st->clkin = readin;
break;
}
if (st->clk) {
tmp = clk_round_rate(st->clk, readin);
if (tmp != readin) {
ret = -EINVAL;
break;
}
ret = clk_set_rate(st->clk, tmp);
if (ret < 0)
break;
}
st->clkin = readin;
ret = adf4350_set_freq(st, st->freq_req);
break;
case ADF4350_FREQ_RESOLUTION:
if (readin == 0)
......@@ -308,6 +326,9 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
}
break;
case ADF4350_FREQ_REFIN:
if (st->clk)
st->clkin = clk_get_rate(st->clk);
val = st->clkin;
break;
case ADF4350_FREQ_RESOLUTION:
......@@ -318,6 +339,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
break;
default:
ret = -EINVAL;
val = 0;
}
mutex_unlock(&indio_dev->mlock);
......@@ -355,19 +377,153 @@ static const struct iio_info adf4350_info = {
.driver_module = THIS_MODULE,
};
#ifdef CONFIG_OF
static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct adf4350_platform_data *pdata;
unsigned int tmp;
int ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "could not allocate memory for platform data\n");
return NULL;
}
strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1);
tmp = 10000;
of_property_read_u32(np, "adi,channel-spacing", &tmp);
pdata->channel_spacing = tmp;
tmp = 0;
of_property_read_u32(np, "adi,power-up-frequency", &tmp);
pdata->power_up_frequency = tmp;
tmp = 0;
of_property_read_u32(np, "adi,reference-div-factor", &tmp);
pdata->ref_div_factor = tmp;
ret = of_get_gpio(np, 0);
if (ret < 0)
pdata->gpio_lock_detect = -1;
else
pdata->gpio_lock_detect = ret;
pdata->ref_doubler_en = of_property_read_bool(np,
"adi,reference-doubler-enable");
pdata->ref_div2_en = of_property_read_bool(np,
"adi,reference-div2-enable");
/* r2_user_settings */
pdata->r2_user_settings = of_property_read_bool(np,
"adi,phase-detector-polarity-positive-enable") ?
ADF4350_REG2_PD_POLARITY_POS : 0;
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,lock-detect-precision-6ns-enable") ?
ADF4350_REG2_LDP_6ns : 0;
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,lock-detect-function-integer-n-enable") ?
ADF4350_REG2_LDF_INT_N : 0;
tmp = 2500;
of_property_read_u32(np, "adi,charge-pump-current", &tmp);
pdata->r2_user_settings |= ADF4350_REG2_CHARGE_PUMP_CURR_uA(tmp);
tmp = 0;
of_property_read_u32(np, "adi,muxout-select", &tmp);
pdata->r2_user_settings |= ADF4350_REG2_MUXOUT(tmp);
pdata->r2_user_settings |= of_property_read_bool(np,
"adi,low-spur-mode-enable") ?
ADF4350_REG2_NOISE_MODE(0x3) : 0;
/* r3_user_settings */
pdata->r3_user_settings = of_property_read_bool(np,
"adi,cycle-slip-reduction-enable") ?
ADF4350_REG3_12BIT_CSR_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,charge-cancellation-enable") ?
ADF4351_REG3_CHARGE_CANCELLATION_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,anti-backlash-3ns-enable") ?
ADF4351_REG3_ANTI_BACKLASH_3ns_EN : 0;
pdata->r3_user_settings |= of_property_read_bool(np,
"adi,band-select-clock-mode-high-enable") ?
ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH : 0;
tmp = 0;
of_property_read_u32(np, "adi,12bit-clk-divider", &tmp);
pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV(tmp);
tmp = 0;
of_property_read_u32(np, "adi,clk-divider-mode", &tmp);
pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV_MODE(tmp);
/* r4_user_settings */
pdata->r4_user_settings = of_property_read_bool(np,
"adi,aux-output-enable") ?
ADF4350_REG4_AUX_OUTPUT_EN : 0;
pdata->r4_user_settings |= of_property_read_bool(np,
"adi,aux-output-fundamental-enable") ?
ADF4350_REG4_AUX_OUTPUT_FUND : 0;
pdata->r4_user_settings |= of_property_read_bool(np,
"adi,mute-till-lock-enable") ?
ADF4350_REG4_MUTE_TILL_LOCK_EN : 0;
tmp = 0;
of_property_read_u32(np, "adi,output-power", &tmp);
pdata->r4_user_settings |= ADF4350_REG4_OUTPUT_PWR(tmp);
tmp = 0;
of_property_read_u32(np, "adi,aux-output-power", &tmp);
pdata->r4_user_settings |= ADF4350_REG4_AUX_OUTPUT_PWR(tmp);
return pdata;
}
#else
static
struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
{
return NULL;
}
#endif
static int adf4350_probe(struct spi_device *spi)
{
struct adf4350_platform_data *pdata = spi->dev.platform_data;
struct adf4350_platform_data *pdata;
struct iio_dev *indio_dev;
struct adf4350_state *st;
struct clk *clk = NULL;
int ret;
if (spi->dev.of_node) {
pdata = adf4350_parse_dt(&spi->dev);
if (pdata == NULL)
return -EINVAL;
} else {
pdata = spi->dev.platform_data;
}
if (!pdata) {
dev_warn(&spi->dev, "no platform data? using default\n");
pdata = &default_pdata;
}
if (!pdata->clkin) {
clk = clk_get(&spi->dev, "clkin");
if (IS_ERR(clk))
return -EPROBE_DEFER;
ret = clk_prepare_enable(clk);
if (ret < 0)
return ret;
}
indio_dev = iio_device_alloc(sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
......@@ -395,7 +551,12 @@ static int adf4350_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
st->chspc = pdata->channel_spacing;
st->clkin = pdata->clkin;
if (clk) {
st->clk = clk;
st->clkin = clk_get_rate(clk);
} else {
st->clkin = pdata->clkin;
}
st->min_out_freq = spi_get_device_id(spi)->driver_data == 4351 ?
ADF4351_MIN_OUT_FREQ : ADF4350_MIN_OUT_FREQ;
......@@ -435,6 +596,8 @@ static int adf4350_probe(struct spi_device *spi)
if (!IS_ERR(st->reg))
regulator_put(st->reg);
if (clk)
clk_disable_unprepare(clk);
iio_device_free(indio_dev);
return ret;
......@@ -451,6 +614,9 @@ static int adf4350_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
if (st->clk)
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg)) {
regulator_disable(reg);
regulator_put(reg);
......@@ -481,6 +647,6 @@ static struct spi_driver adf4350_driver = {
};
module_spi_driver(adf4350_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADF4350/ADF4351 PLL");
MODULE_LICENSE("GPL v2");
......@@ -10,6 +10,13 @@ config ADIS16080
Say yes here to build support for Analog Devices ADIS16080, ADIS16100 Yaw
Rate Gyroscope with SPI.
config ADIS16130
tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver"
depends on SPI
help
Say yes here to build support for Analog Devices ADIS16130 High Precision
Angular Rate Sensor driver.
config ADIS16136
tristate "Analog devices ADIS16136 and similar gyroscopes driver"
depends on SPI_MASTER
......@@ -47,7 +54,6 @@ config IIO_ST_GYRO_3AXIS
select IIO_ST_GYRO_I2C_3AXIS if (I2C)
select IIO_ST_GYRO_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_GYRO_BUFFER if (IIO_TRIGGERED_BUFFER)
help
Say yes here to build support for STMicroelectronics gyroscopes:
L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
......
......@@ -3,6 +3,7 @@
#
obj-$(CONFIG_ADIS16080) += adis16080.o
obj-$(CONFIG_ADIS16130) += adis16130.o
obj-$(CONFIG_ADIS16136) += adis16136.o
obj-$(CONFIG_ADXRS450) += adxrs450.o
......
......@@ -6,18 +6,12 @@
* Licensed under the GPL-2 or later.
*/
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define ADIS16130_CON 0x0
#define ADIS16130_CON_RD (1 << 6)
......@@ -68,7 +62,6 @@ static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(st->us, &msg);
ret = spi_read(st->us, st->buf, 4);
if (ret == 0)
*val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
......@@ -85,14 +78,47 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
int ret;
u32 temp;
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis16130_spi_read(indio_dev, chan->address, &temp);
mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
*val = temp;
return IIO_VAL_INT;
switch (mask) {
case IIO_CHAN_INFO_RAW:
/* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock);
ret = adis16130_spi_read(indio_dev, chan->address, &temp);
mutex_unlock(&indio_dev->mlock);
if (ret)
return ret;
*val = temp;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
/* 0 degree = 838860, 250 degree = 14260608 */
*val = 250;
*val2 = 336440817; /* RAD_TO_DEGREE(14260608 - 8388608) */
return IIO_VAL_FRACTIONAL;
case IIO_TEMP:
/* 0C = 8036283, 105C = 9516048 */
*val = 105000;
*val2 = 9516048 - 8036283;
return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
break;
case IIO_CHAN_INFO_OFFSET:
switch (chan->type) {
case IIO_ANGL_VEL:
*val = -8388608;
return IIO_VAL_INT;
case IIO_TEMP:
*val = -8036283;
return IIO_VAL_INT;
default:
return -EINVAL;
}
break;
}
return -EINVAL;
}
static const struct iio_chan_spec adis16130_channels[] = {
......@@ -100,13 +126,17 @@ static const struct iio_chan_spec adis16130_channels[] = {
.type = IIO_ANGL_VEL,
.modified = 1,
.channel2 = IIO_MOD_Z,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16130_RATEDATA,
}, {
.type = IIO_TEMP,
.indexed = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.address = ADIS16130_TEMPDATA,
}
};
......@@ -153,7 +183,6 @@ static int adis16130_probe(struct spi_device *spi)
return ret;
}
/* fixme, confirm ordering in this function */
static int adis16130_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
......
......@@ -27,6 +27,8 @@
#include <linux/iio/common/st_sensors.h>
#include "st_gyro.h"
#define ST_GYRO_NUMBER_DATA_CHANNELS 3
/* DEFAULT VALUE FOR SENSORS */
#define ST_GYRO_DEFAULT_OUT_X_L_ADDR 0x28
#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR 0x2a
......@@ -86,15 +88,18 @@
#define ST_GYRO_2_MULTIREAD_BIT true
static const struct iio_chan_spec st_gyro_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_X,
IIO_MOD_X, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
ST_GYRO_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Y,
IIO_MOD_Y, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
ST_GYRO_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Z,
IIO_MOD_Z, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
ST_GYRO_DEFAULT_OUT_Z_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
ST_GYRO_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
ST_GYRO_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
ST_GYRO_DEFAULT_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
......@@ -310,6 +315,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
if (err < 0)
goto st_gyro_common_probe_error;
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
gdata->multiread_bit = gdata->sensor->multi_read_bit;
indio_dev->channels = gdata->sensor->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
......
......@@ -542,8 +542,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) {
printk(KERN_ERR
"Buffer not started:"
"buffer preenable failed\n");
"Buffer not started: buffer preenable failed (%d)\n", ret);
goto error_remove_inserted;
}
}
......@@ -556,8 +555,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = buffer->access->request_update(buffer);
if (ret) {
printk(KERN_INFO
"Buffer not started:"
"buffer parameter update failed\n");
"Buffer not started: buffer parameter update failed (%d)\n", ret);
goto error_run_postdisable;
}
}
......@@ -566,7 +564,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
->update_scan_mode(indio_dev,
indio_dev->active_scan_mask);
if (ret < 0) {
printk(KERN_INFO "update scan mode failed\n");
printk(KERN_INFO "Buffer not started: update scan mode failed (%d)\n", ret);
goto error_run_postdisable;
}
}
......@@ -590,7 +588,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) {
printk(KERN_INFO
"Buffer not started: postenable failed\n");
"Buffer not started: postenable failed (%d)\n", ret);
indio_dev->currentmode = INDIO_DIRECT_MODE;
if (indio_dev->setup_ops->postdisable)
indio_dev->setup_ops->postdisable(indio_dev);
......
......@@ -31,7 +31,7 @@
#include "../common/hid-sensors/hid-sensor-trigger.h"
/*Format: HID-SENSOR-usage_id_in_hex*/
/*Usage ID from spec for Accelerometer-3D: 0x200041*/
/*Usage ID from spec for Ambiant-Light: 0x200041*/
#define DRIVER_NAME "HID-SENSOR-200041"
#define CHANNEL_SCAN_INDEX_ILLUM 0
......
......@@ -32,7 +32,6 @@ config IIO_ST_MAGN_3AXIS
select IIO_ST_MAGN_I2C_3AXIS if (I2C)
select IIO_ST_MAGN_SPI_3AXIS if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
select IIO_ST_MAGN_BUFFER if (IIO_TRIGGERED_BUFFER)
help
Say yes here to build support for STMicroelectronics magnetometers:
LSM303DLHC, LSM303DLM, LIS3MDL.
......
......@@ -24,11 +24,13 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
......@@ -82,6 +84,7 @@
*/
#define AK8975_MAX_CONVERSION_TIMEOUT 500
#define AK8975_CONVERSION_DONE_POLL_TIME 10
#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
/*
* Per-instance context data for the device.
......@@ -94,6 +97,9 @@ struct ak8975_data {
long raw_to_gauss[3];
u8 reg_cache[AK8975_MAX_REGS];
int eoc_gpio;
int eoc_irq;
wait_queue_head_t data_ready_queue;
unsigned long flags;
};
static const int ak8975_index_to_reg[] = {
......@@ -122,6 +128,51 @@ static int ak8975_write_data(struct i2c_client *client,
return 0;
}
/*
* Handle data ready irq
*/
static irqreturn_t ak8975_irq_handler(int irq, void *data)
{
struct ak8975_data *ak8975 = data;
set_bit(0, &ak8975->flags);
wake_up(&ak8975->data_ready_queue);
return IRQ_HANDLED;
}
/*
* Install data ready interrupt handler
*/
static int ak8975_setup_irq(struct ak8975_data *data)
{
struct i2c_client *client = data->client;
int rc;
int irq;
if (client->irq)
irq = client->irq;
else
irq = gpio_to_irq(data->eoc_gpio);
rc = request_irq(irq, ak8975_irq_handler,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
dev_name(&client->dev), data);
if (rc < 0) {
dev_err(&client->dev,
"irq %d request failed, (gpio %d): %d\n",
irq, data->eoc_gpio, rc);
return rc;
}
init_waitqueue_head(&data->data_ready_queue);
clear_bit(0, &data->flags);
data->eoc_irq = irq;
return rc;
}
/*
* Perform some start-of-day setup, including reading the asa calibration
* values and caching them.
......@@ -170,6 +221,16 @@ static int ak8975_setup(struct i2c_client *client)
AK8975_REG_CNTL_MODE_POWER_DOWN,
AK8975_REG_CNTL_MODE_MASK,
AK8975_REG_CNTL_MODE_SHIFT);
if (data->eoc_gpio > 0 || client->irq) {
ret = ak8975_setup_irq(data);
if (ret < 0) {
dev_err(&client->dev,
"Error setting data ready interrupt\n");
return ret;
}
}
if (ret < 0) {
dev_err(&client->dev, "Error in setting power-down mode\n");
return ret;
......@@ -266,9 +327,23 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
dev_err(&client->dev, "Conversion timeout happened\n");
return -EINVAL;
}
return read_status;
}
/* Returns 0 if the end of conversion interrupt occured or -ETIME otherwise */
static int wait_conversion_complete_interrupt(struct ak8975_data *data)
{
int ret;
ret = wait_event_timeout(data->data_ready_queue,
test_bit(0, &data->flags),
AK8975_DATA_READY_TIMEOUT);
clear_bit(0, &data->flags);
return ret > 0 ? 0 : -ETIME;
}
/*
* Emits the raw flux value for the x, y, or z axis.
*/
......@@ -294,13 +369,16 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
}
/* Wait for the conversion to complete. */
if (gpio_is_valid(data->eoc_gpio))
if (data->eoc_irq)
ret = wait_conversion_complete_interrupt(data);
else if (gpio_is_valid(data->eoc_gpio))
ret = wait_conversion_complete_gpio(data);
else
ret = wait_conversion_complete_polled(data);
if (ret < 0)
goto exit;
/* This will be executed only for non-interrupt based waiting case */
if (ret & AK8975_REG_ST1_DRDY_MASK) {
ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2);
if (ret < 0) {
......@@ -384,10 +462,15 @@ static int ak8975_probe(struct i2c_client *client,
int err;
/* Grab and set up the supplied GPIO. */
if (client->dev.platform_data == NULL)
eoc_gpio = -1;
else
if (client->dev.platform_data)
eoc_gpio = *(int *)(client->dev.platform_data);
else if (client->dev.of_node)
eoc_gpio = of_get_gpio(client->dev.of_node, 0);
else
eoc_gpio = -1;
if (eoc_gpio == -EPROBE_DEFER)
return -EPROBE_DEFER;
/* We may not have a GPIO based IRQ to scan, that is fine, we will
poll if so */
......@@ -409,6 +492,11 @@ static int ak8975_probe(struct i2c_client *client,
}
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->eoc_gpio = eoc_gpio;
data->eoc_irq = 0;
/* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client);
if (err < 0) {
......@@ -433,6 +521,8 @@ static int ak8975_probe(struct i2c_client *client,
exit_free_iio:
iio_device_free(indio_dev);
if (data->eoc_irq)
free_irq(data->eoc_irq, data);
exit_gpio:
if (gpio_is_valid(eoc_gpio))
gpio_free(eoc_gpio);
......@@ -447,6 +537,9 @@ static int ak8975_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
if (data->eoc_irq)
free_irq(data->eoc_irq, data);
if (gpio_is_valid(data->eoc_gpio))
gpio_free(data->eoc_gpio);
......
......@@ -26,6 +26,8 @@
#include <linux/iio/common/st_sensors.h>
#include "st_magn.h"
#define ST_MAGN_NUMBER_DATA_CHANNELS 3
/* DEFAULT VALUE FOR SENSORS */
#define ST_MAGN_DEFAULT_OUT_X_L_ADDR 0X04
#define ST_MAGN_DEFAULT_OUT_Y_L_ADDR 0X08
......@@ -113,22 +115,34 @@
#define ST_MAGN_2_OUT_Z_L_ADDR 0x2c
static const struct iio_chan_spec st_magn_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Z_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
ST_MAGN_DEFAULT_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
ST_MAGN_DEFAULT_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
ST_MAGN_DEFAULT_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Z_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
ST_MAGN_2_OUT_X_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
ST_MAGN_2_OUT_Y_L_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
ST_MAGN_2_OUT_Z_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(3)
};
......@@ -344,6 +358,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
if (err < 0)
goto st_magn_common_probe_error;
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
mdata->multiread_bit = mdata->sensor->multi_read_bit;
indio_dev->channels = mdata->sensor->ch;
indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
......
#
# Pressure drivers
#
menu "Pressure Sensors"
config IIO_ST_PRESS
tristate "STMicroelectronics pressures Driver"
depends on (I2C || SPI_MASTER) && SYSFS
select IIO_ST_SENSORS_CORE
select IIO_ST_PRESS_I2C if (I2C)
select IIO_ST_PRESS_SPI if (SPI_MASTER)
select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
help
Say yes here to build support for STMicroelectronics pressures:
LPS331AP.
This driver can also be built as a module. If so, will be created
these modules:
- st_pressure (core functions for the driver [it is mandatory]);
- st_pressure_i2c (necessary for the I2C devices [optional*]);
- st_pressure_spi (necessary for the SPI devices [optional*]);
(*) one of these is necessary to do something.
config IIO_ST_PRESS_I2C
tristate
depends on IIO_ST_PRESS
depends on IIO_ST_SENSORS_I2C
config IIO_ST_PRESS_SPI
tristate
depends on IIO_ST_PRESS
depends on IIO_ST_SENSORS_SPI
endmenu
#
# Makefile for industrial I/O pressure drivers
#
obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
st_pressure-y := st_pressure_core.o
st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
/*
* STMicroelectronics pressures driver
*
* Copyright 2013 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
* v. 1.0.0
* Licensed under the GPL-2.
*/
#ifndef ST_PRESS_H
#define ST_PRESS_H
#include <linux/types.h>
#include <linux/iio/common/st_sensors.h>
#define LPS331AP_PRESS_DEV_NAME "lps331ap"
int st_press_common_probe(struct iio_dev *indio_dev);
void st_press_common_remove(struct iio_dev *indio_dev);
#ifdef CONFIG_IIO_BUFFER
int st_press_allocate_ring(struct iio_dev *indio_dev);
void st_press_deallocate_ring(struct iio_dev *indio_dev);
int st_press_trig_set_state(struct iio_trigger *trig, bool state);
#define ST_PRESS_TRIGGER_SET_STATE (&st_press_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
static inline int st_press_allocate_ring(struct iio_dev *indio_dev)
{
return 0;
}
static inline void st_press_deallocate_ring(struct iio_dev *indio_dev)
{
}
#define ST_PRESS_TRIGGER_SET_STATE NULL
#endif /* CONFIG_IIO_BUFFER */
#endif /* ST_PRESS_H */
/*
* STMicroelectronics pressures driver
*
* Copyright 2013 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
*
* Licensed under the GPL-2.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/common/st_sensors.h>
#include "st_pressure.h"
int st_press_trig_set_state(struct iio_trigger *trig, bool state)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
return st_sensors_set_dataready_irq(indio_dev, state);
}
static int st_press_buffer_preenable(struct iio_dev *indio_dev)
{
int err;
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
goto st_press_set_enable_error;
err = iio_sw_buffer_preenable(indio_dev);
st_press_set_enable_error:
return err;
}
static int st_press_buffer_postenable(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *pdata = iio_priv(indio_dev);
pdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (pdata->buffer_data == NULL) {
err = -ENOMEM;
goto allocate_memory_error;
}
err = iio_triggered_buffer_postenable(indio_dev);
if (err < 0)
goto st_press_buffer_postenable_error;
return err;
st_press_buffer_postenable_error:
kfree(pdata->buffer_data);
allocate_memory_error:
return err;
}
static int st_press_buffer_predisable(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *pdata = iio_priv(indio_dev);
err = iio_triggered_buffer_predisable(indio_dev);
if (err < 0)
goto st_press_buffer_predisable_error;
err = st_sensors_set_enable(indio_dev, false);
st_press_buffer_predisable_error:
kfree(pdata->buffer_data);
return err;
}
static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = {
.preenable = &st_press_buffer_preenable,
.postenable = &st_press_buffer_postenable,
.predisable = &st_press_buffer_predisable,
};
int st_press_allocate_ring(struct iio_dev *indio_dev)
{
return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
&st_sensors_trigger_handler, &st_press_buffer_setup_ops);
}
void st_press_deallocate_ring(struct iio_dev *indio_dev)
{
iio_triggered_buffer_cleanup(indio_dev);
}
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures buffer");
MODULE_LICENSE("GPL v2");
/*
* STMicroelectronics pressures driver
*
* Copyright 2013 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
*
* Licensed under the GPL-2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
#include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h>
#include "st_pressure.h"
#define ST_PRESS_MBAR_TO_KPASCAL(x) (x * 10)
#define ST_PRESS_NUMBER_DATA_CHANNELS 1
/* DEFAULT VALUE FOR SENSORS */
#define ST_PRESS_DEFAULT_OUT_XL_ADDR 0x28
#define ST_TEMP_DEFAULT_OUT_L_ADDR 0x2b
/* FULLSCALE */
#define ST_PRESS_FS_AVL_1260MB 1260
/* CUSTOM VALUES FOR SENSOR 1 */
#define ST_PRESS_1_WAI_EXP 0xbb
#define ST_PRESS_1_ODR_ADDR 0x20
#define ST_PRESS_1_ODR_MASK 0x70
#define ST_PRESS_1_ODR_AVL_1HZ_VAL 0x01
#define ST_PRESS_1_ODR_AVL_7HZ_VAL 0x05
#define ST_PRESS_1_ODR_AVL_13HZ_VAL 0x06
#define ST_PRESS_1_ODR_AVL_25HZ_VAL 0x07
#define ST_PRESS_1_PW_ADDR 0x20
#define ST_PRESS_1_PW_MASK 0x80
#define ST_PRESS_1_FS_ADDR 0x23
#define ST_PRESS_1_FS_MASK 0x30
#define ST_PRESS_1_FS_AVL_1260_VAL 0x00
#define ST_PRESS_1_FS_AVL_1260_GAIN ST_PRESS_MBAR_TO_KPASCAL(244141)
#define ST_PRESS_1_FS_AVL_TEMP_GAIN 2083000
#define ST_PRESS_1_BDU_ADDR 0x20
#define ST_PRESS_1_BDU_MASK 0x04
#define ST_PRESS_1_DRDY_IRQ_ADDR 0x22
#define ST_PRESS_1_DRDY_IRQ_MASK 0x04
#define ST_PRESS_1_MULTIREAD_BIT true
#define ST_PRESS_1_TEMP_OFFSET 42500
static const struct iio_chan_spec st_press_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_PRESSURE,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
ST_SENSORS_SCAN_X, 0, IIO_NO_MOD, 'u', IIO_LE, 24, 24,
ST_PRESS_DEFAULT_OUT_XL_ADDR),
ST_SENSORS_LSM_CHANNELS(IIO_TEMP,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
-1, 0, IIO_NO_MOD, 's', IIO_LE, 16, 16,
ST_TEMP_DEFAULT_OUT_L_ADDR),
IIO_CHAN_SOFT_TIMESTAMP(1)
};
static const struct st_sensors st_press_sensors[] = {
{
.wai = ST_PRESS_1_WAI_EXP,
.sensors_supported = {
[0] = LPS331AP_PRESS_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_press_channels,
.odr = {
.addr = ST_PRESS_1_ODR_ADDR,
.mask = ST_PRESS_1_ODR_MASK,
.odr_avl = {
{ 1, ST_PRESS_1_ODR_AVL_1HZ_VAL, },
{ 7, ST_PRESS_1_ODR_AVL_7HZ_VAL, },
{ 13, ST_PRESS_1_ODR_AVL_13HZ_VAL, },
{ 25, ST_PRESS_1_ODR_AVL_25HZ_VAL, },
},
},
.pw = {
.addr = ST_PRESS_1_PW_ADDR,
.mask = ST_PRESS_1_PW_MASK,
.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
.addr = ST_PRESS_1_FS_ADDR,
.mask = ST_PRESS_1_FS_MASK,
.fs_avl = {
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
.value = ST_PRESS_1_FS_AVL_1260_VAL,
.gain = ST_PRESS_1_FS_AVL_1260_GAIN,
.gain2 = ST_PRESS_1_FS_AVL_TEMP_GAIN,
},
},
},
.bdu = {
.addr = ST_PRESS_1_BDU_ADDR,
.mask = ST_PRESS_1_BDU_MASK,
},
.drdy_irq = {
.addr = ST_PRESS_1_DRDY_IRQ_ADDR,
.mask = ST_PRESS_1_DRDY_IRQ_MASK,
},
.multi_read_bit = ST_PRESS_1_MULTIREAD_BIT,
.bootime = 2,
},
};
static int st_press_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *ch, int *val,
int *val2, long mask)
{
int err;
struct st_sensor_data *pdata = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
err = st_sensors_read_info_raw(indio_dev, ch, val);
if (err < 0)
goto read_error;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
switch (ch->type) {
case IIO_PRESSURE:
*val2 = pdata->current_fullscale->gain;
break;
case IIO_TEMP:
*val2 = pdata->current_fullscale->gain2;
break;
default:
err = -EINVAL;
goto read_error;
}
return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_OFFSET:
switch (ch->type) {
case IIO_TEMP:
*val = 425;
*val2 = 10;
break;
default:
err = -EINVAL;
goto read_error;
}
return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
read_error:
return err;
}
static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
static struct attribute *st_press_attributes[] = {
&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL,
};
static const struct attribute_group st_press_attribute_group = {
.attrs = st_press_attributes,
};
static const struct iio_info press_info = {
.driver_module = THIS_MODULE,
.attrs = &st_press_attribute_group,
.read_raw = &st_press_read_raw,
};
#ifdef CONFIG_IIO_TRIGGER
static const struct iio_trigger_ops st_press_trigger_ops = {
.owner = THIS_MODULE,
.set_trigger_state = ST_PRESS_TRIGGER_SET_STATE,
};
#define ST_PRESS_TRIGGER_OPS (&st_press_trigger_ops)
#else
#define ST_PRESS_TRIGGER_OPS NULL
#endif
int st_press_common_probe(struct iio_dev *indio_dev)
{
int err;
struct st_sensor_data *pdata = iio_priv(indio_dev);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &press_info;
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_press_sensors), st_press_sensors);
if (err < 0)
goto st_press_common_probe_error;
pdata->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS;
pdata->multiread_bit = pdata->sensor->multi_read_bit;
indio_dev->channels = pdata->sensor->ch;
indio_dev->num_channels = ARRAY_SIZE(st_press_channels);
pdata->current_fullscale = (struct st_sensor_fullscale_avl *)
&pdata->sensor->fs.fs_avl[0];
pdata->odr = pdata->sensor->odr.odr_avl[0].hz;
err = st_sensors_init_sensor(indio_dev);
if (err < 0)
goto st_press_common_probe_error;
if (pdata->get_irq_data_ready(indio_dev) > 0) {
err = st_press_allocate_ring(indio_dev);
if (err < 0)
goto st_press_common_probe_error;
err = st_sensors_allocate_trigger(indio_dev,
ST_PRESS_TRIGGER_OPS);
if (err < 0)
goto st_press_probe_trigger_error;
}
err = iio_device_register(indio_dev);
if (err)
goto st_press_device_register_error;
return err;
st_press_device_register_error:
if (pdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
st_press_probe_trigger_error:
if (pdata->get_irq_data_ready(indio_dev) > 0)
st_press_deallocate_ring(indio_dev);
st_press_common_probe_error:
return err;
}
EXPORT_SYMBOL(st_press_common_probe);
void st_press_common_remove(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (pdata->get_irq_data_ready(indio_dev) > 0) {
st_sensors_deallocate_trigger(indio_dev);
st_press_deallocate_ring(indio_dev);
}
iio_device_free(indio_dev);
}
EXPORT_SYMBOL(st_press_common_remove);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures driver");
MODULE_LICENSE("GPL v2");
/*
* STMicroelectronics pressures driver
*
* Copyright 2013 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
*
* Licensed under the GPL-2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/common/st_sensors.h>
#include <linux/iio/common/st_sensors_i2c.h>
#include "st_pressure.h"
static int st_press_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct st_sensor_data *pdata;
int err;
indio_dev = iio_device_alloc(sizeof(*pdata));
if (indio_dev == NULL) {
err = -ENOMEM;
goto iio_device_alloc_error;
}
pdata = iio_priv(indio_dev);
pdata->dev = &client->dev;
st_sensors_i2c_configure(indio_dev, client, pdata);
err = st_press_common_probe(indio_dev);
if (err < 0)
goto st_press_common_probe_error;
return 0;
st_press_common_probe_error:
iio_device_free(indio_dev);
iio_device_alloc_error:
return err;
}
static int st_press_i2c_remove(struct i2c_client *client)
{
st_press_common_remove(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id st_press_id_table[] = {
{ LPS331AP_PRESS_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_press_id_table);
static struct i2c_driver st_press_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-press-i2c",
},
.probe = st_press_i2c_probe,
.remove = st_press_i2c_remove,
.id_table = st_press_id_table,
};
module_i2c_driver(st_press_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures i2c driver");
MODULE_LICENSE("GPL v2");
/*
* STMicroelectronics pressures driver
*
* Copyright 2013 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
*
* Licensed under the GPL-2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/common/st_sensors.h>
#include <linux/iio/common/st_sensors_spi.h>
#include "st_pressure.h"
static int st_press_spi_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct st_sensor_data *pdata;
int err;
indio_dev = iio_device_alloc(sizeof(*pdata));
if (indio_dev == NULL) {
err = -ENOMEM;
goto iio_device_alloc_error;
}
pdata = iio_priv(indio_dev);
pdata->dev = &spi->dev;
st_sensors_spi_configure(indio_dev, spi, pdata);
err = st_press_common_probe(indio_dev);
if (err < 0)
goto st_press_common_probe_error;
return 0;
st_press_common_probe_error:
iio_device_free(indio_dev);
iio_device_alloc_error:
return err;
}
static int st_press_spi_remove(struct spi_device *spi)
{
st_press_common_remove(spi_get_drvdata(spi));
return 0;
}
static const struct spi_device_id st_press_id_table[] = {
{ LPS331AP_PRESS_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_press_id_table);
static struct spi_driver st_press_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "st-press-spi",
},
.probe = st_press_spi_probe,
.remove = st_press_spi_remove,
.id_table = st_press_id_table,
};
module_spi_driver(st_press_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures spi driver");
MODULE_LICENSE("GPL v2");
#
# Industrial I/O standalone triggers
#
menu "Triggers - standalone"
config IIO_INTERRUPT_TRIGGER
tristate "Generic interrupt trigger"
help
Provides support for using an interrupt of any type as an IIO
trigger. This may be provided by a gpio driver for example.
To compile this driver as a module, choose M here: the
module will be called iio-trig-interrupt.
config IIO_SYSFS_TRIGGER
tristate "SYSFS trigger"
depends on SYSFS
select IRQ_WORK
help
Provides support for using SYSFS entry as IIO triggers.
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called iio-trig-sysfs.
endmenu
#
# Makefile for triggers not associated with iio-devices
#
obj-$(CONFIG_IIO_INTERRUPT_TRIGGER) += iio-trig-interrupt.o
obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
/*
* Industrial I/O - generic interrupt based trigger support
*
* Copyright (c) 2008-2013 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
struct iio_interrupt_trigger_info {
unsigned int irq;
};
static irqreturn_t iio_interrupt_trigger_poll(int irq, void *private)
{
/* Timestamp not currently provided */
iio_trigger_poll(private, 0);
return IRQ_HANDLED;
}
static const struct iio_trigger_ops iio_interrupt_trigger_ops = {
.owner = THIS_MODULE,
};
static int iio_interrupt_trigger_probe(struct platform_device *pdev)
{
struct iio_interrupt_trigger_info *trig_info;
struct iio_trigger *trig;
unsigned long irqflags;
struct resource *irq_res;
int irq, ret = 0;
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (irq_res == NULL)
return -ENODEV;
irqflags = (irq_res->flags & IRQF_TRIGGER_MASK) | IRQF_SHARED;
irq = irq_res->start;
trig = iio_trigger_alloc("irqtrig%d", irq);
if (!trig) {
ret = -ENOMEM;
goto error_ret;
}
trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL);
if (!trig_info) {
ret = -ENOMEM;
goto error_put_trigger;
}
iio_trigger_set_drvdata(trig, trig_info);
trig_info->irq = irq;
trig->ops = &iio_interrupt_trigger_ops;
ret = request_irq(irq, iio_interrupt_trigger_poll,
irqflags, trig->name, trig);
if (ret) {
dev_err(&pdev->dev,
"request IRQ-%d failed", irq);
goto error_free_trig_info;
}
ret = iio_trigger_register(trig);
if (ret)
goto error_release_irq;
platform_set_drvdata(pdev, trig);
return 0;
/* First clean up the partly allocated trigger */
error_release_irq:
free_irq(irq, trig);
error_free_trig_info:
kfree(trig_info);
error_put_trigger:
iio_trigger_put(trig);
error_ret:
return ret;
}
static int iio_interrupt_trigger_remove(struct platform_device *pdev)
{
struct iio_trigger *trig;
struct iio_interrupt_trigger_info *trig_info;
trig = platform_get_drvdata(pdev);
trig_info = iio_trigger_get_drvdata(trig);
iio_trigger_unregister(trig);
free_irq(trig_info->irq, trig);
kfree(trig_info);
iio_trigger_put(trig);
return 0;
}
static struct platform_driver iio_interrupt_trigger_driver = {
.probe = iio_interrupt_trigger_probe,
.remove = iio_interrupt_trigger_remove,
.driver = {
.name = "iio_interrupt_trigger",
.owner = THIS_MODULE,
},
};
module_platform_driver(iio_interrupt_trigger_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Interrupt trigger for the iio subsystem");
MODULE_LICENSE("GPL v2");
......@@ -34,7 +34,7 @@ static ssize_t iio_sysfs_trig_add(struct device *dev,
int ret;
unsigned long input;
ret = strict_strtoul(buf, 10, &input);
ret = kstrtoul(buf, 10, &input);
if (ret)
return ret;
ret = iio_sysfs_trigger_probe(input);
......@@ -53,7 +53,7 @@ static ssize_t iio_sysfs_trig_remove(struct device *dev,
int ret;
unsigned long input;
ret = strict_strtoul(buf, 10, &input);
ret = kstrtoul(buf, 10, &input);
if (ret)
return ret;
ret = iio_sysfs_trigger_remove(input);
......
......@@ -62,6 +62,8 @@ source "drivers/staging/line6/Kconfig"
source "drivers/staging/octeon/Kconfig"
source "drivers/staging/octeon-usb/Kconfig"
source "drivers/staging/serqt_usb2/Kconfig"
source "drivers/staging/vt6655/Kconfig"
......@@ -140,4 +142,8 @@ source "drivers/staging/netlogic/Kconfig"
source "drivers/staging/dwc2/Kconfig"
source "drivers/staging/lustre/Kconfig"
source "drivers/staging/btmtk_usb/Kconfig"
endif # STAGING
......@@ -25,6 +25,7 @@ obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_NETLOGIC_XLR_NET) += netlogic/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
obj-$(CONFIG_OCTEON_USB) += octeon-usb/
obj-$(CONFIG_VT6655) += vt6655/
obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/
......@@ -62,3 +63,5 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
obj-$(CONFIG_ZCACHE) += zcache/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_USB_DWC2) += dwc2/
obj-$(CONFIG_LUSTRE_FS) += lustre/
obj-$(CONFIG_USB_BTMTK) += btmtk_usb/
......@@ -704,7 +704,8 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* support of 32bit userspace on 64bit platforms */
#ifdef CONFIG_COMPAT
static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static long compat_ashmem_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
......
......@@ -790,7 +790,7 @@ static void binder_delete_free_buffer(struct binder_proc *proc,
list_del(&buffer->entry);
if (free_page_start || free_page_end) {
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: merge free, buffer %p do not share page%s%s with with %p or %p\n",
"%d: merge free, buffer %p do not share page%s%s with %p or %p\n",
proc->pid, buffer, free_page_start ? "" : " end",
free_page_end ? "" : " start", prev, next);
binder_update_page_range(proc, 0, free_page_start ?
......
......@@ -160,7 +160,8 @@ static int sw_sync_release(struct inode *inode, struct file *file)
return 0;
}
static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, unsigned long arg)
static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj,
unsigned long arg)
{
int fd = get_unused_fd();
int err;
......@@ -218,7 +219,8 @@ static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
return 0;
}
static long sw_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static long sw_sync_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct sw_sync_timeline *obj = file->private_data;
......
......@@ -125,9 +125,9 @@ static void sync_timeline_remove_pt(struct sync_pt *pt)
spin_unlock_irqrestore(&obj->active_list_lock, flags);
spin_lock_irqsave(&obj->child_list_lock, flags);
if (!list_empty(&pt->child_list)) {
if (!list_empty(&pt->child_list))
list_del_init(&pt->child_list);
}
spin_unlock_irqrestore(&obj->child_list_lock, flags);
}
......@@ -876,11 +876,11 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
seq_printf(s, " / %s", value);
}
} else if (pt->parent->ops->print_pt) {
seq_printf(s, ": ");
seq_puts(s, ": ");
pt->parent->ops->print_pt(s, pt);
}
seq_printf(s, "\n");
seq_puts(s, "\n");
}
static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
......@@ -895,11 +895,11 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
obj->ops->timeline_value_str(obj, value, sizeof(value));
seq_printf(s, ": %s", value);
} else if (obj->ops->print_obj) {
seq_printf(s, ": ");
seq_puts(s, ": ");
obj->ops->print_obj(s, obj);
}
seq_printf(s, "\n");
seq_puts(s, "\n");
spin_lock_irqsave(&obj->child_list_lock, flags);
list_for_each(pos, &obj->child_list_head) {
......@@ -940,7 +940,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
unsigned long flags;
struct list_head *pos;
seq_printf(s, "objs:\n--------------\n");
seq_puts(s, "objs:\n--------------\n");
spin_lock_irqsave(&sync_timeline_list_lock, flags);
list_for_each(pos, &sync_timeline_list_head) {
......@@ -949,11 +949,11 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
sync_timeline_list);
sync_print_obj(s, obj);
seq_printf(s, "\n");
seq_puts(s, "\n");
}
spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
seq_printf(s, "fences:\n--------------\n");
seq_puts(s, "fences:\n--------------\n");
spin_lock_irqsave(&sync_fence_list_lock, flags);
list_for_each(pos, &sync_fence_list_head) {
......@@ -961,7 +961,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused)
container_of(pos, struct sync_fence, sync_fence_list);
sync_print_fence(s, fence);
seq_printf(s, "\n");
seq_puts(s, "\n");
}
spin_unlock_irqrestore(&sync_fence_list_lock, flags);
return 0;
......@@ -988,7 +988,7 @@ late_initcall(sync_debugfs_init);
#define DUMP_CHUNK 256
static char sync_dump_buf[64 * 1024];
void sync_dump(void)
static void sync_dump(void)
{
struct seq_file s = {
.buf = sync_dump_buf,
......
......@@ -50,9 +50,9 @@
#define ASUS_OLED_DISP_HEIGHT 32
#define ASUS_OLED_PACKET_BUF_SIZE 256
#define USB_VENDOR_ID_ASUS 0x0b05
#define USB_DEVICE_ID_ASUS_LCM 0x1726
#define USB_DEVICE_ID_ASUS_LCM2 0x175b
#define USB_VENDOR_ID_ASUS 0x0b05
#define USB_DEVICE_ID_ASUS_LCM 0x1726
#define USB_DEVICE_ID_ASUS_LCM2 0x175b
MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
MODULE_DESCRIPTION("Asus OLED Driver");
......@@ -324,9 +324,11 @@ static void send_data(struct asus_oled_dev *odev)
return;
if (odev->pack_mode == PACK_MODE_G1) {
/* When sending roll-mode data the display updated only
first packet. I have no idea why, but when static picture
is sent just before rolling picture everything works fine. */
/*
* When sending roll-mode data the display updated only
* first packet. I have no idea why, but when static picture
* is sent just before rolling picture everything works fine.
*/
if (odev->pic_mode == ASUS_OLED_ROLL)
send_packets(odev->udev, packet, odev->buf,
ASUS_OLED_STATIC, 2);
......@@ -363,9 +365,11 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
switch (odev->pack_mode) {
case PACK_MODE_G1:
/* i = (x/128)*640 + 127 - x + (y/8)*128;
This one for 128 is the same, but might be better
for different widths? */
/*
* i = (x/128)*640 + 127 - x + (y/8)*128;
* This one for 128 is the same, but might be better
* for different widths?
*/
i = (x/odev->dev_width)*640 +
odev->dev_width - 1 - x +
(y/8)*odev->dev_width;
......@@ -383,10 +387,8 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
}
if (i >= odev->buf_size) {
dev_err(odev->dev, "Buffer overflow! Report a bug:"
"offs: %d >= %d i: %d (x: %d y: %d)\n",
(int) odev->buf_offs, (int) odev->buf_size,
(int) i, (int) x, (int) y);
dev_err(odev->dev, "Buffer overflow! Report a bug: offs: %zu >= %zu i: %zu (x: %zu y: %zu)\n",
odev->buf_offs, odev->buf_size, i, x, y);
return -EIO;
}
......@@ -401,7 +403,7 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
default:
/* cannot get here; stops gcc complaining*/
;
break;
}
odev->buf_offs++;
......@@ -566,9 +568,11 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev,
if (ret < 0)
return ret;
} else if (buf[offs] == '\n') {
/* New line detected. Lets assume, that all characters
till the end of the line were equal to the last
character in this line.*/
/*
* New line detected. Lets assume, that all characters
* till the end of the line were equal to the last
* character in this line.
*/
if (odev->buf_offs % odev->width != 0)
ret = append_values(odev, odev->last_val,
odev->width -
......
......@@ -13,7 +13,7 @@
* Returns - Zero(Success)
****************************************************************/
static int bcm_char_open(struct inode *inode, struct file * filp)
static int bcm_char_open(struct inode *inode, struct file *filp)
{
struct bcm_mini_adapter *Adapter = NULL;
struct bcm_tarang_data *pTarang = NULL;
......
......@@ -42,107 +42,95 @@ send to f/w with in 200 ms after the Idle/Shutdown req issued
*/
int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int* puiBuffer)
int InterfaceIdleModeRespond(struct bcm_mini_adapter *Adapter, unsigned int *puiBuffer)
{
int status = STATUS_SUCCESS;
unsigned int uiRegRead = 0;
int bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer));
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "SubType of Message :0x%X", ntohl(*puiBuffer));
if(ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL," Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype");
if(ntohl(*(puiBuffer+1)) == 0 )
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Got IDLE MODE WAKE UP Response From F/W");
if (ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, " Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype");
if (ntohl(*(puiBuffer+1)) == 0 ) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got IDLE MODE WAKE UP Response From F/W");
status = wrmalt (Adapter,SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead));
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
status = wrmalt (Adapter, SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead));
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
return status;
}
if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
{
if (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
uiRegRead = 0x00000000 ;
status = wrmalt (Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead));
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
status = wrmalt (Adapter, DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead));
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg");
return status;
}
}
//Below Register should not br read in case of Manual and Protocol Idle mode.
else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
{
//clear on read Register
/* Below Register should not br read in case of Manual and Protocol Idle mode */
else if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
/* clear on read Register */
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0");
return status;
}
//clear on read Register
/* clear on read Register */
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1");
return status;
}
}
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");
// Set Idle Mode Flag to False and Clear IdleMode reg.
/* Set Idle Mode Flag to False and Clear IdleMode reg. */
Adapter->IdleMode = FALSE;
Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
wake_up(&Adapter->lowpower_mode_wait_queue);
}
else
{
if(TRUE == Adapter->IdleMode)
} else {
if (TRUE == Adapter->IdleMode)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode....");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device is already in Idle mode....");
return status ;
}
uiRegRead = 0;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n");
if (Adapter->chip_id== BCS220_2 ||
if (Adapter->chip_id == BCS220_2 ||
Adapter->chip_id == BCS220_2BC ||
Adapter->chip_id== BCS250_BC ||
Adapter->chip_id== BCS220_3)
{
Adapter->chip_id == BCS250_BC ||
Adapter->chip_id == BCS220_3) {
bytes = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
if (bytes < 0) {
status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n");
return status;
}
uiRegRead |= (1<<17);
status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n");
status = wrmalt (Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead));
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n");
return status;
}
}
SendIdleModeResponse(Adapter);
}
}
else if(ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params");
OverrideServiceFlowParams(Adapter,puiBuffer);
} else if (ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params");
OverrideServiceFlowParams(Adapter, puiBuffer);
}
return status;
}
......@@ -152,46 +140,40 @@ static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int
int status = STATUS_SUCCESS;
unsigned int value;
unsigned int chip_id ;
unsigned long timeout = 0 ,itr = 0;
unsigned long timeout = 0, itr = 0;
int lenwritten = 0;
unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
unsigned char aucAbortPattern[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
struct bcm_interface_adapter *psInterfaceAdapter = Adapter->pvInterfaceAdapter;
//Abort Bus suspend if its already suspended
if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend))
{
/* Abort Bus suspend if its already suspended */
if ((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend)) {
status = usb_autopm_get_interface(psInterfaceAdapter->interface);
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Bus got wakeup..Aborting Idle mode... status:%d \n", status);
}
if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
if ((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
||
(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE))
{
//write the SW abort pattern.
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern);
status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern));
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) {
/* write the SW abort pattern. */
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern);
status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern));
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
return status;
}
}
if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
{
if (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
value = 0x80000000;
status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value));
if(status)
status = wrmalt(Adapter, DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value));
if (status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed");
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed");
return status;
}
}
else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)
{
} else if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) {
/*
* Get a Interrupt Out URB and send 8 Bytes Down
* To be Done in Thread Context.
......@@ -204,43 +186,32 @@ static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int
8,
&lenwritten,
5000);
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status);
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n", status);
return status;
}
else
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten);
} else {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten);
}
//mdelay(25);
/* mdelay(25); */
timeout= jiffies + msecs_to_jiffies(50) ;
while( timeout > jiffies )
{
timeout = jiffies + msecs_to_jiffies(50) ;
while ( timeout > jiffies ) {
itr++ ;
rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT));
if(0xbece3200==(chip_id&~(0xF0)))
{
if (0xbece3200 == (chip_id&~(0xF0)))
chip_id = chip_id&~(0xF0);
}
if(chip_id == Adapter->chip_id)
if (chip_id == Adapter->chip_id)
break;
}
if(timeout < jiffies )
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec");
}
if (timeout < jiffies )
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Not able to read chip-id even after 25 msec");
else
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr);
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Number of completed iteration to read chip-id :%lu", itr);
status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status));
if(status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status));
if (status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to Register SW_ABORT_IDLEMODE_LOC failed..");
return status;
}
}
......@@ -249,13 +220,10 @@ static int InterfaceAbortIdlemode(struct bcm_mini_adapter *Adapter, unsigned int
int InterfaceIdleModeWakeup(struct bcm_mini_adapter *Adapter)
{
ULONG Status = 0;
if(Adapter->bTriedToWakeUpFromlowPowerMode)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n");
}
else
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Writing Low Power Mode Abort pattern to the Device\n");
if (Adapter->bTriedToWakeUpFromlowPowerMode) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n");
} else {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing Low Power Mode Abort pattern to the Device\n");
Adapter->bTriedToWakeUpFromlowPowerMode = TRUE;
InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern);
......@@ -269,33 +237,30 @@ void InterfaceHandleShutdownModeWakeup(struct bcm_mini_adapter *Adapter)
INT Status = 0;
int bytes;
if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING)
{
// clear idlemode interrupt.
if (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) {
/* clear idlemode interrupt. */
uiRegVal = 0;
Status =wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal));
if(Status)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status);
Status = wrmalt(Adapter, DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal));
if (Status) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status);
return;
}
}
else
{
else {
//clear Interrupt EP registers.
bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
/* clear Interrupt EP registers. */
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal));
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status);
return;
}
bytes = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
bytes = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal));
if (bytes < 0) {
Status = bytes;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status);
return;
}
}
......
/*Copyright (c) 2005 Beceem Communications Inc.
Module Name:
......@@ -17,7 +16,6 @@ Module Name:
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_NETWORK
#define VER_FILEVERSION 5.2.45
#define VER_FILEVERSION_STR "5.2.45"
......@@ -28,8 +26,4 @@ Module Name:
#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
//#include "common.ver"
#endif //VERSION_H
#endif /* VERSION_H */
#include "headers.h"
//-----------------------------------------------------------------------------
// Procedure: vendorextnGetSectionInfo
//
// Description: Finds the type of NVM used.
//
// Arguments:
// Adapter - ptr to Adapter object instance
// pNVMType - ptr to NVM type.
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//-----------------------------------------------------------------------------
/*
* Procedure: vendorextnGetSectionInfo
*
* Description: Finds the type of NVM used.
*
* Arguments:
* Adapter - ptr to Adapter object instance
* pNVMType - ptr to NVM type.
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*
*/
INT vendorextnGetSectionInfo(PVOID pContext, struct bcm_flash2x_vendor_info *pVendorInfo)
{
return STATUS_FAILURE;
}
//-----------------------------------------------------------------------------
// Procedure: vendorextnInit
//
// Description: Initializing the vendor extension NVM interface
//
// Arguments:
// Adapter - Pointer to MINI Adapter Structure.
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//-----------------------------------------------------------------------------
/*
* Procedure: vendorextnInit
*
* Description: Initializing the vendor extension NVM interface
*
* Arguments:
* Adapter - Pointer to MINI Adapter Structure
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*
*
*/
INT vendorextnInit(struct bcm_mini_adapter *Adapter)
{
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// Procedure: vendorextnExit
//
// Description: Free the resource associated with vendor extension NVM interface
//
// Arguments:
// Adapter - Pointer to MINI Adapter Structure.
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//-----------------------------------------------------------------------------
/*
* Procedure: vendorextnExit
*
* Description: Free the resource associated with vendor extension NVM interface
*
* Arguments:
*
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*
*
*/
INT vendorextnExit(struct bcm_mini_adapter *Adapter)
{
return STATUS_SUCCESS;
}
//------------------------------------------------------------------------
// Procedure: vendorextnIoctl
//
// Description: execute the vendor extension specific ioctl
//
//Arguments:
// Adapter -Beceem private Adapter Structure
// cmd -vendor extension specific Ioctl commad
// arg -input parameter sent by vendor
//
// Returns:
// CONTINUE_COMMON_PATH in case it is not meant to be processed by vendor ioctls
// STATUS_SUCCESS/STATUS_FAILURE as per the IOCTL return value
//
//--------------------------------------------------------------------------
/*
* Procedure: vendorextnIoctl
*
* Description: execute the vendor extension specific ioctl
*
* Arguments:
* Adapter -Beceem private Adapter Structure
* cmd -vendor extension specific Ioctl commad
* arg -input parameter sent by vendor
*
* Returns:
* CONTINUE_COMMON_PATH in case it is not meant to be processed by vendor ioctls
* STATUS_SUCCESS/STATUS_FAILURE as per the IOCTL return value
*/
INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg)
{
return CONTINUE_COMMON_PATH;
......@@ -72,22 +72,21 @@ INT vendorextnIoctl(struct bcm_mini_adapter *Adapter, UINT cmd, ULONG arg)
//------------------------------------------------------------------
// Procedure: vendorextnReadSection
//
// Description: Reads from a section of NVM
//
// Arguments:
// pContext - ptr to Adapter object instance
// pBuffer - Read the data from Vendor Area to this buffer
// SectionVal - Value of type of Section
// Offset - Read from the Offset of the Vendor Section.
// numOfBytes - Read numOfBytes from the Vendor section to Buffer
//
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//------------------------------------------------------------------
/*
* Procedure: vendorextnReadSection
*
* Description: Reads from a section of NVM
*
* Arguments:
* pContext - ptr to Adapter object instance
* pBuffer - Read the data from Vendor Area to this buffer
* SectionVal - Value of type of Section
* Offset - Read from the Offset of the Vendor Section.
* numOfBytes - Read numOfBytes from the Vendor section to Buffer
*
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*/
INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
UINT offset, UINT numOfBytes)
......@@ -97,23 +96,22 @@ INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_sect
//------------------------------------------------------------------
// Procedure: vendorextnWriteSection
//
// Description: Write to a Section of NVM
//
// Arguments:
// pContext - ptr to Adapter object instance
// pBuffer - Write the data provided in the buffer
// SectionVal - Value of type of Section
// Offset - Writes to the Offset of the Vendor Section.
// numOfBytes - Write num Bytes after reading from pBuffer.
// bVerify - the Buffer Written should be verified.
//
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//------------------------------------------------------------------
/*
* Procedure: vendorextnWriteSection
*
* Description: Write to a Section of NVM
*
* Arguments:
* pContext - ptr to Adapter object instance
* pBuffer - Write the data provided in the buffer
* SectionVal - Value of type of Section
* Offset - Writes to the Offset of the Vendor Section.
* numOfBytes - Write num Bytes after reading from pBuffer.
* bVerify - the Buffer Written should be verified.
*
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*/
INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
UINT offset, UINT numOfBytes, BOOLEAN bVerify)
{
......@@ -122,25 +120,23 @@ INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_sec
//------------------------------------------------------------------
// Procedure: vendorextnWriteSectionWithoutErase
//
// Description: Write to a Section of NVM without erasing the sector
//
// Arguments:
// pContext - ptr to Adapter object instance
// pBuffer - Write the data provided in the buffer
// SectionVal - Value of type of Section
// Offset - Writes to the Offset of the Vendor Section.
// numOfBytes - Write num Bytes after reading from pBuffer.
//
// Returns:
// STATUS_SUCCESS/STATUS_FAILURE
//
//------------------------------------------------------------------
/*
* Procedure: vendorextnWriteSectionWithoutErase
*
* Description: Write to a Section of NVM without erasing the sector
*
* Arguments:
* pContext - ptr to Adapter object instance
* pBuffer - Write the data provided in the buffer
* SectionVal - Value of type of Section
* Offset - Writes to the Offset of the Vendor Section.
* numOfBytes - Write num Bytes after reading from pBuffer.
*
* Returns:
* STATUS_SUCCESS/STATUS_FAILURE
*/
INT vendorextnWriteSectionWithoutErase(PVOID pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
UINT offset, UINT numOfBytes)
{
return STATUS_FAILURE;
}
config USB_BTMTK
tristate "Mediatek Bluetooth support"
depends on USB && BT && m
---help---
Say Y here if you wish to control a MTK USB Bluetooth.
This option depends on 'USB' support being enabled
To compile this driver as a module, choose M here: the
module will be called btmtk_usb.
obj-$(CONFIG_USB_BTMTK) += btmtk_usb.o
-build driver modules
make
-install driver modules
make install
-remove driver modules
make clean
-dynamic debug message
turn on CONFIG_DYNAMIC_DEBUG compiler flag for current kernel
mount -t debugfs none /sys/kernel/debug/
echo "module module_name +p" > /sys/kernel/debug/dynamic_debug/control(turn on debug messages, module name such as btmtk_usb)
echo "module module_name -p" > /sys/kernel/debug/dynamic_debug/control(turn off debug messages, module name such as btmtk_usb)
TODO:
- checkpatch.pl clean
- determine if the driver should not be using a duplicate
version of the usb-bluetooth interface code, but should
be merged into the drivers/bluetooth/ directory and
infrastructure instead.
- review by the bluetooth developer community
Please send any patches for this driver to Yu-Chen, Cho <acho@suse.com> and
jay.hung@mediatek.com
此差异已折叠。
/*
* MediaTek Bluetooth USB Driver
*
* Copyright (C) 2013, MediaTek co.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* or on the worldwide web at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
*/
#ifndef __BTMTK_USB_H__
#define __BTMTK_USB_H_
/* Memory map for MTK BT */
/* SYS Control */
#define SYSCTL 0x400000
/* WLAN */
#define WLAN 0x410000
/* MCUCTL */
#define INT_LEVEL 0x0718
#define COM_REG0 0x0730
#define SEMAPHORE_00 0x07B0
#define SEMAPHORE_01 0x07B4
#define SEMAPHORE_02 0x07B8
#define SEMAPHORE_03 0x07BC
/* Chip definition */
#define CONTROL_TIMEOUT_JIFFIES ((300 * HZ) / 100)
#define DEVICE_VENDOR_REQUEST_OUT 0x40
#define DEVICE_VENDOR_REQUEST_IN 0xc0
#define DEVICE_CLASS_REQUEST_OUT 0x20
#define BTUSB_MAX_ISOC_FRAMES 10
#define BTUSB_INTR_RUNNING 0
#define BTUSB_BULK_RUNNING 1
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
#define BTUSB_DID_ISO_RESUME 4
/* ROM Patch */
#define PATCH_HCI_HEADER_SIZE 4
#define PATCH_WMT_HEADER_SIZE 5
#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE)
#define UPLOAD_PATCH_UNIT 2048
#define PATCH_INFO_SIZE 30
#define PATCH_PHASE1 1
#define PATCH_PHASE2 2
#define PATCH_PHASE3 3
struct btmtk_usb_data {
struct hci_dev *hdev;
struct usb_device *udev;
struct usb_interface *intf;
struct usb_interface *isoc;
spinlock_t lock;
unsigned long flags;
struct work_struct work;
struct work_struct waker;
struct usb_anchor tx_anchor;
struct usb_anchor intr_anchor;
struct usb_anchor bulk_anchor;
struct usb_anchor isoc_anchor;
struct usb_anchor deferred;
int tx_in_flight;
spinlock_t txlock;
struct usb_endpoint_descriptor *intr_ep;
struct usb_endpoint_descriptor *bulk_tx_ep;
struct usb_endpoint_descriptor *bulk_rx_ep;
struct usb_endpoint_descriptor *isoc_tx_ep;
struct usb_endpoint_descriptor *isoc_rx_ep;
__u8 cmdreq_type;
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
/* request for different io operation */
u8 w_request;
u8 r_request;
/* io buffer for usb control transfer */
char *io_buf;
struct semaphore fw_upload_sem;
/* unsigned char *fw_image; */
/* unsigned char *rom_patch; */
const struct firmware *firmware;
u32 chip_id;
u8 need_load_fw;
u8 need_load_rom_patch;
u32 rom_patch_offset;
u32 rom_patch_len;
};
static inline int is_mt7630(struct btmtk_usb_data *data)
{
return ((data->chip_id & 0xffff0000) == 0x76300000);
}
static inline int is_mt7650(struct btmtk_usb_data *data)
{
return ((data->chip_id & 0xffff0000) == 0x76500000);
}
static inline int is_mt7632(struct btmtk_usb_data *data)
{
return ((data->chip_id & 0xffff0000) == 0x76320000);
}
static inline int is_mt7662(struct btmtk_usb_data *data)
{
return ((data->chip_id & 0xffff0000) == 0x76620000);
}
#endif
此差异已折叠。
......@@ -35,7 +35,7 @@ typedef struct TransferDesc {
short eSize; /* element size - is tohost flag for circular */
} TRANSFERDESC;
typedef TRANSFERDESC * LPTRANSFERDESC;
typedef TRANSFERDESC *LPTRANSFERDESC;
typedef struct TransferEvent {
unsigned int dwStart; /* offset into the area */
......
......@@ -77,20 +77,13 @@
#endif
#if defined(LINUX) || defined(MAXOSX)
#define FAR
#define FAR
typedef int BOOL; // To match Windows
typedef char * LPSTR;
typedef const char * LPCSTR;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned char BYTE;
typedef BYTE BOOLEAN;
typedef unsigned char UCHAR;
#define __packed __attribute__((packed))
typedef BYTE * LPBYTE;
#define HIWORD(x) (WORD)(((x)>>16) & 0xffff)
#define LOWORD(x) (WORD)((x) & 0xffff)
typedef int BOOL; /* To match Windows */
typedef unsigned char BYTE;
#define __packed __attribute__((packed))
#define HIWORD(x) (unsigned short)(((x)>>16) & 0xffff)
#define LOWORD(x) (unsigned short)((x) & 0xffff)
#endif
#ifdef _IS_WINDOWS_
......@@ -104,21 +97,20 @@
** a synonym.
*/
#ifdef GNUC
#define DllExport __attribute__((dllexport))
#define DllImport __attribute__((dllimport))
#define DllExport __attribute__((dllexport))
#define DllImport __attribute__((dllimport))
#endif
#ifndef DllExport
#ifdef _IS_WINDOWS_
#define DllExport __declspec(dllexport)
#define DllImport __declspec(dllimport)
#define DllExport __declspec(dllexport)
#define DllImport __declspec(dllimport)
#else
#define DllExport
#define DllImport
#define DllExport
#define DllImport
#endif
#endif /* _IS_WINDOWS_ */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
......
此差异已折叠。
此差异已折叠。
......@@ -11,16 +11,16 @@
#define __USE1401_H__
#include "machine.h"
// Some definitions to make things compatible. If you want to use Use1401 directly
// from a Windows program you should define U14_NOT_DLL, in which case you also
// MUST make sure that your application startup code calls U14InitLib().
// DLL_USE1401 is defined when you are building the Use1401 dll, not otherwise.
/* Some definitions to make things compatible. If you want to use Use1401 directly */
/* from a Windows program you should define U14_NOT_DLL, in which case you also */
/* MUST make sure that your application startup code calls U14InitLib(). */
/* DLL_USE1401 is defined when you are building the Use1401 dll, not otherwise. */
#ifdef _IS_WINDOWS_
#ifndef U14_NOT_DLL
#ifdef DLL_USE1401
#define U14API(retType) retType DllExport __stdcall
#define U14API(retType) (retType DllExport __stdcall)
#else
#define U14API(retType) retType DllImport __stdcall
#define U14API(retType) (retType DllImport __stdcall)
#endif
#endif
......@@ -36,7 +36,7 @@
#ifdef _QT
#ifndef U14_NOT_DLL
#undef U14API
#define U14API(retType) retType __declspec(dllimport) __stdcall
#define U14API(retType) (retType __declspec(dllimport) __stdcall)
#endif
#undef U14LONG
#define U14LONG int
......@@ -50,20 +50,20 @@
#define U14LONG long
#endif
/// Error codes: We need them here as user space can see them.
#define U14ERR_NOERROR 0 // no problems
/* Error codes: We need them here as user space can see them. */
#define U14ERR_NOERROR 0 /* no problems */
/// Device error codes, but these don't need to be extended - a succession is assumed
#define U14ERR_STD 4 // standard 1401 connected
#define U14ERR_U1401 5 // u1401 connected
#define U14ERR_PLUS 6 // 1401 plus connected
#define U14ERR_POWER 7 // Power1401 connected
#define U14ERR_U14012 8 // u1401 mkII connected
/* Device error codes, but these don't need to be extended - a succession is assumed */
#define U14ERR_STD 4 /* standard 1401 connected */
#define U14ERR_U1401 5 /* u1401 connected */
#define U14ERR_PLUS 6 /* 1401 plus connected */
#define U14ERR_POWER 7 /* Power1401 connected */
#define U14ERR_U14012 8 /* u1401 mkII connected */
#define U14ERR_POWER2 9
#define U14ERR_U14013 10
#define U14ERR_POWER3 11
/// NBNB Error numbers need shifting as some linux error codes start at 512
/* NBNB Error numbers need shifting as some linux error codes start at 512 */
#define U14ERR(n) (n+U14ERRBASE)
#define U14ERR_OFF U14ERR(0) /* 1401 there but switched off */
#define U14ERR_NC U14ERR(-1) /* 1401 not connected */
......@@ -113,7 +113,7 @@
#define U14ERR_DRIVCOMMS U14ERR(-110) /* failed talking to driver */
#define U14ERR_OUTOFMEMORY U14ERR(-111) /* needed memory and couldnt get it*/
/// 1401 type codes.
/* / 1401 type codes. */
#define U14TYPE1401 0 /* standard 1401 */
#define U14TYPEPLUS 1 /* 1401 plus */
#define U14TYPEU1401 2 /* u1401 */
......@@ -124,9 +124,9 @@
#define U14TYPEPOWER3 7 /* power1401-3 */
#define U14TYPEUNKNOWN -1 /* dont know */
/// Transfer flags to allow driver capabilities to be interrogated
/* Transfer flags to allow driver capabilities to be interrogated */
/// Constants for transfer flags
/* Constants for transfer flags */
#define U14TF_USEDMA 1 /* Transfer flag for use DMA */
#define U14TF_MULTIA 2 /* Transfer flag for multi areas */
#define U14TF_FIFO 4 /* for FIFO interface card */
......@@ -138,18 +138,18 @@
#define U14TF_DIAG 256 /* Diagnostics/debug functions */
#define U14TF_CIRC14 512 /* Circular-mode to 1401 */
/// Definitions of element sizes for DMA transfers - to allow byte-swapping
/* Definitions of element sizes for DMA transfers - to allow byte-swapping */
#define ESZBYTES 0 /* BYTE element size value */
#define ESZWORDS 1 /* WORD element size value */
#define ESZWORDS 1 /* unsigned short element size value */
#define ESZLONGS 2 /* long element size value */
#define ESZUNKNOWN 0 /* unknown element size value */
/// These define required access types for the debug/diagnostics function
/* These define required access types for the debug/diagnostics function */
#define BYTE_SIZE 1 /* 8-bit access */
#define WORD_SIZE 2 /* 16-bit access */
#define LONG_SIZE 3 /* 32-bit access */
/// Stuff used by U14_GetTransfer
/* Stuff used by U14_GetTransfer */
#define GET_TX_MAXENTRIES 257 /* (max length / page size + 1) */
#ifdef _IS_WINDOWS_
......@@ -157,19 +157,19 @@
typedef struct /* used for U14_GetTransfer results */
{ /* Info on a single mapped block */
U14LONG physical;
U14LONG size;
U14LONG physical;
U14LONG size;
} TXENTRY;
typedef struct TGetTxBlock /* used for U14_GetTransfer results */
{ /* matches structure in VXD */
U14LONG size;
U14LONG linear;
short seg;
short reserved;
short avail; /* number of available entries */
short used; /* number of used entries */
TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
U14LONG size;
U14LONG linear;
short seg;
short reserved;
short avail; /* number of available entries */
short used; /* number of used entries */
TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
} TGET_TX_BLOCK;
typedef TGET_TX_BLOCK *LPGET_TX_BLOCK;
......@@ -180,19 +180,19 @@ typedef TGET_TX_BLOCK *LPGET_TX_BLOCK;
#ifdef LINUX
typedef struct /* used for U14_GetTransfer results */
{ /* Info on a single mapped block */
long long physical;
long size;
long long physical;
long size;
} TXENTRY;
typedef struct TGetTxBlock /* used for U14_GetTransfer results */
{ /* matches structure in VXD */
long long linear; /* linear address */
long size; /* total size of the mapped area, holds id when called */
short seg; /* segment of the address for Win16 */
short reserved;
short avail; /* number of available entries */
short used; /* number of used entries */
TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
long long linear; /* linear address */
long size; /* total size of the mapped area, holds id when called */
short seg; /* segment of the address for Win16 */
short reserved;
short avail; /* number of available entries */
short used; /* number of used entries */
TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
} TGET_TX_BLOCK;
#endif
......@@ -200,84 +200,84 @@ typedef struct TGetTxBlock /* used for U14_GetTransfer results */
extern "C" {
#endif
U14API(int) U14WhenToTimeOut(short hand); // when to timeout in ms
U14API(short) U14PassedTime(int iTime); // non-zero if iTime passed
U14API(int) U14WhenToTimeOut(short hand); /* when to timeout in ms */
U14API(short) U14PassedTime(int iTime); /* non-zero if iTime passed */
U14API(short) U14LastErrCode(short hand);
U14API(short) U14LastErrCode(short hand);
U14API(short) U14Open1401(short n1401);
U14API(short) U14Close1401(short hand);
U14API(short) U14Reset1401(short hand);
U14API(short) U14ForceReset(short hand);
U14API(short) U14TypeOf1401(short hand);
U14API(short) U14NameOf1401(short hand, char* pBuf, WORD wMax);
U14API(short) U14Open1401(short n1401);
U14API(short) U14Close1401(short hand);
U14API(short) U14Reset1401(short hand);
U14API(short) U14ForceReset(short hand);
U14API(short) U14TypeOf1401(short hand);
U14API(short) U14NameOf1401(short hand, char *pBuf, unsigned short wMax);
U14API(short) U14Stat1401(short hand);
U14API(short) U14CharCount(short hand);
U14API(short) U14LineCount(short hand);
U14API(short) U14Stat1401(short hand);
U14API(short) U14CharCount(short hand);
U14API(short) U14LineCount(short hand);
U14API(short) U14SendString(short hand, const char* pString);
U14API(short) U14GetString(short hand, char* pBuffer, WORD wMaxLen);
U14API(short) U14SendChar(short hand, char cChar);
U14API(short) U14GetChar(short hand, char* pcChar);
U14API(short) U14SendString(short hand, const char *pString);
U14API(short) U14GetString(short hand, char *pBuffer, unsigned short wMaxLen);
U14API(short) U14SendChar(short hand, char cChar);
U14API(short) U14GetChar(short hand, char *pcChar);
U14API(short) U14LdCmd(short hand, const char* command);
U14API(DWORD) U14Ld(short hand, const char* vl, const char* str);
U14API(short) U14LdCmd(short hand, const char *command);
U14API(unsigned int) U14Ld(short hand, const char *vl, const char *str);
U14API(short) U14SetTransArea(short hand, WORD wArea, void *pvBuff,
DWORD dwLength, short eSz);
U14API(short) U14UnSetTransfer(short hand, WORD wArea);
U14API(short) U14SetTransferEvent(short hand, WORD wArea, BOOL bEvent,
BOOL bToHost, DWORD dwStart, DWORD dwLength);
U14API(int) U14TestTransferEvent(short hand, WORD wArea);
U14API(int) U14WaitTransferEvent(short hand, WORD wArea, int msTimeOut);
U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock);
U14API(short) U14SetTransArea(short hand, unsigned short wArea, void *pvBuff,
unsigned int dwLength, short eSz);
U14API(short) U14UnSetTransfer(short hand, unsigned short wArea);
U14API(short) U14SetTransferEvent(short hand, unsigned short wArea, BOOL bEvent,
BOOL bToHost, unsigned int dwStart, unsigned int dwLength);
U14API(int) U14TestTransferEvent(short hand, unsigned short wArea);
U14API(int) U14WaitTransferEvent(short hand, unsigned short wArea, int msTimeOut);
U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock);
U14API(short) U14ToHost(short hand, char* pAddrHost,DWORD dwSize,DWORD dw1401,
short eSz);
U14API(short) U14To1401(short hand, const char* pAddrHost,DWORD dwSize,DWORD dw1401,
short eSz);
U14API(short) U14ToHost(short hand, char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
short eSz);
U14API(short) U14To1401(short hand, const char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
short eSz);
U14API(short) U14SetCircular(short hand, WORD wArea, BOOL bToHost, void *pvBuff,
DWORD dwLength);
U14API(short) U14SetCircular(short hand, unsigned short wArea, BOOL bToHost, void *pvBuff,
unsigned int dwLength);
U14API(int) U14GetCircBlk(short hand, WORD wArea, DWORD *pdwOffs);
U14API(int) U14FreeCircBlk(short hand, WORD wArea, DWORD dwOffs, DWORD dwSize,
DWORD *pdwOffs);
U14API(int) U14GetCircBlk(short hand, unsigned short wArea, unsigned int *pdwOffs);
U14API(int) U14FreeCircBlk(short hand, unsigned short wArea, unsigned int dwOffs, unsigned int dwSize,
unsigned int *pdwOffs);
U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs);
U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs);
U14API(short) U14StrToLongs(const char *pszBuff, U14LONG *palNums, short sMaxLongs);
U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs);
U14API(void) U14SetTimeout(short hand, int lTimeout);
U14API(int) U14GetTimeout(short hand);
U14API(short) U14OutBufSpace(short hand);
U14API(short) U14OutBufSpace(short hand);
U14API(int) U14BaseAddr1401(short hand);
U14API(int) U14DriverVersion(short hand);
U14API(int) U14DriverType(short hand);
U14API(short) U14DriverName(short hand, char* pBuf, WORD wMax);
U14API(short) U14GetUserMemorySize(short hand, DWORD *pMemorySize);
U14API(short) U14KillIO1401(short hand);
U14API(short) U14BlkTransState(short hand);
U14API(short) U14StateOf1401(short hand);
U14API(short) U14Grab1401(short hand);
U14API(short) U14Free1401(short hand);
U14API(short) U14Peek1401(short hand, DWORD dwAddr, int nSize, int nRepeats);
U14API(short) U14Poke1401(short hand, DWORD dwAddr, DWORD dwValue, int nSize, int nRepeats);
U14API(short) U14Ramp1401(short hand, DWORD dwAddr, DWORD dwDef, DWORD dwEnable, int nSize, int nRepeats);
U14API(short) U14RampAddr(short hand, DWORD dwDef, DWORD dwEnable, int nSize, int nRepeats);
U14API(short) U14StopDebugLoop(short hand);
U14API(short) U14GetDebugData(short hand, U14LONG *plValue);
U14API(short) U14StartSelfTest(short hand);
U14API(short) U14CheckSelfTest(short hand, U14LONG *pData);
U14API(short) U14TransferFlags(short hand);
U14API(void) U14GetErrorString(short nErr, char* pStr, WORD wMax);
U14API(short) U14DriverName(short hand, char *pBuf, unsigned short wMax);
U14API(short) U14GetUserMemorySize(short hand, unsigned int *pMemorySize);
U14API(short) U14KillIO1401(short hand);
U14API(short) U14BlkTransState(short hand);
U14API(short) U14StateOf1401(short hand);
U14API(short) U14Grab1401(short hand);
U14API(short) U14Free1401(short hand);
U14API(short) U14Peek1401(short hand, unsigned int dwAddr, int nSize, int nRepeats);
U14API(short) U14Poke1401(short hand, unsigned int dwAddr, unsigned int dwValue, int nSize, int nRepeats);
U14API(short) U14Ramp1401(short hand, unsigned int dwAddr, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
U14API(short) U14RampAddr(short hand, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
U14API(short) U14StopDebugLoop(short hand);
U14API(short) U14GetDebugData(short hand, U14LONG *plValue);
U14API(short) U14StartSelfTest(short hand);
U14API(short) U14CheckSelfTest(short hand, U14LONG *pData);
U14API(short) U14TransferFlags(short hand);
U14API(void) U14GetErrorString(short nErr, char *pStr, unsigned short wMax);
U14API(int) U14MonitorRev(short hand);
U14API(void) U14CloseAll(void);
U14API(short) U14WorkingSet(DWORD dwMinKb, DWORD dwMaxKb);
U14API(short) U14WorkingSet(unsigned int dwMinKb, unsigned int dwMaxKb);
U14API(int) U14InitLib(void);
#ifdef __cplusplus
......@@ -285,3 +285,4 @@ U14API(int) U14InitLib(void);
#endif
#endif /* End of ifndef __USE1401_H__ */
此差异已折叠。
此差异已折叠。
......@@ -14,11 +14,6 @@
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _COMEDI_H
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部