Commit 54c72d59 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MFD update from Lee Jones:
 "Changes to existing drivers:
   - checkpatch fixes throughout the subsystem
   - use Regmap to handle IRQs in max77686, extcon-max77693 and
     mc13xxx-core
   - use DMA in rtsx_pcr
   - restrict building on unsupported architectures on timberdale,
     cs5535
   - SPI hardening in cros_ec_spi
   - more robust error handing in asic3, cros_ec, ab8500-debugfs,
     max77686 and pcf50633-core
   - reorder PM runtime and regulator handing during shutdown in arizona
   - enable wakeup in cros_ec_spi
   - unused variable/code clean-up in pm8921-core, cros_ec, htc-i2cpld,
     tps65912-spi, wm5110-tables and ab8500-debugfs
   - add regulator handing into suspend() in sec-core
   - remove pointless wrapper functions in extcon-max77693 and
     i2c-cros-ec-tunnel
   - use cross-architecture friendly data sizes in stmpe-i2c, arizona,
     max77686 and tps65910
   - devicetree documentation updates throughout
   - provide power management support in max77686
   - few OF clean-ups in max77686
   - use manged resources in tps6105x

  New drivers/supported devices:
   - add support for s2mpu02 to sec-core
   - add support for Allwinner A32 to sun6i-prcm
   - add support for Maxim 77802 in max77686
   - add support for DA9063 AD in da9063
   - new driver for Intel PMICs (generic) and specifically Crystal Cove

  (Re-)moved drivers ==
   - move out keyboard functionality cros_ec ==> input/keyboard/cros_ec_keyb"

* tag 'mfd-for-linus-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (101 commits)
  MAINTAINERS: Update MFD repo location
  mfd: omap-usb-host: Fix improper mask use.
  mfd: arizona: Only free the CTRLIF_ERR IRQ if we requested it
  mfd: arizona: Add missing handling for ISRC3 under/overclocked
  mfd: wm5110: Add new interrupt register definitions
  mfd: arizona: Rename thermal shutdown interrupt
  mfd: wm5110: Add in the output done interrupts
  mfd: wm5110: Remove non-existant interrupts
  mfd: tps65912-spi: Remove unused variable
  mfd: htc-i2cpld: Remove unused code
  mfd: da9063: Add support for AD silicon variant
  mfd: arizona: Map MICVDD from extcon device to the Arizona core
  mfd: arizona: Add MICVDD to mapped regulators for wm8997
  mfd: max77686: Ensure device type IDs are architecture agnostic
  mfd: max77686: Add Maxim 77802 PMIC support
  mfd: tps6105x: Use managed resources when allocating memory
  mfd: wm8997-tables: Suppress 'line over 80 chars' warnings
  mfd: kempld-core: Correct a variety of checkpatch warnings
  mfd: ipaq-micro: Fix coding style errors/warnings reported by checkpatch
  mfd: si476x-cmd: Remedy checkpatch style complains
  ...
