MFD changes due for the v3.14 merge window
New drivers - Samsung Maxim 14577; Micro USB, Regulator, IRQ Controller and Battery Charger - TI/National Semiconductor LP3943 I2C GPIO Expander and PWM Generator Existing driver adaptions - Expansion of Wolfson Arizona DSP and High-Pass filter controls - TI TWL6040 default Regmap support and Regcache addition/bypass - Some nice Smatch catch fixes - Conversion of TI OMAP-USB and TI TWL6030 to endian neutralness - ChromeOS EC timing (delay) adaptions and added dependency on OF - Many constifications of 'struct {mfd_cell,regmap_irq,et. al}' - Watchdog support added for NVIDIA AS3722 - Convert functions to static in TI AM335x - Realigned previously defeated functionality in TI AM335x - IIO ADC-TSC concurrency dead-lock/timeout resolution - Addition of Power Management and Clock support for Samsung core - DEFINE_PCI_DEVICE_TABLE macro removal from MFD Subsystem - Greater use of irqdomain functionality in ST-E AB8500 - Removal of 'include/linux/mfd/abx500/ab8500-gpio.h' - Wolfson WM831x PMIC Power Management changes s/poweroff/shutdown/ - Device Tree documentation added for TI/Nat Semi LP3943 - Version detection and voltage tables for TI TPS6586x PMIC devices - Simplification of Freescale MC13XXX (de-)initialisation routines - Clean-up and simplification of the Realtek parent driver - Added support for RTL8402 Realtek PCI-Express card reader - Resource leak fix for Maxim 77686 - Possible suspend BUG() fix in OMAP USB TLL - Support for new Wolfson WM5110 Revision (D) - Testing of automatic assignment of of_node in mfd_add_device() - Reversion of the above when it started to cause issues - Remove legacy Platform Data from; TI TWL Core, Qualcomm SSBI and ST-E ABx500 Pinctrl - Clean-ups; tabbing issues, function name changes, 'drvdata = NULL' removal, unused uninitialised warning mitigation, error message clarity, removal of redundant/duplicate checks, licensing (GPL -> GPL2), coding consistency, duplicate function declaration, ret checks, commit corrections, redundant of_match_ptr() helper removal, spelling, #if-deffery removal and header guards name changes -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIbBAABAgAGBQJS3pLGAAoJEFGvii+H/HdhmkkP93Hrd9FBjVpmUQcOrghFDd// vte2LVDovXDcwm7i+BdZNG3+2aWtliTQXIw8PaAziUTwMlDNtT2B6GBFnIff4aXB Em/Oh6Je7r1gom1gMPCuefRrInTk0xEXy9Oazp4Hn4in71T+8PHNlEHdxEojakEm H5FnjAfgISEsA5twSyO9efVLNqPd3UQqg3O571oKwfuSED70YSCW2Yyaoiz4pnE5 0WwZ9cel+sP7CIuyuR4TumUSDeBIAnYnZWqjqXZ1ueMWcm2RNVqeFrt/w0uoZjOA yBg8ZMfkBcePd6qnifqVqagRW/jW1bxmUeIHkp0bWeMqWN6Yyypitz8ZW+Qi7Swa OcmgM9V7OW1WG9FF7HoLbYHIPzmBb6duGtcCfAir4m8HJjyPfTuJpOshBW1F3+VG yEf5a1fj2NO34kvIbLec2f7MveIMmZxzWaoOx+ET9/WPknilifgyp7eDH24pQwI4 5Lo5Z5uAfBCT3roOzHxCLl2nVXQoC66iTwdnneiEOn4rB/ApjfGVvGGd0VT6TD+g z3RqxpTdkd0AtjfeF778uTDBEKu7HZkqmlBP8HKWCBEAzqcKg7BpjYw0ajgmVwKr QiuBuWcEZ/2vVt8Qot7y5Vx89Q4AQwOqc24SldtQLu46iPAuKt+GizzHRw3IxBiQ VU9Aq/VoaTHBLS91tDE= =PuTE -----END PGP SIGNATURE----- Merge tag 'mfd-3.14-1' of git://git.linaro.org/people/ljones/mfd Pull MFD changes from Lee Jones: "New drivers - Samsung Maxim 14577; Micro USB, Regulator, IRQ Controller and Battery Charger - TI/National Semiconductor LP3943 I2C GPIO Expander and PWM Generator Existing driver adaptions - Expansion of Wolfson Arizona DSP and High-Pass filter controls - TI TWL6040 default Regmap support and Regcache addition/bypass - Some nice Smatch catch fixes - Conversion of TI OMAP-USB and TI TWL6030 to endian neutralness - ChromeOS EC timing (delay) adaptions and added dependency on OF - Many constifications of 'struct {mfd_cell,regmap_irq,et.al}' - Watchdog support added for NVIDIA AS3722 - Convert functions to static in TI AM335x - Realigned previously defeated functionality in TI AM335x - IIO ADC-TSC concurrency dead-lock/timeout resolution - Addition of Power Management and Clock support for Samsung core - DEFINE_PCI_DEVICE_TABLE macro removal from MFD Subsystem - Greater use of irqdomain functionality in ST-E AB8500 - Removal of 'include/linux/mfd/abx500/ab8500-gpio.h' - Wolfson WM831x PMIC Power Management changes s/poweroff/shutdown/ - Device Tree documentation added for TI/Nat Semi LP3943 - Version detection and voltage tables for TI TPS6586x PMIC devices - Simplification of Freescale MC13XXX (de-)initialisation routines - Clean-up and simplification of the Realtek parent driver - Added support for RTL8402 Realtek PCI-Express card reader - Resource leak fix for Maxim 77686 - Possible suspend BUG() fix in OMAP USB TLL - Support for new Wolfson WM5110 Revision (D) - Testing of automatic assignment of of_node in mfd_add_device() - Reversion of the above when it started to cause issues - Remove legacy Platform Data from; TI TWL Core, Qualcomm SSBI and ST-E ABx500 Pinctrl - Clean-ups; tabbing issues, function name changes, 'drvdata = NULL' removal, unused uninitialised warning mitigation, error message clarity, removal of redundant/duplicate checks, licensing (GPL -> GPL2), coding consistency, duplicate function declaration, ret checks, commit corrections, redundant of_match_ptr() helper removal, spelling, #if-deffery removal and header guards name changes" * tag 'mfd-3.14-1' of git://git.linaro.org/people/ljones/mfd: (78 commits) mfd: wm5110: Add register patch for rev D chip mfd: omap-usb-tll: Don't hold lock during pm_runtime_get/put_sync() gpio: lp3943: Remove redundant of_match_ptr helper mfd: sta2x11-mfd: Use named constants for pci_power_t values Documentation: mfd: Fix LDO index in s2mps11.txt mfd: Cleanup mfd-mcp-sa11x0.h header mfd: max8997: Use "IS_ENABLED(CONFIG_OF)" for DT code. mfd: twl6030: Fix endianness problem in IRQ handler mfd: sec-core: Add cells for S5M8767-clocks mfd: max14577: Remove redundant of_match_ptr helper mfd: twl6040: Fix sparse non static symbol warning mfd: Revert "mfd: Always assign of_node in mfd_add_device()" mfd: rtsx: Fix sparse non static symbol warning mfd: max77693: Set proper maximum register for MUIC regmap mfd: max77686: Fix regmap resource leak on driver remove mfd: Represent correct filenames in file headers mfd: rtsx: Add support for card reader rtl8402 mfd: rtsx: Add set pull control macro and simplify rtl8411 mfd: max8997: Enforce mfd_add_devices() return value check mfd: mc13xxx: Simplify probe() & remove() ...
This commit is contained in:
commit
ac26663572
|
@ -0,0 +1,37 @@
|
|||
TI/National Semiconductor LP3943 GPIO controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,lp3943-gpio"
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells: Should be 2. See gpio.txt in this directory for a
|
||||
description of the cells format.
|
||||
|
||||
Example:
|
||||
Simple LED controls with LP3943 GPIO controller
|
||||
|
||||
&i2c4 {
|
||||
lp3943@60 {
|
||||
compatible = "ti,lp3943";
|
||||
reg = <0x60>;
|
||||
|
||||
gpioex: gpio {
|
||||
compatible = "ti,lp3943-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
indicator1 {
|
||||
label = "indi1";
|
||||
gpios = <&gpioex 9 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
indicator2 {
|
||||
label = "indi2";
|
||||
gpios = <&gpioex 10 GPIO_ACTIVE_LOW>;
|
||||
default-state = "off";
|
||||
};
|
||||
};
|
|
@ -17,6 +17,15 @@ Required properties (SPI):
|
|||
- compatible: "google,cros-ec-spi"
|
||||
- reg: SPI chip select
|
||||
|
||||
Optional properties (SPI):
|
||||
- google,cros-ec-spi-msg-delay: Some implementations of the EC require some
|
||||
additional processing time in order to accept new transactions. If the delay
|
||||
between transactions is not long enough the EC may not be able to respond
|
||||
properly to subsequent transactions and cause them to hang. This property
|
||||
specifies the delay, in usecs, introduced between transactions to account
|
||||
for the time required by the EC to get back into a state in which new data
|
||||
can be accepted.
|
||||
|
||||
Required properties (LPC):
|
||||
- compatible: "google,cros-ec-lpc"
|
||||
- reg: List of (IO address, size) pairs defining the interface uses
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
TI/National Semiconductor LP3943 MFD driver
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,lp3943"
|
||||
- reg: I2C slave address. From 0x60 to 0x67.
|
||||
|
||||
LP3943 consists of two sub-devices, lp3943-gpio and lp3943-pwm.
|
||||
|
||||
For the LP3943 GPIO properties please refer to:
|
||||
Documentation/devicetree/bindings/gpio/gpio-lp3943.txt
|
||||
|
||||
For the LP3943 PWM properties please refer to:
|
||||
Documentation/devicetree/bindings/pwm/pwm-lp3943.txt
|
||||
|
||||
Example:
|
||||
|
||||
lp3943@60 {
|
||||
compatible = "ti,lp3943";
|
||||
reg = <0x60>;
|
||||
|
||||
gpioex: gpio {
|
||||
compatible = "ti,lp3943-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
pwm3943: pwm {
|
||||
compatible = "ti,lp3943-pwm";
|
||||
#pwm-cells = <2>;
|
||||
ti,pwm0 = <8 9 10>;
|
||||
ti,pwm1 = <15>;
|
||||
};
|
||||
};
|
|
@ -60,7 +60,7 @@ as per the datasheet of s2mps11.
|
|||
|
||||
- LDOn
|
||||
- valid values for n are 1 to 38
|
||||
- Example: LDO0, LD01, LDO28
|
||||
- Example: LDO1, LD02, LDO28
|
||||
- BUCKn
|
||||
- valid values for n are 1 to 10.
|
||||
- Example: BUCK1, BUCK2, BUCK9
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
TI/National Semiconductor LP3943 PWM controller
|
||||
|
||||
Required properties:
|
||||
- compatible: "ti,lp3943-pwm"
|
||||
- #pwm-cells: Should be 2. See pwm.txt in this directory for a
|
||||
description of the cells format.
|
||||
Note that this hardware limits the period length to the
|
||||
range 6250~1600000.
|
||||
- ti,pwm0 or ti,pwm1: Output pin number(s) for PWM channel 0 or 1.
|
||||
0 = output 0
|
||||
1 = output 1
|
||||
.
|
||||
.
|
||||
15 = output 15
|
||||
|
||||
Example:
|
||||
PWM 0 is for RGB LED brightness control
|
||||
PWM 1 is for brightness control of LP8557 backlight device
|
||||
|
||||
&i2c3 {
|
||||
lp3943@60 {
|
||||
compatible = "ti,lp3943";
|
||||
reg = <0x60>;
|
||||
|
||||
/*
|
||||
* PWM 0 : output 8, 9 and 10
|
||||
* PWM 1 : output 15
|
||||
*/
|
||||
pwm3943: pwm {
|
||||
compatible = "ti,lp3943-pwm";
|
||||
#pwm-cells = <2>;
|
||||
ti,pwm0 = <8 9 10>;
|
||||
ti,pwm1 = <15>;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/* LEDs control with PWM 0 of LP3943 */
|
||||
pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
rgb {
|
||||
label = "indi::rgb";
|
||||
pwms = <&pwm3943 0 10000>;
|
||||
max-brightness = <255>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
/* Backlight control with PWM 1 of LP3943 */
|
||||
backlight@2c {
|
||||
compatible = "ti,lp8557";
|
||||
reg = <0x2c>;
|
||||
|
||||
pwms = <&pwm3943 1 10000>;
|
||||
pwm-names = "lp8557";
|
||||
};
|
||||
};
|
|
@ -268,8 +268,8 @@
|
|||
reg = <3>;
|
||||
regulator-compatible = "sm2";
|
||||
regulator-name = "vdd_sm2,vin_ldo*";
|
||||
regulator-min-microvolt = <3700000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
|
|
|
@ -406,6 +406,14 @@ config GPIO_ARIZONA
|
|||
help
|
||||
Support for GPIOs on Wolfson Arizona class devices.
|
||||
|
||||
config GPIO_LP3943
|
||||
tristate "TI/National Semiconductor LP3943 GPIO expander"
|
||||
depends on MFD_LP3943
|
||||
help
|
||||
GPIO driver for LP3943 MFD.
|
||||
LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
|
||||
Open drain outputs are required for this usage.
|
||||
|
||||
config GPIO_MAX7300
|
||||
tristate "Maxim MAX7300 GPIO expander"
|
||||
depends on I2C
|
||||
|
|
|
@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
|
|||
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
|
||||
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
|
||||
obj-$(CONFIG_GPIO_INTEL_MID) += gpio-intel-mid.o
|
||||
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
|
||||
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
|
||||
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
|
||||
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* TI/National Semiconductor LP3943 GPIO driver
|
||||
*
|
||||
* Copyright 2013 Texas Instruments
|
||||
*
|
||||
* Author: Milo Kim <milo.kim@ti.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; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/lp3943.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
enum lp3943_gpios {
|
||||
LP3943_GPIO1,
|
||||
LP3943_GPIO2,
|
||||
LP3943_GPIO3,
|
||||
LP3943_GPIO4,
|
||||
LP3943_GPIO5,
|
||||
LP3943_GPIO6,
|
||||
LP3943_GPIO7,
|
||||
LP3943_GPIO8,
|
||||
LP3943_GPIO9,
|
||||
LP3943_GPIO10,
|
||||
LP3943_GPIO11,
|
||||
LP3943_GPIO12,
|
||||
LP3943_GPIO13,
|
||||
LP3943_GPIO14,
|
||||
LP3943_GPIO15,
|
||||
LP3943_GPIO16,
|
||||
LP3943_MAX_GPIO,
|
||||
};
|
||||
|
||||
struct lp3943_gpio {
|
||||
struct gpio_chip chip;
|
||||
struct lp3943 *lp3943;
|
||||
u16 input_mask; /* 1 = GPIO is input direction, 0 = output */
|
||||
};
|
||||
|
||||
static inline struct lp3943_gpio *to_lp3943_gpio(struct gpio_chip *_chip)
|
||||
{
|
||||
return container_of(_chip, struct lp3943_gpio, chip);
|
||||
}
|
||||
|
||||
static int lp3943_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
struct lp3943 *lp3943 = lp3943_gpio->lp3943;
|
||||
|
||||
/* Return an error if the pin is already assigned */
|
||||
if (test_and_set_bit(offset, &lp3943->pin_used))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lp3943_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
struct lp3943 *lp3943 = lp3943_gpio->lp3943;
|
||||
|
||||
clear_bit(offset, &lp3943->pin_used);
|
||||
}
|
||||
|
||||
static int lp3943_gpio_set_mode(struct lp3943_gpio *lp3943_gpio, u8 offset,
|
||||
u8 val)
|
||||
{
|
||||
struct lp3943 *lp3943 = lp3943_gpio->lp3943;
|
||||
const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
|
||||
|
||||
return lp3943_update_bits(lp3943, mux[offset].reg, mux[offset].mask,
|
||||
val << mux[offset].shift);
|
||||
}
|
||||
|
||||
static int lp3943_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
|
||||
lp3943_gpio->input_mask |= BIT(offset);
|
||||
|
||||
return lp3943_gpio_set_mode(lp3943_gpio, offset, LP3943_GPIO_IN);
|
||||
}
|
||||
|
||||
static int lp3943_get_gpio_in_status(struct lp3943_gpio *lp3943_gpio,
|
||||
struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
u8 addr, read;
|
||||
int err;
|
||||
|
||||
switch (offset) {
|
||||
case LP3943_GPIO1 ... LP3943_GPIO8:
|
||||
addr = LP3943_REG_GPIO_A;
|
||||
break;
|
||||
case LP3943_GPIO9 ... LP3943_GPIO16:
|
||||
addr = LP3943_REG_GPIO_B;
|
||||
offset = offset - 8;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = lp3943_read_byte(lp3943_gpio->lp3943, addr, &read);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !!(read & BIT(offset));
|
||||
}
|
||||
|
||||
static int lp3943_get_gpio_out_status(struct lp3943_gpio *lp3943_gpio,
|
||||
struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct lp3943 *lp3943 = lp3943_gpio->lp3943;
|
||||
const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
|
||||
u8 read;
|
||||
int err;
|
||||
|
||||
err = lp3943_read_byte(lp3943, mux[offset].reg, &read);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
read = (read & mux[offset].mask) >> mux[offset].shift;
|
||||
|
||||
if (read == LP3943_GPIO_OUT_HIGH)
|
||||
return 1;
|
||||
else if (read == LP3943_GPIO_OUT_LOW)
|
||||
return 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int lp3943_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
|
||||
/*
|
||||
* Limitation:
|
||||
* LP3943 doesn't have the GPIO direction register. It provides
|
||||
* only input and output status registers.
|
||||
* So, direction info is required to handle the 'get' operation.
|
||||
* This variable is updated whenever the direction is changed and
|
||||
* it is used here.
|
||||
*/
|
||||
|
||||
if (lp3943_gpio->input_mask & BIT(offset))
|
||||
return lp3943_get_gpio_in_status(lp3943_gpio, chip, offset);
|
||||
else
|
||||
return lp3943_get_gpio_out_status(lp3943_gpio, chip, offset);
|
||||
}
|
||||
|
||||
static void lp3943_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
u8 data;
|
||||
|
||||
if (value)
|
||||
data = LP3943_GPIO_OUT_HIGH;
|
||||
else
|
||||
data = LP3943_GPIO_OUT_LOW;
|
||||
|
||||
lp3943_gpio_set_mode(lp3943_gpio, offset, data);
|
||||
}
|
||||
|
||||
static int lp3943_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = to_lp3943_gpio(chip);
|
||||
|
||||
lp3943_gpio_set(chip, offset, value);
|
||||
lp3943_gpio->input_mask &= ~BIT(offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct gpio_chip lp3943_gpio_chip = {
|
||||
.label = "lp3943",
|
||||
.owner = THIS_MODULE,
|
||||
.request = lp3943_gpio_request,
|
||||
.free = lp3943_gpio_free,
|
||||
.direction_input = lp3943_gpio_direction_input,
|
||||
.get = lp3943_gpio_get,
|
||||
.direction_output = lp3943_gpio_direction_output,
|
||||
.set = lp3943_gpio_set,
|
||||
.base = -1,
|
||||
.ngpio = LP3943_MAX_GPIO,
|
||||
.can_sleep = 1,
|
||||
};
|
||||
|
||||
static int lp3943_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct lp3943_gpio *lp3943_gpio;
|
||||
|
||||
lp3943_gpio = devm_kzalloc(&pdev->dev, sizeof(*lp3943_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!lp3943_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
lp3943_gpio->lp3943 = lp3943;
|
||||
lp3943_gpio->chip = lp3943_gpio_chip;
|
||||
lp3943_gpio->chip.dev = &pdev->dev;
|
||||
|
||||
platform_set_drvdata(pdev, lp3943_gpio);
|
||||
|
||||
return gpiochip_add(&lp3943_gpio->chip);
|
||||
}
|
||||
|
||||
static int lp3943_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp3943_gpio *lp3943_gpio = platform_get_drvdata(pdev);
|
||||
|
||||
return gpiochip_remove(&lp3943_gpio->chip);
|
||||
}
|
||||
|
||||
static const struct of_device_id lp3943_gpio_of_match[] = {
|
||||
{ .compatible = "ti,lp3943-gpio", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lp3943_gpio_of_match);
|
||||
|
||||
static struct platform_driver lp3943_gpio_driver = {
|
||||
.probe = lp3943_gpio_probe,
|
||||
.remove = lp3943_gpio_remove,
|
||||
.driver = {
|
||||
.name = "lp3943-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = lp3943_gpio_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(lp3943_gpio_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LP3943 GPIO driver");
|
||||
MODULE_ALIAS("platform:lp3943-gpio");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -60,6 +60,24 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
|
|||
return step_en;
|
||||
}
|
||||
|
||||
static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
|
||||
struct iio_chan_spec const *chan)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
|
||||
if (chan->channel == adc_dev->channel_line[i]) {
|
||||
u32 step;
|
||||
|
||||
step = adc_dev->channel_step[i];
|
||||
/* +1 for the charger */
|
||||
return 1 << (step + 1);
|
||||
}
|
||||
}
|
||||
WARN_ON(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
|
||||
{
|
||||
return 1 << adc_dev->channel_step[chan];
|
||||
|
@ -181,7 +199,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
|
|||
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
|
||||
adc_dev->buffer_en_ch_steps = enb;
|
||||
|
||||
am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
|
||||
am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
|
||||
|
||||
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
|
||||
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
|
||||
|
@ -199,6 +217,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
|
|||
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
|
||||
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
|
||||
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
|
||||
adc_dev->buffer_en_ch_steps = 0;
|
||||
|
||||
/* Flush FIFO of leftover data in the time it takes to disable adc */
|
||||
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||
|
@ -328,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|||
unsigned int fifo1count, read, stepid;
|
||||
bool found = false;
|
||||
u32 step_en;
|
||||
unsigned long timeout = jiffies + usecs_to_jiffies
|
||||
(IDLE_TIMEOUT * adc_dev->channels);
|
||||
unsigned long timeout;
|
||||
|
||||
if (iio_buffer_enabled(indio_dev))
|
||||
return -EBUSY;
|
||||
|
||||
step_en = get_adc_step_mask(adc_dev);
|
||||
am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
|
||||
step_en = get_adc_chan_step_mask(adc_dev, chan);
|
||||
if (!step_en)
|
||||
return -EINVAL;
|
||||
|
||||
/* Wait for ADC sequencer to complete sampling */
|
||||
while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
|
||||
if (time_after(jiffies, timeout))
|
||||
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||
while (fifo1count--)
|
||||
tiadc_readl(adc_dev, REG_FIFO1);
|
||||
|
||||
am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
|
||||
|
||||
timeout = jiffies + usecs_to_jiffies
|
||||
(IDLE_TIMEOUT * adc_dev->channels);
|
||||
/* Wait for Fifo threshold interrupt */
|
||||
while (1) {
|
||||
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||
if (fifo1count)
|
||||
break;
|
||||
|
||||
if (time_after(jiffies, timeout)) {
|
||||
am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
map_val = chan->channel + TOTAL_CHANNELS;
|
||||
|
||||
/*
|
||||
* When the sub-system is first enabled,
|
||||
* the sequencer will always start with the
|
||||
* lowest step (1) and continue until step (16).
|
||||
* For ex: If we have enabled 4 ADC channels and
|
||||
* currently use only 1 out of them, the
|
||||
* sequencer still configures all the 4 steps,
|
||||
* leading to 3 unwanted data.
|
||||
* Hence we need to flush out this data.
|
||||
* We check the complete FIFO. We programmed just one entry but in case
|
||||
* something went wrong we left empty handed (-EAGAIN previously) and
|
||||
* then the value apeared somehow in the FIFO we would have two entries.
|
||||
* Therefore we read every item and keep only the latest version of the
|
||||
* requested channel.
|
||||
*/
|
||||
|
||||
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
|
||||
for (i = 0; i < fifo1count; i++) {
|
||||
read = tiadc_readl(adc_dev, REG_FIFO1);
|
||||
stepid = read & FIFOREAD_CHNLID_MASK;
|
||||
|
@ -367,6 +395,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
|
|||
*val = (u16) read;
|
||||
}
|
||||
}
|
||||
am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
|
||||
|
||||
if (found == false)
|
||||
return -EBUSY;
|
||||
|
@ -494,7 +523,8 @@ static int tiadc_resume(struct device *dev)
|
|||
tiadc_writel(adc_dev, REG_CTRL, restore);
|
||||
|
||||
tiadc_step_config(indio_dev);
|
||||
|
||||
am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
|
||||
adc_dev->buffer_en_ch_steps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ config INPUT_MAX8997_HAPTIC
|
|||
|
||||
config INPUT_MC13783_PWRBUTTON
|
||||
tristate "MC13783 ON buttons"
|
||||
depends on MFD_MC13783
|
||||
depends on MFD_MC13XXX
|
||||
help
|
||||
Support the ON buttons of MC13783 PMIC as an input device
|
||||
reporting power button status.
|
||||
|
|
|
@ -717,7 +717,7 @@ config TOUCHSCREEN_USB_COMPOSITE
|
|||
|
||||
config TOUCHSCREEN_MC13783
|
||||
tristate "Freescale MC13783 touchscreen input driver"
|
||||
depends on MFD_MC13783
|
||||
depends on MFD_MC13XXX
|
||||
help
|
||||
Say Y here if you have an Freescale MC13783 PMIC on your
|
||||
board and want to use its touchscreen
|
||||
|
|
|
@ -198,7 +198,7 @@ static void titsc_step_config(struct titsc *ts_dev)
|
|||
/* The steps1 … end and bit 0 for TS_Charge */
|
||||
stepenable = (1 << (end_step + 2)) - 1;
|
||||
ts_dev->step_mask = stepenable;
|
||||
am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
|
||||
am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
|
||||
}
|
||||
|
||||
static void titsc_read_coordinates(struct titsc *ts_dev,
|
||||
|
@ -322,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
|
|||
|
||||
if (irqclr) {
|
||||
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
|
||||
am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
|
||||
am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
|
|
|
@ -148,7 +148,7 @@ static struct resource onkey_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell onkey_devs[] = {
|
||||
static const struct mfd_cell onkey_devs[] = {
|
||||
{
|
||||
.name = "88pm80x-onkey",
|
||||
.num_resources = 1,
|
||||
|
@ -157,7 +157,7 @@ static struct mfd_cell onkey_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell regulator_devs[] = {
|
||||
static const struct mfd_cell regulator_devs[] = {
|
||||
{
|
||||
.name = "88pm80x-regulator",
|
||||
.id = -1,
|
||||
|
|
|
@ -77,7 +77,7 @@ static struct resource codec_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell codec_devs[] = {
|
||||
static const struct mfd_cell codec_devs[] = {
|
||||
{
|
||||
.name = "88pm80x-codec",
|
||||
.num_resources = ARRAY_SIZE(codec_resources),
|
||||
|
|
|
@ -80,7 +80,7 @@ config MFD_CROS_EC_I2C
|
|||
|
||||
config MFD_CROS_EC_SPI
|
||||
tristate "ChromeOS Embedded Controller (SPI)"
|
||||
depends on MFD_CROS_EC && SPI
|
||||
depends on MFD_CROS_EC && SPI && OF
|
||||
|
||||
---help---
|
||||
If you say Y here, you get support for talking to the ChromeOS EC
|
||||
|
@ -163,14 +163,10 @@ config MFD_DA9063
|
|||
Additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
config MFD_MC13783
|
||||
tristate
|
||||
|
||||
config MFD_MC13XXX
|
||||
tristate
|
||||
depends on (SPI_MASTER || I2C)
|
||||
select MFD_CORE
|
||||
select MFD_MC13783
|
||||
help
|
||||
Enable support for the Freescale MC13783 and MC13892 PMICs.
|
||||
This driver provides common support for accessing the device,
|
||||
|
@ -321,6 +317,19 @@ config MFD_88PM860X
|
|||
select individual components like voltage regulators, RTC and
|
||||
battery-charger under the corresponding menus.
|
||||
|
||||
config MFD_MAX14577
|
||||
bool "Maxim Semiconductor MAX14577 MUIC + Charger Support"
|
||||
depends on I2C=y
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select IRQ_DOMAIN
|
||||
help
|
||||
Say yes here to support for Maxim Semiconductor MAX14577.
|
||||
This is a Micro-USB IC with Charger 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_MAX77686
|
||||
bool "Maxim Semiconductor MAX77686 PMIC Support"
|
||||
depends on I2C=y
|
||||
|
@ -725,6 +734,17 @@ config MFD_DM355EVM_MSP
|
|||
boards. MSP430 firmware manages resets and power sequencing,
|
||||
inputs from buttons and the IR remote, LEDs, an RTC, and more.
|
||||
|
||||
config MFD_LP3943
|
||||
tristate "TI/National Semiconductor LP3943 MFD Driver"
|
||||
depends on I2C
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Support for the TI/National Semiconductor LP3943.
|
||||
This driver consists of GPIO and PWM drivers.
|
||||
With these functionalities, it can be used for LED string control or
|
||||
general usage such like a GPIO controller and a PWM controller.
|
||||
|
||||
config MFD_LP8788
|
||||
bool "TI LP8788 Power Management Unit Driver"
|
||||
depends on I2C=y
|
||||
|
|
|
@ -102,6 +102,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
|
|||
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
|
||||
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
|
||||
|
||||
obj-$(CONFIG_MFD_LP3943) += lp3943.o
|
||||
obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
|
||||
|
||||
da9055-objs := da9055-core.o da9055-i2c.o
|
||||
|
@ -110,6 +111,7 @@ obj-$(CONFIG_MFD_DA9055) += da9055.o
|
|||
da9063-objs := da9063-core.o da9063-irq.o da9063-i2c.o
|
||||
obj-$(CONFIG_MFD_DA9063) += da9063.o
|
||||
|
||||
obj-$(CONFIG_MFD_MAX14577) += max14577.o
|
||||
obj-$(CONFIG_MFD_MAX77686) += max77686.o max77686-irq.o
|
||||
obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o
|
||||
obj-$(CONFIG_MFD_MAX8907) += max8907.o
|
||||
|
|
|
@ -491,7 +491,7 @@ static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
|
|||
if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
|
||||
line += 1;
|
||||
|
||||
handle_nested_irq(ab8500->irq_base + line);
|
||||
handle_nested_irq(irq_create_mapping(ab8500->domain, line));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1017,7 +1017,7 @@ static struct resource ab8500_temp_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab8500_bm_devs[] = {
|
||||
static const struct mfd_cell ab8500_bm_devs[] = {
|
||||
{
|
||||
.name = "ab8500-charger",
|
||||
.of_compatible = "stericsson,ab8500-charger",
|
||||
|
@ -1052,7 +1052,7 @@ static struct mfd_cell ab8500_bm_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab8500_devs[] = {
|
||||
static const struct mfd_cell ab8500_devs[] = {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
{
|
||||
.name = "ab8500-debug",
|
||||
|
@ -1143,7 +1143,7 @@ static struct mfd_cell ab8500_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab9540_devs[] = {
|
||||
static const struct mfd_cell ab9540_devs[] = {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
{
|
||||
.name = "ab8500-debug",
|
||||
|
@ -1214,7 +1214,7 @@ static struct mfd_cell ab9540_devs[] = {
|
|||
};
|
||||
|
||||
/* Device list for ab8505 */
|
||||
static struct mfd_cell ab8505_devs[] = {
|
||||
static const struct mfd_cell ab8505_devs[] = {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
{
|
||||
.name = "ab8500-debug",
|
||||
|
@ -1275,7 +1275,7 @@ static struct mfd_cell ab8505_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab8540_devs[] = {
|
||||
static const struct mfd_cell ab8540_devs[] = {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
{
|
||||
.name = "ab8500-debug",
|
||||
|
@ -1339,7 +1339,7 @@ static struct mfd_cell ab8540_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab8540_cut1_devs[] = {
|
||||
static const struct mfd_cell ab8540_cut1_devs[] = {
|
||||
{
|
||||
.name = "ab8500-rtc",
|
||||
.of_compatible = "stericsson,ab8500-rtc",
|
||||
|
@ -1348,7 +1348,7 @@ static struct mfd_cell ab8540_cut1_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ab8540_cut2_devs[] = {
|
||||
static const struct mfd_cell ab8540_cut2_devs[] = {
|
||||
{
|
||||
.name = "ab8540-rtc",
|
||||
.of_compatible = "stericsson,ab8540-rtc",
|
||||
|
|
|
@ -1600,7 +1600,6 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
|
|||
|
||||
for (line = 0; line < num_interrupt_lines; line++) {
|
||||
struct irq_desc *desc = irq_to_desc(line + irq_first);
|
||||
struct irqaction *action = desc->action;
|
||||
|
||||
seq_printf(s, "%3i: %6i %4i", line,
|
||||
num_interrupts[line],
|
||||
|
@ -1608,7 +1607,9 @@ static int ab8500_interrupts_print(struct seq_file *s, void *p)
|
|||
|
||||
if (desc && desc->name)
|
||||
seq_printf(s, "-%-8s", desc->name);
|
||||
if (action) {
|
||||
if (desc && desc->action) {
|
||||
struct irqaction *action = desc->action;
|
||||
|
||||
seq_printf(s, " %s", action->name);
|
||||
while ((action = action->next) != NULL)
|
||||
seq_printf(s, ", %s", action->name);
|
||||
|
|
|
@ -565,7 +565,7 @@ static inline int arizona_of_get_core_pdata(struct arizona *arizona)
|
|||
}
|
||||
#endif
|
||||
|
||||
static struct mfd_cell early_devs[] = {
|
||||
static const struct mfd_cell early_devs[] = {
|
||||
{ .name = "arizona-ldo1" },
|
||||
};
|
||||
|
||||
|
@ -577,7 +577,7 @@ static const char *wm5102_supplies[] = {
|
|||
"SPKVDDR",
|
||||
};
|
||||
|
||||
static struct mfd_cell wm5102_devs[] = {
|
||||
static const struct mfd_cell wm5102_devs[] = {
|
||||
{ .name = "arizona-micsupp" },
|
||||
{ .name = "arizona-extcon" },
|
||||
{ .name = "arizona-gpio" },
|
||||
|
@ -590,7 +590,7 @@ static struct mfd_cell wm5102_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm5110_devs[] = {
|
||||
static const struct mfd_cell wm5110_devs[] = {
|
||||
{ .name = "arizona-micsupp" },
|
||||
{ .name = "arizona-extcon" },
|
||||
{ .name = "arizona-gpio" },
|
||||
|
@ -609,7 +609,7 @@ static const char *wm8997_supplies[] = {
|
|||
"SPKVDD",
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8997_devs[] = {
|
||||
static const struct mfd_cell wm8997_devs[] = {
|
||||
{ .name = "arizona-micsupp" },
|
||||
{ .name = "arizona-extcon" },
|
||||
{ .name = "arizona-gpio" },
|
||||
|
|
|
@ -54,7 +54,7 @@ static const struct resource as3722_adc_resource[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell as3722_devs[] = {
|
||||
static const struct mfd_cell as3722_devs[] = {
|
||||
{
|
||||
.name = "as3722-pinctrl",
|
||||
},
|
||||
|
@ -74,6 +74,9 @@ static struct mfd_cell as3722_devs[] = {
|
|||
{
|
||||
.name = "as3722-power-off",
|
||||
},
|
||||
{
|
||||
.name = "as3722-wdt",
|
||||
},
|
||||
};
|
||||
|
||||
static const struct regmap_irq as3722_irqs[] = {
|
||||
|
|
|
@ -695,7 +695,7 @@ static int ds1wm_disable(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct mfd_cell asic3_cell_ds1wm = {
|
||||
static const struct mfd_cell asic3_cell_ds1wm = {
|
||||
.name = "ds1wm",
|
||||
.enable = ds1wm_enable,
|
||||
.disable = ds1wm_disable,
|
||||
|
@ -797,7 +797,7 @@ static int asic3_mmc_disable(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct mfd_cell asic3_cell_mmc = {
|
||||
static const struct mfd_cell asic3_cell_mmc = {
|
||||
.name = "tmio-mmc",
|
||||
.enable = asic3_mmc_enable,
|
||||
.disable = asic3_mmc_disable,
|
||||
|
|
|
@ -84,7 +84,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct mfd_cell cros_devs[] = {
|
||||
static const struct mfd_cell cros_devs[] = {
|
||||
{
|
||||
.name = "cros-ec-keyb",
|
||||
.id = 1,
|
||||
|
|
|
@ -120,7 +120,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int cros_ec_probe_i2c(struct i2c_client *client,
|
||||
static int cros_ec_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -150,7 +150,7 @@ static int cros_ec_probe_i2c(struct i2c_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_remove_i2c(struct i2c_client *client)
|
||||
static int cros_ec_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cros_ec_device *ec_dev = i2c_get_clientdata(client);
|
||||
|
||||
|
@ -190,8 +190,8 @@ static struct i2c_driver cros_ec_driver = {
|
|||
.owner = THIS_MODULE,
|
||||
.pm = &cros_ec_i2c_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_probe_i2c,
|
||||
.remove = cros_ec_remove_i2c,
|
||||
.probe = cros_ec_i2c_probe,
|
||||
.remove = cros_ec_i2c_remove,
|
||||
.id_table = cros_ec_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
@ -50,10 +51,11 @@
|
|||
/*
|
||||
* Time between raising the SPI chip select (for the end of a
|
||||
* transaction) and dropping it again (for the next transaction).
|
||||
* If we go too fast, the EC will miss the transaction. It seems
|
||||
* that 50us is enough with the 16MHz STM32 EC.
|
||||
* If we go too fast, the EC will miss the transaction. We know that we
|
||||
* need at least 70 us with the 16 MHz STM32 EC, so go with 200 us to be
|
||||
* safe.
|
||||
*/
|
||||
#define EC_SPI_RECOVERY_TIME_NS (50 * 1000)
|
||||
#define EC_SPI_RECOVERY_TIME_NS (200 * 1000)
|
||||
|
||||
/**
|
||||
* struct cros_ec_spi - information about a SPI-connected EC
|
||||
|
@ -61,10 +63,13 @@
|
|||
* @spi: SPI device we are connected to
|
||||
* @last_transfer_ns: time that we last finished a transfer, or 0 if there
|
||||
* if no record
|
||||
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
|
||||
* is sent when we want to turn off CS at the end of a transaction.
|
||||
*/
|
||||
struct cros_ec_spi {
|
||||
struct spi_device *spi;
|
||||
s64 last_transfer_ns;
|
||||
unsigned int end_of_msg_delay;
|
||||
};
|
||||
|
||||
static void debug_packet(struct device *dev, const char *name, u8 *ptr,
|
||||
|
@ -75,7 +80,9 @@ static void debug_packet(struct device *dev, const char *name, u8 *ptr,
|
|||
|
||||
dev_dbg(dev, "%s: ", name);
|
||||
for (i = 0; i < len; i++)
|
||||
dev_cont(dev, " %02x", ptr[i]);
|
||||
pr_cont(" %02x", ptr[i]);
|
||||
|
||||
pr_cont("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -105,7 +112,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
|
|||
/* Receive data until we see the header byte */
|
||||
deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
|
||||
do {
|
||||
memset(&trans, '\0', sizeof(trans));
|
||||
memset(&trans, 0, sizeof(trans));
|
||||
trans.cs_change = 1;
|
||||
trans.rx_buf = ptr = ec_dev->din;
|
||||
trans.len = EC_MSG_PREAMBLE_COUNT;
|
||||
|
@ -157,7 +164,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
|
|||
dev_dbg(ec_dev->dev, "loop, todo=%d, need_len=%d, ptr=%zd\n",
|
||||
todo, need_len, ptr - ec_dev->din);
|
||||
|
||||
memset(&trans, '\0', sizeof(trans));
|
||||
memset(&trans, 0, sizeof(trans));
|
||||
trans.cs_change = 1;
|
||||
trans.rx_buf = ptr;
|
||||
trans.len = todo;
|
||||
|
@ -217,7 +224,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
|
|||
|
||||
/* Transmit phase - send our message */
|
||||
debug_packet(ec_dev->dev, "out", ec_dev->dout, len);
|
||||
memset(&trans, '\0', sizeof(trans));
|
||||
memset(&trans, 0, sizeof(trans));
|
||||
trans.tx_buf = ec_dev->dout;
|
||||
trans.len = len;
|
||||
trans.cs_change = 1;
|
||||
|
@ -235,6 +242,17 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
|
|||
|
||||
/* turn off CS */
|
||||
spi_message_init(&msg);
|
||||
|
||||
if (ec_spi->end_of_msg_delay) {
|
||||
/*
|
||||
* Add delay for last transaction, to ensure the rising edge
|
||||
* doesn't come too soon after the end of the data.
|
||||
*/
|
||||
memset(&trans, 0, sizeof(trans));
|
||||
trans.delay_usecs = ec_spi->end_of_msg_delay;
|
||||
spi_message_add_tail(&trans, &msg);
|
||||
}
|
||||
|
||||
final_ret = spi_sync(ec_spi->spi, &msg);
|
||||
ktime_get_ts(&ts);
|
||||
ec_spi->last_transfer_ns = timespec_to_ns(&ts);
|
||||
|
@ -281,7 +299,18 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_probe_spi(struct spi_device *spi)
|
||||
static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_u32(np, "google,cros-ec-spi-msg-delay", &val);
|
||||
if (!ret)
|
||||
ec_spi->end_of_msg_delay = val;
|
||||
}
|
||||
|
||||
static int cros_ec_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct cros_ec_device *ec_dev;
|
||||
|
@ -302,6 +331,9 @@ static int cros_ec_probe_spi(struct spi_device *spi)
|
|||
if (!ec_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Check for any DT properties */
|
||||
cros_ec_spi_dt_probe(ec_spi, dev);
|
||||
|
||||
spi_set_drvdata(spi, ec_dev);
|
||||
ec_dev->name = "SPI";
|
||||
ec_dev->dev = dev;
|
||||
|
@ -323,7 +355,7 @@ static int cros_ec_probe_spi(struct spi_device *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_remove_spi(struct spi_device *spi)
|
||||
static int cros_ec_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct cros_ec_device *ec_dev;
|
||||
|
||||
|
@ -364,12 +396,12 @@ static struct spi_driver cros_ec_driver_spi = {
|
|||
.owner = THIS_MODULE,
|
||||
.pm = &cros_ec_spi_pm_ops,
|
||||
},
|
||||
.probe = cros_ec_probe_spi,
|
||||
.remove = cros_ec_remove_spi,
|
||||
.probe = cros_ec_spi_probe,
|
||||
.remove = cros_ec_spi_remove,
|
||||
.id_table = cros_ec_spi_id,
|
||||
};
|
||||
|
||||
module_spi_driver(cros_ec_driver_spi);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)");
|
||||
|
|
|
@ -172,7 +172,7 @@ static void cs5535_mfd_remove(struct pci_dev *pdev)
|
|||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(cs5535_mfd_pci_tbl) = {
|
||||
static const struct pci_device_id cs5535_mfd_pci_tbl[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
|
||||
{ 0, }
|
||||
|
|
|
@ -427,7 +427,7 @@ int da9052_adc_read_temp(struct da9052 *da9052)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(da9052_adc_read_temp);
|
||||
|
||||
static struct mfd_cell da9052_subdev_info[] = {
|
||||
static const struct mfd_cell da9052_subdev_info[] = {
|
||||
{
|
||||
.name = "da9052-regulator",
|
||||
.id = 1,
|
||||
|
|
|
@ -294,7 +294,7 @@ static struct resource da9055_ld05_6_resource = {
|
|||
.flags = IORESOURCE_IRQ,
|
||||
};
|
||||
|
||||
static struct mfd_cell da9055_devs[] = {
|
||||
static const struct mfd_cell da9055_devs[] = {
|
||||
{
|
||||
.of_compatible = "dialog,da9055-gpio",
|
||||
.name = "da9055-gpio",
|
||||
|
|
|
@ -75,7 +75,7 @@ static struct resource da9063_hwmon_resources[] = {
|
|||
};
|
||||
|
||||
|
||||
static struct mfd_cell da9063_devs[] = {
|
||||
static const struct mfd_cell da9063_devs[] = {
|
||||
{
|
||||
.name = DA9063_DRVNAME_REGULATORS,
|
||||
.num_resources = ARRAY_SIZE(da9063_regulators_resources),
|
||||
|
|
|
@ -3070,7 +3070,7 @@ static struct db8500_thsens_platform_data db8500_thsens_data = {
|
|||
.num_trips = 4,
|
||||
};
|
||||
|
||||
static struct mfd_cell common_prcmu_devs[] = {
|
||||
static const struct mfd_cell common_prcmu_devs[] = {
|
||||
{
|
||||
.name = "ux500_wdt",
|
||||
.platform_data = &db8500_wdt_pdata,
|
||||
|
@ -3079,7 +3079,7 @@ static struct mfd_cell common_prcmu_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell db8500_prcmu_devs[] = {
|
||||
static const struct mfd_cell db8500_prcmu_devs[] = {
|
||||
{
|
||||
.name = "db8500-prcmu-regulators",
|
||||
.of_compatible = "stericsson,db8500-prcmu-regulator",
|
||||
|
|
|
@ -114,7 +114,7 @@ static struct resource ds1wm_resources[] __initdata = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell ds1wm_cell __initdata = {
|
||||
static const struct mfd_cell ds1wm_cell __initconst = {
|
||||
.name = "ds1wm",
|
||||
.enable = ds1wm_enable,
|
||||
.disable = ds1wm_disable,
|
||||
|
|
|
@ -178,7 +178,7 @@ static struct mfd_cell msic_devs[] = {
|
|||
* These devices appear only after the MSIC driver itself is initialized so
|
||||
* we can guarantee that the SCU IPC interface is ready.
|
||||
*/
|
||||
static struct mfd_cell msic_other_devs[] = {
|
||||
static const struct mfd_cell msic_other_devs[] = {
|
||||
/* Audio codec in the MSIC */
|
||||
{
|
||||
.id = -1,
|
||||
|
|
|
@ -265,7 +265,7 @@ static void cmodio_pci_remove(struct pci_dev *dev)
|
|||
#define PCI_VENDOR_ID_JANZ 0x13c3
|
||||
|
||||
/* The list of devices that this module will support */
|
||||
static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = {
|
||||
static const struct pci_device_id cmodio_pci_ids[] = {
|
||||
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 },
|
||||
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 },
|
||||
{ 0, }
|
||||
|
|
|
@ -181,7 +181,7 @@ static struct resource jz4740_battery_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell jz4740_adc_cells[] = {
|
||||
static const struct mfd_cell jz4740_adc_cells[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.name = "jz4740-hwmon",
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* TI/National Semiconductor LP3943 MFD Core Driver
|
||||
*
|
||||
* Copyright 2013 Texas Instruments
|
||||
*
|
||||
* Author: Milo Kim <milo.kim@ti.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.
|
||||
*
|
||||
* Driver structure:
|
||||
* LP3943 is an integrated device capable of driving 16 output channels.
|
||||
* It can be used for a GPIO expander and PWM generators.
|
||||
*
|
||||
* LED control General usage for a device
|
||||
* ___________ ____________________________
|
||||
*
|
||||
* LP3943 MFD ---- GPIO expander leds-gpio eg) HW enable pin
|
||||
* |
|
||||
* --- PWM generator leds-pwm eg) PWM input
|
||||
*
|
||||
* Internal two PWM channels are used for LED dimming effect.
|
||||
* And each output pin can be used as a GPIO as well.
|
||||
* The LED functionality can work with GPIOs or PWMs.
|
||||
* LEDs can be controlled with legacy leds-gpio(static brightness) or
|
||||
* leds-pwm drivers(dynamic brightness control).
|
||||
* Alternatively, it can be used for generic GPIO and PWM controller.
|
||||
* For example, a GPIO is HW enable pin of a device.
|
||||
* A PWM is input pin of a backlight device.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/lp3943.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define LP3943_MAX_REGISTERS 0x09
|
||||
|
||||
/* Register configuration for pin MUX */
|
||||
static const struct lp3943_reg_cfg lp3943_mux_cfg[] = {
|
||||
/* address, mask, shift */
|
||||
{ LP3943_REG_MUX0, 0x03, 0 },
|
||||
{ LP3943_REG_MUX0, 0x0C, 2 },
|
||||
{ LP3943_REG_MUX0, 0x30, 4 },
|
||||
{ LP3943_REG_MUX0, 0xC0, 6 },
|
||||
{ LP3943_REG_MUX1, 0x03, 0 },
|
||||
{ LP3943_REG_MUX1, 0x0C, 2 },
|
||||
{ LP3943_REG_MUX1, 0x30, 4 },
|
||||
{ LP3943_REG_MUX1, 0xC0, 6 },
|
||||
{ LP3943_REG_MUX2, 0x03, 0 },
|
||||
{ LP3943_REG_MUX2, 0x0C, 2 },
|
||||
{ LP3943_REG_MUX2, 0x30, 4 },
|
||||
{ LP3943_REG_MUX2, 0xC0, 6 },
|
||||
{ LP3943_REG_MUX3, 0x03, 0 },
|
||||
{ LP3943_REG_MUX3, 0x0C, 2 },
|
||||
{ LP3943_REG_MUX3, 0x30, 4 },
|
||||
{ LP3943_REG_MUX3, 0xC0, 6 },
|
||||
};
|
||||
|
||||
static struct mfd_cell lp3943_devs[] = {
|
||||
{
|
||||
.name = "lp3943-pwm",
|
||||
.of_compatible = "ti,lp3943-pwm",
|
||||
},
|
||||
{
|
||||
.name = "lp3943-gpio",
|
||||
.of_compatible = "ti,lp3943-gpio",
|
||||
},
|
||||
};
|
||||
|
||||
int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(lp3943->regmap, reg, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*read = (u8)val;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lp3943_read_byte);
|
||||
|
||||
int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data)
|
||||
{
|
||||
return regmap_write(lp3943->regmap, reg, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lp3943_write_byte);
|
||||
|
||||
int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data)
|
||||
{
|
||||
return regmap_update_bits(lp3943->regmap, reg, mask, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lp3943_update_bits);
|
||||
|
||||
static const struct regmap_config lp3943_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = LP3943_MAX_REGISTERS,
|
||||
};
|
||||
|
||||
static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp3943 *lp3943;
|
||||
struct device *dev = &cl->dev;
|
||||
|
||||
lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL);
|
||||
if (!lp3943)
|
||||
return -ENOMEM;
|
||||
|
||||
lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config);
|
||||
if (IS_ERR(lp3943->regmap))
|
||||
return PTR_ERR(lp3943->regmap);
|
||||
|
||||
lp3943->pdata = dev_get_platdata(dev);
|
||||
lp3943->dev = dev;
|
||||
lp3943->mux_cfg = lp3943_mux_cfg;
|
||||
i2c_set_clientdata(cl, lp3943);
|
||||
|
||||
return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs),
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int lp3943_remove(struct i2c_client *cl)
|
||||
{
|
||||
struct lp3943 *lp3943 = i2c_get_clientdata(cl);
|
||||
|
||||
mfd_remove_devices(lp3943->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lp3943_ids[] = {
|
||||
{ "lp3943", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lp3943_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id lp3943_of_match[] = {
|
||||
{ .compatible = "ti,lp3943", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lp3943_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver lp3943_driver = {
|
||||
.probe = lp3943_probe,
|
||||
.remove = lp3943_remove,
|
||||
.driver = {
|
||||
.name = "lp3943",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(lp3943_of_match),
|
||||
},
|
||||
.id_table = lp3943_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(lp3943_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LP3943 MFD Core Driver");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -71,7 +71,7 @@ static struct resource rtc_irqs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell lp8788_devs[] = {
|
||||
static const struct mfd_cell lp8788_devs[] = {
|
||||
/* 4 bucks */
|
||||
MFD_DEV_WITH_ID(BUCK, 1),
|
||||
MFD_DEV_WITH_ID(BUCK, 2),
|
||||
|
|
|
@ -517,7 +517,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
|
|||
* pci_driver, because the I/O Controller Hub has also other
|
||||
* functions that probably will be registered by other drivers.
|
||||
*/
|
||||
static DEFINE_PCI_DEVICE_TABLE(lpc_ich_ids) = {
|
||||
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},
|
||||
|
|
|
@ -76,7 +76,7 @@ static struct mfd_cell wdt_sch_cell = {
|
|||
.ignore_resource_conflicts = true,
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(lpc_sch_ids) = {
|
||||
static const struct pci_device_id lpc_sch_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CENTERTON_ILB) },
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* max14577.c - mfd core driver for the Maxim 14577
|
||||
*
|
||||
* Copyright (C) 2013 Samsung Electrnoics
|
||||
* Chanwoo Choi <cw00.choi@samsung.com>
|
||||
* Krzysztof Kozlowski <k.kozlowski@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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This driver is based on max8997.c
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/max14577.h>
|
||||
#include <linux/mfd/max14577-private.h>
|
||||
|
||||
static struct mfd_cell max14577_devs[] = {
|
||||
{ .name = "max14577-muic", },
|
||||
{
|
||||
.name = "max14577-regulator",
|
||||
.of_compatible = "maxim,max14577-regulator",
|
||||
},
|
||||
{ .name = "max14577-charger", },
|
||||
};
|
||||
|
||||
static bool max14577_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct regmap_config max14577_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_reg = max14577_volatile_reg,
|
||||
.max_register = MAX14577_REG_END,
|
||||
};
|
||||
|
||||
static const struct regmap_irq max14577_irqs[] = {
|
||||
/* INT1 interrupts */
|
||||
{ .reg_offset = 0, .mask = INT1_ADC_MASK, },
|
||||
{ .reg_offset = 0, .mask = INT1_ADCLOW_MASK, },
|
||||
{ .reg_offset = 0, .mask = INT1_ADCERR_MASK, },
|
||||
/* INT2 interrupts */
|
||||
{ .reg_offset = 1, .mask = INT2_CHGTYP_MASK, },
|
||||
{ .reg_offset = 1, .mask = INT2_CHGDETRUN_MASK, },
|
||||
{ .reg_offset = 1, .mask = INT2_DCDTMR_MASK, },
|
||||
{ .reg_offset = 1, .mask = INT2_DBCHG_MASK, },
|
||||
{ .reg_offset = 1, .mask = INT2_VBVOLT_MASK, },
|
||||
/* INT3 interrupts */
|
||||
{ .reg_offset = 2, .mask = INT3_EOC_MASK, },
|
||||
{ .reg_offset = 2, .mask = INT3_CGMBC_MASK, },
|
||||
{ .reg_offset = 2, .mask = INT3_OVP_MASK, },
|
||||
{ .reg_offset = 2, .mask = INT3_MBCCHGERR_MASK, },
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip max14577_irq_chip = {
|
||||
.name = "max14577",
|
||||
.status_base = MAX14577_REG_INT1,
|
||||
.mask_base = MAX14577_REG_INTMASK1,
|
||||
.mask_invert = 1,
|
||||
.num_regs = 3,
|
||||
.irqs = max14577_irqs,
|
||||
.num_irqs = ARRAY_SIZE(max14577_irqs),
|
||||
};
|
||||
|
||||
static int max14577_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max14577 *max14577;
|
||||
struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
||||
struct device_node *np = i2c->dev.of_node;
|
||||
u8 reg_data;
|
||||
int ret = 0;
|
||||
|
||||
if (np) {
|
||||
pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
i2c->dev.platform_data = pdata;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&i2c->dev, "No platform data found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL);
|
||||
if (!max14577)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, max14577);
|
||||
max14577->dev = &i2c->dev;
|
||||
max14577->i2c = i2c;
|
||||
max14577->irq = i2c->irq;
|
||||
|
||||
max14577->regmap = devm_regmap_init_i2c(i2c, &max14577_regmap_config);
|
||||
if (IS_ERR(max14577->regmap)) {
|
||||
ret = PTR_ERR(max14577->regmap);
|
||||
dev_err(max14577->dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID,
|
||||
®_data);
|
||||
if (ret) {
|
||||
dev_err(max14577->dev, "Device not found on this channel: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
max14577->vendor_id = ((reg_data & DEVID_VENDORID_MASK) >>
|
||||
DEVID_VENDORID_SHIFT);
|
||||
max14577->device_id = ((reg_data & DEVID_DEVICEID_MASK) >>
|
||||
DEVID_DEVICEID_SHIFT);
|
||||
dev_info(max14577->dev, "Device ID: 0x%x, vendor: 0x%x\n",
|
||||
max14577->device_id, max14577->vendor_id);
|
||||
|
||||
ret = regmap_add_irq_chip(max14577->regmap, max14577->irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 0,
|
||||
&max14577_irq_chip,
|
||||
&max14577->irq_data);
|
||||
if (ret != 0) {
|
||||
dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
|
||||
max14577->irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mfd_add_devices(max14577->dev, -1, max14577_devs,
|
||||
ARRAY_SIZE(max14577_devs), NULL, 0,
|
||||
regmap_irq_get_domain(max14577->irq_data));
|
||||
if (ret < 0)
|
||||
goto err_mfd;
|
||||
|
||||
device_init_wakeup(max14577->dev, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
err_mfd:
|
||||
regmap_del_irq_chip(max14577->irq, max14577->irq_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max14577_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct max14577 *max14577 = i2c_get_clientdata(i2c);
|
||||
|
||||
mfd_remove_devices(max14577->dev);
|
||||
regmap_del_irq_chip(max14577->irq, max14577->irq_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max14577_i2c_id[] = {
|
||||
{ "max14577", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
|
||||
|
||||
static int max14577_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct max14577 *max14577 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
enable_irq_wake(max14577->irq);
|
||||
/*
|
||||
* MUIC IRQ must be disabled during suspend if this is
|
||||
* a wake up source because it will be handled before
|
||||
* resuming I2C.
|
||||
*
|
||||
* When device is woken up from suspend (e.g. by ADC change),
|
||||
* an interrupt occurs before resuming I2C bus controller.
|
||||
* Interrupt handler tries to read registers but this read
|
||||
* will fail because I2C is still suspended.
|
||||
*/
|
||||
disable_irq(max14577->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max14577_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct max14577 *max14577 = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
disable_irq_wake(max14577->irq);
|
||||
enable_irq(max14577->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id max14577_dt_match[] = {
|
||||
{ .compatible = "maxim,max14577", },
|
||||
{},
|
||||
};
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume);
|
||||
|
||||
static struct i2c_driver max14577_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max14577",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &max14577_pm,
|
||||
.of_match_table = max14577_dt_match,
|
||||
},
|
||||
.probe = max14577_i2c_probe,
|
||||
.remove = max14577_i2c_remove,
|
||||
.id_table = max14577_i2c_id,
|
||||
};
|
||||
|
||||
static int __init max14577_i2c_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max14577_i2c_driver);
|
||||
}
|
||||
subsys_initcall(max14577_i2c_init);
|
||||
|
||||
static void __exit max14577_i2c_exit(void)
|
||||
{
|
||||
i2c_del_driver(&max14577_i2c_driver);
|
||||
}
|
||||
module_exit(max14577_i2c_exit);
|
||||
|
||||
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>, Krzysztof Kozlowski <k.kozlowski@samsung.com>");
|
||||
MODULE_DESCRIPTION("MAXIM 14577 multi-function core driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#define I2C_ADDR_RTC (0x0C >> 1)
|
||||
|
||||
static struct mfd_cell max77686_devs[] = {
|
||||
static const struct mfd_cell max77686_devs[] = {
|
||||
{ .name = "max77686-pmic", },
|
||||
{ .name = "max77686-rtc", },
|
||||
{ .name = "max77686-clk", },
|
||||
|
@ -104,7 +104,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
|
|||
max77686->irq_gpio = pdata->irq_gpio;
|
||||
max77686->irq = i2c->irq;
|
||||
|
||||
max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
|
||||
max77686->regmap = devm_regmap_init_i2c(i2c, &max77686_regmap_config);
|
||||
if (IS_ERR(max77686->regmap)) {
|
||||
ret = PTR_ERR(max77686->regmap);
|
||||
dev_err(max77686->dev, "Failed to allocate register map: %d\n",
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#define I2C_ADDR_MUIC (0x4A >> 1)
|
||||
#define I2C_ADDR_HAPTIC (0x90 >> 1)
|
||||
|
||||
static struct mfd_cell max77693_devs[] = {
|
||||
static const struct mfd_cell max77693_devs[] = {
|
||||
{ .name = "max77693-pmic", },
|
||||
{ .name = "max77693-charger", },
|
||||
{ .name = "max77693-flash", },
|
||||
|
@ -107,6 +107,12 @@ static const struct regmap_config max77693_regmap_config = {
|
|||
.max_register = MAX77693_PMIC_REG_END,
|
||||
};
|
||||
|
||||
static const struct regmap_config max77693_regmap_muic_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX77693_MUIC_REG_END,
|
||||
};
|
||||
|
||||
static int max77693_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -153,7 +159,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
|
|||
* before call max77693-muic probe() function.
|
||||
*/
|
||||
max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic,
|
||||
&max77693_regmap_config);
|
||||
&max77693_regmap_muic_config);
|
||||
if (IS_ERR(max77693->regmap_muic)) {
|
||||
ret = PTR_ERR(max77693->regmap_muic);
|
||||
dev_err(max77693->dev,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static struct mfd_cell max8907_cells[] = {
|
||||
static const struct mfd_cell max8907_cells[] = {
|
||||
{ .name = "max8907-regulator", },
|
||||
{ .name = "max8907-rtc", },
|
||||
};
|
||||
|
|
|
@ -45,7 +45,7 @@ static struct resource touch_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell touch_devs[] = {
|
||||
static const struct mfd_cell touch_devs[] = {
|
||||
{
|
||||
.name = "max8925-touch",
|
||||
.num_resources = 1,
|
||||
|
@ -63,7 +63,7 @@ static struct resource power_supply_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell power_devs[] = {
|
||||
static const struct mfd_cell power_devs[] = {
|
||||
{
|
||||
.name = "max8925-power",
|
||||
.num_resources = 1,
|
||||
|
@ -81,7 +81,7 @@ static struct resource rtc_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell rtc_devs[] = {
|
||||
static const struct mfd_cell rtc_devs[] = {
|
||||
{
|
||||
.name = "max8925-rtc",
|
||||
.num_resources = 1,
|
||||
|
@ -104,7 +104,7 @@ static struct resource onkey_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell onkey_devs[] = {
|
||||
static const struct mfd_cell onkey_devs[] = {
|
||||
{
|
||||
.name = "max8925-onkey",
|
||||
.num_resources = 2,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#define I2C_ADDR_RTC (0x0C >> 1)
|
||||
#define I2C_ADDR_HAPTIC (0x90 >> 1)
|
||||
|
||||
static struct mfd_cell max8997_devs[] = {
|
||||
static const struct mfd_cell max8997_devs[] = {
|
||||
{ .name = "max8997-pmic", },
|
||||
{ .name = "max8997-rtc", },
|
||||
{ .name = "max8997-battery", },
|
||||
|
@ -133,7 +133,6 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(max8997_update_reg);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* Only the common platform data elements for max8997 are parsed here from the
|
||||
* device tree. Other sub-modules of max8997 such as pmic, rtc and others have
|
||||
|
@ -164,24 +163,15 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
|
|||
|
||||
return pd;
|
||||
}
|
||||
#else
|
||||
static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
if (i2c->dev.of_node) {
|
||||
if (IS_ENABLED(CONFIG_OF) && i2c->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
|
||||
return (int)match->data;
|
||||
}
|
||||
#endif
|
||||
return (int)id->driver_data;
|
||||
}
|
||||
|
||||
|
@ -203,7 +193,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
|
|||
max8997->type = max8997_i2c_get_driver_data(i2c, id);
|
||||
max8997->irq = i2c->irq;
|
||||
|
||||
if (max8997->dev->of_node) {
|
||||
if (IS_ENABLED(CONFIG_OF) && max8997->dev->of_node) {
|
||||
pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
|
@ -228,18 +218,19 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
max8997_irq_init(max8997);
|
||||
|
||||
mfd_add_devices(max8997->dev, -1, max8997_devs,
|
||||
ret = mfd_add_devices(max8997->dev, -1, max8997_devs,
|
||||
ARRAY_SIZE(max8997_devs),
|
||||
NULL, 0, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(max8997->dev, "failed to add MFD devices %d\n", ret);
|
||||
goto err_mfd;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: enable others (flash, muic, rtc, battery, ...) and
|
||||
* check the return value
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
goto err_mfd;
|
||||
|
||||
/* MAX8997 has a power button input. */
|
||||
device_init_wakeup(max8997->dev, pdata->wakeup);
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
#define RTC_I2C_ADDR (0x0c >> 1)
|
||||
|
||||
static struct mfd_cell max8998_devs[] = {
|
||||
static const struct mfd_cell max8998_devs[] = {
|
||||
{
|
||||
.name = "max8998-pmic",
|
||||
}, {
|
||||
|
@ -47,7 +47,7 @@ static struct mfd_cell max8998_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell lp3974_devs[] = {
|
||||
static const struct mfd_cell lp3974_devs[] = {
|
||||
{
|
||||
.name = "lp3974-pmic",
|
||||
}, {
|
||||
|
|
|
@ -158,9 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (offset > MC13XXX_NUMREGS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_read(mc13xxx->regmap, offset, val);
|
||||
dev_vdbg(mc13xxx->dev, "[0x%02x] -> 0x%06x\n", offset, *val);
|
||||
|
||||
|
@ -172,7 +169,7 @@ int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
|
|||
{
|
||||
dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
|
||||
|
||||
if (offset > MC13XXX_NUMREGS || val > 0xffffff)
|
||||
if (val >= BIT(24))
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write(mc13xxx->regmap, offset, val);
|
||||
|
@ -639,42 +636,36 @@ static inline int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
|
|||
}
|
||||
#endif
|
||||
|
||||
int mc13xxx_common_init(struct mc13xxx *mc13xxx,
|
||||
struct mc13xxx_platform_data *pdata, int irq)
|
||||
int mc13xxx_common_init(struct device *dev)
|
||||
{
|
||||
struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
u32 revision;
|
||||
|
||||
mc13xxx_lock(mc13xxx);
|
||||
mc13xxx->dev = dev;
|
||||
|
||||
ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
|
||||
if (ret)
|
||||
goto err_revision;
|
||||
return ret;
|
||||
|
||||
mc13xxx->variant->print_revision(mc13xxx, revision);
|
||||
|
||||
/* mask all irqs */
|
||||
ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff);
|
||||
if (ret)
|
||||
goto err_mask;
|
||||
return ret;
|
||||
|
||||
ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK1, 0x00ffffff);
|
||||
if (ret)
|
||||
goto err_mask;
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, mc13xxx_irq_thread,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
|
||||
|
||||
if (ret) {
|
||||
err_mask:
|
||||
err_revision:
|
||||
mc13xxx_unlock(mc13xxx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mc13xxx->irq = irq;
|
||||
ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
|
||||
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mc13xxx_unlock(mc13xxx);
|
||||
mutex_init(&mc13xxx->lock);
|
||||
|
||||
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
|
||||
mc13xxx->flags = pdata->flags;
|
||||
|
@ -710,13 +701,17 @@ err_revision:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_common_init);
|
||||
|
||||
void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx)
|
||||
int mc13xxx_common_exit(struct device *dev)
|
||||
{
|
||||
free_irq(mc13xxx->irq, mc13xxx);
|
||||
struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
|
||||
|
||||
mfd_remove_devices(mc13xxx->dev);
|
||||
free_irq(mc13xxx->irq, mc13xxx);
|
||||
mfd_remove_devices(dev);
|
||||
mutex_destroy(&mc13xxx->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup);
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_common_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Core driver for Freescale MC13XXX PMIC");
|
||||
MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/mc13xxx.h>
|
||||
#include <linux/of.h>
|
||||
|
@ -60,7 +59,6 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct mc13xxx *mc13xxx;
|
||||
struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
int ret;
|
||||
|
||||
mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL);
|
||||
|
@ -69,15 +67,13 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
|
|||
|
||||
dev_set_drvdata(&client->dev, mc13xxx);
|
||||
|
||||
mc13xxx->dev = &client->dev;
|
||||
mutex_init(&mc13xxx->lock);
|
||||
mc13xxx->irq = client->irq;
|
||||
|
||||
mc13xxx->regmap = devm_regmap_init_i2c(client,
|
||||
&mc13xxx_regmap_i2c_config);
|
||||
if (IS_ERR(mc13xxx->regmap)) {
|
||||
ret = PTR_ERR(mc13xxx->regmap);
|
||||
dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
|
||||
ret);
|
||||
dev_err(&client->dev, "Failed to initialize regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -89,18 +85,12 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
|
|||
mc13xxx->variant = (void *)id->driver_data;
|
||||
}
|
||||
|
||||
ret = mc13xxx_common_init(mc13xxx, pdata, client->irq);
|
||||
|
||||
return ret;
|
||||
return mc13xxx_common_init(&client->dev);
|
||||
}
|
||||
|
||||
static int mc13xxx_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct mc13xxx *mc13xxx = dev_get_drvdata(&client->dev);
|
||||
|
||||
mc13xxx_common_cleanup(mc13xxx);
|
||||
|
||||
return 0;
|
||||
return mc13xxx_common_exit(&client->dev);
|
||||
}
|
||||
|
||||
static struct i2c_driver mc13xxx_i2c_driver = {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/mc13xxx.h>
|
||||
|
@ -129,27 +128,24 @@ static struct regmap_bus regmap_mc13xxx_bus = {
|
|||
static int mc13xxx_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct mc13xxx *mc13xxx;
|
||||
struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev);
|
||||
int ret;
|
||||
|
||||
mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL);
|
||||
if (!mc13xxx)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, mc13xxx);
|
||||
dev_set_drvdata(&spi->dev, mc13xxx);
|
||||
|
||||
spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
|
||||
|
||||
mc13xxx->dev = &spi->dev;
|
||||
mutex_init(&mc13xxx->lock);
|
||||
mc13xxx->irq = spi->irq;
|
||||
|
||||
mc13xxx->regmap = devm_regmap_init(&spi->dev, ®map_mc13xxx_bus,
|
||||
&spi->dev,
|
||||
&mc13xxx_regmap_spi_config);
|
||||
if (IS_ERR(mc13xxx->regmap)) {
|
||||
ret = PTR_ERR(mc13xxx->regmap);
|
||||
dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
|
||||
ret);
|
||||
spi_set_drvdata(spi, NULL);
|
||||
dev_err(&spi->dev, "Failed to initialize regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -164,16 +160,12 @@ static int mc13xxx_spi_probe(struct spi_device *spi)
|
|||
mc13xxx->variant = (void *)id_entry->driver_data;
|
||||
}
|
||||
|
||||
return mc13xxx_common_init(mc13xxx, pdata, spi->irq);
|
||||
return mc13xxx_common_init(&spi->dev);
|
||||
}
|
||||
|
||||
static int mc13xxx_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct mc13xxx *mc13xxx = spi_get_drvdata(spi);
|
||||
|
||||
mc13xxx_common_cleanup(mc13xxx);
|
||||
|
||||
return 0;
|
||||
return mc13xxx_common_exit(&spi->dev);
|
||||
}
|
||||
|
||||
static struct spi_driver mc13xxx_spi_driver = {
|
||||
|
|
|
@ -43,9 +43,7 @@ struct mc13xxx {
|
|||
int adcflags;
|
||||
};
|
||||
|
||||
int mc13xxx_common_init(struct mc13xxx *mc13xxx,
|
||||
struct mc13xxx_platform_data *pdata, int irq);
|
||||
|
||||
void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx);
|
||||
int mc13xxx_common_init(struct device *dev);
|
||||
int mc13xxx_common_exit(struct device *dev);
|
||||
|
||||
#endif /* __DRIVERS_MFD_MC13XXX_H */
|
||||
|
|
|
@ -121,22 +121,22 @@ static u64 usbhs_dmamask = DMA_BIT_MASK(32);
|
|||
|
||||
static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
|
||||
{
|
||||
__raw_writel(val, base + reg);
|
||||
writel_relaxed(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u32 usbhs_read(void __iomem *base, u32 reg)
|
||||
{
|
||||
return __raw_readl(base + reg);
|
||||
return readl_relaxed(base + reg);
|
||||
}
|
||||
|
||||
static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val)
|
||||
{
|
||||
__raw_writeb(val, base + reg);
|
||||
writeb_relaxed(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u8 usbhs_readb(void __iomem *base, u8 reg)
|
||||
{
|
||||
return __raw_readb(base + reg);
|
||||
return readb_relaxed(base + reg);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
|
@ -121,22 +121,22 @@ static DEFINE_SPINLOCK(tll_lock); /* serialize access to tll_dev */
|
|||
|
||||
static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
|
||||
{
|
||||
__raw_writel(val, base + reg);
|
||||
writel_relaxed(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u32 usbtll_read(void __iomem *base, u32 reg)
|
||||
{
|
||||
return __raw_readl(base + reg);
|
||||
return readl_relaxed(base + reg);
|
||||
}
|
||||
|
||||
static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val)
|
||||
{
|
||||
__raw_writeb(val, base + reg);
|
||||
writeb_relaxed(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u8 usbtll_readb(void __iomem *base, u8 reg)
|
||||
{
|
||||
return __raw_readb(base + reg);
|
||||
return readb_relaxed(base + reg);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
@ -333,21 +333,17 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
|
|||
unsigned reg;
|
||||
struct usbtll_omap *tll;
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
|
||||
if (!tll_dev) {
|
||||
spin_unlock(&tll_lock);
|
||||
if (!tll_dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pm_runtime_get_sync(tll_dev);
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
tll = dev_get_drvdata(tll_dev);
|
||||
|
||||
needs_tll = false;
|
||||
for (i = 0; i < tll->nch; i++)
|
||||
needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
|
||||
|
||||
pm_runtime_get_sync(tll_dev);
|
||||
|
||||
if (needs_tll) {
|
||||
void __iomem *base = tll->base;
|
||||
|
||||
|
@ -398,9 +394,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
|
|||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(tll_dev);
|
||||
|
||||
spin_unlock(&tll_lock);
|
||||
pm_runtime_put_sync(tll_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -411,17 +406,14 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
|
|||
int i;
|
||||
struct usbtll_omap *tll;
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
|
||||
if (!tll_dev) {
|
||||
spin_unlock(&tll_lock);
|
||||
if (!tll_dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
tll = dev_get_drvdata(tll_dev);
|
||||
|
||||
pm_runtime_get_sync(tll_dev);
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
tll = dev_get_drvdata(tll_dev);
|
||||
|
||||
for (i = 0; i < tll->nch; i++) {
|
||||
if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
|
||||
int r;
|
||||
|
@ -448,13 +440,10 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
|
|||
int i;
|
||||
struct usbtll_omap *tll;
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
|
||||
if (!tll_dev) {
|
||||
spin_unlock(&tll_lock);
|
||||
if (!tll_dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock(&tll_lock);
|
||||
tll = dev_get_drvdata(tll_dev);
|
||||
|
||||
for (i = 0; i < tll->nch; i++) {
|
||||
|
@ -464,9 +453,8 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
|
|||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(tll_dev);
|
||||
|
||||
spin_unlock(&tll_lock);
|
||||
pm_runtime_put_sync(tll_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ static struct deepsleep_control_data deepsleep_data[] = {
|
|||
#define EXT_PWR_REQ \
|
||||
(RC5T583_EXT_PWRREQ1_CONTROL | RC5T583_EXT_PWRREQ2_CONTROL)
|
||||
|
||||
static struct mfd_cell rc5t583_subdevs[] = {
|
||||
static const struct mfd_cell rc5t583_subdevs[] = {
|
||||
{.name = "rc5t583-gpio",},
|
||||
{.name = "rc5t583-regulator",},
|
||||
{.name = "rc5t583-rtc", },
|
||||
|
|
|
@ -56,7 +56,7 @@ static struct resource rdc321x_gpio_resources[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct mfd_cell rdc321x_sb_cells[] = {
|
||||
static const struct mfd_cell rdc321x_sb_cells[] = {
|
||||
{
|
||||
.name = "rdc321x-wdt",
|
||||
.resources = rdc321x_wdt_resource,
|
||||
|
@ -96,7 +96,7 @@ static void rdc321x_sb_remove(struct pci_dev *pdev)
|
|||
mfd_remove_devices(&pdev->dev);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = {
|
||||
static const struct pci_device_id rdc321x_sb_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -55,7 +55,7 @@ static struct resource retu_pwrbutton_res[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell retu_devs[] = {
|
||||
static const struct mfd_cell retu_devs[] = {
|
||||
{
|
||||
.name = "retu-wdt"
|
||||
},
|
||||
|
@ -94,7 +94,7 @@ static struct resource tahvo_usb_res[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell tahvo_devs[] = {
|
||||
static const struct mfd_cell tahvo_devs[] = {
|
||||
{
|
||||
.name = "tahvo-usb",
|
||||
.resources = tahvo_usb_res,
|
||||
|
@ -122,7 +122,7 @@ static const struct retu_data {
|
|||
char *chip_name;
|
||||
char *companion_name;
|
||||
struct regmap_irq_chip *irq_chip;
|
||||
struct mfd_cell *children;
|
||||
const struct mfd_cell *children;
|
||||
int nchildren;
|
||||
} retu_data[] = {
|
||||
[0] = {
|
||||
|
|
|
@ -49,8 +49,8 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
|
|||
|
||||
static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg1;
|
||||
u8 reg3;
|
||||
u32 reg1 = 0;
|
||||
u8 reg3 = 0;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
|
||||
|
@ -71,7 +71,7 @@ static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
|||
|
||||
static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
|
||||
{
|
||||
u32 reg;
|
||||
u32 reg = 0;
|
||||
|
||||
rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®);
|
||||
dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
|
||||
|
@ -191,24 +191,25 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
|
|||
BPP_LDO_POWB, BPP_LDO_SUSPEND);
|
||||
}
|
||||
|
||||
static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage,
|
||||
int bpp_tuned18_shift, int bpp_asic_1v8)
|
||||
{
|
||||
u8 mask, val;
|
||||
int err;
|
||||
|
||||
mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
|
||||
mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK;
|
||||
if (voltage == OUTPUT_3V3) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
|
||||
if (err < 0)
|
||||
return err;
|
||||
val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
|
||||
val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3;
|
||||
} else if (voltage == OUTPUT_1V8) {
|
||||
err = rtsx_pci_write_register(pcr,
|
||||
SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
|
||||
if (err < 0)
|
||||
return err;
|
||||
val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
|
||||
val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -216,6 +217,18 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
|||
return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
|
||||
}
|
||||
|
||||
static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
return rtl8411_do_switch_output_voltage(pcr, voltage,
|
||||
BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8);
|
||||
}
|
||||
|
||||
static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
|
||||
{
|
||||
return rtl8411_do_switch_output_voltage(pcr, voltage,
|
||||
BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0);
|
||||
}
|
||||
|
||||
static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
|
||||
{
|
||||
unsigned int card_exist;
|
||||
|
@ -295,6 +308,22 @@ static const struct pcr_ops rtl8411_pcr_ops = {
|
|||
.force_power_down = rtl8411_force_power_down,
|
||||
};
|
||||
|
||||
static const struct pcr_ops rtl8402_pcr_ops = {
|
||||
.fetch_vendor_settings = rtl8411_fetch_vendor_settings,
|
||||
.extra_init_hw = rtl8411_extra_init_hw,
|
||||
.optimize_phy = NULL,
|
||||
.turn_on_led = rtl8411_turn_on_led,
|
||||
.turn_off_led = rtl8411_turn_off_led,
|
||||
.enable_auto_blink = rtl8411_enable_auto_blink,
|
||||
.disable_auto_blink = rtl8411_disable_auto_blink,
|
||||
.card_power_on = rtl8411_card_power_on,
|
||||
.card_power_off = rtl8411_card_power_off,
|
||||
.switch_output_voltage = rtl8402_switch_output_voltage,
|
||||
.cd_deglitch = rtl8411_cd_deglitch,
|
||||
.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
|
||||
.force_power_down = rtl8411_force_power_down,
|
||||
};
|
||||
|
||||
static const struct pcr_ops rtl8411b_pcr_ops = {
|
||||
.fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
|
||||
.extra_init_hw = rtl8411b_extra_init_hw,
|
||||
|
@ -441,12 +470,10 @@ static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
|
|||
0,
|
||||
};
|
||||
|
||||
void rtl8411_init_params(struct rtsx_pcr *pcr)
|
||||
static void rtl8411_init_common_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
|
||||
pcr->num_slots = 2;
|
||||
pcr->ops = &rtl8411_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
|
@ -454,47 +481,29 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
|
|||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
|
||||
|
||||
pcr->ic_version = rtl8411_get_ic_version(pcr);
|
||||
pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
|
||||
pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl;
|
||||
pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl;
|
||||
}
|
||||
|
||||
void rtl8411_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rtl8411_init_common_params(pcr);
|
||||
pcr->ops = &rtl8411_pcr_ops;
|
||||
set_pull_ctrl_tables(pcr, rtl8411);
|
||||
}
|
||||
|
||||
void rtl8411b_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
|
||||
pcr->num_slots = 2;
|
||||
rtl8411_init_common_params(pcr);
|
||||
pcr->ops = &rtl8411b_pcr_ops;
|
||||
|
||||
pcr->flags = 0;
|
||||
pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
|
||||
pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
|
||||
pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
|
||||
pcr->aspm_en = ASPM_L1_EN;
|
||||
pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
|
||||
pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
|
||||
|
||||
pcr->ic_version = rtl8411_get_ic_version(pcr);
|
||||
|
||||
if (rtl8411b_is_qfn48(pcr)) {
|
||||
pcr->sd_pull_ctl_enable_tbl =
|
||||
rtl8411b_qfn48_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl =
|
||||
rtl8411b_qfn48_sd_pull_ctl_disable_tbl;
|
||||
pcr->ms_pull_ctl_enable_tbl =
|
||||
rtl8411b_qfn48_ms_pull_ctl_enable_tbl;
|
||||
pcr->ms_pull_ctl_disable_tbl =
|
||||
rtl8411b_qfn48_ms_pull_ctl_disable_tbl;
|
||||
} else {
|
||||
pcr->sd_pull_ctl_enable_tbl =
|
||||
rtl8411b_qfn64_sd_pull_ctl_enable_tbl;
|
||||
pcr->sd_pull_ctl_disable_tbl =
|
||||
rtl8411b_qfn64_sd_pull_ctl_disable_tbl;
|
||||
pcr->ms_pull_ctl_enable_tbl =
|
||||
rtl8411b_qfn64_ms_pull_ctl_enable_tbl;
|
||||
pcr->ms_pull_ctl_disable_tbl =
|
||||
rtl8411b_qfn64_ms_pull_ctl_disable_tbl;
|
||||
}
|
||||
if (rtl8411b_is_qfn48(pcr))
|
||||
set_pull_ctrl_tables(pcr, rtl8411b_qfn48);
|
||||
else
|
||||
set_pull_ctrl_tables(pcr, rtl8411b_qfn64);
|
||||
}
|
||||
|
||||
void rtl8402_init_params(struct rtsx_pcr *pcr)
|
||||
{
|
||||
rtl8411_init_common_params(pcr);
|
||||
pcr->ops = &rtl8402_pcr_ops;
|
||||
set_pull_ctrl_tables(pcr, rtl8411);
|
||||
}
|
||||
|
|
|
@ -50,13 +50,14 @@ static struct mfd_cell rtsx_pcr_cells[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = {
|
||||
static const struct pci_device_id rtsx_pci_ids[] = {
|
||||
{ PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
|
||||
{ PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
|
||||
{ PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
|
||||
{ PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
|
||||
{ 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 },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -1061,6 +1062,10 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
|
|||
case 0x5287:
|
||||
rtl8411b_init_params(pcr);
|
||||
break;
|
||||
|
||||
case 0x5286:
|
||||
rtl8402_init_params(pcr);
|
||||
break;
|
||||
}
|
||||
|
||||
dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n",
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
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 rtl8411b_init_params(struct rtsx_pcr *pcr);
|
||||
|
@ -63,4 +64,12 @@ static inline u8 map_sd_drive(int idx)
|
|||
#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
|
||||
#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03)
|
||||
|
||||
#define set_pull_ctrl_tables(pcr, __device) \
|
||||
do { \
|
||||
pcr->sd_pull_ctl_enable_tbl = __device##_sd_pull_ctl_enable_tbl; \
|
||||
pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \
|
||||
pcr->ms_pull_ctl_enable_tbl = __device##_ms_pull_ctl_enable_tbl; \
|
||||
pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <linux/mfd/samsung/s5m8767.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static struct mfd_cell s5m8751_devs[] = {
|
||||
static const struct mfd_cell s5m8751_devs[] = {
|
||||
{
|
||||
.name = "s5m8751-pmic",
|
||||
}, {
|
||||
|
@ -41,7 +41,7 @@ static struct mfd_cell s5m8751_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell s5m8763_devs[] = {
|
||||
static const struct mfd_cell s5m8763_devs[] = {
|
||||
{
|
||||
.name = "s5m8763-pmic",
|
||||
}, {
|
||||
|
@ -51,15 +51,17 @@ static struct mfd_cell s5m8763_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell s5m8767_devs[] = {
|
||||
static const struct mfd_cell s5m8767_devs[] = {
|
||||
{
|
||||
.name = "s5m8767-pmic",
|
||||
}, {
|
||||
.name = "s5m-rtc",
|
||||
},
|
||||
}, {
|
||||
.name = "s5m8767-clk",
|
||||
}
|
||||
};
|
||||
|
||||
static struct mfd_cell s2mps11_devs[] = {
|
||||
static const struct mfd_cell s2mps11_devs[] = {
|
||||
{
|
||||
.name = "s2mps11-pmic",
|
||||
}, {
|
||||
|
@ -134,12 +136,12 @@ static bool s5m8763_volatile(struct device *dev, unsigned int reg)
|
|||
}
|
||||
}
|
||||
|
||||
static struct regmap_config sec_regmap_config = {
|
||||
static const struct regmap_config sec_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static struct regmap_config s2mps11_regmap_config = {
|
||||
static const struct regmap_config s2mps11_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
|
@ -148,7 +150,7 @@ static struct regmap_config s2mps11_regmap_config = {
|
|||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static struct regmap_config s5m8763_regmap_config = {
|
||||
static const struct regmap_config s5m8763_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
|
@ -157,7 +159,7 @@ static struct regmap_config s5m8763_regmap_config = {
|
|||
.cache_type = REGCACHE_FLAT,
|
||||
};
|
||||
|
||||
static struct regmap_config s5m8767_regmap_config = {
|
||||
static const struct regmap_config s5m8767_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
|
||||
|
@ -204,7 +206,7 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
|
|||
static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -323,6 +325,8 @@ static int sec_pmic_probe(struct i2c_client *i2c,
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
|
@ -341,6 +345,43 @@ static int sec_pmic_remove(struct i2c_client *i2c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sec_pmic_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
enable_irq_wake(sec_pmic->irq);
|
||||
/*
|
||||
* PMIC IRQ must be disabled during suspend for RTC alarm
|
||||
* to work properly.
|
||||
* When device is woken up from suspend by RTC Alarm, an
|
||||
* interrupt occurs before resuming I2C bus controller.
|
||||
* The interrupt is handled by regmap_irq_thread which tries
|
||||
* to read RTC registers. This read fails (I2C is still
|
||||
* suspended) and RTC Alarm interrupt is disabled.
|
||||
*/
|
||||
disable_irq(sec_pmic->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sec_pmic_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
|
||||
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
disable_irq_wake(sec_pmic->irq);
|
||||
enable_irq(sec_pmic->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
|
||||
|
||||
static const struct i2c_device_id sec_pmic_id[] = {
|
||||
{ "sec_pmic", 0 },
|
||||
{ }
|
||||
|
@ -351,6 +392,7 @@ static struct i2c_driver sec_pmic_driver = {
|
|||
.driver = {
|
||||
.name = "sec_pmic",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &sec_pmic_pm_ops,
|
||||
.of_match_table = of_match_ptr(sec_dt_match),
|
||||
},
|
||||
.probe = sec_pmic_probe,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/mfd/samsung/s5m8763.h>
|
||||
#include <linux/mfd/samsung/s5m8767.h>
|
||||
|
||||
static struct regmap_irq s2mps11_irqs[] = {
|
||||
static const struct regmap_irq s2mps11_irqs[] = {
|
||||
[S2MPS11_IRQ_PWRONF] = {
|
||||
.reg_offset = 0,
|
||||
.mask = S2MPS11_IRQ_PWRONF_MASK,
|
||||
|
@ -90,7 +90,7 @@ static struct regmap_irq s2mps11_irqs[] = {
|
|||
};
|
||||
|
||||
|
||||
static struct regmap_irq s5m8767_irqs[] = {
|
||||
static const struct regmap_irq s5m8767_irqs[] = {
|
||||
[S5M8767_IRQ_PWRR] = {
|
||||
.reg_offset = 0,
|
||||
.mask = S5M8767_IRQ_PWRR_MASK,
|
||||
|
@ -161,7 +161,7 @@ static struct regmap_irq s5m8767_irqs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct regmap_irq s5m8763_irqs[] = {
|
||||
static const struct regmap_irq s5m8763_irqs[] = {
|
||||
[S5M8763_IRQ_DCINF] = {
|
||||
.reg_offset = 0,
|
||||
.mask = S5M8763_IRQ_DCINF_MASK,
|
||||
|
@ -236,7 +236,7 @@ static struct regmap_irq s5m8763_irqs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip s2mps11_irq_chip = {
|
||||
static const struct regmap_irq_chip s2mps11_irq_chip = {
|
||||
.name = "s2mps11",
|
||||
.irqs = s2mps11_irqs,
|
||||
.num_irqs = ARRAY_SIZE(s2mps11_irqs),
|
||||
|
@ -246,7 +246,7 @@ static struct regmap_irq_chip s2mps11_irq_chip = {
|
|||
.ack_base = S2MPS11_REG_INT1,
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip s5m8767_irq_chip = {
|
||||
static const struct regmap_irq_chip s5m8767_irq_chip = {
|
||||
.name = "s5m8767",
|
||||
.irqs = s5m8767_irqs,
|
||||
.num_irqs = ARRAY_SIZE(s5m8767_irqs),
|
||||
|
@ -256,7 +256,7 @@ static struct regmap_irq_chip s5m8767_irq_chip = {
|
|||
.ack_base = S5M8767_REG_INT1,
|
||||
};
|
||||
|
||||
static struct regmap_irq_chip s5m8763_irq_chip = {
|
||||
static const struct regmap_irq_chip s5m8763_irq_chip = {
|
||||
.name = "s5m8763",
|
||||
.irqs = s5m8763_irqs,
|
||||
.num_irqs = ARRAY_SIZE(s5m8763_irqs),
|
||||
|
|
|
@ -1710,7 +1710,7 @@ static int sm501_plat_remove(struct platform_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(sm501_pci_tbl) = {
|
||||
static const struct pci_device_id sm501_pci_tbl[] = {
|
||||
{ 0x126f, 0x0501, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||
{ 0, },
|
||||
};
|
||||
|
|
|
@ -65,13 +65,19 @@
|
|||
|
||||
#define SSBI_TIMEOUT_US 100
|
||||
|
||||
enum ssbi_controller_type {
|
||||
MSM_SBI_CTRL_SSBI = 0,
|
||||
MSM_SBI_CTRL_SSBI2,
|
||||
MSM_SBI_CTRL_PMIC_ARBITER,
|
||||
};
|
||||
|
||||
struct ssbi {
|
||||
struct device *slave;
|
||||
void __iomem *base;
|
||||
spinlock_t lock;
|
||||
enum ssbi_controller_type controller_type;
|
||||
int (*read)(struct ssbi *, u16 addr, u8 *buf, int len);
|
||||
int (*write)(struct ssbi *, u16 addr, u8 *buf, int len);
|
||||
int (*write)(struct ssbi *, u16 addr, const u8 *buf, int len);
|
||||
};
|
||||
|
||||
#define to_ssbi(dev) platform_get_drvdata(to_platform_device(dev))
|
||||
|
@ -140,7 +146,7 @@ err:
|
|||
}
|
||||
|
||||
static int
|
||||
ssbi_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
|
||||
ssbi_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -217,7 +223,7 @@ err:
|
|||
}
|
||||
|
||||
static int
|
||||
ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
|
||||
ssbi_pa_write_bytes(struct ssbi *ssbi, u16 addr, const u8 *buf, int len)
|
||||
{
|
||||
u32 cmd;
|
||||
int ret = 0;
|
||||
|
@ -249,7 +255,7 @@ int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ssbi_read);
|
||||
|
||||
int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len)
|
||||
int ssbi_write(struct device *dev, u16 addr, const u8 *buf, int len)
|
||||
{
|
||||
struct ssbi *ssbi = to_ssbi(dev);
|
||||
unsigned long flags;
|
||||
|
@ -311,7 +317,7 @@ static int ssbi_probe(struct platform_device *pdev)
|
|||
return of_platform_populate(np, NULL, NULL, &pdev->dev);
|
||||
}
|
||||
|
||||
static struct of_device_id ssbi_match_table[] = {
|
||||
static const struct of_device_id ssbi_match_table[] = {
|
||||
{ .compatible = "qcom,ssbi" },
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -339,7 +339,7 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
|
|||
regmap_config->cache_type = REGCACHE_NONE;
|
||||
mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
|
||||
regmap_config);
|
||||
WARN_ON(!mfd->regmap[index]);
|
||||
WARN_ON(IS_ERR(mfd->regmap[index]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
|
|||
{
|
||||
int err;
|
||||
|
||||
pci_set_power_state(pdev, 0);
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -642,7 +642,7 @@ err_disable:
|
|||
return err;
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
|
||||
static const struct pci_device_id sta2x11_mfd_tbl[] = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
|
||||
{0,},
|
||||
|
|
|
@ -297,14 +297,14 @@ static struct resource stmpe_gpio_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell stmpe_gpio_cell = {
|
||||
static const struct mfd_cell stmpe_gpio_cell = {
|
||||
.name = "stmpe-gpio",
|
||||
.of_compatible = "st,stmpe-gpio",
|
||||
.resources = stmpe_gpio_resources,
|
||||
.num_resources = ARRAY_SIZE(stmpe_gpio_resources),
|
||||
};
|
||||
|
||||
static struct mfd_cell stmpe_gpio_cell_noirq = {
|
||||
static const struct mfd_cell stmpe_gpio_cell_noirq = {
|
||||
.name = "stmpe-gpio",
|
||||
.of_compatible = "st,stmpe-gpio",
|
||||
/* gpio cell resources consist of an irq only so no resources here */
|
||||
|
@ -325,7 +325,7 @@ static struct resource stmpe_keypad_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell stmpe_keypad_cell = {
|
||||
static const struct mfd_cell stmpe_keypad_cell = {
|
||||
.name = "stmpe-keypad",
|
||||
.of_compatible = "st,stmpe-keypad",
|
||||
.resources = stmpe_keypad_resources,
|
||||
|
@ -409,7 +409,7 @@ static struct resource stmpe_ts_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell stmpe_ts_cell = {
|
||||
static const struct mfd_cell stmpe_ts_cell = {
|
||||
.name = "stmpe-ts",
|
||||
.of_compatible = "st,stmpe-ts",
|
||||
.resources = stmpe_ts_resources,
|
||||
|
@ -1064,7 +1064,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
|
|||
return stmpe_reg_write(stmpe, stmpe->regs[STMPE_IDX_ICR_LSB], icr);
|
||||
}
|
||||
|
||||
static int stmpe_add_device(struct stmpe *stmpe, struct mfd_cell *cell)
|
||||
static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
|
||||
{
|
||||
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
|
||||
NULL, stmpe->irq_base, stmpe->domain);
|
||||
|
|
|
@ -38,7 +38,7 @@ static inline void stmpe_dump_bytes(const char *str, const void *buf,
|
|||
* enable and altfunc callbacks
|
||||
*/
|
||||
struct stmpe_variant_block {
|
||||
struct mfd_cell *cell;
|
||||
const struct mfd_cell *cell;
|
||||
int irq;
|
||||
enum stmpe_block block;
|
||||
};
|
||||
|
|
|
@ -155,7 +155,7 @@ static struct resource keypad_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell tc3589x_dev_gpio[] = {
|
||||
static const struct mfd_cell tc3589x_dev_gpio[] = {
|
||||
{
|
||||
.name = "tc3589x-gpio",
|
||||
.num_resources = ARRAY_SIZE(gpio_resources),
|
||||
|
@ -164,7 +164,7 @@ static struct mfd_cell tc3589x_dev_gpio[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell tc3589x_dev_keypad[] = {
|
||||
static const struct mfd_cell tc3589x_dev_keypad[] = {
|
||||
{
|
||||
.name = "tc3589x-keypad",
|
||||
.num_resources = ARRAY_SIZE(keypad_resources),
|
||||
|
|
|
@ -126,7 +126,7 @@ static struct tmio_mmc_data tc6387xb_mmc_data = {
|
|||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static struct mfd_cell tc6387xb_cells[] = {
|
||||
static const struct mfd_cell tc6387xb_cells[] = {
|
||||
[TC6387XB_CELL_MMC] = {
|
||||
.name = "tmio-mmc",
|
||||
.enable = tc6387xb_mmc_enable,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/mfd/ti_am335x_tscadc.h>
|
||||
|
||||
|
@ -48,32 +49,79 @@ static const struct regmap_config tscadc_regmap_config = {
|
|||
.val_bits = 32,
|
||||
};
|
||||
|
||||
void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
|
||||
{
|
||||
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
|
||||
|
||||
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tsadc->reg_lock, flags);
|
||||
tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
|
||||
tsadc->reg_se_cache |= val;
|
||||
am335x_tsc_se_update(tsadc);
|
||||
tsadc->reg_se_cache = val;
|
||||
if (tsadc->adc_waiting)
|
||||
wake_up(&tsadc->reg_se_wait);
|
||||
else if (!tsadc->adc_in_use)
|
||||
tscadc_writel(tsadc, REG_SE, val);
|
||||
|
||||
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
|
||||
|
||||
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;
|
||||
prepare_to_wait(&tsadc->reg_se_wait, &wait,
|
||||
TASK_UNINTERRUPTIBLE);
|
||||
spin_unlock_irq(&tsadc->reg_lock);
|
||||
|
||||
schedule();
|
||||
|
||||
spin_lock_irq(&tsadc->reg_lock);
|
||||
finish_wait(&tsadc->reg_se_wait, &wait);
|
||||
|
||||
reg = tscadc_readl(tsadc, REG_ADCFSM);
|
||||
WARN_ON(reg & SEQ_STATUS);
|
||||
tsadc->adc_waiting = false;
|
||||
}
|
||||
tsadc->adc_in_use = true;
|
||||
}
|
||||
|
||||
void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
{
|
||||
spin_lock_irq(&tsadc->reg_lock);
|
||||
am335x_tscadc_need_adc(tsadc);
|
||||
|
||||
tscadc_writel(tsadc, REG_SE, val);
|
||||
spin_unlock_irq(&tsadc->reg_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
|
||||
|
||||
void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tsadc->reg_lock, flags);
|
||||
tsadc->adc_in_use = false;
|
||||
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
|
||||
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
|
||||
|
||||
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tsadc->reg_lock, flags);
|
||||
tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
|
||||
tsadc->reg_se_cache &= ~val;
|
||||
am335x_tsc_se_update(tsadc);
|
||||
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
|
||||
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
|
||||
|
@ -181,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
spin_lock_init(&tscadc->reg_lock);
|
||||
init_waitqueue_head(&tscadc->reg_se_wait);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
|
@ -302,7 +352,6 @@ static int tscadc_resume(struct device *dev)
|
|||
|
||||
if (tscadc_dev->tsc_cell != -1)
|
||||
tscadc_idle_config(tscadc_dev);
|
||||
am335x_tsc_se_update(tscadc_dev);
|
||||
restore = tscadc_readl(tscadc_dev, REG_CTRL);
|
||||
tscadc_writel(tscadc_dev, REG_CTRL,
|
||||
(restore | CNTRLREG_TSCSSENB));
|
||||
|
|
|
@ -374,7 +374,7 @@ static const struct resource timberdale_dma_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar0_cfg0[] = {
|
||||
{
|
||||
.name = "timb-dma",
|
||||
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
|
||||
|
@ -431,7 +431,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg0[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar0_cfg1[] = {
|
||||
{
|
||||
.name = "timb-dma",
|
||||
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
|
||||
|
@ -498,7 +498,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg1[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar0_cfg2[] = {
|
||||
{
|
||||
.name = "timb-dma",
|
||||
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
|
||||
|
@ -548,7 +548,7 @@ static struct mfd_cell timberdale_cells_bar0_cfg2[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar0_cfg3[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar0_cfg3[] = {
|
||||
{
|
||||
.name = "timb-dma",
|
||||
.num_resources = ARRAY_SIZE(timberdale_dma_resources),
|
||||
|
@ -619,7 +619,7 @@ static const struct resource timberdale_sdhc_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar1[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar1[] = {
|
||||
{
|
||||
.name = "sdhci",
|
||||
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
|
||||
|
@ -627,7 +627,7 @@ static struct mfd_cell timberdale_cells_bar1[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell timberdale_cells_bar2[] = {
|
||||
static const struct mfd_cell timberdale_cells_bar2[] = {
|
||||
{
|
||||
.name = "sdhci",
|
||||
.num_resources = ARRAY_SIZE(timberdale_sdhc_resources),
|
||||
|
@ -851,7 +851,7 @@ static void timb_remove(struct pci_dev *dev)
|
|||
kfree(priv);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(timberdale_pci_tbl) = {
|
||||
static const struct pci_device_id timberdale_pci_tbl[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TIMB, PCI_DEVICE_ID_TIMB) },
|
||||
{ 0 }
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps6507x.h>
|
||||
|
||||
static struct mfd_cell tps6507x_devs[] = {
|
||||
static const struct mfd_cell tps6507x_devs[] = {
|
||||
{
|
||||
.name = "tps6507x-pmic",
|
||||
},
|
||||
|
|
|
@ -64,7 +64,7 @@ static struct resource charger_resources[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct mfd_cell tps65090s[] = {
|
||||
static const struct mfd_cell tps65090s[] = {
|
||||
{
|
||||
.name = "tps65090-pmic",
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps65217.h>
|
||||
|
||||
static struct mfd_cell tps65217s[] = {
|
||||
static const struct mfd_cell tps65217s[] = {
|
||||
{
|
||||
.name = "tps65217-pmic",
|
||||
},
|
||||
|
|
|
@ -103,7 +103,7 @@ static struct resource tps6586x_rtc_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell tps6586x_cell[] = {
|
||||
static const struct mfd_cell tps6586x_cell[] = {
|
||||
{
|
||||
.name = "tps6586x-gpio",
|
||||
},
|
||||
|
@ -124,6 +124,7 @@ struct tps6586x {
|
|||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
int version;
|
||||
|
||||
int irq;
|
||||
struct irq_chip irq_chip;
|
||||
|
@ -208,6 +209,14 @@ int tps6586x_irq_get_virq(struct device *dev, int irq)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tps6586x_irq_get_virq);
|
||||
|
||||
int tps6586x_get_version(struct device *dev)
|
||||
{
|
||||
struct tps6586x *tps6586x = dev_get_drvdata(dev);
|
||||
|
||||
return tps6586x->version;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tps6586x_get_version);
|
||||
|
||||
static int __remove_subdev(struct device *dev, void *unused)
|
||||
{
|
||||
platform_device_unregister(to_platform_device(dev));
|
||||
|
@ -472,12 +481,38 @@ static void tps6586x_power_off(void)
|
|||
tps6586x_set_bits(tps6586x_dev, TPS6586X_SUPPLYENE, SLEEP_MODE_BIT);
|
||||
}
|
||||
|
||||
static void tps6586x_print_version(struct i2c_client *client, int version)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
switch (version) {
|
||||
case TPS658621A:
|
||||
name = "TPS658621A";
|
||||
break;
|
||||
case TPS658621CD:
|
||||
name = "TPS658621C/D";
|
||||
break;
|
||||
case TPS658623:
|
||||
name = "TPS658623";
|
||||
break;
|
||||
case TPS658643:
|
||||
name = "TPS658643";
|
||||
break;
|
||||
default:
|
||||
name = "TPS6586X";
|
||||
break;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "Found %s, VERSIONCRC is %02x\n", name, version);
|
||||
}
|
||||
|
||||
static int tps6586x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps6586x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct tps6586x *tps6586x;
|
||||
int ret;
|
||||
int version;
|
||||
|
||||
if (!pdata && client->dev.of_node)
|
||||
pdata = tps6586x_parse_dt(client);
|
||||
|
@ -487,19 +522,18 @@ static int tps6586x_i2c_probe(struct i2c_client *client,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
|
||||
version = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
|
||||
if (version < 0) {
|
||||
dev_err(&client->dev, "Chip ID read failed: %d\n", version);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "VERSIONCRC is %02x\n", ret);
|
||||
|
||||
tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL);
|
||||
if (tps6586x == NULL) {
|
||||
dev_err(&client->dev, "memory for tps6586x alloc failed\n");
|
||||
if (!tps6586x)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps6586x->version = version;
|
||||
tps6586x_print_version(client, tps6586x->version);
|
||||
|
||||
tps6586x->client = client;
|
||||
tps6586x->dev = &client->dev;
|
||||
|
|
|
@ -36,7 +36,7 @@ static struct resource rtc_resources[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct mfd_cell tps65910s[] = {
|
||||
static const struct mfd_cell tps65910s[] = {
|
||||
{
|
||||
.name = "tps65910-gpio",
|
||||
},
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps65912.h>
|
||||
|
||||
static struct mfd_cell tps65912s[] = {
|
||||
static const struct mfd_cell tps65912s[] = {
|
||||
{
|
||||
.name = "tps65912-pmic",
|
||||
},
|
||||
|
|
|
@ -44,7 +44,7 @@ static struct resource tps80031_rtc_resources[] = {
|
|||
};
|
||||
|
||||
/* TPS80031 sub mfd devices */
|
||||
static struct mfd_cell tps80031_cell[] = {
|
||||
static const struct mfd_cell tps80031_cell[] = {
|
||||
{
|
||||
.name = "tps80031-pmic",
|
||||
},
|
||||
|
|
|
@ -837,62 +837,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
|
|||
usb3v1[0].dev_name = dev_name(child);
|
||||
}
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_TWL6030_USB) && pdata->usb &&
|
||||
twl_class_is_6030()) {
|
||||
|
||||
static struct regulator_consumer_supply usb3v3;
|
||||
int regulator;
|
||||
|
||||
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
|
||||
/* this is a template that gets copied */
|
||||
struct regulator_init_data usb_fixed = {
|
||||
.constraints.valid_modes_mask =
|
||||
REGULATOR_MODE_NORMAL
|
||||
| REGULATOR_MODE_STANDBY,
|
||||
.constraints.valid_ops_mask =
|
||||
REGULATOR_CHANGE_MODE
|
||||
| REGULATOR_CHANGE_STATUS,
|
||||
};
|
||||
|
||||
if (features & TWL6032_SUBCLASS) {
|
||||
usb3v3.supply = "ldousb";
|
||||
regulator = TWL6032_REG_LDOUSB;
|
||||
} else {
|
||||
usb3v3.supply = "vusb";
|
||||
regulator = TWL6030_REG_VUSB;
|
||||
}
|
||||
child = add_regulator_linked(regulator, &usb_fixed,
|
||||
&usb3v3, 1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
pdata->usb->features = features;
|
||||
|
||||
child = add_child(TWL_MODULE_USB, "twl6030_usb",
|
||||
pdata->usb, sizeof(*pdata->usb), true,
|
||||
/* irq1 = VBUS_PRES, irq0 = USB ID */
|
||||
irq_base + USBOTG_INTR_OFFSET,
|
||||
irq_base + USB_PRES_INTR_OFFSET);
|
||||
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
/* we need to connect regulators to this transceiver */
|
||||
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child)
|
||||
usb3v3.dev_name = dev_name(child);
|
||||
} else if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) &&
|
||||
twl_class_is_6030()) {
|
||||
if (features & TWL6032_SUBCLASS)
|
||||
child = add_regulator(TWL6032_REG_LDOUSB,
|
||||
pdata->ldousb, features);
|
||||
else
|
||||
child = add_regulator(TWL6030_REG_VUSB,
|
||||
pdata->vusb, features);
|
||||
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
|
||||
child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
|
||||
|
@ -1006,148 +950,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
|
|||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
/* twl6030 regulators */
|
||||
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
|
||||
!(features & TWL6032_SUBCLASS)) {
|
||||
child = add_regulator(TWL6030_REG_VDD1, pdata->vdd1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VDD2, pdata->vdd2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VDD3, pdata->vdd3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_V1V8, pdata->v1v8,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_V2V1, pdata->v2v1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VMMC, pdata->vmmc,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VPP, pdata->vpp,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VUSIM, pdata->vusim,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VCXIO, pdata->vcxio,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VDAC, pdata->vdac,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VAUX1_6030, pdata->vaux1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VAUX2_6030, pdata->vaux2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
/* 6030 and 6025 share this regulator */
|
||||
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030()) {
|
||||
child = add_regulator(TWL6030_REG_VANA, pdata->vana,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
/* twl6032 regulators */
|
||||
if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_6030() &&
|
||||
(features & TWL6032_SUBCLASS)) {
|
||||
child = add_regulator(TWL6032_REG_LDO5, pdata->ldo5,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO1, pdata->ldo1,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO7, pdata->ldo7,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO6, pdata->ldo6,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDOLN, pdata->ldoln,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO2, pdata->ldo2,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO4, pdata->ldo4,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_LDO3, pdata->ldo3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_SMPS3, pdata->smps3,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_SMPS4, pdata->smps4,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
child = add_regulator(TWL6032_REG_VIO, pdata->vio6025,
|
||||
features);
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
|
||||
!(features & (TPS_SUBSET | TWL5031))) {
|
||||
child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
|
||||
|
@ -1269,6 +1071,11 @@ static int twl_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_dev_auxdata twl_auxdata_lookup[] = {
|
||||
OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
/* NOTE: This driver only handles a single twl4030/tps659x0 chip */
|
||||
static int
|
||||
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
|
@ -1407,10 +1214,14 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
|
||||
}
|
||||
|
||||
if (node)
|
||||
status = of_platform_populate(node, NULL, NULL, &client->dev);
|
||||
else
|
||||
if (node) {
|
||||
if (pdata)
|
||||
twl_auxdata_lookup[0].platform_data = pdata->gpio;
|
||||
status = of_platform_populate(node, NULL, twl_auxdata_lookup,
|
||||
&client->dev);
|
||||
} else {
|
||||
status = add_children(pdata, irq_base, id->driver_data);
|
||||
}
|
||||
|
||||
fail:
|
||||
if (status < 0)
|
||||
|
|
|
@ -176,8 +176,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data)
|
|||
int i, ret;
|
||||
union {
|
||||
u8 bytes[4];
|
||||
u32 int_sts;
|
||||
__le32 int_sts;
|
||||
} sts;
|
||||
u32 int_sts; /* sts.int_sts converted to CPU endianness */
|
||||
struct twl6030_irq *pdata = data;
|
||||
|
||||
/* read INT_STS_A, B and C in one shot using a burst read */
|
||||
|
@ -196,8 +197,9 @@ static irqreturn_t twl6030_irq_thread(int irq, void *data)
|
|||
if (sts.bytes[2] & 0x10)
|
||||
sts.bytes[2] |= 0x08;
|
||||
|
||||
for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++)
|
||||
if (sts.int_sts & 0x1) {
|
||||
int_sts = le32_to_cpu(sts.int_sts);
|
||||
for (i = 0; int_sts; int_sts >>= 1, i++)
|
||||
if (int_sts & 0x1) {
|
||||
int module_irq =
|
||||
irq_find_mapping(pdata->irq_domain,
|
||||
pdata->irq_mapping_tbl[i]);
|
||||
|
|
|
@ -86,7 +86,7 @@ static struct reg_default twl6040_defaults[] = {
|
|||
{ 0x2E, 0x00 }, /* REG_STATUS (ro) */
|
||||
};
|
||||
|
||||
struct reg_default twl6040_patch[] = {
|
||||
static struct reg_default twl6040_patch[] = {
|
||||
/* Select I2C bus access to dual access registers */
|
||||
{ TWL6040_REG_ACCCTL, 0x09 },
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ static const struct usb_device_id vprbrd_table[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(usb, vprbrd_table);
|
||||
|
||||
static struct mfd_cell vprbrd_devs[] = {
|
||||
static const struct mfd_cell vprbrd_devs[] = {
|
||||
{
|
||||
.name = "viperboard-gpio",
|
||||
},
|
||||
|
|
|
@ -60,7 +60,7 @@ static struct resource vx855_gpio_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell vx855_cells[] = {
|
||||
static const struct mfd_cell vx855_cells[] = {
|
||||
{
|
||||
.name = "vx855_gpio",
|
||||
.num_resources = ARRAY_SIZE(vx855_gpio_resources),
|
||||
|
@ -118,7 +118,7 @@ static void vx855_remove(struct pci_dev *pdev)
|
|||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(vx855_pci_tbl) = {
|
||||
static const struct pci_device_id vx855_pci_tbl[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
|
||||
{ 0, }
|
||||
};
|
||||
|
|
|
@ -224,6 +224,31 @@ static const struct reg_default wm5110_revb_patch[] = {
|
|||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
static const struct reg_default wm5110_revd_patch[] = {
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x80, 0x3 },
|
||||
{ 0x393, 0x27 },
|
||||
{ 0x394, 0x27 },
|
||||
{ 0x395, 0x27 },
|
||||
{ 0x396, 0x27 },
|
||||
{ 0x397, 0x27 },
|
||||
{ 0x398, 0x26 },
|
||||
{ 0x221, 0x90 },
|
||||
{ 0x211, 0x8 },
|
||||
{ 0x36c, 0x1fb },
|
||||
{ 0x26e, 0x64 },
|
||||
{ 0x26f, 0xea },
|
||||
{ 0x270, 0x1f16 },
|
||||
{ 0x51b, 0x1 },
|
||||
{ 0x55b, 0x1 },
|
||||
{ 0x59b, 0x1 },
|
||||
{ 0x4f0, 0x633 },
|
||||
{ 0x441, 0xc059 },
|
||||
{ 0x209, 0x27 },
|
||||
{ 0x80, 0x0 },
|
||||
{ 0x80, 0x0 },
|
||||
};
|
||||
|
||||
/* We use a function so we can use ARRAY_SIZE() */
|
||||
int wm5110_patch(struct arizona *arizona)
|
||||
{
|
||||
|
@ -236,7 +261,10 @@ int wm5110_patch(struct arizona *arizona)
|
|||
return regmap_register_patch(arizona->regmap,
|
||||
wm5110_revb_patch,
|
||||
ARRAY_SIZE(wm5110_revb_patch));
|
||||
|
||||
case 3:
|
||||
return regmap_register_patch(arizona->regmap,
|
||||
wm5110_revd_patch,
|
||||
ARRAY_SIZE(wm5110_revd_patch));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -505,7 +533,7 @@ static const struct reg_default wm5110_reg_default[] = {
|
|||
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
|
||||
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
|
||||
{ 0x00000210, 0x0184 }, /* R528 - LDO1 Control 1 */
|
||||
{ 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */
|
||||
{ 0x00000213, 0x03E4 }, /* R531 - LDO2 Control 1 */
|
||||
{ 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
|
||||
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
|
||||
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
|
||||
|
|
|
@ -1011,7 +1011,7 @@ static struct resource wm831x_wdt_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8310_devs[] = {
|
||||
static const struct mfd_cell wm8310_devs[] = {
|
||||
{
|
||||
.name = "wm831x-backup",
|
||||
},
|
||||
|
@ -1165,7 +1165,7 @@ static struct mfd_cell wm8310_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8311_devs[] = {
|
||||
static const struct mfd_cell wm8311_devs[] = {
|
||||
{
|
||||
.name = "wm831x-backup",
|
||||
},
|
||||
|
@ -1295,7 +1295,7 @@ static struct mfd_cell wm8311_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8312_devs[] = {
|
||||
static const struct mfd_cell wm8312_devs[] = {
|
||||
{
|
||||
.name = "wm831x-backup",
|
||||
},
|
||||
|
@ -1449,7 +1449,7 @@ static struct mfd_cell wm8312_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8320_devs[] = {
|
||||
static const struct mfd_cell wm8320_devs[] = {
|
||||
{
|
||||
.name = "wm831x-backup",
|
||||
},
|
||||
|
@ -1578,7 +1578,7 @@ static struct mfd_cell wm8320_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell touch_devs[] = {
|
||||
static const struct mfd_cell touch_devs[] = {
|
||||
{
|
||||
.name = "wm831x-touch",
|
||||
.num_resources = ARRAY_SIZE(wm831x_touch_resources),
|
||||
|
@ -1586,7 +1586,7 @@ static struct mfd_cell touch_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell rtc_devs[] = {
|
||||
static const struct mfd_cell rtc_devs[] = {
|
||||
{
|
||||
.name = "wm831x-rtc",
|
||||
.num_resources = ARRAY_SIZE(wm831x_rtc_resources),
|
||||
|
@ -1594,7 +1594,7 @@ static struct mfd_cell rtc_devs[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell backlight_devs[] = {
|
||||
static const struct mfd_cell backlight_devs[] = {
|
||||
{
|
||||
.name = "wm831x-backlight",
|
||||
},
|
||||
|
|
|
@ -64,11 +64,13 @@ static int wm831x_i2c_suspend(struct device *dev)
|
|||
return wm831x_device_suspend(wm831x);
|
||||
}
|
||||
|
||||
static void wm831x_i2c_shutdown(struct i2c_client *i2c)
|
||||
static int wm831x_i2c_poweroff(struct device *dev)
|
||||
{
|
||||
struct wm831x *wm831x = i2c_get_clientdata(i2c);
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
|
||||
wm831x_device_shutdown(wm831x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id wm831x_i2c_id[] = {
|
||||
|
@ -85,6 +87,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
|
|||
|
||||
static const struct dev_pm_ops wm831x_pm_ops = {
|
||||
.suspend = wm831x_i2c_suspend,
|
||||
.poweroff = wm831x_i2c_poweroff,
|
||||
};
|
||||
|
||||
static struct i2c_driver wm831x_i2c_driver = {
|
||||
|
@ -95,7 +98,6 @@ static struct i2c_driver wm831x_i2c_driver = {
|
|||
},
|
||||
.probe = wm831x_i2c_probe,
|
||||
.remove = wm831x_i2c_remove,
|
||||
.shutdown = wm831x_i2c_shutdown,
|
||||
.id_table = wm831x_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -66,16 +66,19 @@ static int wm831x_spi_suspend(struct device *dev)
|
|||
return wm831x_device_suspend(wm831x);
|
||||
}
|
||||
|
||||
static void wm831x_spi_shutdown(struct spi_device *spi)
|
||||
static int wm831x_spi_poweroff(struct device *dev)
|
||||
{
|
||||
struct wm831x *wm831x = spi_get_drvdata(spi);
|
||||
struct wm831x *wm831x = dev_get_drvdata(dev);
|
||||
|
||||
wm831x_device_shutdown(wm831x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops wm831x_spi_pm = {
|
||||
.freeze = wm831x_spi_suspend,
|
||||
.suspend = wm831x_spi_suspend,
|
||||
.poweroff = wm831x_spi_poweroff,
|
||||
};
|
||||
|
||||
static const struct spi_device_id wm831x_spi_ids[] = {
|
||||
|
@ -99,7 +102,6 @@ static struct spi_driver wm831x_spi_driver = {
|
|||
.id_table = wm831x_spi_ids,
|
||||
.probe = wm831x_spi_probe,
|
||||
.remove = wm831x_spi_remove,
|
||||
.shutdown = wm831x_spi_shutdown,
|
||||
};
|
||||
|
||||
static int __init wm831x_spi_init(void)
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include "wm8994.h"
|
||||
|
||||
static struct mfd_cell wm8994_regulator_devs[] = {
|
||||
static const struct mfd_cell wm8994_regulator_devs[] = {
|
||||
{
|
||||
.name = "wm8994-ldo",
|
||||
.id = 1,
|
||||
|
@ -62,7 +62,7 @@ static struct resource wm8994_gpio_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct mfd_cell wm8994_devs[] = {
|
||||
static const struct mfd_cell wm8994_devs[] = {
|
||||
{
|
||||
.name = "wm8994-codec",
|
||||
.num_resources = ARRAY_SIZE(wm8994_codec_resources),
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/mfd/abx500.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
#include <linux/mfd/abx500/ab8500-gpio.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
@ -1218,21 +1217,15 @@ static const struct of_device_id abx500_gpio_match[] = {
|
|||
|
||||
static int abx500_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ab8500_platform_data *abx500_pdata =
|
||||
dev_get_platdata(pdev->dev.parent);
|
||||
struct abx500_gpio_platform_data *pdata = NULL;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
struct abx500_pinctrl *pct;
|
||||
const struct platform_device_id *platid = platform_get_device_id(pdev);
|
||||
unsigned int id = -1;
|
||||
int ret, err;
|
||||
int i;
|
||||
|
||||
if (abx500_pdata)
|
||||
pdata = abx500_pdata->gpio;
|
||||
|
||||
if (!(pdata || np)) {
|
||||
dev_err(&pdev->dev, "gpio dt and platform data missing\n");
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "gpio dt node missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1248,17 +1241,14 @@ static int abx500_gpio_probe(struct platform_device *pdev)
|
|||
pct->parent = dev_get_drvdata(pdev->dev.parent);
|
||||
pct->chip = abx500gpio_chip;
|
||||
pct->chip.dev = &pdev->dev;
|
||||
pct->chip.base = (np) ? -1 : pdata->gpio_base;
|
||||
pct->chip.base = -1; /* Dynamic allocation */
|
||||
|
||||
if (platid)
|
||||
id = platid->driver_data;
|
||||
else if (np) {
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_device(abx500_gpio_match, &pdev->dev);
|
||||
if (match)
|
||||
id = (unsigned long)match->data;
|
||||
match = of_match_device(abx500_gpio_match, &pdev->dev);
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "gpio dt not matching\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
id = (unsigned long)match->data;
|
||||
|
||||
/* Poke in other ASIC variants here */
|
||||
switch (id) {
|
||||
|
@ -1349,14 +1339,6 @@ static int abx500_gpio_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id abx500_pinctrl_id[] = {
|
||||
{ "pinctrl-ab8500", PINCTRL_AB8500 },
|
||||
{ "pinctrl-ab8540", PINCTRL_AB8540 },
|
||||
{ "pinctrl-ab9540", PINCTRL_AB9540 },
|
||||
{ "pinctrl-ab8505", PINCTRL_AB8505 },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver abx500_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "abx500-gpio",
|
||||
|
@ -1365,7 +1347,6 @@ static struct platform_driver abx500_gpio_driver = {
|
|||
},
|
||||
.probe = abx500_gpio_probe,
|
||||
.remove = abx500_gpio_remove,
|
||||
.id_table = abx500_pinctrl_id,
|
||||
};
|
||||
|
||||
static int __init abx500_gpio_init(void)
|
||||
|
|
|
@ -15,6 +15,18 @@ enum abx500_pin_func {
|
|||
ABX500_ALT_C,
|
||||
};
|
||||
|
||||
enum abx500_gpio_pull_updown {
|
||||
ABX500_GPIO_PULL_DOWN = 0x0,
|
||||
ABX500_GPIO_PULL_NONE = 0x1,
|
||||
ABX500_GPIO_PULL_UP = 0x3,
|
||||
};
|
||||
|
||||
enum abx500_gpio_vinsel {
|
||||
ABX500_GPIO_VINSEL_VBAT = 0x0,
|
||||
ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
|
||||
ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct abx500_function - ABx500 pinctrl mux function
|
||||
* @name: The name of the function, exported to pinctrl core.
|
||||
|
|
|
@ -90,6 +90,16 @@ config PWM_JZ4740
|
|||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-jz4740.
|
||||
|
||||
config PWM_LP3943
|
||||
tristate "TI/National Semiconductor LP3943 PWM support"
|
||||
depends on MFD_LP3943
|
||||
help
|
||||
Generic PWM framework driver for LP3943 which supports two PWM
|
||||
channels.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pwm-lp3943.
|
||||
|
||||
config PWM_LPC32XX
|
||||
tristate "LPC32XX PWM support"
|
||||
depends on ARCH_LPC32XX
|
||||
|
|
|
@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
|
|||
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
|
||||
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
|
||||
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
|
||||
obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o
|
||||
obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o
|
||||
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
|
||||
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
|
||||
|
|
|
@ -0,0 +1,314 @@
|
|||
/*
|
||||
* TI/National Semiconductor LP3943 PWM driver
|
||||
*
|
||||
* Copyright 2013 Texas Instruments
|
||||
*
|
||||
* Author: Milo Kim <milo.kim@ti.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; version 2.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mfd/lp3943.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define LP3943_MAX_DUTY 255
|
||||
#define LP3943_MIN_PERIOD 6250
|
||||
#define LP3943_MAX_PERIOD 1600000
|
||||
|
||||
struct lp3943_pwm {
|
||||
struct pwm_chip chip;
|
||||
struct lp3943 *lp3943;
|
||||
struct lp3943_platform_data *pdata;
|
||||
};
|
||||
|
||||
static inline struct lp3943_pwm *to_lp3943_pwm(struct pwm_chip *_chip)
|
||||
{
|
||||
return container_of(_chip, struct lp3943_pwm, chip);
|
||||
}
|
||||
|
||||
static struct lp3943_pwm_map *
|
||||
lp3943_pwm_request_map(struct lp3943_pwm *lp3943_pwm, int hwpwm)
|
||||
{
|
||||
struct lp3943_platform_data *pdata = lp3943_pwm->pdata;
|
||||
struct lp3943 *lp3943 = lp3943_pwm->lp3943;
|
||||
struct lp3943_pwm_map *pwm_map;
|
||||
int i, offset;
|
||||
|
||||
pwm_map = kzalloc(sizeof(*pwm_map), GFP_KERNEL);
|
||||
if (!pwm_map)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
pwm_map->output = pdata->pwms[hwpwm]->output;
|
||||
pwm_map->num_outputs = pdata->pwms[hwpwm]->num_outputs;
|
||||
|
||||
for (i = 0; i < pwm_map->num_outputs; i++) {
|
||||
offset = pwm_map->output[i];
|
||||
|
||||
/* Return an error if the pin is already assigned */
|
||||
if (test_and_set_bit(offset, &lp3943->pin_used))
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
||||
return pwm_map;
|
||||
}
|
||||
|
||||
static int lp3943_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
|
||||
struct lp3943_pwm_map *pwm_map;
|
||||
|
||||
pwm_map = lp3943_pwm_request_map(lp3943_pwm, pwm->hwpwm);
|
||||
if (IS_ERR(pwm_map))
|
||||
return PTR_ERR(pwm_map);
|
||||
|
||||
return pwm_set_chip_data(pwm, pwm_map);
|
||||
}
|
||||
|
||||
static void lp3943_pwm_free_map(struct lp3943_pwm *lp3943_pwm,
|
||||
struct lp3943_pwm_map *pwm_map)
|
||||
{
|
||||
struct lp3943 *lp3943 = lp3943_pwm->lp3943;
|
||||
int i, offset;
|
||||
|
||||
for (i = 0; i < pwm_map->num_outputs; i++) {
|
||||
offset = pwm_map->output[i];
|
||||
clear_bit(offset, &lp3943->pin_used);
|
||||
}
|
||||
|
||||
kfree(pwm_map);
|
||||
}
|
||||
|
||||
static void lp3943_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
|
||||
struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
|
||||
|
||||
lp3943_pwm_free_map(lp3943_pwm, pwm_map);
|
||||
}
|
||||
|
||||
static int lp3943_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
|
||||
int duty_ns, int period_ns)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
|
||||
struct lp3943 *lp3943 = lp3943_pwm->lp3943;
|
||||
u8 val, reg_duty, reg_prescale;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* How to configure the LP3943 PWMs
|
||||
*
|
||||
* 1) Period = 6250 ~ 1600000
|
||||
* 2) Prescale = period / 6250 -1
|
||||
* 3) Duty = input duty
|
||||
*
|
||||
* Prescale and duty are register values
|
||||
*/
|
||||
|
||||
if (pwm->hwpwm == 0) {
|
||||
reg_prescale = LP3943_REG_PRESCALE0;
|
||||
reg_duty = LP3943_REG_PWM0;
|
||||
} else {
|
||||
reg_prescale = LP3943_REG_PRESCALE1;
|
||||
reg_duty = LP3943_REG_PWM1;
|
||||
}
|
||||
|
||||
period_ns = clamp(period_ns, LP3943_MIN_PERIOD, LP3943_MAX_PERIOD);
|
||||
val = (u8)(period_ns / LP3943_MIN_PERIOD - 1);
|
||||
|
||||
err = lp3943_write_byte(lp3943, reg_prescale, val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
|
||||
|
||||
return lp3943_write_byte(lp3943, reg_duty, val);
|
||||
}
|
||||
|
||||
static int lp3943_pwm_set_mode(struct lp3943_pwm *lp3943_pwm,
|
||||
struct lp3943_pwm_map *pwm_map,
|
||||
u8 val)
|
||||
{
|
||||
struct lp3943 *lp3943 = lp3943_pwm->lp3943;
|
||||
const struct lp3943_reg_cfg *mux = lp3943->mux_cfg;
|
||||
int i, index, err;
|
||||
|
||||
for (i = 0; i < pwm_map->num_outputs; i++) {
|
||||
index = pwm_map->output[i];
|
||||
err = lp3943_update_bits(lp3943, mux[index].reg,
|
||||
mux[index].mask,
|
||||
val << mux[index].shift);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp3943_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
|
||||
struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
|
||||
u8 val;
|
||||
|
||||
if (pwm->hwpwm == 0)
|
||||
val = LP3943_DIM_PWM0;
|
||||
else
|
||||
val = LP3943_DIM_PWM1;
|
||||
|
||||
/*
|
||||
* Each PWM generator is set to control any of outputs of LP3943.
|
||||
* To enable/disable the PWM, these output pins should be configured.
|
||||
*/
|
||||
|
||||
return lp3943_pwm_set_mode(lp3943_pwm, pwm_map, val);
|
||||
}
|
||||
|
||||
static void lp3943_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = to_lp3943_pwm(chip);
|
||||
struct lp3943_pwm_map *pwm_map = pwm_get_chip_data(pwm);
|
||||
|
||||
/*
|
||||
* LP3943 outputs are open-drain, so the pin should be configured
|
||||
* when the PWM is disabled.
|
||||
*/
|
||||
|
||||
lp3943_pwm_set_mode(lp3943_pwm, pwm_map, LP3943_GPIO_OUT_HIGH);
|
||||
}
|
||||
|
||||
static const struct pwm_ops lp3943_pwm_ops = {
|
||||
.request = lp3943_pwm_request,
|
||||
.free = lp3943_pwm_free,
|
||||
.config = lp3943_pwm_config,
|
||||
.enable = lp3943_pwm_enable,
|
||||
.disable = lp3943_pwm_disable,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int lp3943_pwm_parse_dt(struct device *dev,
|
||||
struct lp3943_pwm *lp3943_pwm)
|
||||
{
|
||||
static const char * const name[] = { "ti,pwm0", "ti,pwm1", };
|
||||
struct device_node *node = dev->of_node;
|
||||
struct lp3943_platform_data *pdata;
|
||||
struct lp3943_pwm_map *pwm_map;
|
||||
enum lp3943_pwm_output *output;
|
||||
int i, err, proplen, count = 0;
|
||||
u32 num_outputs;
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Read the output map configuration from the device tree.
|
||||
* Each of the two PWM generators can drive zero or more outputs.
|
||||
*/
|
||||
|
||||
for (i = 0; i < LP3943_NUM_PWMS; i++) {
|
||||
if (!of_get_property(node, name[i], &proplen))
|
||||
continue;
|
||||
|
||||
num_outputs = proplen / sizeof(u32);
|
||||
if (num_outputs == 0)
|
||||
continue;
|
||||
|
||||
output = devm_kzalloc(dev, sizeof(*output) * num_outputs,
|
||||
GFP_KERNEL);
|
||||
if (!output)
|
||||
return -ENOMEM;
|
||||
|
||||
err = of_property_read_u32_array(node, name[i], output,
|
||||
num_outputs);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pwm_map = devm_kzalloc(dev, sizeof(*pwm_map), GFP_KERNEL);
|
||||
if (!pwm_map)
|
||||
return -ENOMEM;
|
||||
|
||||
pwm_map->output = output;
|
||||
pwm_map->num_outputs = num_outputs;
|
||||
pdata->pwms[i] = pwm_map;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
return -ENODATA;
|
||||
|
||||
lp3943_pwm->pdata = pdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp3943_pwm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp3943 *lp3943 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct lp3943_pwm *lp3943_pwm;
|
||||
int ret;
|
||||
|
||||
lp3943_pwm = devm_kzalloc(&pdev->dev, sizeof(*lp3943_pwm), GFP_KERNEL);
|
||||
if (!lp3943_pwm)
|
||||
return -ENOMEM;
|
||||
|
||||
lp3943_pwm->pdata = lp3943->pdata;
|
||||
if (!lp3943_pwm->pdata) {
|
||||
if (IS_ENABLED(CONFIG_OF))
|
||||
ret = lp3943_pwm_parse_dt(&pdev->dev, lp3943_pwm);
|
||||
else
|
||||
ret = -ENODEV;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
lp3943_pwm->lp3943 = lp3943;
|
||||
lp3943_pwm->chip.dev = &pdev->dev;
|
||||
lp3943_pwm->chip.ops = &lp3943_pwm_ops;
|
||||
lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
|
||||
|
||||
platform_set_drvdata(pdev, lp3943_pwm);
|
||||
|
||||
return pwmchip_add(&lp3943_pwm->chip);
|
||||
}
|
||||
|
||||
static int lp3943_pwm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp3943_pwm *lp3943_pwm = platform_get_drvdata(pdev);
|
||||
|
||||
return pwmchip_remove(&lp3943_pwm->chip);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id lp3943_pwm_of_match[] = {
|
||||
{ .compatible = "ti,lp3943-pwm", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lp3943_pwm_of_match);
|
||||
#endif
|
||||
|
||||
static struct platform_driver lp3943_pwm_driver = {
|
||||
.probe = lp3943_pwm_probe,
|
||||
.remove = lp3943_pwm_remove,
|
||||
.driver = {
|
||||
.name = "lp3943-pwm",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(lp3943_pwm_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(lp3943_pwm_driver);
|
||||
|
||||
MODULE_DESCRIPTION("LP3943 PWM driver");
|
||||
MODULE_ALIAS("platform:lp3943-pwm");
|
||||
MODULE_AUTHOR("Milo Kim");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -343,7 +343,7 @@ config REGULATOR_MC13XXX_CORE
|
|||
|
||||
config REGULATOR_MC13783
|
||||
tristate "Freescale MC13783 regulator driver"
|
||||
depends on MFD_MC13783
|
||||
depends on MFD_MC13XXX
|
||||
select REGULATOR_MC13XXX_CORE
|
||||
help
|
||||
Say y here to support the regulators found on the Freescale MC13783
|
||||
|
|
|
@ -93,6 +93,8 @@ static const unsigned int tps6586x_ldo4_voltages[] = {
|
|||
2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
|
||||
};
|
||||
|
||||
#define tps658623_sm2_voltages tps6586x_ldo4_voltages
|
||||
|
||||
static const unsigned int tps6586x_ldo_voltages[] = {
|
||||
1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
|
||||
};
|
||||
|
@ -104,6 +106,13 @@ static const unsigned int tps6586x_sm2_voltages[] = {
|
|||
4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
|
||||
};
|
||||
|
||||
static const unsigned int tps658643_sm2_voltages[] = {
|
||||
1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
|
||||
1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
|
||||
1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000,
|
||||
1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,
|
||||
};
|
||||
|
||||
static const unsigned int tps6586x_dvm_voltages[] = {
|
||||
725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
|
||||
925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
|
||||
|
@ -119,8 +128,8 @@ static const unsigned int tps6586x_dvm_voltages[] = {
|
|||
.ops = &tps6586x_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = TPS6586X_ID_##_id, \
|
||||
.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
|
||||
.volt_table = tps6586x_##vdata##_voltages, \
|
||||
.n_voltages = ARRAY_SIZE(vdata##_voltages), \
|
||||
.volt_table = vdata##_voltages, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_reg = TPS6586X_SUPPLY##ereg0, \
|
||||
.enable_mask = 1 << (ebit0), \
|
||||
|
@ -162,27 +171,47 @@ static const unsigned int tps6586x_dvm_voltages[] = {
|
|||
|
||||
static struct tps6586x_regulator tps6586x_regulator[] = {
|
||||
TPS6586X_SYS_REGULATOR(),
|
||||
TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
|
||||
TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
|
||||
TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
|
||||
TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
|
||||
TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
|
||||
TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
|
||||
TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
|
||||
TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
|
||||
TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
|
||||
TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
|
||||
TPS6586X_LDO(LDO_0, "vinldo01", tps6586x_ldo0, SUPPLYV1, 5, 3, ENC, 0,
|
||||
END, 0),
|
||||
TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo, SUPPLYV4, 0, 3, ENC, 2,
|
||||
END, 2),
|
||||
TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo, SUPPLYV6, 0, 3, ENE, 6,
|
||||
ENE, 6),
|
||||
TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo, SUPPLYV3, 0, 3, ENC, 4,
|
||||
END, 4),
|
||||
TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo, SUPPLYV3, 3, 3, ENC, 5,
|
||||
END, 5),
|
||||
TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo, SUPPLYV2, 5, 3, ENC, 6,
|
||||
END, 6),
|
||||
TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo, SUPPLYV6, 3, 3, ENE, 7,
|
||||
ENE, 7),
|
||||
TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7,
|
||||
V4, 7),
|
||||
TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1,
|
||||
END, 1),
|
||||
TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7,
|
||||
END, 7),
|
||||
|
||||
TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
|
||||
TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3,
|
||||
ENB, 3, TPS6586X_VCC2, BIT(6)),
|
||||
TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
|
||||
TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3,
|
||||
END, 3, TPS6586X_VCC1, BIT(6)),
|
||||
TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
|
||||
TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1,
|
||||
ENB, 1, TPS6586X_VCC1, BIT(2)),
|
||||
TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
|
||||
TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0,
|
||||
ENB, 0, TPS6586X_VCC1, BIT(0)),
|
||||
};
|
||||
|
||||
static struct tps6586x_regulator tps658623_regulator[] = {
|
||||
TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7,
|
||||
END, 7),
|
||||
};
|
||||
|
||||
static struct tps6586x_regulator tps658643_regulator[] = {
|
||||
TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
|
||||
END, 7),
|
||||
};
|
||||
|
||||
/*
|
||||
* TPS6586X has 2 enable bits that are OR'ed to determine the actual
|
||||
* regulator state. Clearing one of this bits allows switching
|
||||
|
@ -254,11 +283,33 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
|
|||
setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
|
||||
}
|
||||
|
||||
static inline struct tps6586x_regulator *find_regulator_info(int id)
|
||||
static struct tps6586x_regulator *find_regulator_info(int id, int version)
|
||||
{
|
||||
struct tps6586x_regulator *ri;
|
||||
struct tps6586x_regulator *table = NULL;
|
||||
int num;
|
||||
int i;
|
||||
|
||||
switch (version) {
|
||||
case TPS658623:
|
||||
table = tps658623_regulator;
|
||||
num = ARRAY_SIZE(tps658623_regulator);
|
||||
break;
|
||||
case TPS658643:
|
||||
table = tps658643_regulator;
|
||||
num = ARRAY_SIZE(tps658643_regulator);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Search version specific table first */
|
||||
if (table) {
|
||||
for (i = 0; i < num; i++) {
|
||||
ri = &table[i];
|
||||
if (ri->desc.id == id)
|
||||
return ri;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
|
||||
ri = &tps6586x_regulator[i];
|
||||
if (ri->desc.id == id)
|
||||
|
@ -351,6 +402,7 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
|
|||
struct regulator_init_data *reg_data;
|
||||
struct tps6586x_platform_data *pdata;
|
||||
struct of_regulator_match *tps6586x_reg_matches = NULL;
|
||||
int version;
|
||||
int id;
|
||||
int err;
|
||||
|
||||
|
@ -373,10 +425,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
version = tps6586x_get_version(pdev->dev.parent);
|
||||
|
||||
for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
|
||||
reg_data = pdata->reg_init_data[id];
|
||||
|
||||
ri = find_regulator_info(id);
|
||||
ri = find_regulator_info(id, version);
|
||||
|
||||
if (!ri) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright ST-Ericsson 2010.
|
||||
*
|
||||
* Author: Bibek Basu <bibek.basu@stericsson.com>
|
||||
* Licensed under GPLv2.
|
||||
*/
|
||||
|
||||
#ifndef _AB8500_GPIO_H
|
||||
#define _AB8500_GPIO_H
|
||||
|
||||
/*
|
||||
* Platform data to register a block: only the initial gpio/irq number.
|
||||
* Array sizes are large enough to contain all AB8500 and AB9540 GPIO
|
||||
* registers.
|
||||
*/
|
||||
|
||||
struct abx500_gpio_platform_data {
|
||||
int gpio_base;
|
||||
};
|
||||
|
||||
enum abx500_gpio_pull_updown {
|
||||
ABX500_GPIO_PULL_DOWN = 0x0,
|
||||
ABX500_GPIO_PULL_NONE = 0x1,
|
||||
ABX500_GPIO_PULL_UP = 0x3,
|
||||
};
|
||||
|
||||
enum abx500_gpio_vinsel {
|
||||
ABX500_GPIO_VINSEL_VBAT = 0x0,
|
||||
ABX500_GPIO_VINSEL_VIN_1V8 = 0x1,
|
||||
ABX500_GPIO_VINSEL_VDD_BIF = 0x2,
|
||||
};
|
||||
|
||||
#endif /* _AB8500_GPIO_H */
|
|
@ -368,7 +368,6 @@ struct ab8500 {
|
|||
};
|
||||
|
||||
struct ab8500_regulator_platform_data;
|
||||
struct ab8500_gpio_platform_data;
|
||||
struct ab8500_codec_platform_data;
|
||||
struct ab8500_sysctrl_platform_data;
|
||||
|
||||
|
@ -382,7 +381,6 @@ struct ab8500_platform_data {
|
|||
int irq_base;
|
||||
void (*init) (struct ab8500 *);
|
||||
struct ab8500_regulator_platform_data *regulator;
|
||||
struct abx500_gpio_platform_data *gpio;
|
||||
struct ab8500_codec_platform_data *codec;
|
||||
struct ab8500_sysctrl_platform_data *sysctrl;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* TI/National Semiconductor LP3943 Device
|
||||
*
|
||||
* Copyright 2013 Texas Instruments
|
||||
*
|
||||
* Author: Milo Kim <milo.kim@ti.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MFD_LP3943_H__
|
||||
#define __MFD_LP3943_H__
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* Registers */
|
||||
#define LP3943_REG_GPIO_A 0x00
|
||||
#define LP3943_REG_GPIO_B 0x01
|
||||
#define LP3943_REG_PRESCALE0 0x02
|
||||
#define LP3943_REG_PWM0 0x03
|
||||
#define LP3943_REG_PRESCALE1 0x04
|
||||
#define LP3943_REG_PWM1 0x05
|
||||
#define LP3943_REG_MUX0 0x06
|
||||
#define LP3943_REG_MUX1 0x07
|
||||
#define LP3943_REG_MUX2 0x08
|
||||
#define LP3943_REG_MUX3 0x09
|
||||
|
||||
/* Bit description for LP3943_REG_MUX0 ~ 3 */
|
||||
#define LP3943_GPIO_IN 0x00
|
||||
#define LP3943_GPIO_OUT_HIGH 0x00
|
||||
#define LP3943_GPIO_OUT_LOW 0x01
|
||||
#define LP3943_DIM_PWM0 0x02
|
||||
#define LP3943_DIM_PWM1 0x03
|
||||
|
||||
#define LP3943_NUM_PWMS 2
|
||||
|
||||
enum lp3943_pwm_output {
|
||||
LP3943_PWM_OUT0,
|
||||
LP3943_PWM_OUT1,
|
||||
LP3943_PWM_OUT2,
|
||||
LP3943_PWM_OUT3,
|
||||
LP3943_PWM_OUT4,
|
||||
LP3943_PWM_OUT5,
|
||||
LP3943_PWM_OUT6,
|
||||
LP3943_PWM_OUT7,
|
||||
LP3943_PWM_OUT8,
|
||||
LP3943_PWM_OUT9,
|
||||
LP3943_PWM_OUT10,
|
||||
LP3943_PWM_OUT11,
|
||||
LP3943_PWM_OUT12,
|
||||
LP3943_PWM_OUT13,
|
||||
LP3943_PWM_OUT14,
|
||||
LP3943_PWM_OUT15,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct lp3943_pwm_map
|
||||
* @output: Output pins which are mapped to each PWM channel
|
||||
* @num_outputs: Number of outputs
|
||||
*/
|
||||
struct lp3943_pwm_map {
|
||||
enum lp3943_pwm_output *output;
|
||||
int num_outputs;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct lp3943_platform_data
|
||||
* @pwms: Output channel definitions for PWM channel 0 and 1
|
||||
*/
|
||||
struct lp3943_platform_data {
|
||||
struct lp3943_pwm_map *pwms[LP3943_NUM_PWMS];
|
||||
};
|
||||
|
||||
/*
|
||||
* struct lp3943_reg_cfg
|
||||
* @reg: Register address
|
||||
* @mask: Register bit mask to be updated
|
||||
* @shift: Register bit shift
|
||||
*/
|
||||
struct lp3943_reg_cfg {
|
||||
u8 reg;
|
||||
u8 mask;
|
||||
u8 shift;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct lp3943
|
||||
* @dev: Parent device pointer
|
||||
* @regmap: Used for I2C communication on accessing registers
|
||||
* @pdata: LP3943 platform specific data
|
||||
* @mux_cfg: Register configuration for pin MUX
|
||||
* @pin_used: Bit mask for output pin used.
|
||||
* This bitmask is used for pin assignment management.
|
||||
* 1 = pin used, 0 = available.
|
||||
* Only LSB 16 bits are used, but it is unsigned long type
|
||||
* for atomic bitwise operations.
|
||||
*/
|
||||
struct lp3943 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct lp3943_platform_data *pdata;
|
||||
const struct lp3943_reg_cfg *mux_cfg;
|
||||
unsigned long pin_used;
|
||||
};
|
||||
|
||||
int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read);
|
||||
int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data);
|
||||
int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data);
|
||||
#endif
|
|
@ -0,0 +1,330 @@
|
|||
/*
|
||||
* max14577-private.h - Common API for the Maxim 14577 internal sub chip
|
||||
*
|
||||
* Copyright (C) 2013 Samsung Electrnoics
|
||||
* Chanwoo Choi <cw00.choi@samsung.com>
|
||||
* Krzysztof Kozlowski <k.kozlowski@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.
|
||||
*
|
||||
* 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 __MAX14577_PRIVATE_H__
|
||||
#define __MAX14577_PRIVATE_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define MAX14577_REG_INVALID (0xff)
|
||||
|
||||
/* Slave addr = 0x4A: Interrupt */
|
||||
enum max14577_reg {
|
||||
MAX14577_REG_DEVICEID = 0x00,
|
||||
MAX14577_REG_INT1 = 0x01,
|
||||
MAX14577_REG_INT2 = 0x02,
|
||||
MAX14577_REG_INT3 = 0x03,
|
||||
MAX14577_REG_STATUS1 = 0x04,
|
||||
MAX14577_REG_STATUS2 = 0x05,
|
||||
MAX14577_REG_STATUS3 = 0x06,
|
||||
MAX14577_REG_INTMASK1 = 0x07,
|
||||
MAX14577_REG_INTMASK2 = 0x08,
|
||||
MAX14577_REG_INTMASK3 = 0x09,
|
||||
MAX14577_REG_CDETCTRL1 = 0x0A,
|
||||
MAX14577_REG_RFU = 0x0B,
|
||||
MAX14577_REG_CONTROL1 = 0x0C,
|
||||
MAX14577_REG_CONTROL2 = 0x0D,
|
||||
MAX14577_REG_CONTROL3 = 0x0E,
|
||||
MAX14577_REG_CHGCTRL1 = 0x0F,
|
||||
MAX14577_REG_CHGCTRL2 = 0x10,
|
||||
MAX14577_REG_CHGCTRL3 = 0x11,
|
||||
MAX14577_REG_CHGCTRL4 = 0x12,
|
||||
MAX14577_REG_CHGCTRL5 = 0x13,
|
||||
MAX14577_REG_CHGCTRL6 = 0x14,
|
||||
MAX14577_REG_CHGCTRL7 = 0x15,
|
||||
|
||||
MAX14577_REG_END,
|
||||
};
|
||||
|
||||
/* Slave addr = 0x4A: MUIC */
|
||||
enum max14577_muic_reg {
|
||||
MAX14577_MUIC_REG_STATUS1 = 0x04,
|
||||
MAX14577_MUIC_REG_STATUS2 = 0x05,
|
||||
MAX14577_MUIC_REG_CONTROL1 = 0x0C,
|
||||
MAX14577_MUIC_REG_CONTROL3 = 0x0E,
|
||||
|
||||
MAX14577_MUIC_REG_END,
|
||||
};
|
||||
|
||||
enum max14577_muic_charger_type {
|
||||
MAX14577_CHARGER_TYPE_NONE = 0,
|
||||
MAX14577_CHARGER_TYPE_USB,
|
||||
MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT,
|
||||
MAX14577_CHARGER_TYPE_DEDICATED_CHG,
|
||||
MAX14577_CHARGER_TYPE_SPECIAL_500MA,
|
||||
MAX14577_CHARGER_TYPE_SPECIAL_1A,
|
||||
MAX14577_CHARGER_TYPE_RESERVED,
|
||||
MAX14577_CHARGER_TYPE_DEAD_BATTERY = 7,
|
||||
};
|
||||
|
||||
/* MAX14577 interrupts */
|
||||
#define INT1_ADC_MASK (0x1 << 0)
|
||||
#define INT1_ADCLOW_MASK (0x1 << 1)
|
||||
#define INT1_ADCERR_MASK (0x1 << 2)
|
||||
|
||||
#define INT2_CHGTYP_MASK (0x1 << 0)
|
||||
#define INT2_CHGDETRUN_MASK (0x1 << 1)
|
||||
#define INT2_DCDTMR_MASK (0x1 << 2)
|
||||
#define INT2_DBCHG_MASK (0x1 << 3)
|
||||
#define INT2_VBVOLT_MASK (0x1 << 4)
|
||||
|
||||
#define INT3_EOC_MASK (0x1 << 0)
|
||||
#define INT3_CGMBC_MASK (0x1 << 1)
|
||||
#define INT3_OVP_MASK (0x1 << 2)
|
||||
#define INT3_MBCCHGERR_MASK (0x1 << 3)
|
||||
|
||||
/* MAX14577 DEVICE ID register */
|
||||
#define DEVID_VENDORID_SHIFT 0
|
||||
#define DEVID_DEVICEID_SHIFT 3
|
||||
#define DEVID_VENDORID_MASK (0x07 << DEVID_VENDORID_SHIFT)
|
||||
#define DEVID_DEVICEID_MASK (0x1f << DEVID_DEVICEID_SHIFT)
|
||||
|
||||
/* MAX14577 STATUS1 register */
|
||||
#define STATUS1_ADC_SHIFT 0
|
||||
#define STATUS1_ADCLOW_SHIFT 5
|
||||
#define STATUS1_ADCERR_SHIFT 6
|
||||
#define STATUS1_ADC_MASK (0x1f << STATUS1_ADC_SHIFT)
|
||||
#define STATUS1_ADCLOW_MASK (0x1 << STATUS1_ADCLOW_SHIFT)
|
||||
#define STATUS1_ADCERR_MASK (0x1 << STATUS1_ADCERR_SHIFT)
|
||||
|
||||
/* MAX14577 STATUS2 register */
|
||||
#define STATUS2_CHGTYP_SHIFT 0
|
||||
#define STATUS2_CHGDETRUN_SHIFT 3
|
||||
#define STATUS2_DCDTMR_SHIFT 4
|
||||
#define STATUS2_DBCHG_SHIFT 5
|
||||
#define STATUS2_VBVOLT_SHIFT 6
|
||||
#define STATUS2_CHGTYP_MASK (0x7 << STATUS2_CHGTYP_SHIFT)
|
||||
#define STATUS2_CHGDETRUN_MASK (0x1 << STATUS2_CHGDETRUN_SHIFT)
|
||||
#define STATUS2_DCDTMR_MASK (0x1 << STATUS2_DCDTMR_SHIFT)
|
||||
#define STATUS2_DBCHG_MASK (0x1 << STATUS2_DBCHG_SHIFT)
|
||||
#define STATUS2_VBVOLT_MASK (0x1 << STATUS2_VBVOLT_SHIFT)
|
||||
|
||||
/* MAX14577 CONTROL1 register */
|
||||
#define COMN1SW_SHIFT 0
|
||||
#define COMP2SW_SHIFT 3
|
||||
#define MICEN_SHIFT 6
|
||||
#define IDBEN_SHIFT 7
|
||||
#define COMN1SW_MASK (0x7 << COMN1SW_SHIFT)
|
||||
#define COMP2SW_MASK (0x7 << COMP2SW_SHIFT)
|
||||
#define MICEN_MASK (0x1 << MICEN_SHIFT)
|
||||
#define IDBEN_MASK (0x1 << IDBEN_SHIFT)
|
||||
#define CLEAR_IDBEN_MICEN_MASK (COMN1SW_MASK | COMP2SW_MASK)
|
||||
#define CTRL1_SW_USB ((1 << COMP2SW_SHIFT) \
|
||||
| (1 << COMN1SW_SHIFT))
|
||||
#define CTRL1_SW_AUDIO ((2 << COMP2SW_SHIFT) \
|
||||
| (2 << COMN1SW_SHIFT))
|
||||
#define CTRL1_SW_UART ((3 << COMP2SW_SHIFT) \
|
||||
| (3 << COMN1SW_SHIFT))
|
||||
#define CTRL1_SW_OPEN ((0 << COMP2SW_SHIFT) \
|
||||
| (0 << COMN1SW_SHIFT))
|
||||
|
||||
/* MAX14577 CONTROL2 register */
|
||||
#define CTRL2_LOWPWR_SHIFT (0)
|
||||
#define CTRL2_ADCEN_SHIFT (1)
|
||||
#define CTRL2_CPEN_SHIFT (2)
|
||||
#define CTRL2_SFOUTASRT_SHIFT (3)
|
||||
#define CTRL2_SFOUTORD_SHIFT (4)
|
||||
#define CTRL2_ACCDET_SHIFT (5)
|
||||
#define CTRL2_USBCPINT_SHIFT (6)
|
||||
#define CTRL2_RCPS_SHIFT (7)
|
||||
#define CTRL2_LOWPWR_MASK (0x1 << CTRL2_LOWPWR_SHIFT)
|
||||
#define CTRL2_ADCEN_MASK (0x1 << CTRL2_ADCEN_SHIFT)
|
||||
#define CTRL2_CPEN_MASK (0x1 << CTRL2_CPEN_SHIFT)
|
||||
#define CTRL2_SFOUTASRT_MASK (0x1 << CTRL2_SFOUTASRT_SHIFT)
|
||||
#define CTRL2_SFOUTORD_MASK (0x1 << CTRL2_SFOUTORD_SHIFT)
|
||||
#define CTRL2_ACCDET_MASK (0x1 << CTRL2_ACCDET_SHIFT)
|
||||
#define CTRL2_USBCPINT_MASK (0x1 << CTRL2_USBCPINT_SHIFT)
|
||||
#define CTRL2_RCPS_MASK (0x1 << CTR2_RCPS_SHIFT)
|
||||
|
||||
#define CTRL2_CPEN1_LOWPWR0 ((1 << CTRL2_CPEN_SHIFT) | \
|
||||
(0 << CTRL2_LOWPWR_SHIFT))
|
||||
#define CTRL2_CPEN0_LOWPWR1 ((0 << CTRL2_CPEN_SHIFT) | \
|
||||
(1 << CTRL2_LOWPWR_SHIFT))
|
||||
|
||||
/* MAX14577 CONTROL3 register */
|
||||
#define CTRL3_JIGSET_SHIFT 0
|
||||
#define CTRL3_BOOTSET_SHIFT 2
|
||||
#define CTRL3_ADCDBSET_SHIFT 4
|
||||
#define CTRL3_JIGSET_MASK (0x3 << CTRL3_JIGSET_SHIFT)
|
||||
#define CTRL3_BOOTSET_MASK (0x3 << CTRL3_BOOTSET_SHIFT)
|
||||
#define CTRL3_ADCDBSET_MASK (0x3 << CTRL3_ADCDBSET_SHIFT)
|
||||
|
||||
/* Slave addr = 0x4A: Charger */
|
||||
enum max14577_charger_reg {
|
||||
MAX14577_CHG_REG_STATUS3 = 0x06,
|
||||
MAX14577_CHG_REG_CHG_CTRL1 = 0x0F,
|
||||
MAX14577_CHG_REG_CHG_CTRL2 = 0x10,
|
||||
MAX14577_CHG_REG_CHG_CTRL3 = 0x11,
|
||||
MAX14577_CHG_REG_CHG_CTRL4 = 0x12,
|
||||
MAX14577_CHG_REG_CHG_CTRL5 = 0x13,
|
||||
MAX14577_CHG_REG_CHG_CTRL6 = 0x14,
|
||||
MAX14577_CHG_REG_CHG_CTRL7 = 0x15,
|
||||
|
||||
MAX14577_CHG_REG_END,
|
||||
};
|
||||
|
||||
/* MAX14577 STATUS3 register */
|
||||
#define STATUS3_EOC_SHIFT 0
|
||||
#define STATUS3_CGMBC_SHIFT 1
|
||||
#define STATUS3_OVP_SHIFT 2
|
||||
#define STATUS3_MBCCHGERR_SHIFT 3
|
||||
#define STATUS3_EOC_MASK (0x1 << STATUS3_EOC_SHIFT)
|
||||
#define STATUS3_CGMBC_MASK (0x1 << STATUS3_CGMBC_SHIFT)
|
||||
#define STATUS3_OVP_MASK (0x1 << STATUS3_OVP_SHIFT)
|
||||
#define STATUS3_MBCCHGERR_MASK (0x1 << STATUS3_MBCCHGERR_SHIFT)
|
||||
|
||||
/* MAX14577 CDETCTRL1 register */
|
||||
#define CDETCTRL1_CHGDETEN_SHIFT 0
|
||||
#define CDETCTRL1_CHGTYPMAN_SHIFT 1
|
||||
#define CDETCTRL1_DCDEN_SHIFT 2
|
||||
#define CDETCTRL1_DCD2SCT_SHIFT 3
|
||||
#define CDETCTRL1_DCHKTM_SHIFT 4
|
||||
#define CDETCTRL1_DBEXIT_SHIFT 5
|
||||
#define CDETCTRL1_DBIDLE_SHIFT 6
|
||||
#define CDETCTRL1_CDPDET_SHIFT 7
|
||||
#define CDETCTRL1_CHGDETEN_MASK (0x1 << CDETCTRL1_CHGDETEN_SHIFT)
|
||||
#define CDETCTRL1_CHGTYPMAN_MASK (0x1 << CDETCTRL1_CHGTYPMAN_SHIFT)
|
||||
#define CDETCTRL1_DCDEN_MASK (0x1 << CDETCTRL1_DCDEN_SHIFT)
|
||||
#define CDETCTRL1_DCD2SCT_MASK (0x1 << CDETCTRL1_DCD2SCT_SHIFT)
|
||||
#define CDETCTRL1_DCHKTM_MASK (0x1 << CDETCTRL1_DCHKTM_SHIFT)
|
||||
#define CDETCTRL1_DBEXIT_MASK (0x1 << CDETCTRL1_DBEXIT_SHIFT)
|
||||
#define CDETCTRL1_DBIDLE_MASK (0x1 << CDETCTRL1_DBIDLE_SHIFT)
|
||||
#define CDETCTRL1_CDPDET_MASK (0x1 << CDETCTRL1_CDPDET_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL1 register */
|
||||
#define CHGCTRL1_TCHW_SHIFT 4
|
||||
#define CHGCTRL1_TCHW_MASK (0x7 << CHGCTRL1_TCHW_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL2 register */
|
||||
#define CHGCTRL2_MBCHOSTEN_SHIFT 6
|
||||
#define CHGCTRL2_MBCHOSTEN_MASK (0x1 << CHGCTRL2_MBCHOSTEN_SHIFT)
|
||||
#define CHGCTRL2_VCHGR_RC_SHIFT 7
|
||||
#define CHGCTRL2_VCHGR_RC_MASK (0x1 << CHGCTRL2_VCHGR_RC_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL3 register */
|
||||
#define CHGCTRL3_MBCCVWRC_SHIFT 0
|
||||
#define CHGCTRL3_MBCCVWRC_MASK (0xf << CHGCTRL3_MBCCVWRC_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL4 register */
|
||||
#define CHGCTRL4_MBCICHWRCH_SHIFT 0
|
||||
#define CHGCTRL4_MBCICHWRCH_MASK (0xf << CHGCTRL4_MBCICHWRCH_SHIFT)
|
||||
#define CHGCTRL4_MBCICHWRCL_SHIFT 4
|
||||
#define CHGCTRL4_MBCICHWRCL_MASK (0x1 << CHGCTRL4_MBCICHWRCL_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL5 register */
|
||||
#define CHGCTRL5_EOCS_SHIFT 0
|
||||
#define CHGCTRL5_EOCS_MASK (0xf << CHGCTRL5_EOCS_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL6 register */
|
||||
#define CHGCTRL6_AUTOSTOP_SHIFT 5
|
||||
#define CHGCTRL6_AUTOSTOP_MASK (0x1 << CHGCTRL6_AUTOSTOP_SHIFT)
|
||||
|
||||
/* MAX14577 CHGCTRL7 register */
|
||||
#define CHGCTRL7_OTPCGHCVS_SHIFT 0
|
||||
#define CHGCTRL7_OTPCGHCVS_MASK (0x3 << CHGCTRL7_OTPCGHCVS_SHIFT)
|
||||
|
||||
/* MAX14577 regulator current limits (as in CHGCTRL4 register), uA */
|
||||
#define MAX14577_REGULATOR_CURRENT_LIMIT_MIN 90000
|
||||
#define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START 200000
|
||||
#define MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP 50000
|
||||
#define MAX14577_REGULATOR_CURRENT_LIMIT_MAX 950000
|
||||
|
||||
/* MAX14577 regulator SFOUT LDO voltage, fixed, uV */
|
||||
#define MAX14577_REGULATOR_SAFEOUT_VOLTAGE 4900000
|
||||
|
||||
enum max14577_irq_source {
|
||||
MAX14577_IRQ_INT1 = 0,
|
||||
MAX14577_IRQ_INT2,
|
||||
MAX14577_IRQ_INT3,
|
||||
|
||||
MAX14577_IRQ_REGS_NUM,
|
||||
};
|
||||
|
||||
enum max14577_irq {
|
||||
/* INT1 */
|
||||
MAX14577_IRQ_INT1_ADC,
|
||||
MAX14577_IRQ_INT1_ADCLOW,
|
||||
MAX14577_IRQ_INT1_ADCERR,
|
||||
|
||||
/* INT2 */
|
||||
MAX14577_IRQ_INT2_CHGTYP,
|
||||
MAX14577_IRQ_INT2_CHGDETRUN,
|
||||
MAX14577_IRQ_INT2_DCDTMR,
|
||||
MAX14577_IRQ_INT2_DBCHG,
|
||||
MAX14577_IRQ_INT2_VBVOLT,
|
||||
|
||||
/* INT3 */
|
||||
MAX14577_IRQ_INT3_EOC,
|
||||
MAX14577_IRQ_INT3_CGMBC,
|
||||
MAX14577_IRQ_INT3_OVP,
|
||||
MAX14577_IRQ_INT3_MBCCHGERR,
|
||||
|
||||
MAX14577_IRQ_NUM,
|
||||
};
|
||||
|
||||
struct max14577 {
|
||||
struct device *dev;
|
||||
struct i2c_client *i2c; /* Slave addr = 0x4A */
|
||||
|
||||
struct regmap *regmap;
|
||||
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
int irq;
|
||||
|
||||
/* Device ID */
|
||||
u8 vendor_id; /* Vendor Identification */
|
||||
u8 device_id; /* Chip Version */
|
||||
};
|
||||
|
||||
/* MAX14577 shared regmap API function */
|
||||
static inline int max14577_read_reg(struct regmap *map, u8 reg, u8 *dest)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(map, reg, &val);
|
||||
*dest = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int max14577_bulk_read(struct regmap *map, u8 reg, u8 *buf,
|
||||
int count)
|
||||
{
|
||||
return regmap_bulk_read(map, reg, buf, count);
|
||||
}
|
||||
|
||||
static inline int max14577_write_reg(struct regmap *map, u8 reg, u8 value)
|
||||
{
|
||||
return regmap_write(map, reg, value);
|
||||
}
|
||||
|
||||
static inline int max14577_bulk_write(struct regmap *map, u8 reg, u8 *buf,
|
||||
int count)
|
||||
{
|
||||
return regmap_bulk_write(map, reg, buf, count);
|
||||
}
|
||||
|
||||
static inline int max14577_update_reg(struct regmap *map, u8 reg, u8 mask,
|
||||
u8 val)
|
||||
{
|
||||
return regmap_update_bits(map, reg, mask, val);
|
||||
}
|
||||
|
||||
#endif /* __MAX14577_PRIVATE_H__ */
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* max14577.h - Driver for the Maxim 14577
|
||||
*
|
||||
* Copyright (C) 2013 Samsung Electrnoics
|
||||
* Chanwoo Choi <cw00.choi@samsung.com>
|
||||
* Krzysztof Kozlowski <k.kozlowski@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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This driver is based on max8997.h
|
||||
*
|
||||
* MAX14577 has MUIC, Charger devices.
|
||||
* The devices share the same I2C bus and interrupt line
|
||||
* included in this mfd driver.
|
||||
*/
|
||||
|
||||
#ifndef __MAX14577_H__
|
||||
#define __MAX14577_H__
|
||||
|
||||
#include <linux/mfd/max14577-private.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
/*
|
||||
* MAX14577 Regulator
|
||||
*/
|
||||
|
||||
/* MAX14577 regulator IDs */
|
||||
enum max14577_regulators {
|
||||
MAX14577_SAFEOUT = 0,
|
||||
MAX14577_CHARGER,
|
||||
|
||||
MAX14577_REG_MAX,
|
||||
};
|
||||
|
||||
struct max14577_regulator_platform_data {
|
||||
int id;
|
||||
struct regulator_init_data *initdata;
|
||||
struct device_node *of_node;
|
||||
};
|
||||
|
||||
/*
|
||||
* MAX14577 MFD platform data
|
||||
*/
|
||||
struct max14577_platform_data {
|
||||
/* IRQ */
|
||||
int irq_base;
|
||||
|
||||
/* current control GPIOs */
|
||||
int gpio_pogo_vbatt_en;
|
||||
int gpio_pogo_vbus_en;
|
||||
|
||||
/* current control GPIO control function */
|
||||
int (*set_gpio_pogo_vbatt_en) (int gpio_val);
|
||||
int (*set_gpio_pogo_vbus_en) (int gpio_val);
|
||||
|
||||
int (*set_gpio_pogo_cb) (int new_dev);
|
||||
|
||||
struct max14577_regulator_platform_data *regulators;
|
||||
};
|
||||
|
||||
#endif /* __MAX14577_H__ */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* max77686.h - Voltage regulator driver for the Maxim 77686
|
||||
* max77686-private.h - Voltage regulator driver for the Maxim 77686
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electrnoics
|
||||
* Chiwoong Byun <woong.byun@samsung.com>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* max8997.h - Voltage regulator driver for the Maxim 8997
|
||||
* max8997-private.h - Voltage regulator driver for the Maxim 8997
|
||||
*
|
||||
* Copyright (C) 2010 Samsung Electrnoics
|
||||
* MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* max8998.h - Voltage regulator driver for the Maxim 8998
|
||||
* max8998-private.h - Voltage regulator driver for the Maxim 8998
|
||||
*
|
||||
* Copyright (C) 2009-2010 Samsung Electrnoics
|
||||
* Kyungmin Park <kyungmin.park@samsung.com>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue