Commit cf2e8c54 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "New Drivers:
   - Add STMPE ADC Input driver
   - Add STMicroelectronics STPMIC1 Parent driver
   - Add STMicroelectronics STPMIC1 OnKey Misc driver
   - Add STMicroelectronics STPMIC1 Watchdog driver
   - Add Cirrus Logic Lochnagar Parent driver
   - Add TQ-Systems TQMX86 Parent driver

  New Device Support:
   - Add support for ADC to STMPE

  New (or moved) Functionality:
   - Move Lightbar functionality to its own driver; cros_ec_lightbar
   - Move VBC functionality to its own driver; cros_ec_vbc
   - Move VBC functionality to its own driver; cros_ec_vbc
   - Move DebugFS functionality to its own driver; cros_ec_debugfs
   - Move SYSFS functionality to its own driver; cros_ec_sysfs
   - Add support for input voltage options; tps65218

  Fixes:
   - Use devm_* managed resources; cros_ec
   - Device Tree documentation; stmpe, aspeed-lpc, lochnagar
   - Trivial Clean-ups; stmpe
   - Rip out broken modular code; aat2870-core, adp5520, as3711,
         db8500-prcmu, htc-i2cpld, max8925-core, rc5t583, sta2x11-mfd,
	 syscon, tps65090, tps65910, tps68470 tps80031, wm831x-spi,
	 wm831x-i2c, wm831x-core, wm8350-i2c, wm8350-core, wm8400-core
   - Kconfig fixups; INTEL_SOC_PMIC
   - Improve error path; sm501, sec-core
   - Use struct_size() helper; sm501
   - Constify; at91-usart
   - Use pointers instead of copying data; at91-usart
   - Deliver proper return value; cros_ec_dev
   - Trivial formatting/whitespace; sec-core"

* tag 'mfd-next-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (53 commits)
  mfd: mxs-lradc: Mark expected switch fall-through
  mfd: sec-core: Cleanup formatting to a consistent style
  mfd: tqmx86: IO controller with I2C, Wachdog and GPIO
  mfd: intel-lpss: Move linux/pm.h to the local header
  mfd: cros_ec_dev: Return number of bytes read with CROS_EC_DEV_IOCRDMEM
  mfd: tps68470: Drop unused MODULE_DEVICE_TABLE
  mfd: at91-usart: No need to copy mfd_cell in probe
  mfd: at91-usart: Constify at91_usart_spi_subdev and at91_usart_serial_subdev
  mfd: lochnagar: Add support for the Cirrus Logic Lochnagar
  mfd: lochnagar: Add initial binding documentation
  dt-bindings: mfd: aspeed-lpc: Make parameter optional
  mfd: sec-core: Return gracefully instead of BUG() if device cannot match
  mfd: sm501: Use struct_size() in devm_kzalloc()
  mfd: sm501: Fix potential NULL pointer dereference
  mfd: Kconfig: Fix I2C_DESIGNWARE_PLATFORM dependencies
  mfd: tps65218.c: Add input voltage options
  mfd: wm8400-core: Make it explicitly non-modular
  mfd: wm8350-core: Drop unused module infrastructure from non-modular code
  mfd: wm8350-i2c: Make it explicitly non-modular
  mfd: wm831x-core: Drop unused module infrastructure from non-modular code
  ...
