Commit 3a7dbed7 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MFD updates from Lee Jones:
 "Changes to the core:
   - Honour PLATFORM_DEVID_NONE and PLATFORM_DEVID_AUTO dev IDs

  Changes to existing drivers:
   - IRQ additions/fixes; axp20x, da9063-core
   - Code simplification; i2c-dln2
   - Regmap additions/fixes; max77693
   - Error checking/handling improvements; dln2, db8500-prcmu
   - Bug fixes; dln2, wm8350-core
   - DT support/documentation; max77693, max77686, tps65217, twl4030-power,
                               gpio-tc3589x
   - Decouple syscon interface from platform devices
   - Use MFD hotplug registration; rtsx_usb, viperboard, hid-sensor-hub
   - Regulator fixups; sec-core
   - Power Management additions/fixes; rts5227, tc6393xb
   - Remove relic/redundant code; ab8500-sysctrl, lpc_sch, max77693-private
   - Clean-up/coding style changes; tps65090
   - Clk additions/fixes; tc6393xb, tc6387xb, t7l66xb
   - Add USB-SPI support; dln2
   - Trivial changes; max14577, arizona-spi, lpc_sch, wm8997-tables, wm5102-tables
                      wm5110-tables, axp20x, atmel-hlcdc, rtsx_pci

  New drivers/supported devices:
   - axp288 PMIC support added to axp20x
   - s2mps13 support added to sec-core
   - New support for Diolan DLN-2
   - New support for atmel-hlcdc"

* tag 'mfd-for-linus-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (55 commits)
  mfd: rtsx: Add func to split u32 into register
  mfd: atmel-hlcdc: Add Kconfig option description and name
  mfd: da9063: Get irq base dynamically before registering device
  mfd: max14577: Fix obvious typo in company name in copyright
  mfd: axp20x: Constify axp20x_acpi_match and rid unused warning
  mfd: t7l66xb: prepare/unprepare clocks
  mfd: tc6387xb: prepare/unprepare clocks
  mfd: dln2: add support for USB-SPI module
  mfd: wm5110: Add missing registers for AIF2 channels 3-6
  mfd: tc3589x: get rid of static base
  mfd: arizona: Document HP_CTRL_1L and HP_CTRL_1R registers
  mfd: wm8997: Mark INTERRUPT_STATUS_2_MASK as readable
  mfd: tc6393xb: Prepare/unprepare clocks
  mfd: tps65090: Fix bonkers indenting strategy
  mfd: tc6393xb: Fail ohci suspend if full state restore is required
  mfd: lpc_sch: Don't call mfd_remove_devices()
  mfd: wm8350-core: Fix probable mask then right shift defect
  mfd: ab8500-sysctrl: Drop ab8500_restart
  mfd: db8500-prcmu: Provide sane error path values
  mfd: db8500-prcmu: Check return of devm_ioremap for error
  ...
