Commit f0c1bc95 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mfd-for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd

Pull MFD updates from Lee Jones:
 "Changes to existing drivers:

   - Rename child driver [axp288_battery => axp288_fuel_gauge]; axp20x
   - Rename child driver [max77693-flash => max77693-led]; max77693
   - Error handling fixes; intel_soc_pmic
   - GPIO tweaking; intel_soc_pmic
   - Remove non-DT code; vexpress-sysreg, tc3589x
   - Remove unused/legacy code; ti_am335x_tscadc, rts5249, rtsx_gops, rtsx_pcr,
                                rtc-s5m, sec-core, max77693, menelaus,
                                wm5102-tables
   - Trivial fixups; rtsx_pci, da9150-core, sec-core, max7769, max77693,
                     mc13xxx-core, dln2, hi6421-pmic-core, rk808, twl4030-power,
                     lpc_ich, menelaus, twl6040
   - Update register/address values; rts5227, rts5249
   - DT and/or binding document fixups; arizona, da9150, mt6397, axp20x,
                                        qcom-rpm, qcom-spmi-pmic
   - Couple of trivial core Kconfig fixups
   - Remove use of seq_printf return value; ab8500-debugfs
   - Remove __exit markups; menelaus, tps65010
   - Fix platform-device name collisions; mfd-core

  New drivers/supported devices:

   - Add support for wm8280/wm8281 into arizona
   - Add support for COMe-cBL6 into kempld-core
   - Add support for rts524a and rts525a into rts5249
   - Add support for ipq8064 into qcom_rpm
   - Add support for extcon into axp20x
   - New MediaTek MT6397 PMIC driver
   - New Maxim MAX77843 PMIC dirver
   - New Intel Quark X1000 I2C-GPIO driver
   - New Skyworks SKY81452 driver"

* tag 'mfd-for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (76 commits)
  mfd: sec: Fix RTC alarm interrupt number on S2MPS11
  mfd: wm5102: Remove registers for output 3R from readable list
  mfd: tps65010: Remove incorrect __exit markups
  mfd: devicetree: bindings: Add Qualcomm RPM regulator subnodes
  mfd: axp20x: Add support for extcon cell
  mfd: lpc_ich: Sort IDs
  mfd: twl6040: Remove wrong and unneeded "platform:twl6040" modalias
  mfd: qcom-spmi-pmic: Add specific compatible strings for Qualcomm's SPMI PMIC's
  mfd: axp20x: Fix duplicate const for model names
  mfd: menelaus: Use macro for magic number
  mfd: menelaus: Drop support for SW controller VCORE
  mfd: menelaus: Delete omap_has_menelaus
  mfd: arizona: Correct type of gpio_defaults
  mfd: lpc_ich: Sort IDs
  mfd: Fix a typo in Kconfig
  mfd: qcom_rpm: Add support for IPQ8064
  mfd: devicetree: qcom_rpm: Document IPQ8064 resources
  mfd: core: Fix platform-device name collisions
  mfd: intel_quark_i2c_gpio: Don't crash if !DMI
  dt-bindings: Add vendor-prefix for X-Powers
  ...