parents 04e03618 d2d833e0
What: /sys/class/chromeos/<ec-device-name>/flashinfo
Date: August 2015
KernelVersion: 4.2
Description:
Show the EC flash information.
What: /sys/class/chromeos/<ec-device-name>/kb_wake_angle
Date: March 2018
KernelVersion: 4.17
Description:
Control the keyboard wake lid angle. Values are between
0 and 360. This file will also show the keyboard wake lid
angle by querying the hardware.
What: /sys/class/chromeos/<ec-device-name>/reboot
Date: August 2015
KernelVersion: 4.2
Description:
Tell the EC to reboot in various ways. Options are:
"cancel": Cancel a pending reboot.
"ro": Jump to RO without rebooting.
"rw": Jump to RW without rebooting.
"cold": Cold reboot.
"disable-jump": Disable jump until next reboot.
"hibernate": Hibernate the EC.
"at-shutdown": Reboot after an AP shutdown.
What: /sys/class/chromeos/<ec-device-name>/version
Date: August 2015
KernelVersion: 4.2
Description:
Show the information about the EC software and hardware.
What: /sys/class/chromeos/<ec-device-name>/lightbar/brightness
Date: August 2015
KernelVersion: 4.2
Description:
Writing to this file adjusts the overall brightness of
the lightbar, separate from any color intensity. The
valid range is 0 (off) to 255 (maximum brightness).
What: /sys/class/chromeos/<ec-device-name>/lightbar/interval_msec
Date: August 2015
KernelVersion: 4.2
Description:
The lightbar is controlled by an embedded controller (EC),
which also manages the keyboard, battery charging, fans,
and other system hardware. To prevent unprivileged users
from interfering with the other EC functions, the rate at
which the lightbar control files can be read or written is
limited.
Reading this file will return the number of milliseconds
that must elapse between accessing any of the lightbar
functions through this interface. Going faster will simply
block until the necessary interval has lapsed. The interval
applies uniformly to all accesses of any kind by any user.
What: /sys/class/chromeos/<ec-device-name>/lightbar/led_rgb
Date: August 2015
KernelVersion: 4.2
Description:
This allows you to control each LED segment. If the
lightbar is already running one of the automatic
sequences, you probably won’t see anything change because
your color setting will be almost immediately replaced.
To get useful results, you should stop the lightbar
sequence first.
The values written to this file are sets of four integers,
indicating LED, RED, GREEN, BLUE. The LED number is 0 to 3
to select a single segment, or 4 to set all four segments
to the same value at once. The RED, GREEN, and BLUE
numbers should be in the range 0 (off) to 255 (maximum).
You can update more than one segment at a time by writing
more than one set of four integers.
What: /sys/class/chromeos/<ec-device-name>/lightbar/program
Date: August 2015
KernelVersion: 4.2
Description:
This allows you to upload and run custom lightbar sequences.
What: /sys/class/chromeos/<ec-device-name>/lightbar/sequence
Date: August 2015
KernelVersion: 4.2
Description:
The Pixel lightbar has a number of built-in sequences
that it displays under various conditions, such as at
power on, shut down, or while running. Reading from this
file displays the current sequence that the lightbar is
displaying. Writing to this file allows you to change the
sequence.
What: /sys/class/chromeos/<ec-device-name>/lightbar/userspace_control
Date: August 2015
KernelVersion: 4.2
Description:
This allows you to take the control of the lightbar. This
prevents the kernel from going through its normal
sequences.
What: /sys/class/chromeos/<ec-device-name>/lightbar/version
Date: August 2015
KernelVersion: 4.2
Description:
Show the information about the lightbar version.
What: /sys/class/chromeos/<ec-device-name>/vbc/vboot_context
Date: October 2015
KernelVersion: 4.4
Description:
Read/write the verified boot context data included on a
small nvram space on some EC implementations.
STMPE ADC driver
----------------
Required properties:
- compatible: "st,stmpe-adc"
Optional properties:
Note that the ADC is shared with the STMPE touchscreen. ADC related settings
have to be done in the mfd.
- st,norequest-mask: bitmask specifying which ADC channels should _not_ be
requestable due to different usage (e.g. touch)
Node name must be stmpe_adc and should be child node of stmpe node to
which it belongs.
Example:
stmpe_adc {
compatible = "st,stmpe-adc";
st,norequest-mask = <0x0F>; /* dont use ADC CH3-0 */
};
STMicroelectronics STPMIC1 Onkey
Required properties:
- compatible = "st,stpmic1-onkey";
- interrupts: interrupt line to use
- interrupt-names = "onkey-falling", "onkey-rising"
onkey-falling: happens when onkey is pressed; IT_PONKEY_F of pmic
onkey-rising: happens when onkey is released; IT_PONKEY_R of pmic
Optional properties:
- st,onkey-clear-cc-flag: onkey is able power on after an
over-current shutdown event.
- st,onkey-pu-inactive: onkey pull up is not active
- power-off-time-sec: Duration in seconds which the key should be kept
pressed for device to power off automatically (from 1 to 16 seconds).
see See Documentation/devicetree/bindings/input/keys.txt
Example:
onkey {
compatible = "st,stpmic1-onkey";
interrupt-parent = <&pmic>;
interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
interrupt-names = "onkey-falling", "onkey-rising";
power-off-time-sec = <10>;
};
...@@ -5,39 +5,105 @@ Required properties: ...@@ -5,39 +5,105 @@ Required properties:
- compatible: "st,stmpe-ts" - compatible: "st,stmpe-ts"
Optional properties: Optional properties:
- st,sample-time: ADC converstion time in number of clock. (0 -> 36 clocks, 1 -> - st,ave-ctrl : Sample average control
44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, 4 -> 80 clocks, 5 -> 96 clocks, 6 0 -> 1 sample
-> 144 clocks), recommended is 4. 1 -> 2 samples
- st,mod-12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC) 2 -> 4 samples
- st,ref-sel: ADC reference source (0 -> internal reference, 1 -> external 3 -> 8 samples
reference) - st,touch-det-delay : Touch detect interrupt delay (recommended is 3)
- st,adc-freq: ADC Clock speed (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz) 0 -> 10 us
- st,ave-ctrl: Sample average control (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 1 -> 50 us
samples, 3 -> 8 samples) 2 -> 100 us
- st,touch-det-delay: Touch detect interrupt delay (0 -> 10 us, 1 -> 50 us, 2 -> 3 -> 500 us
100 us, 3 -> 500 us, 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) recommended 4 -> 1 ms
is 3 5 -> 5 ms
- st,settling: Panel driver settling time (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 6 -> 10 ms
-> 1 ms, 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) recommended is 2 7 -> 50 ms
- st,fraction-z: Length of the fractional part in z (fraction-z ([0..7]) = Count of - st,settling : Panel driver settling time (recommended is 2)
the fractional part) recommended is 7 0 -> 10 us
- st,i-drive: current limit value of the touchscreen drivers (0 -> 20 mA typical 35 1 -> 100 us
mA max, 1 -> 50 mA typical 80 mA max) 2 -> 500 us
3 -> 1 ms
4 -> 5 ms
5 -> 10 ms
6 -> 50 ms
7 -> 100 ms
- st,fraction-z : Length of the fractional part in z (recommended is 7)
(fraction-z ([0..7]) = Count of the fractional part)
- st,i-drive : current limit value of the touchscreen drivers
0 -> 20 mA (typical 35mA max)
1 -> 50 mA (typical 80 mA max)
Optional properties common with MFD (deprecated):
- st,sample-time : ADC conversion time in number of clock.
0 -> 36 clocks
1 -> 44 clocks
2 -> 56 clocks
3 -> 64 clocks
4 -> 80 clocks (recommended)
5 -> 96 clocks
6 -> 124 clocks
- st,mod-12b : ADC Bit mode
0 -> 10bit ADC
1 -> 12bit ADC
- st,ref-sel : ADC reference source
0 -> internal
1 -> external
- st,adc-freq : ADC Clock speed
0 -> 1.625 MHz
1 -> 3.25 MHz
2 || 3 -> 6.5 MHz
Node name must be stmpe_touchscreen and should be child node of stmpe node to Node name must be stmpe_touchscreen and should be child node of stmpe node to
which it belongs. which it belongs.
Note that common ADC settings of stmpe_touchscreen (child) will take precedence
over the settings done in MFD.
Example: Example:
stmpe811@41 {
compatible = "st,stmpe811";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_touch_int>;
#address-cells = <1>;
#size-cells = <0>;
reg = <0x41>;
interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpio4>;
interrupt-controller;
id = <0>;
blocks = <0x5>;
irq-trigger = <0x1>;
/* Common ADC settings */
/* 3.25 MHz ADC clock speed */
st,adc-freq = <1>;
/* 12-bit ADC */
st,mod-12b = <1>;
/* internal ADC reference */
st,ref-sel = <0>;
/* ADC converstion time: 80 clocks */
st,sample-time = <4>;
stmpe_touchscreen { stmpe_touchscreen {
compatible = "st,stmpe-ts"; compatible = "st,stmpe-ts";
st,sample-time = <4>; reg = <0>;
st,mod-12b = <1>; /* 8 sample average control */
st,ref-sel = <0>; st,ave-ctrl = <3>;
st,adc-freq = <1>; /* 5 ms touch detect interrupt delay */
st,ave-ctrl = <1>; st,touch-det-delay = <5>;
st,touch-det-delay = <2>; /* 1 ms panel driver settling time */
st,settling = <2>; st,settling = <3>;
/* 7 length fractional part in z */
st,fraction-z = <7>; st,fraction-z = <7>;
/*
* 50 mA typical 80 mA max touchscreen drivers
* current limit value
*/
st,i-drive = <1>; st,i-drive = <1>;
}; };
stmpe_adc {
compatible = "st,stmpe-adc";
st,norequest-mask = <0x0F>;
};
};
...@@ -135,6 +135,8 @@ Required properties: ...@@ -135,6 +135,8 @@ Required properties:
- clocks: contains a phandle to the syscon node describing the clocks. - clocks: contains a phandle to the syscon node describing the clocks.
There should then be one cell representing the clock to use There should then be one cell representing the clock to use
Optional properties:
- memory-region: A phandle to a reserved_memory region to be used for the LPC - memory-region: A phandle to a reserved_memory region to be used for the LPC
to AHB mapping to AHB mapping
......
Cirrus Logic Lochnagar Audio Development Board
Lochnagar is an evaluation and development board for Cirrus Logic
Smart CODEC and Amp devices. It allows the connection of most Cirrus
Logic devices on mini-cards, as well as allowing connection of
various application processor systems to provide a full evaluation
platform. Audio system topology, clocking and power can all be
controlled through the Lochnagar, allowing the device under test
to be used in a variety of possible use cases.
Also see these documents for generic binding information:
[1] GPIO : ../gpio/gpio.txt
And these for relevant defines:
[2] include/dt-bindings/pinctrl/lochnagar.h
[3] include/dt-bindings/clock/lochnagar.h
And these documents for the required sub-node binding details:
[4] Clock: ../clock/cirrus,lochnagar.txt
[5] Pinctrl: ../pinctrl/cirrus,lochnagar.txt
[6] Regulator: ../regulator/cirrus,lochnagar.txt
Required properties:
- compatible : One of the following strings:
"cirrus,lochnagar1"
"cirrus,lochnagar2"
- reg : I2C slave address
- reset-gpios : Reset line to the Lochnagar, see [1].
Required sub-nodes:
- lochnagar-clk : Binding for the clocking components, see [4].
- lochnagar-pinctrl : Binding for the pin control components, see [5].
Optional sub-nodes:
- Bindings for the regulator components, see [6]. Only available on
Lochnagar 2.
Optional properties:
- present-gpios : Host present line, indicating the presence of a
host system, see [1]. This can be omitted if the present line is
tied in hardware.
Example:
lochnagar: lochnagar@22 {
compatible = "cirrus,lochnagar2";
reg = <0x22>;
reset-gpios = <&gpio0 55 0>;
present-gpios = <&gpio0 60 0>;
lochnagar-clk {
compatible = "cirrus,lochnagar2-clk";
...
};
lochnagar-pinctrl {
compatible = "cirrus,lochnagar-pinctrl";
...
};
};
* STMicroelectronics STPMIC1 Power Management IC
Required properties:
- compatible: : "st,stpmic1"
- reg: : The I2C slave address for the STPMIC1 chip.
- interrupts: : The interrupt line the device is connected to.
- #interrupt-cells: : Should be 1.
- interrupt-controller: : Marks the device node as an interrupt controller.
Interrupt numbers are defined at
dt-bindings/mfd/st,stpmic1.h.
STPMIC1 consists in a varied group of sub-devices.
Each sub-device binding is be described in own documentation file.
Device Description
------ ------------
st,stpmic1-onkey : Power on key, see ../input/st,stpmic1-onkey.txt
st,stpmic1-regulators : Regulators, see ../regulator/st,stpmic1-regulator.txt
st,stpmic1-wdt : Watchdog, see ../watchdog/st,stpmic1-wdt.txt
Example:
#include <dt-bindings/mfd/st,stpmic1.h>
pmic: pmic@33 {
compatible = "st,stpmic1";
reg = <0x33>;
interrupt-parent = <&gpioa>;
interrupts = <0 2>;
interrupt-controller;
#interrupt-cells = <2>;
onkey {
compatible = "st,stpmic1-onkey";
interrupts = <IT_PONKEY_F 0>,<IT_PONKEY_R 1>;
interrupt-names = "onkey-falling", "onkey-rising";
power-off-time-sec = <10>;
};
watchdog {
compatible = "st,stpmic1-wdt";
};
regulators {
compatible = "st,stpmic1-regulators";
vdd_core: buck1 {
regulator-name = "vdd_core";
regulator-boot-on;
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1200000>;
};
vdd: buck3 {
regulator-name = "vdd";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-pull-down;
};
};
...@@ -4,15 +4,29 @@ STMPE is an MFD device which may expose the following inbuilt devices: gpio, ...@@ -4,15 +4,29 @@ STMPE is an MFD device which may expose the following inbuilt devices: gpio,
keypad, touchscreen, adc, pwm, rotator. keypad, touchscreen, adc, pwm, rotator.
Required properties: Required properties:
- compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]" - compatible : "st,stmpe[610|801|811|1600|1601|2401|2403]"
- reg : I2C/SPI address of the device - reg : I2C/SPI address of the device
Optional properties: Optional properties:
- interrupts : The interrupt outputs from the controller - interrupts : The interrupt outputs from the controller
- interrupt-controller : Marks the device node as an interrupt controller - interrupt-controller : Marks the device node as an interrupt controller
- wakeup-source : Marks the input device as wakable - wakeup-source : Marks the input device as wakable
- st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024 - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
- irq-gpio : If present, which GPIO to use for event IRQ - irq-gpio : If present, which GPIO to use for event IRQ
Optional properties for devices with touch and ADC (STMPE811|STMPE610):
- st,sample-time : ADC conversion time in number of clock.
0 -> 36 clocks 4 -> 80 clocks (recommended)
1 -> 44 clocks 5 -> 96 clocks
2 -> 56 clocks 6 -> 124 clocks
3 -> 64 clocks
- st,mod-12b : ADC Bit mode
0 -> 10bit ADC 1 -> 12bit ADC
- st,ref-sel : ADC reference source
0 -> internal 1 -> external
- st,adc-freq : ADC Clock speed
0 -> 1.625 MHz 2 || 3 -> 6.5 MHz
1 -> 3.25 MHz
Example: Example:
......
STMicroelectronics STPMIC1 Watchdog
Required properties:
- compatible : should be "st,stpmic1-wdt"
Example:
watchdog {
compatible = "st,stpmic1-wdt";
};
...@@ -3777,6 +3777,23 @@ L: netdev@vger.kernel.org ...@@ -3777,6 +3777,23 @@ L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/ethernet/cirrus/ep93xx_eth.c F: drivers/net/ethernet/cirrus/ep93xx_eth.c
CIRRUS LOGIC LOCHNAGAR DRIVER
M: Charles Keepax <ckeepax@opensource.cirrus.com>
M: Richard Fitzgerald <rf@opensource.cirrus.com>
L: patches@opensource.cirrus.com
S: Supported
F: drivers/clk/clk-lochnagar.c
F: drivers/mfd/lochnagar-i2c.c
F: drivers/pinctrl/cirrus/pinctrl-lochnagar.c
F: drivers/regulator/lochnagar-regulator.c
F: include/dt-bindings/clk/lochnagar.h
F: include/dt-bindings/pinctrl/lochnagar.h
F: include/linux/mfd/lochnagar*
F: Documentation/devicetree/bindings/mfd/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/clock/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/pinctrl/cirrus,lochnagar.txt
F: Documentation/devicetree/bindings/regulator/cirrus,lochnagar.txt
CISCO FCOE HBA DRIVER CISCO FCOE HBA DRIVER
M: Satish Kharat <satishkh@cisco.com> M: Satish Kharat <satishkh@cisco.com>
M: Sesidhar Baddela <sebaddel@cisco.com> M: Sesidhar Baddela <sebaddel@cisco.com>
......
...@@ -817,6 +817,13 @@ config STM32_DFSDM_ADC ...@@ -817,6 +817,13 @@ config STM32_DFSDM_ADC
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called stm32-dfsdm-adc. will be called stm32-dfsdm-adc.
config STMPE_ADC
tristate "STMicroelectronics STMPE ADC driver"
depends on OF && MFD_STMPE
help
Say yes here to build support for ST Microelectronics STMPE
built-in ADC block (stmpe811).
config STX104 config STX104
tristate "Apex Embedded Systems STX104 driver" tristate "Apex Embedded Systems STX104 driver"
depends on PC104 && X86 depends on PC104 && X86
......
...@@ -77,6 +77,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o ...@@ -77,6 +77,7 @@ obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
obj-$(CONFIG_STM32_ADC) += stm32-adc.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o
obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
obj-$(CONFIG_STMPE_ADC) += stmpe-adc.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* STMicroelectronics STMPE811 IIO ADC Driver
*
* 4 channel, 10/12-bit ADC
*
* Copyright (C) 2013-2018 Toradex AG <stefan.agner@toradex.com>
*/
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/stmpe.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#define STMPE_REG_INT_STA 0x0B
#define STMPE_REG_ADC_INT_EN 0x0E
#define STMPE_REG_ADC_INT_STA 0x0F
#define STMPE_REG_ADC_CTRL1 0x20
#define STMPE_REG_ADC_CTRL2 0x21
#define STMPE_REG_ADC_CAPT 0x22
#define STMPE_REG_ADC_DATA_CH(channel) (0x30 + 2 * (channel))
#define STMPE_REG_TEMP_CTRL 0x60
#define STMPE_TEMP_CTRL_ENABLE BIT(0)
#define STMPE_TEMP_CTRL_ACQ BIT(1)
#define STMPE_TEMP_CTRL_THRES_EN BIT(3)
#define STMPE_START_ONE_TEMP_CONV (STMPE_TEMP_CTRL_ENABLE | \
STMPE_TEMP_CTRL_ACQ | \
STMPE_TEMP_CTRL_THRES_EN)
#define STMPE_REG_TEMP_DATA 0x61
#define STMPE_REG_TEMP_TH 0x63
#define STMPE_ADC_LAST_NR 7
#define STMPE_TEMP_CHANNEL (STMPE_ADC_LAST_NR + 1)
#define STMPE_ADC_CH(channel) ((1 << (channel)) & 0xff)
#define STMPE_ADC_TIMEOUT msecs_to_jiffies(1000)
struct stmpe_adc {
struct stmpe *stmpe;
struct clk *clk;
struct device *dev;
struct mutex lock;
/* We are allocating plus one for the temperature channel */
struct iio_chan_spec stmpe_adc_iio_channels[STMPE_ADC_LAST_NR + 2];
struct completion completion;
u8 channel;
u32 value;
};
static int stmpe_read_voltage(struct stmpe_adc *info,
struct iio_chan_spec const *chan, int *val)
{
long ret;
mutex_lock(&info->lock);
info->channel = (u8)chan->channel;
if (info->channel > STMPE_ADC_LAST_NR) {
mutex_unlock(&info->lock);
return -EINVAL;
}
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
STMPE_ADC_CH(info->channel));
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
STMPE_ADC_CH(info->channel));
*val = info->value;
ret = wait_for_completion_interruptible_timeout
(&info->completion, STMPE_ADC_TIMEOUT);
if (ret <= 0) {
mutex_unlock(&info->lock);
if (ret == 0)
return -ETIMEDOUT;
else
return ret;
}
*val = info->value;
mutex_unlock(&info->lock);
return 0;
}
static int stmpe_read_temp(struct stmpe_adc *info,
struct iio_chan_spec const *chan, int *val)
{
long ret;
mutex_lock(&info->lock);
info->channel = (u8)chan->channel;
if (info->channel != STMPE_TEMP_CHANNEL) {
mutex_unlock(&info->lock);
return -EINVAL;
}
stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
STMPE_START_ONE_TEMP_CONV);
ret = wait_for_completion_interruptible_timeout
(&info->completion, STMPE_ADC_TIMEOUT);
if (ret <= 0) {
mutex_unlock(&info->lock);
if (ret == 0)
return -ETIMEDOUT;
else
return ret;
}
/*
* absolute temp = +V3.3 * value /7.51 [K]
* scale to [milli °C]
*/
*val = ((449960l * info->value) / 1024l) - 273150;
mutex_unlock(&info->lock);
return 0;
}
static int stmpe_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long mask)
{
struct stmpe_adc *info = iio_priv(indio_dev);
long ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_VOLTAGE:
ret = stmpe_read_voltage(info, chan, val);
break;
case IIO_TEMP:
ret = stmpe_read_temp(info, chan, val);
break;
default:
return -EINVAL;
}
if (ret < 0)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 3300;
*val2 = info->stmpe->mod_12b ? 12 : 10;
return IIO_VAL_FRACTIONAL_LOG2;
default:
break;
}
return -EINVAL;
}
static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
{
struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
u16 data;
if (info->channel > STMPE_TEMP_CHANNEL)
return IRQ_NONE;
if (info->channel <= STMPE_ADC_LAST_NR) {
int int_sta;
int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
/* Is the interrupt relevant */
if (!(int_sta & STMPE_ADC_CH(info->channel)))
return IRQ_NONE;
/* Read value */
stmpe_block_read(info->stmpe,
STMPE_REG_ADC_DATA_CH(info->channel), 2, (u8 *) &data);
stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
} else if (info->channel == STMPE_TEMP_CHANNEL) {
/* Read value */
stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2,
(u8 *) &data);
}
info->value = (u32) be16_to_cpu(data);
complete(&info->completion);
return IRQ_HANDLED;
}
static const struct iio_info stmpe_adc_iio_info = {
.read_raw = &stmpe_read_raw,
};
static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan)
{
ics->type = IIO_VOLTAGE;
ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
ics->indexed = 1;
ics->channel = chan;
}
static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan)
{
ics->type = IIO_TEMP;
ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
ics->indexed = 1;
ics->channel = chan;
}
static int stmpe_adc_init_hw(struct stmpe_adc *adc)
{
int ret;
struct stmpe *stmpe = adc->stmpe;
ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC);
if (ret) {
dev_err(stmpe->dev, "Could not enable clock for ADC\n");
return ret;
}
ret = stmpe811_adc_common_init(stmpe);
if (ret) {
stmpe_disable(stmpe, STMPE_BLOCK_ADC);
return ret;
}
/* use temp irq for each conversion completion */
stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
return 0;
}
static int stmpe_adc_probe(struct platform_device *pdev)
{
struct iio_dev *indio_dev;
struct stmpe_adc *info;
struct device_node *np;
u32 norequest_mask = 0;
int irq_temp, irq_adc;
int num_chan = 0;
int i = 0;
int ret;
irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC");
if (irq_adc < 0)
return irq_adc;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc));
if (!indio_dev) {
dev_err(&pdev->dev, "failed allocating iio device\n");
return -ENOMEM;
}
info = iio_priv(indio_dev);
mutex_init(&info->lock);
init_completion(&info->completion);
ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL,
stmpe_adc_isr, IRQF_ONESHOT,
"stmpe-adc", info);
if (ret < 0) {
dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
irq_adc);
return ret;
}
irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
if (irq_temp >= 0) {
ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL,
stmpe_adc_isr, IRQF_ONESHOT,
"stmpe-adc", info);
if (ret < 0)
dev_warn(&pdev->dev, "failed requesting irq for"
" temp sensor, irq = %d\n", irq_temp);
}
platform_set_drvdata(pdev, indio_dev);
indio_dev->name = dev_name(&pdev->dev);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &stmpe_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
info->stmpe = dev_get_drvdata(pdev->dev.parent);
np = pdev->dev.of_node;
if (!np)
dev_err(&pdev->dev, "no device tree node found\n");
of_property_read_u32(np, "st,norequest-mask", &norequest_mask);
for_each_clear_bit(i, (unsigned long *) &norequest_mask,
(STMPE_ADC_LAST_NR + 1)) {
stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i);
num_chan++;
}
stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i);
num_chan++;
indio_dev->channels = info->stmpe_adc_iio_channels;
indio_dev->num_channels = num_chan;
ret = stmpe_adc_init_hw(info);
if (ret)
return ret;
return devm_iio_device_register(&pdev->dev, indio_dev);
}
static int __maybe_unused stmpe_adc_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct stmpe_adc *info = iio_priv(indio_dev);
stmpe_adc_init_hw(info);
return 0;
}
static SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
static struct platform_driver stmpe_adc_driver = {
.probe = stmpe_adc_probe,
.driver = {
.name = "stmpe-adc",
.pm = &stmpe_adc_pm_ops,
},
};
module_platform_driver(stmpe_adc_driver);
MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
MODULE_DESCRIPTION("STMPEXXX ADC driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:stmpe-adc");
...@@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA ...@@ -851,4 +851,15 @@ config INPUT_SC27XX_VIBRA
To compile this driver as a module, choose M here. The module will To compile this driver as a module, choose M here. The module will
be called sc27xx_vibra. be called sc27xx_vibra.
config INPUT_STPMIC1_ONKEY
tristate "STPMIC1 PMIC Onkey support"
depends on MFD_STPMIC1
help
Say Y to enable support of onkey embedded into STPMIC1 PMIC. onkey
can be used to wakeup from low power modes and force a shut-down on
long press.
To compile this driver as a module, choose M here: the
module will be called stpmic1_onkey.
endif endif
...@@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o ...@@ -71,6 +71,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_STPMIC1_ONKEY) += stpmic1_onkey.o
obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
...@@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o ...@@ -81,3 +82,4 @@ obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o
obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o obj-$(CONFIG_INPUT_IDEAPAD_SLIDEBAR) += ideapad_slidebar.o
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) STMicroelectronics 2018
// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/mfd/stpmic1.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
/**
* struct stpmic1_onkey - OnKey data
* @input_dev: pointer to input device
* @irq_falling: irq that we are hooked on to
* @irq_rising: irq that we are hooked on to
*/
struct stpmic1_onkey {
struct input_dev *input_dev;
int irq_falling;
int irq_rising;
};
static irqreturn_t onkey_falling_irq(int irq, void *ponkey)
{
struct stpmic1_onkey *onkey = ponkey;
struct input_dev *input_dev = onkey->input_dev;
input_report_key(input_dev, KEY_POWER, 1);
pm_wakeup_event(input_dev->dev.parent, 0);
input_sync(input_dev);
return IRQ_HANDLED;
}
static irqreturn_t onkey_rising_irq(int irq, void *ponkey)
{
struct stpmic1_onkey *onkey = ponkey;
struct input_dev *input_dev = onkey->input_dev;
input_report_key(input_dev, KEY_POWER, 0);
pm_wakeup_event(input_dev->dev.parent, 0);
input_sync(input_dev);
return IRQ_HANDLED;
}
static int stpmic1_onkey_probe(struct platform_device *pdev)
{
struct stpmic1 *pmic = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct input_dev *input_dev;
struct stpmic1_onkey *onkey;
unsigned int val, reg = 0;
int error;
onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL);
if (!onkey)
return -ENOMEM;
onkey->irq_falling = platform_get_irq_byname(pdev, "onkey-falling");
if (onkey->irq_falling < 0) {
dev_err(dev, "failed: request IRQ onkey-falling %d\n",
onkey->irq_falling);
return onkey->irq_falling;
}
onkey->irq_rising = platform_get_irq_byname(pdev, "onkey-rising");
if (onkey->irq_rising < 0) {
dev_err(dev, "failed: request IRQ onkey-rising %d\n",
onkey->irq_rising);
return onkey->irq_rising;
}
if (!device_property_read_u32(dev, "power-off-time-sec", &val)) {
if (val > 0 && val <= 16) {
dev_dbg(dev, "power-off-time=%d seconds\n", val);
reg |= PONKEY_PWR_OFF;
reg |= ((16 - val) & PONKEY_TURNOFF_TIMER_MASK);
} else {
dev_err(dev, "power-off-time-sec out of range\n");
return -EINVAL;
}
}
if (device_property_present(dev, "st,onkey-clear-cc-flag"))
reg |= PONKEY_CC_FLAG_CLEAR;
error = regmap_update_bits(pmic->regmap, PKEY_TURNOFF_CR,
PONKEY_TURNOFF_MASK, reg);
if (error) {
dev_err(dev, "PKEY_TURNOFF_CR write failed: %d\n", error);
return error;
}
if (device_property_present(dev, "st,onkey-pu-inactive")) {
error = regmap_update_bits(pmic->regmap, PADS_PULL_CR,
PONKEY_PU_INACTIVE,
PONKEY_PU_INACTIVE);
if (error) {
dev_err(dev, "ONKEY Pads configuration failed: %d\n",
error);
return error;
}
}
input_dev = devm_input_allocate_device(dev);
if (!input_dev) {
dev_err(dev, "Can't allocate Pwr Onkey Input Device\n");
return -ENOMEM;
}
input_dev->name = "pmic_onkey";
input_dev->phys = "pmic_onkey/input0";
input_set_capability(input_dev, EV_KEY, KEY_POWER);
onkey->input_dev = input_dev;
/* interrupt is nested in a thread */
error = devm_request_threaded_irq(dev, onkey->irq_falling, NULL,
onkey_falling_irq, IRQF_ONESHOT,
dev_name(dev), onkey);
if (error) {
dev_err(dev, "Can't get IRQ Onkey Falling: %d\n", error);
return error;
}
error = devm_request_threaded_irq(dev, onkey->irq_rising, NULL,
onkey_rising_irq, IRQF_ONESHOT,
dev_name(dev), onkey);
if (error) {
dev_err(dev, "Can't get IRQ Onkey Rising: %d\n", error);
return error;
}
error = input_register_device(input_dev);
if (error) {
dev_err(dev, "Can't register power button: %d\n", error);
return error;
}
platform_set_drvdata(pdev, onkey);
device_init_wakeup(dev, true);
return 0;
}
static int __maybe_unused stpmic1_onkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
if (device_may_wakeup(dev)) {
enable_irq_wake(onkey->irq_falling);
enable_irq_wake(onkey->irq_rising);
}
return 0;
}
static int __maybe_unused stpmic1_onkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct stpmic1_onkey *onkey = platform_get_drvdata(pdev);
if (device_may_wakeup(dev)) {
disable_irq_wake(onkey->irq_falling);
disable_irq_wake(onkey->irq_rising);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm,
stpmic1_onkey_suspend,
stpmic1_onkey_resume);
static const struct of_device_id of_stpmic1_onkey_match[] = {
{ .compatible = "st,stpmic1-onkey" },
{ },
};
MODULE_DEVICE_TABLE(of, of_stpmic1_onkey_match);
static struct platform_driver stpmic1_onkey_driver = {
.probe = stpmic1_onkey_probe,
.driver = {
.name = "stpmic1_onkey",
.of_match_table = of_match_ptr(of_stpmic1_onkey_match),
.pm = &stpmic1_onkey_pm,
},
};
module_platform_driver(stpmic1_onkey_driver);
MODULE_DESCRIPTION("Onkey driver for STPMIC1");
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
MODULE_LICENSE("GPL v2");
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
* with touchscreen controller * with touchscreen controller
*/ */
#define STMPE_REG_INT_STA 0x0B #define STMPE_REG_INT_STA 0x0B
#define STMPE_REG_ADC_CTRL1 0x20
#define STMPE_REG_ADC_CTRL2 0x21
#define STMPE_REG_TSC_CTRL 0x40 #define STMPE_REG_TSC_CTRL 0x40
#define STMPE_REG_TSC_CFG 0x41 #define STMPE_REG_TSC_CFG 0x41
#define STMPE_REG_FIFO_TH 0x4A #define STMPE_REG_FIFO_TH 0x4A
...@@ -49,17 +47,6 @@ ...@@ -49,17 +47,6 @@
#define STMPE_IRQ_TOUCH_DET 0 #define STMPE_IRQ_TOUCH_DET 0
#define SAMPLE_TIME(x) ((x & 0xf) << 4)
#define MOD_12B(x) ((x & 0x1) << 3)
#define REF_SEL(x) ((x & 0x1) << 1)
#define ADC_FREQ(x) (x & 0x3)
#define AVE_CTRL(x) ((x & 0x3) << 6)
#define DET_DELAY(x) ((x & 0x7) << 3)
#define SETTLING(x) (x & 0x7)
#define FRACTION_Z(x) (x & 0x7)
#define I_DRIVE(x) (x & 0x1)
#define OP_MODE(x) ((x & 0x7) << 1)
#define STMPE_TS_NAME "stmpe-ts" #define STMPE_TS_NAME "stmpe-ts"
#define XY_MASK 0xfff #define XY_MASK 0xfff
...@@ -69,15 +56,6 @@ ...@@ -69,15 +56,6 @@
* @idev: registered input device * @idev: registered input device
* @work: a work item used to scan the device * @work: a work item used to scan the device
* @dev: a pointer back to the MFD cell struct device* * @dev: a pointer back to the MFD cell struct device*
* @sample_time: ADC converstion time in number of clock.
* (0 -> 36 clocks, 1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks,
* 4 -> 80 clocks, 5 -> 96 clocks, 6 -> 144 clocks),
* recommended is 4.
* @mod_12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
* @ref_sel: ADC reference source
* (0 -> internal reference, 1 -> external reference)
* @adc_freq: ADC Clock speed
* (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
* @ave_ctrl: Sample average control * @ave_ctrl: Sample average control
* (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples) * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
* @touch_det_delay: Touch detect interrupt delay * @touch_det_delay: Touch detect interrupt delay
...@@ -99,10 +77,6 @@ struct stmpe_touch { ...@@ -99,10 +77,6 @@ struct stmpe_touch {
struct input_dev *idev; struct input_dev *idev;
struct delayed_work work; struct delayed_work work;
struct device *dev; struct device *dev;
u8 sample_time;
u8 mod_12b;
u8 ref_sel;
u8 adc_freq;
u8 ave_ctrl; u8 ave_ctrl;
u8 touch_det_delay; u8 touch_det_delay;
u8 settling; u8 settling;
...@@ -203,7 +177,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) ...@@ -203,7 +177,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data)
static int stmpe_init_hw(struct stmpe_touch *ts) static int stmpe_init_hw(struct stmpe_touch *ts)
{ {
int ret; int ret;
u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; u8 tsc_cfg, tsc_cfg_mask;
struct stmpe *stmpe = ts->stmpe; struct stmpe *stmpe = ts->stmpe;
struct device *dev = ts->dev; struct device *dev = ts->dev;
...@@ -213,27 +187,17 @@ static int stmpe_init_hw(struct stmpe_touch *ts) ...@@ -213,27 +187,17 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
return ret; return ret;
} }
adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) | ret = stmpe811_adc_common_init(stmpe);
REF_SEL(ts->ref_sel);
adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
adc_ctrl1_mask, adc_ctrl1);
if (ret) {
dev_err(dev, "Could not setup ADC\n");
return ret;
}
ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
if (ret) { if (ret) {
dev_err(dev, "Could not setup ADC\n"); stmpe_disable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
return ret; return ret;
} }
tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) | tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) |
SETTLING(ts->settling); STMPE_DET_DELAY(ts->touch_det_delay) |
tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff); STMPE_SETTLING(ts->settling);
tsc_cfg_mask = STMPE_AVE_CTRL(0xff) | STMPE_DET_DELAY(0xff) |
STMPE_SETTLING(0xff);
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg); ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
if (ret) { if (ret) {
...@@ -242,14 +206,14 @@ static int stmpe_init_hw(struct stmpe_touch *ts) ...@@ -242,14 +206,14 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
} }
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z, ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z)); STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z));
if (ret) { if (ret) {
dev_err(dev, "Could not config touch\n"); dev_err(dev, "Could not config touch\n");
return ret; return ret;
} }
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE, ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
I_DRIVE(0xff), I_DRIVE(ts->i_drive)); STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive));
if (ret) { if (ret) {
dev_err(dev, "Could not config touch\n"); dev_err(dev, "Could not config touch\n");
return ret; return ret;
...@@ -263,7 +227,7 @@ static int stmpe_init_hw(struct stmpe_touch *ts) ...@@ -263,7 +227,7 @@ static int stmpe_init_hw(struct stmpe_touch *ts)
} }
ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL, ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
OP_MODE(0xff), OP_MODE(OP_MOD_XYZ)); STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ));
if (ret) { if (ret) {
dev_err(dev, "Could not set mode\n"); dev_err(dev, "Could not set mode\n");
return ret; return ret;
...@@ -303,13 +267,13 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev, ...@@ -303,13 +267,13 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev,
if (np) { if (np) {
if (!of_property_read_u32(np, "st,sample-time", &val)) if (!of_property_read_u32(np, "st,sample-time", &val))
ts->sample_time = val; ts->stmpe->sample_time = val;
if (!of_property_read_u32(np, "st,mod-12b", &val)) if (!of_property_read_u32(np, "st,mod-12b", &val))
ts->mod_12b = val; ts->stmpe->mod_12b = val;
if (!of_property_read_u32(np, "st,ref-sel", &val)) if (!of_property_read_u32(np, "st,ref-sel", &val))
ts->ref_sel = val; ts->stmpe->ref_sel = val;
if (!of_property_read_u32(np, "st,adc-freq", &val)) if (!of_property_read_u32(np, "st,adc-freq", &val))
ts->adc_freq = val; ts->stmpe->adc_freq = val;
if (!of_property_read_u32(np, "st,ave-ctrl", &val)) if (!of_property_read_u32(np, "st,ave-ctrl", &val))
ts->ave_ctrl = val; ts->ave_ctrl = val;
if (!of_property_read_u32(np, "st,touch-det-delay", &val)) if (!of_property_read_u32(np, "st,touch-det-delay", &val))
......
...@@ -215,7 +215,6 @@ config MFD_CROS_EC ...@@ -215,7 +215,6 @@ config MFD_CROS_EC
config MFD_CROS_EC_CHARDEV config MFD_CROS_EC_CHARDEV
tristate "Chrome OS Embedded Controller userspace device interface" tristate "Chrome OS Embedded Controller userspace device interface"
depends on MFD_CROS_EC depends on MFD_CROS_EC
select CROS_EC_CTL
---help--- ---help---
This driver adds support to talk with the ChromeOS EC from userspace. This driver adds support to talk with the ChromeOS EC from userspace.
...@@ -519,10 +518,10 @@ config INTEL_SOC_PMIC ...@@ -519,10 +518,10 @@ config INTEL_SOC_PMIC
bool "Support for Crystal Cove PMIC" bool "Support for Crystal Cove PMIC"
depends on ACPI && HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK depends on ACPI && HAS_IOMEM && I2C=y && GPIOLIB && COMMON_CLK
depends on X86 || COMPILE_TEST depends on X86 || COMPILE_TEST
depends on I2C_DESIGNWARE_PLATFORM=y
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ select REGMAP_IRQ
select I2C_DESIGNWARE_PLATFORM
help help
Select this option to enable support for Crystal Cove PMIC Select this option to enable support for Crystal Cove PMIC
on some Intel SoC systems. The PMIC provides ADC, GPIO, on some Intel SoC systems. The PMIC provides ADC, GPIO,
...@@ -548,10 +547,10 @@ config INTEL_SOC_PMIC_CHTWC ...@@ -548,10 +547,10 @@ config INTEL_SOC_PMIC_CHTWC
bool "Support for Intel Cherry Trail Whiskey Cove PMIC" bool "Support for Intel Cherry Trail Whiskey Cove PMIC"
depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK
depends on X86 || COMPILE_TEST depends on X86 || COMPILE_TEST
depends on I2C_DESIGNWARE_PLATFORM=y
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ select REGMAP_IRQ
select I2C_DESIGNWARE_PLATFORM
help help
Select this option to enable support for the Intel Cherry Trail Select this option to enable support for the Intel Cherry Trail
Whiskey Cove PMIC found on some Intel Cherry Trail systems. Whiskey Cove PMIC found on some Intel Cherry Trail systems.
...@@ -1205,7 +1204,7 @@ config MFD_STMPE ...@@ -1205,7 +1204,7 @@ config MFD_STMPE
Currently supported devices are: Currently supported devices are:
STMPE811: GPIO, Touchscreen STMPE811: GPIO, Touchscreen, ADC
STMPE1601: GPIO, Keypad STMPE1601: GPIO, Keypad
STMPE1801: GPIO, Keypad STMPE1801: GPIO, Keypad
STMPE2401: GPIO, Keypad STMPE2401: GPIO, Keypad
...@@ -1218,6 +1217,7 @@ config MFD_STMPE ...@@ -1218,6 +1217,7 @@ config MFD_STMPE
GPIO: stmpe-gpio GPIO: stmpe-gpio
Keypad: stmpe-keypad Keypad: stmpe-keypad
Touchscreen: stmpe-ts Touchscreen: stmpe-ts
ADC: stmpe-adc
menu "STMicroelectronics STMPE Interface Drivers" menu "STMicroelectronics STMPE Interface Drivers"
depends on MFD_STMPE depends on MFD_STMPE
...@@ -1420,9 +1420,9 @@ config MFD_TPS65217 ...@@ -1420,9 +1420,9 @@ config MFD_TPS65217
config MFD_TPS68470 config MFD_TPS68470
bool "TI TPS68470 Power Management / LED chips" bool "TI TPS68470 Power Management / LED chips"
depends on ACPI && PCI && I2C=y depends on ACPI && PCI && I2C=y
depends on I2C_DESIGNWARE_PLATFORM=y
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select I2C_DESIGNWARE_PLATFORM
help help
If you say yes here you get support for the TPS68470 series of If you say yes here you get support for the TPS68470 series of
Power Management / LED chips. Power Management / LED chips.
...@@ -1677,6 +1677,14 @@ config MFD_TC6393XB ...@@ -1677,6 +1677,14 @@ config MFD_TC6393XB
help help
Support for Toshiba Mobile IO Controller TC6393XB Support for Toshiba Mobile IO Controller TC6393XB
config MFD_TQMX86
tristate "TQ-Systems IO controller TQMX86"
select MFD_CORE
help
Say yes here to enable support for various functions of the
TQ-Systems IO controller and watchdog device, found on their
ComExpress CPU modules.
config MFD_VX855 config MFD_VX855
tristate "VIA VX855/VX875 integrated south bridge" tristate "VIA VX855/VX875 integrated south bridge"
depends on PCI depends on PCI
...@@ -1686,6 +1694,14 @@ config MFD_VX855 ...@@ -1686,6 +1694,14 @@ config MFD_VX855
VIA VX855/VX875 south bridge. You will need to enable the vx855_spi VIA VX855/VX875 south bridge. You will need to enable the vx855_spi
and/or vx855_gpio drivers for this to do anything useful. and/or vx855_gpio drivers for this to do anything useful.
config MFD_LOCHNAGAR
bool "Cirrus Logic Lochnagar Audio Development Board"
select MFD_CORE
select REGMAP_I2C
depends on I2C=y && OF
help
Support for Cirrus Logic Lochnagar audio development board.
config MFD_ARIZONA config MFD_ARIZONA
select REGMAP select REGMAP
select REGMAP_IRQ select REGMAP_IRQ
...@@ -1872,6 +1888,22 @@ config MFD_STM32_TIMERS ...@@ -1872,6 +1888,22 @@ config MFD_STM32_TIMERS
for PWM and IIO Timer. This driver allow to share the for PWM and IIO Timer. This driver allow to share the
registers between the others drivers. registers between the others drivers.
config MFD_STPMIC1
tristate "Support for STPMIC1 PMIC"
depends on (I2C=y && OF)
select REGMAP_I2C
select REGMAP_IRQ
select MFD_CORE
help
Support for ST Microelectronics STPMIC1 PMIC. STPMIC1 has power on
key, watchdog and regulator functionalities which are supported via
the relevant subsystems. This driver provides core support for the
STPMIC1. In order to use the actual functionaltiy of the device other
drivers must be enabled.
To compile this driver as a module, choose M here: the
module will be called stpmic1.
menu "Multimedia Capabilities Port drivers" menu "Multimedia Capabilities Port drivers"
depends on ARCH_SA1100 depends on ARCH_SA1100
......
...@@ -37,6 +37,9 @@ obj-$(CONFIG_MFD_TC3589X) += tc3589x.o ...@@ -37,6 +37,9 @@ obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
obj-$(CONFIG_MFD_TQMX86) += tqmx86.o
obj-$(CONFIG_MFD_LOCHNAGAR) += lochnagar-i2c.o
obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o
obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o
...@@ -234,6 +237,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o ...@@ -234,6 +237,7 @@ obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
obj-$(CONFIG_MFD_STPMIC1) += stpmic1.o
obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o
obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o obj-$(CONFIG_MFD_STM32_LPTIMER) += stm32-lptimer.o
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -349,18 +348,10 @@ static void aat2870_init_debugfs(struct aat2870_data *aat2870) ...@@ -349,18 +348,10 @@ static void aat2870_init_debugfs(struct aat2870_data *aat2870)
"Failed to create debugfs register file\n"); "Failed to create debugfs register file\n");
} }
static void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
{
debugfs_remove_recursive(aat2870->dentry_root);
}
#else #else
static inline void aat2870_init_debugfs(struct aat2870_data *aat2870) static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
{ {
} }
static inline void aat2870_uninit_debugfs(struct aat2870_data *aat2870)
{
}
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
static int aat2870_i2c_probe(struct i2c_client *client, static int aat2870_i2c_probe(struct i2c_client *client,
...@@ -440,20 +431,6 @@ static int aat2870_i2c_probe(struct i2c_client *client, ...@@ -440,20 +431,6 @@ static int aat2870_i2c_probe(struct i2c_client *client,
return ret; return ret;
} }
static int aat2870_i2c_remove(struct i2c_client *client)
{
struct aat2870_data *aat2870 = i2c_get_clientdata(client);
aat2870_uninit_debugfs(aat2870);
mfd_remove_devices(aat2870->dev);
aat2870_disable(aat2870);
if (aat2870->uninit)
aat2870->uninit(aat2870);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int aat2870_i2c_suspend(struct device *dev) static int aat2870_i2c_suspend(struct device *dev)
{ {
...@@ -492,15 +469,14 @@ static const struct i2c_device_id aat2870_i2c_id_table[] = { ...@@ -492,15 +469,14 @@ static const struct i2c_device_id aat2870_i2c_id_table[] = {
{ "aat2870", 0 }, { "aat2870", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, aat2870_i2c_id_table);
static struct i2c_driver aat2870_i2c_driver = { static struct i2c_driver aat2870_i2c_driver = {
.driver = { .driver = {
.name = "aat2870", .name = "aat2870",
.pm = &aat2870_pm_ops, .pm = &aat2870_pm_ops,
.suppress_bind_attrs = true,
}, },
.probe = aat2870_i2c_probe, .probe = aat2870_i2c_probe,
.remove = aat2870_i2c_remove,
.id_table = aat2870_i2c_id_table, .id_table = aat2870_i2c_id_table,
}; };
...@@ -509,13 +485,3 @@ static int __init aat2870_init(void) ...@@ -509,13 +485,3 @@ static int __init aat2870_init(void)
return i2c_add_driver(&aat2870_i2c_driver); return i2c_add_driver(&aat2870_i2c_driver);
} }
subsys_initcall(aat2870_init); subsys_initcall(aat2870_init);
static void __exit aat2870_exit(void)
{
i2c_del_driver(&aat2870_i2c_driver);
}
module_exit(aat2870_exit);
MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* *
* Copyright 2009 Analog Devices Inc. * Copyright 2009 Analog Devices Inc.
* *
* Author: Michael Hennerich <michael.hennerich@analog.com>
*
* Derived from da903x: * Derived from da903x:
* Copyright (C) 2008 Compulab, Ltd. * Copyright (C) 2008 Compulab, Ltd.
* Mike Rapoport <mike@compulab.co.il> * Mike Rapoport <mike@compulab.co.il>
...@@ -18,7 +20,7 @@ ...@@ -18,7 +20,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -304,18 +306,6 @@ static int adp5520_probe(struct i2c_client *client, ...@@ -304,18 +306,6 @@ static int adp5520_probe(struct i2c_client *client,
return ret; return ret;
} }
static int adp5520_remove(struct i2c_client *client)
{
struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
if (chip->irq)
free_irq(chip->irq, chip);
adp5520_remove_subdevs(chip);
adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int adp5520_suspend(struct device *dev) static int adp5520_suspend(struct device *dev)
{ {
...@@ -346,20 +336,14 @@ static const struct i2c_device_id adp5520_id[] = { ...@@ -346,20 +336,14 @@ static const struct i2c_device_id adp5520_id[] = {
{ "pmic-adp5501", ID_ADP5501 }, { "pmic-adp5501", ID_ADP5501 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, adp5520_id);
static struct i2c_driver adp5520_driver = { static struct i2c_driver adp5520_driver = {
.driver = { .driver = {
.name = "adp5520", .name = "adp5520",
.pm = &adp5520_pm, .pm = &adp5520_pm,
.suppress_bind_attrs = true,
}, },
.probe = adp5520_probe, .probe = adp5520_probe,
.remove = adp5520_remove,
.id_table = adp5520_id, .id_table = adp5520_id,
}; };
builtin_i2c_driver(adp5520_driver);
module_i2c_driver(adp5520_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("ADP5520(01) PMIC-MFD Driver");
MODULE_LICENSE("GPL");
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/as3711.h> #include <linux/mfd/as3711.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -118,7 +117,6 @@ static const struct of_device_id as3711_of_match[] = { ...@@ -118,7 +117,6 @@ static const struct of_device_id as3711_of_match[] = {
{.compatible = "ams,as3711",}, {.compatible = "ams,as3711",},
{} {}
}; };
MODULE_DEVICE_TABLE(of, as3711_of_match);
#endif #endif
static int as3711_i2c_probe(struct i2c_client *client, static int as3711_i2c_probe(struct i2c_client *client,
...@@ -202,8 +200,6 @@ static const struct i2c_device_id as3711_i2c_id[] = { ...@@ -202,8 +200,6 @@ static const struct i2c_device_id as3711_i2c_id[] = {
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, as3711_i2c_id);
static struct i2c_driver as3711_i2c_driver = { static struct i2c_driver as3711_i2c_driver = {
.driver = { .driver = {
.name = "as3711", .name = "as3711",
...@@ -219,13 +215,3 @@ static int __init as3711_i2c_init(void) ...@@ -219,13 +215,3 @@ static int __init as3711_i2c_init(void)
} }
/* Initialise early */ /* Initialise early */
subsys_initcall(as3711_i2c_init); subsys_initcall(as3711_i2c_init);
static void __exit as3711_i2c_exit(void)
{
i2c_del_driver(&as3711_i2c_driver);
}
module_exit(as3711_i2c_exit);
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
MODULE_DESCRIPTION("AS3711 PMIC driver");
MODULE_LICENSE("GPL v2");
...@@ -15,29 +15,29 @@ ...@@ -15,29 +15,29 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/property.h> #include <linux/property.h>
static struct mfd_cell at91_usart_spi_subdev = { static const struct mfd_cell at91_usart_spi_subdev = {
.name = "at91_usart_spi", .name = "at91_usart_spi",
.of_compatible = "microchip,at91sam9g45-usart-spi", .of_compatible = "microchip,at91sam9g45-usart-spi",
}; };
static struct mfd_cell at91_usart_serial_subdev = { static const struct mfd_cell at91_usart_serial_subdev = {
.name = "atmel_usart_serial", .name = "atmel_usart_serial",
.of_compatible = "atmel,at91rm9200-usart-serial", .of_compatible = "atmel,at91rm9200-usart-serial",
}; };
static int at91_usart_mode_probe(struct platform_device *pdev) static int at91_usart_mode_probe(struct platform_device *pdev)
{ {
struct mfd_cell cell; const struct mfd_cell *cell;
u32 opmode = AT91_USART_MODE_SERIAL; u32 opmode = AT91_USART_MODE_SERIAL;
device_property_read_u32(&pdev->dev, "atmel,usart-mode", &opmode); device_property_read_u32(&pdev->dev, "atmel,usart-mode", &opmode);
switch (opmode) { switch (opmode) {
case AT91_USART_MODE_SPI: case AT91_USART_MODE_SPI:
cell = at91_usart_spi_subdev; cell = &at91_usart_spi_subdev;
break; break;
case AT91_USART_MODE_SERIAL: case AT91_USART_MODE_SERIAL:
cell = at91_usart_serial_subdev; cell = &at91_usart_serial_subdev;
break; break;
default: default:
dev_err(&pdev->dev, "atmel,usart-mode has an invalid value %u\n", dev_err(&pdev->dev, "atmel,usart-mode has an invalid value %u\n",
...@@ -45,7 +45,7 @@ static int at91_usart_mode_probe(struct platform_device *pdev) ...@@ -45,7 +45,7 @@ static int at91_usart_mode_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, &cell, 1, return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, cell, 1,
NULL, 0, NULL); NULL, 0, NULL);
} }
......
...@@ -129,8 +129,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -129,8 +129,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
} }
} }
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell, 1, err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell,
NULL, ec_dev->irq, NULL); 1, NULL, ec_dev->irq, NULL);
if (err) { if (err) {
dev_err(dev, dev_err(dev,
"Failed to register Embedded Controller subdevice %d\n", "Failed to register Embedded Controller subdevice %d\n",
...@@ -147,7 +147,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -147,7 +147,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
* - the EC is responsive at init time (it is not true for a * - the EC is responsive at init time (it is not true for a
* sensor hub. * sensor hub.
*/ */
err = mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO,
&ec_pd_cell, 1, NULL, ec_dev->irq, NULL); &ec_pd_cell, 1, NULL, ec_dev->irq, NULL);
if (err) { if (err) {
dev_err(dev, dev_err(dev,
...@@ -181,14 +181,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev) ...@@ -181,14 +181,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
} }
EXPORT_SYMBOL(cros_ec_register); EXPORT_SYMBOL(cros_ec_register);
int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
return 0;
}
EXPORT_SYMBOL(cros_ec_remove);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
int cros_ec_suspend(struct cros_ec_device *ec_dev) int cros_ec_suspend(struct cros_ec_device *ec_dev)
{ {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -34,17 +35,9 @@ ...@@ -34,17 +35,9 @@
#define CROS_MAX_DEV 128 #define CROS_MAX_DEV 128
static int ec_major; static int ec_major;
static const struct attribute_group *cros_ec_groups[] = {
&cros_ec_attr_group,
&cros_ec_lightbar_attr_group,
&cros_ec_vbc_attr_group,
NULL,
};
static struct class cros_class = { static struct class cros_class = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "chromeos", .name = "chromeos",
.dev_groups = cros_ec_groups,
}; };
/* Basic communication */ /* Basic communication */
...@@ -231,7 +224,7 @@ static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg) ...@@ -231,7 +224,7 @@ static long ec_device_ioctl_readmem(struct cros_ec_dev *ec, void __user *arg)
if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem))) if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
return -EFAULT; return -EFAULT;
return 0; return num;
} }
static long ec_device_ioctl(struct file *filp, unsigned int cmd, static long ec_device_ioctl(struct file *filp, unsigned int cmd,
...@@ -395,9 +388,20 @@ static const struct mfd_cell cros_usbpd_charger_cells[] = { ...@@ -395,9 +388,20 @@ static const struct mfd_cell cros_usbpd_charger_cells[] = {
{ .name = "cros-usbpd-charger" } { .name = "cros-usbpd-charger" }
}; };
static const struct mfd_cell cros_ec_platform_cells[] = {
{ .name = "cros-ec-debugfs" },
{ .name = "cros-ec-lightbar" },
{ .name = "cros-ec-sysfs" },
};
static const struct mfd_cell cros_ec_vbc_cells[] = {
{ .name = "cros-ec-vbc" }
};
static int ec_device_probe(struct platform_device *pdev) static int ec_device_probe(struct platform_device *pdev)
{ {
int retval = -ENOMEM; int retval = -ENOMEM;
struct device_node *node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct cros_ec_platform *ec_platform = dev_get_platdata(dev); struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL); struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
...@@ -470,9 +474,6 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -470,9 +474,6 @@ static int ec_device_probe(struct platform_device *pdev)
retval); retval);
} }
/* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1);
/* We can now add the sysfs class, we know which parameter to show */ /* We can now add the sysfs class, we know which parameter to show */
retval = cdev_device_add(&ec->cdev, &ec->class_dev); retval = cdev_device_add(&ec->cdev, &ec->class_dev);
if (retval) { if (retval) {
...@@ -480,8 +481,26 @@ static int ec_device_probe(struct platform_device *pdev) ...@@ -480,8 +481,26 @@ static int ec_device_probe(struct platform_device *pdev)
goto failed; goto failed;
} }
if (cros_ec_debugfs_init(ec)) retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
dev_warn(dev, "failed to create debugfs directory\n"); cros_ec_platform_cells,
ARRAY_SIZE(cros_ec_platform_cells),
NULL, 0, NULL);
if (retval)
dev_warn(ec->dev,
"failed to add cros-ec platform devices: %d\n",
retval);
/* Check whether this EC instance has a VBC NVRAM */
node = ec->ec_dev->dev->of_node;
if (of_property_read_bool(node, "google,has-vbc-nvram")) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
cros_ec_vbc_cells,
ARRAY_SIZE(cros_ec_vbc_cells),
NULL, 0, NULL);
if (retval)
dev_warn(ec->dev, "failed to add VBC devices: %d\n",
retval);
}
return 0; return 0;
...@@ -494,69 +513,25 @@ static int ec_device_remove(struct platform_device *pdev) ...@@ -494,69 +513,25 @@ static int ec_device_remove(struct platform_device *pdev)
{ {
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev); struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
/* Let the EC take over the lightbar again. */
lb_manual_suspend_ctrl(ec, 0);
cros_ec_debugfs_remove(ec);
mfd_remove_devices(ec->dev); mfd_remove_devices(ec->dev);
cdev_del(&ec->cdev); cdev_del(&ec->cdev);
device_unregister(&ec->class_dev); device_unregister(&ec->class_dev);
return 0; return 0;
} }
static void ec_device_shutdown(struct platform_device *pdev)
{
struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
/* Be sure to clear up debugfs delayed works */
cros_ec_debugfs_remove(ec);
}
static const struct platform_device_id cros_ec_id[] = { static const struct platform_device_id cros_ec_id[] = {
{ DRV_NAME, 0 }, { DRV_NAME, 0 },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(platform, cros_ec_id); MODULE_DEVICE_TABLE(platform, cros_ec_id);
static __maybe_unused int ec_device_suspend(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
cros_ec_debugfs_suspend(ec);
lb_suspend(ec);
return 0;
}
static __maybe_unused int ec_device_resume(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
cros_ec_debugfs_resume(ec);
lb_resume(ec);
return 0;
}
static const struct dev_pm_ops cros_ec_dev_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend = ec_device_suspend,
.resume = ec_device_resume,
#endif
};
static struct platform_driver cros_ec_dev_driver = { static struct platform_driver cros_ec_dev_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.pm = &cros_ec_dev_pm_ops,
}, },
.id_table = cros_ec_id, .id_table = cros_ec_id,
.probe = ec_device_probe, .probe = ec_device_probe,
.remove = ec_device_remove, .remove = ec_device_remove,
.shutdown = ec_device_shutdown,
}; };
static int __init cros_ec_dev_init(void) static int __init cros_ec_dev_init(void)
......
...@@ -44,10 +44,4 @@ struct cros_ec_readmem { ...@@ -44,10 +44,4 @@ struct cros_ec_readmem {
#define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command) #define CROS_EC_DEV_IOCXCMD _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
#define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem) #define CROS_EC_DEV_IOCRDMEM _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
/* Lightbar utilities */
extern bool ec_has_lightbar(struct cros_ec_dev *ec);
extern int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable);
extern int lb_suspend(struct cros_ec_dev *ec);
extern int lb_resume(struct cros_ec_dev *ec);
#endif /* _CROS_EC_DEV_H_ */ #endif /* _CROS_EC_DEV_H_ */
/* /*
* DB8500 PRCM Unit driver
*
* Copyright (C) STMicroelectronics 2009 * Copyright (C) STMicroelectronics 2009
* Copyright (C) ST-Ericsson SA 2010 * Copyright (C) ST-Ericsson SA 2010
* *
...@@ -10,7 +12,8 @@ ...@@ -10,7 +12,8 @@
* U8500 PRCM Unit interface driver * U8500 PRCM Unit interface driver
* *
*/ */
#include <linux/module.h> #include <linux/init.h>
#include <linux/export.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -3188,9 +3191,4 @@ static int __init db8500_prcmu_init(void) ...@@ -3188,9 +3191,4 @@ static int __init db8500_prcmu_init(void)
{ {
return platform_driver_register(&db8500_prcmu_driver); return platform_driver_register(&db8500_prcmu_driver);
} }
core_initcall(db8500_prcmu_init); core_initcall(db8500_prcmu_init);
MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>");
MODULE_DESCRIPTION("DB8500 PRCM Unit driver");
MODULE_LICENSE("GPL v2");
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -614,8 +613,6 @@ static const struct i2c_device_id htcpld_chip_id[] = { ...@@ -614,8 +613,6 @@ static const struct i2c_device_id htcpld_chip_id[] = {
{ "htcpld-chip", 0 }, { "htcpld-chip", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
static struct i2c_driver htcpld_chip_driver = { static struct i2c_driver htcpld_chip_driver = {
.driver = { .driver = {
...@@ -643,17 +640,4 @@ static int __init htcpld_core_init(void) ...@@ -643,17 +640,4 @@ static int __init htcpld_core_init(void)
/* Probe for our chips */ /* Probe for our chips */
return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe); return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
} }
device_initcall(htcpld_core_init);
static void __exit htcpld_core_exit(void)
{
i2c_del_driver(&htcpld_chip_driver);
platform_driver_unregister(&htcpld_core_driver);
}
module_init(htcpld_core_init);
module_exit(htcpld_core_exit);
MODULE_AUTHOR("Cory Maccarrone <darkstar6262@gmail.com>");
MODULE_DESCRIPTION("I2C HTC PLD Driver");
MODULE_LICENSE("GPL");
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h> #include <linux/property.h>
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/property.h> #include <linux/property.h>
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#ifndef __MFD_INTEL_LPSS_H #ifndef __MFD_INTEL_LPSS_H
#define __MFD_INTEL_LPSS_H #define __MFD_INTEL_LPSS_H
#include <linux/pm.h>
struct device; struct device;
struct resource; struct resource;
struct property_entry; struct property_entry;
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -919,8 +919,3 @@ void max8925_device_exit(struct max8925_chip *chip) ...@@ -919,8 +919,3 @@ void max8925_device_exit(struct max8925_chip *chip)
free_irq(chip->tsc_irq, chip); free_irq(chip->tsc_irq, chip);
mfd_remove_devices(chip->dev); mfd_remove_devices(chip->dev);
} }
MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
MODULE_LICENSE("GPL");
...@@ -181,7 +181,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) ...@@ -181,7 +181,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
MXS_LRADC_TOUCHSCREEN_5WIRE; MXS_LRADC_TOUCHSCREEN_5WIRE;
break; break;
} }
/* fall through to an error message for i.MX23 */ /* fall through - to an error message for i.MX23 */
default: default:
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unsupported number of touchscreen wires (%d)\n" "Unsupported number of touchscreen wires (%d)\n"
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -298,8 +297,6 @@ static const struct i2c_device_id rc5t583_i2c_id[] = { ...@@ -298,8 +297,6 @@ static const struct i2c_device_id rc5t583_i2c_id[] = {
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, rc5t583_i2c_id);
static struct i2c_driver rc5t583_i2c_driver = { static struct i2c_driver rc5t583_i2c_driver = {
.driver = { .driver = {
.name = "rc5t583", .name = "rc5t583",
...@@ -313,14 +310,3 @@ static int __init rc5t583_i2c_init(void) ...@@ -313,14 +310,3 @@ static int __init rc5t583_i2c_init(void)
return i2c_add_driver(&rc5t583_i2c_driver); return i2c_add_driver(&rc5t583_i2c_driver);
} }
subsys_initcall(rc5t583_i2c_init); subsys_initcall(rc5t583_i2c_init);
static void __exit rc5t583_i2c_exit(void)
{
i2c_del_driver(&rc5t583_i2c_driver);
}
module_exit(rc5t583_i2c_exit);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_DESCRIPTION("RICOH RC5T583 power management system device driver");
MODULE_LICENSE("GPL v2");
...@@ -114,7 +114,8 @@ static const struct mfd_cell s2mpu02_devs[] = { ...@@ -114,7 +114,8 @@ static const struct mfd_cell s2mpu02_devs[] = {
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id sec_dt_match[] = { static const struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic", {
.compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X, .data = (void *)S5M8767X,
}, { }, {
.compatible = "samsung,s2mps11-pmic", .compatible = "samsung,s2mps11-pmic",
...@@ -309,8 +310,8 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic) ...@@ -309,8 +310,8 @@ static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)
* the sub-modules need not instantiate another instance while parsing their * the sub-modules need not instantiate another instance while parsing their
* platform data. * platform data.
*/ */
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( static struct sec_platform_data *
struct device *dev) sec_pmic_i2c_parse_dt_pdata(struct device *dev)
{ {
struct sec_platform_data *pd; struct sec_platform_data *pd;
...@@ -331,8 +332,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( ...@@ -331,8 +332,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
return pd; return pd;
} }
#else #else
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( static struct sec_platform_data *
struct device *dev) sec_pmic_i2c_parse_dt_pdata(struct device *dev)
{ {
return NULL; return NULL;
} }
...@@ -471,8 +472,9 @@ static int sec_pmic_probe(struct i2c_client *i2c, ...@@ -471,8 +472,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
num_sec_devs = ARRAY_SIZE(s2mpu02_devs); num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
break; break;
default: default:
/* If this happens the probe function is problem */ dev_err(&i2c->dev, "Unsupported device type (%lu)\n",
BUG(); sec_pmic->device_type);
return -ENODEV;
} }
ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,
NULL, 0, NULL); NULL, 0, NULL);
......
...@@ -1142,9 +1142,11 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, ...@@ -1142,9 +1142,11 @@ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
return -ENOMEM; return -ENOMEM;
/* Create a gpiod lookup using gpiochip-local offsets */ /* Create a gpiod lookup using gpiochip-local offsets */
lookup = devm_kzalloc(&pdev->dev, lookup = devm_kzalloc(&pdev->dev, struct_size(lookup, table, 3),
sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
GFP_KERNEL); GFP_KERNEL);
if (!lookup)
return -ENOMEM;
lookup->dev_id = "i2c-gpio"; lookup->dev_id = "i2c-gpio";
if (iic->pin_sda < 32) if (iic->pin_sda < 32)
lookup->table[0].chip_label = "SM501-LOW"; lookup->table[0].chip_label = "SM501-LOW";
......
/* /*
* STA2x11 mfd for GPIO, SCTL and APBREG
*
* Copyright (c) 2009-2011 Wind River Systems, Inc. * Copyright (c) 2009-2011 Wind River Systems, Inc.
* Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi) * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
* *
...@@ -18,7 +20,8 @@ ...@@ -18,7 +20,8 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/export.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -653,8 +656,3 @@ static int __init sta2x11_mfd_init(void) ...@@ -653,8 +656,3 @@ static int __init sta2x11_mfd_init(void)
*/ */
subsys_initcall(sta2x11_drivers_init); subsys_initcall(sta2x11_drivers_init);
rootfs_initcall(sta2x11_mfd_init); rootfs_initcall(sta2x11_mfd_init);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wind River");
MODULE_DESCRIPTION("STA2x11 mfd for GPIO, SCTL and APBREG");
MODULE_DEVICE_TABLE(pci, sta2x11_mfd_tbl);
...@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = { ...@@ -463,6 +463,28 @@ static const struct mfd_cell stmpe_ts_cell = {
.num_resources = ARRAY_SIZE(stmpe_ts_resources), .num_resources = ARRAY_SIZE(stmpe_ts_resources),
}; };
/*
* ADC (STMPE811)
*/
static struct resource stmpe_adc_resources[] = {
{
.name = "STMPE_TEMP_SENS",
.flags = IORESOURCE_IRQ,
},
{
.name = "STMPE_ADC",
.flags = IORESOURCE_IRQ,
},
};
static const struct mfd_cell stmpe_adc_cell = {
.name = "stmpe-adc",
.of_compatible = "st,stmpe-adc",
.resources = stmpe_adc_resources,
.num_resources = ARRAY_SIZE(stmpe_adc_resources),
};
/* /*
* STMPE811 or STMPE610 * STMPE811 or STMPE610
*/ */
...@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = { ...@@ -497,6 +519,11 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
.irq = STMPE811_IRQ_TOUCH_DET, .irq = STMPE811_IRQ_TOUCH_DET,
.block = STMPE_BLOCK_TOUCHSCREEN, .block = STMPE_BLOCK_TOUCHSCREEN,
}, },
{
.cell = &stmpe_adc_cell,
.irq = STMPE811_IRQ_TEMP_SENS,
.block = STMPE_BLOCK_ADC,
},
}; };
static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
...@@ -517,6 +544,35 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks, ...@@ -517,6 +544,35 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
enable ? 0 : mask); enable ? 0 : mask);
} }
int stmpe811_adc_common_init(struct stmpe *stmpe)
{
int ret;
u8 adc_ctrl1, adc_ctrl1_mask;
adc_ctrl1 = STMPE_SAMPLE_TIME(stmpe->sample_time) |
STMPE_MOD_12B(stmpe->mod_12b) |
STMPE_REF_SEL(stmpe->ref_sel);
adc_ctrl1_mask = STMPE_SAMPLE_TIME(0xff) | STMPE_MOD_12B(0xff) |
STMPE_REF_SEL(0xff);
ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL1,
adc_ctrl1_mask, adc_ctrl1);
if (ret) {
dev_err(stmpe->dev, "Could not setup ADC\n");
return ret;
}
ret = stmpe_set_bits(stmpe, STMPE811_REG_ADC_CTRL2,
STMPE_ADC_FREQ(0xff), STMPE_ADC_FREQ(stmpe->adc_freq));
if (ret) {
dev_err(stmpe->dev, "Could not setup ADC\n");
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(stmpe811_adc_common_init);
static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block) static int stmpe811_get_altfunc(struct stmpe *stmpe, enum stmpe_block block)
{ {
/* 0 for touchscreen, 1 for GPIO */ /* 0 for touchscreen, 1 for GPIO */
...@@ -1325,6 +1381,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) ...@@ -1325,6 +1381,7 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
struct device_node *np = ci->dev->of_node; struct device_node *np = ci->dev->of_node;
struct stmpe *stmpe; struct stmpe *stmpe;
int ret; int ret;
u32 val;
pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL); pdata = devm_kzalloc(ci->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) if (!pdata)
...@@ -1342,6 +1399,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum) ...@@ -1342,6 +1399,15 @@ int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
mutex_init(&stmpe->irq_lock); mutex_init(&stmpe->irq_lock);
mutex_init(&stmpe->lock); mutex_init(&stmpe->lock);
if (!of_property_read_u32(np, "st,sample-time", &val))
stmpe->sample_time = val;
if (!of_property_read_u32(np, "st,mod-12b", &val))
stmpe->mod_12b = val;
if (!of_property_read_u32(np, "st,ref-sel", &val))
stmpe->ref_sel = val;
if (!of_property_read_u32(np, "st,adc-freq", &val))
stmpe->adc_freq = val;
stmpe->dev = ci->dev; stmpe->dev = ci->dev;
stmpe->client = ci->client; stmpe->client = ci->client;
stmpe->pdata = pdata; stmpe->pdata = pdata;
...@@ -1433,6 +1499,8 @@ int stmpe_remove(struct stmpe *stmpe) ...@@ -1433,6 +1499,8 @@ int stmpe_remove(struct stmpe *stmpe)
if (!IS_ERR(stmpe->vcc)) if (!IS_ERR(stmpe->vcc))
regulator_disable(stmpe->vcc); regulator_disable(stmpe->vcc);
__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
mfd_remove_devices(stmpe->dev); mfd_remove_devices(stmpe->dev);
return 0; return 0;
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) STMicroelectronics 2018
// Author: Pascal Paillet <p.paillet@st.com>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/stpmic1.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
#include <dt-bindings/mfd/st,stpmic1.h>
#define STPMIC1_MAIN_IRQ 0
static const struct regmap_range stpmic1_readable_ranges[] = {
regmap_reg_range(TURN_ON_SR, VERSION_SR),
regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
regmap_reg_range(BST_SW_CR, BST_SW_CR),
regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
regmap_reg_range(INT_MASK_R1, INT_MASK_R4),
regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),
regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),
regmap_reg_range(INT_SRC_R1, INT_SRC_R1),
};
static const struct regmap_range stpmic1_writeable_ranges[] = {
regmap_reg_range(SWOFF_PWRCTRL_CR, LDO6_STDBY_CR),
regmap_reg_range(BST_SW_CR, BST_SW_CR),
regmap_reg_range(INT_CLEAR_R1, INT_CLEAR_R4),
regmap_reg_range(INT_SET_MASK_R1, INT_SET_MASK_R4),
regmap_reg_range(INT_CLEAR_MASK_R1, INT_CLEAR_MASK_R4),
};
static const struct regmap_range stpmic1_volatile_ranges[] = {
regmap_reg_range(TURN_ON_SR, VERSION_SR),
regmap_reg_range(WCHDG_CR, WCHDG_CR),
regmap_reg_range(INT_PENDING_R1, INT_PENDING_R4),
regmap_reg_range(INT_SRC_R1, INT_SRC_R4),
};
static const struct regmap_access_table stpmic1_readable_table = {
.yes_ranges = stpmic1_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(stpmic1_readable_ranges),
};
static const struct regmap_access_table stpmic1_writeable_table = {
.yes_ranges = stpmic1_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(stpmic1_writeable_ranges),
};
static const struct regmap_access_table stpmic1_volatile_table = {
.yes_ranges = stpmic1_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(stpmic1_volatile_ranges),
};
const struct regmap_config stpmic1_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.max_register = PMIC_MAX_REGISTER_ADDRESS,
.rd_table = &stpmic1_readable_table,
.wr_table = &stpmic1_writeable_table,
.volatile_table = &stpmic1_volatile_table,
};
static const struct regmap_irq stpmic1_irqs[] = {
REGMAP_IRQ_REG(IT_PONKEY_F, 0, 0x01),
REGMAP_IRQ_REG(IT_PONKEY_R, 0, 0x02),
REGMAP_IRQ_REG(IT_WAKEUP_F, 0, 0x04),
REGMAP_IRQ_REG(IT_WAKEUP_R, 0, 0x08),
REGMAP_IRQ_REG(IT_VBUS_OTG_F, 0, 0x10),
REGMAP_IRQ_REG(IT_VBUS_OTG_R, 0, 0x20),
REGMAP_IRQ_REG(IT_SWOUT_F, 0, 0x40),
REGMAP_IRQ_REG(IT_SWOUT_R, 0, 0x80),
REGMAP_IRQ_REG(IT_CURLIM_BUCK1, 1, 0x01),
REGMAP_IRQ_REG(IT_CURLIM_BUCK2, 1, 0x02),
REGMAP_IRQ_REG(IT_CURLIM_BUCK3, 1, 0x04),
REGMAP_IRQ_REG(IT_CURLIM_BUCK4, 1, 0x08),
REGMAP_IRQ_REG(IT_OCP_OTG, 1, 0x10),
REGMAP_IRQ_REG(IT_OCP_SWOUT, 1, 0x20),
REGMAP_IRQ_REG(IT_OCP_BOOST, 1, 0x40),
REGMAP_IRQ_REG(IT_OVP_BOOST, 1, 0x80),
REGMAP_IRQ_REG(IT_CURLIM_LDO1, 2, 0x01),
REGMAP_IRQ_REG(IT_CURLIM_LDO2, 2, 0x02),
REGMAP_IRQ_REG(IT_CURLIM_LDO3, 2, 0x04),
REGMAP_IRQ_REG(IT_CURLIM_LDO4, 2, 0x08),
REGMAP_IRQ_REG(IT_CURLIM_LDO5, 2, 0x10),
REGMAP_IRQ_REG(IT_CURLIM_LDO6, 2, 0x20),
REGMAP_IRQ_REG(IT_SHORT_SWOTG, 2, 0x40),
REGMAP_IRQ_REG(IT_SHORT_SWOUT, 2, 0x80),
REGMAP_IRQ_REG(IT_TWARN_F, 3, 0x01),
REGMAP_IRQ_REG(IT_TWARN_R, 3, 0x02),
REGMAP_IRQ_REG(IT_VINLOW_F, 3, 0x04),
REGMAP_IRQ_REG(IT_VINLOW_R, 3, 0x08),
REGMAP_IRQ_REG(IT_SWIN_F, 3, 0x40),
REGMAP_IRQ_REG(IT_SWIN_R, 3, 0x80),
};
static const struct regmap_irq_chip stpmic1_regmap_irq_chip = {
.name = "pmic_irq",
.status_base = INT_PENDING_R1,
.mask_base = INT_CLEAR_MASK_R1,
.unmask_base = INT_SET_MASK_R1,
.ack_base = INT_CLEAR_R1,
.num_regs = STPMIC1_PMIC_NUM_IRQ_REGS,
.irqs = stpmic1_irqs,
.num_irqs = ARRAY_SIZE(stpmic1_irqs),
};
static int stpmic1_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct stpmic1 *ddata;
struct device *dev = &i2c->dev;
int ret;
struct device_node *np = dev->of_node;
u32 reg;
ddata = devm_kzalloc(dev, sizeof(struct stpmic1), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
i2c_set_clientdata(i2c, ddata);
ddata->dev = dev;
ddata->regmap = devm_regmap_init_i2c(i2c, &stpmic1_regmap_config);
if (IS_ERR(ddata->regmap))
return PTR_ERR(ddata->regmap);
ddata->irq = of_irq_get(np, STPMIC1_MAIN_IRQ);
if (ddata->irq < 0) {
dev_err(dev, "Failed to get main IRQ: %d\n", ddata->irq);
return ddata->irq;
}
ret = regmap_read(ddata->regmap, VERSION_SR, &reg);
if (ret) {
dev_err(dev, "Unable to read PMIC version\n");
return ret;
}
dev_info(dev, "PMIC Chip Version: 0x%x\n", reg);
/* Initialize PMIC IRQ Chip & associated IRQ domains */
ret = devm_regmap_add_irq_chip(dev, ddata->regmap, ddata->irq,
IRQF_ONESHOT | IRQF_SHARED,
0, &stpmic1_regmap_irq_chip,
&ddata->irq_data);
if (ret) {
dev_err(dev, "IRQ Chip registration failed: %d\n", ret);
return ret;
}
return devm_of_platform_populate(dev);
}
#ifdef CONFIG_PM_SLEEP
static int stpmic1_suspend(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
disable_irq(pmic_dev->irq);
return 0;
}
static int stpmic1_resume(struct device *dev)
{
struct i2c_client *i2c = to_i2c_client(dev);
struct stpmic1 *pmic_dev = i2c_get_clientdata(i2c);
int ret;
ret = regcache_sync(pmic_dev->regmap);
if (ret)
return ret;
enable_irq(pmic_dev->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(stpmic1_pm, stpmic1_suspend, stpmic1_resume);
static const struct of_device_id stpmic1_of_match[] = {
{ .compatible = "st,stpmic1", },
{},
};
MODULE_DEVICE_TABLE(of, stpmic1_of_match);
static struct i2c_driver stpmic1_driver = {
.driver = {
.name = "stpmic1",
.of_match_table = of_match_ptr(stpmic1_of_match),
.pm = &stpmic1_pm,
},
.probe = stpmic1_probe,
};
module_i2c_driver(stpmic1_driver);
MODULE_DESCRIPTION("STPMIC1 PMIC Driver");
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
MODULE_LICENSE("GPL v2");
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/hwspinlock.h> #include <linux/hwspinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
...@@ -272,13 +272,3 @@ static int __init syscon_init(void) ...@@ -272,13 +272,3 @@ static int __init syscon_init(void)
return platform_driver_register(&syscon_driver); return platform_driver_register(&syscon_driver);
} }
postcore_initcall(syscon_init); postcore_initcall(syscon_init);
static void __exit syscon_exit(void)
{
platform_driver_unregister(&syscon_driver);
}
module_exit(syscon_exit);
MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
MODULE_DESCRIPTION("System Control driver");
MODULE_LICENSE("GPL v2");
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
* Core driver for TI TPS65090 PMIC family * Core driver for TI TPS65090 PMIC family
* *
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* Author: Venu Byravarasu <vbyravarasu@nvidia.com>
*
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation. * version 2, as published by the Free Software Foundation.
...@@ -19,7 +21,7 @@ ...@@ -19,7 +21,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -171,7 +173,6 @@ static const struct of_device_id tps65090_of_match[] = { ...@@ -171,7 +173,6 @@ static const struct of_device_id tps65090_of_match[] = {
{ .compatible = "ti,tps65090",}, { .compatible = "ti,tps65090",},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, tps65090_of_match);
#endif #endif
static int tps65090_i2c_probe(struct i2c_client *client, static int tps65090_i2c_probe(struct i2c_client *client,
...@@ -236,30 +237,19 @@ static int tps65090_i2c_probe(struct i2c_client *client, ...@@ -236,30 +237,19 @@ static int tps65090_i2c_probe(struct i2c_client *client,
return ret; return ret;
} }
static int tps65090_i2c_remove(struct i2c_client *client)
{
struct tps65090 *tps65090 = i2c_get_clientdata(client);
mfd_remove_devices(tps65090->dev);
if (client->irq)
regmap_del_irq_chip(client->irq, tps65090->irq_data);
return 0;
}
static const struct i2c_device_id tps65090_id_table[] = { static const struct i2c_device_id tps65090_id_table[] = {
{ "tps65090", 0 }, { "tps65090", 0 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, tps65090_id_table);
static struct i2c_driver tps65090_driver = { static struct i2c_driver tps65090_driver = {
.driver = { .driver = {
.name = "tps65090", .name = "tps65090",
.suppress_bind_attrs = true,
.of_match_table = of_match_ptr(tps65090_of_match), .of_match_table = of_match_ptr(tps65090_of_match),
}, },
.probe = tps65090_i2c_probe, .probe = tps65090_i2c_probe,
.remove = tps65090_i2c_remove,
.id_table = tps65090_id_table, .id_table = tps65090_id_table,
}; };
...@@ -268,13 +258,3 @@ static int __init tps65090_init(void) ...@@ -268,13 +258,3 @@ static int __init tps65090_init(void)
return i2c_add_driver(&tps65090_driver); return i2c_add_driver(&tps65090_driver);
} }
subsys_initcall(tps65090_init); subsys_initcall(tps65090_init);
static void __exit tps65090_exit(void)
{
i2c_del_driver(&tps65090_driver);
}
module_exit(tps65090_exit);
MODULE_DESCRIPTION("TPS65090 core driver");
MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
MODULE_LICENSE("GPL v2");
...@@ -211,6 +211,83 @@ static const struct of_device_id of_tps65218_match_table[] = { ...@@ -211,6 +211,83 @@ static const struct of_device_id of_tps65218_match_table[] = {
}; };
MODULE_DEVICE_TABLE(of, of_tps65218_match_table); MODULE_DEVICE_TABLE(of, of_tps65218_match_table);
static int tps65218_voltage_set_strict(struct tps65218 *tps)
{
u32 strict;
if (of_property_read_u32(tps->dev->of_node,
"ti,strict-supply-voltage-supervision",
&strict))
return 0;
if (strict != 0 && strict != 1) {
dev_err(tps->dev,
"Invalid ti,strict-supply-voltage-supervision value\n");
return -EINVAL;
}
tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_STRICT,
strict ? TPS65218_CONFIG1_STRICT : 0,
TPS65218_PROTECT_L1);
return 0;
}
static int tps65218_voltage_set_uv_hyst(struct tps65218 *tps)
{
u32 hyst;
if (of_property_read_u32(tps->dev->of_node,
"ti,under-voltage-hyst-microvolt", &hyst))
return 0;
if (hyst != 400000 && hyst != 200000) {
dev_err(tps->dev,
"Invalid ti,under-voltage-hyst-microvolt value\n");
return -EINVAL;
}
tps65218_update_bits(tps, TPS65218_REG_CONFIG2,
TPS65218_CONFIG2_UVLOHYS,
hyst == 400000 ? TPS65218_CONFIG2_UVLOHYS : 0,
TPS65218_PROTECT_L1);
return 0;
}
static int tps65218_voltage_set_uvlo(struct tps65218 *tps)
{
u32 uvlo;
int uvloval;
if (of_property_read_u32(tps->dev->of_node,
"ti,under-voltage-limit-microvolt", &uvlo))
return 0;
switch (uvlo) {
case 2750000:
uvloval = TPS65218_CONFIG1_UVLO_2750000;
break;
case 2950000:
uvloval = TPS65218_CONFIG1_UVLO_2950000;
break;
case 3250000:
uvloval = TPS65218_CONFIG1_UVLO_3250000;
break;
case 3350000:
uvloval = TPS65218_CONFIG1_UVLO_3350000;
break;
default:
dev_err(tps->dev,
"Invalid ti,under-voltage-limit-microvolt value\n");
return -EINVAL;
}
tps65218_update_bits(tps, TPS65218_REG_CONFIG1,
TPS65218_CONFIG1_UVLO_MASK, uvloval,
TPS65218_PROTECT_L1);
return 0;
}
static int tps65218_probe(struct i2c_client *client, static int tps65218_probe(struct i2c_client *client,
const struct i2c_device_id *ids) const struct i2c_device_id *ids)
{ {
...@@ -249,6 +326,18 @@ static int tps65218_probe(struct i2c_client *client, ...@@ -249,6 +326,18 @@ static int tps65218_probe(struct i2c_client *client,
tps->rev = chipid & TPS65218_CHIPID_REV_MASK; tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
ret = tps65218_voltage_set_strict(tps);
if (ret)
return ret;
ret = tps65218_voltage_set_uvlo(tps);
if (ret)
return ret;
ret = tps65218_voltage_set_uv_hyst(tps);
if (ret)
return ret;
ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells, ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
ARRAY_SIZE(tps65218_cells), NULL, 0, ARRAY_SIZE(tps65218_cells), NULL, 0,
regmap_irq_get_domain(tps->irq_data)); regmap_irq_get_domain(tps->irq_data));
......
/* /*
* tps65910.c -- TI TPS6591x * tps65910.c -- TI TPS6591x chip family multi-function driver
* *
* Copyright 2010 Texas Instruments Inc. * Copyright 2010 Texas Instruments Inc.
* *
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
* *
*/ */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -374,7 +372,6 @@ static const struct of_device_id tps65910_of_match[] = { ...@@ -374,7 +372,6 @@ static const struct of_device_id tps65910_of_match[] = {
{ .compatible = "ti,tps65911", .data = (void *)TPS65911}, { .compatible = "ti,tps65911", .data = (void *)TPS65911},
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, tps65910_of_match);
static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
unsigned long *chip_id) unsigned long *chip_id)
...@@ -527,8 +524,6 @@ static const struct i2c_device_id tps65910_i2c_id[] = { ...@@ -527,8 +524,6 @@ static const struct i2c_device_id tps65910_i2c_id[] = {
{ "tps65911", TPS65911 }, { "tps65911", TPS65911 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, tps65910_i2c_id);
static struct i2c_driver tps65910_i2c_driver = { static struct i2c_driver tps65910_i2c_driver = {
.driver = { .driver = {
...@@ -545,14 +540,3 @@ static int __init tps65910_i2c_init(void) ...@@ -545,14 +540,3 @@ static int __init tps65910_i2c_init(void)
} }
/* init early so consumer devices can complete system boot */ /* init early so consumer devices can complete system boot */
subsys_initcall(tps65910_i2c_init); subsys_initcall(tps65910_i2c_init);
static void __exit tps65910_i2c_exit(void)
{
i2c_del_driver(&tps65910_i2c_driver);
}
module_exit(tps65910_i2c_exit);
MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
MODULE_AUTHOR("Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>");
MODULE_DESCRIPTION("TPS6591x chip family multi-function driver");
MODULE_LICENSE("GPL");
...@@ -86,7 +86,6 @@ static const struct acpi_device_id tps68470_acpi_ids[] = { ...@@ -86,7 +86,6 @@ static const struct acpi_device_id tps68470_acpi_ids[] = {
{"INT3472"}, {"INT3472"},
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, tps68470_acpi_ids);
static struct i2c_driver tps68470_driver = { static struct i2c_driver tps68470_driver = {
.driver = { .driver = {
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/tps80031.h> #include <linux/mfd/tps80031.h>
#include <linux/module.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -516,40 +515,18 @@ static int tps80031_probe(struct i2c_client *client, ...@@ -516,40 +515,18 @@ static int tps80031_probe(struct i2c_client *client,
return ret; return ret;
} }
static int tps80031_remove(struct i2c_client *client)
{
struct tps80031 *tps80031 = i2c_get_clientdata(client);
int i;
if (tps80031_power_off_dev == tps80031) {
tps80031_power_off_dev = NULL;
pm_power_off = NULL;
}
mfd_remove_devices(tps80031->dev);
regmap_del_irq_chip(client->irq, tps80031->irq_data);
for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
if (tps80031->clients[i] != client)
i2c_unregister_device(tps80031->clients[i]);
}
return 0;
}
static const struct i2c_device_id tps80031_id_table[] = { static const struct i2c_device_id tps80031_id_table[] = {
{ "tps80031", TPS80031 }, { "tps80031", TPS80031 },
{ "tps80032", TPS80032 }, { "tps80032", TPS80032 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, tps80031_id_table);
static struct i2c_driver tps80031_driver = { static struct i2c_driver tps80031_driver = {
.driver = { .driver = {
.name = "tps80031", .name = "tps80031",
.suppress_bind_attrs = true,
}, },
.probe = tps80031_probe, .probe = tps80031_probe,
.remove = tps80031_remove,
.id_table = tps80031_id_table, .id_table = tps80031_id_table,
}; };
...@@ -558,13 +535,3 @@ static int __init tps80031_init(void) ...@@ -558,13 +535,3 @@ static int __init tps80031_init(void)
return i2c_add_driver(&tps80031_driver); return i2c_add_driver(&tps80031_driver);
} }
subsys_initcall(tps80031_init); subsys_initcall(tps80031_init);
static void __exit tps80031_exit(void)
{
i2c_del_driver(&tps80031_driver);
}
module_exit(tps80031_exit);
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_DESCRIPTION("TPS80031 core driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0+
/*
* TQ-Systems PLD MFD core driver, based on vendor driver by
* Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
*
* Copyright (c) 2015 TQ-Systems GmbH
* Copyright (c) 2019 Andrew Lunn <andrew@lunn.ch>
*/
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/platform_data/i2c-ocores.h>
#include <linux/platform_device.h>
#define TQMX86_IOBASE 0x160
#define TQMX86_IOSIZE 0x3f
#define TQMX86_IOBASE_I2C 0x1a0
#define TQMX86_IOSIZE_I2C 0xa
#define TQMX86_IOBASE_WATCHDOG 0x18b
#define TQMX86_IOSIZE_WATCHDOG 0x2
#define TQMX86_IOBASE_GPIO 0x18d
#define TQMX86_IOSIZE_GPIO 0x4
#define TQMX86_REG_BOARD_ID 0x20
#define TQMX86_REG_BOARD_ID_E38M 1
#define TQMX86_REG_BOARD_ID_50UC 2
#define TQMX86_REG_BOARD_ID_E38C 3
#define TQMX86_REG_BOARD_ID_60EB 4
#define TQMX86_REG_BOARD_ID_E39M 5
#define TQMX86_REG_BOARD_ID_E39C 6
#define TQMX86_REG_BOARD_ID_E39x 7
#define TQMX86_REG_BOARD_ID_70EB 8
#define TQMX86_REG_BOARD_ID_80UC 9
#define TQMX86_REG_BOARD_ID_90UC 10
#define TQMX86_REG_BOARD_REV 0x21
#define TQMX86_REG_IO_EXT_INT 0x26
#define TQMX86_REG_IO_EXT_INT_NONE 0
#define TQMX86_REG_IO_EXT_INT_7 1
#define TQMX86_REG_IO_EXT_INT_9 2
#define TQMX86_REG_IO_EXT_INT_12 3
#define TQMX86_REG_IO_EXT_INT_MASK 0x3
#define TQMX86_REG_IO_EXT_INT_GPIO_SHIFT 4
#define TQMX86_REG_I2C_DETECT 0x47
#define TQMX86_REG_I2C_DETECT_SOFT 0xa5
#define TQMX86_REG_I2C_INT_EN 0x49
static uint gpio_irq;
module_param(gpio_irq, uint, 0);
MODULE_PARM_DESC(gpio_irq, "GPIO IRQ number (7, 9, 12)");
static const struct resource tqmx_i2c_soft_resources[] = {
DEFINE_RES_IO(TQMX86_IOBASE_I2C, TQMX86_IOSIZE_I2C),
};
static const struct resource tqmx_watchdog_resources[] = {
DEFINE_RES_IO(TQMX86_IOBASE_WATCHDOG, TQMX86_IOSIZE_WATCHDOG),
};
/*
* The IRQ resource must be first, since it is updated with the
* configured IRQ in the probe function.
*/
static struct resource tqmx_gpio_resources[] = {
DEFINE_RES_IRQ(0),
DEFINE_RES_IO(TQMX86_IOBASE_GPIO, TQMX86_IOSIZE_GPIO),
};
static struct i2c_board_info tqmx86_i2c_devices[] = {
{
/* 4K EEPROM at 0x50 */
I2C_BOARD_INFO("24c32", 0x50),
},
};
static struct ocores_i2c_platform_data ocores_platfom_data = {
.num_devices = ARRAY_SIZE(tqmx86_i2c_devices),
.devices = tqmx86_i2c_devices,
};
static const struct mfd_cell tqmx86_i2c_soft_dev[] = {
{
.name = "ocores-i2c",
.platform_data = &ocores_platfom_data,
.pdata_size = sizeof(ocores_platfom_data),
.resources = tqmx_i2c_soft_resources,
.num_resources = ARRAY_SIZE(tqmx_i2c_soft_resources),
},
};
static const struct mfd_cell tqmx86_devs[] = {
{
.name = "tqmx86-wdt",
.resources = tqmx_watchdog_resources,
.num_resources = ARRAY_SIZE(tqmx_watchdog_resources),
.ignore_resource_conflicts = true,
},
{
.name = "tqmx86-gpio",
.resources = tqmx_gpio_resources,
.num_resources = ARRAY_SIZE(tqmx_gpio_resources),
.ignore_resource_conflicts = true,
},
};
static const char *tqmx86_board_id_to_name(u8 board_id)
{
switch (board_id) {
case TQMX86_REG_BOARD_ID_E38M:
return "TQMxE38M";
case TQMX86_REG_BOARD_ID_50UC:
return "TQMx50UC";
case TQMX86_REG_BOARD_ID_E38C:
return "TQMxE38C";
case TQMX86_REG_BOARD_ID_60EB:
return "TQMx60EB";
case TQMX86_REG_BOARD_ID_E39M:
return "TQMxE39M";
case TQMX86_REG_BOARD_ID_E39C:
return "TQMxE39C";
case TQMX86_REG_BOARD_ID_E39x:
return "TQMxE39x";
case TQMX86_REG_BOARD_ID_70EB:
return "TQMx70EB";
case TQMX86_REG_BOARD_ID_80UC:
return "TQMx80UC";
case TQMX86_REG_BOARD_ID_90UC:
return "TQMx90UC";
default:
return "Unknown";
}
}
static int tqmx86_board_id_to_clk_rate(u8 board_id)
{
switch (board_id) {
case TQMX86_REG_BOARD_ID_50UC:
case TQMX86_REG_BOARD_ID_60EB:
case TQMX86_REG_BOARD_ID_70EB:
case TQMX86_REG_BOARD_ID_80UC:
case TQMX86_REG_BOARD_ID_90UC:
return 24000;
case TQMX86_REG_BOARD_ID_E39M:
case TQMX86_REG_BOARD_ID_E39C:
case TQMX86_REG_BOARD_ID_E39x:
return 25000;
case TQMX86_REG_BOARD_ID_E38M:
case TQMX86_REG_BOARD_ID_E38C:
return 33000;
default:
return 0;
}
}
static int tqmx86_probe(struct platform_device *pdev)
{
u8 board_id, rev, i2c_det, i2c_ien, io_ext_int_val;
struct device *dev = &pdev->dev;
u8 gpio_irq_cfg, readback;
const char *board_name;
void __iomem *io_base;
int err;
switch (gpio_irq) {
case 0:
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_NONE;
break;
case 7:
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_7;
break;
case 9:
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_9;
break;
case 12:
gpio_irq_cfg = TQMX86_REG_IO_EXT_INT_12;
break;
default:
pr_err("tqmx86: Invalid GPIO IRQ (%d)\n", gpio_irq);
return -EINVAL;
}
io_base = devm_ioport_map(dev, TQMX86_IOBASE, TQMX86_IOSIZE);
if (!io_base)
return -ENOMEM;
board_id = ioread8(io_base + TQMX86_REG_BOARD_ID);
board_name = tqmx86_board_id_to_name(board_id);
rev = ioread8(io_base + TQMX86_REG_BOARD_REV);
dev_info(dev,
"Found %s - Board ID %d, PCB Revision %d, PLD Revision %d\n",
board_name, board_id, rev >> 4, rev & 0xf);
i2c_det = ioread8(io_base + TQMX86_REG_I2C_DETECT);
i2c_ien = ioread8(io_base + TQMX86_REG_I2C_INT_EN);
if (gpio_irq_cfg) {
io_ext_int_val =
gpio_irq_cfg << TQMX86_REG_IO_EXT_INT_GPIO_SHIFT;
iowrite8(io_ext_int_val, io_base + TQMX86_REG_IO_EXT_INT);
readback = ioread8(io_base + TQMX86_REG_IO_EXT_INT);
if (readback != io_ext_int_val) {
dev_warn(dev, "GPIO interrupts not supported.\n");
return -EINVAL;
}
/* Assumes the IRQ resource is first. */
tqmx_gpio_resources[0].start = gpio_irq;
}
ocores_platfom_data.clock_khz = tqmx86_board_id_to_clk_rate(board_id);
if (i2c_det == TQMX86_REG_I2C_DETECT_SOFT) {
err = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
tqmx86_i2c_soft_dev,
ARRAY_SIZE(tqmx86_i2c_soft_dev),
NULL, 0, NULL);
if (err)
return err;
}
return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
tqmx86_devs,
ARRAY_SIZE(tqmx86_devs),
NULL, 0, NULL);
}
static int tqmx86_create_platform_device(const struct dmi_system_id *id)
{
struct platform_device *pdev;
int err;
pdev = platform_device_alloc("tqmx86", -1);
if (!pdev)
return -ENOMEM;
err = platform_device_add(pdev);
if (err)
platform_device_put(pdev);
return err;
}
static const struct dmi_system_id tqmx86_dmi_table[] __initconst = {
{
.ident = "TQMX86",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TQ-Group"),
DMI_MATCH(DMI_PRODUCT_NAME, "TQMx"),
},
.callback = tqmx86_create_platform_device,
},
{}
};
MODULE_DEVICE_TABLE(dmi, tqmx86_dmi_table);
static struct platform_driver tqmx86_driver = {
.driver = {
.name = "tqmx86",
},
.probe = tqmx86_probe,
};
static int __init tqmx86_init(void)
{
if (!dmi_check_system(tqmx86_dmi_table))
return -ENODEV;
return platform_driver_register(&tqmx86_driver);
}
module_init(tqmx86_init);
MODULE_DESCRIPTION("TQx86 PLD Core Driver");
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:tqmx86");
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/export.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
...@@ -1892,14 +1893,6 @@ int wm831x_device_init(struct wm831x *wm831x, int irq) ...@@ -1892,14 +1893,6 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
return ret; return ret;
} }
void wm831x_device_exit(struct wm831x *wm831x)
{
wm831x_otp_exit(wm831x);
mfd_remove_devices(wm831x->dev);
free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x);
wm831x_irq_exit(wm831x);
}
int wm831x_device_suspend(struct wm831x *wm831x) int wm831x_device_suspend(struct wm831x *wm831x)
{ {
int reg, mask; int reg, mask;
...@@ -1944,7 +1937,3 @@ void wm831x_device_shutdown(struct wm831x *wm831x) ...@@ -1944,7 +1937,3 @@ void wm831x_device_shutdown(struct wm831x *wm831x)
} }
} }
EXPORT_SYMBOL_GPL(wm831x_device_shutdown); EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown");
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
...@@ -68,15 +68,6 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, ...@@ -68,15 +68,6 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
return wm831x_device_init(wm831x, i2c->irq); return wm831x_device_init(wm831x, i2c->irq);
} }
static int wm831x_i2c_remove(struct i2c_client *i2c)
{
struct wm831x *wm831x = i2c_get_clientdata(i2c);
wm831x_device_exit(wm831x);
return 0;
}
static int wm831x_i2c_suspend(struct device *dev) static int wm831x_i2c_suspend(struct device *dev)
{ {
struct wm831x *wm831x = dev_get_drvdata(dev); struct wm831x *wm831x = dev_get_drvdata(dev);
...@@ -103,7 +94,6 @@ static const struct i2c_device_id wm831x_i2c_id[] = { ...@@ -103,7 +94,6 @@ static const struct i2c_device_id wm831x_i2c_id[] = {
{ "wm8326", WM8326 }, { "wm8326", WM8326 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
static const struct dev_pm_ops wm831x_pm_ops = { static const struct dev_pm_ops wm831x_pm_ops = {
.suspend = wm831x_i2c_suspend, .suspend = wm831x_i2c_suspend,
...@@ -115,9 +105,9 @@ static struct i2c_driver wm831x_i2c_driver = { ...@@ -115,9 +105,9 @@ static struct i2c_driver wm831x_i2c_driver = {
.name = "wm831x", .name = "wm831x",
.pm = &wm831x_pm_ops, .pm = &wm831x_pm_ops,
.of_match_table = of_match_ptr(wm831x_of_match), .of_match_table = of_match_ptr(wm831x_of_match),
.suppress_bind_attrs = true,
}, },
.probe = wm831x_i2c_probe, .probe = wm831x_i2c_probe,
.remove = wm831x_i2c_remove,
.id_table = wm831x_i2c_id, .id_table = wm831x_i2c_id,
}; };
...@@ -132,9 +122,3 @@ static int __init wm831x_i2c_init(void) ...@@ -132,9 +122,3 @@ static int __init wm831x_i2c_init(void)
return ret; return ret;
} }
subsys_initcall(wm831x_i2c_init); subsys_initcall(wm831x_i2c_init);
static void __exit wm831x_i2c_exit(void)
{
i2c_del_driver(&wm831x_i2c_driver);
}
module_exit(wm831x_i2c_exit);
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm.h> #include <linux/pm.h>
...@@ -67,15 +67,6 @@ static int wm831x_spi_probe(struct spi_device *spi) ...@@ -67,15 +67,6 @@ static int wm831x_spi_probe(struct spi_device *spi)
return wm831x_device_init(wm831x, spi->irq); return wm831x_device_init(wm831x, spi->irq);
} }
static int wm831x_spi_remove(struct spi_device *spi)
{
struct wm831x *wm831x = spi_get_drvdata(spi);
wm831x_device_exit(wm831x);
return 0;
}
static int wm831x_spi_suspend(struct device *dev) static int wm831x_spi_suspend(struct device *dev)
{ {
struct wm831x *wm831x = dev_get_drvdata(dev); struct wm831x *wm831x = dev_get_drvdata(dev);
...@@ -108,17 +99,16 @@ static const struct spi_device_id wm831x_spi_ids[] = { ...@@ -108,17 +99,16 @@ static const struct spi_device_id wm831x_spi_ids[] = {
{ "wm8326", WM8326 }, { "wm8326", WM8326 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(spi, wm831x_spi_ids);
static struct spi_driver wm831x_spi_driver = { static struct spi_driver wm831x_spi_driver = {
.driver = { .driver = {
.name = "wm831x", .name = "wm831x",
.pm = &wm831x_spi_pm, .pm = &wm831x_spi_pm,
.of_match_table = of_match_ptr(wm831x_of_match), .of_match_table = of_match_ptr(wm831x_of_match),
.suppress_bind_attrs = true,
}, },
.id_table = wm831x_spi_ids, .id_table = wm831x_spi_ids,
.probe = wm831x_spi_probe, .probe = wm831x_spi_probe,
.remove = wm831x_spi_remove,
}; };
static int __init wm831x_spi_init(void) static int __init wm831x_spi_init(void)
...@@ -132,13 +122,3 @@ static int __init wm831x_spi_init(void) ...@@ -132,13 +122,3 @@ static int __init wm831x_spi_init(void)
return 0; return 0;
} }
subsys_initcall(wm831x_spi_init); subsys_initcall(wm831x_spi_init);
static void __exit wm831x_spi_exit(void)
{
spi_unregister_driver(&wm831x_spi_driver);
}
module_exit(wm831x_spi_exit);
MODULE_DESCRIPTION("SPI support for WM831x/2x AudioPlus PMICs");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown");
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/init.h>
#include <linux/export.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/device.h> #include <linux/device.h>
...@@ -442,30 +443,3 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, ...@@ -442,30 +443,3 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(wm8350_device_init); EXPORT_SYMBOL_GPL(wm8350_device_init);
void wm8350_device_exit(struct wm8350 *wm8350)
{
int i;
for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++)
platform_device_unregister(wm8350->pmic.led[i].pdev);
for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
platform_device_unregister(wm8350->pmic.pdev[i]);
platform_device_unregister(wm8350->wdt.pdev);
platform_device_unregister(wm8350->rtc.pdev);
platform_device_unregister(wm8350->power.pdev);
platform_device_unregister(wm8350->hwmon.pdev);
platform_device_unregister(wm8350->gpio.pdev);
platform_device_unregister(wm8350->codec.pdev);
if (wm8350->irq_base)
free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
wm8350_irq_exit(wm8350);
}
EXPORT_SYMBOL_GPL(wm8350_device_exit);
MODULE_DESCRIPTION("WM8350 AudioPlus PMIC core driver");
MODULE_LICENSE("GPL");
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
* *
*/ */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -48,30 +46,19 @@ static int wm8350_i2c_probe(struct i2c_client *i2c, ...@@ -48,30 +46,19 @@ static int wm8350_i2c_probe(struct i2c_client *i2c,
return wm8350_device_init(wm8350, i2c->irq, pdata); return wm8350_device_init(wm8350, i2c->irq, pdata);
} }
static int wm8350_i2c_remove(struct i2c_client *i2c)
{
struct wm8350 *wm8350 = i2c_get_clientdata(i2c);
wm8350_device_exit(wm8350);
return 0;
}
static const struct i2c_device_id wm8350_i2c_id[] = { static const struct i2c_device_id wm8350_i2c_id[] = {
{ "wm8350", 0 }, { "wm8350", 0 },
{ "wm8351", 0 }, { "wm8351", 0 },
{ "wm8352", 0 }, { "wm8352", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
static struct i2c_driver wm8350_i2c_driver = { static struct i2c_driver wm8350_i2c_driver = {
.driver = { .driver = {
.name = "wm8350", .name = "wm8350",
.suppress_bind_attrs = true,
}, },
.probe = wm8350_i2c_probe, .probe = wm8350_i2c_probe,
.remove = wm8350_i2c_remove,
.id_table = wm8350_i2c_id, .id_table = wm8350_i2c_id,
}; };
...@@ -81,12 +68,3 @@ static int __init wm8350_i2c_init(void) ...@@ -81,12 +68,3 @@ static int __init wm8350_i2c_init(void)
} }
/* init early so consumer devices can complete system boot */ /* init early so consumer devices can complete system boot */
subsys_initcall(wm8350_i2c_init); subsys_initcall(wm8350_i2c_init);
static void __exit wm8350_i2c_exit(void)
{
i2c_del_driver(&wm8350_i2c_driver);
}
module_exit(wm8350_i2c_exit);
MODULE_DESCRIPTION("I2C support for the WM8350 AudioPlus PMIC");
MODULE_LICENSE("GPL");
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
*/ */
#include <linux/module.h> #include <linux/init.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -150,7 +150,6 @@ static const struct i2c_device_id wm8400_i2c_id[] = { ...@@ -150,7 +150,6 @@ static const struct i2c_device_id wm8400_i2c_id[] = {
{ "wm8400", 0 }, { "wm8400", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, wm8400_i2c_id);
static struct i2c_driver wm8400_i2c_driver = { static struct i2c_driver wm8400_i2c_driver = {
.driver = { .driver = {
...@@ -161,7 +160,7 @@ static struct i2c_driver wm8400_i2c_driver = { ...@@ -161,7 +160,7 @@ static struct i2c_driver wm8400_i2c_driver = {
}; };
#endif #endif
static int __init wm8400_module_init(void) static int __init wm8400_driver_init(void)
{ {
int ret = -ENODEV; int ret = -ENODEV;
...@@ -173,15 +172,4 @@ static int __init wm8400_module_init(void) ...@@ -173,15 +172,4 @@ static int __init wm8400_module_init(void)
return ret; return ret;
} }
subsys_initcall(wm8400_module_init); subsys_initcall(wm8400_driver_init);
static void __exit wm8400_module_exit(void)
{
#if IS_ENABLED(CONFIG_I2C)
i2c_del_driver(&wm8400_i2c_driver);
#endif
}
module_exit(wm8400_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
...@@ -49,9 +49,6 @@ config CHROMEOS_TBMC ...@@ -49,9 +49,6 @@ config CHROMEOS_TBMC
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called chromeos_tbmc. module will be called chromeos_tbmc.
config CROS_EC_CTL
tristate
config CROS_EC_I2C config CROS_EC_I2C
tristate "ChromeOS Embedded Controller (I2C)" tristate "ChromeOS Embedded Controller (I2C)"
depends on MFD_CROS_EC && I2C depends on MFD_CROS_EC && I2C
...@@ -111,4 +108,48 @@ config CROS_KBD_LED_BACKLIGHT ...@@ -111,4 +108,48 @@ config CROS_KBD_LED_BACKLIGHT
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called cros_kbd_led_backlight. module will be called cros_kbd_led_backlight.
config CROS_EC_LIGHTBAR
tristate "Chromebook Pixel's lightbar support"
depends on MFD_CROS_EC_CHARDEV
default MFD_CROS_EC_CHARDEV
help
This option exposes the Chromebook Pixel's lightbar to
userspace.
To compile this driver as a module, choose M here: the
module will be called cros_ec_lightbar.
config CROS_EC_VBC
tristate "ChromeOS EC vboot context support"
depends on MFD_CROS_EC_CHARDEV && OF
default MFD_CROS_EC_CHARDEV
help
This option exposes the ChromeOS EC vboot context nvram to
userspace.
To compile this driver as a module, choose M here: the
module will be called cros_ec_vbc.
config CROS_EC_DEBUGFS
tristate "Export ChromeOS EC internals in DebugFS"
depends on MFD_CROS_EC_CHARDEV && DEBUG_FS
default MFD_CROS_EC_CHARDEV
help
This option exposes the ChromeOS EC device internals to
userspace.
To compile this driver as a module, choose M here: the
module will be called cros_ec_debugfs.
config CROS_EC_SYSFS
tristate "ChromeOS EC control and information through sysfs"
depends on MFD_CROS_EC_CHARDEV && SYSFS
default MFD_CROS_EC_CHARDEV
help
This option exposes some sysfs attributes to control and get
information from ChromeOS EC.
To compile this driver as a module, choose M here: the
module will be called cros_ec_sysfs.
endif # CHROMEOS_PLATFORMS endif # CHROMEOS_PLATFORMS
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
cros_ec_vbc.o cros_ec_debugfs.o
obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o
...@@ -13,3 +10,7 @@ cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o ...@@ -13,3 +10,7 @@ cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o
obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o
obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
...@@ -23,12 +23,16 @@ ...@@ -23,12 +23,16 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h> #include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/wait.h> #include <linux/wait.h>
#define DRV_NAME "cros-ec-debugfs"
#define LOG_SHIFT 14 #define LOG_SHIFT 14
#define LOG_SIZE (1 << LOG_SHIFT) #define LOG_SIZE (1 << LOG_SHIFT)
#define LOG_POLL_SEC 10 #define LOG_POLL_SEC 10
...@@ -423,8 +427,9 @@ static int cros_ec_create_pdinfo(struct cros_ec_debugfs *debug_info) ...@@ -423,8 +427,9 @@ static int cros_ec_create_pdinfo(struct cros_ec_debugfs *debug_info)
return 0; return 0;
} }
int cros_ec_debugfs_init(struct cros_ec_dev *ec) static int cros_ec_debugfs_probe(struct platform_device *pd)
{ {
struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent);
struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev);
const char *name = ec_platform->ec_name; const char *name = ec_platform->ec_name;
struct cros_ec_debugfs *debug_info; struct cros_ec_debugfs *debug_info;
...@@ -453,40 +458,57 @@ int cros_ec_debugfs_init(struct cros_ec_dev *ec) ...@@ -453,40 +458,57 @@ int cros_ec_debugfs_init(struct cros_ec_dev *ec)
ec->debug_info = debug_info; ec->debug_info = debug_info;
dev_set_drvdata(&pd->dev, ec);
return 0; return 0;
remove_debugfs: remove_debugfs:
debugfs_remove_recursive(debug_info->dir); debugfs_remove_recursive(debug_info->dir);
return ret; return ret;
} }
EXPORT_SYMBOL(cros_ec_debugfs_init);
void cros_ec_debugfs_remove(struct cros_ec_dev *ec) static int cros_ec_debugfs_remove(struct platform_device *pd)
{ {
if (!ec->debug_info) struct cros_ec_dev *ec = dev_get_drvdata(pd->dev.parent);
return;
debugfs_remove_recursive(ec->debug_info->dir); debugfs_remove_recursive(ec->debug_info->dir);
cros_ec_cleanup_console_log(ec->debug_info); cros_ec_cleanup_console_log(ec->debug_info);
return 0;
} }
EXPORT_SYMBOL(cros_ec_debugfs_remove);
void cros_ec_debugfs_suspend(struct cros_ec_dev *ec) static int __maybe_unused cros_ec_debugfs_suspend(struct device *dev)
{ {
/* struct cros_ec_dev *ec = dev_get_drvdata(dev);
* cros_ec_debugfs_init() failures are non-fatal; it's also possible
* that we initted things but decided that console log wasn't supported. cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
* We'll use the same set of checks that cros_ec_debugfs_remove() +
* cros_ec_cleanup_console_log() end up using to handle those cases. return 0;
*/
if (ec->debug_info && ec->debug_info->log_buffer.buf)
cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
} }
EXPORT_SYMBOL(cros_ec_debugfs_suspend);
void cros_ec_debugfs_resume(struct cros_ec_dev *ec) static int __maybe_unused cros_ec_debugfs_resume(struct device *dev)
{ {
if (ec->debug_info && ec->debug_info->log_buffer.buf) struct cros_ec_dev *ec = dev_get_drvdata(dev);
schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
return 0;
} }
EXPORT_SYMBOL(cros_ec_debugfs_resume);
static SIMPLE_DEV_PM_OPS(cros_ec_debugfs_pm_ops,
cros_ec_debugfs_suspend, cros_ec_debugfs_resume);
static struct platform_driver cros_ec_debugfs_driver = {
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_debugfs_pm_ops,
},
.probe = cros_ec_debugfs_probe,
.remove = cros_ec_debugfs_remove,
};
module_platform_driver(cros_ec_debugfs_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Debug logs for ChromeOS EC");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -317,15 +317,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client, ...@@ -317,15 +317,6 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
return 0; return 0;
} }
static int cros_ec_i2c_remove(struct i2c_client *client)
{
struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
cros_ec_remove(ec_dev);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int cros_ec_i2c_suspend(struct device *dev) static int cros_ec_i2c_suspend(struct device *dev)
{ {
...@@ -376,7 +367,6 @@ static struct i2c_driver cros_ec_driver = { ...@@ -376,7 +367,6 @@ static struct i2c_driver cros_ec_driver = {
.pm = &cros_ec_i2c_pm_ops, .pm = &cros_ec_i2c_pm_ops,
}, },
.probe = cros_ec_i2c_probe, .probe = cros_ec_i2c_probe,
.remove = cros_ec_i2c_remove,
.id_table = cros_ec_i2c_id, .id_table = cros_ec_i2c_id,
}; };
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/slab.h> #include <linux/slab.h>
#define DRV_NAME "cros-ec-lightbar"
/* Rate-limit the lightbar interface to prevent DoS. */ /* Rate-limit the lightbar interface to prevent DoS. */
static unsigned long lb_interval_jiffies = 50 * HZ / 1000; static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
...@@ -41,7 +43,6 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000; ...@@ -41,7 +43,6 @@ static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
* If this is true, we won't do anything during suspend/resume. * If this is true, we won't do anything during suspend/resume.
*/ */
static bool userspace_control; static bool userspace_control;
static struct cros_ec_dev *ec_with_lightbar;
static ssize_t interval_msec_show(struct device *dev, static ssize_t interval_msec_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
...@@ -373,15 +374,12 @@ static int lb_send_empty_cmd(struct cros_ec_dev *ec, uint8_t cmd) ...@@ -373,15 +374,12 @@ static int lb_send_empty_cmd(struct cros_ec_dev *ec, uint8_t cmd)
return ret; return ret;
} }
int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable) static int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
{ {
struct ec_params_lightbar *param; struct ec_params_lightbar *param;
struct cros_ec_command *msg; struct cros_ec_command *msg;
int ret; int ret;
if (ec != ec_with_lightbar)
return 0;
msg = alloc_lightbar_cmd_msg(ec); msg = alloc_lightbar_cmd_msg(ec);
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
...@@ -408,25 +406,6 @@ int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable) ...@@ -408,25 +406,6 @@ int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
return ret; return ret;
} }
EXPORT_SYMBOL(lb_manual_suspend_ctrl);
int lb_suspend(struct cros_ec_dev *ec)
{
if (userspace_control || ec != ec_with_lightbar)
return 0;
return lb_send_empty_cmd(ec, LIGHTBAR_CMD_SUSPEND);
}
EXPORT_SYMBOL(lb_suspend);
int lb_resume(struct cros_ec_dev *ec)
{
if (userspace_control || ec != ec_with_lightbar)
return 0;
return lb_send_empty_cmd(ec, LIGHTBAR_CMD_RESUME);
}
EXPORT_SYMBOL(lb_resume);
static ssize_t sequence_store(struct device *dev, struct device_attribute *attr, static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -584,36 +563,91 @@ static struct attribute *__lb_cmds_attrs[] = { ...@@ -584,36 +563,91 @@ static struct attribute *__lb_cmds_attrs[] = {
NULL, NULL,
}; };
bool ec_has_lightbar(struct cros_ec_dev *ec) struct attribute_group cros_ec_lightbar_attr_group = {
.name = "lightbar",
.attrs = __lb_cmds_attrs,
};
static int cros_ec_lightbar_probe(struct platform_device *pd)
{ {
return !!get_lightbar_version(ec, NULL, NULL); struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
struct cros_ec_platform *pdata = dev_get_platdata(ec_dev->dev);
struct device *dev = &pd->dev;
int ret;
/*
* Only instantiate the lightbar if the EC name is 'cros_ec'. Other EC
* devices like 'cros_pd' doesn't have a lightbar.
*/
if (strcmp(pdata->ec_name, CROS_EC_DEV_NAME) != 0)
return -ENODEV;
/*
* Ask then for the lightbar version, if it's 0 then the 'cros_ec'
* doesn't have a lightbar.
*/
if (!get_lightbar_version(ec_dev, NULL, NULL))
return -ENODEV;
/* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec_dev, 1);
ret = sysfs_create_group(&ec_dev->class_dev.kobj,
&cros_ec_lightbar_attr_group);
if (ret < 0)
dev_err(dev, "failed to create %s attributes. err=%d\n",
cros_ec_lightbar_attr_group.name, ret);
return ret;
} }
static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj, static int cros_ec_lightbar_remove(struct platform_device *pd)
struct attribute *a, int n)
{ {
struct device *dev = container_of(kobj, struct device, kobj); struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
struct cros_ec_dev *ec = to_cros_ec_dev(dev);
struct platform_device *pdev = to_platform_device(ec->dev);
struct cros_ec_platform *pdata = pdev->dev.platform_data;
int is_cros_ec;
is_cros_ec = strcmp(pdata->ec_name, CROS_EC_DEV_NAME); sysfs_remove_group(&ec_dev->class_dev.kobj,
&cros_ec_lightbar_attr_group);
if (is_cros_ec != 0) /* Let the EC take over the lightbar again. */
return 0; lb_manual_suspend_ctrl(ec_dev, 0);
/* Only instantiate this stuff if the EC has a lightbar */
if (ec_has_lightbar(ec)) {
ec_with_lightbar = ec;
return a->mode;
}
return 0; return 0;
} }
struct attribute_group cros_ec_lightbar_attr_group = { static int __maybe_unused cros_ec_lightbar_resume(struct device *dev)
.name = "lightbar", {
.attrs = __lb_cmds_attrs, struct cros_ec_dev *ec_dev = dev_get_drvdata(dev);
.is_visible = cros_ec_lightbar_attrs_are_visible,
if (userspace_control)
return 0;
return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_RESUME);
}
static int __maybe_unused cros_ec_lightbar_suspend(struct device *dev)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev);
if (userspace_control)
return 0;
return lb_send_empty_cmd(ec_dev, LIGHTBAR_CMD_SUSPEND);
}
static SIMPLE_DEV_PM_OPS(cros_ec_lightbar_pm_ops,
cros_ec_lightbar_suspend, cros_ec_lightbar_resume);
static struct platform_driver cros_ec_lightbar_driver = {
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_lightbar_pm_ops,
},
.probe = cros_ec_lightbar_probe,
.remove = cros_ec_lightbar_remove,
}; };
EXPORT_SYMBOL(cros_ec_lightbar_attr_group);
module_platform_driver(cros_ec_lightbar_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Expose the Chromebook Pixel's lightbar to userspace");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -327,7 +327,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev) ...@@ -327,7 +327,6 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
static int cros_ec_lpc_remove(struct platform_device *pdev) static int cros_ec_lpc_remove(struct platform_device *pdev)
{ {
struct cros_ec_device *ec_dev;
struct acpi_device *adev; struct acpi_device *adev;
adev = ACPI_COMPANION(&pdev->dev); adev = ACPI_COMPANION(&pdev->dev);
...@@ -335,9 +334,6 @@ static int cros_ec_lpc_remove(struct platform_device *pdev) ...@@ -335,9 +334,6 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY, acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
cros_ec_lpc_acpi_notify); cros_ec_lpc_acpi_notify);
ec_dev = platform_get_drvdata(pdev);
cros_ec_remove(ec_dev);
return 0; return 0;
} }
......
...@@ -685,16 +685,6 @@ static int cros_ec_spi_probe(struct spi_device *spi) ...@@ -685,16 +685,6 @@ static int cros_ec_spi_probe(struct spi_device *spi)
return 0; return 0;
} }
static int cros_ec_spi_remove(struct spi_device *spi)
{
struct cros_ec_device *ec_dev;
ec_dev = spi_get_drvdata(spi);
cros_ec_remove(ec_dev);
return 0;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int cros_ec_spi_suspend(struct device *dev) static int cros_ec_spi_suspend(struct device *dev)
{ {
...@@ -733,7 +723,6 @@ static struct spi_driver cros_ec_driver_spi = { ...@@ -733,7 +723,6 @@ static struct spi_driver cros_ec_driver_spi = {
.pm = &cros_ec_spi_pm_ops, .pm = &cros_ec_spi_pm_ops,
}, },
.probe = cros_ec_spi_probe, .probe = cros_ec_spi_probe,
.remove = cros_ec_spi_remove,
.id_table = cros_ec_spi_id, .id_table = cros_ec_spi_id,
}; };
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#define DRV_NAME "cros-ec-sysfs"
/* Accessor functions */ /* Accessor functions */
static ssize_t reboot_show(struct device *dev, static ssize_t reboot_show(struct device *dev,
...@@ -353,7 +355,39 @@ struct attribute_group cros_ec_attr_group = { ...@@ -353,7 +355,39 @@ struct attribute_group cros_ec_attr_group = {
.attrs = __ec_attrs, .attrs = __ec_attrs,
.is_visible = cros_ec_ctrl_visible, .is_visible = cros_ec_ctrl_visible,
}; };
EXPORT_SYMBOL(cros_ec_attr_group);
static int cros_ec_sysfs_probe(struct platform_device *pd)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
struct device *dev = &pd->dev;
int ret;
ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
if (ret < 0)
dev_err(dev, "failed to create attributes. err=%d\n", ret);
return ret;
}
static int cros_ec_sysfs_remove(struct platform_device *pd)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
sysfs_remove_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
return 0;
}
static struct platform_driver cros_ec_sysfs_driver = {
.driver = {
.name = DRV_NAME,
},
.probe = cros_ec_sysfs_probe,
.remove = cros_ec_sysfs_remove,
};
module_platform_driver(cros_ec_sysfs_driver);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ChromeOS EC control driver"); MODULE_DESCRIPTION("ChromeOS EC control driver");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -22,8 +22,11 @@ ...@@ -22,8 +22,11 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h> #include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#define DRV_NAME "cros-ec-vbc"
static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj, static ssize_t vboot_context_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *att, char *buf, struct bin_attribute *att, char *buf,
loff_t pos, size_t count) loff_t pos, size_t count)
...@@ -105,21 +108,6 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj, ...@@ -105,21 +108,6 @@ static ssize_t vboot_context_write(struct file *filp, struct kobject *kobj,
return data_sz; return data_sz;
} }
static umode_t cros_ec_vbc_is_visible(struct kobject *kobj,
struct bin_attribute *a, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct cros_ec_dev *ec = to_cros_ec_dev(dev);
struct device_node *np = ec->ec_dev->dev->of_node;
if (IS_ENABLED(CONFIG_OF) && np) {
if (of_property_read_bool(np, "google,has-vbc-nvram"))
return a->attr.mode;
}
return 0;
}
static BIN_ATTR_RW(vboot_context, 16); static BIN_ATTR_RW(vboot_context, 16);
static struct bin_attribute *cros_ec_vbc_bin_attrs[] = { static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
...@@ -130,6 +118,43 @@ static struct bin_attribute *cros_ec_vbc_bin_attrs[] = { ...@@ -130,6 +118,43 @@ static struct bin_attribute *cros_ec_vbc_bin_attrs[] = {
struct attribute_group cros_ec_vbc_attr_group = { struct attribute_group cros_ec_vbc_attr_group = {
.name = "vbc", .name = "vbc",
.bin_attrs = cros_ec_vbc_bin_attrs, .bin_attrs = cros_ec_vbc_bin_attrs,
.is_bin_visible = cros_ec_vbc_is_visible,
}; };
EXPORT_SYMBOL(cros_ec_vbc_attr_group);
static int cros_ec_vbc_probe(struct platform_device *pd)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
struct device *dev = &pd->dev;
int ret;
ret = sysfs_create_group(&ec_dev->class_dev.kobj,
&cros_ec_vbc_attr_group);
if (ret < 0)
dev_err(dev, "failed to create %s attributes. err=%d\n",
cros_ec_vbc_attr_group.name, ret);
return ret;
}
static int cros_ec_vbc_remove(struct platform_device *pd)
{
struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
sysfs_remove_group(&ec_dev->class_dev.kobj,
&cros_ec_vbc_attr_group);
return 0;
}
static struct platform_driver cros_ec_vbc_driver = {
.driver = {
.name = DRV_NAME,
},
.probe = cros_ec_vbc_probe,
.remove = cros_ec_vbc_remove,
};
module_platform_driver(cros_ec_vbc_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Expose the vboot context nvram to userspace");
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -817,6 +817,18 @@ config STM32_WATCHDOG ...@@ -817,6 +817,18 @@ config STM32_WATCHDOG
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called stm32_iwdg. module will be called stm32_iwdg.
config STPMIC1_WATCHDOG
tristate "STPMIC1 PMIC watchdog support"
depends on MFD_STPMIC1
select WATCHDOG_CORE
help
Say Y here to include watchdog support embedded into STPMIC1 PMIC.
If the watchdog timer expires, stpmic1 will shut down all its power
supplies.
To compile this driver as a module, choose M here: the
module will be called spmic1_wdt.
config UNIPHIER_WATCHDOG config UNIPHIER_WATCHDOG
tristate "UniPhier watchdog support" tristate "UniPhier watchdog support"
depends on ARCH_UNIPHIER || COMPILE_TEST depends on ARCH_UNIPHIER || COMPILE_TEST
......
...@@ -220,3 +220,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o ...@@ -220,3 +220,4 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) STMicroelectronics 2018
// Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
#include <linux/kernel.h>
#include <linux/mfd/stpmic1.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/watchdog.h>
/* WATCHDOG CONTROL REGISTER bit */
#define WDT_START BIT(0)
#define WDT_PING BIT(1)
#define WDT_START_MASK BIT(0)
#define WDT_PING_MASK BIT(1)
#define WDT_STOP 0
#define PMIC_WDT_MIN_TIMEOUT 1
#define PMIC_WDT_MAX_TIMEOUT 256
#define PMIC_WDT_DEFAULT_TIMEOUT 30
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
struct stpmic1_wdt {
struct stpmic1 *pmic;
struct watchdog_device wdtdev;
};
static int pmic_wdt_start(struct watchdog_device *wdd)
{
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
return regmap_update_bits(wdt->pmic->regmap,
WCHDG_CR, WDT_START_MASK, WDT_START);
}
static int pmic_wdt_stop(struct watchdog_device *wdd)
{
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
return regmap_update_bits(wdt->pmic->regmap,
WCHDG_CR, WDT_START_MASK, WDT_STOP);
}
static int pmic_wdt_ping(struct watchdog_device *wdd)
{
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
return regmap_update_bits(wdt->pmic->regmap,
WCHDG_CR, WDT_PING_MASK, WDT_PING);
}
static int pmic_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
struct stpmic1_wdt *wdt = watchdog_get_drvdata(wdd);
wdd->timeout = timeout;
/* timeout is equal to register value + 1 */
return regmap_write(wdt->pmic->regmap, WCHDG_TIMER_CR, timeout - 1);
}
static const struct watchdog_info pmic_watchdog_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "STPMIC1 PMIC Watchdog",
};
static const struct watchdog_ops pmic_watchdog_ops = {
.owner = THIS_MODULE,
.start = pmic_wdt_start,
.stop = pmic_wdt_stop,
.ping = pmic_wdt_ping,
.set_timeout = pmic_wdt_set_timeout,
};
static int pmic_wdt_probe(struct platform_device *pdev)
{
int ret;
struct stpmic1 *pmic;
struct stpmic1_wdt *wdt;
if (!pdev->dev.parent)
return -EINVAL;
pmic = dev_get_drvdata(pdev->dev.parent);
if (!pmic)
return -EINVAL;
wdt = devm_kzalloc(&pdev->dev, sizeof(struct stpmic1_wdt), GFP_KERNEL);
if (!wdt)
return -ENOMEM;
wdt->pmic = pmic;
wdt->wdtdev.info = &pmic_watchdog_info;
wdt->wdtdev.ops = &pmic_watchdog_ops;
wdt->wdtdev.min_timeout = PMIC_WDT_MIN_TIMEOUT;
wdt->wdtdev.max_timeout = PMIC_WDT_MAX_TIMEOUT;
wdt->wdtdev.parent = &pdev->dev;
wdt->wdtdev.timeout = PMIC_WDT_DEFAULT_TIMEOUT;
watchdog_init_timeout(&wdt->wdtdev, 0, &pdev->dev);
watchdog_set_nowayout(&wdt->wdtdev, nowayout);
watchdog_set_drvdata(&wdt->wdtdev, wdt);
ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
if (ret)
return ret;
dev_dbg(wdt->pmic->dev, "PMIC Watchdog driver probed\n");
return 0;
}
static const struct of_device_id of_pmic_wdt_match[] = {
{ .compatible = "st,stpmic1-wdt" },
{ },
};
MODULE_DEVICE_TABLE(of, of_pmic_wdt_match);
static struct platform_driver stpmic1_wdt_driver = {
.probe = pmic_wdt_probe,
.driver = {
.name = "stpmic1-wdt",
.of_match_table = of_pmic_wdt_match,
},
};
module_platform_driver(stpmic1_wdt_driver);
MODULE_DESCRIPTION("Watchdog driver for STPMIC1 device");
MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
MODULE_LICENSE("GPL v2");
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Device Tree defines for Lochnagar clocking
*
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
*/
#ifndef DT_BINDINGS_CLK_LOCHNAGAR_H
#define DT_BINDINGS_CLK_LOCHNAGAR_H
#define LOCHNAGAR_CDC_MCLK1 0
#define LOCHNAGAR_CDC_MCLK2 1
#define LOCHNAGAR_DSP_CLKIN 2
#define LOCHNAGAR_GF_CLKOUT1 3
#define LOCHNAGAR_GF_CLKOUT2 4
#define LOCHNAGAR_PSIA1_MCLK 5
#define LOCHNAGAR_PSIA2_MCLK 6
#define LOCHNAGAR_SPDIF_MCLK 7
#define LOCHNAGAR_ADAT_MCLK 8
#define LOCHNAGAR_SOUNDCARD_MCLK 9
#define LOCHNAGAR_SPDIF_CLKOUT 10
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
* Author: Philippe Peurichard <philippe.peurichard@st.com>,
* Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
*/
#ifndef __DT_BINDINGS_STPMIC1_H__
#define __DT_BINDINGS_STPMIC1_H__
/* IRQ definitions */
#define IT_PONKEY_F 0
#define IT_PONKEY_R 1
#define IT_WAKEUP_F 2
#define IT_WAKEUP_R 3
#define IT_VBUS_OTG_F 4
#define IT_VBUS_OTG_R 5
#define IT_SWOUT_F 6
#define IT_SWOUT_R 7
#define IT_CURLIM_BUCK1 8
#define IT_CURLIM_BUCK2 9
#define IT_CURLIM_BUCK3 10
#define IT_CURLIM_BUCK4 11
#define IT_OCP_OTG 12
#define IT_OCP_SWOUT 13
#define IT_OCP_BOOST 14
#define IT_OVP_BOOST 15
#define IT_CURLIM_LDO1 16
#define IT_CURLIM_LDO2 17
#define IT_CURLIM_LDO3 18
#define IT_CURLIM_LDO4 19
#define IT_CURLIM_LDO5 20
#define IT_CURLIM_LDO6 21
#define IT_SHORT_SWOTG 22
#define IT_SHORT_SWOUT 23
#define IT_TWARN_F 24
#define IT_TWARN_R 25
#define IT_VINLOW_F 26
#define IT_VINLOW_R 27
#define IT_SWIN_F 30
#define IT_SWIN_R 31
/* BUCK MODES definitions */
#define STPMIC1_BUCK_MODE_NORMAL 0
#define STPMIC1_BUCK_MODE_LP 2
#endif /* __DT_BINDINGS_STPMIC1_H__ */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Device Tree defines for Lochnagar pinctrl
*
* Copyright (c) 2018 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
*/
#ifndef DT_BINDINGS_PINCTRL_LOCHNAGAR_H
#define DT_BINDINGS_PINCTRL_LOCHNAGAR_H
#define LOCHNAGAR1_PIN_CDC_RESET 0
#define LOCHNAGAR1_PIN_DSP_RESET 1
#define LOCHNAGAR1_PIN_CDC_CIF1MODE 2
#define LOCHNAGAR1_PIN_NUM_GPIOS 3
#define LOCHNAGAR2_PIN_CDC_RESET 0
#define LOCHNAGAR2_PIN_DSP_RESET 1
#define LOCHNAGAR2_PIN_CDC_CIF1MODE 2
#define LOCHNAGAR2_PIN_CDC_LDOENA 3
#define LOCHNAGAR2_PIN_SPDIF_HWMODE 4
#define LOCHNAGAR2_PIN_SPDIF_RESET 5
#define LOCHNAGAR2_PIN_FPGA_GPIO1 6
#define LOCHNAGAR2_PIN_FPGA_GPIO2 7
#define LOCHNAGAR2_PIN_FPGA_GPIO3 8
#define LOCHNAGAR2_PIN_FPGA_GPIO4 9
#define LOCHNAGAR2_PIN_FPGA_GPIO5 10
#define LOCHNAGAR2_PIN_FPGA_GPIO6 11
#define LOCHNAGAR2_PIN_CDC_GPIO1 12
#define LOCHNAGAR2_PIN_CDC_GPIO2 13
#define LOCHNAGAR2_PIN_CDC_GPIO3 14
#define LOCHNAGAR2_PIN_CDC_GPIO4 15
#define LOCHNAGAR2_PIN_CDC_GPIO5 16
#define LOCHNAGAR2_PIN_CDC_GPIO6 17
#define LOCHNAGAR2_PIN_CDC_GPIO7 18
#define LOCHNAGAR2_PIN_CDC_GPIO8 19
#define LOCHNAGAR2_PIN_DSP_GPIO1 20
#define LOCHNAGAR2_PIN_DSP_GPIO2 21
#define LOCHNAGAR2_PIN_DSP_GPIO3 22
#define LOCHNAGAR2_PIN_DSP_GPIO4 23
#define LOCHNAGAR2_PIN_DSP_GPIO5 24
#define LOCHNAGAR2_PIN_DSP_GPIO6 25
#define LOCHNAGAR2_PIN_GF_GPIO2 26
#define LOCHNAGAR2_PIN_GF_GPIO3 27
#define LOCHNAGAR2_PIN_GF_GPIO7 28
#define LOCHNAGAR2_PIN_CDC_AIF1_BCLK 29
#define LOCHNAGAR2_PIN_CDC_AIF1_RXDAT 30
#define LOCHNAGAR2_PIN_CDC_AIF1_LRCLK 31
#define LOCHNAGAR2_PIN_CDC_AIF1_TXDAT 32
#define LOCHNAGAR2_PIN_CDC_AIF2_BCLK 33
#define LOCHNAGAR2_PIN_CDC_AIF2_RXDAT 34
#define LOCHNAGAR2_PIN_CDC_AIF2_LRCLK 35
#define LOCHNAGAR2_PIN_CDC_AIF2_TXDAT 36
#define LOCHNAGAR2_PIN_CDC_AIF3_BCLK 37
#define LOCHNAGAR2_PIN_CDC_AIF3_RXDAT 38
#define LOCHNAGAR2_PIN_CDC_AIF3_LRCLK 39
#define LOCHNAGAR2_PIN_CDC_AIF3_TXDAT 40
#define LOCHNAGAR2_PIN_DSP_AIF1_BCLK 41
#define LOCHNAGAR2_PIN_DSP_AIF1_RXDAT 42
#define LOCHNAGAR2_PIN_DSP_AIF1_LRCLK 43
#define LOCHNAGAR2_PIN_DSP_AIF1_TXDAT 44
#define LOCHNAGAR2_PIN_DSP_AIF2_BCLK 45
#define LOCHNAGAR2_PIN_DSP_AIF2_RXDAT 46
#define LOCHNAGAR2_PIN_DSP_AIF2_LRCLK 47
#define LOCHNAGAR2_PIN_DSP_AIF2_TXDAT 48
#define LOCHNAGAR2_PIN_PSIA1_BCLK 49
#define LOCHNAGAR2_PIN_PSIA1_RXDAT 50
#define LOCHNAGAR2_PIN_PSIA1_LRCLK 51
#define LOCHNAGAR2_PIN_PSIA1_TXDAT 52
#define LOCHNAGAR2_PIN_PSIA2_BCLK 53
#define LOCHNAGAR2_PIN_PSIA2_RXDAT 54
#define LOCHNAGAR2_PIN_PSIA2_LRCLK 55
#define LOCHNAGAR2_PIN_PSIA2_TXDAT 56
#define LOCHNAGAR2_PIN_GF_AIF3_BCLK 57
#define LOCHNAGAR2_PIN_GF_AIF3_RXDAT 58
#define LOCHNAGAR2_PIN_GF_AIF3_LRCLK 59
#define LOCHNAGAR2_PIN_GF_AIF3_TXDAT 60
#define LOCHNAGAR2_PIN_GF_AIF4_BCLK 61
#define LOCHNAGAR2_PIN_GF_AIF4_RXDAT 62
#define LOCHNAGAR2_PIN_GF_AIF4_LRCLK 63
#define LOCHNAGAR2_PIN_GF_AIF4_TXDAT 64
#define LOCHNAGAR2_PIN_GF_AIF1_BCLK 65
#define LOCHNAGAR2_PIN_GF_AIF1_RXDAT 66
#define LOCHNAGAR2_PIN_GF_AIF1_LRCLK 67
#define LOCHNAGAR2_PIN_GF_AIF1_TXDAT 68
#define LOCHNAGAR2_PIN_GF_AIF2_BCLK 69
#define LOCHNAGAR2_PIN_GF_AIF2_RXDAT 70
#define LOCHNAGAR2_PIN_GF_AIF2_LRCLK 71
#define LOCHNAGAR2_PIN_GF_AIF2_TXDAT 72
#define LOCHNAGAR2_PIN_DSP_UART1_RX 73
#define LOCHNAGAR2_PIN_DSP_UART1_TX 74
#define LOCHNAGAR2_PIN_DSP_UART2_RX 75
#define LOCHNAGAR2_PIN_DSP_UART2_TX 76
#define LOCHNAGAR2_PIN_GF_UART2_RX 77
#define LOCHNAGAR2_PIN_GF_UART2_TX 78
#define LOCHNAGAR2_PIN_USB_UART_RX 79
#define LOCHNAGAR2_PIN_CDC_PDMCLK1 80
#define LOCHNAGAR2_PIN_CDC_PDMDAT1 81
#define LOCHNAGAR2_PIN_CDC_PDMCLK2 82
#define LOCHNAGAR2_PIN_CDC_PDMDAT2 83
#define LOCHNAGAR2_PIN_CDC_DMICCLK1 84
#define LOCHNAGAR2_PIN_CDC_DMICDAT1 85
#define LOCHNAGAR2_PIN_CDC_DMICCLK2 86
#define LOCHNAGAR2_PIN_CDC_DMICDAT2 87
#define LOCHNAGAR2_PIN_CDC_DMICCLK3 88
#define LOCHNAGAR2_PIN_CDC_DMICDAT3 89
#define LOCHNAGAR2_PIN_CDC_DMICCLK4 90
#define LOCHNAGAR2_PIN_CDC_DMICDAT4 91
#define LOCHNAGAR2_PIN_DSP_DMICCLK1 92
#define LOCHNAGAR2_PIN_DSP_DMICDAT1 93
#define LOCHNAGAR2_PIN_DSP_DMICCLK2 94
#define LOCHNAGAR2_PIN_DSP_DMICDAT2 95
#define LOCHNAGAR2_PIN_I2C2_SCL 96
#define LOCHNAGAR2_PIN_I2C2_SDA 97
#define LOCHNAGAR2_PIN_I2C3_SCL 98
#define LOCHNAGAR2_PIN_I2C3_SDA 99
#define LOCHNAGAR2_PIN_I2C4_SCL 100
#define LOCHNAGAR2_PIN_I2C4_SDA 101
#define LOCHNAGAR2_PIN_DSP_STANDBY 102
#define LOCHNAGAR2_PIN_CDC_MCLK1 103
#define LOCHNAGAR2_PIN_CDC_MCLK2 104
#define LOCHNAGAR2_PIN_DSP_CLKIN 105
#define LOCHNAGAR2_PIN_PSIA1_MCLK 106
#define LOCHNAGAR2_PIN_PSIA2_MCLK 107
#define LOCHNAGAR2_PIN_GF_GPIO1 108
#define LOCHNAGAR2_PIN_GF_GPIO5 109
#define LOCHNAGAR2_PIN_DSP_GPIO20 110
#define LOCHNAGAR2_PIN_NUM_GPIOS 111
#endif
...@@ -281,16 +281,6 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, ...@@ -281,16 +281,6 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg); struct cros_ec_command *msg);
/**
* cros_ec_remove() - Remove a ChromeOS EC.
* @ec_dev: Device to register.
*
* Call this to deregister a ChromeOS EC, then clean up any private data.
*
* Return: 0 on success or negative error code.
*/
int cros_ec_remove(struct cros_ec_device *ec_dev);
/** /**
* cros_ec_register() - Register a new ChromeOS EC, using the provided info. * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
* @ec_dev: Device to register. * @ec_dev: Device to register.
...@@ -335,15 +325,4 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event); ...@@ -335,15 +325,4 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
*/ */
u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev); u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
/* sysfs stuff */
extern struct attribute_group cros_ec_attr_group;
extern struct attribute_group cros_ec_lightbar_attr_group;
extern struct attribute_group cros_ec_vbc_attr_group;
/* debugfs stuff */
int cros_ec_debugfs_init(struct cros_ec_dev *ec);
void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
#endif /* __LINUX_MFD_CROS_EC_H */ #endif /* __LINUX_MFD_CROS_EC_H */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Lochnagar internals
*
* Copyright (c) 2013-2018 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
*/
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#ifndef CIRRUS_LOCHNAGAR_H
#define CIRRUS_LOCHNAGAR_H
enum lochnagar_type {
LOCHNAGAR1,
LOCHNAGAR2,
};
/**
* struct lochnagar - Core data for the Lochnagar audio board driver.
*
* @type: The type of Lochnagar device connected.
* @dev: A pointer to the struct device for the main MFD.
* @regmap: The devices main register map.
* @analogue_config_lock: Lock used to protect updates in the analogue
* configuration as these must not be changed whilst the hardware is processing
* the last update.
*/
struct lochnagar {
enum lochnagar_type type;
struct device *dev;
struct regmap *regmap;
/* Lock to protect updates to the analogue configuration */
struct mutex analogue_config_lock;
};
/* Register Addresses */
#define LOCHNAGAR_SOFTWARE_RESET 0x00
#define LOCHNAGAR_FIRMWARE_ID1 0x01
#define LOCHNAGAR_FIRMWARE_ID2 0x02
/* (0x0000) Software Reset */
#define LOCHNAGAR_DEVICE_ID_MASK 0xFFFC
#define LOCHNAGAR_DEVICE_ID_SHIFT 2
#define LOCHNAGAR_REV_ID_MASK 0x0003
#define LOCHNAGAR_REV_ID_SHIFT 0
int lochnagar_update_config(struct lochnagar *lochnagar);
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Lochnagar1 register definitions
*
* Copyright (c) 2017-2018 Cirrus Logic, Inc. and
* Cirrus Logic International Semiconductor Ltd.
*
* Author: Charles Keepax <ckeepax@opensource.cirrus.com>
*/
#ifndef LOCHNAGAR1_REGISTERS_H
#define LOCHNAGAR1_REGISTERS_H
/* Register Addresses */
#define LOCHNAGAR1_CDC_AIF1_SEL 0x0008
#define LOCHNAGAR1_CDC_AIF2_SEL 0x0009
#define LOCHNAGAR1_CDC_AIF3_SEL 0x000A
#define LOCHNAGAR1_CDC_MCLK1_SEL 0x000B
#define LOCHNAGAR1_CDC_MCLK2_SEL 0x000C
#define LOCHNAGAR1_CDC_AIF_CTRL1 0x000D
#define LOCHNAGAR1_CDC_AIF_CTRL2 0x000E
#define LOCHNAGAR1_EXT_AIF_CTRL 0x000F
#define LOCHNAGAR1_DSP_AIF1_SEL 0x0010
#define LOCHNAGAR1_DSP_AIF2_SEL 0x0011
#define LOCHNAGAR1_DSP_CLKIN_SEL 0x0012
#define LOCHNAGAR1_DSP_AIF 0x0013
#define LOCHNAGAR1_GF_AIF1 0x0014
#define LOCHNAGAR1_GF_AIF2 0x0015
#define LOCHNAGAR1_PSIA_AIF 0x0016
#define LOCHNAGAR1_PSIA1_SEL 0x0017
#define LOCHNAGAR1_PSIA2_SEL 0x0018
#define LOCHNAGAR1_SPDIF_AIF_SEL 0x0019
#define LOCHNAGAR1_GF_AIF3_SEL 0x001C
#define LOCHNAGAR1_GF_AIF4_SEL 0x001D
#define LOCHNAGAR1_GF_CLKOUT1_SEL 0x001E
#define LOCHNAGAR1_GF_AIF1_SEL 0x001F
#define LOCHNAGAR1_GF_AIF2_SEL 0x0020
#define LOCHNAGAR1_GF_GPIO2 0x0026
#define LOCHNAGAR1_GF_GPIO3 0x0027
#define LOCHNAGAR1_GF_GPIO7 0x0028
#define LOCHNAGAR1_RST 0x0029
#define LOCHNAGAR1_LED1 0x002A
#define LOCHNAGAR1_LED2 0x002B
#define LOCHNAGAR1_I2C_CTRL 0x0046
/*
* (0x0008 - 0x000C, 0x0010 - 0x0012, 0x0017 - 0x0020)
* CDC_AIF1_SEL - GF_AIF2_SEL
*/
#define LOCHNAGAR1_SRC_MASK 0xFF
#define LOCHNAGAR1_SRC_SHIFT 0
/* (0x000D) CDC_AIF_CTRL1 */
#define LOCHNAGAR1_CDC_AIF2_LRCLK_DIR_MASK 0x40
#define LOCHNAGAR1_CDC_AIF2_LRCLK_DIR_SHIFT 6
#define LOCHNAGAR1_CDC_AIF2_BCLK_DIR_MASK 0x20
#define LOCHNAGAR1_CDC_AIF2_BCLK_DIR_SHIFT 5
#define LOCHNAGAR1_CDC_AIF2_ENA_MASK 0x10
#define LOCHNAGAR1_CDC_AIF2_ENA_SHIFT 4
#define LOCHNAGAR1_CDC_AIF1_LRCLK_DIR_MASK 0x04
#define LOCHNAGAR1_CDC_AIF1_LRCLK_DIR_SHIFT 2
#define LOCHNAGAR1_CDC_AIF1_BCLK_DIR_MASK 0x02
#define LOCHNAGAR1_CDC_AIF1_BCLK_DIR_SHIFT 1
#define LOCHNAGAR1_CDC_AIF1_ENA_MASK 0x01
#define LOCHNAGAR1_CDC_AIF1_ENA_SHIFT 0
/* (0x000E) CDC_AIF_CTRL2 */
#define LOCHNAGAR1_CDC_AIF3_LRCLK_DIR_MASK 0x40
#define LOCHNAGAR1_CDC_AIF3_LRCLK_DIR_SHIFT 6
#define LOCHNAGAR1_CDC_AIF3_BCLK_DIR_MASK 0x20
#define LOCHNAGAR1_CDC_AIF3_BCLK_DIR_SHIFT 5
#define LOCHNAGAR1_CDC_AIF3_ENA_MASK 0x10
#define LOCHNAGAR1_CDC_AIF3_ENA_SHIFT 4
#define LOCHNAGAR1_CDC_MCLK1_ENA_MASK 0x02
#define LOCHNAGAR1_CDC_MCLK1_ENA_SHIFT 1
#define LOCHNAGAR1_CDC_MCLK2_ENA_MASK 0x01
#define LOCHNAGAR1_CDC_MCLK2_ENA_SHIFT 0
/* (0x000F) EXT_AIF_CTRL */
#define LOCHNAGAR1_SPDIF_AIF_LRCLK_DIR_MASK 0x20
#define LOCHNAGAR1_SPDIF_AIF_LRCLK_DIR_SHIFT 5
#define LOCHNAGAR1_SPDIF_AIF_BCLK_DIR_MASK 0x10
#define LOCHNAGAR1_SPDIF_AIF_BCLK_DIR_SHIFT 4
#define LOCHNAGAR1_SPDIF_AIF_ENA_MASK 0x08
#define LOCHNAGAR1_SPDIF_AIF_ENA_SHIFT 3
/* (0x0013) DSP_AIF */
#define LOCHNAGAR1_DSP_AIF2_LRCLK_DIR_MASK 0x40
#define LOCHNAGAR1_DSP_AIF2_LRCLK_DIR_SHIFT 6
#define LOCHNAGAR1_DSP_AIF2_BCLK_DIR_MASK 0x20
#define LOCHNAGAR1_DSP_AIF2_BCLK_DIR_SHIFT 5
#define LOCHNAGAR1_DSP_AIF2_ENA_MASK 0x10
#define LOCHNAGAR1_DSP_AIF2_ENA_SHIFT 4
#define LOCHNAGAR1_DSP_CLKIN_ENA_MASK 0x08
#define LOCHNAGAR1_DSP_CLKIN_ENA_SHIFT 3
#define LOCHNAGAR1_DSP_AIF1_LRCLK_DIR_MASK 0x04
#define LOCHNAGAR1_DSP_AIF1_LRCLK_DIR_SHIFT 2
#define LOCHNAGAR1_DSP_AIF1_BCLK_DIR_MASK 0x02
#define LOCHNAGAR1_DSP_AIF1_BCLK_DIR_SHIFT 1
#define LOCHNAGAR1_DSP_AIF1_ENA_MASK 0x01
#define LOCHNAGAR1_DSP_AIF1_ENA_SHIFT 0
/* (0x0014) GF_AIF1 */
#define LOCHNAGAR1_GF_CLKOUT1_ENA_MASK 0x40
#define LOCHNAGAR1_GF_CLKOUT1_ENA_SHIFT 6
#define LOCHNAGAR1_GF_AIF3_LRCLK_DIR_MASK 0x20
#define LOCHNAGAR1_GF_AIF3_LRCLK_DIR_SHIFT 5
#define LOCHNAGAR1_GF_AIF3_BCLK_DIR_MASK 0x10
#define LOCHNAGAR1_GF_AIF3_BCLK_DIR_SHIFT 4
#define LOCHNAGAR1_GF_AIF3_ENA_MASK 0x08
#define LOCHNAGAR1_GF_AIF3_ENA_SHIFT 3
#define LOCHNAGAR1_GF_AIF1_LRCLK_DIR_MASK 0x04
#define LOCHNAGAR1_GF_AIF1_LRCLK_DIR_SHIFT 2
#define LOCHNAGAR1_GF_AIF1_BCLK_DIR_MASK 0x02
#define LOCHNAGAR1_GF_AIF1_BCLK_DIR_SHIFT 1
#define LOCHNAGAR1_GF_AIF1_ENA_MASK 0x01
#define LOCHNAGAR1_GF_AIF1_ENA_SHIFT 0
/* (0x0015) GF_AIF2 */
#define LOCHNAGAR1_GF_AIF4_LRCLK_DIR_MASK 0x20
#define LOCHNAGAR1_GF_AIF4_LRCLK_DIR_SHIFT 5
#define LOCHNAGAR1_GF_AIF4_BCLK_DIR_MASK 0x10
#define LOCHNAGAR1_GF_AIF4_BCLK_DIR_SHIFT 4
#define LOCHNAGAR1_GF_AIF4_ENA_MASK 0x08
#define LOCHNAGAR1_GF_AIF4_ENA_SHIFT 3
#define LOCHNAGAR1_GF_AIF2_LRCLK_DIR_MASK 0x04
#define LOCHNAGAR1_GF_AIF2_LRCLK_DIR_SHIFT 2
#define LOCHNAGAR1_GF_AIF2_BCLK_DIR_MASK 0x02
#define LOCHNAGAR1_GF_AIF2_BCLK_DIR_SHIFT 1
#define LOCHNAGAR1_GF_AIF2_ENA_MASK 0x01
#define LOCHNAGAR1_GF_AIF2_ENA_SHIFT 0
/* (0x0016) PSIA_AIF */
#define LOCHNAGAR1_PSIA2_LRCLK_DIR_MASK 0x40
#define LOCHNAGAR1_PSIA2_LRCLK_DIR_SHIFT 6
#define LOCHNAGAR1_PSIA2_BCLK_DIR_MASK 0x20
#define LOCHNAGAR1_PSIA2_BCLK_DIR_SHIFT 5
#define LOCHNAGAR1_PSIA2_ENA_MASK 0x10
#define LOCHNAGAR1_PSIA2_ENA_SHIFT 4
#define LOCHNAGAR1_PSIA1_LRCLK_DIR_MASK 0x04
#define LOCHNAGAR1_PSIA1_LRCLK_DIR_SHIFT 2
#define LOCHNAGAR1_PSIA1_BCLK_DIR_MASK 0x02
#define LOCHNAGAR1_PSIA1_BCLK_DIR_SHIFT 1
#define LOCHNAGAR1_PSIA1_ENA_MASK 0x01
#define LOCHNAGAR1_PSIA1_ENA_SHIFT 0
/* (0x0029) RST */
#define LOCHNAGAR1_DSP_RESET_MASK 0x02
#define LOCHNAGAR1_DSP_RESET_SHIFT 1
#define LOCHNAGAR1_CDC_RESET_MASK 0x01
#define LOCHNAGAR1_CDC_RESET_SHIFT 0
/* (0x0046) I2C_CTRL */
#define LOCHNAGAR1_CDC_CIF_MODE_MASK 0x01
#define LOCHNAGAR1_CDC_CIF_MODE_SHIFT 0
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -137,6 +137,10 @@ ...@@ -137,6 +137,10 @@
#define TPS65218_CONFIG1_PGDLY_MASK 0x18 #define TPS65218_CONFIG1_PGDLY_MASK 0x18
#define TPS65218_CONFIG1_STRICT BIT(2) #define TPS65218_CONFIG1_STRICT BIT(2)
#define TPS65218_CONFIG1_UVLO_MASK 0x3 #define TPS65218_CONFIG1_UVLO_MASK 0x3
#define TPS65218_CONFIG1_UVLO_2750000 0x0
#define TPS65218_CONFIG1_UVLO_2950000 0x1
#define TPS65218_CONFIG1_UVLO_3250000 0x2
#define TPS65218_CONFIG1_UVLO_3350000 0x3
#define TPS65218_CONFIG2_DC12_RST BIT(7) #define TPS65218_CONFIG2_DC12_RST BIT(7)
#define TPS65218_CONFIG2_UVLOHYS BIT(6) #define TPS65218_CONFIG2_UVLOHYS BIT(6)
......
...@@ -418,7 +418,6 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, ...@@ -418,7 +418,6 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
int count, u16 *buf); int count, u16 *buf);
int wm831x_device_init(struct wm831x *wm831x, int irq); int wm831x_device_init(struct wm831x *wm831x, int irq);
void wm831x_device_exit(struct wm831x *wm831x);
int wm831x_device_suspend(struct wm831x *wm831x); int wm831x_device_suspend(struct wm831x *wm831x);
void wm831x_device_shutdown(struct wm831x *wm831x); void wm831x_device_shutdown(struct wm831x *wm831x);
int wm831x_irq_init(struct wm831x *wm831x, int irq); int wm831x_irq_init(struct wm831x *wm831x, int irq);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment