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:
Linus Torvalds 2014-01-21 10:58:17 -08:00
commit ac26663572
106 changed files with 2348 additions and 658 deletions

View File

@ -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";
};
};

View File

@ -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

View File

@ -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>;
};
};

View File

@ -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

View File

@ -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";
};
};

View File

@ -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;
};

View File

@ -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

View File

@ -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

242
drivers/gpio/gpio-lp3943.c Normal file
View File

@ -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");

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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" },

View File

@ -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[] = {

View File

@ -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,

View File

@ -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,

View File

@ -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,
};

View File

@ -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)");

View File

@ -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, }

View File

@ -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,

View File

@ -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",

View File

@ -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),

View File

@ -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",

View File

@ -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,

View File

@ -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,

View File

@ -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, }

View File

@ -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",

167
drivers/mfd/lp3943.c Normal file
View File

@ -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");

View File

@ -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),

View File

@ -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},

View File

@ -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) },

245
drivers/mfd/max14577.c Normal file
View File

@ -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,
&reg_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");

View File

@ -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",

View File

@ -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,

View File

@ -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", },
};

View File

@ -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,

View File

@ -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);

View File

@ -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",
}, {

View File

@ -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>");

View File

@ -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 = {

View File

@ -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, &regmap_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 = {

View File

@ -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 */

View File

@ -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);
}
/*-------------------------------------------------------------------------*/

View File

@ -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;
}

View File

@ -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", },

View File

@ -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) },
{}
};

View File

@ -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] = {

View File

@ -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, &reg1);
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, &reg);
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);
}

View File

@ -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",

View File

@ -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

View File

@ -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,

View File

@ -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),

View File

@ -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, },
};

View File

@ -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" },
{}
};

View File

@ -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,},

View File

@ -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);

View File

@ -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;
};

View File

@ -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),

View File

@ -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,

View File

@ -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));

View File

@ -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 }
};

View File

@ -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",
},

View File

@ -64,7 +64,7 @@ static struct resource charger_resources[] = {
}
};
static struct mfd_cell tps65090s[] = {
static const struct mfd_cell tps65090s[] = {
{
.name = "tps65090-pmic",
},

View File

@ -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",
},

View File

@ -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;

View File

@ -36,7 +36,7 @@ static struct resource rtc_resources[] = {
}
};
static struct mfd_cell tps65910s[] = {
static const struct mfd_cell tps65910s[] = {
{
.name = "tps65910-gpio",
},

View File

@ -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",
},

View File

@ -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",
},

View File

@ -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)

View File

@ -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]);

View File

@ -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 },
};

View File

@ -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",
},

View File

@ -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, }
};

View File

@ -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 */

View File

@ -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",
},

View File

@ -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,
};

View File

@ -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)

View File

@ -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),

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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

314
drivers/pwm/pwm-lp3943.c Normal file
View File

@ -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");

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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;
};

114
include/linux/mfd/lp3943.h Normal file
View File

@ -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

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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>

View File

@ -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>

View File

@ -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