parents 1dcf58d6 e554a99e
......@@ -89,6 +89,7 @@ ricoh,rv5c386 I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
sii,s35390a 2-wire CMOS real-time clock
skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
st-micro,24c256 i2c serial eeprom (24cxx)
stm,m41t00 Serial Access TIMEKEEPER
stm,m41t62 Serial real-time clock (RTC) with alarm
......
......@@ -8,6 +8,7 @@ Required properties:
- compatible : One of the following chip-specific strings:
"wlf,wm5102"
"wlf,wm5110"
"wlf,wm8280"
"wlf,wm8997"
- reg : I2C slave address when connected using I2C, chip select number when
using SPI.
......@@ -26,21 +27,27 @@ Required properties:
- #gpio-cells : Must be 2. The first cell is the pin number and the
second cell is used to specify optional parameters (currently unused).
- AVDD-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply (wm5102, wm5110),
CPVDD-supply, SPKVDDL-supply (wm5102, wm5110), SPKVDDR-supply (wm5102,
wm5110), SPKVDD-supply (wm8997) : Power supplies for the device, as covered
in Documentation/devicetree/bindings/regulator/regulator.txt
- AVDD-supply, DBVDD1-supply, CPVDD-supply : Power supplies for the device,
as covered in Documentation/devicetree/bindings/regulator/regulator.txt
- DBVDD2-supply, DBVDD3-supply : Additional databus power supplies (wm5102,
wm5110, wm8280)
- SPKVDDL-supply, SPKVDDR-supply : Speaker driver power supplies (wm5102,
wm5110, wm8280)
- SPKVDD-supply : Speaker driver power supply (wm8997)
Optional properties:
- wlf,reset : GPIO specifier for the GPIO controlling /RESET
- wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA
- wlf,gpio-defaults : A list of GPIO configuration register values. If
absent, no configuration of these registers is performed. If any
entry has a value that is out of range for a 16 bit register then
the chip default will be used. If present exactly five values must
be specified.
- wlf,gpio-defaults : A list of GPIO configuration register values. Defines
for the appropriate values can found in <dt-bindings/mfd/arizona.txt>. If
absent, no configuration of these registers is performed. If any entry has
a value that is out of range for a 16 bit register then the chip default
will be used. If present exactly five values must be specified.
- wlf,inmode : A list of INn_MODE register values, where n is the number
of input signals. Valid values are 0 (Differential), 1 (Single-ended) and
......@@ -49,6 +56,12 @@ Optional properties:
input singals. If values less than the number of input signals, elements
that has not been specifed are set to 0 by default.
- wlf,dmic-ref : DMIC reference voltage source for each input, can be
selected from either MICVDD or one of the MICBIAS's, defines
(ARIZONA_DMIC_xxxx) are provided in <dt-bindings/mfd/arizona.txt>. If
present, the number of values should be less than or equal to the
number of inputs, unspecified inputs will use the chip default.
- DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
they are being externally supplied. As covered in
Documentation/devicetree/bindings/regulator/regulator.txt
......@@ -73,10 +86,10 @@ codec: wm5102@1a {
#gpio-cells = <2>;
wlf,gpio-defaults = <
0x00000000 /* AIF1TXLRCLK */
0xffffffff
0xffffffff
0xffffffff
0xffffffff
ARIZONA_GP_FN_TXLRCLK
ARIZONA_GP_DEFAULT
ARIZONA_GP_DEFAULT
ARIZONA_GP_DEFAULT
ARIZONA_GP_DEFAULT
>;
};
AXP202/AXP209 device tree bindings
The axp20x family current members :
axp202 (X-Powers)
axp209 (X-Powers)
Required properties:
- compatible: "x-powers,axp202" or "x-powers,axp209"
- reg: The I2C slave address for the AXP chip
- interrupt-parent: The parent interrupt controller
- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- interrupt-controller: axp20x has its own internal IRQs
- #interrupt-cells: Should be set to 1
Optional properties:
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
(range: 750-1875). Default: 1.5MHz
- <input>-supply: a phandle to the regulator supply node. May be omitted if
inputs are unregulated, such as using the IPSOUT output
from the PMIC.
- regulators: A node that houses a sub-node for each regulator. Regulators
not used but preferred to be managed by the OS should be
listed as well.
See Documentation/devicetree/bindings/regulator/regulator.txt
for more information on standard regulator bindings.
Optional properties for DCDC regulators:
- x-powers,dcdc-workmode: 1 for PWM mode, 0 for AUTO (PWM/PFM) mode
Default: Current hardware setting
The DCDC regulators work in a mixed PWM/PFM mode,
using PFM under light loads and switching to PWM
for heavier loads. Forcing PWM mode trades efficiency
under light loads for lower output noise. This
probably makes sense for HiFi audio related
applications that aren't battery constrained.
AXP202/AXP209 regulators, type, and corresponding input supply names:
Regulator Type Supply Name Notes
--------- ---- ----------- -----
DCDC2 : DC-DC buck : vin2-supply
DCDC3 : DC-DC buck : vin3-supply
LDO1 : LDO : acin-supply : always on
LDO2 : LDO : ldo24in-supply : shared supply
LDO3 : LDO : ldo3in-supply
LDO4 : LDO : ldo24in-supply : shared supply
LDO5 : LDO : ldo5in-supply
Example:
axp209: pmic@34 {
compatible = "x-powers,axp209";
reg = <0x34>;
interrupt-parent = <&nmi_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <1>;
regulators {
x-powers,dcdc-freq = <1500>;
vdd_cpu: dcdc2 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1450000>;
regulator-name = "vdd-cpu";
};
vdd_int_dll: dcdc3 {
regulator-always-on;
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-int-dll";
};
vdd_rtc: ldo1 {
regulator-always-on;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1400000>;
regulator-name = "vdd-rtc";
};
avcc: ldo2 {
regulator-always-on;
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3300000>;
regulator-name = "avcc";
};
ldo3 {
/* unused but preferred to be managed by OS */
};
};
};
Dialog Semiconductor DA9150 Combined Charger/Fuel-Gauge MFD bindings
DA9150 consists of a group of sub-devices:
Device Description
------ -----------
da9150-gpadc : General Purpose ADC
da9150-charger : Battery Charger
======
Required properties:
- compatible : Should be "dlg,da9150"
- reg: Specifies the I2C slave address
- interrupt-parent: Specifies the phandle of the interrupt controller to which
the IRQs from da9150 are delivered to.
- interrupts: IRQ line info for da9150 chip.
- interrupt-controller: da9150 has internal IRQs (own IRQ domain).
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
further information relating to interrupt properties)
Sub-devices:
- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt
Example:
charger_fg: da9150@58 {
compatible = "dlg,da9150";
reg = <0x58>;
interrupt-parent = <&gpio6>;
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
gpadc: da9150-gpadc {
...
};
da9150-charger {
...
};
};
MediaTek MT6397 Multifunction Device Driver
MT6397 is a multifunction device with the following sub modules:
- Regulator
- RTC
- Audio codec
- GPIO
- Clock
It is interfaced to host controller using SPI interface by a proprietary hardware
called PMIC wrapper or pwrap. MT6397 MFD is a child device of pwrap.
See the following for pwarp node definitions:
Documentation/devicetree/bindings/soc/pwrap.txt
This document describes the binding for MFD device and its sub module.
Required properties:
compatible: "mediatek,mt6397"
Optional subnodes:
- rtc
Required properties:
- compatible: "mediatek,mt6397-rtc"
- regulators
Required properties:
- compatible: "mediatek,mt6397-regulator"
see Documentation/devicetree/bindings/regulator/mt6397-regulator.txt
- codec
Required properties:
- compatible: "mediatek,mt6397-codec"
- clk
Required properties:
- compatible: "mediatek,mt6397-clk"
Example:
pwrap: pwrap@1000f000 {
compatible = "mediatek,mt8135-pwrap";
...
pmic {
compatible = "mediatek,mt6397";
codec: mt6397codec {
compatible = "mediatek,mt6397-codec";
};
regulators {
compatible = "mediatek,mt6397-regulator";
mt6397_vpca15_reg: buck_vpca15 {
regulator-compatible = "buck_vpca15";
regulator-name = "vpca15";
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <1400000>;
regulator-ramp-delay = <12500>;
regulator-always-on;
};
mt6397_vgp4_reg: ldo_vgp4 {
regulator-compatible = "ldo_vgp4";
regulator-name = "vgp4";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <218>;
};
};
};
};
......@@ -15,9 +15,20 @@ each. A function can consume one or more of these fixed-size register regions.
Required properties:
- compatible: Should contain one of:
"qcom,pm8941"
"qcom,pm8841"
"qcom,pma8084"
"qcom,pm8941",
"qcom,pm8841",
"qcom,pma8084",
"qcom,pm8019",
"qcom,pm8226",
"qcom,pm8110",
"qcom,pma8084",
"qcom,pmi8962",
"qcom,pmd9635",
"qcom,pm8994",
"qcom,pmi8994",
"qcom,pm8916",
"qcom,pm8004",
"qcom,pm8909",
or generalized "qcom,spmi-pmic".
- reg: Specifies the SPMI USID slave address for this device.
For more information see:
......
......@@ -12,6 +12,7 @@ frequencies.
"qcom,rpm-apq8064"
"qcom,rpm-msm8660"
"qcom,rpm-msm8960"
"qcom,rpm-ipq8064"
- reg:
Usage: required
......@@ -31,16 +32,6 @@ frequencies.
Value type: <string-array>
Definition: must be the three strings "ack", "err" and "wakeup", in order
- #address-cells:
Usage: required
Value type: <u32>
Definition: must be 1
- #size-cells:
Usage: required
Value type: <u32>
Definition: must be 0
- qcom,ipc:
Usage: required
Value type: <prop-encoded-array>
......@@ -52,6 +43,188 @@ frequencies.
- u32 representing the ipc bit within the register
= SUBNODES
The RPM exposes resources to its subnodes. The below bindings specify the set
of valid subnodes that can operate on these resources.
== Regulators
Regulator nodes are identified by their compatible:
- compatible:
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,rpm-pm8058-regulators"
"qcom,rpm-pm8901-regulators"
"qcom,rpm-pm8921-regulators"
- vdd_l0_l1_lvs-supply:
- vdd_l2_l11_l12-supply:
- vdd_l3_l4_l5-supply:
- vdd_l6_l7-supply:
- vdd_l8-supply:
- vdd_l9-supply:
- vdd_l10-supply:
- vdd_l13_l16-supply:
- vdd_l14_l15-supply:
- vdd_l17_l18-supply:
- vdd_l19_l20-supply:
- vdd_l21-supply:
- vdd_l22-supply:
- vdd_l23_l24_l25-supply:
- vdd_ncp-supply:
- vdd_s0-supply:
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
Usage: optional (pm8058 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- lvs0_in-supply:
- lvs1_in-supply:
- lvs2_in-supply:
- lvs3_in-supply:
- mvs_in-supply:
- vdd_l0-supply:
- vdd_l1-supply:
- vdd_l2-supply:
- vdd_l3-supply:
- vdd_l4-supply:
- vdd_l5-supply:
- vdd_l6-supply:
- vdd_s0-supply:
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
Usage: optional (pm8901 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- vdd_l1_l2_l12_l18-supply:
- vdd_l3_l15_l17-supply:
- vdd_l4_l14-supply:
- vdd_l5_l8_l16-supply:
- vdd_l6_l7-supply:
- vdd_l9_l11-supply:
- vdd_l10_l22-supply:
- vdd_l21_l23_l29-supply:
- vdd_l24-supply:
- vdd_l25-supply:
- vdd_l26-supply:
- vdd_l27-supply:
- vdd_l28-supply:
- vdd_ncp-supply:
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s4-supply:
- vdd_s5-supply:
- vdd_s6-supply:
- vdd_s7-supply:
- vdd_s8-supply:
- vin_5vs-supply:
- vin_lvs1_3_6-supply:
- vin_lvs2-supply:
- vin_lvs4_5_7-supply:
Usage: optional (pm8921 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
The regulator node houses sub-nodes for each regulator within the device. Each
sub-node is identified using the node's name, with valid values listed for each
of the pmics below.
pm8058:
l0, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15,
l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, s0, s1, s2, s3, s4,
lvs0, lvs1, ncp
pm8901:
l0, l1, l2, l3, l4, l5, l6, s0, s1, s2, s3, s4, lvs0, lvs1, lvs2, lvs3,
mvs
pm8921:
s1, s2, s3, s4, s7, s8, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
l12, l14, l15, l16, l17, l18, l21, l22, l23, l24, l25, l26, l27, l28,
l29, lvs1, lvs2, lvs3, lvs4, lvs5, lvs6, lvs7, usb-switch, hdmi-switch,
ncp
The content of each sub-node is defined by the standard binding for regulators -
see regulator.txt - with additional custom properties described below:
=== Switch-mode Power Supply regulator custom properties
- bias-pull-down:
Usage: optional
Value type: <empty>
Definition: enable pull down of the regulator when inactive
- qcom,switch-mode-frequency:
Usage: required
Value type: <u32>
Definition: Frequency (Hz) of the switch-mode power supply;
must be one of:
19200000, 9600000, 6400000, 4800000, 3840000, 3200000,
2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
1480000, 1370000, 1280000, 1200000
- qcom,force-mode:
Usage: optional (default if no other qcom,force-mode is specified)
Value type: <u32>
Defintion: indicates that the regulator should be forced to a
particular mode, valid values are:
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
QCOM_RPM_FORCE_MODE_HPM - force into high power mode
QCOM_RPM_FORCE_MODE_AUTO - allow regulator to automatically
select its own mode based on
realtime current draw, only for:
pm8921 smps and ftsmps
- qcom,power-mode-hysteretic:
Usage: optional
Value type: <empty>
Definition: select that the power supply should operate in hysteretic
mode, instead of the default pwm mode
=== Low-dropout regulator custom properties
- bias-pull-down:
Usage: optional
Value type: <empty>
Definition: enable pull down of the regulator when inactive
- qcom,force-mode:
Usage: optional
Value type: <u32>
Defintion: indicates that the regulator should not be forced to any
particular mode, valid values are:
QCOM_RPM_FORCE_MODE_NONE - do not force any mode
QCOM_RPM_FORCE_MODE_LPM - force into low power mode
QCOM_RPM_FORCE_MODE_HPM - force into high power mode
QCOM_RPM_FORCE_MODE_BYPASS - set regulator to use bypass
mode, i.e. to act as a switch
and not regulate, only for:
pm8921 pldo, nldo and nldo1200
=== Negative Charge Pump custom properties
- qcom,switch-mode-frequency:
Usage: required
Value type: <u32>
Definition: Frequency (Hz) of the swith mode power supply;
must be one of:
19200000, 9600000, 6400000, 4800000, 3840000, 3200000,
2740000, 2400000, 2130000, 1920000, 1750000, 1600000,
1480000, 1370000, 1280000, 1200000
= EXAMPLE
#include <dt-bindings/mfd/qcom-rpm.h>
......@@ -64,7 +237,28 @@ frequencies.
interrupts = <0 19 0>, <0 21 0>, <0 22 0>;
interrupt-names = "ack", "err", "wakeup";
#address-cells = <1>;
#size-cells = <0>;
regulators {
compatible = "qcom,rpm-pm8921-regulators";
vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
s1 {
regulator-min-microvolt = <1225000>;
regulator-max-microvolt = <1225000>;
bias-pull-down;
qcom,switch-mode-frequency = <3200000>;
};
pm8921_s4: s4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
qcom,switch-mode-frequency = <1600000>;
bias-pull-down;
qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>;
};
};
};
SKY81452 bindings
Required properties:
- compatible : Must be "skyworks,sky81452"
- reg : I2C slave address
Required child nodes:
- backlight : container node for backlight following the binding
in video/backlight/sky81452-backlight.txt
- regulator : container node for regulators following the binding
in regulator/sky81452-regulator.txt
Example:
sky81452@2c {
compatible = "skyworks,sky81452";
reg = <0x2c>;
backlight {
compatible = "skyworks,sky81452-backlight";
name = "pwm-backlight";
led-sources = <0 1 2 3 6>;
skyworks,ignore-pwm;
skyworks,phase-shift;
skyworks,current-limit = <2300>;
};
regulator {
lout {
regulator-name = "sky81452-lout";
regulator-min-microvolt = <4500000>;
regulator-max-microvolt = <8000000>;
};
};
};
......@@ -167,6 +167,7 @@ sii Seiko Instruments, Inc.
silergy Silergy Corp.
sirf SiRF Technology, Inc.
sitronix Sitronix Technology Corporation
skyworks Skyworks Solutions, Inc.
smsc Standard Microsystems Corporation
snps Synopsys, Inc.
solidrun SolidRun
......@@ -194,6 +195,7 @@ voipac Voipac Technologies s.r.o.
winbond Winbond Electronics corp.
wlf Wolfson Microelectronics
wm Wondermedia Technologies, Inc.
x-powers X-Powers
xes Extreme Engineering Solutions (X-ES)
xillybus Xillybus Ltd.
xlnx Xilinx
......
SKY81452-backlight bindings
Required properties:
- compatible : Must be "skyworks,sky81452-backlight"
Optional properties:
- name : Name of backlight device. Default is 'lcd-backlight'.
- gpios : GPIO to use to EN pin.
See Documentation/devicetree/bindings/gpio/gpio.txt
- led-sources : List of enabled channels from 0 to 5.
See Documentation/devicetree/bindings/leds/common.txt
- skyworks,ignore-pwm : Ignore both PWM input
- skyworks,dpwm-mode : Enable DPWM dimming mode, otherwise Analog dimming.
- skyworks,phase-shift : Enable phase shift mode
- skyworks,short-detection-threshold-volt
: It should be one of 4, 5, 6 and 7V.
- skyworks,current-limit-mA
: It should be 2300mA or 2750mA.
Example:
backlight {
compatible = "skyworks,sky81452-backlight";
name = "pwm-backlight";
led-sources = <0 1 2 5>;
skyworks,ignore-pwm;
skyworks,phase-shift;
skyworks,current-limit-mA = <2300>;
};
......@@ -1149,6 +1149,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
}
break;
case WM5110:
case WM8280:
switch (arizona->rev) {
case 0 ... 2:
break;
......
......@@ -669,6 +669,7 @@ config GPIO_STP_XWAY
config GPIO_TC3589X
bool "TC3589X GPIOs"
depends on MFD_TC3589X
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
This enables support for the GPIOs found on the TC3589X
......
......@@ -116,6 +116,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
switch (arizona->type) {
case WM5102:
case WM5110:
case WM8280:
case WM8997:
arizona_gpio->gpio_chip.ngpio = 5;
break;
......
......@@ -260,10 +260,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
tc3589x_gpio->chip.dev = &pdev->dev;
tc3589x_gpio->chip.base = -1;
#ifdef CONFIG_OF_GPIO
tc3589x_gpio->chip.of_node = np;
#endif
/* Bring the GPIO module out of reset */
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
......
......@@ -296,7 +296,6 @@ static void tc3589x_keypad_close(struct input_dev *input)
tc3589x_keypad_disable(keypad);
}
#ifdef CONFIG_OF
static const struct tc3589x_keypad_platform_data *
tc3589x_keypad_of_probe(struct device *dev)
{
......@@ -346,14 +345,6 @@ tc3589x_keypad_of_probe(struct device *dev)
return plat;
}
#else
static inline const struct tc3589x_keypad_platform_data *
tc3589x_keypad_of_probe(struct device *dev)
{
return ERR_PTR(-ENODEV);
}
#endif
static int tc3589x_keypad_probe(struct platform_device *pdev)
{
......
......@@ -283,6 +283,18 @@ config HTC_I2CPLD
This device provides input and output GPIOs through an I2C
interface to one or more sub-chips.
config MFD_INTEL_QUARK_I2C_GPIO
tristate "Intel Quark MFD I2C GPIO"
depends on PCI
depends on X86
depends on COMMON_CLK
select MFD_CORE
help
This MFD provides support for I2C and GPIO that exist only
in a single PCI device. It splits the 2 IO devices to
their respective IO driver.
The GPIO exports a total amount of 8 interrupt-capable GPIOs.
config LPC_ICH
tristate "Intel ICH LPC"
depends on PCI
......@@ -364,6 +376,7 @@ config MFD_KEMPLD
* COMe-bIP#
* COMe-bPC2 (ETXexpress-PC)
* COMe-bSC# (ETXexpress-SC T#)
* COMe-cBL6
* COMe-cBT6
* COMe-cCT6
* COMe-cDC2 (microETXexpress-DC)
......@@ -455,6 +468,20 @@ config MFD_MAX77693
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX77843
bool "Maxim Semiconductor MAX77843 PMIC Support"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
Say yes here to add support for Maxim Semiconductor MAX77843.
This is companion Power Management IC with LEDs, Haptic, Charger,
Fuel Gauge, MUIC(Micro USB Interface Controller) controls on chip.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MAX8907
tristate "Maxim Semiconductor MAX8907 PMIC Support"
select MFD_CORE
......@@ -502,6 +529,16 @@ config MFD_MAX8998
additional drivers must be enabled in order to use the functionality
of the device.
config MFD_MT6397
tristate "MediaTek MT6397 PMIC Support"
select MFD_CORE
select IRQ_DOMAIN
help
Say yes here to add support for MediaTek MT6397 PMIC. This is
a Power Management IC. This driver provides common support for
accessing the device; additional drivers must be enabled in order
to use the functionality of the device.
config MFD_MENF21BMC
tristate "MEN 14F021P00 Board Management Controller Support"
depends on I2C
......@@ -655,6 +692,7 @@ config MFD_RT5033
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
This driver provides for the Richtek RT5033 Power Management IC,
which includes the I2C driver and the Core APIs. This driver provides
......@@ -753,6 +791,18 @@ config MFD_SM501_GPIO
lines on the SM501. The platform data is used to supply the
base number for the first GPIO line to register.
config MFD_SKY81452
tristate "Skyworks Solutions SKY81452"
select MFD_CORE
select REGMAP_I2C
depends on I2C
help
This is the core driver for the Skyworks SKY81452 backlight and
voltage regulator device.
This driver can also be built as a module. If so, the module
will be called sky81452.
config MFD_SMSC
bool "SMSC ECE1099 series chips"
depends on I2C=y
......@@ -1210,6 +1260,7 @@ config MFD_TIMBERDALE
config MFD_TC3589X
bool "Toshiba TC35892 and variants"
depends on I2C=y
depends on OF
select MFD_CORE
help
Support for the Toshiba TC35892 and variants I/O Expander.
......@@ -1289,10 +1340,11 @@ config MFD_WM5102
Support for Wolfson Microelectronics WM5102 low power audio SoC
config MFD_WM5110
bool "Wolfson Microelectronics WM5110"
bool "Wolfson Microelectronics WM5110 and WM8280/WM8281"
depends on MFD_ARIZONA
help
Support for Wolfson Microelectronics WM5110 low power audio SoC
Support for Wolfson Microelectronics WM5110 and WM8280/WM8281
low power audio SoC
config MFD_WM8997
bool "Wolfson Microelectronics WM8997"
......@@ -1362,7 +1414,7 @@ config MFD_WM8994
depends on I2C
help
The WM8994 is a highly integrated hi-fi CODEC designed for
smartphone applicatiosn. As well as audio functionality it
smartphone applications. As well as audio functionality it
has on board GPIO and regulator functionality which is
supported via the relevant subsystems. This driver provides
core support for the WM8994, in order to use the actual
......
......@@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
rtsx_pci-objs := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
......@@ -117,6 +117,7 @@ obj-$(CONFIG_MFD_DA9150) += da9150-core.o
obj-$(CONFIG_MFD_MAX14577) += max14577.o
obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX77843) += max77843.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
obj-$(CONFIG_MFD_MAX8925) += max8925.o
......@@ -138,6 +139,7 @@ obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
obj-$(CONFIG_LPC_ICH) += lpc_ich.o
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
......@@ -178,6 +180,8 @@ obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
This diff is collapsed.
......@@ -561,12 +561,23 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
count++;
}
count = 0;
of_property_for_each_u32(arizona->dev->of_node, "wlf,dmic-ref", prop,
cur, val) {
if (count == ARRAY_SIZE(arizona->pdata.dmic_ref))
break;
arizona->pdata.dmic_ref[count] = val;
count++;
}
return 0;
}
const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm5102", .data = (void *)WM5102 },
{ .compatible = "wlf,wm5110", .data = (void *)WM5110 },
{ .compatible = "wlf,wm8280", .data = (void *)WM8280 },
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{},
};
......@@ -671,6 +682,7 @@ int arizona_dev_init(struct arizona *arizona)
switch (arizona->type) {
case WM5102:
case WM5110:
case WM8280:
case WM8997:
for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
arizona->core_supplies[i].supply
......@@ -834,11 +846,19 @@ int arizona_dev_init(struct arizona *arizona)
#endif
#ifdef CONFIG_MFD_WM5110
case 0x5110:
switch (arizona->type) {
case WM5110:
type_name = "WM5110";
break;
case WM8280:
type_name = "WM8280";
break;
default:
type_name = "WM5110";
if (arizona->type != WM5110) {
dev_err(arizona->dev, "WM5110 registered as %d\n",
arizona->type);
arizona->type = WM5110;
break;
}
apply_patch = wm5110_patch;
break;
......@@ -1010,6 +1030,7 @@ int arizona_dev_init(struct arizona *arizona)
ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
break;
case WM5110:
case WM8280:
ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
break;
......
......@@ -44,6 +44,7 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
case WM8280:
regmap_config = &wm5110_i2c_regmap;
break;
#endif
......@@ -87,6 +88,7 @@ static int arizona_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id arizona_i2c_id[] = {
{ "wm5102", WM5102 },
{ "wm5110", WM5110 },
{ "wm8280", WM8280 },
{ "wm8997", WM8997 },
{ }
};
......
......@@ -211,6 +211,7 @@ int arizona_irq_init(struct arizona *arizona)
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
case WM8280:
aod = &wm5110_aod;
switch (arizona->rev) {
......
......@@ -44,6 +44,7 @@ static int arizona_spi_probe(struct spi_device *spi)
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
case WM8280:
regmap_config = &wm5110_spi_regmap;
break;
#endif
......@@ -84,6 +85,7 @@ static int arizona_spi_remove(struct spi_device *spi)
static const struct spi_device_id arizona_spi_ids[] = {
{ "wm5102", WM5102 },
{ "wm5110", WM5110 },
{ "wm8280", WM8280 },
{ },
};
MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
......
......@@ -29,7 +29,7 @@
#define AXP20X_OFF 0x80
static const char const *axp20x_model_names[] = {
static const char * const axp20x_model_names[] = {
"AXP202",
"AXP209",
"AXP288",
......@@ -290,6 +290,29 @@ static struct resource axp288_adc_resources[] = {
},
};
static struct resource axp288_extcon_resources[] = {
{
.start = AXP288_IRQ_VBUS_FALL,
.end = AXP288_IRQ_VBUS_FALL,
.flags = IORESOURCE_IRQ,
},
{
.start = AXP288_IRQ_VBUS_RISE,
.end = AXP288_IRQ_VBUS_RISE,
.flags = IORESOURCE_IRQ,
},
{
.start = AXP288_IRQ_MV_CHNG,
.end = AXP288_IRQ_MV_CHNG,
.flags = IORESOURCE_IRQ,
},
{
.start = AXP288_IRQ_BC_USB_CHNG,
.end = AXP288_IRQ_BC_USB_CHNG,
.flags = IORESOURCE_IRQ,
},
};
static struct resource axp288_charger_resources[] = {
{
.start = AXP288_IRQ_OV,
......@@ -344,6 +367,11 @@ static struct mfd_cell axp288_cells[] = {
.num_resources = ARRAY_SIZE(axp288_adc_resources),
.resources = axp288_adc_resources,
},
{
.name = "axp288_extcon",
.num_resources = ARRAY_SIZE(axp288_extcon_resources),
.resources = axp288_extcon_resources,
},
{
.name = "axp288_charger",
.num_resources = ARRAY_SIZE(axp288_charger_resources),
......
......@@ -262,6 +262,8 @@ int da9052_irq_init(struct da9052 *da9052)
goto regmap_err;
}
enable_irq_wake(da9052->chip_irq);
ret = da9052_request_irq(da9052, DA9052_IRQ_ADC_EOM, "adc-irq",
da9052_auxadc_irq, da9052);
......
......@@ -32,7 +32,7 @@ static int da9052_spi_probe(struct spi_device *spi)
if (!da9052)
return -ENOMEM;
spi->mode = SPI_MODE_0 | SPI_CPOL;
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
spi_setup(spi);
......@@ -43,6 +43,10 @@ static int da9052_spi_probe(struct spi_device *spi)
config = da9052_regmap_config;
config.read_flag_mask = 1;
config.reg_bits = 7;
config.pad_bits = 1;
config.val_bits = 8;
config.use_single_rw = 1;
da9052->regmap = devm_regmap_init_spi(spi, &config);
if (IS_ERR(da9052->regmap)) {
......
......@@ -95,7 +95,7 @@ static const struct regmap_range_cfg da9150_range_cfg[] = {
},
};
static struct regmap_config da9150_regmap_config = {
static const struct regmap_config da9150_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.ranges = da9150_range_cfg,
......
......@@ -435,7 +435,7 @@ static int _dln2_transfer(struct dln2_dev *dln2, u16 handle, u16 cmd,
struct dln2_response *rsp;
struct dln2_rx_context *rxc;
struct device *dev = &dln2->interface->dev;
const unsigned long timeout = DLN2_USB_TIMEOUT * HZ / 1000;
const unsigned long timeout = msecs_to_jiffies(DLN2_USB_TIMEOUT);
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
int size;
......
......@@ -93,7 +93,7 @@ static int hi6421_pmic_remove(struct platform_device *pdev)
return 0;
}
static struct of_device_id of_hi6421_pmic_match_tbl[] = {
static const struct of_device_id of_hi6421_pmic_match_tbl[] = {
{ .compatible = "hisilicon,hi6421-pmic", },
{ },
};
......
/*
* Intel Quark MFD PCI driver for I2C & GPIO
*
* Copyright(c) 2014 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* Intel Quark PCI device for I2C and GPIO controller sharing the same
* PCI function. This PCI driver will split the 2 devices into their
* respective drivers.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/mfd/core.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/dmi.h>
#include <linux/platform_data/gpio-dwapb.h>
#include <linux/platform_data/i2c-designware.h>
/* PCI BAR for register base address */
#define MFD_I2C_BAR 0
#define MFD_GPIO_BAR 1
/* The base GPIO number under GPIOLIB framework */
#define INTEL_QUARK_MFD_GPIO_BASE 8
/* The default number of South-Cluster GPIO on Quark. */
#define INTEL_QUARK_MFD_NGPIO 8
/* The DesignWare GPIO ports on Quark. */
#define INTEL_QUARK_GPIO_NPORTS 1
#define INTEL_QUARK_IORES_MEM 0
#define INTEL_QUARK_IORES_IRQ 1
#define INTEL_QUARK_I2C_CONTROLLER_CLK "i2c_designware.0"
/* The Quark I2C controller source clock */
#define INTEL_QUARK_I2C_CLK_HZ 33000000
#define INTEL_QUARK_I2C_NCLK 1
struct intel_quark_mfd {
struct pci_dev *pdev;
struct clk *i2c_clk;
struct clk_lookup *i2c_clk_lookup;
};
struct i2c_mode_info {
const char *name;
unsigned int i2c_scl_freq;
};
static const struct i2c_mode_info platform_i2c_mode_info[] = {
{
.name = "Galileo",
.i2c_scl_freq = 100000,
},
{
.name = "GalileoGen2",
.i2c_scl_freq = 400000,
},
{}
};
static struct resource intel_quark_i2c_res[] = {
[INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM,
},
[INTEL_QUARK_IORES_IRQ] = {
.flags = IORESOURCE_IRQ,
},
};
static struct resource intel_quark_gpio_res[] = {
[INTEL_QUARK_IORES_MEM] = {
.flags = IORESOURCE_MEM,
},
};
static struct mfd_cell intel_quark_mfd_cells[] = {
{
.id = MFD_I2C_BAR,
.name = "i2c_designware",
.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
.resources = intel_quark_i2c_res,
.ignore_resource_conflicts = true,
},
{
.id = MFD_GPIO_BAR,
.name = "gpio-dwapb",
.num_resources = ARRAY_SIZE(intel_quark_gpio_res),
.resources = intel_quark_gpio_res,
.ignore_resource_conflicts = true,
},
};
static const struct pci_device_id intel_quark_mfd_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0934), },
{},
};
MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids);
static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd)
{
struct pci_dev *pdev = quark_mfd->pdev;
struct clk_lookup *i2c_clk_lookup;
struct clk *i2c_clk;
int ret;
i2c_clk_lookup = devm_kcalloc(&pdev->dev, INTEL_QUARK_I2C_NCLK,
sizeof(*i2c_clk_lookup), GFP_KERNEL);
if (!i2c_clk_lookup)
return -ENOMEM;
i2c_clk_lookup[0].dev_id = INTEL_QUARK_I2C_CONTROLLER_CLK;
i2c_clk = clk_register_fixed_rate(&pdev->dev,
INTEL_QUARK_I2C_CONTROLLER_CLK, NULL,
CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ);
quark_mfd->i2c_clk_lookup = i2c_clk_lookup;
quark_mfd->i2c_clk = i2c_clk;
ret = clk_register_clkdevs(i2c_clk, i2c_clk_lookup,
INTEL_QUARK_I2C_NCLK);
if (ret)
dev_err(&pdev->dev, "Fixed clk register failed: %d\n", ret);
return ret;
}
static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev)
{
struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev);
if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup)
return;
clkdev_drop(quark_mfd->i2c_clk_lookup);
clk_unregister(quark_mfd->i2c_clk);
}
static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell)
{
const char *board_name = dmi_get_system_info(DMI_BOARD_NAME);
const struct i2c_mode_info *info;
struct dw_i2c_platform_data *pdata;
struct resource *res = (struct resource *)cell->resources;
struct device *dev = &pdev->dev;
res[INTEL_QUARK_IORES_MEM].start =
pci_resource_start(pdev, MFD_I2C_BAR);
res[INTEL_QUARK_IORES_MEM].end =
pci_resource_end(pdev, MFD_I2C_BAR);
res[INTEL_QUARK_IORES_IRQ].start = pdev->irq;
res[INTEL_QUARK_IORES_IRQ].end = pdev->irq;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
/* Normal mode by default */
pdata->i2c_scl_freq = 100000;
if (board_name) {
for (info = platform_i2c_mode_info; info->name; info++) {
if (!strcmp(board_name, info->name)) {
pdata->i2c_scl_freq = info->i2c_scl_freq;
break;
}
}
}
cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
return 0;
}
static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell)
{
struct dwapb_platform_data *pdata;
struct resource *res = (struct resource *)cell->resources;
struct device *dev = &pdev->dev;
res[INTEL_QUARK_IORES_MEM].start =
pci_resource_start(pdev, MFD_GPIO_BAR);
res[INTEL_QUARK_IORES_MEM].end =
pci_resource_end(pdev, MFD_GPIO_BAR);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
/* For intel quark x1000, it has only one port: portA */
pdata->nports = INTEL_QUARK_GPIO_NPORTS;
pdata->properties = devm_kcalloc(dev, pdata->nports,
sizeof(*pdata->properties),
GFP_KERNEL);
if (!pdata->properties)
return -ENOMEM;
/* Set the properties for portA */
pdata->properties->node = NULL;
pdata->properties->name = "intel-quark-x1000-gpio-portA";
pdata->properties->idx = 0;
pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO;
pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE;
pdata->properties->irq = pdev->irq;
pdata->properties->irq_shared = true;
cell->platform_data = pdata;
cell->pdata_size = sizeof(*pdata);
return 0;
}
static int intel_quark_mfd_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct intel_quark_mfd *quark_mfd;
int ret;
ret = pcim_enable_device(pdev);
if (ret)
return ret;
quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL);
if (!quark_mfd)
return -ENOMEM;
quark_mfd->pdev = pdev;
ret = intel_quark_register_i2c_clk(quark_mfd);
if (ret)
return ret;
dev_set_drvdata(&pdev->dev, quark_mfd);
ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]);
if (ret)
return ret;
ret = intel_quark_gpio_setup(pdev,
&intel_quark_mfd_cells[MFD_GPIO_BAR]);
if (ret)
return ret;
return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
NULL);
}
static void intel_quark_mfd_remove(struct pci_dev *pdev)
{
intel_quark_unregister_i2c_clk(pdev);
mfd_remove_devices(&pdev->dev);
}
static struct pci_driver intel_quark_mfd_driver = {
.name = "intel_quark_mfd_i2c_gpio",
.id_table = intel_quark_mfd_ids,
.probe = intel_quark_mfd_probe,
.remove = intel_quark_mfd_remove,
};
module_pci_driver(intel_quark_mfd_driver);
MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
MODULE_DESCRIPTION("Intel Quark MFD PCI driver for I2C & GPIO");
MODULE_LICENSE("GPL v2");
......@@ -26,19 +26,14 @@
#include <linux/mfd/intel_soc_pmic.h>
#include "intel_soc_pmic_core.h"
/*
* On some boards the PMIC interrupt may come from a GPIO line.
* Try to lookup the ACPI table and see if such connection exists. If not,
* return -ENOENT and use the IRQ provided by I2C.
*/
static int intel_soc_pmic_find_gpio_irq(struct device *dev)
{
struct gpio_desc *desc;
int irq;
desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0, GPIOD_IN);
if (IS_ERR(desc))
return -ENOENT;
return PTR_ERR(desc);
irq = gpiod_to_irq(desc);
if (irq < 0)
......@@ -71,6 +66,11 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
/*
* On some boards the PMIC interrupt may come from a GPIO line. Try to
* lookup the ACPI table for a such connection and setup a GPIO
* interrupt if it exists. Otherwise use the IRQ provided by I2C
*/
irq = intel_soc_pmic_find_gpio_irq(dev);
pmic->irq = (irq < 0) ? i2c->irq : irq;
......
......@@ -508,8 +508,15 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = {
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CBL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cBL6"),
},
{
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CCR2",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
......
......@@ -539,72 +539,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
* functions that probably will be registered by other drivers.
*/
static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
{ PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
{ PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
{ PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M},
{ PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3},
{ PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M},
{ PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4},
{ PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M},
{ PCI_VDEVICE(INTEL, 0x2450), LPC_CICH},
{ PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5},
{ PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB},
{ PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6},
{ PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M},
{ PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W},
{ PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7},
{ PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH},
{ PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M},
{ PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH},
{ PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10},
{ PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8},
{ PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH},
{ PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO},
{ PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M},
{ PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME},
{ PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
{ PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R},
{ PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH},
{ PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO},
{ PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
{ PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
{ PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
{ PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
{ PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D},
{ PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
{ PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH},
{ PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM},
{ PCI_VDEVICE(INTEL, 0x3b02), LPC_P55},
{ PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55},
{ PCI_VDEVICE(INTEL, 0x3b06), LPC_H55},
{ PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57},
{ PCI_VDEVICE(INTEL, 0x3b08), LPC_H57},
{ PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55},
{ PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57},
{ PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57},
{ PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF},
{ PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57},
{ PCI_VDEVICE(INTEL, 0x3b12), LPC_3400},
{ PCI_VDEVICE(INTEL, 0x3b14), LPC_3420},
{ PCI_VDEVICE(INTEL, 0x3b16), LPC_3450},
{ PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579},
{ PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
{ PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT},
{ PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD},
{ PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM},
......@@ -638,7 +573,6 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT},
{ PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG},
{ PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG},
{ PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC},
{ PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT},
{ PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT},
{ PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT},
......@@ -671,6 +605,79 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT},
{ PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL},
{ PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC},
{ PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
{ PCI_VDEVICE(INTEL, 0x2410), LPC_ICH},
{ PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0},
{ PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2},
{ PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M},
{ PCI_VDEVICE(INTEL, 0x2450), LPC_CICH},
{ PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3},
{ PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M},
{ PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4},
{ PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M},
{ PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5},
{ PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB},
{ PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6},
{ PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M},
{ PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W},
{ PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB},
{ PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH},
{ PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7},
{ PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M},
{ PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10},
{ PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH},
{ PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8},
{ PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME},
{ PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH},
{ PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO},
{ PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M},
{ PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH},
{ PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO},
{ PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R},
{ PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
{ PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
{ PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
{ PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
{ PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
{ PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
{ PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D},
{ PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH},
{ PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM},
{ PCI_VDEVICE(INTEL, 0x3b02), LPC_P55},
{ PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55},
{ PCI_VDEVICE(INTEL, 0x3b06), LPC_H55},
{ PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57},
{ PCI_VDEVICE(INTEL, 0x3b08), LPC_H57},
{ PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55},
{ PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57},
{ PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57},
{ PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF},
{ PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57},
{ PCI_VDEVICE(INTEL, 0x3b12), LPC_3400},
{ PCI_VDEVICE(INTEL, 0x3b14), LPC_3420},
{ PCI_VDEVICE(INTEL, 0x3b16), LPC_3450},
{ PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579},
{ PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT},
......@@ -703,14 +710,11 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT},
{ PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG},
......@@ -743,12 +747,14 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG},
{ PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN},
{ PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL},
{ PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO},
{ PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP},
......@@ -756,12 +762,6 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL},
{ PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S},
{ PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
......
......@@ -53,8 +53,8 @@ static const struct mfd_cell max77693_devs[] = {
.of_compatible = "maxim,max77693-haptic",
},
{
.name = "max77693-flash",
.of_compatible = "maxim,max77693-flash",
.name = "max77693-led",
.of_compatible = "maxim,max77693-led",
},
};
......
/*
* MFD core driver for the Maxim MAX77843
*
* Copyright (C) 2015 Samsung Electronics
* Author: Jaewon Kim <jaewon02.kim@samsung.com>
* Author: Beomho Seo <beomho.seo@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77843-private.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
static const struct mfd_cell max77843_devs[] = {
{
.name = "max77843-muic",
.of_compatible = "maxim,max77843-muic",
}, {
.name = "max77843-regulator",
.of_compatible = "maxim,max77843-regulator",
}, {
.name = "max77843-charger",
.of_compatible = "maxim,max77843-charger"
}, {
.name = "max77843-fuelgauge",
.of_compatible = "maxim,max77843-fuelgauge",
}, {
.name = "max77843-haptic",
.of_compatible = "maxim,max77843-haptic",
},
};
static const struct regmap_config max77843_charger_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77843_CHG_REG_END,
};
static const struct regmap_config max77843_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77843_SYS_REG_END,
};
static const struct regmap_irq max77843_irqs[] = {
/* TOPSYS interrupts */
{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSUVLO_INT, },
{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_SYSOVLO_INT, },
{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TSHDN_INT, },
{ .reg_offset = 0, .mask = MAX77843_SYS_IRQ_TM_INT, },
};
static const struct regmap_irq_chip max77843_irq_chip = {
.name = "max77843",
.status_base = MAX77843_SYS_REG_SYSINTSRC,
.mask_base = MAX77843_SYS_REG_SYSINTMASK,
.mask_invert = false,
.num_regs = 1,
.irqs = max77843_irqs,
.num_irqs = ARRAY_SIZE(max77843_irqs),
};
/* Charger and Charger regulator use same regmap. */
static int max77843_chg_init(struct max77843 *max77843)
{
int ret;
max77843->i2c_chg = i2c_new_dummy(max77843->i2c->adapter, I2C_ADDR_CHG);
if (!max77843->i2c_chg) {
dev_err(&max77843->i2c->dev,
"Cannot allocate I2C device for Charger\n");
return PTR_ERR(max77843->i2c_chg);
}
i2c_set_clientdata(max77843->i2c_chg, max77843);
max77843->regmap_chg = devm_regmap_init_i2c(max77843->i2c_chg,
&max77843_charger_regmap_config);
if (IS_ERR(max77843->regmap_chg)) {
ret = PTR_ERR(max77843->regmap_chg);
goto err_chg_i2c;
}
return 0;
err_chg_i2c:
i2c_unregister_device(max77843->i2c_chg);
return ret;
}
static int max77843_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct max77843 *max77843;
unsigned int reg_data;
int ret;
max77843 = devm_kzalloc(&i2c->dev, sizeof(*max77843), GFP_KERNEL);
if (!max77843)
return -ENOMEM;
i2c_set_clientdata(i2c, max77843);
max77843->dev = &i2c->dev;
max77843->i2c = i2c;
max77843->irq = i2c->irq;
max77843->regmap = devm_regmap_init_i2c(i2c,
&max77843_regmap_config);
if (IS_ERR(max77843->regmap)) {
dev_err(&i2c->dev, "Failed to allocate topsys register map\n");
return PTR_ERR(max77843->regmap);
}
ret = regmap_add_irq_chip(max77843->regmap, max77843->irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
0, &max77843_irq_chip, &max77843->irq_data);
if (ret) {
dev_err(&i2c->dev, "Failed to add TOPSYS IRQ chip\n");
return ret;
}
ret = regmap_read(max77843->regmap,
MAX77843_SYS_REG_PMICID, &reg_data);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read PMIC ID\n");
goto err_pmic_id;
}
dev_info(&i2c->dev, "device ID: 0x%x\n", reg_data);
ret = max77843_chg_init(max77843);
if (ret) {
dev_err(&i2c->dev, "Failed to init Charger\n");
goto err_pmic_id;
}
ret = regmap_update_bits(max77843->regmap,
MAX77843_SYS_REG_INTSRCMASK,
MAX77843_INTSRC_MASK_MASK,
(unsigned int)~MAX77843_INTSRC_MASK_MASK);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to unmask interrupt source\n");
goto err_pmic_id;
}
ret = mfd_add_devices(max77843->dev, -1, max77843_devs,
ARRAY_SIZE(max77843_devs), NULL, 0, NULL);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to add mfd device\n");
goto err_pmic_id;
}
device_init_wakeup(max77843->dev, true);
return 0;
err_pmic_id:
regmap_del_irq_chip(max77843->irq, max77843->irq_data);
return ret;
}
static int max77843_remove(struct i2c_client *i2c)
{
struct max77843 *max77843 = i2c_get_clientdata(i2c);
mfd_remove_devices(max77843->dev);
regmap_del_irq_chip(max77843->irq, max77843->irq_data);
i2c_unregister_device(max77843->i2c_chg);
return 0;
}
static const struct of_device_id max77843_dt_match[] = {
{ .compatible = "maxim,max77843", },
{ },
};
static const struct i2c_device_id max77843_id[] = {
{ "max77843", },
{ },
};
MODULE_DEVICE_TABLE(i2c, max77843_id);
static int __maybe_unused max77843_suspend(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77843 *max77843 = i2c_get_clientdata(i2c);
disable_irq(max77843->irq);
if (device_may_wakeup(dev))
enable_irq_wake(max77843->irq);
return 0;
}
static int __maybe_unused max77843_resume(struct device *dev)
{
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max77843 *max77843 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
disable_irq_wake(max77843->irq);
enable_irq(max77843->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(max77843_pm, max77843_suspend, max77843_resume);
static struct i2c_driver max77843_i2c_driver = {
.driver = {
.name = "max77843",
.pm = &max77843_pm,
.of_match_table = max77843_dt_match,
},
.probe = max77843_probe,
.remove = max77843_remove,
.id_table = max77843_id,
};
static int __init max77843_i2c_init(void)
{
return i2c_add_driver(&max77843_i2c_driver);
}
subsys_initcall(max77843_i2c_init);
static void __exit max77843_i2c_exit(void)
{
i2c_del_driver(&max77843_i2c_driver);
}
module_exit(max77843_i2c_exit);
......@@ -51,19 +51,19 @@
void mc13xxx_lock(struct mc13xxx *mc13xxx)
{
if (!mutex_trylock(&mc13xxx->lock)) {
dev_dbg(mc13xxx->dev, "wait for %s from %pf\n",
dev_dbg(mc13xxx->dev, "wait for %s from %ps\n",
__func__, __builtin_return_address(0));
mutex_lock(&mc13xxx->lock);
}
dev_dbg(mc13xxx->dev, "%s from %pf\n",
dev_dbg(mc13xxx->dev, "%s from %ps\n",
__func__, __builtin_return_address(0));
}
EXPORT_SYMBOL(mc13xxx_lock);
void mc13xxx_unlock(struct mc13xxx *mc13xxx)
{
dev_dbg(mc13xxx->dev, "%s from %pf\n",
dev_dbg(mc13xxx->dev, "%s from %ps\n",
__func__, __builtin_return_address(0));
mutex_unlock(&mc13xxx->lock);
}
......
......@@ -532,29 +532,6 @@ static const struct menelaus_vtg_value vcore_values[] = {
{ 1450, 18 },
};
int menelaus_set_vcore_sw(unsigned int mV)
{
int val, ret;
struct i2c_client *c = the_menelaus->client;
val = menelaus_get_vtg_value(mV, vcore_values,
ARRAY_SIZE(vcore_values));
if (val < 0)
return -EINVAL;
dev_dbg(&c->dev, "Setting VCORE to %d mV (val 0x%02x)\n", mV, val);
/* Set SW mode and the voltage in one go. */
mutex_lock(&the_menelaus->lock);
ret = menelaus_write_reg(MENELAUS_VCORE_CTRL1, val);
if (ret == 0)
the_menelaus->vcore_hw_mode = 0;
mutex_unlock(&the_menelaus->lock);
msleep(1);
return ret;
}
int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV)
{
int fval, rval, val, ret;
......@@ -1239,7 +1216,7 @@ static int menelaus_probe(struct i2c_client *client,
err = menelaus_read_reg(MENELAUS_VCORE_CTRL1);
if (err < 0)
goto fail;
if (err & BIT(7))
if (err & VCORE_CTRL1_HW_NSW)
menelaus->vcore_hw_mode = 1;
else
menelaus->vcore_hw_mode = 0;
......@@ -1259,7 +1236,7 @@ static int menelaus_probe(struct i2c_client *client,
return err;
}
static int __exit menelaus_remove(struct i2c_client *client)
static int menelaus_remove(struct i2c_client *client)
{
struct menelaus_chip *menelaus = i2c_get_clientdata(client);
......@@ -1280,7 +1257,7 @@ static struct i2c_driver menelaus_i2c_driver = {
.name = DRIVER_NAME,
},
.probe = menelaus_probe,
.remove = __exit_p(menelaus_remove),
.remove = menelaus_remove,
.id_table = menelaus_id,
};
......
......@@ -128,7 +128,7 @@ static int mfd_add_device(struct device *parent, int id,
int platform_id;
int r;
if (id < 0)
if (id == PLATFORM_DEVID_AUTO)
platform_id = id;
else
platform_id = id + cell->id;
......
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Flora Fu, MediaTek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
static const struct mfd_cell mt6397_devs[] = {
{
.name = "mt6397-rtc",
.of_compatible = "mediatek,mt6397-rtc",
}, {
.name = "mt6397-regulator",
.of_compatible = "mediatek,mt6397-regulator",
}, {
.name = "mt6397-codec",
.of_compatible = "mediatek,mt6397-codec",
}, {
.name = "mt6397-clk",
.of_compatible = "mediatek,mt6397-clk",
},
};
static void mt6397_irq_lock(struct irq_data *data)
{
struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
mutex_lock(&mt6397->irqlock);
}
static void mt6397_irq_sync_unlock(struct irq_data *data)
{
struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
regmap_write(mt6397->regmap, MT6397_INT_CON0, mt6397->irq_masks_cur[0]);
regmap_write(mt6397->regmap, MT6397_INT_CON1, mt6397->irq_masks_cur[1]);
mutex_unlock(&mt6397->irqlock);
}
static void mt6397_irq_disable(struct irq_data *data)
{
struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
int shift = data->hwirq & 0xf;
int reg = data->hwirq >> 4;
mt6397->irq_masks_cur[reg] &= ~BIT(shift);
}
static void mt6397_irq_enable(struct irq_data *data)
{
struct mt6397_chip *mt6397 = irq_get_chip_data(data->irq);
int shift = data->hwirq & 0xf;
int reg = data->hwirq >> 4;
mt6397->irq_masks_cur[reg] |= BIT(shift);
}
static struct irq_chip mt6397_irq_chip = {
.name = "mt6397-irq",
.irq_bus_lock = mt6397_irq_lock,
.irq_bus_sync_unlock = mt6397_irq_sync_unlock,
.irq_enable = mt6397_irq_enable,
.irq_disable = mt6397_irq_disable,
};
static void mt6397_irq_handle_reg(struct mt6397_chip *mt6397, int reg,
int irqbase)
{
unsigned int status;
int i, irq, ret;
ret = regmap_read(mt6397->regmap, reg, &status);
if (ret) {
dev_err(mt6397->dev, "Failed to read irq status: %d\n", ret);
return;
}
for (i = 0; i < 16; i++) {
if (status & BIT(i)) {
irq = irq_find_mapping(mt6397->irq_domain, irqbase + i);
if (irq)
handle_nested_irq(irq);
}
}
regmap_write(mt6397->regmap, reg, status);
}
static irqreturn_t mt6397_irq_thread(int irq, void *data)
{
struct mt6397_chip *mt6397 = data;
mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS0, 0);
mt6397_irq_handle_reg(mt6397, MT6397_INT_STATUS1, 16);
return IRQ_HANDLED;
}
static int mt6397_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
struct mt6397_chip *mt6397 = d->host_data;
irq_set_chip_data(irq, mt6397);
irq_set_chip_and_handler(irq, &mt6397_irq_chip, handle_level_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static struct irq_domain_ops mt6397_irq_domain_ops = {
.map = mt6397_irq_domain_map,
};
static int mt6397_irq_init(struct mt6397_chip *mt6397)
{
int ret;
mutex_init(&mt6397->irqlock);
/* Mask all interrupt sources */
regmap_write(mt6397->regmap, MT6397_INT_CON0, 0x0);
regmap_write(mt6397->regmap, MT6397_INT_CON1, 0x0);
mt6397->irq_domain = irq_domain_add_linear(mt6397->dev->of_node,
MT6397_IRQ_NR, &mt6397_irq_domain_ops, mt6397);
if (!mt6397->irq_domain) {
dev_err(mt6397->dev, "could not create irq domain\n");
return -ENOMEM;
}
ret = devm_request_threaded_irq(mt6397->dev, mt6397->irq, NULL,
mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", mt6397);
if (ret) {
dev_err(mt6397->dev, "failed to register irq=%d; err: %d\n",
mt6397->irq, ret);
return ret;
}
return 0;
}
static int mt6397_probe(struct platform_device *pdev)
{
int ret;
struct mt6397_chip *mt6397;
mt6397 = devm_kzalloc(&pdev->dev, sizeof(*mt6397), GFP_KERNEL);
if (!mt6397)
return -ENOMEM;
mt6397->dev = &pdev->dev;
/*
* mt6397 MFD is child device of soc pmic wrapper.
* Regmap is set from its parent.
*/
mt6397->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!mt6397->regmap)
return -ENODEV;
platform_set_drvdata(pdev, mt6397);
mt6397->irq = platform_get_irq(pdev, 0);
if (mt6397->irq > 0) {
ret = mt6397_irq_init(mt6397);
if (ret)
return ret;
}
ret = mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL, 0, NULL);
if (ret)
dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
return ret;
}
static int mt6397_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id mt6397_of_match[] = {
{ .compatible = "mediatek,mt6397" },
{ }
};
MODULE_DEVICE_TABLE(of, mt6397_of_match);
static struct platform_driver mt6397_driver = {
.probe = mt6397_probe,
.remove = mt6397_remove,
.driver = {
.name = "mt6397",
.of_match_table = of_match_ptr(mt6397_of_match),
},
};
module_platform_driver(mt6397_driver);
MODULE_AUTHOR("Flora Fu, MediaTek");
MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:mt6397");
......@@ -17,6 +17,100 @@
#include <linux/regmap.h>
#include <linux/of_platform.h>
#define PMIC_REV2 0x101
#define PMIC_REV3 0x102
#define PMIC_REV4 0x103
#define PMIC_TYPE 0x104
#define PMIC_SUBTYPE 0x105
#define PMIC_TYPE_VALUE 0x51
#define COMMON_SUBTYPE 0x00
#define PM8941_SUBTYPE 0x01
#define PM8841_SUBTYPE 0x02
#define PM8019_SUBTYPE 0x03
#define PM8226_SUBTYPE 0x04
#define PM8110_SUBTYPE 0x05
#define PMA8084_SUBTYPE 0x06
#define PMI8962_SUBTYPE 0x07
#define PMD9635_SUBTYPE 0x08
#define PM8994_SUBTYPE 0x09
#define PMI8994_SUBTYPE 0x0a
#define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d
static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
{ .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE },
{ .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE },
{ .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE },
{ .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE },
{ .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE },
{ .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE },
{ .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE },
{ .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE },
{ .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE },
{ .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE },
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
{ }
};
static void pmic_spmi_show_revid(struct regmap *map, struct device *dev)
{
unsigned int rev2, minor, major, type, subtype;
const char *name = "unknown";
int ret, i;
ret = regmap_read(map, PMIC_TYPE, &type);
if (ret < 0)
return;
if (type != PMIC_TYPE_VALUE)
return;
ret = regmap_read(map, PMIC_SUBTYPE, &subtype);
if (ret < 0)
return;
for (i = 0; i < ARRAY_SIZE(pmic_spmi_id_table); i++) {
if (subtype == (unsigned long)pmic_spmi_id_table[i].data)
break;
}
if (i != ARRAY_SIZE(pmic_spmi_id_table))
name = pmic_spmi_id_table[i].compatible;
ret = regmap_read(map, PMIC_REV2, &rev2);
if (ret < 0)
return;
ret = regmap_read(map, PMIC_REV3, &minor);
if (ret < 0)
return;
ret = regmap_read(map, PMIC_REV4, &major);
if (ret < 0)
return;
/*
* In early versions of PM8941 and PM8226, the major revision number
* started incrementing from 0 (eg 0 = v1.0, 1 = v2.0).
* Increment the major revision number here if the chip is an early
* version of PM8941 or PM8226.
*/
if ((subtype == PM8941_SUBTYPE || subtype == PM8226_SUBTYPE) &&
major < 0x02)
major++;
if (subtype == PM8110_SUBTYPE)
minor = rev2;
dev_dbg(dev, "%x: %s v%d.%d\n", subtype, name, major, minor);
}
static const struct regmap_config spmi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
......@@ -33,6 +127,8 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
pmic_spmi_show_revid(regmap, &sdev->dev);
return of_platform_populate(root, NULL, NULL, &sdev->dev);
}
......@@ -41,13 +137,6 @@ static void pmic_spmi_remove(struct spmi_device *sdev)
of_platform_depopulate(&sdev->dev);
}
static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic" },
{ .compatible = "qcom,pm8941" },
{ .compatible = "qcom,pm8841" },
{ .compatible = "qcom,pma8084" },
{ }
};
MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
static struct spmi_driver pmic_spmi_driver = {
......
......@@ -323,10 +323,51 @@ static const struct qcom_rpm_data msm8960_template = {
.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
};
static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = {
[QCOM_RPM_CXO_CLK] = { 25, 9, 5, 1 },
[QCOM_RPM_PXO_CLK] = { 26, 10, 6, 1 },
[QCOM_RPM_APPS_FABRIC_CLK] = { 27, 11, 8, 1 },
[QCOM_RPM_SYS_FABRIC_CLK] = { 28, 12, 9, 1 },
[QCOM_RPM_NSS_FABRIC_0_CLK] = { 29, 13, 10, 1 },
[QCOM_RPM_DAYTONA_FABRIC_CLK] = { 30, 14, 11, 1 },
[QCOM_RPM_SFPB_CLK] = { 31, 15, 12, 1 },
[QCOM_RPM_CFPB_CLK] = { 32, 16, 13, 1 },
[QCOM_RPM_NSS_FABRIC_1_CLK] = { 33, 17, 14, 1 },
[QCOM_RPM_EBI1_CLK] = { 34, 18, 16, 1 },
[QCOM_RPM_APPS_FABRIC_HALT] = { 35, 19, 18, 2 },
[QCOM_RPM_APPS_FABRIC_MODE] = { 37, 20, 19, 3 },
[QCOM_RPM_APPS_FABRIC_IOCTL] = { 40, 21, 20, 1 },
[QCOM_RPM_APPS_FABRIC_ARB] = { 41, 22, 21, 12 },
[QCOM_RPM_SYS_FABRIC_HALT] = { 53, 23, 22, 2 },
[QCOM_RPM_SYS_FABRIC_MODE] = { 55, 24, 23, 3 },
[QCOM_RPM_SYS_FABRIC_IOCTL] = { 58, 25, 24, 1 },
[QCOM_RPM_SYS_FABRIC_ARB] = { 59, 26, 25, 30 },
[QCOM_RPM_MM_FABRIC_HALT] = { 89, 27, 26, 2 },
[QCOM_RPM_MM_FABRIC_MODE] = { 91, 28, 27, 3 },
[QCOM_RPM_MM_FABRIC_IOCTL] = { 94, 29, 28, 1 },
[QCOM_RPM_MM_FABRIC_ARB] = { 95, 30, 29, 2 },
[QCOM_RPM_CXO_BUFFERS] = { 209, 33, 31, 1 },
[QCOM_RPM_USB_OTG_SWITCH] = { 210, 34, 32, 1 },
[QCOM_RPM_HDMI_SWITCH] = { 211, 35, 33, 1 },
[QCOM_RPM_DDR_DMM] = { 212, 36, 34, 2 },
[QCOM_RPM_VDDMIN_GPIO] = { 215, 40, 39, 1 },
[QCOM_RPM_SMB208_S1a] = { 216, 41, 90, 2 },
[QCOM_RPM_SMB208_S1b] = { 218, 43, 91, 2 },
[QCOM_RPM_SMB208_S2a] = { 220, 45, 92, 2 },
[QCOM_RPM_SMB208_S2b] = { 222, 47, 93, 2 },
};
static const struct qcom_rpm_data ipq806x_template = {
.version = 3,
.resource_table = ipq806x_rpm_resource_table,
.n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table),
};
static const struct of_device_id qcom_rpm_of_match[] = {
{ .compatible = "qcom,rpm-apq8064", .data = &apq8064_template },
{ .compatible = "qcom,rpm-msm8660", .data = &msm8660_template },
{ .compatible = "qcom,rpm-msm8960", .data = &msm8960_template },
{ .compatible = "qcom,rpm-ipq8064", .data = &ipq806x_template },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
......
......@@ -89,6 +89,7 @@ static const struct rk808_reg_data pre_init_reg[] = {
{ RK808_BOOST_CONFIG_REG, BOOST_ILMIN_MASK, BOOST_ILMIN_100MA },
{ RK808_BUCK1_CONFIG_REG, BUCK1_RATE_MASK, BUCK_ILMIN_200MA },
{ RK808_BUCK2_CONFIG_REG, BUCK2_RATE_MASK, BUCK_ILMIN_200MA },
{ RK808_DCDC_UV_ACT_REG, BUCK_UV_ACT_MASK, BUCK_UV_ACT_DISABLE},
{ RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
VB_LO_SEL_3500MV },
};
......@@ -245,7 +246,7 @@ static int rk808_remove(struct i2c_client *client)
return 0;
}
static struct of_device_id rk808_of_match[] = {
static const struct of_device_id rk808_of_match[] = {
{ .compatible = "rockchip,rk808" },
{ },
};
......
......@@ -53,7 +53,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
u8 reg3 = 0;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
if (!rtsx_vendor_setting_valid(reg1))
return;
......@@ -65,7 +65,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
}
......@@ -74,7 +74,7 @@ static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
u32 reg = 0;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
if (!rtsx_vendor_setting_valid(reg))
return;
......@@ -260,8 +260,7 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, CARD_PWR_CTL,
BPP_POWER_MASK, BPP_POWER_OFF);
dev_dbg(&(pcr->pci->dev),
"After CD deglitch, card_exist = 0x%x\n",
pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n",
card_exist);
}
......
......@@ -38,7 +38,7 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
u32 reg;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
if (rts5209_vendor_setting1_valid(reg)) {
if (rts5209_reg_check_ms_pmos(reg))
......@@ -47,7 +47,7 @@ static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
}
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
if (rts5209_vendor_setting2_valid(reg)) {
pcr->sd30_drive_sel_1v8 =
......
......@@ -63,7 +63,7 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
u32 reg;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
if (!rtsx_vendor_setting_valid(reg))
return;
......@@ -74,7 +74,7 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
if (rtsx_reg_check_reverse_socket(reg))
pcr->flags |= PCR_REVERSE_SOCKET;
......@@ -118,11 +118,9 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
rts5227_fill_driving(pcr, OUTPUT_3V3);
/* Configure force_clock_req */
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
return rtsx_pci_send_cmd(pcr, 100);
......@@ -132,7 +130,7 @@ static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
{
int err;
err = rtsx_gops_pm_reset(pcr);
err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
if (err < 0)
return err;
......
......@@ -38,7 +38,7 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
u32 reg;
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
if (!rtsx_vendor_setting_valid(reg))
return;
......@@ -50,7 +50,7 @@ static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
pcr->sd30_drive_sel_3v3 =
map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
}
......
This diff is collapsed.
......@@ -58,11 +58,25 @@ static const struct pci_device_id rtsx_pci_ids[] = {
{ PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr)
{
rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
0xFC, pcr->aspm_en);
}
static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
{
rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
0xFC, 0);
}
void rtsx_pci_start_run(struct rtsx_pcr *pcr)
{
/* If pci device removed, don't queue idle work any more */
......@@ -75,7 +89,7 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr)
pcr->ops->enable_auto_blink(pcr);
if (pcr->aspm_en)
rtsx_pci_write_config_byte(pcr, LCTLR, 0);
rtsx_pci_disable_aspm(pcr);
}
mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
......@@ -130,7 +144,7 @@ int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
}
EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
{
int err, i, finished = 0;
u8 tmp;
......@@ -162,9 +176,17 @@ int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
return 0;
}
int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
{
if (pcr->ops->write_phy)
return pcr->ops->write_phy(pcr, addr, val);
return __rtsx_pci_write_phy_register(pcr, addr, val);
}
EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
{
int err, i, finished = 0;
u16 data;
......@@ -210,6 +232,14 @@ int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
return 0;
}
int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
{
if (pcr->ops->read_phy)
return pcr->ops->read_phy(pcr, addr, val);
return __rtsx_pci_read_phy_register(pcr, addr, val);
}
EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
......@@ -286,8 +316,7 @@ int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, msecs_to_jiffies(timeout));
if (timeleft <= 0) {
dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
__func__, __LINE__);
pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
err = -ETIMEDOUT;
goto finish_send_cmd;
}
......@@ -323,8 +352,7 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
u64 val;
u8 option = SG_VALID | SG_TRANS_DATA;
dev_dbg(&(pcr->pci->dev), "DMA addr: 0x%x, Len: 0x%x\n",
(unsigned int)addr, len);
pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len);
if (end)
option |= SG_END;
......@@ -339,11 +367,11 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
{
int err = 0, count;
dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg);
count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
if (count < 1)
return -EINVAL;
dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
pcr_dbg(pcr, "DMA mapping count: %d\n", count);
err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
......@@ -417,8 +445,7 @@ int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
timeleft = wait_for_completion_interruptible_timeout(
&trans_done, msecs_to_jiffies(timeout));
if (timeleft <= 0) {
dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n",
__func__, __LINE__);
pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
err = -ETIMEDOUT;
goto out;
}
......@@ -592,7 +619,7 @@ static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
/* Enable Bus Interrupt */
rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
dev_dbg(&(pcr->pci->dev), "RTSX_BIER: 0x%08x\n", pcr->bier);
pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier);
}
static inline u8 double_ssc_depth(u8 depth)
......@@ -638,13 +665,12 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
return err;
card_clock /= 1000000;
dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock);
pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock);
clk = card_clock;
if (!initial_mode && double_clk)
clk = card_clock * 2;
dev_dbg(&(pcr->pci->dev),
"Internal SSC clock: %dMHz (cur_clock = %d)\n",
pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n",
clk, pcr->cur_clock);
if (clk == pcr->cur_clock)
......@@ -674,14 +700,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
}
div++;
}
dev_dbg(&(pcr->pci->dev), "n = %d, div = %d\n", n, div);
pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
ssc_depth = depth[ssc_depth];
if (double_clk)
ssc_depth = double_ssc_depth(ssc_depth);
ssc_depth = revise_ssc_depth(ssc_depth, div);
dev_dbg(&(pcr->pci->dev), "ssc_depth = %d\n", ssc_depth);
pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
......@@ -803,13 +829,13 @@ static void rtsx_pci_card_detect(struct work_struct *work)
dwork = to_delayed_work(work);
pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
pcr_dbg(pcr, "--> %s\n", __func__);
mutex_lock(&pcr->pcr_mutex);
spin_lock_irqsave(&pcr->lock, flags);
irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status);
pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status);
irq_status &= CARD_EXIST;
card_inserted = pcr->card_inserted & irq_status;
......@@ -820,8 +846,7 @@ static void rtsx_pci_card_detect(struct work_struct *work)
spin_unlock_irqrestore(&pcr->lock, flags);
if (card_inserted || card_removed) {
dev_dbg(&(pcr->pci->dev),
"card_inserted: 0x%x, card_removed: 0x%x\n",
pcr_dbg(pcr, "card_inserted: 0x%x, card_removed: 0x%x\n",
card_inserted, card_removed);
if (pcr->ops->cd_deglitch)
......@@ -930,7 +955,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
struct delayed_work *dwork = to_delayed_work(work);
struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__);
pcr_dbg(pcr, "--> %s\n", __func__);
mutex_lock(&pcr->pcr_mutex);
......@@ -942,7 +967,7 @@ static void rtsx_pci_idle_work(struct work_struct *work)
pcr->ops->turn_off_led(pcr);
if (pcr->aspm_en)
rtsx_pci_write_config_byte(pcr, LCTLR, pcr->aspm_en);
rtsx_pci_enable_aspm(pcr);
mutex_unlock(&pcr->pcr_mutex);
}
......@@ -968,6 +993,7 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
{
int err;
pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP);
rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
rtsx_pci_enable_bus_int(pcr);
......@@ -980,6 +1006,7 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
/* Wait SSC power stable */
udelay(200);
rtsx_pci_disable_aspm(pcr);
if (pcr->ops->optimize_phy) {
err = pcr->ops->optimize_phy(pcr);
if (err < 0)
......@@ -1028,10 +1055,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
if (err < 0)
return err;
rtsx_pci_write_config_byte(pcr, LCTLR, 0);
/* Enable clk_request_n to enable clock power management */
rtsx_pci_write_config_byte(pcr, 0x81, 1);
rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
/* Enter L1 when host tx idle */
rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
......@@ -1081,6 +1106,14 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
rts5249_init_params(pcr);
break;
case 0x524A:
rts524a_init_params(pcr);
break;
case 0x525A:
rts525a_init_params(pcr);
break;
case 0x5287:
rtl8411b_init_params(pcr);
break;
......@@ -1090,7 +1123,7 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
break;
}
dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
PCI_PID(pcr), pcr->ic_version);
pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
......@@ -1101,14 +1134,14 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
if (pcr->ops->fetch_vendor_settings)
pcr->ops->fetch_vendor_settings(pcr);
dev_dbg(&(pcr->pci->dev), "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_1v8 = 0x%x\n",
pcr_dbg(pcr, "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
pcr_dbg(pcr, "pcr->sd30_drive_sel_1v8 = 0x%x\n",
pcr->sd30_drive_sel_1v8);
dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_3v3 = 0x%x\n",
pcr_dbg(pcr, "pcr->sd30_drive_sel_3v3 = 0x%x\n",
pcr->sd30_drive_sel_3v3);
dev_dbg(&(pcr->pci->dev), "pcr->card_drive_sel = 0x%x\n",
pcr_dbg(pcr, "pcr->card_drive_sel = 0x%x\n",
pcr->card_drive_sel);
dev_dbg(&(pcr->pci->dev), "pcr->flags = 0x%x\n", pcr->flags);
pcr_dbg(pcr, "pcr->flags = 0x%x\n", pcr->flags);
pcr->state = PDEV_STAT_IDLE;
err = rtsx_pci_init_hw(pcr);
......@@ -1126,7 +1159,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
struct rtsx_pcr *pcr;
struct pcr_handle *handle;
u32 base, len;
int ret, i;
int ret, i, bar = 0;
dev_dbg(&(pcidev->dev),
": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
......@@ -1171,8 +1204,10 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
pcr->pci = pcidev;
dev_set_drvdata(&pcidev->dev, handle);
len = pci_resource_len(pcidev, 0);
base = pci_resource_start(pcidev, 0);
if (CHK_PCI_PID(pcr, 0x525A))
bar = 1;
len = pci_resource_len(pcidev, bar);
base = pci_resource_start(pcidev, bar);
pcr->remap_addr = ioremap_nocache(base, len);
if (!pcr->remap_addr) {
ret = -ENOMEM;
......
......@@ -27,12 +27,20 @@
#define MIN_DIV_N_PCR 80
#define MAX_DIV_N_PCR 208
#define RTS524A_PME_FORCE_CTL 0xFF78
#define RTS524A_PM_CTRL3 0xFF7E
int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
void rts5209_init_params(struct rtsx_pcr *pcr);
void rts5229_init_params(struct rtsx_pcr *pcr);
void rtl8411_init_params(struct rtsx_pcr *pcr);
void rtl8402_init_params(struct rtsx_pcr *pcr);
void rts5227_init_params(struct rtsx_pcr *pcr);
void rts5249_init_params(struct rtsx_pcr *pcr);
void rts524a_init_params(struct rtsx_pcr *pcr);
void rts525a_init_params(struct rtsx_pcr *pcr);
void rtl8411b_init_params(struct rtsx_pcr *pcr);
static inline u8 map_sd_drive(int idx)
......
......@@ -68,6 +68,8 @@ static const struct mfd_cell s5m8767_devs[] = {
static const struct mfd_cell s2mps11_devs[] = {
{
.name = "s2mps11-pmic",
}, {
.name = "s2mps14-rtc",
}, {
.name = "s2mps11-clk",
.of_compatible = "samsung,s2mps11-clk",
......@@ -267,10 +269,8 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
struct sec_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd) {
dev_err(dev, "could not allocate memory for pdata\n");
if (!pd)
return ERR_PTR(-ENOMEM);
}
/*
* ToDo: the 'wakeup' member in the platform data is more of a linux
......@@ -333,7 +333,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
}
if (pdata) {
sec_pmic->device_type = pdata->device_type;
sec_pmic->ono = pdata->ono;
sec_pmic->irq_base = pdata->irq_base;
sec_pmic->wakeup = pdata->wakeup;
sec_pmic->pdata = pdata;
......
......@@ -61,14 +61,14 @@ static const struct regmap_irq s2mps11_irqs[] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPS11_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS11_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPS11_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS11_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
......@@ -484,6 +484,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return ret;
}
/*
* The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
* so the interrupt number must be consistent.
*/
BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
return 0;
}
......
/*
* sky81452.c SKY81452 MFD driver
*
* Copyright 2014 Skyworks Solutions Inc.
* Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/sky81452.h>
static const struct regmap_config sky81452_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int sky81452_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
const struct sky81452_platform_data *pdata = dev_get_platdata(dev);
struct mfd_cell cells[2];
struct regmap *regmap;
int ret;
if (!pdata) {
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
}
regmap = devm_regmap_init_i2c(client, &sky81452_config);
if (IS_ERR(regmap)) {
dev_err(dev, "failed to initialize.err=%ld\n", PTR_ERR(regmap));
return PTR_ERR(regmap);
}
i2c_set_clientdata(client, regmap);
memset(cells, 0, sizeof(cells));
cells[0].name = "sky81452-backlight";
cells[0].of_compatible = "skyworks,sky81452-backlight";
cells[0].platform_data = pdata->bl_pdata;
cells[0].pdata_size = sizeof(*pdata->bl_pdata);
cells[1].name = "sky81452-regulator";
cells[1].platform_data = pdata->regulator_init_data;
cells[1].pdata_size = sizeof(*pdata->regulator_init_data);
ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL);
if (ret)
dev_err(dev, "failed to add child devices. err=%d\n", ret);
return ret;
}
static int sky81452_remove(struct i2c_client *client)
{
mfd_remove_devices(&client->dev);
return 0;
}
static const struct i2c_device_id sky81452_ids[] = {
{ "sky81452" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sky81452_ids);
#ifdef CONFIG_OF
static const struct of_device_id sky81452_of_match[] = {
{ .compatible = "skyworks,sky81452", },
{ }
};
MODULE_DEVICE_TABLE(of, sky81452_of_match);
#endif
static struct i2c_driver sky81452_driver = {
.driver = {
.name = "sky81452",
.of_match_table = of_match_ptr(sky81452_of_match),
},
.probe = sky81452_probe,
.remove = sky81452_remove,
.id_table = sky81452_ids,
};
module_i2c_driver(sky81452_driver);
MODULE_DESCRIPTION("Skyworks SKY81452 MFD driver");
MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
MODULE_LICENSE("GPL v2");
......@@ -318,7 +318,6 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
return ret;
}
#ifdef CONFIG_OF
static const struct of_device_id tc3589x_match[] = {
/* Legacy compatible string */
{ .compatible = "tc3589x", .data = (void *) TC3589X_UNKNOWN },
......@@ -359,14 +358,6 @@ tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
return pdata;
}
#else
static inline struct tc3589x_platform_data *
tc3589x_of_probe(struct device *dev, enum tc3589x_version *version)
{
dev_err(dev, "no device tree support\n");
return ERR_PTR(-ENODEV);
}
#endif
static int tc3589x_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
......
......@@ -68,12 +68,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
DEFINE_WAIT(wait);
u32 reg;
/*
* disable TSC steps so it does not run while the ADC is using it. If
* write 0 while it is running (it just started or was already running)
* then it completes all steps that were enabled and stops then.
*/
tscadc_writel(tsadc, REG_SE, 0);
reg = tscadc_readl(tsadc, REG_ADCFSM);
if (reg & SEQ_STATUS) {
tsadc->adc_waiting = true;
......@@ -86,8 +80,12 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
spin_lock_irq(&tsadc->reg_lock);
finish_wait(&tsadc->reg_se_wait, &wait);
/*
* Sequencer should either be idle or
* busy applying the charge step.
*/
reg = tscadc_readl(tsadc, REG_ADCFSM);
WARN_ON(reg & SEQ_STATUS);
WARN_ON((reg & SEQ_STATUS) && !(reg & CHARGE_STEP));
tsadc->adc_waiting = false;
}
tsadc->adc_in_use = true;
......@@ -96,7 +94,6 @@ static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
{
spin_lock_irq(&tsadc->reg_lock);
tsadc->reg_se_cache |= val;
am335x_tscadc_need_adc(tsadc);
tscadc_writel(tsadc, REG_SE, val);
......
......@@ -515,7 +515,7 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
static struct tps65010 *the_tps;
static int __exit tps65010_remove(struct i2c_client *client)
static int tps65010_remove(struct i2c_client *client)
{
struct tps65010 *tps = i2c_get_clientdata(client);
struct tps65010_board *board = dev_get_platdata(&client->dev);
......@@ -684,7 +684,7 @@ static struct i2c_driver tps65010_driver = {
.name = "tps65010",
},
.probe = tps65010_probe,
.remove = __exit_p(tps65010_remove),
.remove = tps65010_remove,
.id_table = tps65010_id,
};
......
......@@ -829,7 +829,7 @@ static struct twl4030_power_data osc_off_idle = {
.board_config = osc_off_rconfig,
};
static struct of_device_id twl4030_power_of_match[] = {
static const struct of_device_id twl4030_power_of_match[] = {
{
.compatible = "ti,twl4030-power",
},
......
......@@ -814,4 +814,3 @@ MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
MODULE_AUTHOR("Jorge Eduardo Candelaria <jorge.candelaria@ti.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl6040");
......@@ -47,71 +47,26 @@
#define SYS_HBI_MASK 0xfff
#define SYS_PROCIDx_HBI_SHIFT 0
#define SYS_MCI_CARDIN (1 << 0)
#define SYS_MCI_WPROT (1 << 1)
#define SYS_MISC_MASTERSITE (1 << 14)
static void __iomem *__vexpress_sysreg_base;
static void __iomem *vexpress_sysreg_base(void)
void vexpress_flags_set(u32 data)
{
if (!__vexpress_sysreg_base) {
static void __iomem *base;
if (!base) {
struct device_node *node = of_find_compatible_node(NULL, NULL,
"arm,vexpress-sysreg");
__vexpress_sysreg_base = of_iomap(node, 0);
base = of_iomap(node, 0);
}
WARN_ON(!__vexpress_sysreg_base);
return __vexpress_sysreg_base;
}
static int vexpress_sysreg_get_master(void)
{
if (readl(vexpress_sysreg_base() + SYS_MISC) & SYS_MISC_MASTERSITE)
return VEXPRESS_SITE_DB2;
return VEXPRESS_SITE_DB1;
}
void vexpress_flags_set(u32 data)
{
writel(~0, vexpress_sysreg_base() + SYS_FLAGSCLR);
writel(data, vexpress_sysreg_base() + SYS_FLAGSSET);
}
unsigned int vexpress_get_mci_cardin(struct device *dev)
{
return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN;
}
u32 vexpress_get_procid(int site)
{
if (site == VEXPRESS_SITE_MASTER)
site = vexpress_sysreg_get_master();
return readl(vexpress_sysreg_base() + (site == VEXPRESS_SITE_DB1 ?
SYS_PROCID0 : SYS_PROCID1));
}
void __iomem *vexpress_get_24mhz_clock_base(void)
{
return vexpress_sysreg_base() + SYS_24MHZ;
}
if (WARN_ON(!base))
return;
void __init vexpress_sysreg_early_init(void __iomem *base)
{
__vexpress_sysreg_base = base;
vexpress_config_set_master(vexpress_sysreg_get_master());
writel(~0, base + SYS_FLAGSCLR);
writel(data, base + SYS_FLAGSSET);
}
/* The sysreg block is just a random collection of various functions... */
static struct syscon_platform_data vexpress_sysreg_sys_id_pdata = {
......@@ -210,6 +165,7 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
struct resource *mem;
void __iomem *base;
struct bgpio_chip *mmc_gpio_chip;
int master;
u32 dt_hbi;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -220,11 +176,14 @@ static int vexpress_sysreg_probe(struct platform_device *pdev)
if (!base)
return -ENOMEM;
vexpress_config_set_master(vexpress_sysreg_get_master());
master = readl(base + SYS_MISC) & SYS_MISC_MASTERSITE ?
VEXPRESS_SITE_DB2 : VEXPRESS_SITE_DB1;
vexpress_config_set_master(master);
/* Confirm board type against DT property, if available */
if (of_property_read_u32(of_root, "arm,hbi", &dt_hbi) == 0) {
u32 id = vexpress_get_procid(VEXPRESS_SITE_MASTER);
u32 id = readl(base + (master == VEXPRESS_SITE_DB1 ?
SYS_PROCID0 : SYS_PROCID1));
u32 hbi = (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
if (WARN_ON(dt_hbi != hbi))
......
......@@ -1172,9 +1172,6 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DAC_DIGITAL_VOLUME_3L:
case ARIZONA_DAC_VOLUME_LIMIT_3L:
case ARIZONA_NOISE_GATE_SELECT_3L:
case ARIZONA_OUTPUT_PATH_CONFIG_3R:
case ARIZONA_DAC_DIGITAL_VOLUME_3R:
case ARIZONA_DAC_VOLUME_LIMIT_3R:
case ARIZONA_OUTPUT_PATH_CONFIG_4L:
case ARIZONA_DAC_DIGITAL_VOLUME_4L:
case ARIZONA_OUT_VOLUME_4L:
......
......@@ -246,6 +246,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
*/
switch (arizona->type) {
case WM5110:
case WM8280:
desc = &arizona_micsupp_ext;
micsupp->init_data = arizona_micsupp_ext_default;
break;
......
......@@ -48,8 +48,6 @@ struct s5m_rtc_reg_config {
unsigned int alarm0;
/* First register for alarm 1, seconds */
unsigned int alarm1;
/* SMPL/WTSR register */
unsigned int smpl_wtsr;
/*
* Register for update flag (UDR). Typically setting UDR field to 1
* will enable update of time or alarm register. Then it will be
......@@ -67,7 +65,6 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
.ctrl = S5M_ALARM1_CONF,
.alarm0 = S5M_ALARM0_SEC,
.alarm1 = S5M_ALARM1_SEC,
.smpl_wtsr = S5M_WTSR_SMPL_CNTL,
.rtc_udr_update = S5M_RTC_UDR_CON,
.rtc_udr_mask = S5M_RTC_UDR_MASK,
};
......@@ -82,7 +79,6 @@ static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
.ctrl = S2MPS_RTC_CTRL,
.alarm0 = S2MPS_ALARM0_SEC,
.alarm1 = S2MPS_ALARM1_SEC,
.smpl_wtsr = S2MPS_WTSR_SMPL_CNTL,
.rtc_udr_update = S2MPS_RTC_UDR_CON,
.rtc_udr_mask = S2MPS_RTC_WUDR_MASK,
};
......@@ -96,7 +92,6 @@ struct s5m_rtc_info {
int irq;
int device_type;
int rtc_24hr_mode;
bool wtsr_smpl;
const struct s5m_rtc_reg_config *regs;
};
......@@ -597,28 +592,6 @@ static const struct rtc_class_ops s5m_rtc_ops = {
.alarm_irq_enable = s5m_rtc_alarm_irq_enable,
};
static void s5m_rtc_enable_wtsr(struct s5m_rtc_info *info, bool enable)
{
int ret;
ret = regmap_update_bits(info->regmap, info->regs->smpl_wtsr,
WTSR_ENABLE_MASK,
enable ? WTSR_ENABLE_MASK : 0);
if (ret < 0)
dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
__func__, ret);
}
static void s5m_rtc_enable_smpl(struct s5m_rtc_info *info, bool enable)
{
int ret;
ret = regmap_update_bits(info->regmap, info->regs->smpl_wtsr,
SMPL_ENABLE_MASK,
enable ? SMPL_ENABLE_MASK : 0);
if (ret < 0)
dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
__func__, ret);
}
static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
{
u8 data[2];
......@@ -715,7 +688,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
info->s5m87xx = s5m87xx;
info->device_type = s5m87xx->device_type;
info->wtsr_smpl = s5m87xx->wtsr_smpl;
if (s5m87xx->irq_data) {
info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
......@@ -731,11 +703,6 @@ static int s5m_rtc_probe(struct platform_device *pdev)
ret = s5m8767_rtc_init_reg(info);
if (info->wtsr_smpl) {
s5m_rtc_enable_wtsr(info, true);
s5m_rtc_enable_smpl(info, true);
}
device_init_wakeup(&pdev->dev, 1);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc",
......@@ -768,36 +735,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)
return ret;
}
static void s5m_rtc_shutdown(struct platform_device *pdev)
{
struct s5m_rtc_info *info = platform_get_drvdata(pdev);
int i;
unsigned int val = 0;
if (info->wtsr_smpl) {
for (i = 0; i < 3; i++) {
s5m_rtc_enable_wtsr(info, false);
regmap_read(info->regmap, info->regs->smpl_wtsr, &val);
pr_debug("%s: WTSR_SMPL reg(0x%02x)\n", __func__, val);
if (val & WTSR_ENABLE_MASK)
pr_emerg("%s: fail to disable WTSR\n",
__func__);
else {
pr_info("%s: success to disable WTSR\n",
__func__);
break;
}
}
}
/* Disable SMPL when power off */
s5m_rtc_enable_smpl(info, false);
}
static int s5m_rtc_remove(struct platform_device *pdev)
{
struct s5m_rtc_info *info = platform_get_drvdata(pdev);
/* Perform also all shutdown steps when removing */
s5m_rtc_shutdown(pdev);
i2c_unregister_device(info->i2c);
return 0;
......@@ -842,7 +783,6 @@ static struct platform_driver s5m_rtc_driver = {
},
.probe = s5m_rtc_probe,
.remove = s5m_rtc_remove,
.shutdown = s5m_rtc_shutdown,
.id_table = s5m_rtc_id,
};
......
......@@ -408,6 +408,16 @@ config BACKLIGHT_PANDORA
If you have a Pandora console, say Y to enable the
backlight driver.
config BACKLIGHT_SKY81452
tristate "Backlight driver for SKY81452"
depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
help
If you have a Skyworks SKY81452, say Y to enable the
backlight driver.
To compile this driver as a module, choose M here: the module will
be called sky81452-backlight
config BACKLIGHT_TPS65217
tristate "TPS65217 Backlight"
depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
......
......@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o
obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
/*
* sky81452-backlight.c SKY81452 backlight driver
*
* Copyright 2014 Skyworks Solutions Inc.
* Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/backlight.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/platform_data/sky81452-backlight.h>
#include <linux/slab.h>
/* registers */
#define SKY81452_REG0 0x00
#define SKY81452_REG1 0x01
#define SKY81452_REG2 0x02
#define SKY81452_REG4 0x04
#define SKY81452_REG5 0x05
/* bit mask */
#define SKY81452_CS 0xFF
#define SKY81452_EN 0x3F
#define SKY81452_IGPW 0x20
#define SKY81452_PWMMD 0x10
#define SKY81452_PHASE 0x08
#define SKY81452_ILIM 0x04
#define SKY81452_VSHRT 0x03
#define SKY81452_OCP 0x80
#define SKY81452_OTMP 0x40
#define SKY81452_SHRT 0x3F
#define SKY81452_OPN 0x3F
#define SKY81452_DEFAULT_NAME "lcd-backlight"
#define SKY81452_MAX_BRIGHTNESS (SKY81452_CS + 1)
#define CTZ(b) __builtin_ctz(b)
static int sky81452_bl_update_status(struct backlight_device *bd)
{
const struct sky81452_bl_platform_data *pdata =
dev_get_platdata(bd->dev.parent);
const unsigned int brightness = (unsigned int)bd->props.brightness;
struct regmap *regmap = bl_get_data(bd);
int ret;
if (brightness > 0) {
ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
if (IS_ERR_VALUE(ret))
return ret;
return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
pdata->enable << CTZ(SKY81452_EN));
}
return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
}
static const struct backlight_ops sky81452_bl_ops = {
.update_status = sky81452_bl_update_status,
};
static ssize_t sky81452_bl_store_enable(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct regmap *regmap = bl_get_data(to_backlight_device(dev));
unsigned long value;
int ret;
ret = kstrtoul(buf, 16, &value);
if (IS_ERR_VALUE(ret))
return ret;
ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
value << CTZ(SKY81452_EN));
if (IS_ERR_VALUE(ret))
return ret;
return count;
}
static ssize_t sky81452_bl_show_open_short(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regmap *regmap = bl_get_data(to_backlight_device(dev));
unsigned int reg, value = 0;
char tmp[3];
int i, ret;
reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
ret = regmap_read(regmap, reg, &value);
if (IS_ERR_VALUE(ret))
return ret;
if (value & SKY81452_SHRT) {
*buf = 0;
for (i = 0; i < 6; i++) {
if (value & 0x01) {
sprintf(tmp, "%d ", i + 1);
strcat(buf, tmp);
}
value >>= 1;
}
strcat(buf, "\n");
} else {
strcpy(buf, "none\n");
}
return strlen(buf);
}
static ssize_t sky81452_bl_show_fault(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regmap *regmap = bl_get_data(to_backlight_device(dev));
unsigned int value = 0;
int ret;
ret = regmap_read(regmap, SKY81452_REG4, &value);
if (IS_ERR_VALUE(ret))
return ret;
*buf = 0;
if (value & SKY81452_OCP)
strcat(buf, "over-current ");
if (value & SKY81452_OTMP)
strcat(buf, "over-temperature");
strcat(buf, "\n");
return strlen(buf);
}
static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
static struct attribute *sky81452_bl_attribute[] = {
&dev_attr_enable.attr,
&dev_attr_open.attr,
&dev_attr_short.attr,
&dev_attr_fault.attr,
NULL
};
static const struct attribute_group sky81452_bl_attr_group = {
.attrs = sky81452_bl_attribute,
};
#ifdef CONFIG_OF
static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
struct device *dev)
{
struct device_node *np = of_node_get(dev->of_node);
struct sky81452_bl_platform_data *pdata;
int num_entry;
unsigned int sources[6];
int ret;
if (!np) {
dev_err(dev, "backlight node not found.\n");
return ERR_PTR(-ENODATA);
}
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
of_node_put(np);
return ERR_PTR(-ENOMEM);
}
of_property_read_string(np, "name", &pdata->name);
pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
pdata->gpio_enable = of_get_gpio(np, 0);
ret = of_property_count_u32_elems(np, "led-sources");
if (IS_ERR_VALUE(ret)) {
pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
} else {
num_entry = ret;
if (num_entry > 6)
num_entry = 6;
ret = of_property_read_u32_array(np, "led-sources", sources,
num_entry);
if (IS_ERR_VALUE(ret)) {
dev_err(dev, "led-sources node is invalid.\n");
return ERR_PTR(-EINVAL);
}
pdata->enable = 0;
while (--num_entry)
pdata->enable |= (1 << sources[num_entry]);
}
ret = of_property_read_u32(np,
"skyworks,short-detection-threshold-volt",
&pdata->short_detection_threshold);
if (IS_ERR_VALUE(ret))
pdata->short_detection_threshold = 7;
ret = of_property_read_u32(np, "skyworks,current-limit-mA",
&pdata->boost_current_limit);
if (IS_ERR_VALUE(ret))
pdata->boost_current_limit = 2750;
of_node_put(np);
return pdata;
}
#else
static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
struct device *dev)
{
return ERR_PTR(-EINVAL);
}
#endif
static int sky81452_bl_init_device(struct regmap *regmap,
struct sky81452_bl_platform_data *pdata)
{
unsigned int value;
value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
if (pdata->boost_current_limit == 2300)
value |= SKY81452_ILIM;
else if (pdata->boost_current_limit != 2750)
return -EINVAL;
if (pdata->short_detection_threshold < 4 ||
pdata->short_detection_threshold > 7)
return -EINVAL;
value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
return regmap_write(regmap, SKY81452_REG2, value);
}
static int sky81452_bl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *regmap = dev_get_drvdata(dev->parent);
struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
struct backlight_device *bd;
struct backlight_properties props;
const char *name;
int ret;
if (!pdata) {
pdata = sky81452_bl_parse_dt(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
}
if (gpio_is_valid(pdata->gpio_enable)) {
ret = devm_gpio_request_one(dev, pdata->gpio_enable,
GPIOF_OUT_INIT_HIGH, "sky81452-en");
if (IS_ERR_VALUE(ret)) {
dev_err(dev, "failed to request GPIO. err=%d\n", ret);
return ret;
}
}
ret = sky81452_bl_init_device(regmap, pdata);
if (IS_ERR_VALUE(ret)) {
dev_err(dev, "failed to initialize. err=%d\n", ret);
return ret;
}
memset(&props, 0, sizeof(props));
props.max_brightness = SKY81452_MAX_BRIGHTNESS,
name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
bd = devm_backlight_device_register(dev, name, dev, regmap,
&sky81452_bl_ops, &props);
if (IS_ERR(bd)) {
dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
return PTR_ERR(bd);
}
platform_set_drvdata(pdev, bd);
ret = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
if (IS_ERR_VALUE(ret)) {
dev_err(dev, "failed to create attribute. err=%d\n", ret);
return ret;
}
return ret;
}
static int sky81452_bl_remove(struct platform_device *pdev)
{
const struct sky81452_bl_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct backlight_device *bd = platform_get_drvdata(pdev);
sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
bd->props.power = FB_BLANK_UNBLANK;
bd->props.brightness = 0;
backlight_update_status(bd);
if (gpio_is_valid(pdata->gpio_enable))
gpio_set_value_cansleep(pdata->gpio_enable, 0);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id sky81452_bl_of_match[] = {
{ .compatible = "skyworks,sky81452-backlight", },
{ }
};
MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
#endif
static struct platform_driver sky81452_bl_driver = {
.driver = {
.name = "sky81452-backlight",
.of_match_table = of_match_ptr(sky81452_bl_of_match),
},
.probe = sky81452_bl_probe,
.remove = sky81452_bl_remove,
};
module_platform_driver(sky81452_bl_driver);
MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
MODULE_LICENSE("GPL v2");
/*
* GPIO configuration for Arizona devices
* Device Tree defines for Arizona devices
*
* Copyright 2013 Wolfson Microelectronics. PLC.
* Copyright 2015 Cirrus Logic Inc.
*
* Author: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
*
......@@ -10,9 +10,10 @@
* published by the Free Software Foundation.
*/
#ifndef _ARIZONA_GPIO_H
#define _ARIZONA_GPIO_H
#ifndef _DT_BINDINGS_MFD_ARIZONA_H
#define _DT_BINDINGS_MFD_ARIZONA_H
/* GPIO Function Definitions */
#define ARIZONA_GP_FN_TXLRCLK 0x00
#define ARIZONA_GP_FN_GPIO 0x01
#define ARIZONA_GP_FN_IRQ1 0x02
......@@ -61,36 +62,32 @@
#define ARIZONA_GP_FN_SYSCLK_ENA_STATUS 0x4B
#define ARIZONA_GP_FN_ASYNCCLK_ENA_STATUS 0x4C
#define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */
#define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */
#define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */
#define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */
#define ARIZONA_GPN_PU 0x4000 /* GPN_PU */
#define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */
#define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */
#define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */
#define ARIZONA_GPN_PD 0x2000 /* GPN_PD */
#define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */
#define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */
#define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */
#define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */
#define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */
#define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */
#define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */
#define ARIZONA_GPN_POL 0x0400 /* GPN_POL */
#define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */
#define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */
#define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */
#define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */
#define ARIZONA_GPN_DB 0x0100 /* GPN_DB */
#define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */
#define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */
#define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */
#define ARIZONA_GPN_FN_MASK 0x007F /* GPN_DB */
#define ARIZONA_GPN_FN_SHIFT 0 /* GPN_DB */
#define ARIZONA_GPN_FN_WIDTH 7 /* GPN_DB */
/* GPIO Configuration Bits */
#define ARIZONA_GPN_DIR 0x8000
#define ARIZONA_GPN_PU 0x4000
#define ARIZONA_GPN_PD 0x2000
#define ARIZONA_GPN_LVL 0x0800
#define ARIZONA_GPN_POL 0x0400
#define ARIZONA_GPN_OP_CFG 0x0200
#define ARIZONA_GPN_DB 0x0100
/* Provide some defines for the most common configs */
#define ARIZONA_GP_DEFAULT 0xffffffff
#define ARIZONA_GP_OUTPUT (ARIZONA_GP_FN_GPIO)
#define ARIZONA_GP_INPUT (ARIZONA_GP_FN_GPIO | \
ARIZONA_GPN_DIR)
#define ARIZONA_32KZ_MCLK1 1
#define ARIZONA_32KZ_MCLK2 2
#define ARIZONA_32KZ_NONE 3
#define ARIZONA_DMIC_MICVDD 0
#define ARIZONA_DMIC_MICBIAS1 1
#define ARIZONA_DMIC_MICBIAS2 2
#define ARIZONA_DMIC_MICBIAS3 3
#define ARIZONA_INMODE_DIFF 0
#define ARIZONA_INMODE_SE 1
#define ARIZONA_INMODE_DMIC 2
#endif
......@@ -141,6 +141,12 @@
#define QCOM_RPM_SYS_FABRIC_MODE 131
#define QCOM_RPM_USB_OTG_SWITCH 132
#define QCOM_RPM_VDDMIN_GPIO 133
#define QCOM_RPM_NSS_FABRIC_0_CLK 134
#define QCOM_RPM_NSS_FABRIC_1_CLK 135
#define QCOM_RPM_SMB208_S1a 136
#define QCOM_RPM_SMB208_S1b 137
#define QCOM_RPM_SMB208_S2a 138
#define QCOM_RPM_SMB208_S2b 139
/*
* Constants used to select force mode for regulators.
......
......@@ -24,6 +24,7 @@ enum arizona_type {
WM5102 = 1,
WM5110 = 2,
WM8997 = 3,
WM8280 = 4,
};
#define ARIZONA_IRQ_GP1 0
......
......@@ -11,31 +11,26 @@
#ifndef _ARIZONA_PDATA_H
#define _ARIZONA_PDATA_H
#define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */
#include <dt-bindings/mfd/arizona.h>
#define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */
#define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */
#define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */
#define ARIZONA_GPN_PU 0x4000 /* GPN_PU */
#define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */
#define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */
#define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */
#define ARIZONA_GPN_PD 0x2000 /* GPN_PD */
#define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */
#define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */
#define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */
#define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */
#define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */
#define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */
#define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */
#define ARIZONA_GPN_POL 0x0400 /* GPN_POL */
#define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */
#define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */
#define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */
#define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */
#define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */
#define ARIZONA_GPN_DB 0x0100 /* GPN_DB */
#define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */
#define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */
#define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */
......@@ -45,23 +40,10 @@
#define ARIZONA_MAX_GPIO 5
#define ARIZONA_32KZ_MCLK1 1
#define ARIZONA_32KZ_MCLK2 2
#define ARIZONA_32KZ_NONE 3
#define ARIZONA_MAX_INPUT 4
#define ARIZONA_DMIC_MICVDD 0
#define ARIZONA_DMIC_MICBIAS1 1
#define ARIZONA_DMIC_MICBIAS2 2
#define ARIZONA_DMIC_MICBIAS3 3
#define ARIZONA_MAX_MICBIAS 3
#define ARIZONA_INMODE_DIFF 0
#define ARIZONA_INMODE_SE 1
#define ARIZONA_INMODE_DMIC 2
#define ARIZONA_MAX_OUTPUT 6
#define ARIZONA_MAX_AIF 3
......@@ -112,7 +94,7 @@ struct arizona_pdata {
int gpio_base;
/** Pin state for GPIO pins */
int gpio_defaults[ARIZONA_MAX_GPIO];
unsigned int gpio_defaults[ARIZONA_MAX_GPIO];
/**
* Maximum number of channels clocks will be generated for,
......
......@@ -87,6 +87,7 @@ enum max77693_pmic_reg {
/* MAX77693 ITORCH register */
#define TORCH_IOUT1_SHIFT 0
#define TORCH_IOUT2_SHIFT 4
#define TORCH_IOUT_MASK(x) (0xf << (x))
#define TORCH_IOUT_MIN 15625
#define TORCH_IOUT_MAX 250000
#define TORCH_IOUT_STEP 15625
......@@ -113,8 +114,8 @@ enum max77693_pmic_reg {
#define FLASH_EN_FLASH 0x1
#define FLASH_EN_TORCH 0x2
#define FLASH_EN_ON 0x3
#define FLASH_EN_SHIFT(x) (6 - ((x) - 1) * 2)
#define TORCH_EN_SHIFT(x) (2 - ((x) - 1) * 2)
#define FLASH_EN_SHIFT(x) (6 - (x) * 2)
#define TORCH_EN_SHIFT(x) (2 - (x) * 2)
/* MAX77693 MAX_FLASH1 register */
#define MAX_FLASH1_MAX_FL_EN 0x80
......
......@@ -81,19 +81,6 @@ enum max77693_led_boost_mode {
MAX77693_LED_BOOST_FIXED,
};
struct max77693_led_platform_data {
u32 fleds[2];
u32 iout_torch[2];
u32 iout_flash[2];
u32 trigger[2];
u32 trigger_type[2];
u32 num_leds;
u32 boost_mode;
u32 flash_timeout;
u32 boost_vout;
u32 low_vsys;
};
/* MAX77693 */
struct max77693_platform_data {
......
This diff is collapsed.
......@@ -24,7 +24,6 @@ extern int menelaus_set_vaux(unsigned int mV);
extern int menelaus_set_vdcdc(int dcdc, unsigned int mV);
extern int menelaus_set_slot_sel(int enable);
extern int menelaus_get_slot_pin_states(void);
extern int menelaus_set_vcore_sw(unsigned int mV);
extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
#define EN_VPLL_SLEEP (1 << 7)
......@@ -38,10 +37,4 @@ extern int menelaus_set_vcore_hw(unsigned int roof_mV, unsigned int floor_mV);
extern int menelaus_set_regulator_sleep(int enable, u32 val);
#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_MENELAUS)
#define omap_has_menelaus() 1
#else
#define omap_has_menelaus() 0
#endif
#endif
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Flora Fu, MediaTek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MFD_MT6397_CORE_H__
#define __MFD_MT6397_CORE_H__
enum mt6397_irq_numbers {
MT6397_IRQ_SPKL_AB = 0,
MT6397_IRQ_SPKR_AB,
MT6397_IRQ_SPKL,
MT6397_IRQ_SPKR,
MT6397_IRQ_BAT_L,
MT6397_IRQ_BAT_H,
MT6397_IRQ_FG_BAT_L,
MT6397_IRQ_FG_BAT_H,
MT6397_IRQ_WATCHDOG,
MT6397_IRQ_PWRKEY,
MT6397_IRQ_THR_L,
MT6397_IRQ_THR_H,
MT6397_IRQ_VBATON_UNDET,
MT6397_IRQ_BVALID_DET,
MT6397_IRQ_CHRDET,
MT6397_IRQ_OV,
MT6397_IRQ_LDO,
MT6397_IRQ_HOMEKEY,
MT6397_IRQ_ACCDET,
MT6397_IRQ_AUDIO,
MT6397_IRQ_RTC,
MT6397_IRQ_PWRKEY_RSTB,
MT6397_IRQ_HDMI_SIFM,
MT6397_IRQ_HDMI_CEC,
MT6397_IRQ_VCA15,
MT6397_IRQ_VSRMCA15,
MT6397_IRQ_VCORE,
MT6397_IRQ_VGPU,
MT6397_IRQ_VIO18,
MT6397_IRQ_VPCA7,
MT6397_IRQ_VSRMCA7,
MT6397_IRQ_VDRM,
MT6397_IRQ_NR,
};
struct mt6397_chip {
struct device *dev;
struct regmap *regmap;
int irq;
struct irq_domain *irq_domain;
struct mutex irqlock;
u16 irq_masks_cur[2];
u16 irq_masks_cache[2];
};
#endif /* __MFD_MT6397_CORE_H__ */
This diff is collapsed.
......@@ -156,6 +156,9 @@ enum rk808_reg {
#define BUCK2_RATE_MASK (3 << 3)
#define MASK_ALL 0xff
#define BUCK_UV_ACT_MASK 0x0f
#define BUCK_UV_ACT_DISABLE 0
#define SWITCH2_EN BIT(6)
#define SWITCH1_EN BIT(5)
#define DEV_OFF_RST BIT(3)
......
This diff is collapsed.
......@@ -58,13 +58,7 @@ enum sec_device_type {
* @irq_base: Base IRQ number for device, required for IRQs
* @irq: Generic IRQ number for device
* @irq_data: Runtime data structure for IRQ controller
* @ono: Power onoff IRQ number for s5m87xx
* @wakeup: Whether or not this is a wakeup device
* @wtsr_smpl: Whether or not to enable in RTC driver the Watchdog
* Timer Software Reset (registers set to default value
* after PWRHOLD falling) and Sudden Momentary Power Loss
* (PMIC will enter power on sequence after short drop in
* VBATT voltage).
*/
struct sec_pmic_dev {
struct device *dev;
......@@ -77,9 +71,7 @@ struct sec_pmic_dev {
int irq;
struct regmap_irq_chip_data *irq_data;
int ono;
bool wakeup;
bool wtsr_smpl;
};
int sec_irq_init(struct sec_pmic_dev *sec_pmic);
......@@ -95,7 +87,6 @@ struct sec_platform_data {
int irq_base;
int (*cfg_pmic_irq)(void);
int ono;
bool wakeup;
bool buck_voltage_lock;
......
......@@ -74,8 +74,8 @@ enum s2mps11_irq {
S2MPS11_IRQ_MRB,
S2MPS11_IRQ_RTC60S,
S2MPS11_IRQ_RTCA0,
S2MPS11_IRQ_RTCA1,
S2MPS11_IRQ_RTCA0,
S2MPS11_IRQ_SMPL,
S2MPS11_IRQ_RTC1S,
S2MPS11_IRQ_WTSR,
......
/* Driver for Realtek PCI-Express card reader
/*
* sky81452.h SKY81452 MFD driver
*
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
* Copyright 2014 Skyworks Solutions Inc.
* Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
......@@ -14,24 +15,17 @@
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Micky Ching <micky_ching@realsil.com.cn>
*/
#include <linux/mfd/rtsx_pci.h>
#include "rtsx_pcr.h"
#ifndef _SKY81452_H
#define _SKY81452_H
int rtsx_gops_pm_reset(struct rtsx_pcr *pcr)
{
int err;
#include <linux/platform_data/sky81452-backlight.h>
#include <linux/regulator/machine.h>
/* init aspm */
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00);
err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00);
if (err < 0)
return err;
struct sky81452_platform_data {
struct sky81452_bl_platform_data *bl_pdata;
struct regulator_init_data *regulator_init_data;
};
/* reset PM_CTRL3 before send buffer cmd */
return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
}
#endif
......@@ -128,6 +128,7 @@
/* Sequencer Status */
#define SEQ_STATUS BIT(5)
#define CHARGE_STEP 0x11
#define ADC_CLK 3000000
#define TOTAL_STEPS 16
......
/*
* sky81452.h SKY81452 backlight driver
*
* Copyright 2014 Skyworks Solutions Inc.
* Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SKY81452_BACKLIGHT_H
#define _SKY81452_BACKLIGHT_H
/**
* struct sky81452_platform_data
* @name: backlight driver name.
If it is not defined, default name is lcd-backlight.
* @gpio_enable:GPIO number which control EN pin
* @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
* @ignore_pwm: true if DPWMI should be ignored.
* @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode.
* @phase_shift:true is phase shift mode.
* @short_detecion_threshold: It should be one of 4, 5, 6 and 7V.
* @boost_current_limit: It should be one of 2300, 2750mA.
*/
struct sky81452_bl_platform_data {
const char *name;
int gpio_enable;
unsigned int enable;
bool ignore_pwm;
bool dpwm_mode;
bool phase_shift;
unsigned int short_detection_threshold;
unsigned int boost_current_limit;
};
#endif
......@@ -19,7 +19,6 @@
#include <sound/tlv.h>
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/gpio.h>
#include <linux/mfd/arizona/registers.h>
#include "arizona.h"
......@@ -281,6 +280,7 @@ int arizona_init_gpio(struct snd_soc_codec *codec)
switch (arizona->type) {
case WM5110:
case WM8280:
snd_soc_dapm_disable_pin(&codec->dapm, "DRC2 Signal Activity");
break;
default:
......@@ -1729,6 +1729,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
switch (fll->arizona->type) {
case WM5110:
case WM8280:
if (fll->arizona->rev < 3 || sync)
return init_ratio;
break;
......
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