parents 66bb0aa0 7caa7991
......@@ -42,6 +42,16 @@ Optional properties:
the chip default will be used. If present exactly five values must
be specified.
- DCVDD-supply, MICVDD-supply : Power supplies, only need to be specified if
they are being externally supplied. As covered in
Documentation/devicetree/bindings/regulator/regulator.txt
Optional subnodes:
- ldo1 : Initial data for the LDO1 regulator, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt
- micvdd : Initial data for the MICVDD regulator, as covered in
Documentation/devicetree/bindings/regulator/regulator.txt
Example:
codec: wm5102@1a {
......
......@@ -13,6 +13,14 @@ Required properties:
The second cell is the flags, encoded as the trigger masks from binding document
interrupts.txt, using dt-bindings/irq.
Optional properties:
--------------------
- ams,enable-internal-int-pullup: Boolean property, to enable internal pullup on
interrupt pin. Missing this will disable internal pullup on INT pin.
- ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
i2c scl/sda pins. Missing this will disable internal pullup on i2c
scl/sda lines.
Optional submodule and their properties:
=======================================
......
* Samsung S2MPS11 and S2MPS14 Voltage and Current Regulator
* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
The Samsung S2MPS11 is a multi-function device which includes voltage and
current regulators, RTC, charger controller and other sub-blocks. It is
......@@ -7,7 +7,8 @@ interfaced to the host controller using an I2C interface. Each sub-block is
addressed by the host system using different I2C slave addresses.
Required properties:
- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic".
- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic"
or "samsung,s2mpu02-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties:
......@@ -81,11 +82,13 @@ as per the datasheet of s2mps11.
- valid values for n are:
- S2MPS11: 1 to 38
- S2MPS14: 1 to 25
- Example: LDO1, LD02, LDO28
- S2MPU02: 1 to 28
- Example: LDO1, LDO2, LDO28
- BUCKn
- valid values for n are:
- S2MPS11: 1 to 10
- S2MPS14: 1 to 5
- S2MPU02: 1 to 7
- Example: BUCK1, BUCK2, BUCK9
Example:
......@@ -96,7 +99,7 @@ Example:
s2m_osc: clocks {
compatible = "samsung,s2mps11-clk";
#clock-cells = 1;
#clock-cells = <1>;
clock-output-names = "xx", "yy", "zz";
};
......
......@@ -4,7 +4,7 @@ PRCM is an MFD device exposing several Power Management related devices
(like clks and reset controllers).
Required properties:
- compatible: "allwinner,sun6i-a31-prcm"
- compatible: "allwinner,sun6i-a31-prcm" or "allwinner,sun8i-a23-prcm"
- reg: The PRCM registers range
The prcm node may contain several subdevices definitions:
......
......@@ -86,7 +86,7 @@ as per the datasheet of s5m8767.
- LDOn
- valid values for n are 1 to 28
- Example: LDO1, LD02, LDO28
- Example: LDO1, LDO2, LDO28
- BUCKn
- valid values for n are 1 to 9.
- Example: BUCK1, BUCK2, BUCK9
......
......@@ -6037,8 +6037,7 @@ F: include/media/mt9v032.h
MULTIFUNCTION DEVICES (MFD)
M: Samuel Ortiz <sameo@linux.intel.com>
M: Lee Jones <lee.jones@linaro.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-fixes.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
S: Supported
F: drivers/mfd/
F: include/linux/mfd/
......
......@@ -450,6 +450,19 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
config GPIO_CRYSTAL_COVE
tristate "GPIO support for Crystal Cove PMIC"
depends on INTEL_SOC_PMIC
select GPIOLIB_IRQCHIP
help
Support for GPIO pins on Crystal Cove PMIC.
Say Yes if you have a Intel SoC based tablet with Crystal Cove PMIC
inside.
This driver can also be built as a module. If so, the module will be
called gpio-crystalcove.
config GPIO_LP3943
tristate "TI/National Semiconductor LP3943 GPIO expander"
depends on MFD_LP3943
......
......@@ -20,6 +20,7 @@ obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
obj-$(CONFIG_GPIO_CRYSTAL_COVE) += gpio-crystalcove.o
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
......
/*
* gpio-crystalcove.c - Intel Crystal Cove GPIO Driver
*
* Copyright (C) 2012, 2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Yang, Bin <bin.yang@intel.com>
*/
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/seq_file.h>
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <linux/mfd/intel_soc_pmic.h>
#define CRYSTALCOVE_GPIO_NUM 16
#define UPDATE_IRQ_TYPE BIT(0)
#define UPDATE_IRQ_MASK BIT(1)
#define GPIO0IRQ 0x0b
#define GPIO1IRQ 0x0c
#define MGPIO0IRQS0 0x19
#define MGPIO1IRQS0 0x1a
#define MGPIO0IRQSX 0x1b
#define MGPIO1IRQSX 0x1c
#define GPIO0P0CTLO 0x2b
#define GPIO0P0CTLI 0x33
#define GPIO1P0CTLO 0x3b
#define GPIO1P0CTLI 0x43
#define CTLI_INTCNT_DIS (0)
#define CTLI_INTCNT_NE (1 << 1)
#define CTLI_INTCNT_PE (2 << 1)
#define CTLI_INTCNT_BE (3 << 1)
#define CTLO_DIR_IN (0)
#define CTLO_DIR_OUT (1 << 5)
#define CTLO_DRV_CMOS (0)
#define CTLO_DRV_OD (1 << 4)
#define CTLO_DRV_REN (1 << 3)
#define CTLO_RVAL_2KDW (0)
#define CTLO_RVAL_2KUP (1 << 1)
#define CTLO_RVAL_50KDW (2 << 1)
#define CTLO_RVAL_50KUP (3 << 1)
#define CTLO_INPUT_SET (CTLO_DRV_CMOS | CTLO_DRV_REN | CTLO_RVAL_2KUP)
#define CTLO_OUTPUT_SET (CTLO_DIR_OUT | CTLO_INPUT_SET)
enum ctrl_register {
CTRL_IN,
CTRL_OUT,
};
/**
* struct crystalcove_gpio - Crystal Cove GPIO controller
* @buslock: for bus lock/sync and unlock.
* @chip: the abstract gpio_chip structure.
* @regmap: the regmap from the parent device.
* @update: pending IRQ setting update, to be written to the chip upon unlock.
* @intcnt_value: the Interrupt Detect value to be written.
* @set_irq_mask: true if the IRQ mask needs to be set, false to clear.
*/
struct crystalcove_gpio {
struct mutex buslock; /* irq_bus_lock */
struct gpio_chip chip;
struct regmap *regmap;
int update;
int intcnt_value;
bool set_irq_mask;
};
static inline struct crystalcove_gpio *to_cg(struct gpio_chip *gc)
{
return container_of(gc, struct crystalcove_gpio, chip);
}
static inline int to_reg(int gpio, enum ctrl_register reg_type)
{
int reg;
if (reg_type == CTRL_IN) {
if (gpio < 8)
reg = GPIO0P0CTLI;
else
reg = GPIO1P0CTLI;
} else {
if (gpio < 8)
reg = GPIO0P0CTLO;
else
reg = GPIO1P0CTLO;
}
return reg + gpio % 8;
}
static void crystalcove_update_irq_mask(struct crystalcove_gpio *cg,
int gpio)
{
u8 mirqs0 = gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0;
int mask = BIT(gpio % 8);
if (cg->set_irq_mask)
regmap_update_bits(cg->regmap, mirqs0, mask, mask);
else
regmap_update_bits(cg->regmap, mirqs0, mask, 0);
}
static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
{
int reg = to_reg(gpio, CTRL_IN);
regmap_update_bits(cg->regmap, reg, CTLI_INTCNT_BE, cg->intcnt_value);
}
static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
{
struct crystalcove_gpio *cg = to_cg(chip);
return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_INPUT_SET);
}
static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct crystalcove_gpio *cg = to_cg(chip);
return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
CTLO_OUTPUT_SET | value);
}
static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct crystalcove_gpio *cg = to_cg(chip);
int ret;
unsigned int val;
ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
if (ret)
return ret;
return val & 0x1;
}
static void crystalcove_gpio_set(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct crystalcove_gpio *cg = to_cg(chip);
if (value)
regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
else
regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
}
static int crystalcove_irq_type(struct irq_data *data, unsigned type)
{
struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
switch (type) {
case IRQ_TYPE_NONE:
cg->intcnt_value = CTLI_INTCNT_DIS;
break;
case IRQ_TYPE_EDGE_BOTH:
cg->intcnt_value = CTLI_INTCNT_BE;
break;
case IRQ_TYPE_EDGE_RISING:
cg->intcnt_value = CTLI_INTCNT_PE;
break;
case IRQ_TYPE_EDGE_FALLING:
cg->intcnt_value = CTLI_INTCNT_NE;
break;
default:
return -EINVAL;
}
cg->update |= UPDATE_IRQ_TYPE;
return 0;
}
static void crystalcove_bus_lock(struct irq_data *data)
{
struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
mutex_lock(&cg->buslock);
}
static void crystalcove_bus_sync_unlock(struct irq_data *data)
{
struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
int gpio = data->hwirq;
if (cg->update & UPDATE_IRQ_TYPE)
crystalcove_update_irq_ctrl(cg, gpio);
if (cg->update & UPDATE_IRQ_MASK)
crystalcove_update_irq_mask(cg, gpio);
cg->update = 0;
mutex_unlock(&cg->buslock);
}
static void crystalcove_irq_unmask(struct irq_data *data)
{
struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
cg->set_irq_mask = false;
cg->update |= UPDATE_IRQ_MASK;
}
static void crystalcove_irq_mask(struct irq_data *data)
{
struct crystalcove_gpio *cg = to_cg(irq_data_get_irq_chip_data(data));
cg->set_irq_mask = true;
cg->update |= UPDATE_IRQ_MASK;
}
static struct irq_chip crystalcove_irqchip = {
.name = "Crystal Cove",
.irq_mask = crystalcove_irq_mask,
.irq_unmask = crystalcove_irq_unmask,
.irq_set_type = crystalcove_irq_type,
.irq_bus_lock = crystalcove_bus_lock,
.irq_bus_sync_unlock = crystalcove_bus_sync_unlock,
};
static irqreturn_t crystalcove_gpio_irq_handler(int irq, void *data)
{
struct crystalcove_gpio *cg = data;
unsigned int p0, p1;
int pending;
int gpio;
unsigned int virq;
if (regmap_read(cg->regmap, GPIO0IRQ, &p0) ||
regmap_read(cg->regmap, GPIO1IRQ, &p1))
return IRQ_NONE;
regmap_write(cg->regmap, GPIO0IRQ, p0);
regmap_write(cg->regmap, GPIO1IRQ, p1);
pending = p0 | p1 << 8;
for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
if (pending & BIT(gpio)) {
virq = irq_find_mapping(cg->chip.irqdomain, gpio);
generic_handle_irq(virq);
}
}
return IRQ_HANDLED;
}
static void crystalcove_gpio_dbg_show(struct seq_file *s,
struct gpio_chip *chip)
{
struct crystalcove_gpio *cg = to_cg(chip);
int gpio, offset;
unsigned int ctlo, ctli, mirqs0, mirqsx, irq;
for (gpio = 0; gpio < cg->chip.ngpio; gpio++) {
regmap_read(cg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &ctli);
regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQS0 : MGPIO1IRQS0,
&mirqs0);
regmap_read(cg->regmap, gpio < 8 ? MGPIO0IRQSX : MGPIO1IRQSX,
&mirqsx);
regmap_read(cg->regmap, gpio < 8 ? GPIO0IRQ : GPIO1IRQ,
&irq);
offset = gpio % 8;
seq_printf(s, " gpio-%-2d %s %s %s %s ctlo=%2x,%s %s %s\n",
gpio, ctlo & CTLO_DIR_OUT ? "out" : "in ",
ctli & 0x1 ? "hi" : "lo",
ctli & CTLI_INTCNT_NE ? "fall" : " ",
ctli & CTLI_INTCNT_PE ? "rise" : " ",
ctlo,
mirqs0 & BIT(offset) ? "s0 mask " : "s0 unmask",
mirqsx & BIT(offset) ? "sx mask " : "sx unmask",
irq & BIT(offset) ? "pending" : " ");
}
}
static int crystalcove_gpio_probe(struct platform_device *pdev)
{
int irq = platform_get_irq(pdev, 0);
struct crystalcove_gpio *cg;
int retval;
struct device *dev = pdev->dev.parent;
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
if (irq < 0)
return irq;
cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL);
if (!cg)
return -ENOMEM;
platform_set_drvdata(pdev, cg);
mutex_init(&cg->buslock);
cg->chip.label = KBUILD_MODNAME;
cg->chip.direction_input = crystalcove_gpio_dir_in;
cg->chip.direction_output = crystalcove_gpio_dir_out;
cg->chip.get = crystalcove_gpio_get;
cg->chip.set = crystalcove_gpio_set;
cg->chip.base = -1;
cg->chip.ngpio = CRYSTALCOVE_GPIO_NUM;
cg->chip.can_sleep = true;
cg->chip.dev = dev;
cg->chip.dbg_show = crystalcove_gpio_dbg_show;
cg->regmap = pmic->regmap;
retval = gpiochip_add(&cg->chip);
if (retval) {
dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
return retval;
}
gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
IRQF_ONESHOT, KBUILD_MODNAME, cg);
if (retval) {
dev_warn(&pdev->dev, "request irq failed: %d\n", retval);
goto out_remove_gpio;
}
return 0;
out_remove_gpio:
WARN_ON(gpiochip_remove(&cg->chip));
return retval;
}
static int crystalcove_gpio_remove(struct platform_device *pdev)
{
struct crystalcove_gpio *cg = platform_get_drvdata(pdev);
int irq = platform_get_irq(pdev, 0);
int err;
err = gpiochip_remove(&cg->chip);
if (irq >= 0)
free_irq(irq, cg);
return err;
}
static struct platform_driver crystalcove_gpio_driver = {
.probe = crystalcove_gpio_probe,
.remove = crystalcove_gpio_remove,
.driver = {
.name = "crystal_cove_gpio",
.owner = THIS_MODULE,
},
};
module_platform_driver(crystalcove_gpio_driver);
MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
MODULE_DESCRIPTION("Intel Crystal Cove GPIO Driver");
MODULE_LICENSE("GPL v2");
......@@ -183,6 +183,7 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
u8 *request = NULL;
u8 *response = NULL;
int result;
struct cros_ec_command msg;
request_len = ec_i2c_count_message(i2c_msgs, num);
if (request_len < 0) {
......@@ -218,10 +219,16 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
}
ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
request, request_len,
response, response_len);
if (result)
msg.version = 0;
msg.command = EC_CMD_I2C_PASSTHRU;
msg.outdata = request;
msg.outsize = request_len;
msg.indata = response;
msg.insize = response_len;
result = bus->ec->cmd_xfer(bus->ec, &msg);
if (result < 0)
goto exit;
result = ec_i2c_parse_response(response, i2c_msgs, &num);
......@@ -258,7 +265,7 @@ static int ec_i2c_probe(struct platform_device *pdev)
u32 remote_bus;
int err;
if (!ec->command_sendrecv) {
if (!ec->cmd_xfer) {
dev_err(dev, "Missing sendrecv\n");
return -EINVAL;
}
......
......@@ -24,8 +24,8 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/input/matrix_keypad.h>
......@@ -42,7 +42,6 @@
* @dev: Device pointer
* @idev: Input device
* @ec: Top level ChromeOS device to use to talk to EC
* @event_notifier: interrupt event notifier for transport devices
*/
struct cros_ec_keyb {
unsigned int rows;
......@@ -55,7 +54,6 @@ struct cros_ec_keyb {
struct device *dev;
struct input_dev *idev;
struct cros_ec_device *ec;
struct notifier_block notifier;
};
......@@ -173,41 +171,55 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
input_sync(ckdev->idev);
}
static int cros_ec_keyb_open(struct input_dev *dev)
{
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
&ckdev->notifier);
}
static void cros_ec_keyb_close(struct input_dev *dev)
{
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
&ckdev->notifier);
}
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
{
return ckdev->ec->command_recv(ckdev->ec, EC_CMD_MKBP_STATE,
kb_state, ckdev->cols);
struct cros_ec_command msg = {
.version = 0,
.command = EC_CMD_MKBP_STATE,
.outdata = NULL,
.outsize = 0,
.indata = kb_state,
.insize = ckdev->cols,
};
return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
}
static int cros_ec_keyb_work(struct notifier_block *nb,
unsigned long state, void *_notify)
static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
{
struct cros_ec_keyb *ckdev = data;
struct cros_ec_device *ec = ckdev->ec;
int ret;
struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
notifier);
uint8_t kb_state[ckdev->cols];
if (device_may_wakeup(ec->dev))
pm_wakeup_event(ec->dev, 0);
ret = cros_ec_keyb_get_state(ckdev, kb_state);
if (ret >= 0)
cros_ec_keyb_process(ckdev, kb_state, ret);
else
dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
return NOTIFY_DONE;
return IRQ_HANDLED;
}
static int cros_ec_keyb_open(struct input_dev *dev)
{
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
struct cros_ec_device *ec = ckdev->ec;
return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"cros_ec_keyb", ckdev);
}
static void cros_ec_keyb_close(struct input_dev *dev)
{
struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
struct cros_ec_device *ec = ckdev->ec;
free_irq(ec->irq, ckdev);
}
static int cros_ec_keyb_probe(struct platform_device *pdev)
......@@ -238,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
if (!idev)
return -ENOMEM;
if (!ec->irq) {
dev_err(dev, "no EC IRQ specified\n");
return -EINVAL;
}
ckdev->ec = ec;
ckdev->notifier.notifier_call = cros_ec_keyb_work;
ckdev->dev = dev;
dev_set_drvdata(&pdev->dev, ckdev);
......
......@@ -158,7 +158,7 @@ static int device_irq_init_805(struct pm80x_chip *chip)
* PM805_INT_STATUS is under 32K clock domain, so need to
* add proper delay before the next I2C register access.
*/
msleep(1);
usleep_range(1000, 3000);
if (ret < 0)
goto out;
......
......@@ -2,7 +2,8 @@
* Base driver for Marvell 88PM8607
*
* Copyright (C) 2009 Marvell International Ltd.
* Haojian Zhuang <haojian.zhuang@marvell.com>
*
* Author: Haojian Zhuang <haojian.zhuang@marvell.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
......@@ -140,7 +141,8 @@ static struct resource codec_resources[] = {
/* Headset insertion or removal */
{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
/* Audio short */
{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short",
IORESOURCE_IRQ,},
};
static struct resource battery_resources[] = {
......@@ -150,10 +152,14 @@ static struct resource battery_resources[] = {
static struct resource charger_resources[] = {
{PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAIL, PM8607_IRQ_CHG_FAIL, "charging timeout", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault", IORESOURCE_IRQ,},
{PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done",
IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAIL, PM8607_IRQ_CHG_FAIL, "charging timeout",
IORESOURCE_IRQ,},
{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging fault",
IORESOURCE_IRQ,},
{PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature",
IORESOURCE_IRQ,},
{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,},
};
......@@ -568,8 +574,8 @@ static struct irq_domain_ops pm860x_irq_domain_ops = {
static int device_irq_init(struct pm860x_chip *chip,
struct pm860x_platform_data *pdata)
{
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
: chip->companion;
struct i2c_client *i2c = (chip->id == CHIP_PM8607) ?
chip->client : chip->companion;
unsigned char status_buf[INT_STATUS_NUM];
unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
int data, mask, ret = -EINVAL;
......@@ -631,8 +637,8 @@ static int device_irq_init(struct pm860x_chip *chip,
if (!chip->core_irq)
goto out;
ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags | IRQF_ONESHOT,
"88pm860x", chip);
ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq,
flags | IRQF_ONESHOT, "88pm860x", chip);
if (ret) {
dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
chip->core_irq = 0;
......@@ -871,7 +877,7 @@ static void device_rtc_init(struct pm860x_chip *chip,
{
int ret;
if ((pdata == NULL))
if (!pdata)
return;
rtc_devs[0].platform_data = pdata->rtc;
......@@ -997,8 +1003,9 @@ static void device_8607_init(struct pm860x_chip *chip,
ret);
break;
default:
dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
"Chip ID: %02x\n", ret);
dev_err(chip->dev,
"Failed to detect Marvell 88PM8607. Chip ID: %02x\n",
ret);
goto out;
}
......@@ -1120,8 +1127,8 @@ static int pm860x_dt_init(struct device_node *np,
ret = of_property_read_u32(np, "marvell,88pm860x-slave-addr",
&pdata->companion_addr);
if (ret) {
dev_err(dev, "Not found \"marvell,88pm860x-slave-addr\" "
"property\n");
dev_err(dev,
"Not found \"marvell,88pm860x-slave-addr\" property\n");
pdata->companion_addr = 0;
}
return 0;
......
......@@ -2,7 +2,8 @@
* I2C driver for Marvell 88PM860x
*
* Copyright (C) 2009 Marvell International Ltd.
* Haojian Zhuang <haojian.zhuang@marvell.com>
*
* Author: Haojian Zhuang <haojian.zhuang@marvell.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
......
......@@ -13,7 +13,7 @@ config MFD_CORE
config MFD_CS5535
tristate "AMD CS5535 and CS5536 southbridge core functions"
select MFD_CORE
depends on PCI && X86
depends on PCI && (X86_32 || (X86 && COMPILE_TEST))
---help---
This is the core driver for CS5535/CS5536 MFD functions. This is
necessary for using the board's GPIO and MFGPT functionality.
......@@ -187,6 +187,7 @@ config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
select MFD_CORE
select REGMAP_IRQ
help
Enable support for the Freescale MC13783 and MC13892 PMICs.
This driver provides common support for accessing the device,
......@@ -253,6 +254,18 @@ config LPC_SCH
LPC bridge function of the Intel SCH provides support for
System Management Bus and General Purpose I/O.
config INTEL_SOC_PMIC
bool "Support for Intel Atom SoC PMIC"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
Select this option to enable support for the PMIC device
on some Intel SoC systems. The PMIC provides ADC, GPIO,
thermal, charger and related power management functions
on these systems.
config MFD_INTEL_MSIC
bool "Intel MSIC"
depends on INTEL_SCU_IPC
......@@ -367,14 +380,15 @@ config MFD_MAX14577
of the device.
config MFD_MAX77686
bool "Maxim Semiconductor MAX77686 PMIC Support"
bool "Maxim Semiconductor MAX77686/802 PMIC Support"
depends on I2C=y
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select IRQ_DOMAIN
help
Say yes here to add support for Maxim Semiconductor MAX77686.
This is a Power Management IC with RTC on chip.
Say yes here to add support for Maxim Semiconductor MAX77686 and
MAX77802 which are Power Management IC with an RTC 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.
......@@ -574,6 +588,7 @@ config MFD_SEC_CORE
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select REGULATOR
help
Support for the Samsung Electronics MFD series.
This driver provides common support for accessing the device,
......@@ -1057,7 +1072,7 @@ config MFD_LM3533
config MFD_TIMBERDALE
tristate "Timberdale FPGA"
select MFD_CORE
depends on PCI && GPIOLIB
depends on PCI && GPIOLIB && (X86_32 || COMPILE_TEST)
---help---
This is the core driver for the timberdale FPGA. This device is a
multifunction device which exposes numerous platform devices.
......
......@@ -115,7 +115,7 @@ 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_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
......@@ -169,3 +169,6 @@ obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
obj-$(CONFIG_MFD_STW481X) += stw481x.o
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
......@@ -303,7 +303,10 @@ static ssize_t aat2870_reg_write_file(struct file *file,
while (*start == ' ')
start++;
addr = simple_strtoul(start, &start, 16);
ret = kstrtoul(start, 16, &addr);
if (ret)
return ret;
if (addr >= AAT2870_REG_NUM) {
dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
return -EINVAL;
......
......@@ -91,8 +91,8 @@ static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
"write error (write register) "
"%d bytes transferred (expected 2)\n",
"write error (write register)\n"
" %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
......@@ -135,8 +135,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
err);
} else if (err != 2) {
dev_err(ab3100->dev,
"write error (write test register) "
"%d bytes transferred (expected 2)\n",
"write error (write test register)\n"
" %d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
......@@ -171,8 +171,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (send register address) "
"%d bytes transferred (expected 1)\n",
"write error (send register address)\n"
" %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
......@@ -189,8 +189,8 @@ static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (read register) "
"%d bytes transferred (expected 1)\n",
"write error (read register)\n"
" %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
......@@ -237,8 +237,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (send first register address) "
"%d bytes transferred (expected 1)\n",
"write error (send first register address)\n"
" %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_page_out_unlock;
......@@ -252,8 +252,8 @@ static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100,
goto get_reg_page_out_unlock;
} else if (err != numregs) {
dev_err(ab3100->dev,
"write error (read register page) "
"%d bytes transferred (expected %d)\n",
"write error (read register page)\n"
" %d bytes transferred (expected %d)\n",
err, numregs);
err = -EIO;
goto get_reg_page_out_unlock;
......@@ -295,8 +295,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (maskset send address) "
"%d bytes transferred (expected 1)\n",
"write error (maskset send address)\n"
" %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
......@@ -310,8 +310,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (maskset read register) "
"%d bytes transferred (expected 1)\n",
"write error (maskset read register)\n"
" %d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_maskset_unlock;
......@@ -330,8 +330,8 @@ static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100,
goto get_maskset_unlock;
} else if (err != 2) {
dev_err(ab3100->dev,
"write error (write register) "
"%d bytes transferred (expected 2)\n",
"write error (write register)\n"
" %d bytes transferred (expected 2)\n",
err);
err = -EIO;
goto get_maskset_unlock;
......@@ -371,7 +371,7 @@ EXPORT_SYMBOL(ab3100_event_register);
int ab3100_event_unregister(struct ab3100 *ab3100,
struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
return blocking_notifier_chain_unregister(&ab3100->event_subscribers,
nb);
}
EXPORT_SYMBOL(ab3100_event_unregister);
......@@ -455,7 +455,7 @@ static int ab3100_registers_print(struct seq_file *s, void *p)
u8 value;
u8 reg;
seq_printf(s, "AB3100 registers:\n");
seq_puts(s, "AB3100 registers:\n");
for (reg = 0; reg < 0xff; reg++) {
ab3100_get_register_interruptible(ab3100, reg, &value);
......@@ -560,8 +560,8 @@ static ssize_t ab3100_get_set_reg(struct file *file,
ab3100_get_register_interruptible(ab3100, user_reg, &regvalue);
dev_info(ab3100->dev,
"debug write reg[0x%02x] with 0x%02x, "
"after readback: 0x%02x\n",
"debug write reg[0x%02x]\n"
" with 0x%02x, after readback: 0x%02x\n",
user_reg, user_value, regvalue);
}
return buf_size;
......@@ -719,8 +719,7 @@ static int ab3100_setup(struct ab3100 *ab3100)
*/
if (ab3100->chip_id == 0xc4) {
dev_warn(ab3100->dev,
"AB3100 P1E variant detected, "
"forcing chip to 32KHz\n");
"AB3100 P1E variant detected forcing chip to 32KHz\n");
err = ab3100_set_test_register_interruptible(ab3100,
0x02, 0x08);
}
......@@ -878,8 +877,7 @@ static int ab3100_probe(struct i2c_client *client,
&ab3100->chip_id);
if (err) {
dev_err(&client->dev,
"could not communicate with the AB3100 analog "
"baseband chip\n");
"failed to communicate with AB3100 chip\n");
goto exit_no_detect;
}
......@@ -902,8 +900,8 @@ static int ab3100_probe(struct i2c_client *client,
if (ids[i].id == 0x0) {
dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
ab3100->chip_id);
dev_err(&client->dev, "accepting it anyway. Please update "
"the driver.\n");
dev_err(&client->dev,
"accepting it anyway. Please update the driver.\n");
goto exit_no_detect;
}
......
......@@ -148,8 +148,8 @@ static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
/* AB8540 support */
static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23,
25, 26, 27, 28, 29, 30, 31,
0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
23, 25, 26, 27, 28, 29, 30, 31,
};
static const char ab8500_version_str[][7] = {
......@@ -322,7 +322,7 @@ static int ab8500_mask_and_set_register(struct device *dev,
struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
atomic_inc(&ab8500->transfer_ongoing);
ret= mask_and_set_register_interruptible(ab8500, bank, reg,
ret = mask_and_set_register_interruptible(ab8500, bank, reg,
bitmask, bitvalues);
atomic_dec(&ab8500->transfer_ongoing);
return ret;
......@@ -415,9 +415,11 @@ static void ab8500_irq_unmask(struct irq_data *data)
if (type & IRQ_TYPE_EDGE_FALLING) {
if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
ab8500->mask[index + 2] &= ~mask;
else if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
else if (offset >= AB9540_INT_GPIO50R &&
offset <= AB9540_INT_GPIO54R)
ab8500->mask[index + 1] &= ~mask;
else if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
else if (offset == AB8540_INT_GPIO43R ||
offset == AB8540_INT_GPIO44R)
/* Here the falling IRQ is one bit lower */
ab8500->mask[index] &= ~(mask << 1);
else
......@@ -451,7 +453,7 @@ static void update_latch_offset(u8 *offset, int i)
/* Fix inconsistent ab8540 bit mapping... */
if (unlikely(*offset == 16))
*offset = 25;
if ((i==3) && (*offset >= 24))
if ((i == 3) && (*offset >= 24))
*offset += 2;
}
......@@ -573,8 +575,8 @@ static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
}
static struct irq_domain_ops ab8500_irq_ops = {
.map = ab8500_irq_map,
.xlate = irq_domain_xlate_twocell,
.map = ab8500_irq_map,
.xlate = irq_domain_xlate_twocell,
};
static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
......@@ -607,8 +609,8 @@ int ab8500_suspend(struct ab8500 *ab8500)
{
if (atomic_read(&ab8500->transfer_ongoing))
return -EINVAL;
else
return 0;
return 0;
}
static struct resource ab8500_gpadc_resources[] = {
......@@ -1551,7 +1553,7 @@ static struct attribute_group ab9540_attr_group = {
static int ab8500_probe(struct platform_device *pdev)
{
static char *switch_off_status[] = {
static const char *switch_off_status[] = {
"Swoff bit programming",
"Thermal protection activation",
"Vbat lower then BattOk falling threshold",
......@@ -1560,7 +1562,7 @@ static int ab8500_probe(struct platform_device *pdev)
"Battery level lower than power on reset threshold",
"Power on key 1 pressed longer than 10 seconds",
"DB8500 thermal shutdown"};
static char *turn_on_status[] = {
static const char *turn_on_status[] = {
"Battery rising (Vbat)",
"Power On Key 1 dbF",
"Power On Key 2 dbF",
......@@ -1579,7 +1581,7 @@ static int ab8500_probe(struct platform_device *pdev)
int i;
u8 value;
ab8500 = devm_kzalloc(&pdev->dev, sizeof *ab8500, GFP_KERNEL);
ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
if (!ab8500)
return -ENOMEM;
......@@ -1636,7 +1638,7 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->mask_size = AB8540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab8540_irq_regoffset;
ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
}/* Configure AB8500 or AB9540 IRQ */
} /* Configure AB8500 or AB9540 IRQ */
else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
ab8500->mask_size = AB9540_NUM_IRQ_REGS;
ab8500->irq_reg_offset = ab9540_irq_regoffset;
......@@ -1646,10 +1648,12 @@ static int ab8500_probe(struct platform_device *pdev)
ab8500->irq_reg_offset = ab8500_irq_regoffset;
ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
}
ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
GFP_KERNEL);
if (!ab8500->mask)
return -ENOMEM;
ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size, GFP_KERNEL);
ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
GFP_KERNEL);
if (!ab8500->oldmask)
return -ENOMEM;
......@@ -1674,14 +1678,13 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
if (value & 1)
printk(KERN_CONT " \"%s\"",
switch_off_status[i]);
pr_cont(" \"%s\"", switch_off_status[i]);
value = value >> 1;
}
printk(KERN_CONT "\n");
pr_cont("\n");
} else {
printk(KERN_CONT " None\n");
pr_cont(" None\n");
}
ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
AB8500_TURN_ON_STATUS, &value);
......@@ -1692,12 +1695,12 @@ static int ab8500_probe(struct platform_device *pdev)
if (value) {
for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
if (value & 1)
printk("\"%s\" ", turn_on_status[i]);
pr_cont("\"%s\" ", turn_on_status[i]);
value = value >> 1;
}
printk("\n");
pr_cont("\n");
} else {
printk("None\n");
pr_cont("None\n");
}
if (plat && plat->init)
......
This diff is collapsed.
......@@ -123,6 +123,8 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
dev_err(arizona->dev, "AIF2 underclocked\n");
if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
dev_err(arizona->dev, "AIF1 underclocked\n");
if (val & ARIZONA_ISRC3_UNDERCLOCKED_STS)
dev_err(arizona->dev, "ISRC3 underclocked\n");
if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 underclocked\n");
if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS)
......@@ -192,6 +194,8 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
dev_err(arizona->dev, "ASRC sync WARP overclocked\n");
if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS)
dev_err(arizona->dev, "DSP1 overclocked\n");
if (val[1] & ARIZONA_ISRC3_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC3 overclocked\n");
if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS)
dev_err(arizona->dev, "ISRC2 overclocked\n");
if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS)
......@@ -497,12 +501,12 @@ const struct dev_pm_ops arizona_pm_ops = {
EXPORT_SYMBOL_GPL(arizona_pm_ops);
#ifdef CONFIG_OF
int arizona_of_get_type(struct device *dev)
unsigned long arizona_of_get_type(struct device *dev)
{
const struct of_device_id *id = of_match_device(arizona_of_match, dev);
if (id)
return (int)id->data;
return (unsigned long)id->data;
else
return 0;
}
......@@ -578,17 +582,21 @@ static const struct mfd_cell early_devs[] = {
};
static const char *wm5102_supplies[] = {
"MICVDD",
"DBVDD2",
"DBVDD3",
"CPVDD",
"SPKVDDL",
"SPKVDDR",
"MICVDD",
};
static const struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
......@@ -601,7 +609,11 @@ static const struct mfd_cell wm5102_devs[] = {
static const struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{
.name = "arizona-extcon",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
......@@ -613,6 +625,7 @@ static const struct mfd_cell wm5110_devs[] = {
};
static const char *wm8997_supplies[] = {
"MICVDD",
"DBVDD2",
"CPVDD",
"SPKVDD",
......@@ -620,7 +633,11 @@ static const char *wm8997_supplies[] = {
static const struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{
.name = "arizona-extcon",
.parent_supplies = wm8997_supplies,
.num_parent_supplies = 1, /* We only need MICVDD */
},
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
......@@ -683,7 +700,13 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early;
}
arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD");
/**
* Don't use devres here because the only device we have to get
* against is the MFD device and DCVDD will likely be supplied by
* one of its children. Meaning that the regulator will be
* destroyed by the time devres calls regulator put.
*/
arizona->dcvdd = regulator_get(arizona->dev, "DCVDD");
if (IS_ERR(arizona->dcvdd)) {
ret = PTR_ERR(arizona->dcvdd);
dev_err(dev, "Failed to request DCVDD: %d\n", ret);
......@@ -697,7 +720,7 @@ int arizona_dev_init(struct arizona *arizona)
"arizona /RESET");
if (ret != 0) {
dev_err(dev, "Failed to request /RESET: %d\n", ret);
goto err_early;
goto err_dcvdd;
}
}
......@@ -706,7 +729,7 @@ int arizona_dev_init(struct arizona *arizona)
if (ret != 0) {
dev_err(dev, "Failed to enable core supplies: %d\n",
ret);
goto err_early;
goto err_dcvdd;
}
ret = regulator_enable(arizona->dcvdd);
......@@ -1015,6 +1038,8 @@ int arizona_dev_init(struct arizona *arizona)
err_enable:
regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
err_dcvdd:
regulator_put(arizona->dcvdd);
err_early:
mfd_remove_devices(dev);
return ret;
......@@ -1023,16 +1048,20 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
int arizona_dev_exit(struct arizona *arizona)
{
pm_runtime_disable(arizona->dev);
regulator_disable(arizona->dcvdd);
regulator_put(arizona->dcvdd);
mfd_remove_devices(arizona->dev);
arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona);
pm_runtime_disable(arizona->dev);
arizona_irq_exit(arizona);
if (arizona->pdata.reset)
gpio_set_value_cansleep(arizona->pdata.reset, 0);
regulator_disable(arizona->dcvdd);
regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies),
regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
return 0;
}
......
......@@ -24,11 +24,12 @@
#include "arizona.h"
static int arizona_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
const struct i2c_device_id *id)
{
struct arizona *arizona;
const struct regmap_config *regmap_config;
int ret, type;
unsigned long type;
int ret;
if (i2c->dev.of_node)
type = arizona_of_get_type(&i2c->dev);
......
......@@ -188,24 +188,33 @@ int arizona_irq_init(struct arizona *arizona)
int flags = IRQF_ONESHOT;
int ret, i;
const struct regmap_irq_chip *aod, *irq;
bool ctrlif_error = true;
struct irq_data *irq_data;
arizona->ctrlif_error = true;
switch (arizona->type) {
#ifdef CONFIG_MFD_WM5102
case WM5102:
aod = &wm5102_aod;
irq = &wm5102_irq;
ctrlif_error = false;
arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM5110
case WM5110:
aod = &wm5110_aod;
irq = &wm5110_irq;
ctrlif_error = false;
switch (arizona->rev) {
case 0 ... 2:
irq = &wm5110_irq;
break;
default:
irq = &wm5110_revd_irq;
break;
}
arizona->ctrlif_error = false;
break;
#endif
#ifdef CONFIG_MFD_WM8997
......@@ -213,7 +222,7 @@ int arizona_irq_init(struct arizona *arizona)
aod = &wm8997_aod;
irq = &wm8997_irq;
ctrlif_error = false;
arizona->ctrlif_error = false;
break;
#endif
default:
......@@ -300,7 +309,7 @@ int arizona_irq_init(struct arizona *arizona)
}
/* Handle control interface errors in the core */
if (ctrlif_error) {
if (arizona->ctrlif_error) {
i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
IRQF_ONESHOT,
......@@ -345,7 +354,9 @@ int arizona_irq_init(struct arizona *arizona)
return 0;
err_main_irq:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
if (arizona->ctrlif_error)
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
arizona);
err_ctrlif:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
err_boot_done:
......@@ -361,7 +372,9 @@ int arizona_irq_init(struct arizona *arizona)
int arizona_irq_exit(struct arizona *arizona)
{
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
if (arizona->ctrlif_error)
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
arizona);
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
arizona->irq_chip);
......
......@@ -28,7 +28,8 @@ static int arizona_spi_probe(struct spi_device *spi)
const struct spi_device_id *id = spi_get_device_id(spi);
struct arizona *arizona;
const struct regmap_config *regmap_config;
int ret, type;
unsigned long type;
int ret;
if (spi->dev.of_node)
type = arizona_of_get_type(&spi->dev);
......
......@@ -36,6 +36,7 @@ extern const struct regmap_irq_chip wm5102_irq;
extern const struct regmap_irq_chip wm5110_aod;
extern const struct regmap_irq_chip wm5110_irq;
extern const struct regmap_irq_chip wm5110_revd_irq;
extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq;
......@@ -46,9 +47,9 @@ int arizona_irq_init(struct arizona *arizona);
int arizona_irq_exit(struct arizona *arizona);
#ifdef CONFIG_OF
int arizona_of_get_type(struct device *dev);
unsigned long arizona_of_get_type(struct device *dev);
#else
static inline int arizona_of_get_type(struct device *dev)
static inline unsigned long arizona_of_get_type(struct device *dev)
{
return 0;
}
......
......@@ -899,13 +899,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
ds1wm_resources[0].end >>= asic->bus_shift;
/* MMC */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
if (mem_sdio) {
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start,
ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
if (!asic->tmio_cnf) {
ret = -ENOMEM;
dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
goto out;
if (!asic->tmio_cnf) {
ret = -ENOMEM;
dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
goto out;
}
}
asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift;
......
......@@ -25,64 +25,42 @@
#include <linux/mfd/cros_ec_commands.h>
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
struct cros_ec_msg *msg)
struct cros_ec_command *msg)
{
uint8_t *out;
int csum, i;
BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
out = ec_dev->dout;
out[0] = EC_CMD_VERSION0 + msg->version;
out[1] = msg->cmd;
out[2] = msg->out_len;
out[1] = msg->command;
out[2] = msg->outsize;
csum = out[0] + out[1] + out[2];
for (i = 0; i < msg->out_len; i++)
csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->out_buf[i];
out[EC_MSG_TX_HEADER_BYTES + msg->out_len] = (uint8_t)(csum & 0xff);
for (i = 0; i < msg->outsize; i++)
csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->outdata[i];
out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff);
return EC_MSG_TX_PROTO_BYTES + msg->out_len;
return EC_MSG_TX_PROTO_BYTES + msg->outsize;
}
EXPORT_SYMBOL(cros_ec_prepare_tx);
static int cros_ec_command_sendrecv(struct cros_ec_device *ec_dev,
uint16_t cmd, void *out_buf, int out_len,
void *in_buf, int in_len)
int cros_ec_check_result(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg)
{
struct cros_ec_msg msg;
msg.version = cmd >> 8;
msg.cmd = cmd & 0xff;
msg.out_buf = out_buf;
msg.out_len = out_len;
msg.in_buf = in_buf;
msg.in_len = in_len;
return ec_dev->command_xfer(ec_dev, &msg);
}
static int cros_ec_command_recv(struct cros_ec_device *ec_dev,
uint16_t cmd, void *buf, int buf_len)
{
return cros_ec_command_sendrecv(ec_dev, cmd, NULL, 0, buf, buf_len);
}
static int cros_ec_command_send(struct cros_ec_device *ec_dev,
uint16_t cmd, void *buf, int buf_len)
{
return cros_ec_command_sendrecv(ec_dev, cmd, buf, buf_len, NULL, 0);
}
static irqreturn_t ec_irq_thread(int irq, void *data)
{
struct cros_ec_device *ec_dev = data;
if (device_may_wakeup(ec_dev->dev))
pm_wakeup_event(ec_dev->dev, 0);
blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
return IRQ_HANDLED;
switch (msg->result) {
case EC_RES_SUCCESS:
return 0;
case EC_RES_IN_PROGRESS:
dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
msg->command);
return -EAGAIN;
default:
dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
msg->command, msg->result);
return 0;
}
}
EXPORT_SYMBOL(cros_ec_check_result);
static const struct mfd_cell cros_devs[] = {
{
......@@ -102,12 +80,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
struct device *dev = ec_dev->dev;
int err = 0;
BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
ec_dev->command_send = cros_ec_command_send;
ec_dev->command_recv = cros_ec_command_recv;
ec_dev->command_sendrecv = cros_ec_command_sendrecv;
if (ec_dev->din_size) {
ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
if (!ec_dev->din)
......@@ -119,42 +91,23 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return -ENOMEM;
}
if (!ec_dev->irq) {
dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
return err;
}
err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev);
if (err) {
dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
return err;
}
err = mfd_add_devices(dev, 0, cros_devs,
ARRAY_SIZE(cros_devs),
NULL, ec_dev->irq, NULL);
if (err) {
dev_err(dev, "failed to add mfd devices\n");
goto fail_mfd;
return err;
}
dev_info(dev, "Chrome EC (%s)\n", ec_dev->name);
dev_info(dev, "Chrome EC device registered\n");
return 0;
fail_mfd:
free_irq(ec_dev->irq, ec_dev);
return err;
}
EXPORT_SYMBOL(cros_ec_register);
int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
free_irq(ec_dev->irq, ec_dev);
return 0;
}
......
......@@ -29,12 +29,13 @@ static inline struct cros_ec_device *to_ec_dev(struct device *dev)
return i2c_get_clientdata(client);
}
static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
struct cros_ec_msg *msg)
static int cros_ec_cmd_xfer_i2c(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg)
{
struct i2c_client *client = ec_dev->priv;
int ret = -ENOMEM;
int i;
int len;
int packet_len;
u8 *out_buf = NULL;
u8 *in_buf = NULL;
......@@ -50,7 +51,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one byte for
* length, and one for result code)
*/
packet_len = msg->in_len + 3;
packet_len = msg->insize + 3;
in_buf = kzalloc(packet_len, GFP_KERNEL);
if (!in_buf)
goto done;
......@@ -61,7 +62,7 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
* allocate larger packet (one byte for checksum, one for
* command code, one for length, and one for command version)
*/
packet_len = msg->out_len + 4;
packet_len = msg->outsize + 4;
out_buf = kzalloc(packet_len, GFP_KERNEL);
if (!out_buf)
goto done;
......@@ -69,16 +70,16 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
i2c_msg[0].buf = (char *)out_buf;
out_buf[0] = EC_CMD_VERSION0 + msg->version;
out_buf[1] = msg->cmd;
out_buf[2] = msg->out_len;
out_buf[1] = msg->command;
out_buf[2] = msg->outsize;
/* copy message payload and compute checksum */
sum = out_buf[0] + out_buf[1] + out_buf[2];
for (i = 0; i < msg->out_len; i++) {
out_buf[3 + i] = msg->out_buf[i];
for (i = 0; i < msg->outsize; i++) {
out_buf[3 + i] = msg->outdata[i];
sum += out_buf[3 + i];
}
out_buf[3 + msg->out_len] = sum;
out_buf[3 + msg->outsize] = sum;
/* send command to EC and read answer */
ret = i2c_transfer(client->adapter, i2c_msg, 2);
......@@ -92,28 +93,34 @@ static int cros_ec_command_xfer(struct cros_ec_device *ec_dev,
}
/* check response error code */
if (i2c_msg[1].buf[0]) {
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
msg->cmd, i2c_msg[1].buf[0]);
ret = -EINVAL;
msg->result = i2c_msg[1].buf[0];
ret = cros_ec_check_result(ec_dev, msg);
if (ret)
goto done;
len = in_buf[1];
if (len > msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
len, msg->insize);
ret = -ENOSPC;
goto done;
}
/* copy response packet payload and compute checksum */
sum = in_buf[0] + in_buf[1];
for (i = 0; i < msg->in_len; i++) {
msg->in_buf[i] = in_buf[2 + i];
for (i = 0; i < len; i++) {
msg->indata[i] = in_buf[2 + i];
sum += in_buf[2 + i];
}
dev_dbg(ec_dev->dev, "packet: %*ph, sum = %02x\n",
i2c_msg[1].len, in_buf, sum);
if (sum != in_buf[2 + msg->in_len]) {
if (sum != in_buf[2 + len]) {
dev_err(ec_dev->dev, "bad packet checksum\n");
ret = -EBADMSG;
goto done;
}
ret = 0;
ret = len;
done:
kfree(in_buf);
kfree(out_buf);
......@@ -132,11 +139,10 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, ec_dev);
ec_dev->name = "I2C";
ec_dev->dev = dev;
ec_dev->priv = client;
ec_dev->irq = client->irq;
ec_dev->command_xfer = cros_ec_command_xfer;
ec_dev->cmd_xfer = cros_ec_cmd_xfer_i2c;
ec_dev->ec_name = client->name;
ec_dev->phys_name = client->adapter->name;
ec_dev->parent = &client->dev;
......
......@@ -73,7 +73,7 @@
* 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.
* @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
* @lock: mutex to ensure only one user of cros_ec_cmd_xfer_spi at a time
*/
struct cros_ec_spi {
struct spi_device *spi;
......@@ -210,13 +210,13 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
}
/**
* cros_ec_command_spi_xfer - Transfer a message over SPI and receive the reply
* cros_ec_cmd_xfer_spi - Transfer a message over SPI and receive the reply
*
* @ec_dev: ChromeOS EC device
* @ec_msg: Message to transfer
*/
static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
struct cros_ec_msg *ec_msg)
static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
struct cros_ec_command *ec_msg)
{
struct cros_ec_spi *ec_spi = ec_dev->priv;
struct spi_transfer trans;
......@@ -258,23 +258,19 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* Get the response */
if (!ret) {
ret = cros_ec_spi_receive_response(ec_dev,
ec_msg->in_len + EC_MSG_TX_PROTO_BYTES);
ec_msg->insize + EC_MSG_TX_PROTO_BYTES);
} else {
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
}
/* turn off CS */
/*
* Turn off CS, possibly adding a delay to ensure the rising edge
* doesn't come too soon after the end of the data.
*/
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);
}
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);
ec_spi->last_transfer_ns = ktime_get_ns();
......@@ -285,20 +281,19 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
/* check response error code */
ptr = ec_dev->din;
if (ptr[0]) {
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
ec_msg->cmd, ptr[0]);
debug_packet(ec_dev->dev, "in_err", ptr, len);
ret = -EINVAL;
/* check response error code */
ec_msg->result = ptr[0];
ret = cros_ec_check_result(ec_dev, ec_msg);
if (ret)
goto exit;
}
len = ptr[1];
sum = ptr[0] + ptr[1];
if (len > ec_msg->in_len) {
if (len > ec_msg->insize) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
len, ec_msg->in_len);
len, ec_msg->insize);
ret = -ENOSPC;
goto exit;
}
......@@ -306,8 +301,8 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
/* copy response packet payload and compute checksum */
for (i = 0; i < len; i++) {
sum += ptr[i + 2];
if (ec_msg->in_len)
ec_msg->in_buf[i] = ptr[i + 2];
if (ec_msg->insize)
ec_msg->indata[i] = ptr[i + 2];
}
sum &= 0xff;
......@@ -321,7 +316,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
goto exit;
}
ret = 0;
ret = len;
exit:
mutex_unlock(&ec_spi->lock);
return ret;
......@@ -364,11 +359,10 @@ static int cros_ec_spi_probe(struct spi_device *spi)
cros_ec_spi_dt_probe(ec_spi, dev);
spi_set_drvdata(spi, ec_dev);
ec_dev->name = "SPI";
ec_dev->dev = dev;
ec_dev->priv = ec_spi;
ec_dev->irq = spi->irq;
ec_dev->command_xfer = cros_ec_command_spi_xfer;
ec_dev->cmd_xfer = cros_ec_cmd_xfer_spi;
ec_dev->ec_name = ec_spi->spi->modalias;
ec_dev->phys_name = dev_name(&ec_spi->spi->dev);
ec_dev->parent = &ec_spi->spi->dev;
......@@ -381,6 +375,8 @@ static int cros_ec_spi_probe(struct spi_device *spi)
return err;
}
device_init_wakeup(&spi->dev, true);
return 0;
}
......
......@@ -153,9 +153,9 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
"Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
model, variant_id);
if (variant_code != PMIC_DA9063_BB) {
dev_err(da9063->dev, "Unknown chip variant code: 0x%02X\n",
variant_code);
if (variant_code < PMIC_DA9063_BB && variant_code != PMIC_DA9063_AD) {
dev_err(da9063->dev,
"Cannot support variant code: 0x%02X\n", variant_code);
return -ENODEV;
}
......
......@@ -25,10 +25,10 @@
#include <linux/mfd/da9063/pdata.h>
#include <linux/mfd/da9063/registers.h>
static const struct regmap_range da9063_readable_ranges[] = {
static const struct regmap_range da9063_ad_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_SECOND_D,
.range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
......@@ -37,14 +37,14 @@ static const struct regmap_range da9063_readable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
.range_max = DA9063_REG_GP_ID_19,
.range_max = DA9063_AD_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};
static const struct regmap_range da9063_writeable_ranges[] = {
static const struct regmap_range da9063_ad_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
......@@ -53,7 +53,7 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
.range_max = DA9063_REG_ALARM_Y,
.range_max = DA9063_AD_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
......@@ -62,14 +62,14 @@ static const struct regmap_range da9063_writeable_ranges[] = {
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
.range_max = DA9063_REG_MON_REG_4,
.range_max = DA9063_AD_REG_MON_REG_4,
}, {
.range_min = DA9063_REG_GP_ID_0,
.range_max = DA9063_REG_GP_ID_19,
.range_min = DA9063_AD_REG_GP_ID_0,
.range_max = DA9063_AD_REG_GP_ID_19,
},
};
static const struct regmap_range da9063_volatile_ranges[] = {
static const struct regmap_range da9063_ad_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
......@@ -81,26 +81,104 @@ static const struct regmap_range da9063_volatile_ranges[] = {
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
.range_max = DA9063_REG_SECOND_D,
.range_max = DA9063_AD_REG_SECOND_D,
}, {
.range_min = DA9063_REG_MON_REG_5,
.range_max = DA9063_REG_MON_REG_6,
.range_min = DA9063_AD_REG_MON_REG_5,
.range_max = DA9063_AD_REG_MON_REG_6,
},
};
static const struct regmap_access_table da9063_readable_table = {
.yes_ranges = da9063_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_readable_ranges),
static const struct regmap_access_table da9063_ad_readable_table = {
.yes_ranges = da9063_ad_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
};
static const struct regmap_access_table da9063_writeable_table = {
.yes_ranges = da9063_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_writeable_ranges),
static const struct regmap_access_table da9063_ad_writeable_table = {
.yes_ranges = da9063_ad_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
};
static const struct regmap_access_table da9063_volatile_table = {
.yes_ranges = da9063_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_volatile_ranges),
static const struct regmap_access_table da9063_ad_volatile_table = {
.yes_ranges = da9063_ad_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
};
static const struct regmap_range da9063_bb_readable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_BB_REG_SECOND_D,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
}, {
.range_min = DA9063_REG_SEQ_A,
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_T_OFFSET,
.range_max = DA9063_BB_REG_GP_ID_19,
}, {
.range_min = DA9063_REG_CHIP_ID,
.range_max = DA9063_REG_CHIP_VARIANT,
},
};
static const struct regmap_range da9063_bb_writeable_ranges[] = {
{
.range_min = DA9063_REG_PAGE_CON,
.range_max = DA9063_REG_PAGE_CON,
}, {
.range_min = DA9063_REG_FAULT_LOG,
.range_max = DA9063_REG_VSYS_MON,
}, {
.range_min = DA9063_REG_COUNT_S,
.range_max = DA9063_BB_REG_ALARM_Y,
}, {
.range_min = DA9063_REG_SEQ,
.range_max = DA9063_REG_ID_32_31,
}, {
.range_min = DA9063_REG_SEQ_A,
.range_max = DA9063_REG_AUTO3_LOW,
}, {
.range_min = DA9063_REG_CONFIG_I,
.range_max = DA9063_BB_REG_MON_REG_4,
}, {
.range_min = DA9063_BB_REG_GP_ID_0,
.range_max = DA9063_BB_REG_GP_ID_19,
},
};
static const struct regmap_range da9063_bb_volatile_ranges[] = {
{
.range_min = DA9063_REG_STATUS_A,
.range_max = DA9063_REG_EVENT_D,
}, {
.range_min = DA9063_REG_CONTROL_F,
.range_max = DA9063_REG_CONTROL_F,
}, {
.range_min = DA9063_REG_ADC_MAN,
.range_max = DA9063_REG_ADC_MAN,
}, {
.range_min = DA9063_REG_ADC_RES_L,
.range_max = DA9063_BB_REG_SECOND_D,
}, {
.range_min = DA9063_BB_REG_MON_REG_5,
.range_max = DA9063_BB_REG_MON_REG_6,
},
};
static const struct regmap_access_table da9063_bb_readable_table = {
.yes_ranges = da9063_bb_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
};
static const struct regmap_access_table da9063_bb_writeable_table = {
.yes_ranges = da9063_bb_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
};
static const struct regmap_access_table da9063_bb_volatile_table = {
.yes_ranges = da9063_bb_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
};
static const struct regmap_range_cfg da9063_range_cfg[] = {
......@@ -123,10 +201,6 @@ static struct regmap_config da9063_regmap_config = {
.max_register = DA9063_REG_CHIP_VARIANT,
.cache_type = REGCACHE_RBTREE,
.rd_table = &da9063_readable_table,
.wr_table = &da9063_writeable_table,
.volatile_table = &da9063_volatile_table,
};
static int da9063_i2c_probe(struct i2c_client *i2c,
......@@ -143,6 +217,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
da9063->dev = &i2c->dev;
da9063->chip_irq = i2c->irq;
if (da9063->variant_code == PMIC_DA9063_AD) {
da9063_regmap_config.rd_table = &da9063_ad_readable_table;
da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
} else {
da9063_regmap_config.rd_table = &da9063_bb_readable_table;
da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
}
da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
if (IS_ERR(da9063->regmap)) {
ret = PTR_ERR(da9063->regmap);
......
......@@ -95,7 +95,7 @@ EXPORT_SYMBOL(dm355evm_msp_read);
* Many of the msp430 pins are just used as fixed-direction GPIOs.
* We could export a few more of them this way, if we wanted.
*/
#define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
#define MSP_GPIO(bit, reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
static const u8 msp_gpios[] = {
/* eight leds */
......
......@@ -62,7 +62,7 @@ static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data)
struct spi_message m;
int status;
memset(&t, 0, sizeof t);
memset(&t, 0, sizeof(t));
spi_message_init(&m);
t.len = sizeof(u32);
spi_message_add_tail(&t, &m);
......@@ -211,7 +211,6 @@ static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
desc->irq_data.chip->irq_ack(&desc->irq_data);
queue_work(pcap->workqueue, &pcap->isr_work);
return;
}
/* ADC */
......
......@@ -332,18 +332,13 @@ static int htcpld_setup_chip_irq(
int chip_index)
{
struct htcpld_data *htcpld;
struct device *dev = &pdev->dev;
struct htcpld_core_platform_data *pdata;
struct htcpld_chip *chip;
struct htcpld_chip_platform_data *plat_chip_data;
unsigned int irq, irq_end;
int ret = 0;
/* Get the platform and driver data */
pdata = dev_get_platdata(dev);
htcpld = platform_get_drvdata(pdev);
chip = &htcpld->chip[chip_index];
plat_chip_data = &pdata->chip[chip_index];
/* Setup irq handlers */
irq_end = chip->irq_start + chip->nirqs;
......
/*
* intel_soc_pmic_core.c - Intel SoC PMIC MFD Driver
*
* Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Yang, Bin <bin.yang@intel.com>
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
*/
#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
#include <linux/regmap.h>
#include <linux/mfd/intel_soc_pmic.h>
#include "intel_soc_pmic_core.h"
/*
* On some boards the PMIC interrupt may come from a GPIO line.
* Try to lookup the ACPI table and see if such connection exists. If not,
* return -ENOENT and use the IRQ provided by I2C.
*/
static int intel_soc_pmic_find_gpio_irq(struct device *dev)
{
struct gpio_desc *desc;
int irq;
desc = devm_gpiod_get_index(dev, "intel_soc_pmic", 0);
if (IS_ERR(desc))
return -ENOENT;
irq = gpiod_to_irq(desc);
if (irq < 0)
dev_warn(dev, "Can't get irq: %d\n", irq);
return irq;
}
static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id)
{
struct device *dev = &i2c->dev;
const struct acpi_device_id *id;
struct intel_soc_pmic_config *config;
struct intel_soc_pmic *pmic;
int ret;
int irq;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id || !id->driver_data)
return -ENODEV;
config = (struct intel_soc_pmic_config *)id->driver_data;
pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
dev_set_drvdata(dev, pmic);
pmic->regmap = devm_regmap_init_i2c(i2c, config->regmap_config);
irq = intel_soc_pmic_find_gpio_irq(dev);
pmic->irq = (irq < 0) ? i2c->irq : irq;
ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
config->irq_flags | IRQF_ONESHOT,
0, config->irq_chip,
&pmic->irq_chip_data);
if (ret)
return ret;
ret = enable_irq_wake(pmic->irq);
if (ret)
dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret);
ret = mfd_add_devices(dev, -1, config->cell_dev,
config->n_cell_devs, NULL, 0,
regmap_irq_get_domain(pmic->irq_chip_data));
if (ret)
goto err_del_irq_chip;
return 0;
err_del_irq_chip:
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
return ret;
}
static int intel_soc_pmic_i2c_remove(struct i2c_client *i2c)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
mfd_remove_devices(&i2c->dev);
return 0;
}
static void intel_soc_pmic_shutdown(struct i2c_client *i2c)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev);
disable_irq(pmic->irq);
return;
}
static int intel_soc_pmic_suspend(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
disable_irq(pmic->irq);
return 0;
}
static int intel_soc_pmic_resume(struct device *dev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
enable_irq(pmic->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(intel_soc_pmic_pm_ops, intel_soc_pmic_suspend,
intel_soc_pmic_resume);
static const struct i2c_device_id intel_soc_pmic_i2c_id[] = {
{ }
};
MODULE_DEVICE_TABLE(i2c, intel_soc_pmic_i2c_id);
#if defined(CONFIG_ACPI)
static struct acpi_device_id intel_soc_pmic_acpi_match[] = {
{"INT33FD", (kernel_ulong_t)&intel_soc_pmic_config_crc},
{ },
};
MODULE_DEVICE_TABLE(acpi, intel_soc_pmic_acpi_match);
#endif
static struct i2c_driver intel_soc_pmic_i2c_driver = {
.driver = {
.name = "intel_soc_pmic_i2c",
.owner = THIS_MODULE,
.pm = &intel_soc_pmic_pm_ops,
.acpi_match_table = ACPI_PTR(intel_soc_pmic_acpi_match),
},
.probe = intel_soc_pmic_i2c_probe,
.remove = intel_soc_pmic_i2c_remove,
.id_table = intel_soc_pmic_i2c_id,
.shutdown = intel_soc_pmic_shutdown,
};
module_i2c_driver(intel_soc_pmic_i2c_driver);
MODULE_DESCRIPTION("I2C driver for Intel SoC PMIC");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Yang, Bin <bin.yang@intel.com>");
MODULE_AUTHOR("Zhu, Lejun <lejun.zhu@linux.intel.com>");
/*
* intel_soc_pmic_core.h - Intel SoC PMIC MFD Driver
*
* Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Yang, Bin <bin.yang@intel.com>
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
*/
#ifndef __INTEL_SOC_PMIC_CORE_H__
#define __INTEL_SOC_PMIC_CORE_H__
struct intel_soc_pmic_config {
unsigned long irq_flags;
struct mfd_cell *cell_dev;
int n_cell_devs;
struct regmap_config *regmap_config;
struct regmap_irq_chip *irq_chip;
};
extern struct intel_soc_pmic_config intel_soc_pmic_config_crc;
#endif /* __INTEL_SOC_PMIC_CORE_H__ */
/*
* intel_soc_pmic_crc.c - Device access for Crystal Cove PMIC
*
* Copyright (C) 2013, 2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Yang, Bin <bin.yang@intel.com>
* Author: Zhu, Lejun <lejun.zhu@linux.intel.com>
*/
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/regmap.h>
#include <linux/mfd/intel_soc_pmic.h>
#include "intel_soc_pmic_core.h"
#define CRYSTAL_COVE_MAX_REGISTER 0xC6
#define CRYSTAL_COVE_REG_IRQLVL1 0x02
#define CRYSTAL_COVE_REG_MIRQLVL1 0x0E
#define CRYSTAL_COVE_IRQ_PWRSRC 0
#define CRYSTAL_COVE_IRQ_THRM 1
#define CRYSTAL_COVE_IRQ_BCU 2
#define CRYSTAL_COVE_IRQ_ADC 3
#define CRYSTAL_COVE_IRQ_CHGR 4
#define CRYSTAL_COVE_IRQ_GPIO 5
#define CRYSTAL_COVE_IRQ_VHDMIOCP 6
static struct resource gpio_resources[] = {
{
.name = "GPIO",
.start = CRYSTAL_COVE_IRQ_GPIO,
.end = CRYSTAL_COVE_IRQ_GPIO,
.flags = IORESOURCE_IRQ,
},
};
static struct resource pwrsrc_resources[] = {
{
.name = "PWRSRC",
.start = CRYSTAL_COVE_IRQ_PWRSRC,
.end = CRYSTAL_COVE_IRQ_PWRSRC,
.flags = IORESOURCE_IRQ,
},
};
static struct resource adc_resources[] = {
{
.name = "ADC",
.start = CRYSTAL_COVE_IRQ_ADC,
.end = CRYSTAL_COVE_IRQ_ADC,
.flags = IORESOURCE_IRQ,
},
};
static struct resource thermal_resources[] = {
{
.name = "THERMAL",
.start = CRYSTAL_COVE_IRQ_THRM,
.end = CRYSTAL_COVE_IRQ_THRM,
.flags = IORESOURCE_IRQ,
},
};
static struct resource bcu_resources[] = {
{
.name = "BCU",
.start = CRYSTAL_COVE_IRQ_BCU,
.end = CRYSTAL_COVE_IRQ_BCU,
.flags = IORESOURCE_IRQ,
},
};
static struct mfd_cell crystal_cove_dev[] = {
{
.name = "crystal_cove_pwrsrc",
.num_resources = ARRAY_SIZE(pwrsrc_resources),
.resources = pwrsrc_resources,
},
{
.name = "crystal_cove_adc",
.num_resources = ARRAY_SIZE(adc_resources),
.resources = adc_resources,
},
{
.name = "crystal_cove_thermal",
.num_resources = ARRAY_SIZE(thermal_resources),
.resources = thermal_resources,
},
{
.name = "crystal_cove_bcu",
.num_resources = ARRAY_SIZE(bcu_resources),
.resources = bcu_resources,
},
{
.name = "crystal_cove_gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
.resources = gpio_resources,
},
};
static struct regmap_config crystal_cove_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = CRYSTAL_COVE_MAX_REGISTER,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_irq crystal_cove_irqs[] = {
[CRYSTAL_COVE_IRQ_PWRSRC] = {
.mask = BIT(CRYSTAL_COVE_IRQ_PWRSRC),
},
[CRYSTAL_COVE_IRQ_THRM] = {
.mask = BIT(CRYSTAL_COVE_IRQ_THRM),
},
[CRYSTAL_COVE_IRQ_BCU] = {
.mask = BIT(CRYSTAL_COVE_IRQ_BCU),
},
[CRYSTAL_COVE_IRQ_ADC] = {
.mask = BIT(CRYSTAL_COVE_IRQ_ADC),
},
[CRYSTAL_COVE_IRQ_CHGR] = {
.mask = BIT(CRYSTAL_COVE_IRQ_CHGR),
},
[CRYSTAL_COVE_IRQ_GPIO] = {
.mask = BIT(CRYSTAL_COVE_IRQ_GPIO),
},
[CRYSTAL_COVE_IRQ_VHDMIOCP] = {
.mask = BIT(CRYSTAL_COVE_IRQ_VHDMIOCP),
},
};
static struct regmap_irq_chip crystal_cove_irq_chip = {
.name = "Crystal Cove",
.irqs = crystal_cove_irqs,
.num_irqs = ARRAY_SIZE(crystal_cove_irqs),
.num_regs = 1,
.status_base = CRYSTAL_COVE_REG_IRQLVL1,
.mask_base = CRYSTAL_COVE_REG_MIRQLVL1,
};
struct intel_soc_pmic_config intel_soc_pmic_config_crc = {
.irq_flags = IRQF_TRIGGER_RISING,
.cell_dev = crystal_cove_dev,
.n_cell_devs = ARRAY_SIZE(crystal_cove_dev),
.regmap_config = &crystal_cove_regmap_config,
.irq_chip = &crystal_cove_irq_chip,
};
......@@ -115,7 +115,7 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
} else {
dev_err(micro->dev,
"out of band RX message 0x%02x\n", id);
if(!micro->msg)
if (!micro->msg)
dev_info(micro->dev, "no message queued\n");
else
dev_info(micro->dev, "expected message %02x\n",
......@@ -126,13 +126,13 @@ static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
if (micro->key)
micro->key(micro->key_data, len, data);
else
dev_dbg(micro->dev, "key message ignored, no handle \n");
dev_dbg(micro->dev, "key message ignored, no handle\n");
break;
case MSG_TOUCHSCREEN:
if (micro->ts)
micro->ts(micro->ts_data, len, data);
else
dev_dbg(micro->dev, "touchscreen message ignored, no handle \n");
dev_dbg(micro->dev, "touchscreen message ignored, no handle\n");
break;
default:
dev_err(micro->dev,
......@@ -154,7 +154,7 @@ static void micro_process_char(struct ipaq_micro *micro, u8 ch)
rx->state = STATE_ID; /* Next byte is the id and len */
break;
case STATE_ID: /* Looking for id and len byte */
rx->id = (ch & 0xf0) >> 4 ;
rx->id = (ch & 0xf0) >> 4;
rx->len = (ch & 0x0f);
rx->index = 0;
rx->chksum = ch;
......
......@@ -24,7 +24,8 @@
#define MAX_ID_LEN 4
static char force_device_id[MAX_ID_LEN + 1] = "";
module_param_string(force_device_id, force_device_id, sizeof(force_device_id), 0);
module_param_string(force_device_id, force_device_id,
sizeof(force_device_id), 0);
MODULE_PARM_DESC(force_device_id, "Override detected product");
/*
......@@ -36,7 +37,7 @@ static void kempld_get_hardware_mutex(struct kempld_device_data *pld)
{
/* The mutex bit will read 1 until access has been granted */
while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
msleep(1);
usleep_range(1000, 3000);
}
static void kempld_release_hardware_mutex(struct kempld_device_data *pld)
......@@ -499,7 +500,7 @@ static struct platform_driver kempld_driver = {
.remove = kempld_remove,
};
static struct dmi_system_id __initdata kempld_dmi_table[] = {
static struct dmi_system_id kempld_dmi_table[] __initdata = {
{
.ident = "BHL6",
.matches = {
......@@ -736,7 +737,8 @@ static int __init kempld_init(void)
int ret;
if (force_device_id[0]) {
for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++)
for (id = kempld_dmi_table;
id->matches[0].slot != DMI_NONE; id++)
if (strstr(id->ident, force_device_id))
if (id->callback && id->callback(id))
break;
......
......@@ -66,12 +66,14 @@ static inline u8 _irq_to_val(enum lp8788_int_id id, int enable)
static void lp8788_irq_enable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
irqd->enabled[data->hwirq] = 1;
}
static void lp8788_irq_disable(struct irq_data *data)
{
struct lp8788_irq_data *irqd = irq_data_get_irq_chip_data(data);
irqd->enabled[data->hwirq] = 0;
}
......
/*
* max77686-irq.c - Interrupt controller support for MAX77686
*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
* Chiwoong Byun <woong.byun@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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This driver is based on max8997-irq.c
*/
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/mfd/max77686.h>
#include <linux/mfd/max77686-private.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
enum {
MAX77686_DEBUG_IRQ_INFO = 1 << 0,
MAX77686_DEBUG_IRQ_MASK = 1 << 1,
MAX77686_DEBUG_IRQ_INT = 1 << 2,
};
static int debug_mask = 0;
module_param(debug_mask, int, 0);
MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)");
static const u8 max77686_mask_reg[] = {
[PMIC_INT1] = MAX77686_REG_INT1MSK,
[PMIC_INT2] = MAX77686_REG_INT2MSK,
[RTC_INT] = MAX77686_RTC_INTM,
};
static struct regmap *max77686_get_regmap(struct max77686_dev *max77686,
enum max77686_irq_source src)
{
switch (src) {
case PMIC_INT1 ... PMIC_INT2:
return max77686->regmap;
case RTC_INT:
return max77686->rtc_regmap;
default:
return ERR_PTR(-EINVAL);
}
}
struct max77686_irq_data {
int mask;
enum max77686_irq_source group;
};
#define DECLARE_IRQ(idx, _group, _mask) \
[(idx)] = { .group = (_group), .mask = (_mask) }
static const struct max77686_irq_data max77686_irqs[] = {
DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0),
DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1),
DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2),
DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3),
DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4),
DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5),
DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6),
DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7),
DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0),
DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1),
DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0),
DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1),
DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2),
DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3),
DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4),
DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5),
};
static void max77686_irq_lock(struct irq_data *data)
{
struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
pr_info("%s\n", __func__);
mutex_lock(&max77686->irqlock);
}
static void max77686_irq_sync_unlock(struct irq_data *data)
{
struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
int i;
for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
u8 mask_reg = max77686_mask_reg[i];
struct regmap *map = max77686_get_regmap(max77686, i);
if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n",
__func__, i, mask_reg, max77686->irq_masks_cur[i]);
if (mask_reg == MAX77686_REG_INVALID ||
IS_ERR_OR_NULL(map))
continue;
max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i];
regmap_write(map, max77686_mask_reg[i],
max77686->irq_masks_cur[i]);
}
mutex_unlock(&max77686->irqlock);
}
static const inline struct max77686_irq_data *to_max77686_irq(int irq)
{
struct irq_data *data = irq_get_irq_data(irq);
return &max77686_irqs[data->hwirq];
}
static void max77686_irq_mask(struct irq_data *data)
{
struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
max77686->irq_masks_cur[irq_data->group] |= irq_data->mask;
if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
pr_info("%s: group=%d, cur=0x%x\n",
__func__, irq_data->group,
max77686->irq_masks_cur[irq_data->group]);
}
static void max77686_irq_unmask(struct irq_data *data)
{
struct max77686_dev *max77686 = irq_get_chip_data(data->irq);
const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq);
max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
if (debug_mask & MAX77686_DEBUG_IRQ_MASK)
pr_info("%s: group=%d, cur=0x%x\n",
__func__, irq_data->group,
max77686->irq_masks_cur[irq_data->group]);
}
static struct irq_chip max77686_irq_chip = {
.name = "max77686",
.irq_bus_lock = max77686_irq_lock,
.irq_bus_sync_unlock = max77686_irq_sync_unlock,
.irq_mask = max77686_irq_mask,
.irq_unmask = max77686_irq_unmask,
};
static irqreturn_t max77686_irq_thread(int irq, void *data)
{
struct max77686_dev *max77686 = data;
unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {};
unsigned int irq_src;
int ret;
int i, cur_irq;
ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src);
if (ret < 0) {
dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
ret);
return IRQ_NONE;
}
if (debug_mask & MAX77686_DEBUG_IRQ_INT)
pr_info("%s: irq_src=0x%x\n", __func__, irq_src);
if (irq_src == MAX77686_IRQSRC_PMIC) {
ret = regmap_bulk_read(max77686->regmap,
MAX77686_REG_INT1, irq_reg, 2);
if (ret < 0) {
dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
ret);
return IRQ_NONE;
}
if (debug_mask & MAX77686_DEBUG_IRQ_INT)
pr_info("%s: int1=0x%x, int2=0x%x\n", __func__,
irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]);
}
if (irq_src & MAX77686_IRQSRC_RTC) {
ret = regmap_read(max77686->rtc_regmap,
MAX77686_RTC_INT, &irq_reg[RTC_INT]);
if (ret < 0) {
dev_err(max77686->dev, "Failed to read interrupt source: %d\n",
ret);
return IRQ_NONE;
}
if (debug_mask & MAX77686_DEBUG_IRQ_INT)
pr_info("%s: rtc int=0x%x\n", __func__,
irq_reg[RTC_INT]);
}
for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++)
irq_reg[i] &= ~max77686->irq_masks_cur[i];
for (i = 0; i < MAX77686_IRQ_NR; i++) {
if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) {
cur_irq = irq_find_mapping(max77686->irq_domain, i);
if (cur_irq)
handle_nested_irq(cur_irq);
}
}
return IRQ_HANDLED;
}
static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
struct max77686_dev *max77686 = d->host_data;
irq_set_chip_data(irq, max77686);
irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
return 0;
}
static struct irq_domain_ops max77686_irq_domain_ops = {
.map = max77686_irq_domain_map,
};
int max77686_irq_init(struct max77686_dev *max77686)
{
struct irq_domain *domain;
int i;
int ret;
int val;
struct regmap *map;
mutex_init(&max77686->irqlock);
if (max77686->irq_gpio && !max77686->irq) {
max77686->irq = gpio_to_irq(max77686->irq_gpio);
if (debug_mask & MAX77686_DEBUG_IRQ_INT) {
ret = gpio_request(max77686->irq_gpio, "pmic_irq");
if (ret < 0) {
dev_err(max77686->dev,
"Failed to request gpio %d with ret:"
"%d\n", max77686->irq_gpio, ret);
return IRQ_NONE;
}
gpio_direction_input(max77686->irq_gpio);
val = gpio_get_value(max77686->irq_gpio);
gpio_free(max77686->irq_gpio);
pr_info("%s: gpio_irq=%x\n", __func__, val);
}
}
if (!max77686->irq) {
dev_err(max77686->dev, "irq is not specified\n");
return -ENODEV;
}
/* Mask individual interrupt sources */
for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) {
max77686->irq_masks_cur[i] = 0xff;
max77686->irq_masks_cache[i] = 0xff;
map = max77686_get_regmap(max77686, i);
if (IS_ERR_OR_NULL(map))
continue;
if (max77686_mask_reg[i] == MAX77686_REG_INVALID)
continue;
regmap_write(map, max77686_mask_reg[i], 0xff);
}
domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR,
&max77686_irq_domain_ops, max77686);
if (!domain) {
dev_err(max77686->dev, "could not create irq domain\n");
return -ENODEV;
}
max77686->irq_domain = domain;
ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"max77686-irq", max77686);
if (ret)
dev_err(max77686->dev, "Failed to request IRQ %d: %d\n",
max77686->irq, ret);
if (debug_mask & MAX77686_DEBUG_IRQ_INFO)
pr_info("%s-\n", __func__);
return 0;
}
void max77686_irq_exit(struct max77686_dev *max77686)
{
if (max77686->irq)
free_irq(max77686->irq, max77686);
}
This diff is collapsed.
......@@ -624,6 +624,7 @@ static void max8925_irq_sync_unlock(struct irq_data *data)
static void max8925_irq_enable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
max8925_irqs[data->irq - chip->irq_base].enable
= max8925_irqs[data->irq - chip->irq_base].offs;
}
......@@ -631,6 +632,7 @@ static void max8925_irq_enable(struct irq_data *data)
static void max8925_irq_disable(struct irq_data *data)
{
struct max8925_chip *chip = irq_data_get_irq_chip_data(data);
max8925_irqs[data->irq - chip->irq_base].enable = 0;
}
......
......@@ -257,9 +257,11 @@ static struct i2c_driver max8925_driver = {
static int __init max8925_i2c_init(void)
{
int ret;
ret = i2c_add_driver(&max8925_driver);
if (ret != 0)
pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
return ret;
}
subsys_initcall(max8925_i2c_init);
......
This diff is collapsed.
......@@ -13,7 +13,9 @@
#include <linux/regmap.h>
#include <linux/mfd/mc13xxx.h>
#define MC13XXX_NUMREGS 0x3f
#define MC13XXX_NUMREGS 0x3f
#define MC13XXX_IRQ_REG_CNT 2
#define MC13XXX_IRQ_PER_REG 24
struct mc13xxx;
......@@ -33,13 +35,14 @@ struct mc13xxx {
struct device *dev;
const struct mc13xxx_variant *variant;
struct regmap_irq irqs[MC13XXX_IRQ_PER_REG * MC13XXX_IRQ_REG_CNT];
struct regmap_irq_chip irq_chip;
struct regmap_irq_chip_data *irq_data;
struct mutex lock;
int irq;
int flags;
irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
void *irqdata[MC13XXX_NUM_IRQ];
int adcflags;
};
......
......@@ -137,6 +137,7 @@ EXPORT_SYMBOL(mcp_reg_read);
void mcp_enable(struct mcp *mcp)
{
unsigned long flags;
spin_lock_irqsave(&mcp->lock, flags);
if (mcp->use_count++ == 0)
mcp->ops->enable(mcp);
......
......@@ -445,7 +445,7 @@ static unsigned omap_usbhs_rev1_hostconfig(struct usbhs_hcd_omap *omap,
for (i = 0; i < omap->nports; i++) {
if (is_ehci_phy_mode(pdata->port_mode[i])) {
reg &= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
break;
}
}
......
......@@ -244,20 +244,20 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
struct platform_device *pdev;
int j;
pdev = platform_device_alloc("pcf50633-regulator", i);
if (!pdev) {
dev_err(pcf->dev, "Cannot create regulator %d\n", i);
continue;
}
if (!pdev)
return -ENOMEM;
pdev->dev.parent = pcf->dev;
if (platform_device_add_data(pdev, &pdata->reg_init_data[i],
sizeof(pdata->reg_init_data[i])) < 0) {
ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
sizeof(pdata->reg_init_data[i]));
if (ret) {
platform_device_put(pdev);
dev_err(pcf->dev, "Out of memory for regulator parameters %d\n",
i);
continue;
for (j = 0; j < i; j++)
platform_device_put(pcf->regulator_pdev[j]);
return ret;
}
pcf->regulator_pdev[i] = pdev;
......
......@@ -186,11 +186,9 @@ static void pm8xxx_irq_mask_ack(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
int irq_bit;
u8 block, config;
block = pmirq / 8;
irq_bit = pmirq % 8;
config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
pm8xxx_config_irq(chip, block, config);
......@@ -200,11 +198,9 @@ static void pm8xxx_irq_unmask(struct irq_data *d)
{
struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
unsigned int pmirq = irqd_to_hwirq(d);
int irq_bit;
u8 block, config;
block = pmirq / 8;
irq_bit = pmirq % 8;
config = chip->config[pmirq];
pm8xxx_config_irq(chip, block, config);
......
......@@ -337,40 +337,64 @@ static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read, int timeout)
{
struct completion trans_done;
u8 dir;
int err = 0, i, count;
long timeleft;
unsigned long flags;
struct scatterlist *sg;
enum dma_data_direction dma_dir;
u32 val;
dma_addr_t addr;
unsigned int len;
int err = 0, count;
dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
if (count < 1)
return -EINVAL;
dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
return err;
}
EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read)
{
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
/* don't transfer data during abort processing */
if (pcr->remove_pci)
return -EINVAL;
if ((sglist == NULL) || (num_sg <= 0))
return -EINVAL;
if (read) {
dir = DEVICE_TO_HOST;
dma_dir = DMA_FROM_DEVICE;
} else {
dir = HOST_TO_DEVICE;
dma_dir = DMA_TO_DEVICE;
}
return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
}
EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
if (count < 1) {
dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int num_sg, bool read)
{
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
}
EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
int count, bool read, int timeout)
{
struct completion trans_done;
struct scatterlist *sg;
dma_addr_t addr;
long timeleft;
unsigned long flags;
unsigned int len;
int i, err = 0;
u32 val;
u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
if (pcr->remove_pci)
return -ENODEV;
if ((sglist == NULL) || (count < 1))
return -EINVAL;
}
dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
pcr->sgi = 0;
......@@ -400,12 +424,10 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
}
spin_lock_irqsave(&pcr->lock, flags);
if (pcr->trans_result == TRANS_RESULT_FAIL)
err = -EINVAL;
else if (pcr->trans_result == TRANS_NO_DEVICE)
err = -ENODEV;
spin_unlock_irqrestore(&pcr->lock, flags);
out:
......@@ -413,8 +435,6 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
pcr->done = NULL;
spin_unlock_irqrestore(&pcr->lock, flags);
dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
if ((err < 0) && (err != -ENODEV))
rtsx_pci_stop_cmd(pcr);
......@@ -423,7 +443,7 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
return err;
}
EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
{
......
......@@ -28,8 +28,10 @@
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/regulator/machine.h>
#include <linux/regmap.h>
static const struct mfd_cell s5m8751_devs[] = {
......@@ -89,6 +91,15 @@ static const struct mfd_cell s2mpa01_devs[] = {
},
};
static const struct mfd_cell s2mpu02_devs[] = {
{ .name = "s2mpu02-pmic", },
{ .name = "s2mpu02-rtc", },
{
.name = "s2mpu02-clk",
.of_compatible = "samsung,s2mpu02-clk",
}
};
#ifdef CONFIG_OF
static const struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic",
......@@ -102,6 +113,9 @@ static const struct of_device_id sec_dt_match[] = {
}, {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
.compatible = "samsung,s2mpu02-pmic",
.data = (void *)S2MPU02,
}, {
/* Sentinel */
},
......@@ -132,6 +146,18 @@ static bool s2mps11_volatile(struct device *dev, unsigned int reg)
}
}
static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPU02_REG_INT1M:
case S2MPU02_REG_INT2M:
case S2MPU02_REG_INT3M:
return false;
default:
return true;
}
}
static bool s5m8763_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
......@@ -177,6 +203,15 @@ static const struct regmap_config s2mps14_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mpu02_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPU02_REG_DVSDATA,
.volatile_reg = s2mpu02_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -238,6 +273,7 @@ static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c,
#ifdef CONFIG_OF
if (i2c->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(sec_dt_match, i2c->dev.of_node);
return (unsigned long)match->data;
}
......@@ -250,9 +286,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
{
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
const struct regmap_config *regmap;
const struct mfd_cell *sec_devs;
struct sec_pmic_dev *sec_pmic;
unsigned long device_type;
int ret;
int ret, num_sec_devs;
sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
GFP_KERNEL);
......@@ -297,6 +334,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
case S5M8767X:
regmap = &s5m8767_regmap_config;
break;
case S2MPU02:
regmap = &s2mpu02_regmap_config;
break;
default:
regmap = &sec_regmap_config;
break;
......@@ -319,34 +359,39 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S5M8751X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
sec_devs = s5m8751_devs;
num_sec_devs = ARRAY_SIZE(s5m8751_devs);
break;
case S5M8763X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
sec_devs = s5m8763_devs;
num_sec_devs = ARRAY_SIZE(s5m8763_devs);
break;
case S5M8767X:
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
sec_devs = s5m8767_devs;
num_sec_devs = ARRAY_SIZE(s5m8767_devs);
break;
case S2MPA01:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
sec_devs = s2mpa01_devs;
num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
break;
case S2MPS11X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
sec_devs = s2mps11_devs;
num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS14X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
sec_devs = s2mps14_devs;
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
break;
case S2MPU02:
sec_devs = s2mpu02_devs;
num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
break;
default:
/* If this happens the probe function is problem */
BUG();
}
ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
0, NULL);
if (ret)
goto err_mfd;
......@@ -387,6 +432,15 @@ static int sec_pmic_suspend(struct device *dev)
*/
disable_irq(sec_pmic->irq);
switch (sec_pmic->device_type) {
case S2MPS14X:
case S2MPU02:
regulator_suspend_prepare(PM_SUSPEND_MEM);
break;
default:
break;
}
return 0;
}
......
......@@ -20,6 +20,7 @@
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
......@@ -161,6 +162,77 @@ static const struct regmap_irq s2mps14_irqs[] = {
},
};
static const struct regmap_irq s2mpu02_irqs[] = {
[S2MPU02_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
},
[S2MPU02_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONR_MASK,
},
[S2MPU02_IRQ_JIGONBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBF_MASK,
},
[S2MPU02_IRQ_JIGONBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBR_MASK,
},
[S2MPU02_IRQ_ACOKBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBF_MASK,
},
[S2MPU02_IRQ_ACOKBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBR_MASK,
},
[S2MPU02_IRQ_PWRON1S] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRON1S_MASK,
},
[S2MPU02_IRQ_MRB] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_MRB_MASK,
},
[S2MPU02_IRQ_RTC60S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPU02_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPU02_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPU02_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
},
[S2MPU02_IRQ_RTC1S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC1S_MASK,
},
[S2MPU02_IRQ_WTSR] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_WTSR_MASK,
},
[S2MPU02_IRQ_INT120C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT120C_MASK,
},
[S2MPU02_IRQ_INT140C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT140C_MASK,
},
[S2MPU02_IRQ_TSD] = {
.reg_offset = 2,
.mask = S2MPS14_IRQ_TSD_MASK,
},
};
static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = {
.reg_offset = 0,
......@@ -327,6 +399,16 @@ static const struct regmap_irq_chip s2mps14_irq_chip = {
.ack_base = S2MPS14_REG_INT1,
};
static const struct regmap_irq_chip s2mpu02_irq_chip = {
.name = "s2mpu02",
.irqs = s2mpu02_irqs,
.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
.num_regs = 3,
.status_base = S2MPU02_REG_INT1,
.mask_base = S2MPU02_REG_INT1M,
.ack_base = S2MPU02_REG_INT1,
};
static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767",
.irqs = s5m8767_irqs,
......@@ -351,6 +433,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
{
int ret = 0;
int type = sec_pmic->device_type;
const struct regmap_irq_chip *sec_irq_chip;
if (!sec_pmic->irq) {
dev_warn(sec_pmic->dev,
......@@ -361,28 +444,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
switch (type) {
case S5M8763X:
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, &s5m8763_irq_chip,
&sec_pmic->irq_data);
sec_irq_chip = &s5m8763_irq_chip;
break;
case S5M8767X:
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, &s5m8767_irq_chip,
&sec_pmic->irq_data);
sec_irq_chip = &s5m8767_irq_chip;
break;
case S2MPS11X:
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, &s2mps11_irq_chip,
&sec_pmic->irq_data);
sec_irq_chip = &s2mps11_irq_chip;
break;
case S2MPS14X:
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, &s2mps14_irq_chip,
&sec_pmic->irq_data);
sec_irq_chip = &s2mps14_irq_chip;
break;
case S2MPU02:
sec_irq_chip = &s2mpu02_irq_chip;
break;
default:
dev_err(sec_pmic->dev, "Unknown device type %lu\n",
......@@ -390,6 +464,10 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
return -EINVAL;
}
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, sec_irq_chip,
&sec_pmic->irq_data);
if (ret != 0) {
dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
......
......@@ -1228,8 +1228,8 @@ static int si476x_core_cmd_fm_rsq_status_a10(struct si476x_core *core,
}
static int si476x_core_cmd_fm_rsq_status_a20(struct si476x_core *core,
struct si476x_rsq_status_args *rsqargs,
struct si476x_rsq_status_report *report)
struct si476x_rsq_status_args *rsqargs,
struct si476x_rsq_status_report *report)
{
int err;
u8 resp[CMD_FM_RSQ_STATUS_A10_NRESP];
......@@ -1434,10 +1434,10 @@ typedef int (*tune_freq_func_t) (struct si476x_core *core,
struct si476x_tune_freq_args *tuneargs);
static struct {
int (*power_up) (struct si476x_core *,
struct si476x_power_up_args *);
int (*power_down) (struct si476x_core *,
struct si476x_power_down_args *);
int (*power_up)(struct si476x_core *,
struct si476x_power_up_args *);
int (*power_down)(struct si476x_core *,
struct si476x_power_down_args *);
tune_freq_func_t fm_tune_freq;
tune_freq_func_t am_tune_freq;
......
......@@ -68,7 +68,7 @@ MODULE_DEVICE_TABLE(of, stmpe_of_match);
static int
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
int partnum;
enum stmpe_partnum partnum;
const struct of_device_id *of_id;
i2c_ci.data = (void *)id;
......@@ -85,7 +85,7 @@ stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
dev_info(&i2c->dev, "matching on node name, compatible is preferred\n");
partnum = id->driver_data;
} else
partnum = (int)of_id->data;
partnum = (enum stmpe_partnum)of_id->data;
return stmpe_probe(&i2c_ci, partnum);
}
......
......@@ -1147,7 +1147,7 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
}
/* Called from client specific probe routines */
int stmpe_probe(struct stmpe_client_info *ci, int partnum)
int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum)
{
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
struct device_node *np = ci->dev->of_node;
......
......@@ -97,7 +97,7 @@ struct stmpe_client_info {
void (*init)(struct stmpe *stmpe);
};
int stmpe_probe(struct stmpe_client_info *ci, int partnum);
int stmpe_probe(struct stmpe_client_info *ci, enum stmpe_partnum partnum);
int stmpe_remove(struct stmpe *stmpe);
#define STMPE_ICR_LSB_HIGH (1 << 2)
......
......@@ -76,16 +76,46 @@ static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
},
};
static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
{
.name = "sun8i-a23-apb0-clk",
.of_compatible = "allwinner,sun8i-a23-apb0-clk",
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
.resources = sun6i_a31_apb0_clk_res,
},
{
.name = "sun6i-a31-apb0-gates-clk",
.of_compatible = "allwinner,sun8i-a23-apb0-gates-clk",
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
.resources = sun6i_a31_apb0_gates_clk_res,
},
{
.name = "sun6i-a31-apb0-clock-reset",
.of_compatible = "allwinner,sun6i-a31-clock-reset",
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
.resources = sun6i_a31_apb0_rstc_res,
},
};
static const struct prcm_data sun6i_a31_prcm_data = {
.nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
.subdevs = sun6i_a31_prcm_subdevs,
};
static const struct prcm_data sun8i_a23_prcm_data = {
.nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs),
.subdevs = sun8i_a23_prcm_subdevs,
};
static const struct of_device_id sun6i_prcm_dt_ids[] = {
{
.compatible = "allwinner,sun6i-a31-prcm",
.data = &sun6i_a31_prcm_data,
},
{
.compatible = "allwinner,sun8i-a23-prcm",
.data = &sun8i_a23_prcm_data,
},
{ /* sentinel */ },
};
......
......@@ -236,7 +236,7 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq)
static struct irq_domain_ops tc3589x_irq_ops = {
.map = tc3589x_irq_map,
.unmap = tc3589x_irq_unmap,
.xlate = irq_domain_xlate_twocell,
.xlate = irq_domain_xlate_onecell,
};
static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
......
......@@ -147,11 +147,10 @@ static int tc6387xb_probe(struct platform_device *dev)
int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!iomem) {
if (!iomem)
return -EINVAL;
}
tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
tc6387xb = kzalloc(sizeof(*tc6387xb), GFP_KERNEL);
if (!tc6387xb)
return -ENOMEM;
......@@ -189,7 +188,7 @@ static int tc6387xb_probe(struct platform_device *dev)
if (pdata && pdata->enable)
pdata->enable(dev);
printk(KERN_INFO "Toshiba tc6387xb initialised\n");
dev_info(&dev->dev, "Toshiba tc6387xb initialised\n");
ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
......
This diff is collapsed.
This diff is collapsed.
......@@ -32,10 +32,9 @@ static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr,
unsigned long spi_data = 1 << 23 | addr << 15 | *data;
struct spi_transfer xfer;
struct spi_message msg;
u32 tx_buf, rx_buf;
u32 tx_buf;
tx_buf = spi_data;
rx_buf = 0;
xfer.tx_buf = &tx_buf;
xfer.rx_buf = NULL;
......
This diff is collapsed.
This diff is collapsed.
......@@ -700,7 +700,7 @@ static int twl6040_probe(struct i2c_client *client,
}
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
0, &twl6040_irq_chip,&twl6040->irq_data);
0, &twl6040_irq_chip, &twl6040->irq_data);
if (ret < 0)
goto gpio_err;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -497,7 +497,8 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
if (pdata && pdata->irq_base > 0)
irq_base = pdata->irq_base;
wm8350->irq_base = irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
wm8350->irq_base =
irq_alloc_descs(irq_base, 0, ARRAY_SIZE(wm8350_irqs), 0);
if (wm8350->irq_base < 0) {
dev_warn(wm8350->dev, "Allocating irqs failed with %d\n",
wm8350->irq_base);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment