aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 11:35:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-07 11:35:35 -0400
commitd042380886fb2fc6c4b0fcfe1214ba473769a8e9 (patch)
tree61e29ff167e0f83f67930ee9911062415030e1ef /drivers/platform
parent3477d168ba61c5b0ca42d3d4642f3463609a5417 (diff)
parentb8d336ed90f541097a2ce583be430bb3e895dfbd (diff)
Merge tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD updates from Lee Jones: "Core framework: - Add the MFD bindings doc to MAINTAINERS New drivers: - X-Powers AC100 Audio CODEC and RTC - TI LP873x PMIC - Rockchip RK808 PMIC - Samsung Exynos Low Power Audio New device support: - Add support for STMPE1600 variant to stmpe - Add support for PM8018 PMIC to pm8921-core - Add support for AXP806 PMIC in axp20x - Add support for AXP209 GPIO in axp20x New functionality: - Add support for Reset to all STMPE variants - Add support for MKBP event support to cros_ec - Add support for USB to intel_soc_pmic_bxtwc - Add support for IRQs and Power Button to tps65217 Fix-ups: - Clean-up defunct author emails (da9063, max14577) - Kconfig fixups (wm8350-i2c, as37220 - Constify (altera-a10sr, sm501) - Supply PCI IDs (intel-lpss-pci) - Improve clocking (qcom_rpm) - Fix IRQ probing (ucb1x00-core) - Ensure fault log is cleared (da9052) - Remove NO_IRQ check (ucb1x00-core) - Supply I2C properties (intel-lpss-acpi, intel-lpss-pci) - Non standard declaration (tps65217, max8997-irq) - Remove unused code (lp873x, db8500-prcmu, ab8500-debugfs, cros_ec_spi) - Make non-modular (altera-a10sr, intel_msic, smsc-ece1099, sun6i-prcm, twl-core) - OF bindings (ac100, stmpe, qcom-pm8xxx, qcom-rpm, rk808, axp20x, lp873x, exynos5433-lpass, act8945a, aspeed-scu, twl6040, arizona) Bugfixes: - Release OF pointer (qcom_rpm) - Avoid double shifting in suspend/resume (88pm80x) - Fix 'defined but not used' error (exynos-lpass) - Fix 'sleeping whilst attomic' (atmel-hlcdc)" * tag 'mfd-for-linus-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (69 commits) mfd: arizona: Handle probe deferral for reset GPIO mfd: arizona: Remove arizona_of_get_named_gpio helper function mfd: arizona: Add DT options for max_channels_clocked and PDM speaker config mfd: twl6040: Register child device for twl6040-pdmclk mfd: cros_ec_spi: Remove unused variable 'request' mfd: omap-usb-host: Return value is not 'const int' mfd: ab8500-debugfs: Remove 'weak' function suspend_test_wake_cause_interrupt_is_mine() mfd: ab8500-debugfs: Remove ab8500_dump_all_banks_to_mem() mfd: db8500-prcmu: Remove unused *prcmu_set_ddr_opp() calls mfd: ab8500-debugfs: Prevent initialised field from being over-written mfd: max8997-irq: 'inline' should be at the beginning of the declaration mfd: rk808: Fix RK818_IRQ_DISCHG_ILIM initializer mfd: tps65217: Fix nonstandard declaration mfd: lp873x: Remove unused mutex lock from struct lp873x mfd: atmel-hlcdc: Do not sleep in atomic context mfd: exynos-lpass: Mark PM functions as __maybe_unused mfd: intel-lpss: Add default I2C device properties for Apollo Lake mfd: twl-core: Make it explicitly non-modular mfd: sun6i-prcm: Make it explicitly non-modular mfd: smsc-ece1099: Make it explicitly non-modular ...
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 6c084b266651..04053fe1e980 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -19,6 +19,7 @@
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <asm/unaligned.h>
22 23
23#define EC_COMMAND_RETRIES 50 24#define EC_COMMAND_RETRIES 50
24 25
@@ -234,11 +235,44 @@ static int cros_ec_host_command_proto_query_v2(struct cros_ec_device *ec_dev)
234 return ret; 235 return ret;
235} 236}
236 237
238static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev,
239 u16 cmd, u32 *mask)
240{
241 struct ec_params_get_cmd_versions *pver;
242 struct ec_response_get_cmd_versions *rver;
243 struct cros_ec_command *msg;
244 int ret;
245
246 msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)),
247 GFP_KERNEL);
248 if (!msg)
249 return -ENOMEM;
250
251 msg->version = 0;
252 msg->command = EC_CMD_GET_CMD_VERSIONS;
253 msg->insize = sizeof(*rver);
254 msg->outsize = sizeof(*pver);
255
256 pver = (struct ec_params_get_cmd_versions *)msg->data;
257 pver->cmd = cmd;
258
259 ret = cros_ec_cmd_xfer(ec_dev, msg);
260 if (ret > 0) {
261 rver = (struct ec_response_get_cmd_versions *)msg->data;
262 *mask = rver->version_mask;
263 }
264
265 kfree(msg);
266
267 return ret;
268}
269
237int cros_ec_query_all(struct cros_ec_device *ec_dev) 270int cros_ec_query_all(struct cros_ec_device *ec_dev)
238{ 271{
239 struct device *dev = ec_dev->dev; 272 struct device *dev = ec_dev->dev;
240 struct cros_ec_command *proto_msg; 273 struct cros_ec_command *proto_msg;
241 struct ec_response_get_protocol_info *proto_info; 274 struct ec_response_get_protocol_info *proto_info;
275 u32 ver_mask = 0;
242 int ret; 276 int ret;
243 277
244 proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info), 278 proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info),
@@ -328,6 +362,15 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
328 goto exit; 362 goto exit;
329 } 363 }
330 364
365 /* Probe if MKBP event is supported */
366 ret = cros_ec_get_host_command_version_mask(ec_dev,
367 EC_CMD_GET_NEXT_EVENT,
368 &ver_mask);
369 if (ret < 0 || ver_mask == 0)
370 ec_dev->mkbp_event_supported = 0;
371 else
372 ec_dev->mkbp_event_supported = 1;
373
331exit: 374exit:
332 kfree(proto_msg); 375 kfree(proto_msg);
333 return ret; 376 return ret;
@@ -397,3 +440,52 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
397 return ret; 440 return ret;
398} 441}
399EXPORT_SYMBOL(cros_ec_cmd_xfer_status); 442EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
443
444static int get_next_event(struct cros_ec_device *ec_dev)
445{
446 u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
447 struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
448 int ret;
449
450 msg->version = 0;
451 msg->command = EC_CMD_GET_NEXT_EVENT;
452 msg->insize = sizeof(ec_dev->event_data);
453 msg->outsize = 0;
454
455 ret = cros_ec_cmd_xfer(ec_dev, msg);
456 if (ret > 0) {
457 ec_dev->event_size = ret - 1;
458 memcpy(&ec_dev->event_data, msg->data,
459 sizeof(ec_dev->event_data));
460 }
461
462 return ret;
463}
464
465static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
466{
467 u8 buffer[sizeof(struct cros_ec_command) +
468 sizeof(ec_dev->event_data.data)];
469 struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
470
471 msg->version = 0;
472 msg->command = EC_CMD_MKBP_STATE;
473 msg->insize = sizeof(ec_dev->event_data.data);
474 msg->outsize = 0;
475
476 ec_dev->event_size = cros_ec_cmd_xfer(ec_dev, msg);
477 ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX;
478 memcpy(&ec_dev->event_data.data, msg->data,
479 sizeof(ec_dev->event_data.data));
480
481 return ec_dev->event_size;
482}
483
484int cros_ec_get_next_event(struct cros_ec_device *ec_dev)
485{
486 if (ec_dev->mkbp_event_supported)
487 return get_next_event(ec_dev);
488 else
489 return get_keyboard_state_event(ec_dev);
490}
491EXPORT_SYMBOL(cros_ec_get_next_event);