Commit df9cdc17 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MFD updates from Lee Jones:
 "Core Frameworks:
   - Add new !TOUCHSCREEN_SUN4I dependency for SUN4I_GPADC
   - List include/dt-bindings/mfd/* to files supported in MAINTAINERS

  New Drivers:
   - Intel Apollo Lake SPI NOR
   - ST STM32 Timers (Advanced, Basic and PWM)
   - Motorola 6556002 CPCAP (PMIC)

  New Device Support:
   - Add support for AXP221 to axp20x
   - Add support for Intel Gemini Lake to intel-lpss-pci
   - Add support for MT6323 LED to mt6397-core
   - Add support for COMe-bBD#, COMe-bSL6, COMe-bKL6, COMe-cAL6 and
     COMe-cKL6 to kempld-core

  New Functionality:
   - Add support for Analog CODAC to sun6i-prcm
   - Add support for Watchdog to lpc_ich

  Fix-ups:
   - Error handling improvements; axp288_charger, axp20x, ab8500-sysctrl
   - Adapt platform data handling; axp20x
   - IRQ handling improvements; arizona, axp20x
   - Remove superfluous code; arizona, axp20x, lpc_ich
   - Trivial coding style/spelling fixes; axp20x, abx500, mfd.txt
   - Regmap fix-ups; axp20x
   - DT changes; mfd.txt, aspeed-lpc, aspeed-gfx, ab8500-core, tps65912,
     mt6397
   - Use new I2C probing mechanism; max77686
   - Constification; rk808

  Bug Fixes:
   - Stop data transfer whilst suspended; cros_ec"

* tag 'mfd-for-linus-4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (43 commits)
  mfd: lpc_ich: Enable watchdog on Intel Apollo Lake PCH
  mfd: lpc_ich: Remove useless comments in core part
  mfd: Add support for several boards to Kontron PLD driver
  mfd: constify regmap_irq_chip structures
  MAINTAINERS: Add include/dt-bindings/mfd to MFD entry
  mfd: cpcap: Add minimal support
  mfd: mt6397: Add MT6323 LED support into MT6397 driver
  Documentation: devicetree: Add LED subnode binding for MT6323 PMIC
  mfd: tps65912: Export OF device ID table as module aliases
  mfd: ab8500-core: Rename clock device and compatible
  mfd: cros_ec: Send correct suspend/resume event to EC
  mfd: max77686: Remove I2C device ID table
  mfd: max77686: Use the struct i2c_driver .probe_new instead of .probe
  mfd: max77686: Use of_device_get_match_data() helper
  mfd: max77686: Don't attempt to get i2c_device_id .data
  mfd: ab8500-sysctrl: Handle probe deferral
  mfd: intel-lpss: Add Intel Gemini Lake PCI IDs
  mfd: axp20x: Fix AXP806 access errors on cold boot
  mfd: cros_ec: Send suspend state notification to EC
  mfd: cros_ec: Prevent data transfer while device is suspended
  ...
parents bc49a783 e93c1021
* Device tree bindings for Aspeed SoC Display Controller (GFX)
The Aspeed SoC Display Controller primarily does as its name suggests, but also
participates in pinmux requests on the g5 SoCs. It is therefore considered a
syscon device.
Required properties:
- compatible: "aspeed,ast2500-gfx", "syscon"
- reg: contains offset/length value of the GFX memory
region.
Example:
gfx: display@1e6e6000 {
compatible = "aspeed,ast2500-gfx", "syscon";
reg = <0x1e6e6000 0x1000>;
};
======================================================================
Device tree bindings for the Aspeed Low Pin Count (LPC) Bus Controller
======================================================================
The LPC bus is a means to bridge a host CPU to a number of low-bandwidth
peripheral devices, replacing the use of the ISA bus in the age of PCI[0]. The
primary use case of the Aspeed LPC controller is as a slave on the bus
(typically in a Baseboard Management Controller SoC), but under certain
conditions it can also take the role of bus master.
The LPC controller is represented as a multi-function device to account for the
mix of functionality it provides. The principle split is between the register
layout at the start of the I/O space which is, to quote the Aspeed datasheet,
"basically compatible with the [LPC registers from the] popular BMC controller
H8S/2168[1]", and everything else, where everything else is an eclectic
collection of functions with a esoteric register layout. "Everything else",
here labeled the "host" portion of the controller, includes, but is not limited
to:
* An IPMI Block Transfer[2] Controller
* An LPC Host Controller: Manages LPC functions such as host vs slave mode, the
physical properties of some LPC pins, configuration of serial IRQs, and
APB-to-LPC bridging amonst other functions.
* An LPC Host Interface Controller: Manages functions exposed to the host such
as LPC firmware hub cycles, configuration of the LPC-to-AHB mapping, UART
management and bus snoop configuration.
* A set of SuperIO[3] scratch registers: Enables implementation of e.g. custom
hardware management protocols for handover between the host and baseboard
management controller.
Additionally the state of the LPC controller influences the pinmux
configuration, therefore the host portion of the controller is exposed as a
syscon as a means to arbitrate access.
[0] http://www.intel.com/design/chipsets/industry/25128901.pdf
[1] https://www.renesas.com/en-sg/doc/products/mpumcu/001/rej09b0078_h8s2168.pdf?key=7c88837454702128622bee53acbda8f4
[2] http://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf
[3] https://en.wikipedia.org/wiki/Super_I/O
Required properties
===================
- compatible: One of:
"aspeed,ast2400-lpc", "simple-mfd"
"aspeed,ast2500-lpc", "simple-mfd"
- reg: contains the physical address and length values of the Aspeed
LPC memory region.
- #address-cells: <1>
- #size-cells: <1>
- ranges: Maps 0 to the physical address and length of the LPC memory
region
Required LPC Child nodes
========================
BMC Node
--------
- compatible: One of:
"aspeed,ast2400-lpc-bmc"
"aspeed,ast2500-lpc-bmc"
- reg: contains the physical address and length values of the
H8S/2168-compatible LPC controller memory region
Host Node
---------
- compatible: One of:
"aspeed,ast2400-lpc-host", "simple-mfd", "syscon"
"aspeed,ast2500-lpc-host", "simple-mfd", "syscon"
- reg: contains the address and length values of the host-related
register space for the Aspeed LPC controller
- #address-cells: <1>
- #size-cells: <1>
- ranges: Maps 0 to the address and length of the host-related LPC memory
region
Example:
lpc: lpc@1e789000 {
compatible = "aspeed,ast2500-lpc", "simple-mfd";
reg = <0x1e789000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x1e789000 0x1000>;
lpc_bmc: lpc-bmc@0 {
compatible = "aspeed,ast2500-lpc-bmc";
reg = <0x0 0x80>;
};
lpc_host: lpc-host@80 {
compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon";
reg = <0x80 0x1e0>;
reg-io-width = <4>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80 0x1e0>;
};
};
Host Node Children
==================
LPC Host Controller
-------------------
The Aspeed LPC Host Controller configures the Low Pin Count (LPC) bus behaviour
between the host and the baseboard management controller. The registers exist
in the "host" portion of the Aspeed LPC controller, which must be the parent of
the LPC host controller node.
Required properties:
- compatible: One of:
"aspeed,ast2400-lhc";
"aspeed,ast2500-lhc";
- reg: contains offset/length values of the LHC memory regions. In the
AST2400 and AST2500 there are two regions.
Example:
lhc: lhc@20 {
compatible = "aspeed,ast2500-lhc";
reg = <0x20 0x24 0x48 0x8>;
};
......@@ -19,12 +19,22 @@ Optional properties:
- compatible : "simple-mfd" - this signifies that the operating system should
consider all subnodes of the MFD device as separate devices akin to how
"simple-bus" inidicates when to see subnodes as children for a simple
"simple-bus" indicates when to see subnodes as children for a simple
memory-mapped bus. For more complex devices, when the nexus driver has to
probe registers to figure out what child devices exist etc, this should not
be used. In the latter case the child devices will be determined by the
operating system.
- ranges: Describes the address mapping relationship to the parent. Should set
the child's base address to 0, the physical address within parent's address
space, and the length of the address map.
- #address-cells: Specifies the number of cells used to represent physical base
addresses. Must be present if ranges is used.
- #size-cells: Specifies the number of cells used to represent the size of an
address. Must be present if ranges is used.
Example:
foo@1000 {
......
Motorola CPCAP PMIC device tree binding
Required properties:
- compatible : One or both of "motorola,cpcap" or "ste,6556002"
- reg : SPI chip select
- interrupt-parent : The parent interrupt controller
- interrupts : The interrupt line the device is connected to
- interrupt-controller : Marks the device node as an interrupt controller
- #interrupt-cells : The number of cells to describe an IRQ, should be 2
- #address-cells : Child device offset number of cells, should be 1
- #size-cells : Child device size number of cells, should be 0
- spi-max-frequency : Typically set to 3000000
- spi-cs-high : SPI chip select direction
Example:
&mcspi1 {
cpcap: pmic@0 {
compatible = "motorola,cpcap", "ste,6556002";
reg = <0>; /* cs0 */
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <3000000>;
spi-cs-high;
};
};
......@@ -34,6 +34,10 @@ Optional subnodes:
- clk
Required properties:
- compatible: "mediatek,mt6397-clk"
- led
Required properties:
- compatible: "mediatek,mt6323-led"
see Documentation/devicetree/bindings/leds/leds-mt6323.txt
Example:
pwrap: pwrap@1000f000 {
......
......@@ -8476,6 +8476,7 @@ S: Supported
F: Documentation/devicetree/bindings/mfd/
F: drivers/mfd/
F: include/linux/mfd/
F: include/dt-bindings/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
M: Ulf Hansson <ulf.hansson@linaro.org>
......
This diff is collapsed.
......@@ -46,6 +46,7 @@ config MFD_SUN4I_GPADC
select REGMAP_MMIO
select REGMAP_IRQ
depends on ARCH_SUNXI || COMPILE_TEST
depends on !TOUCHSCREEN_SUN4I
help
Select this to get support for Allwinner SoCs (A10, A13 and A31) ADC.
This driver will only map the hardware interrupt and registers, you
......@@ -506,17 +507,22 @@ config MFD_KEMPLD
device may provide functions like watchdog, GPIO, UART and I2C bus.
The following modules are supported:
* COMe-bBD#
* COMe-bBL6
* COMe-bHL6
* COMe-bSL6
* COMe-bIP#
* COMe-bKL6
* COMe-bPC2 (ETXexpress-PC)
* COMe-bSC# (ETXexpress-SC T#)
* COMe-cAL6
* COMe-cBL6
* COMe-cBT6
* COMe-cBW6
* COMe-cCT6
* COMe-cDC2 (microETXexpress-DC)
* COMe-cHL6
* COMe-cKL6
* COMe-cPC2 (microETXexpress-PC)
* COMe-cSL6
* COMe-mAL10
......@@ -714,6 +720,17 @@ config EZX_PCAP
This enables the PCAP ASIC present on EZX Phones. This is
needed for MMC, TouchScreen, Sound, USB, etc..
config MFD_CPCAP
tristate "Support for Motorola CPCAP"
depends on SPI
depends on OF || COMPILE_TEST
select REGMAP_SPI
select REGMAP_IRQ
help
Say yes here if you want to include driver for CPCAP.
It is used on many Motorola phones and tablets as a PMIC.
At least Motorola Droid 4 is known to use CPCAP.
config MFD_VIPERBOARD
tristate "Nano River Technologies Viperboard"
select MFD_CORE
......
......@@ -97,6 +97,7 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o
obj-$(CONFIG_MCP) += mcp-core.o
obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
......
......@@ -656,8 +656,8 @@ static const struct mfd_cell ab8500_devs[] = {
.of_compatible = "stericsson,ab8500-regulator",
},
{
.name = "abx500-clk",
.of_compatible = "stericsson,abx500-clk",
.name = "ab8500-clk",
.of_compatible = "stericsson,ab8500-clk",
},
{
.name = "ab8500-gpadc",
......
......@@ -101,7 +101,7 @@ int ab8500_sysctrl_read(u16 reg, u8 *value)
u8 bank;
if (sysctrl_dev == NULL)
return -EINVAL;
return -EPROBE_DEFER;
bank = (reg >> 8);
if (!valid_bank(bank))
......@@ -117,11 +117,13 @@ int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
u8 bank;
if (sysctrl_dev == NULL)
return -EINVAL;
return -EPROBE_DEFER;
bank = (reg >> 8);
if (!valid_bank(bank))
if (!valid_bank(bank)) {
pr_err("invalid bank\n");
return -EINVAL;
}
return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,
(u8)(reg & 0xFF), mask, value);
......@@ -148,9 +150,15 @@ static int ab8500_sysctrl_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id ab8500_sysctrl_match[] = {
{ .compatible = "stericsson,ab8500-sysctrl", },
{}
};
static struct platform_driver ab8500_sysctrl_driver = {
.driver = {
.name = "ab8500-sysctrl",
.of_match_table = ab8500_sysctrl_match,
},
.probe = ab8500_sysctrl_probe,
.remove = ab8500_sysctrl_remove,
......
......@@ -26,6 +26,9 @@
#include "arizona.h"
#define ARIZONA_AOD_IRQ_INDEX 0
#define ARIZONA_MAIN_IRQ_INDEX 1
static int arizona_map_irq(struct arizona *arizona, int irq)
{
int ret;
......@@ -204,9 +207,10 @@ static const struct irq_domain_ops arizona_domain_ops = {
int arizona_irq_init(struct arizona *arizona)
{
int flags = IRQF_ONESHOT;
int ret, i;
int ret;
const struct regmap_irq_chip *aod, *irq;
struct irq_data *irq_data;
unsigned int virq;
arizona->ctrlif_error = true;
......@@ -318,24 +322,34 @@ int arizona_irq_init(struct arizona *arizona)
}
if (aod) {
ret = regmap_add_irq_chip(arizona->regmap,
irq_create_mapping(arizona->virq, 0),
IRQF_ONESHOT, 0, aod,
&arizona->aod_irq_chip);
virq = irq_create_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
if (!virq) {
dev_err(arizona->dev, "Failed to map AOD IRQs\n");
ret = -EINVAL;
goto err_domain;
}
ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0, aod, &arizona->aod_irq_chip);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to add AOD IRQs: %d\n", ret);
goto err;
goto err_map_aod;
}
}
ret = regmap_add_irq_chip(arizona->regmap,
irq_create_mapping(arizona->virq, 1),
IRQF_ONESHOT, 0, irq,
&arizona->irq_chip);
virq = irq_create_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
if (!virq) {
dev_err(arizona->dev, "Failed to map main IRQs\n");
ret = -EINVAL;
goto err_aod;
}
ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0, irq, &arizona->irq_chip);
if (ret != 0) {
dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret);
goto err_aod;
goto err_map_main_irq;
}
/* Used to emulate edge trigger and to work around broken pinmux */
......@@ -368,9 +382,8 @@ int arizona_irq_init(struct arizona *arizona)
}
/* Make sure the boot done IRQ is unmasked for resumes */
i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE);
ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT,
"Boot done", arizona);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_BOOT_DONE, "Boot done",
arizona_boot_done, arizona);
if (ret != 0) {
dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
arizona->irq, ret);
......@@ -379,10 +392,9 @@ int arizona_irq_init(struct arizona *arizona)
/* Handle control interface errors in the core */
if (arizona->ctrlif_error) {
i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
IRQF_ONESHOT,
"Control interface error", arizona);
ret = arizona_request_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR,
"Control interface error",
arizona_ctrlif_err, arizona);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to request CTRLIF_ERR %d: %d\n",
......@@ -394,29 +406,47 @@ int arizona_irq_init(struct arizona *arizona)
return 0;
err_ctrlif:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
err_boot_done:
free_irq(arizona->irq, arizona);
err_main_irq:
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 1),
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX),
arizona->irq_chip);
err_map_main_irq:
irq_dispose_mapping(irq_find_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX));
err_aod:
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX),
arizona->aod_irq_chip);
err_map_aod:
irq_dispose_mapping(irq_find_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX));
err_domain:
irq_domain_remove(arizona->virq);
err:
return ret;
}
int arizona_irq_exit(struct arizona *arizona)
{
unsigned int virq;
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_find_mapping(arizona->virq, 1),
arizona->irq_chip);
regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
arizona->aod_irq_chip);
arizona_free_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
virq = irq_find_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
regmap_del_irq_chip(virq, arizona->irq_chip);
irq_dispose_mapping(virq);
virq = irq_find_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
regmap_del_irq_chip(virq, arizona->aod_irq_chip);
irq_dispose_mapping(virq);
irq_domain_remove(arizona->virq);
free_irq(arizona->irq, arizona);
return 0;
......
......@@ -17,8 +17,6 @@
#include <linux/regmap.h>
#include <linux/pm.h>
struct wm_arizona;
extern const struct regmap_config wm5102_i2c_regmap;
extern const struct regmap_config wm5102_spi_regmap;
......
......@@ -31,6 +31,8 @@
#define AXP20X_OFF 0x80
#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
static const char * const axp20x_model_names[] = {
"AXP152",
"AXP202",
......@@ -118,7 +120,14 @@ static const struct regmap_range axp288_writeable_ranges[] = {
};
static const struct regmap_range axp288_volatile_ranges[] = {
regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT),
regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
};
static const struct regmap_access_table axp288_writeable_table = {
......@@ -207,14 +216,14 @@ static struct resource axp22x_pek_resources[] = {
static struct resource axp288_power_button_resources[] = {
{
.name = "PEK_DBR",
.start = AXP288_IRQ_POKN,
.end = AXP288_IRQ_POKN,
.start = AXP288_IRQ_POKP,
.end = AXP288_IRQ_POKP,
.flags = IORESOURCE_IRQ,
},
{
.name = "PEK_DBF",
.start = AXP288_IRQ_POKP,
.end = AXP288_IRQ_POKP,
.start = AXP288_IRQ_POKN,
.end = AXP288_IRQ_POKN,
.flags = IORESOURCE_IRQ,
},
};
......@@ -407,6 +416,9 @@ static const struct regmap_irq axp288_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2),
INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3),
INIT_REGMAP_IRQ(AXP288, OV, 0, 4),
INIT_REGMAP_IRQ(AXP288, FALLING_ALT, 0, 5),
INIT_REGMAP_IRQ(AXP288, RISING_ALT, 0, 6),
INIT_REGMAP_IRQ(AXP288, OV_ALT, 0, 7),
INIT_REGMAP_IRQ(AXP288, DONE, 1, 2),
INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3),
......@@ -589,7 +601,22 @@ static struct mfd_cell axp20x_cells[] = {
},
};
static struct mfd_cell axp22x_cells[] = {
static struct mfd_cell axp221_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
.resources = axp22x_pek_resources,
}, {
.name = "axp20x-regulator",
}, {
.name = "axp20x-usb-power-supply",
.of_compatible = "x-powers,axp221-usb-power-supply",
.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
.resources = axp22x_usb_power_supply_resources,
},
};
static struct mfd_cell axp223_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
......@@ -598,7 +625,7 @@ static struct mfd_cell axp22x_cells[] = {
.name = "axp20x-regulator",
}, {
.name = "axp20x-usb-power-supply",
.of_compatible = "x-powers,axp221-usb-power-supply",
.of_compatible = "x-powers,axp223-usb-power-supply",
.num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources),
.resources = axp22x_usb_power_supply_resources,
},
......@@ -791,9 +818,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
break;
case AXP221_ID:
axp20x->nr_cells = ARRAY_SIZE(axp221_cells);
axp20x->cells = axp221_cells;
axp20x->regmap_cfg = &axp22x_regmap_config;
axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
break;
case AXP223_ID:
axp20x->nr_cells = ARRAY_SIZE(axp22x_cells);
axp20x->cells = axp22x_cells;
axp20x->nr_cells = ARRAY_SIZE(axp223_cells);
axp20x->cells = axp223_cells;
axp20x->regmap_cfg = &axp22x_regmap_config;
axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
break;
......@@ -802,6 +834,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
axp20x->regmap_cfg = &axp288_regmap_config;
axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
axp20x->irq_flags = IRQF_TRIGGER_LOW;
break;
case AXP806_ID:
axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
......@@ -830,10 +863,33 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
{
int ret;
/*
* The AXP806 supports either master/standalone or slave mode.
* Slave mode allows sharing the serial bus, even with multiple
* AXP806 which all have the same hardware address.
*
* This is done with extra "serial interface address extension",
* or AXP806_BUS_ADDR_EXT, and "register address extension", or
* AXP806_REG_ADDR_EXT, registers. The former is read-only, with
* 1 bit customizable at the factory, and 1 bit depending on the
* state of an external pin. The latter is writable. The device
* will only respond to operations to its other registers when
* the these device addressing bits (in the upper 4 bits of the
* registers) match.
*
* Since we only support an AXP806 chained to an AXP809 in slave
* mode, and there isn't any existing hardware which uses AXP806
* in master mode, or has 2 AXP806s in the same system, we can
* just program the register address extension to the slave mode
* address.
*/
if (axp20x->variant == AXP806_ID)
regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
IRQF_ONESHOT | IRQF_SHARED, -1,
axp20x->regmap_irq_chip,
&axp20x->regmap_irqc);
IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
-1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc);
if (ret) {
dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
return ret;
......
......@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/mfd/core.h>
#include <linux/mfd/cros_ec.h>
#include <linux/suspend.h>
#include <asm/unaligned.h>
#define CROS_EC_DEV_EC_INDEX 0
......@@ -65,6 +66,24 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}
static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
{
struct {
struct cros_ec_command msg;
struct ec_params_host_sleep_event req;
} __packed buf;
memset(&buf, 0, sizeof(buf));
buf.req.sleep_event = sleep_event;
buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
buf.msg.version = 0;
buf.msg.outsize = sizeof(buf.req);
return cros_ec_cmd_xfer(ec_dev, &buf.msg);
}
int cros_ec_register(struct cros_ec_device *ec_dev)
{
struct device *dev = ec_dev->dev;
......@@ -136,6 +155,15 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
}
/*
* Clear sleep event - this will fail harmlessly on platforms that
* don't implement the sleep event host command.
*/
err = cros_ec_sleep_event(ec_dev, 0);
if (err < 0)
dev_dbg(ec_dev->dev, "Error %d clearing sleep event to ec",
err);
dev_info(dev, "Chrome EC device registered\n");
return 0;
......@@ -159,12 +187,24 @@ EXPORT_SYMBOL(cros_ec_remove);
int cros_ec_suspend(struct cros_ec_device *ec_dev)
{
struct device *dev = ec_dev->dev;
int ret;
u8 sleep_event;
sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
HOST_SLEEP_EVENT_S3_RESUME :
HOST_SLEEP_EVENT_S0IX_RESUME;
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec",
ret);
if (device_may_wakeup(dev))
ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
disable_irq(ec_dev->irq);
ec_dev->was_wake_device = ec_dev->wake_enabled;
ec_dev->suspended = true;
return 0;
}
......@@ -179,8 +219,21 @@ static void cros_ec_drain_events(struct cros_ec_device *ec_dev)
int cros_ec_resume(struct cros_ec_device *ec_dev)
{
int ret;
u8 sleep_event;
ec_dev->suspended = false;
enable_irq(ec_dev->irq);
sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
HOST_SLEEP_EVENT_S3_RESUME :
HOST_SLEEP_EVENT_S0IX_RESUME;
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
dev_dbg(ec_dev->dev, "Error %d sending resume event to ec",
ret);
/*
* In some cases, we need to distinguish between events that occur
* during suspend if the EC is not a wake source. For example,
......
......@@ -157,7 +157,22 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info },
/* GLK */
{ PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&bxt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31ee), (kernel_ulong_t)&bxt_uart_info },
{ PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
......
......@@ -496,6 +496,14 @@ static struct platform_driver kempld_driver = {
static struct dmi_system_id kempld_dmi_table[] __initdata = {
{
.ident = "BBD6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bBD"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "BBL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
......@@ -511,6 +519,30 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = {
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "BKL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bKL6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "BSL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-bSL6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CAL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cAL"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CBL6",
.matches = {
......@@ -599,6 +631,14 @@ static struct dmi_system_id kempld_dmi_table[] __initdata = {
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CKL6",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Kontron"),
DMI_MATCH(DMI_BOARD_NAME, "COMe-cKL6"),
},
.driver_data = (void *)&kempld_platform_data_generic,
.callback = kempld_create_platform_device,
}, {
.ident = "CNTG",
.matches = {
......
......@@ -20,10 +20,6 @@
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* This driver supports the following I/O Controller hubs:
* (See the intel documentation on http://developer.intel.com.)
* document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO)
......@@ -45,18 +41,6 @@
* document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH)
* document number 320066-003, 320257-008: EP80597 (IICH)
* document number 324645-001, 324646-001: Cougar Point (CPT)
* document number TBD : Patsburg (PBG)
* document number TBD : DH89xxCC
* document number TBD : Panther Point
* document number TBD : Lynx Point
* document number TBD : Lynx Point-LP
* document number TBD : Wellsburg
* document number TBD : Avoton SoC
* document number TBD : Coleto Creek
* document number TBD : Wildcat Point-LP
* document number TBD : 9 Series
* document number TBD : Lewisburg
* document number TBD : Apollo Lake SoC
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
......@@ -567,6 +551,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
},
[LPC_APL] = {
.name = "Apollo Lake SoC",
.iTCO_version = 5,
.spi_type = INTEL_SPI_BXT,
},
};
......
......@@ -34,6 +34,7 @@
#include <linux/mfd/max77686-private.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_device.h>
static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-pmic", },
......@@ -171,11 +172,9 @@ static const struct of_device_id max77686_pmic_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, max77686_pmic_dt_match);
static int max77686_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
static int max77686_i2c_probe(struct i2c_client *i2c)
{
struct max77686_dev *max77686 = NULL;
const struct of_device_id *match;
unsigned int data;
int ret = 0;
const struct regmap_config *config;
......@@ -188,16 +187,8 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
if (!max77686)
return -ENOMEM;
if (i2c->dev.of_node) {
match = of_match_node(max77686_pmic_dt_match, i2c->dev.of_node);
if (!match)
return -EINVAL;
max77686->type = (unsigned long)match->data;
} else
max77686->type = id->driver_data;
i2c_set_clientdata(i2c, max77686);
max77686->type = (unsigned long)of_device_get_match_data(&i2c->dev);
max77686->dev = &i2c->dev;
max77686->i2c = i2c;
......@@ -250,13 +241,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return 0;
}
static const struct i2c_device_id max77686_i2c_id[] = {
{ "max77686", TYPE_MAX77686 },
{ "max77802", TYPE_MAX77802 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
#ifdef CONFIG_PM_SLEEP
static int max77686_suspend(struct device *dev)
{
......@@ -302,8 +286,7 @@ static struct i2c_driver max77686_i2c_driver = {
.pm = &max77686_pm,
.of_match_table = of_match_ptr(max77686_pmic_dt_match),
},
.probe = max77686_i2c_probe,
.id_table = max77686_i2c_id,
.probe_new = max77686_i2c_probe,
};
module_i2c_driver(max77686_i2c_driver);
......
/*
* Motorola CPCAP PMIC core driver
*
* Copyright (C) 2016 Tony Lindgren <tony@atomide.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.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/sysfs.h>
#include <linux/mfd/motorola-cpcap.h>
#include <linux/spi/spi.h>
#define CPCAP_NR_IRQ_REG_BANKS 6
#define CPCAP_NR_IRQ_CHIPS 3
struct cpcap_ddata {
struct spi_device *spi;
struct regmap_irq *irqs;
struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
const struct regmap_config *regmap_conf;
struct regmap *regmap;
};
static int cpcap_check_revision(struct cpcap_ddata *cpcap)
{
u16 vendor, rev;
int ret;
ret = cpcap_get_vendor(&cpcap->spi->dev, cpcap->regmap, &vendor);
if (ret)
return ret;
ret = cpcap_get_revision(&cpcap->spi->dev, cpcap->regmap, &rev);
if (ret)
return ret;
dev_info(&cpcap->spi->dev, "CPCAP vendor: %s rev: %i.%i (%x)\n",
vendor == CPCAP_VENDOR_ST ? "ST" : "TI",
CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev),
rev);
if (rev < CPCAP_REVISION_2_1) {
dev_info(&cpcap->spi->dev,
"Please add old CPCAP revision support as needed\n");
return -ENODEV;
}
return 0;
}
/*
* First two irq chips are the two private macro interrupt chips, the third
* irq chip is for register banks 1 - 4 and is available for drivers to use.
*/
static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
{
.name = "cpcap-m2",
.num_regs = 1,
.status_base = CPCAP_REG_MI1,
.ack_base = CPCAP_REG_MI1,
.mask_base = CPCAP_REG_MIM1,
.use_ack = true,
},
{
.name = "cpcap-m2",
.num_regs = 1,
.status_base = CPCAP_REG_MI2,
.ack_base = CPCAP_REG_MI2,
.mask_base = CPCAP_REG_MIM2,
.use_ack = true,
},
{
.name = "cpcap1-4",
.num_regs = 4,
.status_base = CPCAP_REG_INT1,
.ack_base = CPCAP_REG_INT1,
.mask_base = CPCAP_REG_INTM1,
.type_base = CPCAP_REG_INTS1,
.use_ack = true,
},
};
static void cpcap_init_one_regmap_irq(struct cpcap_ddata *cpcap,
struct regmap_irq *rirq,
int irq_base, int irq)
{
unsigned int reg_offset;
unsigned int bit, mask;
reg_offset = irq - irq_base;
reg_offset /= cpcap->regmap_conf->val_bits;
reg_offset *= cpcap->regmap_conf->reg_stride;
bit = irq % cpcap->regmap_conf->val_bits;
mask = (1 << bit);
rirq->reg_offset = reg_offset;
rirq->mask = mask;
}
static int cpcap_init_irq_chip(struct cpcap_ddata *cpcap, int irq_chip,
int irq_start, int nr_irqs)
{
struct regmap_irq_chip *chip = &cpcap_irq_chip[irq_chip];
int i, ret;
for (i = irq_start; i < irq_start + nr_irqs; i++) {
struct regmap_irq *rirq = &cpcap->irqs[i];
cpcap_init_one_regmap_irq(cpcap, rirq, irq_start, i);
}
chip->irqs = &cpcap->irqs[irq_start];
chip->num_irqs = nr_irqs;
chip->irq_drv_data = cpcap;
ret = devm_regmap_add_irq_chip(&cpcap->spi->dev, cpcap->regmap,
cpcap->spi->irq,
IRQF_TRIGGER_RISING |
IRQF_SHARED, -1,
chip, &cpcap->irqdata[irq_chip]);
if (ret) {
dev_err(&cpcap->spi->dev, "could not add irq chip %i: %i\n",
irq_chip, ret);
return ret;
}
return 0;
}
static int cpcap_init_irq(struct cpcap_ddata *cpcap)
{
int ret;
cpcap->irqs = devm_kzalloc(&cpcap->spi->dev,
sizeof(*cpcap->irqs) *
CPCAP_NR_IRQ_REG_BANKS *
cpcap->regmap_conf->val_bits,
GFP_KERNEL);
if (!cpcap->irqs)
return -ENOMEM;
ret = cpcap_init_irq_chip(cpcap, 0, 0, 16);
if (ret)
return ret;
ret = cpcap_init_irq_chip(cpcap, 1, 16, 16);
if (ret)
return ret;
ret = cpcap_init_irq_chip(cpcap, 2, 32, 64);
if (ret)
return ret;
enable_irq_wake(cpcap->spi->irq);
return 0;
}
static const struct of_device_id cpcap_of_match[] = {
{ .compatible = "motorola,cpcap", },
{ .compatible = "st,6556002", },
{},
};
MODULE_DEVICE_TABLE(of, cpcap_of_match);
static const struct regmap_config cpcap_regmap_config = {
.reg_bits = 16,
.reg_stride = 4,
.pad_bits = 0,
.val_bits = 16,
.write_flag_mask = 0x8000,
.max_register = CPCAP_REG_ST_TEST2,
.cache_type = REGCACHE_NONE,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
};
static int cpcap_probe(struct spi_device *spi)
{
const struct of_device_id *match;
struct cpcap_ddata *cpcap;
int ret;
match = of_match_device(of_match_ptr(cpcap_of_match), &spi->dev);
if (!match)
return -ENODEV;
cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
if (!cpcap)
return -ENOMEM;
cpcap->spi = spi;
spi_set_drvdata(spi, cpcap);
spi->bits_per_word = 16;
spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
ret = spi_setup(spi);
if (ret)
return ret;
cpcap->regmap_conf = &cpcap_regmap_config;
cpcap->regmap = devm_regmap_init_spi(spi, &cpcap_regmap_config);
if (IS_ERR(cpcap->regmap)) {
ret = PTR_ERR(cpcap->regmap);
dev_err(&cpcap->spi->dev, "Failed to initialize regmap: %d\n",
ret);
return ret;
}
ret = cpcap_check_revision(cpcap);
if (ret) {
dev_err(&cpcap->spi->dev, "Failed to detect CPCAP: %i\n", ret);
return ret;
}
ret = cpcap_init_irq(cpcap);
if (ret)
return ret;
return of_platform_populate(spi->dev.of_node, NULL, NULL,
&cpcap->spi->dev);
}
static int cpcap_remove(struct spi_device *pdev)
{
struct cpcap_ddata *cpcap = spi_get_drvdata(pdev);
of_platform_depopulate(&cpcap->spi->dev);
return 0;
}
static struct spi_driver cpcap_driver = {
.driver = {
.name = "cpcap-core",
.of_match_table = cpcap_of_match,
},
.probe = cpcap_probe,
.remove = cpcap_remove,
};
module_spi_driver(cpcap_driver);
MODULE_ALIAS("platform:cpcap");
MODULE_DESCRIPTION("CPCAP driver");
MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
MODULE_LICENSE("GPL v2");
......@@ -48,6 +48,10 @@ static const struct mfd_cell mt6323_devs[] = {
.name = "mt6323-regulator",
.of_compatible = "mediatek,mt6323-regulator"
},
{
.name = "mt6323-led",
.of_compatible = "mediatek,mt6323-led"
},
};
static const struct mfd_cell mt6397_devs[] = {
......
......@@ -247,7 +247,7 @@ static const struct regmap_irq rk818_irqs[] = {
},
};
static struct regmap_irq_chip rk808_irq_chip = {
static const struct regmap_irq_chip rk808_irq_chip = {
.name = "rk808",
.irqs = rk808_irqs,
.num_irqs = ARRAY_SIZE(rk808_irqs),
......@@ -259,7 +259,7 @@ static struct regmap_irq_chip rk808_irq_chip = {
.init_ack_masked = true,
};
static struct regmap_irq_chip rk818_irq_chip = {
static const struct regmap_irq_chip rk818_irq_chip = {
.name = "rk818",
.irqs = rk818_irqs,
.num_irqs = ARRAY_SIZE(rk818_irqs),
......
......@@ -12,6 +12,9 @@
#include <linux/init.h>
#include <linux/of.h>
#define SUN8I_CODEC_ANALOG_BASE 0x1c0
#define SUN8I_CODEC_ANALOG_SIZE 0x4
struct prcm_data {
int nsubdevs;
const struct mfd_cell *subdevs;
......@@ -57,6 +60,10 @@ static const struct resource sun6i_a31_apb0_rstc_res[] = {
},
};
static const struct resource sun8i_codec_analog_res[] = {
DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE, SUN8I_CODEC_ANALOG_SIZE),
};
static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
{
.name = "sun6i-a31-ar100-clk",
......@@ -109,6 +116,12 @@ static const struct mfd_cell sun8i_a23_prcm_subdevs[] = {
.num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
.resources = sun6i_a31_apb0_rstc_res,
},
{
.name = "sun8i-codec-analog",
.of_compatible = "allwinner,sun8i-a23-codec-analog",
.num_resources = ARRAY_SIZE(sun8i_codec_analog_res),
.resources = sun8i_codec_analog_res,
},
};
static const struct prcm_data sun6i_a31_prcm_data = {
......
......@@ -27,6 +27,7 @@ static const struct of_device_id tps65912_i2c_of_match_table[] = {
{ .compatible = "ti,tps65912", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, tps65912_i2c_of_match_table);
static int tps65912_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
......
......@@ -447,6 +447,11 @@ static int get_next_event(struct cros_ec_device *ec_dev)
struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
int ret;
if (ec_dev->suspended) {
dev_dbg(ec_dev->dev, "Device suspended.\n");
return -EHOSTDOWN;
}
msg->version = 0;
msg->command = EC_CMD_GET_NEXT_EVENT;
msg->insize = sizeof(ec_dev->event_data);
......
......@@ -45,7 +45,7 @@ enum abx500_adc_therm {
* struct abx500_res_to_temp - defines one point in a temp to res curve. To
* be used in battery packs that combines the identification resistor with a
* NTC resistor.
* @temp: battery pack temperature in Celcius
* @temp: battery pack temperature in Celsius
* @resist: NTC resistor net total resistance
*/
struct abx500_res_to_temp {
......
......@@ -279,7 +279,7 @@ enum bup_vch_sel {
* struct res_to_temp - defines one point in a temp to res curve. To
* be used in battery packs that combines the identification resistor with a
* NTC resistor.
* @temp: battery pack temperature in Celcius
* @temp: battery pack temperature in Celsius
* @resist: NTC resistor net total resistance
*/
struct res_to_temp {
......@@ -290,7 +290,7 @@ struct res_to_temp {
/**
* struct batres_vs_temp - defines one point in a temp vs battery internal
* resistance curve.
* @temp: battery pack temperature in Celcius
* @temp: battery pack temperature in Celsius
* @resist: battery internal reistance in mOhm
*/
struct batres_vs_temp {
......
......@@ -235,10 +235,20 @@ enum axp20x_variants {
#define AXP22X_BATLOW_THRES1 0xe6
/* AXP288 specific registers */
#define AXP288_POWER_REASON 0x02
#define AXP288_BC_GLOBAL 0x2c
#define AXP288_BC_VBUS_CNTL 0x2d
#define AXP288_BC_USB_STAT 0x2e
#define AXP288_BC_DET_STAT 0x2f
#define AXP288_PMIC_ADC_H 0x56
#define AXP288_PMIC_ADC_L 0x57
#define AXP288_TS_ADC_H 0x58
#define AXP288_TS_ADC_L 0x59
#define AXP288_GP_ADC_H 0x5a
#define AXP288_GP_ADC_L 0x5b
#define AXP288_ADC_TS_PIN_CTRL 0x84
#define AXP288_PMIC_ADC_EN 0x84
#define AXP288_RT_BATT_V_H 0xa0
#define AXP288_RT_BATT_V_L 0xa1
/* Fuel Gauge */
#define AXP288_FG_RDC1_REG 0xba
......@@ -515,14 +525,10 @@ enum axp809_irqs {
AXP809_IRQ_GPIO0_INPUT,
};
#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;
int irq;
unsigned long irq_flags;
struct regmap *regmap;
struct regmap_irq_chip_data *regmap_irqc;
long variant;
......@@ -582,7 +588,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x);
int axp20x_device_probe(struct axp20x_dev *axp20x);
/**
* axp20x_device_probe(): Remove a axp20x device
* axp20x_device_remove(): Remove a axp20x device
*
* @axp20x: axp20x device to remove
*
......
......@@ -103,6 +103,7 @@ struct cros_ec_command {
* @din_size: size of din buffer to allocate (zero to use static din)
* @dout_size: size of dout buffer to allocate (zero to use static dout)
* @wake_enabled: true if this device can wake the system from sleep
* @suspended: true if this device had been suspended
* @cmd_xfer: send command to EC and get response
* Returns the number of bytes received if the communication succeeded, but
* that doesn't mean the EC was happy with the command. The caller
......@@ -136,6 +137,7 @@ struct cros_ec_device {
int din_size;
int dout_size;
bool wake_enabled;
bool suspended;
int (*cmd_xfer)(struct cros_ec_device *ec,
struct cros_ec_command *msg);
int (*pkt_xfer)(struct cros_ec_device *ec,
......
......@@ -1840,18 +1840,69 @@ struct ec_response_tmp006_get_raw {
*
* Returns raw data for keyboard cols; see ec_response_mkbp_info.cols for
* expected response size.
*
* NOTE: This has been superseded by EC_CMD_MKBP_GET_NEXT_EVENT. If you wish
* to obtain the instantaneous state, use EC_CMD_MKBP_INFO with the type
* EC_MKBP_INFO_CURRENT and event EC_MKBP_EVENT_KEY_MATRIX.
*/
#define EC_CMD_MKBP_STATE 0x60
/* Provide information about the matrix : number of rows and columns */
/*
* Provide information about various MKBP things. See enum ec_mkbp_info_type.
*/
#define EC_CMD_MKBP_INFO 0x61
struct ec_response_mkbp_info {
uint32_t rows;
uint32_t cols;
uint8_t switches;
/* Formerly "switches", which was 0. */
uint8_t reserved;
} __packed;
struct ec_params_mkbp_info {
uint8_t info_type;
uint8_t event_type;
} __packed;
enum ec_mkbp_info_type {
/*
* Info about the keyboard matrix: number of rows and columns.
*
* Returns struct ec_response_mkbp_info.
*/
EC_MKBP_INFO_KBD = 0,
/*
* For buttons and switches, info about which specifically are
* supported. event_type must be set to one of the values in enum
* ec_mkbp_event.
*
* For EC_MKBP_EVENT_BUTTON and EC_MKBP_EVENT_SWITCH, returns a 4 byte
* bitmask indicating which buttons or switches are present. See the
* bit inidices below.
*/
EC_MKBP_INFO_SUPPORTED = 1,
/*
* Instantaneous state of buttons and switches.
*
* event_type must be set to one of the values in enum ec_mkbp_event.
*
* For EC_MKBP_EVENT_KEY_MATRIX, returns uint8_t key_matrix[13]
* indicating the current state of the keyboard matrix.
*
* For EC_MKBP_EVENT_HOST_EVENT, return uint32_t host_event, the raw
* event state.
*
* For EC_MKBP_EVENT_BUTTON, returns uint32_t buttons, indicating the
* state of supported buttons.
*
* For EC_MKBP_EVENT_SWITCH, returns uint32_t switches, indicating the
* state of supported switches.
*/
EC_MKBP_INFO_CURRENT = 2,
};
/* Simulate key press */
#define EC_CMD_MKBP_SIMULATE_KEY 0x62
......@@ -1984,6 +2035,12 @@ enum ec_mkbp_event {
/* New Sensor FIFO data. The event data is fifo_info structure. */
EC_MKBP_EVENT_SENSOR_FIFO = 2,
/* The state of the non-matrixed buttons have changed. */
EC_MKBP_EVENT_BUTTON = 3,
/* The state of the switches have changed. */
EC_MKBP_EVENT_SWITCH = 4,
/* Number of MKBP events */
EC_MKBP_EVENT_COUNT,
};
......@@ -1993,6 +2050,9 @@ union ec_response_get_next_data {
/* Unaligned */
uint32_t host_event;
uint32_t buttons;
uint32_t switches;
} __packed;
struct ec_response_get_next_event {
......@@ -2001,6 +2061,16 @@ struct ec_response_get_next_event {
union ec_response_get_next_data data;
} __packed;
/* Bit indices for buttons and switches.*/
/* Buttons */
#define EC_MKBP_POWER_BUTTON 0
#define EC_MKBP_VOL_UP 1
#define EC_MKBP_VOL_DOWN 2
/* Switches */
#define EC_MKBP_LID_OPEN 0
#define EC_MKBP_TABLET_MODE 1
/*****************************************************************************/
/* Temperature sensor commands */
......@@ -2478,6 +2548,20 @@ struct ec_params_ext_power_current_limit {
uint32_t limit; /* in mA */
} __packed;
/* Inform the EC when entering a sleep state */
#define EC_CMD_HOST_SLEEP_EVENT 0xa9
enum host_sleep_event {
HOST_SLEEP_EVENT_S3_SUSPEND = 1,
HOST_SLEEP_EVENT_S3_RESUME = 2,
HOST_SLEEP_EVENT_S0IX_SUSPEND = 3,
HOST_SLEEP_EVENT_S0IX_RESUME = 4
};
struct ec_params_host_sleep_event {
uint8_t sleep_event;
} __packed;
/*****************************************************************************/
/* Smart battery pass-through */
......
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