parents f2fb3804 a3b63979
Device-Tree bindings for Atmel's HLCDC (High LCD Controller) MFD driver
Required properties:
- compatible: value should be one of the following:
"atmel,sama5d3-hlcdc"
- reg: base address and size of the HLCDC device registers.
- clock-names: the name of the 3 clocks requested by the HLCDC device.
Should contain "periph_clk", "sys_clk" and "slow_clk".
- clocks: should contain the 3 clocks requested by the HLCDC device.
- interrupts: should contain the description of the HLCDC interrupt line
The HLCDC IP exposes two subdevices:
- a PWM chip: see ../pwm/atmel-hlcdc-pwm.txt
- a Display Controller: see ../drm/atmel-hlcdc-dc.txt
Example:
hlcdc: hlcdc@f0030000 {
compatible = "atmel,sama5d3-hlcdc";
reg = <0xf0030000 0x2000>;
clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
clock-names = "periph_clk","sys_clk", "slow_clk";
interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>;
status = "disabled";
hlcdc-display-controller {
compatible = "atmel,hlcdc-display-controller";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
hlcdc_panel_output: endpoint@0 {
reg = <0>;
remote-endpoint = <&panel_input>;
};
};
};
hlcdc_pwm: hlcdc-pwm {
compatible = "atmel,hlcdc-pwm";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcd_pwm>;
#pwm-cells = <3>;
};
};
......@@ -34,6 +34,12 @@ to get matched with their hardware counterparts as follow:
-BUCKn : for BUCKs, where n can lie in range 1 to 9.
example: BUCK1, BUCK5, BUCK9.
Regulators which can be turned off during system suspend:
-LDOn : 2, 6-8, 10-12, 14-16,
-BUCKn : 1-4.
Use standard regulator bindings for it ('regulator-off-in-suspend').
Example:
max77686@09 {
......
......@@ -27,6 +27,20 @@ Optional properties:
[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
- haptic : The MAX77693 haptic device utilises a PWM controlled motor to provide
users with tactile feedback. PWM period and duty-cycle are varied in
order to provide the approprite level of feedback.
Required properties:
- compatible : Must be "maxim,max77693-hpatic"
- haptic-supply : power supply for the haptic motor
[*] refer Documentation/devicetree/bindings/regulator/regulator.txt
- pwms : phandle to the physical PWM(Pulse Width Modulation) device.
PWM properties should be named "pwms". And number of cell is different
for each pwm device.
To get more informations, please refer to documentaion.
[*] refer Documentation/devicetree/bindings/pwm/pwm.txt
Example:
max77693@66 {
compatible = "maxim,max77693";
......@@ -52,4 +66,11 @@ Example:
regulator-boot-on;
};
};
haptic {
compatible = "maxim,max77693-haptic";
haptic-supply = <&haptic_supply>;
pwms = <&pwm 0 40000 0>;
pwm-names = "haptic";
};
};
* Samsung S2MPS11, S2MPS14 and S2MPU02 Voltage and Current Regulator
* Samsung S2MPS11, S2MPS13, 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,8 +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"
or "samsung,s2mpu02-pmic".
- compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps13-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:
......@@ -17,8 +17,8 @@ Optional properties:
- interrupts: Interrupt specifiers for interrupt sources.
Optional nodes:
- clocks: s2mps11 and s5m8767 provide three(AP/CP/BT) buffered 32.768 KHz
outputs, so to register these as clocks with common clock framework
- clocks: s2mps11, s2mps13 and s5m8767 provide three(AP/CP/BT) buffered 32.768
KHz outputs, so to register these as clocks with common clock framework
instantiate a sub-node named "clocks". It uses the common clock binding
documented in :
[Documentation/devicetree/bindings/clock/clock-bindings.txt]
......@@ -30,12 +30,12 @@ Optional nodes:
the clock which they consume.
Clock ID Devices
----------------------------------------------------------
32KhzAP 0 S2MPS11, S2MPS14, S5M8767
32KhzCP 1 S2MPS11, S5M8767
32KhzBT 2 S2MPS11, S2MPS14, S5M8767
32KhzAP 0 S2MPS11, S2MPS13, S2MPS14, S5M8767
32KhzCP 1 S2MPS11, S2MPS13, S5M8767
32KhzBT 2 S2MPS11, S2MPS13, S2MPS14, S5M8767
- compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps14-clk",
"samsung,s5m8767-clk"
- compatible: Should be one of: "samsung,s2mps11-clk", "samsung,s2mps13-clk",
"samsung,s2mps14-clk", "samsung,s5m8767-clk"
- regulators: The regulators of s2mps11 that have to be instantiated should be
included in a sub-node named 'regulators'. Regulator nodes included in this
......@@ -81,12 +81,14 @@ as per the datasheet of s2mps11.
- LDOn
- valid values for n are:
- S2MPS11: 1 to 38
- S2MPS13: 1 to 40
- S2MPS14: 1 to 25
- S2MPU02: 1 to 28
- Example: LDO1, LDO2, LDO28
- BUCKn
- valid values for n are:
- S2MPS11: 1 to 10
- S2MPS13: 1 to 10
- S2MPS14: 1 to 5
- S2MPU02: 1 to 7
- Example: BUCK1, BUCK2, BUCK9
......
......@@ -23,6 +23,7 @@
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/mfd/samsung/core.h>
......@@ -120,6 +121,24 @@ static struct clk_init_data s2mps11_clks_init[S2MPS11_CLKS_NUM] = {
},
};
static struct clk_init_data s2mps13_clks_init[S2MPS11_CLKS_NUM] = {
[S2MPS11_CLK_AP] = {
.name = "s2mps13_ap",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
[S2MPS11_CLK_CP] = {
.name = "s2mps13_cp",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
[S2MPS11_CLK_BT] = {
.name = "s2mps13_bt",
.ops = &s2mps11_clk_ops,
.flags = CLK_IS_ROOT,
},
};
static struct clk_init_data s2mps14_clks_init[S2MPS11_CLKS_NUM] = {
[S2MPS11_CLK_AP] = {
.name = "s2mps14_ap",
......@@ -184,6 +203,10 @@ static int s2mps11_clk_probe(struct platform_device *pdev)
s2mps11_reg = S2MPS11_REG_RTC_CTRL;
clks_init = s2mps11_clks_init;
break;
case S2MPS13X:
s2mps11_reg = S2MPS13_REG_RTCCTRL;
clks_init = s2mps13_clks_init;
break;
case S2MPS14X:
s2mps11_reg = S2MPS14_REG_RTCCTRL;
clks_init = s2mps14_clks_init;
......@@ -279,6 +302,7 @@ static int s2mps11_clk_remove(struct platform_device *pdev)
static const struct platform_device_id s2mps11_clk_id[] = {
{ "s2mps11-clk", S2MPS11X},
{ "s2mps13-clk", S2MPS13X},
{ "s2mps14-clk", S2MPS14X},
{ "s5m8767-clk", S5M8767X},
{ },
......
......@@ -905,4 +905,16 @@ config GPIO_VIPERBOARD
River Tech's viperboard.h for detailed meaning
of the module parameters.
config GPIO_DLN2
tristate "Diolan DLN2 GPIO support"
depends on MFD_DLN2
select GPIOLIB_IRQCHIP
help
Select this option to enable GPIO driver for the Diolan DLN2
board.
This driver can also be built as a module. If so, the module
will be called gpio-dln2.
endif
......@@ -26,6 +26,7 @@ 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
obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o
obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o
obj-$(CONFIG_GPIO_EM) += gpio-em.o
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
......
This diff is collapsed.
......@@ -262,7 +262,7 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
tc3589x_gpio->chip = template_chip;
tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
tc3589x_gpio->chip.dev = &pdev->dev;
tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1;
tc3589x_gpio->chip.base = -1;
#ifdef CONFIG_OF_GPIO
tc3589x_gpio->chip.of_node = np;
......
......@@ -640,9 +640,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
ret = -ENOMEM;
goto err_stop_hw;
}
sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].id =
PLATFORM_DEVID_AUTO;
sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].name = name;
sd->hid_sensor_hub_client_devs[
......@@ -659,8 +656,9 @@ static int sensor_hub_probe(struct hid_device *hdev,
if (last_hsdev)
last_hsdev->end_collection_index = i;
ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
sd->hid_sensor_client_cnt, NULL, 0, NULL);
ret = mfd_add_hotplug_devices(&hdev->dev,
sd->hid_sensor_hub_client_devs,
sd->hid_sensor_client_cnt);
if (ret < 0)
goto err_stop_hw;
......
......@@ -881,6 +881,16 @@ config I2C_DIOLAN_U2C
This driver can also be built as a module. If so, the module
will be called i2c-diolan-u2c.
config I2C_DLN2
tristate "Diolan DLN-2 USB I2C adapter"
depends on MFD_DLN2
help
If you say yes to this option, support will be included for Diolan
DLN2, a USB to I2C interface.
This driver can also be built as a module. If so, the module
will be called i2c-dln2.
config I2C_PARPORT
tristate "Parallel port adapter"
depends on PARPORT
......
......@@ -87,6 +87,7 @@ obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
obj-$(CONFIG_I2C_DLN2) += i2c-dln2.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_ROBOTFUZZ_OSIF) += i2c-robotfuzz-osif.o
......
/*
* Driver for the Diolan DLN-2 USB-I2C adapter
*
* Copyright (c) 2014 Intel Corporation
*
* Derived from:
* i2c-diolan-u2c.c
* Copyright (c) 2010-2011 Ericsson AB
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/mfd/dln2.h>
#define DLN2_I2C_MODULE_ID 0x03
#define DLN2_I2C_CMD(cmd) DLN2_CMD(cmd, DLN2_I2C_MODULE_ID)
/* I2C commands */
#define DLN2_I2C_GET_PORT_COUNT DLN2_I2C_CMD(0x00)
#define DLN2_I2C_ENABLE DLN2_I2C_CMD(0x01)
#define DLN2_I2C_DISABLE DLN2_I2C_CMD(0x02)
#define DLN2_I2C_IS_ENABLED DLN2_I2C_CMD(0x03)
#define DLN2_I2C_WRITE DLN2_I2C_CMD(0x06)
#define DLN2_I2C_READ DLN2_I2C_CMD(0x07)
#define DLN2_I2C_SCAN_DEVICES DLN2_I2C_CMD(0x08)
#define DLN2_I2C_PULLUP_ENABLE DLN2_I2C_CMD(0x09)
#define DLN2_I2C_PULLUP_DISABLE DLN2_I2C_CMD(0x0A)
#define DLN2_I2C_PULLUP_IS_ENABLED DLN2_I2C_CMD(0x0B)
#define DLN2_I2C_TRANSFER DLN2_I2C_CMD(0x0C)
#define DLN2_I2C_SET_MAX_REPLY_COUNT DLN2_I2C_CMD(0x0D)
#define DLN2_I2C_GET_MAX_REPLY_COUNT DLN2_I2C_CMD(0x0E)
#define DLN2_I2C_MAX_XFER_SIZE 256
#define DLN2_I2C_BUF_SIZE (DLN2_I2C_MAX_XFER_SIZE + 16)
struct dln2_i2c {
struct platform_device *pdev;
struct i2c_adapter adapter;
u8 port;
/*
* Buffer to hold the packet for read or write transfers. One is enough
* since we can't have multiple transfers in parallel on the i2c bus.
*/
void *buf;
};
static int dln2_i2c_enable(struct dln2_i2c *dln2, bool enable)
{
u16 cmd;
struct {
u8 port;
} tx;
tx.port = dln2->port;
if (enable)
cmd = DLN2_I2C_ENABLE;
else
cmd = DLN2_I2C_DISABLE;
return dln2_transfer_tx(dln2->pdev, cmd, &tx, sizeof(tx));
}
static int dln2_i2c_write(struct dln2_i2c *dln2, u8 addr,
u8 *data, u16 data_len)
{
int ret;
struct {
u8 port;
u8 addr;
u8 mem_addr_len;
__le32 mem_addr;
__le16 buf_len;
u8 buf[DLN2_I2C_MAX_XFER_SIZE];
} __packed *tx = dln2->buf;
unsigned len;
BUILD_BUG_ON(sizeof(*tx) > DLN2_I2C_BUF_SIZE);
tx->port = dln2->port;
tx->addr = addr;
tx->mem_addr_len = 0;
tx->mem_addr = 0;
tx->buf_len = cpu_to_le16(data_len);
memcpy(tx->buf, data, data_len);
len = sizeof(*tx) + data_len - DLN2_I2C_MAX_XFER_SIZE;
ret = dln2_transfer_tx(dln2->pdev, DLN2_I2C_WRITE, tx, len);
if (ret < 0)
return ret;
return data_len;
}
static int dln2_i2c_read(struct dln2_i2c *dln2, u16 addr, u8 *data,
u16 data_len)
{
int ret;
struct {
u8 port;
u8 addr;
u8 mem_addr_len;
__le32 mem_addr;
__le16 buf_len;
} __packed tx;
struct {
__le16 buf_len;
u8 buf[DLN2_I2C_MAX_XFER_SIZE];
} __packed *rx = dln2->buf;
unsigned rx_len = sizeof(*rx);
BUILD_BUG_ON(sizeof(*rx) > DLN2_I2C_BUF_SIZE);
tx.port = dln2->port;
tx.addr = addr;
tx.mem_addr_len = 0;
tx.mem_addr = 0;
tx.buf_len = cpu_to_le16(data_len);
ret = dln2_transfer(dln2->pdev, DLN2_I2C_READ, &tx, sizeof(tx),
rx, &rx_len);
if (ret < 0)
return ret;
if (rx_len < sizeof(rx->buf_len) + data_len)
return -EPROTO;
if (le16_to_cpu(rx->buf_len) != data_len)
return -EPROTO;
memcpy(data, rx->buf, data_len);
return data_len;
}
static int dln2_i2c_xfer(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num)
{
struct dln2_i2c *dln2 = i2c_get_adapdata(adapter);
struct i2c_msg *pmsg;
struct device *dev = &dln2->adapter.dev;
int i;
for (i = 0; i < num; i++) {
int ret;
pmsg = &msgs[i];
if (pmsg->len > DLN2_I2C_MAX_XFER_SIZE) {
dev_warn(dev, "maximum transfer size exceeded\n");
return -EOPNOTSUPP;
}
if (pmsg->flags & I2C_M_RD) {
ret = dln2_i2c_read(dln2, pmsg->addr, pmsg->buf,
pmsg->len);
if (ret < 0)
return ret;
pmsg->len = ret;
} else {
ret = dln2_i2c_write(dln2, pmsg->addr, pmsg->buf,
pmsg->len);
if (ret != pmsg->len)
return -EPROTO;
}
}
return num;
}
static u32 dln2_i2c_func(struct i2c_adapter *a)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_SMBUS_I2C_BLOCK;
}
static const struct i2c_algorithm dln2_i2c_usb_algorithm = {
.master_xfer = dln2_i2c_xfer,
.functionality = dln2_i2c_func,
};
static int dln2_i2c_probe(struct platform_device *pdev)
{
int ret;
struct dln2_i2c *dln2;
struct device *dev = &pdev->dev;
struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev);
dln2 = devm_kzalloc(dev, sizeof(*dln2), GFP_KERNEL);
if (!dln2)
return -ENOMEM;
dln2->buf = devm_kmalloc(dev, DLN2_I2C_BUF_SIZE, GFP_KERNEL);
if (!dln2->buf)
return -ENOMEM;
dln2->pdev = pdev;
dln2->port = pdata->port;
/* setup i2c adapter description */
dln2->adapter.owner = THIS_MODULE;
dln2->adapter.class = I2C_CLASS_HWMON;
dln2->adapter.algo = &dln2_i2c_usb_algorithm;
dln2->adapter.dev.parent = dev;
i2c_set_adapdata(&dln2->adapter, dln2);
snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
"dln2-i2c", dev_name(pdev->dev.parent), dln2->port);
platform_set_drvdata(pdev, dln2);
/* initialize the i2c interface */
ret = dln2_i2c_enable(dln2, true);
if (ret < 0) {
dev_err(dev, "failed to initialize adapter: %d\n", ret);
return ret;
}
/* and finally attach to i2c layer */
ret = i2c_add_adapter(&dln2->adapter);
if (ret < 0) {
dev_err(dev, "failed to add I2C adapter: %d\n", ret);
goto out_disable;
}
return 0;
out_disable:
dln2_i2c_enable(dln2, false);
return ret;
}
static int dln2_i2c_remove(struct platform_device *pdev)
{
struct dln2_i2c *dln2 = platform_get_drvdata(pdev);
i2c_del_adapter(&dln2->adapter);
dln2_i2c_enable(dln2, false);
return 0;
}
static struct platform_driver dln2_i2c_driver = {
.driver.name = "dln2-i2c",
.probe = dln2_i2c_probe,
.remove = dln2_i2c_remove,
};
module_platform_driver(dln2_i2c_driver);
MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>");
MODULE_DESCRIPTION("Driver for the Diolan DLN2 I2C master interface");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:dln2-i2c");
......@@ -127,6 +127,14 @@ config AT91_ADC
help
Say yes here to build support for Atmel AT91 ADC.
config AXP288_ADC
tristate "X-Powers AXP288 ADC driver"
depends on MFD_AXP20X
help
Say yes here to have support for X-Powers power management IC (PMIC) ADC
device. Depending on platform configuration, this general purpose ADC can
be used for sampling sensors such as thermal resistors.
config EXYNOS_ADC
tristate "Exynos ADC driver support"
depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_MAX1027) += max1027.o
......
/*
* axp288_adc.c - X-Powers AXP288 PMIC ADC Driver
*
* Copyright (C) 2014 Intel Corporation
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/regmap.h>
#include <linux/mfd/axp20x.h>
#include <linux/platform_device.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#define AXP288_ADC_EN_MASK 0xF1
#define AXP288_ADC_TS_PIN_GPADC 0xF2
#define AXP288_ADC_TS_PIN_ON 0xF3
enum axp288_adc_id {
AXP288_ADC_TS,
AXP288_ADC_PMIC,
AXP288_ADC_GP,
AXP288_ADC_BATT_CHRG_I,
AXP288_ADC_BATT_DISCHRG_I,
AXP288_ADC_BATT_V,
AXP288_ADC_NR_CHAN,
};
struct axp288_adc_info {
int irq;
struct regmap *regmap;
};
static const struct iio_chan_spec const axp288_adc_channels[] = {
{
.indexed = 1,
.type = IIO_TEMP,
.channel = 0,
.address = AXP288_TS_ADC_H,
.datasheet_name = "TS_PIN",
}, {
.indexed = 1,
.type = IIO_TEMP,
.channel = 1,
.address = AXP288_PMIC_ADC_H,
.datasheet_name = "PMIC_TEMP",
}, {
.indexed = 1,
.type = IIO_TEMP,
.channel = 2,
.address = AXP288_GP_ADC_H,
.datasheet_name = "GPADC",
}, {
.indexed = 1,
.type = IIO_CURRENT,
.channel = 3,
.address = AXP20X_BATT_CHRG_I_H,
.datasheet_name = "BATT_CHG_I",
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
}, {
.indexed = 1,
.type = IIO_CURRENT,
.channel = 4,
.address = AXP20X_BATT_DISCHRG_I_H,
.datasheet_name = "BATT_DISCHRG_I",
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
}, {
.indexed = 1,
.type = IIO_VOLTAGE,
.channel = 5,
.address = AXP20X_BATT_V_H,
.datasheet_name = "BATT_V",
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
},
};
#define AXP288_ADC_MAP(_adc_channel_label, _consumer_dev_name, \
_consumer_channel) \
{ \
.adc_channel_label = _adc_channel_label, \
.consumer_dev_name = _consumer_dev_name, \
.consumer_channel = _consumer_channel, \
}
/* for consumer drivers */
static struct iio_map axp288_adc_default_maps[] = {
AXP288_ADC_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
AXP288_ADC_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
AXP288_ADC_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
AXP288_ADC_MAP("BATT_CHG_I", "axp288-chrg", "axp288-chrg-curr"),
AXP288_ADC_MAP("BATT_DISCHRG_I", "axp288-chrg", "axp288-chrg-d-curr"),
AXP288_ADC_MAP("BATT_V", "axp288-batt", "axp288-batt-volt"),
{},
};
static int axp288_adc_read_channel(int *val, unsigned long address,
struct regmap *regmap)
{
u8 buf[2];
if (regmap_bulk_read(regmap, address, buf, 2))
return -EIO;
*val = (buf[0] << 4) + ((buf[1] >> 4) & 0x0F);
return IIO_VAL_INT;
}
static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
unsigned long address)
{
/* channels other than GPADC do not need to switch TS pin */
if (address != AXP288_GP_ADC_H)
return 0;
return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
}
static int axp288_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret;
struct axp288_adc_info *info = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
chan->address)) {
dev_err(&indio_dev->dev, "GPADC mode\n");
ret = -EINVAL;
break;
}
ret = axp288_adc_read_channel(val, chan->address, info->regmap);
if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
chan->address))
dev_err(&indio_dev->dev, "TS pin restore\n");
break;
case IIO_CHAN_INFO_PROCESSED:
ret = axp288_adc_read_channel(val, chan->address, info->regmap);
break;
default:
ret = -EINVAL;
}
mutex_unlock(&indio_dev->mlock);
return ret;
}
static int axp288_adc_set_state(struct regmap *regmap)
{
/* ADC should be always enabled for internal FG to function */
if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
return -EIO;
return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
}
static const struct iio_info axp288_adc_iio_info = {
.read_raw = &axp288_adc_read_raw,
.driver_module = THIS_MODULE,
};
static int axp288_adc_probe(struct platform_device *pdev)
{
int ret;
struct axp288_adc_info *info;
struct iio_dev *indio_dev;
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
if (!indio_dev)
return -ENOMEM;
info = iio_priv(indio_dev);
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
dev_err(&pdev->dev, "no irq resource?\n");
return info->irq;
}
platform_set_drvdata(pdev, indio_dev);
info->regmap = axp20x->regmap;
/*
* Set ADC to enabled state at all time, including system suspend.
* otherwise internal fuel gauge functionality may be affected.
*/
ret = axp288_adc_set_state(axp20x->regmap);
if (ret) {
dev_err(&pdev->dev, "unable to enable ADC device\n");
return ret;
}
indio_dev->dev.parent = &pdev->dev;
indio_dev->name = pdev->name;
indio_dev->channels = axp288_adc_channels;
indio_dev->num_channels = ARRAY_SIZE(axp288_adc_channels);
indio_dev->info = &axp288_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
ret = iio_map_array_register(indio_dev, axp288_adc_default_maps);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&pdev->dev, "unable to register iio device\n");
goto err_array_unregister;
}
return 0;
err_array_unregister:
iio_map_array_unregister(indio_dev);
return ret;
}
static int axp288_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
iio_map_array_unregister(indio_dev);
return 0;
}
static struct platform_device_id axp288_adc_id_table[] = {
{ .name = "axp288_adc" },
{},
};
static struct platform_driver axp288_adc_driver = {
.probe = axp288_adc_probe,
.remove = axp288_adc_remove,
.id_table = axp288_adc_id_table,
.driver = {
.name = "axp288_adc",
},
};
MODULE_DEVICE_TABLE(platform, axp288_adc_id_table);
module_platform_driver(axp288_adc_driver);
MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@linux.intel.com>");
MODULE_DESCRIPTION("X-Powers AXP288 ADC Driver");
MODULE_LICENSE("GPL");
......@@ -59,6 +59,17 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the
functionality of the device.
config MFD_ATMEL_HLCDC
tristate "Atmel HLCDC (High-end LCD Controller)"
select MFD_CORE
select REGMAP_MMIO
depends on OF
help
If you say yes here you get support for the HLCDC block.
This driver provides common support for accessing the device,
additional drivers must be enabled in order to use the
functionality of the device.
config MFD_BCM590XX
tristate "Broadcom BCM590xx PMUs"
select MFD_CORE
......@@ -74,7 +85,8 @@ config MFD_AXP20X
select REGMAP_IRQ
depends on I2C=y
help
If you say Y here you get support for the X-Powers AXP202 and AXP209.
If you say Y here you get support for the X-Powers AXP202, AXP209 and
AXP288 power management IC (PMIC).
This driver include only the core APIs. You have to select individual
components like regulators or the PEK (Power Enable Key) under the
corresponding menus.
......@@ -183,6 +195,16 @@ config MFD_DA9063
Additional drivers must be enabled in order to use the functionality
of the device.
config MFD_DLN2
tristate "Diolan DLN2 support"
select MFD_CORE
depends on USB
help
This adds support for Diolan USB-I2C/SPI/GPIO Master Adapter
DLN-2. Additional drivers such as I2C_DLN2, GPIO_DLN2,
etc. must be enabled in order to use the functionality of
the device.
config MFD_MC13XXX
tristate
depends on (SPI_MASTER || I2C)
......@@ -655,7 +677,6 @@ 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,
......
......@@ -13,7 +13,7 @@ obj-$(CONFIG_MFD_CROS_EC) += cros_ec.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
rtsx_pci-objs := rtsx_pcr.o rtsx_gops.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
obj-$(CONFIG_MFD_RTSX_USB) += rtsx_usb.o
......@@ -157,6 +157,7 @@ obj-$(CONFIG_MFD_SPMI_PMIC) += qcom-spmi-pmic.o
obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o
obj-$(CONFIG_MFD_TPS65090) += tps65090.o
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o
obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
obj-$(CONFIG_MFD_PALMAS) += palmas.o
obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
......@@ -174,6 +175,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
......@@ -85,63 +85,6 @@ static void ab8500_power_off(void)
}
}
/*
* Use the AB WD to reset the platform. It will perform a hard
* reset instead of a soft reset. Write the reset reason to
* the AB before reset, which can be read upon restart.
*/
void ab8500_restart(char mode, const char *cmd)
{
struct ab8500_platform_data *plat;
struct ab8500_sysctrl_platform_data *pdata;
u16 reason = 0;
u8 val;
if (sysctrl_dev == NULL) {
pr_err("%s: sysctrl not initialized\n", __func__);
return;
}
plat = dev_get_platdata(sysctrl_dev->parent);
pdata = plat->sysctrl;
if (pdata && pdata->reboot_reason_code)
reason = pdata->reboot_reason_code(cmd);
else
pr_warn("[%s] No reboot reason set. Default reason %d\n",
__func__, reason);
/*
* Disable RTC alarm, just a precaution so that no alarm
* is running when WD reset is executed.
*/
abx500_get_register_interruptible(sysctrl_dev, AB8500_RTC,
RTC_CTRL , &val);
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
RTC_CTRL , (val & ~RTC_ALARM_ENABLE));
/*
* Android is not using the RTC alarm registers during reboot
* so we borrow them for writing the reason of reset
*/
/* reason[8 LSB] */
val = reason & 0xFF;
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
AB8500_ALARM_MIN_LOW , val);
/* reason[8 MSB] */
val = (reason>>8) & 0xFF;
abx500_set_register_interruptible(sysctrl_dev, AB8500_RTC,
AB8500_ALARM_MIN_MID , val);
/* Setting WD timeout to 0 */
ab8500_sysctrl_write(AB8500_MAINWDOGTIMER, 0xFF, 0x0);
/* Setting the parameters to AB8500 WD*/
ab8500_sysctrl_write(AB8500_MAINWDOGCTRL, 0xFF, (AB8500_ENABLE_WD |
AB8500_WD_RESTART_ON_EXPIRE | AB8500_KICK_WD));
}
static inline bool valid_bank(u8 bank)
{
return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
......
......@@ -75,7 +75,9 @@ static int arizona_spi_probe(struct spi_device *spi)
static int arizona_spi_remove(struct spi_device *spi)
{
struct arizona *arizona = spi_get_drvdata(spi);
arizona_dev_exit(arizona);
return 0;
}
......
/*
* Copyright (C) 2014 Free Electrons
* Copyright (C) 2014 Atmel
*
* Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
#include <linux/mfd/atmel-hlcdc.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define ATMEL_HLCDC_REG_MAX (0x4000 - 0x4)
static const struct mfd_cell atmel_hlcdc_cells[] = {
{
.name = "atmel-hlcdc-pwm",
.of_compatible = "atmel,hlcdc-pwm",
},
{
.name = "atmel-hlcdc-dc",
.of_compatible = "atmel,hlcdc-display-controller",
},
};
static const struct regmap_config atmel_hlcdc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = ATMEL_HLCDC_REG_MAX,
};
static int atmel_hlcdc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct atmel_hlcdc *hlcdc;
struct resource *res;
void __iomem *regs;
hlcdc = devm_kzalloc(dev, sizeof(*hlcdc), GFP_KERNEL);
if (!hlcdc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
hlcdc->irq = platform_get_irq(pdev, 0);
if (hlcdc->irq < 0)
return hlcdc->irq;
hlcdc->periph_clk = devm_clk_get(dev, "periph_clk");
if (IS_ERR(hlcdc->periph_clk)) {
dev_err(dev, "failed to get peripheral clock\n");
return PTR_ERR(hlcdc->periph_clk);
}
hlcdc->sys_clk = devm_clk_get(dev, "sys_clk");
if (IS_ERR(hlcdc->sys_clk)) {
dev_err(dev, "failed to get system clock\n");
return PTR_ERR(hlcdc->sys_clk);
}
hlcdc->slow_clk = devm_clk_get(dev, "slow_clk");
if (IS_ERR(hlcdc->slow_clk)) {
dev_err(dev, "failed to get slow clock\n");
return PTR_ERR(hlcdc->slow_clk);
}
hlcdc->regmap = devm_regmap_init_mmio(dev, regs,
&atmel_hlcdc_regmap_config);
if (IS_ERR(hlcdc->regmap))
return PTR_ERR(hlcdc->regmap);
dev_set_drvdata(dev, hlcdc);
return mfd_add_devices(dev, -1, atmel_hlcdc_cells,
ARRAY_SIZE(atmel_hlcdc_cells),
NULL, 0, NULL);
}
static int atmel_hlcdc_remove(struct platform_device *pdev)
{
mfd_remove_devices(&pdev->dev);
return 0;
}
static const struct of_device_id atmel_hlcdc_match[] = {
{ .compatible = "atmel,sama5d3-hlcdc" },
{ /* sentinel */ },
};
static struct platform_driver atmel_hlcdc_driver = {
.probe = atmel_hlcdc_probe,
.remove = atmel_hlcdc_remove,
.driver = {
.name = "atmel-hlcdc",
.of_match_table = atmel_hlcdc_match,
},
};
module_platform_driver(atmel_hlcdc_driver);
MODULE_ALIAS("platform:atmel-hlcdc");
MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
MODULE_DESCRIPTION("Atmel HLCDC driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
......@@ -118,7 +118,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
da9063->irq_base = pdata->irq_base;
} else {
da9063->flags = 0;
da9063->irq_base = 0;
da9063->irq_base = -1;
}
da9063->chip_irq = irq;
......@@ -168,6 +168,8 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
return ret;
}
da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
NULL);
......
......@@ -3150,23 +3150,28 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu");
if (!res) {
dev_err(&pdev->dev, "no prcmu memory region provided\n");
return -ENOENT;
return -EINVAL;
}
prcmu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!prcmu_base) {
dev_err(&pdev->dev,
"failed to ioremap prcmu register memory\n");
return -ENOENT;
return -ENOMEM;
}
init_prcm_registers();
dbx500_fw_version_init(pdev, pdata->version_offset);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
if (!res) {
dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
return -ENOENT;
return -EINVAL;
}
tcdm_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!tcdm_base) {
dev_err(&pdev->dev,
"failed to ioremap prcmu-tcdm register memory\n");
return -ENOMEM;
}
/* Clean up the mailbox interrupts after pre-kernel code. */
writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
......@@ -3174,15 +3179,14 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev, "no prcmu irq provided\n");
return -ENOENT;
return irq;
}
err = request_threaded_irq(irq, prcmu_irq_handler,
prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
if (err < 0) {
pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
err = -EBUSY;
goto no_irq_return;
return err;
}
db8500_irq_init(np);
......@@ -3206,7 +3210,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
if (err) {
mfd_remove_devices(&pdev->dev);
pr_err("prcmu: Failed to add subdevices\n");
goto no_irq_return;
return err;
}
}
......@@ -3214,12 +3218,10 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
if (err) {
mfd_remove_devices(&pdev->dev);
pr_err("prcmu: Failed to add ab8500 subdevice\n");
goto no_irq_return;
return err;
}
pr_info("DB8500 PRCMU initialized\n");
no_irq_return:
return err;
}
static const struct of_device_id db8500_prcmu_match[] = {
......
This diff is collapsed.
......@@ -193,11 +193,7 @@ static int lpc_sch_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
}
ret = mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
if (ret)
mfd_remove_devices(&dev->dev);
return ret;
return mfd_add_devices(&dev->dev, 0, lpc_sch_cells, cells, NULL, 0, NULL);
}
static void lpc_sch_remove(struct pci_dev *dev)
......
/*
* max14577.c - mfd core driver for the Maxim 14577/77836
*
* Copyright (C) 2014 Samsung Electrnoics
* Copyright (C) 2014 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
*
......
......@@ -43,9 +43,15 @@
static const struct mfd_cell max77693_devs[] = {
{ .name = "max77693-pmic", },
{ .name = "max77693-charger", },
{
.name = "max77693-charger",
.of_compatible = "maxim,max77693-charger",
},
{ .name = "max77693-muic", },
{ .name = "max77693-haptic", },
{
.name = "max77693-haptic",
.of_compatible = "maxim,max77693-haptic",
},
{
.name = "max77693-flash",
.of_compatible = "maxim,max77693-flash",
......@@ -147,6 +153,12 @@ static const struct regmap_irq_chip max77693_muic_irq_chip = {
.num_irqs = ARRAY_SIZE(max77693_muic_irqs),
};
static const struct regmap_config max77693_regmap_haptic_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = MAX77693_HAPTIC_REG_END,
};
static int max77693_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
......@@ -196,6 +208,15 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
}
i2c_set_clientdata(max77693->haptic, max77693);
max77693->regmap_haptic = devm_regmap_init_i2c(max77693->haptic,
&max77693_regmap_haptic_config);
if (IS_ERR(max77693->regmap_haptic)) {
ret = PTR_ERR(max77693->regmap_haptic);
dev_err(max77693->dev,
"failed to initialize haptic register map: %d\n", ret);
goto err_regmap;
}
/*
* Initialize register map for MUIC device because use regmap-muic
* instance of MUIC device when irq of max77693 is initialized
......@@ -207,7 +228,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(max77693->regmap_muic);
dev_err(max77693->dev,
"failed to allocate register map: %d\n", ret);
goto err_regmap_muic;
goto err_regmap;
}
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
......@@ -217,7 +238,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
&max77693->irq_data_led);
if (ret) {
dev_err(max77693->dev, "failed to add irq chip: %d\n", ret);
goto err_regmap_muic;
goto err_regmap;
}
ret = regmap_add_irq_chip(max77693->regmap, max77693->irq,
......@@ -280,7 +301,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
regmap_del_irq_chip(max77693->irq, max77693->irq_data_topsys);
err_irq_topsys:
regmap_del_irq_chip(max77693->irq, max77693->irq_data_led);
err_regmap_muic:
err_regmap:
i2c_unregister_device(max77693->haptic);
err_i2c_haptic:
i2c_unregister_device(max77693->muic);
......
......@@ -125,9 +125,15 @@ static int mfd_add_device(struct device *parent, int id,
struct platform_device *pdev;
struct device_node *np = NULL;
int ret = -ENOMEM;
int platform_id;
int r;
pdev = platform_device_alloc(cell->name, id + cell->id);
if (id < 0)
platform_id = id;
else
platform_id = id + cell->id;
pdev = platform_device_alloc(cell->name, platform_id);
if (!pdev)
goto fail_alloc;
......
......@@ -130,6 +130,12 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
{
int err;
err = rtsx_gops_pm_reset(pcr);
if (err < 0)
return err;
/* Optimize RX sensitivity */
return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
}
......
......@@ -130,6 +130,10 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
{
int err;
err = rtsx_gops_pm_reset(pcr);
if (err < 0)
return err;
err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
......
/* Driver for Realtek PCI-Express card reader
*
* Copyright(c) 2009-2013 Realtek Semiconductor Corp. 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 as published by the
* Free Software Foundation; either version 2, 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, see <http://www.gnu.org/licenses/>.
*
* Author:
* Micky Ching <micky_ching@realsil.com.cn>
*/
#include <linux/mfd/rtsx_pci.h>
#include "rtsx_pcr.h"
int rtsx_gops_pm_reset(struct rtsx_pcr *pcr)
{
int err;
/* init aspm */
rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0xFF, 0x00);
err = rtsx_pci_update_cfg_byte(pcr, LCTLR, ~LCTLR_ASPM_CTL_MASK, 0x00);
if (err < 0)
return err;
/* reset PM_CTRL3 before send buffer cmd */
return rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
}
......@@ -72,4 +72,7 @@ do { \
pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
} while (0)
/* generic operations */
int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
#endif
......@@ -647,8 +647,8 @@ static int rtsx_usb_probe(struct usb_interface *intf,
/* initialize USB SG transfer timer */
setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
ARRAY_SIZE(rtsx_usb_cells));
if (ret)
goto out_init_fail;
......
......@@ -27,11 +27,11 @@
#include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.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[] = {
......@@ -74,6 +74,15 @@ static const struct mfd_cell s2mps11_devs[] = {
}
};
static const struct mfd_cell s2mps13_devs[] = {
{ .name = "s2mps13-pmic", },
{ .name = "s2mps13-rtc", },
{
.name = "s2mps13-clk",
.of_compatible = "samsung,s2mps13-clk",
},
};
static const struct mfd_cell s2mps14_devs[] = {
{
.name = "s2mps14-pmic",
......@@ -107,6 +116,9 @@ static const struct of_device_id sec_dt_match[] = {
}, {
.compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X,
}, {
.compatible = "samsung,s2mps13-pmic",
.data = (void *)S2MPS13X,
}, {
.compatible = "samsung,s2mps14-pmic",
.data = (void *)S2MPS14X,
......@@ -194,6 +206,15 @@ static const struct regmap_config s2mps11_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps13_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS13_REG_LDODSCH5,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps14_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -325,6 +346,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
case S2MPS11X:
regmap = &s2mps11_regmap_config;
break;
case S2MPS13X:
regmap = &s2mps13_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
break;
......@@ -378,6 +402,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
sec_devs = s2mps11_devs;
num_sec_devs = ARRAY_SIZE(s2mps11_devs);
break;
case S2MPS13X:
sec_devs = s2mps13_devs;
num_sec_devs = ARRAY_SIZE(s2mps13_devs);
break;
case S2MPS14X:
sec_devs = s2mps14_devs;
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
......@@ -432,15 +460,6 @@ 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;
}
......
......@@ -389,14 +389,22 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
.ack_base = S2MPS11_REG_INT1,
};
#define S2MPS1X_IRQ_CHIP_COMMON_DATA \
.irqs = s2mps14_irqs, \
.num_irqs = ARRAY_SIZE(s2mps14_irqs), \
.num_regs = 3, \
.status_base = S2MPS14_REG_INT1, \
.mask_base = S2MPS14_REG_INT1M, \
.ack_base = S2MPS14_REG_INT1 \
static const struct regmap_irq_chip s2mps13_irq_chip = {
.name = "s2mps13",
S2MPS1X_IRQ_CHIP_COMMON_DATA,
};
static const struct regmap_irq_chip s2mps14_irq_chip = {
.name = "s2mps14",
.irqs = s2mps14_irqs,
.num_irqs = ARRAY_SIZE(s2mps14_irqs),
.num_regs = 3,
.status_base = S2MPS14_REG_INT1,
.mask_base = S2MPS14_REG_INT1M,
.ack_base = S2MPS14_REG_INT1,
S2MPS1X_IRQ_CHIP_COMMON_DATA,
};
static const struct regmap_irq_chip s2mpu02_irq_chip = {
......@@ -452,6 +460,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
case S2MPS11X:
sec_irq_chip = &s2mps11_irq_chip;
break;
case S2MPS13X:
sec_irq_chip = &s2mps13_irq_chip;
break;
case S2MPS14X:
sec_irq_chip = &s2mps14_irq_chip;
break;
......
......@@ -15,6 +15,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
......@@ -22,31 +23,94 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
static struct platform_driver syscon_driver;
static DEFINE_SPINLOCK(syscon_list_slock);
static LIST_HEAD(syscon_list);
struct syscon {
struct device_node *np;
struct regmap *regmap;
struct list_head list;
};
static struct regmap_config syscon_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static int syscon_match_node(struct device *dev, void *data)
static struct syscon *of_syscon_register(struct device_node *np)
{
struct device_node *dn = data;
struct syscon *syscon;
struct regmap *regmap;
void __iomem *base;
int ret;
struct regmap_config syscon_config = syscon_regmap_config;
if (!of_device_is_compatible(np, "syscon"))
return ERR_PTR(-EINVAL);
syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
if (!syscon)
return ERR_PTR(-ENOMEM);
base = of_iomap(np, 0);
if (!base) {
ret = -ENOMEM;
goto err_map;
}
/* Parse the device's DT node for an endianness specification */
if (of_property_read_bool(np, "big-endian"))
syscon_config.val_format_endian = REGMAP_ENDIAN_BIG;
else if (of_property_read_bool(np, "little-endian"))
syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) {
pr_err("regmap init failed\n");
ret = PTR_ERR(regmap);
goto err_regmap;
}
syscon->regmap = regmap;
syscon->np = np;
spin_lock(&syscon_list_slock);
list_add_tail(&syscon->list, &syscon_list);
spin_unlock(&syscon_list_slock);
return (dev->of_node == dn) ? 1 : 0;
return syscon;
err_regmap:
iounmap(base);
err_map:
kfree(syscon);
return ERR_PTR(ret);
}
struct regmap *syscon_node_to_regmap(struct device_node *np)
{
struct syscon *syscon;
struct device *dev;
struct syscon *entry, *syscon = NULL;
dev = driver_find_device(&syscon_driver.driver, NULL, np,
syscon_match_node);
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
spin_lock(&syscon_list_slock);
syscon = dev_get_drvdata(dev);
list_for_each_entry(entry, &syscon_list, list)
if (entry->np == np) {
syscon = entry;
break;
}
spin_unlock(&syscon_list_slock);
if (!syscon)
syscon = of_syscon_register(np);
if (IS_ERR(syscon))
return ERR_CAST(syscon);
return syscon->regmap;
}
......@@ -110,17 +174,6 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
static const struct of_device_id of_syscon_match[] = {
{ .compatible = "syscon", },
{ },
};
static struct regmap_config syscon_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static int syscon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
......@@ -167,7 +220,6 @@ static struct platform_driver syscon_driver = {
.driver = {
.name = "syscon",
.owner = THIS_MODULE,
.of_match_table = of_syscon_match,
},
.probe = syscon_probe,
.id_table = syscon_ids,
......
......@@ -87,7 +87,7 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
unsigned long flags;
u8 dev_ctl;
clk_enable(t7l66xb->clk32k);
clk_prepare_enable(t7l66xb->clk32k);
spin_lock_irqsave(&t7l66xb->lock, flags);
......@@ -118,7 +118,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
spin_unlock_irqrestore(&t7l66xb->lock, flags);
clk_disable(t7l66xb->clk32k);
clk_disable_unprepare(t7l66xb->clk32k);
return 0;
}
......@@ -285,7 +285,7 @@ static int t7l66xb_suspend(struct platform_device *dev, pm_message_t state)
if (pdata && pdata->suspend)
pdata->suspend(dev);
clk_disable(t7l66xb->clk48m);
clk_disable_unprepare(t7l66xb->clk48m);
return 0;
}
......@@ -295,7 +295,7 @@ static int t7l66xb_resume(struct platform_device *dev)
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
clk_enable(t7l66xb->clk48m);
clk_prepare_enable(t7l66xb->clk48m);
if (pdata && pdata->resume)
pdata->resume(dev);
......@@ -369,7 +369,7 @@ static int t7l66xb_probe(struct platform_device *dev)
goto err_ioremap;
}
clk_enable(t7l66xb->clk48m);
clk_prepare_enable(t7l66xb->clk48m);
if (pdata && pdata->enable)
pdata->enable(dev);
......@@ -414,9 +414,9 @@ static int t7l66xb_remove(struct platform_device *dev)
int ret;
ret = pdata->disable(dev);
clk_disable(t7l66xb->clk48m);
clk_disable_unprepare(t7l66xb->clk48m);
clk_put(t7l66xb->clk48m);
clk_disable(t7l66xb->clk32k);
clk_disable_unprepare(t7l66xb->clk32k);
clk_put(t7l66xb->clk32k);
t7l66xb_detach_irq(dev);
iounmap(t7l66xb->scr);
......
......@@ -241,10 +241,8 @@ static struct irq_domain_ops tc3589x_irq_ops = {
static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
{
int base = tc3589x->irq_base;
tc3589x->domain = irq_domain_add_simple(
np, TC3589x_NR_INTERNAL_IRQS, base,
np, TC3589x_NR_INTERNAL_IRQS, 0,
&tc3589x_irq_ops, tc3589x);
if (!tc3589x->domain) {
......@@ -298,7 +296,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
if (blocks & TC3589x_BLOCK_GPIO) {
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
ARRAY_SIZE(tc3589x_dev_gpio), NULL,
tc3589x->irq_base, tc3589x->domain);
0, tc3589x->domain);
if (ret) {
dev_err(tc3589x->dev, "failed to add gpio child\n");
return ret;
......@@ -309,7 +307,7 @@ static int tc3589x_device_init(struct tc3589x *tc3589x)
if (blocks & TC3589x_BLOCK_KEYPAD) {
ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
ARRAY_SIZE(tc3589x_dev_keypad), NULL,
tc3589x->irq_base, tc3589x->domain);
0, tc3589x->domain);
if (ret) {
dev_err(tc3589x->dev, "failed to keypad child\n");
return ret;
......@@ -404,7 +402,6 @@ static int tc3589x_probe(struct i2c_client *i2c,
tc3589x->dev = &i2c->dev;
tc3589x->i2c = i2c;
tc3589x->pdata = pdata;
tc3589x->irq_base = pdata->irq_base;
switch (version) {
case TC3589X_TC35893:
......
......@@ -52,7 +52,7 @@ static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
if (pdata && pdata->suspend)
pdata->suspend(dev);
clk_disable(tc6387xb->clk32k);
clk_disable_unprepare(tc6387xb->clk32k);
return 0;
}
......@@ -62,7 +62,7 @@ static int tc6387xb_resume(struct platform_device *dev)
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
struct tc6387xb_platform_data *pdata = dev_get_platdata(&dev->dev);
clk_enable(tc6387xb->clk32k);
clk_prepare_enable(tc6387xb->clk32k);
if (pdata && pdata->resume)
pdata->resume(dev);
......@@ -100,7 +100,7 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
clk_enable(tc6387xb->clk32k);
clk_prepare_enable(tc6387xb->clk32k);
tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
tc6387xb_mmc_resources[0].start & 0xfffe);
......@@ -113,7 +113,7 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc)
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
clk_disable(tc6387xb->clk32k);
clk_disable_unprepare(tc6387xb->clk32k);
return 0;
}
......@@ -214,7 +214,7 @@ static int tc6387xb_remove(struct platform_device *dev)
mfd_remove_devices(&dev->dev);
iounmap(tc6387xb->scr);
release_resource(&tc6387xb->rscr);
clk_disable(tc6387xb->clk32k);
clk_disable_unprepare(tc6387xb->clk32k);
clk_put(tc6387xb->clk32k);
kfree(tc6387xb);
......
......@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct platform_device *dev)
return 0;
}
static int tc6393xb_ohci_suspend(struct platform_device *dev)
{
struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent);
/* We can't properly store/restore OHCI state, so fail here */
if (tcpd->resume_restore)
return -EBUSY;
return tc6393xb_ohci_disable(dev);
}
static int tc6393xb_fb_enable(struct platform_device *dev)
{
struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
......@@ -403,7 +414,7 @@ static struct mfd_cell tc6393xb_cells[] = {
.num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
.resources = tc6393xb_ohci_resources,
.enable = tc6393xb_ohci_enable,
.suspend = tc6393xb_ohci_disable,
.suspend = tc6393xb_ohci_suspend,
.resume = tc6393xb_ohci_enable,
.disable = tc6393xb_ohci_disable,
},
......@@ -654,7 +665,7 @@ static int tc6393xb_probe(struct platform_device *dev)
goto err_ioremap;
}
ret = clk_enable(tc6393xb->clk);
ret = clk_prepare_enable(tc6393xb->clk);
if (ret)
goto err_clk_enable;
......@@ -717,7 +728,7 @@ static int tc6393xb_probe(struct platform_device *dev)
gpiochip_remove(&tc6393xb->gpio);
tcpd->disable(dev);
err_enable:
clk_disable(tc6393xb->clk);
clk_disable_unprepare(tc6393xb->clk);
err_clk_enable:
iounmap(tc6393xb->scr);
err_ioremap:
......@@ -748,7 +759,7 @@ static int tc6393xb_remove(struct platform_device *dev)
gpiochip_remove(&tc6393xb->gpio);
ret = tcpd->disable(dev);
clk_disable(tc6393xb->clk);
clk_disable_unprepare(tc6393xb->clk);
iounmap(tc6393xb->scr);
release_resource(&tc6393xb->rscr);
clk_put(tc6393xb->clk);
......@@ -776,7 +787,7 @@ static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
}
ret = tcpd->suspend(dev);
clk_disable(tc6393xb->clk);
clk_disable_unprepare(tc6393xb->clk);
return ret;
}
......@@ -788,7 +799,7 @@ static int tc6393xb_resume(struct platform_device *dev)
int ret;
int i;
clk_enable(tc6393xb->clk);
clk_prepare_enable(tc6393xb->clk);
ret = tcpd->resume(dev);
if (ret)
......
......@@ -33,9 +33,11 @@
static const struct mfd_cell tps65217s[] = {
{
.name = "tps65217-pmic",
.of_compatible = "ti,tps65217-pmic",
},
{
.name = "tps65217-bl",
.of_compatible = "ti,tps65217-bl",
},
};
......
......@@ -830,6 +830,9 @@ static struct twl4030_power_data osc_off_idle = {
};
static struct of_device_id twl4030_power_of_match[] = {
{
.compatible = "ti,twl4030-power",
},
{
.compatible = "ti,twl4030-power-reset",
.data = &omap3_reset,
......
......@@ -93,9 +93,8 @@ static int vprbrd_probe(struct usb_interface *interface,
version >> 8, version & 0xff,
vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
ret = mfd_add_devices(&interface->dev, PLATFORM_DEVID_AUTO,
vprbrd_devs, ARRAY_SIZE(vprbrd_devs), NULL, 0,
NULL);
ret = mfd_add_hotplug_devices(&interface->dev, vprbrd_devs,
ARRAY_SIZE(vprbrd_devs));
if (ret != 0) {
dev_err(&interface->dev, "Failed to add mfd devices to core.");
goto error;
......
......@@ -336,8 +336,6 @@ static const struct reg_default wm5102_reg_default[] = {
{ 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
{ 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
{ 0x00000225, 0x0400 }, /* R549 - HP Ctrl 1L */
{ 0x00000226, 0x0400 }, /* R550 - HP Ctrl 1R */
{ 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */
{ 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */
{ 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */
......@@ -1112,6 +1110,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_MIC_BIAS_CTRL_1:
case ARIZONA_MIC_BIAS_CTRL_2:
case ARIZONA_MIC_BIAS_CTRL_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_ACCESSORY_DETECT_MODE_1:
case ARIZONA_HEADPHONE_DETECT_1:
case ARIZONA_HEADPHONE_DETECT_2:
......@@ -1949,6 +1949,8 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP1_SCRATCH_1:
case ARIZONA_DSP1_SCRATCH_2:
case ARIZONA_DSP1_SCRATCH_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_HEADPHONE_DETECT_2:
case ARIZONA_HP_DACVAL:
case ARIZONA_MIC_DETECT_3:
......
......@@ -895,8 +895,16 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */
{ 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */
{ 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */
{ 0x0000054B, 0x0002 }, /* R1355 - AIF2 Frame Ctrl 5 */
{ 0x0000054C, 0x0003 }, /* R1356 - AIF2 Frame Ctrl 6 */
{ 0x0000054D, 0x0004 }, /* R1357 - AIF2 Frame Ctrl 7 */
{ 0x0000054E, 0x0005 }, /* R1358 - AIF2 Frame Ctrl 8 */
{ 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */
{ 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */
{ 0x00000553, 0x0002 }, /* R1363 - AIF2 Frame Ctrl 13 */
{ 0x00000554, 0x0003 }, /* R1364 - AIF2 Frame Ctrl 14 */
{ 0x00000555, 0x0004 }, /* R1365 - AIF2 Frame Ctrl 15 */
{ 0x00000556, 0x0005 }, /* R1366 - AIF2 Frame Ctrl 16 */
{ 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */
{ 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */
{ 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */
......@@ -1790,6 +1798,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_MIC_BIAS_CTRL_1:
case ARIZONA_MIC_BIAS_CTRL_2:
case ARIZONA_MIC_BIAS_CTRL_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_ACCESSORY_DETECT_MODE_1:
case ARIZONA_HEADPHONE_DETECT_1:
case ARIZONA_HEADPHONE_DETECT_2:
......@@ -1934,8 +1944,16 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_AIF2_FRAME_CTRL_2:
case ARIZONA_AIF2_FRAME_CTRL_3:
case ARIZONA_AIF2_FRAME_CTRL_4:
case ARIZONA_AIF2_FRAME_CTRL_5:
case ARIZONA_AIF2_FRAME_CTRL_6:
case ARIZONA_AIF2_FRAME_CTRL_7:
case ARIZONA_AIF2_FRAME_CTRL_8:
case ARIZONA_AIF2_FRAME_CTRL_11:
case ARIZONA_AIF2_FRAME_CTRL_12:
case ARIZONA_AIF2_FRAME_CTRL_13:
case ARIZONA_AIF2_FRAME_CTRL_14:
case ARIZONA_AIF2_FRAME_CTRL_15:
case ARIZONA_AIF2_FRAME_CTRL_16:
case ARIZONA_AIF2_TX_ENABLES:
case ARIZONA_AIF2_RX_ENABLES:
case ARIZONA_AIF3_BCLK_CTRL:
......@@ -2825,6 +2843,8 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
case ARIZONA_MIC_DETECT_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_HEADPHONE_DETECT_2:
case ARIZONA_INPUT_ENABLES_STATUS:
case ARIZONA_OUTPUT_STATUS_1:
......
......@@ -308,7 +308,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
goto err;
}
mode = id2 & WM8350_CONF_STS_MASK >> 10;
mode = (id2 & WM8350_CONF_STS_MASK) >> 10;
cust_id = id2 & WM8350_CUST_ID_MASK;
chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
dev_info(wm8350->dev,
......
......@@ -670,6 +670,7 @@ static const struct reg_default wm8997_reg_default[] = {
{ 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */
{ 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */
{ 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */
{ 0x00000D09, 0xFFFF }, /* R3337 - Interrupt Status 2 Mask */
{ 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */
{ 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */
{ 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */
......@@ -886,6 +887,8 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_MIC_BIAS_CTRL_1:
case ARIZONA_MIC_BIAS_CTRL_2:
case ARIZONA_MIC_BIAS_CTRL_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_ACCESSORY_DETECT_MODE_1:
case ARIZONA_HEADPHONE_DETECT_1:
case ARIZONA_HEADPHONE_DETECT_2:
......@@ -1328,6 +1331,7 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_INTERRUPT_STATUS_4:
case ARIZONA_INTERRUPT_STATUS_5:
case ARIZONA_INTERRUPT_STATUS_1_MASK:
case ARIZONA_INTERRUPT_STATUS_2_MASK:
case ARIZONA_INTERRUPT_STATUS_3_MASK:
case ARIZONA_INTERRUPT_STATUS_4_MASK:
case ARIZONA_INTERRUPT_STATUS_5_MASK:
......@@ -1477,6 +1481,8 @@ static bool wm8997_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_SAMPLE_RATE_3_STATUS:
case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
case ARIZONA_MIC_DETECT_3:
case ARIZONA_HP_CTRL_1L:
case ARIZONA_HP_CTRL_1R:
case ARIZONA_HEADPHONE_DETECT_2:
case ARIZONA_INPUT_ENABLES_STATUS:
case ARIZONA_OUTPUT_STATUS_1:
......
......@@ -529,13 +529,13 @@ config REGULATOR_S2MPA01
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
tristate "Samsung S2MPS11/S2MPS14/S2MPU02 voltage regulator"
tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator"
depends on MFD_SEC_CORE
help
This driver supports a Samsung S2MPS11/S2MPS14/S2MPU02 voltage output
regulator via I2C bus. The chip is comprised of high efficient Buck
converters including Dual-Phase Buck converter, Buck-Boost converter,
various LDOs.
This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage
output regulator via I2C bus. The chip is comprised of high efficient
Buck converters including Dual-Phase Buck converter, Buck-Boost
converter, various LDOs.
config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator"
......
......@@ -30,6 +30,7 @@
#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
......@@ -45,10 +46,10 @@ struct s2mps11_info {
enum sec_device_type dev_type;
/*
* One bit for each S2MPS14/S2MPU02 regulator whether the suspend mode
* was enabled.
* One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
* the suspend mode was enabled.
*/
unsigned long long s2mps14_suspend_state:35;
unsigned long long s2mps14_suspend_state:50;
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
......@@ -369,12 +370,101 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
};
static struct regulator_ops s2mps14_reg_ops;
#define regulator_desc_s2mps13_ldo(num, min, step, min_sel) { \
.name = "LDO"#num, \
.id = S2MPS13_LDO##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = min, \
.uV_step = step, \
.linear_min_sel = min_sel, \
.n_voltages = S2MPS14_LDO_N_VOLTAGES, \
.vsel_reg = S2MPS13_REG_L1CTRL + num - 1, \
.vsel_mask = S2MPS14_LDO_VSEL_MASK, \
.enable_reg = S2MPS13_REG_L1CTRL + num - 1, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
#define regulator_desc_s2mps13_buck(num, min, step, min_sel) { \
.name = "BUCK"#num, \
.id = S2MPS13_BUCK##num, \
.ops = &s2mps14_reg_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.min_uV = min, \
.uV_step = step, \
.linear_min_sel = min_sel, \
.n_voltages = S2MPS14_BUCK_N_VOLTAGES, \
.ramp_delay = S2MPS13_BUCK_RAMP_DELAY, \
.vsel_reg = S2MPS13_REG_B1OUT + (num - 1) * 2, \
.vsel_mask = S2MPS14_BUCK_VSEL_MASK, \
.enable_reg = S2MPS13_REG_B1CTRL + (num - 1) * 2, \
.enable_mask = S2MPS14_ENABLE_MASK \
}
static const struct regulator_desc s2mps13_regulators[] = {
regulator_desc_s2mps13_ldo(1, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(2, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(3, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(4, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(5, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(6, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(7, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(8, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(9, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(10, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(11, MIN_800_MV, STEP_25_MV, 0x10),
regulator_desc_s2mps13_ldo(12, MIN_800_MV, STEP_25_MV, 0x10),
regulator_desc_s2mps13_ldo(13, MIN_800_MV, STEP_25_MV, 0x10),
regulator_desc_s2mps13_ldo(14, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(15, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(16, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(17, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(18, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(19, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(20, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(21, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(22, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(23, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(24, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(25, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(26, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(27, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(28, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(29, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(30, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(31, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(32, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(33, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(34, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(35, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(36, MIN_800_MV, STEP_12_5_MV, 0x00),
regulator_desc_s2mps13_ldo(37, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(38, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_ldo(39, MIN_1000_MV, STEP_25_MV, 0x08),
regulator_desc_s2mps13_ldo(40, MIN_1400_MV, STEP_50_MV, 0x0C),
regulator_desc_s2mps13_buck(1, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(2, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(3, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(4, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(5, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(6, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(7, MIN_500_MV, STEP_6_25_MV, 0x10),
regulator_desc_s2mps13_buck(8, MIN_1000_MV, STEP_12_5_MV, 0x20),
regulator_desc_s2mps13_buck(9, MIN_1000_MV, STEP_12_5_MV, 0x20),
regulator_desc_s2mps13_buck(10, MIN_500_MV, STEP_6_25_MV, 0x10),
};
static int s2mps14_regulator_enable(struct regulator_dev *rdev)
{
struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev);
unsigned int val;
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
val = S2MPS14_ENABLE_SUSPEND;
......@@ -406,6 +496,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
/* Below LDO should be always on or does not support suspend mode. */
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
switch (rdev_id) {
case S2MPS14_LDO3:
......@@ -831,6 +922,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
break;
case S2MPS13X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
regulators = s2mps13_regulators;
break;
case S2MPS14X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
......@@ -927,6 +1022,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
static const struct platform_device_id s2mps11_pmic_id[] = {
{ "s2mps11-pmic", S2MPS11X},
{ "s2mps13-pmic", S2MPS13X},
{ "s2mps14-pmic", S2MPS14X},
{ "s2mpu02-pmic", S2MPU02},
{ },
......
......@@ -12,7 +12,6 @@
int ab8500_sysctrl_read(u16 reg, u8 *value);
int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value);
void ab8500_restart(char mode, const char *cmd);
#else
......
......@@ -125,6 +125,8 @@
#define ARIZONA_MIC_BIAS_CTRL_1 0x218
#define ARIZONA_MIC_BIAS_CTRL_2 0x219
#define ARIZONA_MIC_BIAS_CTRL_3 0x21A
#define ARIZONA_HP_CTRL_1L 0x225
#define ARIZONA_HP_CTRL_1R 0x226
#define ARIZONA_ACCESSORY_DETECT_MODE_1 0x293
#define ARIZONA_HEADPHONE_DETECT_1 0x29B
#define ARIZONA_HEADPHONE_DETECT_2 0x29C
......@@ -279,8 +281,16 @@
#define ARIZONA_AIF2_FRAME_CTRL_2 0x548
#define ARIZONA_AIF2_FRAME_CTRL_3 0x549
#define ARIZONA_AIF2_FRAME_CTRL_4 0x54A
#define ARIZONA_AIF2_FRAME_CTRL_5 0x54B
#define ARIZONA_AIF2_FRAME_CTRL_6 0x54C
#define ARIZONA_AIF2_FRAME_CTRL_7 0x54D
#define ARIZONA_AIF2_FRAME_CTRL_8 0x54E
#define ARIZONA_AIF2_FRAME_CTRL_11 0x551
#define ARIZONA_AIF2_FRAME_CTRL_12 0x552
#define ARIZONA_AIF2_FRAME_CTRL_13 0x553
#define ARIZONA_AIF2_FRAME_CTRL_14 0x554
#define ARIZONA_AIF2_FRAME_CTRL_15 0x555
#define ARIZONA_AIF2_FRAME_CTRL_16 0x556
#define ARIZONA_AIF2_TX_ENABLES 0x559
#define ARIZONA_AIF2_RX_ENABLES 0x55A
#define ARIZONA_AIF2_FORCE_WRITE 0x55B
......@@ -2244,6 +2254,46 @@
#define ARIZONA_MICB3_ENA_SHIFT 0 /* MICB3_ENA */
#define ARIZONA_MICB3_ENA_WIDTH 1 /* MICB3_ENA */
/*
* R549 (0x225) - HP Ctrl 1L
*/
#define ARIZONA_RMV_SHRT_HP1L 0x4000 /* RMV_SHRT_HP1L */
#define ARIZONA_RMV_SHRT_HP1L_MASK 0x4000 /* RMV_SHRT_HP1L */
#define ARIZONA_RMV_SHRT_HP1L_SHIFT 14 /* RMV_SHRT_HP1L */
#define ARIZONA_RMV_SHRT_HP1L_WIDTH 1 /* RMV_SHRT_HP1L */
#define ARIZONA_HP1L_FLWR 0x0004 /* HP1L_FLWR */
#define ARIZONA_HP1L_FLWR_MASK 0x0004 /* HP1L_FLWR */
#define ARIZONA_HP1L_FLWR_SHIFT 2 /* HP1L_FLWR */
#define ARIZONA_HP1L_FLWR_WIDTH 1 /* HP1L_FLWR */
#define ARIZONA_HP1L_SHRTI 0x0002 /* HP1L_SHRTI */
#define ARIZONA_HP1L_SHRTI_MASK 0x0002 /* HP1L_SHRTI */
#define ARIZONA_HP1L_SHRTI_SHIFT 1 /* HP1L_SHRTI */
#define ARIZONA_HP1L_SHRTI_WIDTH 1 /* HP1L_SHRTI */
#define ARIZONA_HP1L_SHRTO 0x0001 /* HP1L_SHRTO */
#define ARIZONA_HP1L_SHRTO_MASK 0x0001 /* HP1L_SHRTO */
#define ARIZONA_HP1L_SHRTO_SHIFT 0 /* HP1L_SHRTO */
#define ARIZONA_HP1L_SHRTO_WIDTH 1 /* HP1L_SHRTO */
/*
* R550 (0x226) - HP Ctrl 1R
*/
#define ARIZONA_RMV_SHRT_HP1R 0x4000 /* RMV_SHRT_HP1R */
#define ARIZONA_RMV_SHRT_HP1R_MASK 0x4000 /* RMV_SHRT_HP1R */
#define ARIZONA_RMV_SHRT_HP1R_SHIFT 14 /* RMV_SHRT_HP1R */
#define ARIZONA_RMV_SHRT_HP1R_WIDTH 1 /* RMV_SHRT_HP1R */
#define ARIZONA_HP1R_FLWR 0x0004 /* HP1R_FLWR */
#define ARIZONA_HP1R_FLWR_MASK 0x0004 /* HP1R_FLWR */
#define ARIZONA_HP1R_FLWR_SHIFT 2 /* HP1R_FLWR */
#define ARIZONA_HP1R_FLWR_WIDTH 1 /* HP1R_FLWR */
#define ARIZONA_HP1R_SHRTI 0x0002 /* HP1R_SHRTI */
#define ARIZONA_HP1R_SHRTI_MASK 0x0002 /* HP1R_SHRTI */
#define ARIZONA_HP1R_SHRTI_SHIFT 1 /* HP1R_SHRTI */
#define ARIZONA_HP1R_SHRTI_WIDTH 1 /* HP1R_SHRTI */
#define ARIZONA_HP1R_SHRTO 0x0001 /* HP1R_SHRTO */
#define ARIZONA_HP1R_SHRTO_MASK 0x0001 /* HP1R_SHRTO */
#define ARIZONA_HP1R_SHRTO_SHIFT 0 /* HP1R_SHRTO */
#define ARIZONA_HP1R_SHRTO_WIDTH 1 /* HP1R_SHRTO */
/*
* R659 (0x293) - Accessory Detect Mode 1
*/
......
/*
* Copyright (C) 2014 Free Electrons
* Copyright (C) 2014 Atmel
*
* Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __LINUX_MFD_HLCDC_H
#define __LINUX_MFD_HLCDC_H
#include <linux/clk.h>
#include <linux/regmap.h>
#define ATMEL_HLCDC_CFG(i) ((i) * 0x4)
#define ATMEL_HLCDC_SIG_CFG LCDCFG(5)
#define ATMEL_HLCDC_HSPOL BIT(0)
#define ATMEL_HLCDC_VSPOL BIT(1)
#define ATMEL_HLCDC_VSPDLYS BIT(2)
#define ATMEL_HLCDC_VSPDLYE BIT(3)
#define ATMEL_HLCDC_DISPPOL BIT(4)
#define ATMEL_HLCDC_DITHER BIT(6)
#define ATMEL_HLCDC_DISPDLY BIT(7)
#define ATMEL_HLCDC_MODE_MASK GENMASK(9, 8)
#define ATMEL_HLCDC_PP BIT(10)
#define ATMEL_HLCDC_VSPSU BIT(12)
#define ATMEL_HLCDC_VSPHO BIT(13)
#define ATMEL_HLCDC_GUARDTIME_MASK GENMASK(20, 16)
#define ATMEL_HLCDC_EN 0x20
#define ATMEL_HLCDC_DIS 0x24
#define ATMEL_HLCDC_SR 0x28
#define ATMEL_HLCDC_IER 0x2c
#define ATMEL_HLCDC_IDR 0x30
#define ATMEL_HLCDC_IMR 0x34
#define ATMEL_HLCDC_ISR 0x38
#define ATMEL_HLCDC_CLKPOL BIT(0)
#define ATMEL_HLCDC_CLKSEL BIT(2)
#define ATMEL_HLCDC_CLKPWMSEL BIT(3)
#define ATMEL_HLCDC_CGDIS(i) BIT(8 + (i))
#define ATMEL_HLCDC_CLKDIV_SHFT 16
#define ATMEL_HLCDC_CLKDIV_MASK GENMASK(23, 16)
#define ATMEL_HLCDC_CLKDIV(div) ((div - 2) << ATMEL_HLCDC_CLKDIV_SHFT)
#define ATMEL_HLCDC_PIXEL_CLK BIT(0)
#define ATMEL_HLCDC_SYNC BIT(1)
#define ATMEL_HLCDC_DISP BIT(2)
#define ATMEL_HLCDC_PWM BIT(3)
#define ATMEL_HLCDC_SIP BIT(4)
#define ATMEL_HLCDC_SOF BIT(0)
#define ATMEL_HLCDC_SYNCDIS BIT(1)
#define ATMEL_HLCDC_FIFOERR BIT(4)
#define ATMEL_HLCDC_LAYER_STATUS(x) BIT((x) + 8)
/**
* Structure shared by the MFD device and its subdevices.
*
* @regmap: register map used to access HLCDC IP registers
* @periph_clk: the hlcdc peripheral clock
* @sys_clk: the hlcdc system clock
* @slow_clk: the system slow clk
* @irq: the hlcdc irq
*/
struct atmel_hlcdc {
struct regmap *regmap;
struct clk *periph_clk;
struct clk *sys_clk;
struct clk *slow_clk;
int irq;
};
#endif /* __LINUX_MFD_HLCDC_H */
......@@ -14,6 +14,8 @@
enum {
AXP202_ID = 0,
AXP209_ID,
AXP288_ID,
NR_AXP20X_VARIANTS,
};
#define AXP20X_DATACACHE(m) (0x04 + (m))
......@@ -49,11 +51,13 @@ enum {
#define AXP20X_IRQ3_EN 0x42
#define AXP20X_IRQ4_EN 0x43
#define AXP20X_IRQ5_EN 0x44
#define AXP20X_IRQ6_EN 0x45
#define AXP20X_IRQ1_STATE 0x48
#define AXP20X_IRQ2_STATE 0x49
#define AXP20X_IRQ3_STATE 0x4a
#define AXP20X_IRQ4_STATE 0x4b
#define AXP20X_IRQ5_STATE 0x4c
#define AXP20X_IRQ6_STATE 0x4d
/* ADC */
#define AXP20X_ACIN_V_ADC_H 0x56
......@@ -116,6 +120,15 @@ enum {
#define AXP20X_CC_CTRL 0xb8
#define AXP20X_FG_RES 0xb9
/* AXP288 specific registers */
#define AXP288_PMIC_ADC_H 0x56
#define AXP288_PMIC_ADC_L 0x57
#define AXP288_ADC_TS_PIN_CTRL 0x84
#define AXP288_PMIC_ADC_EN 0x84
#define AXP288_FG_TUNE5 0xed
/* Regulators IDs */
enum {
AXP20X_LDO1 = 0,
......@@ -169,12 +182,58 @@ enum {
AXP20X_IRQ_GPIO0_INPUT,
};
enum axp288_irqs {
AXP288_IRQ_VBUS_FALL = 2,
AXP288_IRQ_VBUS_RISE,
AXP288_IRQ_OV,
AXP288_IRQ_FALLING_ALT,
AXP288_IRQ_RISING_ALT,
AXP288_IRQ_OV_ALT,
AXP288_IRQ_DONE = 10,
AXP288_IRQ_CHARGING,
AXP288_IRQ_SAFE_QUIT,
AXP288_IRQ_SAFE_ENTER,
AXP288_IRQ_ABSENT,
AXP288_IRQ_APPEND,
AXP288_IRQ_QWBTU,
AXP288_IRQ_WBTU,
AXP288_IRQ_QWBTO,
AXP288_IRQ_WBTO,
AXP288_IRQ_QCBTU,
AXP288_IRQ_CBTU,
AXP288_IRQ_QCBTO,
AXP288_IRQ_CBTO,
AXP288_IRQ_WL2,
AXP288_IRQ_WL1,
AXP288_IRQ_GPADC,
AXP288_IRQ_OT = 31,
AXP288_IRQ_GPIO0,
AXP288_IRQ_GPIO1,
AXP288_IRQ_POKO,
AXP288_IRQ_POKL,
AXP288_IRQ_POKS,
AXP288_IRQ_POKN,
AXP288_IRQ_POKP,
AXP288_IRQ_TIMER,
AXP288_IRQ_MV_CHNG,
AXP288_IRQ_BC_USB_CHNG,
};
#define AXP288_TS_ADC_H 0x58
#define AXP288_TS_ADC_L 0x59
#define AXP288_GP_ADC_H 0x5a
#define AXP288_GP_ADC_L 0x5b
struct axp20x_dev {
struct device *dev;
struct i2c_client *i2c_client;
struct regmap *regmap;
struct regmap_irq_chip_data *regmap_irqc;
long variant;
int nr_cells;
struct mfd_cell *cells;
const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip;
};
#endif /* __LINUX_MFD_AXP20X_H */
......@@ -111,6 +111,13 @@ extern int mfd_add_devices(struct device *parent, int id,
struct resource *mem_base,
int irq_base, struct irq_domain *irq_domain);
static inline int mfd_add_hotplug_devices(struct device *parent,
const struct mfd_cell *cells, int n_devs)
{
return mfd_add_devices(parent, PLATFORM_DEVID_AUTO, cells, n_devs,
NULL, 0, NULL);
}
extern void mfd_remove_devices(struct device *parent);
#endif
#ifndef __LINUX_USB_DLN2_H
#define __LINUX_USB_DLN2_H
#define DLN2_CMD(cmd, id) ((cmd) | ((id) << 8))
struct dln2_platform_data {
u16 handle; /* sub-driver handle (internally used only) */
u8 port; /* I2C/SPI port */
};
/**
* dln2_event_cb_t - event callback function signature
*
* @pdev - the sub-device that registered this callback
* @echo - the echo header field received in the message
* @data - the data payload
* @len - the data payload length
*
* The callback function is called in interrupt context and the data payload is
* only valid during the call. If the user needs later access of the data, it
* must copy it.
*/
typedef void (*dln2_event_cb_t)(struct platform_device *pdev, u16 echo,
const void *data, int len);
/**
* dl2n_register_event_cb - register a callback function for an event
*
* @pdev - the sub-device that registers the callback
* @event - the event for which to register a callback
* @event_cb - the callback function
*
* @return 0 in case of success, negative value in case of error
*/
int dln2_register_event_cb(struct platform_device *pdev, u16 event,
dln2_event_cb_t event_cb);
/**
* dln2_unregister_event_cb - unregister the callback function for an event
*
* @pdev - the sub-device that registered the callback
* @event - the event for which to register a callback
*/
void dln2_unregister_event_cb(struct platform_device *pdev, u16 event);
/**
* dln2_transfer - issue a DLN2 command and wait for a response and the
* associated data
*
* @pdev - the sub-device which is issuing this transfer
* @cmd - the command to be sent to the device
* @obuf - the buffer to be sent to the device; it can be NULL if the user
* doesn't need to transmit data with this command
* @obuf_len - the size of the buffer to be sent to the device
* @ibuf - any data associated with the response will be copied here; it can be
* NULL if the user doesn't need the response data
* @ibuf_len - must be initialized to the input buffer size; it will be modified
* to indicate the actual data transferred;
*
* @return 0 for success, negative value for errors
*/
int dln2_transfer(struct platform_device *pdev, u16 cmd,
const void *obuf, unsigned obuf_len,
void *ibuf, unsigned *ibuf_len);
/**
* dln2_transfer_rx - variant of @dln2_transfer() where TX buffer is not needed
*
* @pdev - the sub-device which is issuing this transfer
* @cmd - the command to be sent to the device
* @ibuf - any data associated with the response will be copied here; it can be
* NULL if the user doesn't need the response data
* @ibuf_len - must be initialized to the input buffer size; it will be modified
* to indicate the actual data transferred;
*
* @return 0 for success, negative value for errors
*/
static inline int dln2_transfer_rx(struct platform_device *pdev, u16 cmd,
void *ibuf, unsigned *ibuf_len)
{
return dln2_transfer(pdev, cmd, NULL, 0, ibuf, ibuf_len);
}
/**
* dln2_transfer_tx - variant of @dln2_transfer() where RX buffer is not needed
*
* @pdev - the sub-device which is issuing this transfer
* @cmd - the command to be sent to the device
* @obuf - the buffer to be sent to the device; it can be NULL if the
* user doesn't need to transmit data with this command
* @obuf_len - the size of the buffer to be sent to the device
*
* @return 0 for success, negative value for errors
*/
static inline int dln2_transfer_tx(struct platform_device *pdev, u16 cmd,
const void *obuf, unsigned obuf_len)
{
return dln2_transfer(pdev, cmd, obuf, obuf_len, NULL, NULL);
}
#endif
......@@ -26,7 +26,6 @@
#include <linux/i2c.h>
#define MAX77693_NUM_IRQ_MUIC_REGS 3
#define MAX77693_REG_INVALID (0xff)
/* Slave addr = 0xCC: PMIC, Charger, Flash LED */
......
......@@ -558,6 +558,7 @@
#define SD_SAMPLE_POINT_CTL 0xFDA7
#define SD_PUSH_POINT_CTL 0xFDA8
#define SD_CMD0 0xFDA9
#define SD_CMD_START 0x40
#define SD_CMD1 0xFDAA
#define SD_CMD2 0xFDAB
#define SD_CMD3 0xFDAC
......@@ -707,6 +708,14 @@
#define PM_CTRL1 0xFF44
#define PM_CTRL2 0xFF45
#define PM_CTRL3 0xFF46
#define SDIO_SEND_PME_EN 0x80
#define FORCE_RC_MODE_ON 0x40
#define FORCE_RX50_LINK_ON 0x20
#define D3_DELINK_MODE_EN 0x10
#define USE_PESRTB_CTL_DELINK 0x08
#define DELAY_PIN_WAKE 0x04
#define RESET_PIN_WAKE 0x02
#define PM_WAKE_EN 0x01
#define PM_CTRL4 0xFF47
/* Memory mapping */
......@@ -752,6 +761,14 @@
#define PHY_DUM_REG 0x1F
#define LCTLR 0x80
#define LCTLR_EXT_SYNC 0x80
#define LCTLR_COMMON_CLOCK_CFG 0x40
#define LCTLR_RETRAIN_LINK 0x20
#define LCTLR_LINK_DISABLE 0x10
#define LCTLR_RCB 0x08
#define LCTLR_RESERVED 0x04
#define LCTLR_ASPM_CTL_MASK 0x03
#define PCR_SETTING_REG1 0x724
#define PCR_SETTING_REG2 0x814
#define PCR_SETTING_REG3 0x747
......@@ -967,4 +984,24 @@ static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
return (u8 *)(pcr->host_cmds_ptr);
}
static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr,
u8 mask, u8 append)
{
int err;
u8 val;
err = pci_read_config_byte(pcr->pci, addr, &val);
if (err < 0)
return err;
return pci_write_config_byte(pcr->pci, addr, (val & mask) | append);
}
static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val)
{
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg, 0xFF, val >> 24);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 1, 0xFF, val >> 16);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 2, 0xFF, val >> 8);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val);
}
#endif
......@@ -28,6 +28,7 @@
#define MIN_800_MV 800000
#define MIN_750_MV 750000
#define MIN_600_MV 600000
#define MIN_500_MV 500000
/* Macros to represent steps for LDO/BUCK */
#define STEP_50_MV 50000
......@@ -41,6 +42,7 @@ enum sec_device_type {
S5M8767X,
S2MPA01,
S2MPS11X,
S2MPS13X,
S2MPS14X,
S2MPU02,
};
......
/*
* s2mps13.h
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd
* http://www.samsung.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __LINUX_MFD_S2MPS13_H
#define __LINUX_MFD_S2MPS13_H
/* S2MPS13 registers */
enum s2mps13_reg {
S2MPS13_REG_ID,
S2MPS13_REG_INT1,
S2MPS13_REG_INT2,
S2MPS13_REG_INT3,
S2MPS13_REG_INT1M,
S2MPS13_REG_INT2M,
S2MPS13_REG_INT3M,
S2MPS13_REG_ST1,
S2MPS13_REG_ST2,
S2MPS13_REG_PWRONSRC,
S2MPS13_REG_OFFSRC,
S2MPS13_REG_BU_CHG,
S2MPS13_REG_RTCCTRL,
S2MPS13_REG_CTRL1,
S2MPS13_REG_CTRL2,
S2MPS13_REG_RSVD1,
S2MPS13_REG_RSVD2,
S2MPS13_REG_RSVD3,
S2MPS13_REG_RSVD4,
S2MPS13_REG_RSVD5,
S2MPS13_REG_RSVD6,
S2MPS13_REG_CTRL3,
S2MPS13_REG_RSVD7,
S2MPS13_REG_RSVD8,
S2MPS13_REG_WRSTBI,
S2MPS13_REG_B1CTRL,
S2MPS13_REG_B1OUT,
S2MPS13_REG_B2CTRL,
S2MPS13_REG_B2OUT,
S2MPS13_REG_B3CTRL,
S2MPS13_REG_B3OUT,
S2MPS13_REG_B4CTRL,
S2MPS13_REG_B4OUT,
S2MPS13_REG_B5CTRL,
S2MPS13_REG_B5OUT,
S2MPS13_REG_B6CTRL,
S2MPS13_REG_B6OUT,
S2MPS13_REG_B7CTRL,
S2MPS13_REG_B7OUT,
S2MPS13_REG_B8CTRL,
S2MPS13_REG_B8OUT,
S2MPS13_REG_B9CTRL,
S2MPS13_REG_B9OUT,
S2MPS13_REG_B10CTRL,
S2MPS13_REG_B10OUT,
S2MPS13_REG_BB1CTRL,
S2MPS13_REG_BB1OUT,
S2MPS13_REG_BUCK_RAMP1,
S2MPS13_REG_BUCK_RAMP2,
S2MPS13_REG_LDO_DVS1,
S2MPS13_REG_LDO_DVS2,
S2MPS13_REG_LDO_DVS3,
S2MPS13_REG_B6OUT2,
S2MPS13_REG_L1CTRL,
S2MPS13_REG_L2CTRL,
S2MPS13_REG_L3CTRL,
S2MPS13_REG_L4CTRL,
S2MPS13_REG_L5CTRL,
S2MPS13_REG_L6CTRL,
S2MPS13_REG_L7CTRL,
S2MPS13_REG_L8CTRL,
S2MPS13_REG_L9CTRL,
S2MPS13_REG_L10CTRL,
S2MPS13_REG_L11CTRL,
S2MPS13_REG_L12CTRL,
S2MPS13_REG_L13CTRL,
S2MPS13_REG_L14CTRL,
S2MPS13_REG_L15CTRL,
S2MPS13_REG_L16CTRL,
S2MPS13_REG_L17CTRL,
S2MPS13_REG_L18CTRL,
S2MPS13_REG_L19CTRL,
S2MPS13_REG_L20CTRL,
S2MPS13_REG_L21CTRL,
S2MPS13_REG_L22CTRL,
S2MPS13_REG_L23CTRL,
S2MPS13_REG_L24CTRL,
S2MPS13_REG_L25CTRL,
S2MPS13_REG_L26CTRL,
S2MPS13_REG_L27CTRL,
S2MPS13_REG_L28CTRL,
S2MPS13_REG_L30CTRL,
S2MPS13_REG_L31CTRL,
S2MPS13_REG_L32CTRL,
S2MPS13_REG_L33CTRL,
S2MPS13_REG_L34CTRL,
S2MPS13_REG_L35CTRL,
S2MPS13_REG_L36CTRL,
S2MPS13_REG_L37CTRL,
S2MPS13_REG_L38CTRL,
S2MPS13_REG_L39CTRL,
S2MPS13_REG_L40CTRL,
S2MPS13_REG_LDODSCH1,
S2MPS13_REG_LDODSCH2,
S2MPS13_REG_LDODSCH3,
S2MPS13_REG_LDODSCH4,
S2MPS13_REG_LDODSCH5,
};
/* regulator ids */
enum s2mps13_regulators {
S2MPS13_LDO1,
S2MPS13_LDO2,
S2MPS13_LDO3,
S2MPS13_LDO4,
S2MPS13_LDO5,
S2MPS13_LDO6,
S2MPS13_LDO7,
S2MPS13_LDO8,
S2MPS13_LDO9,
S2MPS13_LDO10,
S2MPS13_LDO11,
S2MPS13_LDO12,
S2MPS13_LDO13,
S2MPS13_LDO14,
S2MPS13_LDO15,
S2MPS13_LDO16,
S2MPS13_LDO17,
S2MPS13_LDO18,
S2MPS13_LDO19,
S2MPS13_LDO20,
S2MPS13_LDO21,
S2MPS13_LDO22,
S2MPS13_LDO23,
S2MPS13_LDO24,
S2MPS13_LDO25,
S2MPS13_LDO26,
S2MPS13_LDO27,
S2MPS13_LDO28,
S2MPS13_LDO29,
S2MPS13_LDO30,
S2MPS13_LDO31,
S2MPS13_LDO32,
S2MPS13_LDO33,
S2MPS13_LDO34,
S2MPS13_LDO35,
S2MPS13_LDO36,
S2MPS13_LDO37,
S2MPS13_LDO38,
S2MPS13_LDO39,
S2MPS13_LDO40,
S2MPS13_BUCK1,
S2MPS13_BUCK2,
S2MPS13_BUCK3,
S2MPS13_BUCK4,
S2MPS13_BUCK5,
S2MPS13_BUCK6,
S2MPS13_BUCK7,
S2MPS13_BUCK8,
S2MPS13_BUCK9,
S2MPS13_BUCK10,
S2MPS13_REGULATOR_MAX,
};
/*
* Default ramp delay in uv/us. Datasheet says that ramp delay can be
* controlled however it does not specify which register is used for that.
* Let's assume that default value will be set.
*/
#define S2MPS13_BUCK_RAMP_DELAY 12500
#endif /* __LINUX_MFD_S2MPS13_H */
......@@ -164,13 +164,10 @@ struct tc3589x_keypad_platform_data {
/**
* struct tc3589x_gpio_platform_data - TC3589x GPIO platform data
* @gpio_base: first gpio number assigned to TC3589x. A maximum of
* %TC3589x_NR_GPIOS GPIOs will be allocated.
* @setup: callback for board-specific initialization
* @remove: callback for board-specific teardown
*/
struct tc3589x_gpio_platform_data {
int gpio_base;
void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base);
void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base);
};
......@@ -178,18 +175,13 @@ struct tc3589x_gpio_platform_data {
/**
* struct tc3589x_platform_data - TC3589x platform data
* @block: bitmask of blocks to enable (use TC3589x_BLOCK_*)
* @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used.
* @gpio: GPIO-specific platform data
* @keypad: keypad-specific platform data
*/
struct tc3589x_platform_data {
unsigned int block;
int irq_base;
struct tc3589x_gpio_platform_data *gpio;
const struct tc3589x_keypad_platform_data *keypad;
};
#define TC3589x_NR_GPIOS 24
#define TC3589x_NR_IRQS TC3589x_INT_GPIO(TC3589x_NR_GPIOS)
#endif
......@@ -922,4 +922,15 @@ static inline int of_changeset_update_property(struct of_changeset *ocs,
/* CONFIG_OF_RESOLVE api */
extern int of_resolve_phandles(struct device_node *tree);
/**
* of_system_has_poweroff_source - Tells if poweroff-source is found for device_node
* @np: Pointer to the given device_node
*
* return true if present false otherwise
*/
static inline bool of_system_has_poweroff_source(const struct device_node *np)
{
return of_property_read_bool(np, "poweroff-source");
}
#endif /* _LINUX_OF_H */
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