summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/block/floppy.c5
-rw-r--r--drivers/clocksource/Kconfig13
-rw-r--r--drivers/clocksource/vt8500_timer.c6
-rw-r--r--drivers/firmware/efi/libstub/fdt.c2
-rw-r--r--drivers/gpio/gpio-arizona.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.h2
-rw-r--r--drivers/hid/hid-core.c49
-rw-r--r--drivers/hid/hid-corsair.c13
-rw-r--r--drivers/hid/hid-cp2112.c8
-rw-r--r--drivers/hid/hid-debug.c4
-rw-r--r--drivers/hid/hid-gt683r.c8
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hid-input.c21
-rw-r--r--drivers/hid/hid-lenovo.c36
-rw-r--r--drivers/hid/hid-lg4ff.c6
-rw-r--r--drivers/hid/hid-logitech-hidpp.c286
-rw-r--r--drivers/hid/hid-multitouch.c24
-rw-r--r--drivers/hid/hid-ntrig.c32
-rw-r--r--drivers/hid/hid-picolcd_leds.c4
-rw-r--r--drivers/hid/hid-prodikeys.c12
-rw-r--r--drivers/hid/hid-roccat-arvo.c6
-rw-r--r--drivers/hid/hid-roccat-common.c6
-rw-r--r--drivers/hid/hid-roccat-isku.c6
-rw-r--r--drivers/hid/hid-roccat-kone.c12
-rw-r--r--drivers/hid/hid-roccat-koneplus.c12
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c12
-rw-r--r--drivers/hid/hid-roccat-lua.c4
-rw-r--r--drivers/hid/hid-roccat-pyra.c15
-rw-r--r--drivers/hid/hid-sensor-hub.c3
-rw-r--r--drivers/hid/hid-sony.c107
-rw-r--r--drivers/hid/hid-steelseries.c8
-rw-r--r--drivers/hid/hid-wiimote-modules.c8
-rw-r--r--drivers/hid/hid-wiimote.h3
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c22
-rw-r--r--drivers/hid/usbhid/hid-core.c6
-rw-r--r--drivers/hid/usbhid/usbhid.h2
-rw-r--r--drivers/hid/wacom_sys.c23
-rw-r--r--drivers/hid/wacom_wac.c617
-rw-r--r--drivers/hid/wacom_wac.h5
-rw-r--r--drivers/hsi/controllers/omap_ssi.c7
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c6
-rw-r--r--drivers/i2c/busses/Kconfig9
-rw-r--r--drivers/i2c/busses/i2c-at91.c53
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c10
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c80
-rw-r--r--drivers/i2c/busses/i2c-cadence.c73
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c23
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c32
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c1
-rw-r--r--drivers/i2c/busses/i2c-emev2.c112
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c4
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c92
-rw-r--r--drivers/i2c/busses/i2c-imx.c109
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c54
-rw-r--r--drivers/i2c/busses/i2c-piix4.c202
-rw-r--r--drivers/i2c/busses/i2c-rcar.c319
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c6
-rw-r--r--drivers/i2c/busses/i2c-st.c3
-rw-r--r--drivers/i2c/busses/i2c-taos-evm.c8
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c11
-rw-r--r--drivers/i2c/busses/i2c-uniphier.c11
-rw-r--r--drivers/i2c/busses/i2c-xiic.c12
-rw-r--r--drivers/i2c/busses/i2c-xlr.c250
-rw-r--r--drivers/i2c/i2c-core.c56
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c2
-rw-r--r--drivers/lguest/core.c74
-rw-r--r--drivers/md/raid0.c4
-rw-r--r--drivers/media/common/saa7146/saa7146_video.c2
-rw-r--r--drivers/media/dvb-frontends/m88ds3103.c2
-rw-r--r--drivers/media/dvb-frontends/si2165.c4
-rw-r--r--drivers/media/pci/netup_unidvb/netup_unidvb_core.c2
-rw-r--r--drivers/mfd/88pm80x.c4
-rw-r--r--drivers/mfd/88pm860x-core.c13
-rw-r--r--drivers/mfd/Kconfig20
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/aat2870-core.c5
-rw-r--r--drivers/mfd/ab3100-core.c23
-rw-r--r--drivers/mfd/ab3100-otp.c5
-rw-r--r--drivers/mfd/ab8500-core.c506
-rw-r--r--drivers/mfd/ab8500-debugfs.c25
-rw-r--r--drivers/mfd/ab8500-gpadc.c145
-rw-r--r--drivers/mfd/ab8500-sysctrl.c13
-rw-r--r--drivers/mfd/adp5520.c6
-rw-r--r--drivers/mfd/arizona-core.c92
-rw-r--r--drivers/mfd/arizona-i2c.c2
-rw-r--r--drivers/mfd/arizona-irq.c95
-rw-r--r--drivers/mfd/arizona-spi.c7
-rw-r--r--drivers/mfd/arizona.h4
-rw-r--r--drivers/mfd/as3711.c28
-rw-r--r--drivers/mfd/as3722.c30
-rw-r--r--drivers/mfd/asic3.c30
-rw-r--r--drivers/mfd/cros_ec_i2c.c2
-rw-r--r--drivers/mfd/cros_ec_spi.c34
-rw-r--r--drivers/mfd/cs47l24-tables.c1629
-rw-r--r--drivers/mfd/cs5535-mfd.c6
-rw-r--r--drivers/mfd/da903x.c14
-rw-r--r--drivers/mfd/da9052-i2c.c2
-rw-r--r--drivers/mfd/da9052-irq.c2
-rw-r--r--drivers/mfd/davinci_voicecodec.c5
-rw-r--r--drivers/mfd/dm355evm_msp.c2
-rw-r--r--drivers/mfd/htc-egpio.c2
-rw-r--r--drivers/mfd/lpc_ich.c15
-rw-r--r--drivers/mfd/max14577.c4
-rw-r--r--drivers/mfd/max77686.c4
-rw-r--r--drivers/mfd/max77693.c4
-rw-r--r--drivers/mfd/max77843.c4
-rw-r--r--drivers/mfd/max8925-i2c.c4
-rw-r--r--drivers/mfd/max8997.c8
-rw-r--r--drivers/mfd/max8998.c8
-rw-r--r--drivers/mfd/mc13xxx-core.c8
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c4
-rw-r--r--drivers/mfd/qcom_rpm.c2
-rw-r--r--drivers/mfd/sec-core.c43
-rw-r--r--drivers/mfd/sec-irq.c8
-rw-r--r--drivers/mfd/sta2x11-mfd.c36
-rw-r--r--drivers/mfd/syscon.c13
-rw-r--r--drivers/mfd/tc6393xb.c4
-rw-r--r--drivers/mfd/tps65010.c4
-rw-r--r--drivers/mfd/ucb1x00-core.c2
-rw-r--r--drivers/mfd/wm5110-tables.c6
-rw-r--r--drivers/mfd/wm831x-otp.c10
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c2
-rw-r--r--drivers/of/address.c2
-rw-r--r--drivers/of/dynamic.c65
-rw-r--r--drivers/of/irq.c27
-rw-r--r--drivers/of/of_private.h2
-rw-r--r--drivers/of/overlay.c8
-rw-r--r--drivers/of/platform.c1
-rw-r--r--drivers/of/unittest.c18
-rw-r--r--drivers/power/Kconfig17
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/bq2415x_charger.c6
-rw-r--r--drivers/power/bq27xxx_battery.c348
-rw-r--r--drivers/power/bq27xxx_battery_i2c.c150
-rw-r--r--drivers/power/ds2782_battery.c4
-rw-r--r--drivers/power/generic-adc-battery.c2
-rw-r--r--drivers/power/isp1704_charger.c2
-rw-r--r--drivers/power/max8903_charger.c24
-rw-r--r--drivers/power/reset/at91-reset.c1
-rw-r--r--drivers/power/test_power.c2
-rw-r--r--drivers/regulator/Kconfig4
-rw-r--r--drivers/regulator/s2mps11.c143
-rw-r--r--drivers/rtc/rtc-s5m.c37
-rw-r--r--drivers/soc/ti/knav_dma.c2
-rw-r--r--drivers/video/backlight/adp8860_bl.c18
-rw-r--r--drivers/video/backlight/adp8870_bl.c10
-rw-r--r--drivers/video/backlight/gpio_backlight.c10
-rw-r--r--drivers/video/backlight/pwm_bl.c28
-rw-r--r--drivers/video/backlight/tps65217_bl.c9
152 files changed, 4718 insertions, 2235 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 795d0ca714bf..8f5d076baeb0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -106,7 +106,7 @@ obj-y += i2c/ media/
obj-$(CONFIG_PPS) += pps/
obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
obj-$(CONFIG_W1) += w1/
-obj-$(CONFIG_POWER_SUPPLY) += power/
+obj-y += power/
obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_THERMAL) += thermal/
obj-$(CONFIG_WATCHDOG) += watchdog/
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 331363e7de0f..9e251201dd48 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3585,7 +3585,7 @@ static void __init config_types(void)
unsigned int type = UDP->cmos;
struct floppy_drive_params *params;
const char *name = NULL;
- static char temparea[32];
+ char temparea[32];
if (type < ARRAY_SIZE(default_drive_params)) {
params = &default_drive_params[type].params;
@@ -3596,7 +3596,8 @@ static void __init config_types(void)
allowed_drive_mask &= ~(1 << drive);
} else {
params = &default_drive_params[0].params;
- sprintf(temparea, "unknown type %d (usb?)", type);
+ snprintf(temparea, sizeof(temparea),
+ "unknown type %d (usb?)", type);
name = temparea;
}
if (name) {
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index b251013eef0a..56777f04d2d9 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -152,7 +152,7 @@ config CLKSRC_EFM32
config CLKSRC_LPC32XX
bool "Clocksource for LPC32XX" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
select CLKSRC_MMIO
select CLKSRC_OF
help
@@ -160,6 +160,7 @@ config CLKSRC_LPC32XX
config CLKSRC_PISTACHIO
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
+ depends on HAS_IOMEM
select CLKSRC_OF
help
Enables the clocksource for the Pistachio SoC.
@@ -256,6 +257,7 @@ config CLKSRC_SAMSUNG_PWM
config FSL_FTM_TIMER
bool "Freescale FlexTimer Module driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_MMIO
help
Support for Freescale FlexTimer Module (FTM) timer.
@@ -269,7 +271,7 @@ config SYS_SUPPORTS_SH_CMT
config MTK_TIMER
bool "Mediatek timer driver" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
select CLKSRC_OF
select CLKSRC_MMIO
help
@@ -365,20 +367,20 @@ config CLKSRC_PXA
config H8300_TMR8
bool "Clockevent timer for the H8300 platform" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
help
This enables the 8 bits timer for the H8300 platform.
config H8300_TMR16
bool "Clockevent timer for the H83069 platform" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
help
This enables the 16 bits timer for the H8300 platform with the
H83069 cpu.
config H8300_TPU
bool "Clocksource for the H8300 platform" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
+ depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
help
This enables the clocksource for the H8300 platform with the
H8S2678 cpu.
@@ -391,6 +393,7 @@ config CLKSRC_IMX_GPT
config CLKSRC_ST_LPC
bool "Low power clocksource found in the LPC" if COMPILE_TEST
select CLKSRC_OF if OF
+ depends on HAS_IOMEM
help
Enable this option to use the Low Power controller timer
as clocksource.
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index de49805fbb09..ddb409274f45 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -49,6 +49,8 @@
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+#define MIN_OSCR_DELTA 16
+
static void __iomem *regbase;
static cycle_t vt8500_timer_read(struct clocksource *cs)
@@ -79,7 +81,7 @@ static int vt8500_timer_set_next_event(unsigned long cycles,
cpu_relax();
writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
- if ((signed)(alarm - clocksource.read(&clocksource)) <= 16)
+ if ((signed)(alarm - clocksource.read(&clocksource)) <= MIN_OSCR_DELTA)
return -ETIME;
writel(1, regbase + TIMER_IER_VAL);
@@ -150,7 +152,7 @@ static void __init vt8500_timer_init(struct device_node *np)
pr_err("%s: setup_irq failed for %s\n", __func__,
clockevent.name);
clockevents_config_and_register(&clockevent, VT8500_TIMER_HZ,
- 4, 0xf0000000);
+ MIN_OSCR_DELTA * 2, 0xf0000000);
}
CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index b62e2f5dcab3..cf7b7d46302a 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -253,7 +253,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
sys_table->boottime->free_pool(memory_map);
new_fdt_size += EFI_PAGE_SIZE;
} else {
- pr_efi_err(sys_table, "Unable to constuct new device tree.\n");
+ pr_efi_err(sys_table, "Unable to construct new device tree.\n");
goto fail_free_mmap;
}
}
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index ca002739616a..624ea5421995 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -122,6 +122,10 @@ static int arizona_gpio_probe(struct platform_device *pdev)
case WM1814:
arizona_gpio->gpio_chip.ngpio = 5;
break;
+ case WM1831:
+ case CS47L24:
+ arizona_gpio->gpio_chip.ngpio = 2;
+ break;
default:
dev_err(&pdev->dev, "Unknown chip variant %d\n",
arizona->type);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.h b/drivers/gpu/drm/exynos/exynos_drm_fb.h
index 726a2d44371f..cf39f9816a87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.h
@@ -12,7 +12,7 @@
*/
#ifndef _EXYNOS_DRM_FB_H_
-#define _EXYNOS_DRM_FB_H
+#define _EXYNOS_DRM_FB_H_
#include "exynos_drm_gem.h"
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c6f7a694f67a..7e89288b1537 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -625,7 +625,7 @@ static void hid_close_report(struct hid_device *device)
static void hid_device_release(struct device *dev)
{
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
hid_close_report(hid);
kfree(hid->dev_rdesc);
@@ -1571,8 +1571,8 @@ read_report_descriptor(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct device *dev = kobj_to_dev(kobj);
+ struct hid_device *hdev = to_hid_device(dev);
if (off >= hdev->rsize)
return 0;
@@ -1589,7 +1589,7 @@ static ssize_t
show_country(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
return sprintf(buf, "%02x\n", hdev->country & 0xff);
}
@@ -1691,11 +1691,6 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
hid_warn(hdev,
"can't create sysfs country code attribute err: %d\n", ret);
- ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
- if (ret)
- hid_warn(hdev,
- "can't create sysfs report descriptor attribute err: %d\n", ret);
-
hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
buf, bus, hdev->version >> 8, hdev->version & 0xff,
type, hdev->name, hdev->phys);
@@ -1707,7 +1702,6 @@ EXPORT_SYMBOL_GPL(hid_connect);
void hid_disconnect(struct hid_device *hdev)
{
device_remove_file(&hdev->dev, &dev_attr_country);
- device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
if (hdev->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hdev);
if (hdev->claimed & HID_CLAIMED_HIDDEV)
@@ -1902,6 +1896,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
@@ -2076,7 +2071,7 @@ struct hid_dynid {
static ssize_t store_new_id(struct device_driver *drv, const char *buf,
size_t count)
{
- struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+ struct hid_driver *hdrv = to_hid_driver(drv);
struct hid_dynid *dynid;
__u32 bus, vendor, product;
unsigned long driver_data = 0;
@@ -2138,17 +2133,16 @@ static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
static int hid_bus_match(struct device *dev, struct device_driver *drv)
{
- struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_driver *hdrv = to_hid_driver(drv);
+ struct hid_device *hdev = to_hid_device(dev);
return hid_match_device(hdev, hdrv) != NULL;
}
static int hid_device_probe(struct device *dev)
{
- struct hid_driver *hdrv = container_of(dev->driver,
- struct hid_driver, driver);
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_driver *hdrv = to_hid_driver(dev->driver);
+ struct hid_device *hdev = to_hid_device(dev);
const struct hid_device_id *id;
int ret = 0;
@@ -2190,7 +2184,7 @@ unlock_driver_lock:
static int hid_device_remove(struct device *dev)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct hid_driver *hdrv;
int ret = 0;
@@ -2223,12 +2217,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
char *buf)
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- int len;
-
- len = snprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n",
- hdev->bus, hdev->group, hdev->vendor, hdev->product);
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+ return scnprintf(buf, PAGE_SIZE, "hid:b%04Xg%04Xv%08Xp%08X\n",
+ hdev->bus, hdev->group, hdev->vendor, hdev->product);
}
static DEVICE_ATTR_RO(modalias);
@@ -2236,11 +2227,19 @@ static struct attribute *hid_dev_attrs[] = {
&dev_attr_modalias.attr,
NULL,
};
-ATTRIBUTE_GROUPS(hid_dev);
+static struct bin_attribute *hid_dev_bin_attrs[] = {
+ &dev_bin_attr_report_desc,
+ NULL
+};
+static const struct attribute_group hid_dev_group = {
+ .attrs = hid_dev_attrs,
+ .bin_attrs = hid_dev_bin_attrs,
+};
+__ATTRIBUTE_GROUPS(hid_dev);
static int hid_uevent(struct device *dev, struct kobj_uevent_env *env)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
if (add_uevent_var(env, "HID_ID=%04X:%08X:%08X",
hdev->bus, hdev->vendor, hdev->product))
@@ -2408,6 +2407,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454_V2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) },
@@ -2660,6 +2660,7 @@ struct hid_device *hid_allocate_device(void)
device_initialize(&hdev->dev);
hdev->dev.release = hid_device_release;
hdev->dev.bus = &hid_bus_type;
+ device_enable_async_suspend(&hdev->dev);
hid_close_report(hdev);
diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c
index bcefb9ebb026..58551964ce86 100644
--- a/drivers/hid/hid-corsair.c
+++ b/drivers/hid/hid-corsair.c
@@ -655,18 +655,7 @@ static struct hid_driver corsair_driver = {
.input_mapping = corsair_input_mapping,
};
-static int __init corsair_init(void)
-{
- return hid_register_driver(&corsair_driver);
-}
-
-static void corsair_exit(void)
-{
- hid_unregister_driver(&corsair_driver);
-}
-
-module_init(corsair_init);
-module_exit(corsair_exit);
+module_hid_driver(corsair_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Clement Vuchener");
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 7afc3fcc122c..7c38bfa05fac 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -807,7 +807,7 @@ static ssize_t name##_store(struct device *kdev, \
struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
- struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
+ struct hid_device *hdev = to_hid_device(kdev); \
struct cp2112_usb_config_report cfg; \
int ret = cp2112_get_usb_config(hdev, &cfg); \
if (ret) \
@@ -822,7 +822,7 @@ static ssize_t name##_store(struct device *kdev, \
static ssize_t name##_show(struct device *kdev, \
struct device_attribute *attr, char *buf) \
{ \
- struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
+ struct hid_device *hdev = to_hid_device(kdev); \
struct cp2112_usb_config_report cfg; \
int ret = cp2112_get_usb_config(hdev, &cfg); \
if (ret) \
@@ -887,7 +887,7 @@ static ssize_t pstr_store(struct device *kdev,
struct device_attribute *kattr, const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(kdev);
struct cp2112_pstring_attribute *attr =
container_of(kattr, struct cp2112_pstring_attribute, attr);
struct cp2112_string_report report;
@@ -918,7 +918,7 @@ static ssize_t pstr_store(struct device *kdev,
static ssize_t pstr_show(struct device *kdev,
struct device_attribute *kattr, char *buf)
{
- struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(kdev);
struct cp2112_pstring_attribute *attr =
container_of(kattr, struct cp2112_pstring_attribute, attr);
struct cp2112_string_report report;
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 2886b645ced7..acfb522a432a 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -659,13 +659,13 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
/* enqueue string to 'events' ring buffer */
void hid_debug_event(struct hid_device *hdev, char *buf)
{
- int i;
+ unsigned i;
struct hid_debug_list *list;
unsigned long flags;
spin_lock_irqsave(&hdev->debug_list_lock, flags);
list_for_each_entry(list, &hdev->debug_list, node) {
- for (i = 0; i < strlen(buf); i++)
+ for (i = 0; buf[i]; i++)
list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
buf[i];
list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
diff --git a/drivers/hid/hid-gt683r.c b/drivers/hid/hid-gt683r.c
index 0d6f135e266c..a298fbd8db6b 100644
--- a/drivers/hid/hid-gt683r.c
+++ b/drivers/hid/hid-gt683r.c
@@ -70,7 +70,7 @@ static void gt683r_brightness_set(struct led_classdev *led_cdev,
{
int i;
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct gt683r_led *led = hid_get_drvdata(hdev);
for (i = 0; i < GT683R_LED_COUNT; i++) {
@@ -89,8 +89,7 @@ static ssize_t mode_show(struct device *dev,
char *buf)
{
u8 sysfs_mode;
- struct hid_device *hdev = container_of(dev->parent,
- struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev->parent);
struct gt683r_led *led = hid_get_drvdata(hdev);
if (led->mode == GT683R_LED_NORMAL)
@@ -108,8 +107,7 @@ static ssize_t mode_store(struct device *dev,
const char *buf, size_t count)
{
u8 sysfs_mode;
- struct hid_device *hdev = container_of(dev->parent,
- struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev->parent);
struct gt683r_led *led = hid_get_drvdata(hdev);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 8b78a7f1f779..b6ff6e78ac54 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -510,6 +510,7 @@
#define USB_VENDOR_ID_ITE 0x048d
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
+#define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396
#define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
@@ -615,6 +616,7 @@
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
#define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f
+#define USB_DEVICE_ID_LOGITECH_G920_WHEEL 0xc262
#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287
@@ -664,6 +666,7 @@
#define USB_DEVICE_ID_PICOLCD 0xc002
#define USB_DEVICE_ID_PICOLCD_BOOTLOADER 0xf002
#define USB_DEVICE_ID_PICK16F1454 0x0042
+#define USB_DEVICE_ID_PICK16F1454_V2 0xf2f7
#define USB_VENDOR_ID_MICROSOFT 0x045e
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2ba6bf69b7d0..bcfaf32d9e5e 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -303,6 +303,7 @@ static enum power_supply_property hidinput_battery_props[] = {
#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */
#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
+#define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */
static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
@@ -320,6 +321,9 @@ static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
+ USB_DEVICE_ID_ELECOM_BM084),
+ HID_BATTERY_QUIRK_IGNORE },
{}
};
@@ -408,6 +412,14 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
if (dev->battery != NULL)
goto out; /* already initialized? */
+ quirks = find_battery_quirk(dev);
+
+ hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
+ dev->bus, dev->vendor, dev->product, dev->version, quirks);
+
+ if (quirks & HID_BATTERY_QUIRK_IGNORE)
+ goto out;
+
psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);
if (psy_desc == NULL)
goto out;
@@ -424,11 +436,6 @@ static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
psy_desc->use_for_apm = 0;
psy_desc->get_property = hidinput_get_battery_property;
- quirks = find_battery_quirk(dev);
-
- hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
- dev->bus, dev->vendor, dev->product, dev->version, quirks);
-
min = field->logical_minimum;
max = field->logical_maximum;
@@ -960,6 +967,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
goto ignore;
case HID_UP_LOGIVENDOR:
+ /* intentional fallback */
+ case HID_UP_LOGIVENDOR2:
+ /* intentional fallback */
+ case HID_UP_LOGIVENDOR3:
goto ignore;
case HID_UP_PID:
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 8979f1fd5208..0125e356bd8d 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -220,7 +220,7 @@ static ssize_t attr_fn_lock_show_cptkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock);
@@ -231,7 +231,7 @@ static ssize_t attr_fn_lock_store_cptkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
int value;
@@ -250,7 +250,7 @@ static ssize_t attr_sensitivity_show_cptkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n",
@@ -262,7 +262,7 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
int value;
@@ -387,7 +387,7 @@ static ssize_t attr_press_to_select_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
@@ -398,7 +398,7 @@ static ssize_t attr_press_to_select_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -417,7 +417,7 @@ static ssize_t attr_dragging_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
@@ -428,7 +428,7 @@ static ssize_t attr_dragging_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -447,7 +447,7 @@ static ssize_t attr_release_to_select_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
@@ -458,7 +458,7 @@ static ssize_t attr_release_to_select_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -477,7 +477,7 @@ static ssize_t attr_select_right_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
@@ -488,7 +488,7 @@ static ssize_t attr_select_right_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -507,7 +507,7 @@ static ssize_t attr_sensitivity_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n",
@@ -519,7 +519,7 @@ static ssize_t attr_sensitivity_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -536,7 +536,7 @@ static ssize_t attr_press_speed_show_tpkbd(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%u\n",
@@ -548,7 +548,7 @@ static ssize_t attr_press_speed_store_tpkbd(struct device *dev,
const char *buf,
size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int value;
@@ -609,7 +609,7 @@ static enum led_brightness lenovo_led_brightness_get_tpkbd(
struct led_classdev *led_cdev)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
int led_nr = 0;
@@ -625,7 +625,7 @@ static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
struct hid_report *report;
int led_nr = 0;
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index fbddcb37ae98..af3a8ec8a746 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -33,8 +33,6 @@
#include "hid-lg4ff.h"
#include "hid-ids.h"
-#define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
-
#define LG4FF_MMODE_IS_MULTIMODE 0
#define LG4FF_MMODE_SWITCHED 1
#define LG4FF_MMODE_NOT_MULTIMODE 2
@@ -1020,7 +1018,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct lg_drv_data *drv_data = hid_get_drvdata(hid);
struct lg4ff_device_entry *entry;
int i, state = 0;
@@ -1055,7 +1053,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct lg_drv_data *drv_data = hid_get_drvdata(hid);
struct lg4ff_device_entry *entry;
int i, value = 0;
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 5fd97860aec4..bd2ab476c65e 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -40,18 +40,22 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define REPORT_ID_HIDPP_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11
+#define REPORT_ID_HIDPP_VERY_LONG 0x12
#define HIDPP_REPORT_SHORT_LENGTH 7
#define HIDPP_REPORT_LONG_LENGTH 20
+#define HIDPP_REPORT_VERY_LONG_LENGTH 64
#define HIDPP_QUIRK_CLASS_WTP BIT(0)
#define HIDPP_QUIRK_CLASS_M560 BIT(1)
#define HIDPP_QUIRK_CLASS_K400 BIT(2)
+#define HIDPP_QUIRK_CLASS_G920 BIT(3)
/* bits 2..20 are reserved for classes */
#define HIDPP_QUIRK_CONNECT_EVENTS BIT(21)
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
+#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
#define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \
HIDPP_QUIRK_CONNECT_EVENTS)
@@ -81,13 +85,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
struct fap {
u8 feature_index;
u8 funcindex_clientid;
- u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+ u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
};
struct rap {
u8 sub_id;
u8 reg_address;
- u8 params[HIDPP_REPORT_LONG_LENGTH - 4U];
+ u8 params[HIDPP_REPORT_VERY_LONG_LENGTH - 4U];
};
struct hidpp_report {
@@ -144,8 +148,11 @@ static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
static int __hidpp_send_report(struct hid_device *hdev,
struct hidpp_report *hidpp_report)
{
+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);
int fields_count, ret;
+ hidpp = hid_get_drvdata(hdev);
+
switch (hidpp_report->report_id) {
case REPORT_ID_HIDPP_SHORT:
fields_count = HIDPP_REPORT_SHORT_LENGTH;
@@ -153,6 +160,9 @@ static int __hidpp_send_report(struct hid_device *hdev,
case REPORT_ID_HIDPP_LONG:
fields_count = HIDPP_REPORT_LONG_LENGTH;
break;
+ case REPORT_ID_HIDPP_VERY_LONG:
+ fields_count = HIDPP_REPORT_VERY_LONG_LENGTH;
+ break;
default:
return -ENODEV;
}
@@ -163,9 +173,13 @@ static int __hidpp_send_report(struct hid_device *hdev,
*/
hidpp_report->device_index = 0xff;
- ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
- (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
- HID_REQ_SET_REPORT);
+ if (hidpp->quirks & HIDPP_QUIRK_FORCE_OUTPUT_REPORTS) {
+ ret = hid_hw_output_report(hdev, (u8 *)hidpp_report, fields_count);
+ } else {
+ ret = hid_hw_raw_request(hdev, hidpp_report->report_id,
+ (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+ }
return ret == fields_count ? 0 : -1;
}
@@ -217,8 +231,9 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
goto exit;
}
- if (response->report_id == REPORT_ID_HIDPP_LONG &&
- response->fap.feature_index == HIDPP20_ERROR) {
+ if ((response->report_id == REPORT_ID_HIDPP_LONG ||
+ response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
+ response->fap.feature_index == HIDPP20_ERROR) {
ret = response->fap.params[1];
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
goto exit;
@@ -243,7 +258,11 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
if (!message)
return -ENOMEM;
- message->report_id = REPORT_ID_HIDPP_LONG;
+
+ if (param_count > (HIDPP_REPORT_LONG_LENGTH - 4))
+ message->report_id = REPORT_ID_HIDPP_VERY_LONG;
+ else
+ message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid;
memcpy(&message->fap.params, params, param_count);
@@ -258,13 +277,23 @@ static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
struct hidpp_report *response)
{
struct hidpp_report *message;
- int ret;
+ int ret, max_count;
- if ((report_id != REPORT_ID_HIDPP_SHORT) &&
- (report_id != REPORT_ID_HIDPP_LONG))
+ switch (report_id) {
+ case REPORT_ID_HIDPP_SHORT:
+ max_count = HIDPP_REPORT_SHORT_LENGTH - 4;
+ break;
+ case REPORT_ID_HIDPP_LONG:
+ max_count = HIDPP_REPORT_LONG_LENGTH - 4;
+ break;
+ case REPORT_ID_HIDPP_VERY_LONG:
+ max_count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+ break;
+ default:
return -EINVAL;
+ }
- if (param_count > sizeof(message->rap.params))
+ if (param_count > max_count)
return -EINVAL;
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
@@ -508,10 +537,19 @@ static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp,
if (ret)
return ret;
- if (response.report_id == REPORT_ID_HIDPP_LONG)
+ switch (response.report_id) {
+ case REPORT_ID_HIDPP_VERY_LONG:
+ count = HIDPP_REPORT_VERY_LONG_LENGTH - 4;
+ break;
+ case REPORT_ID_HIDPP_LONG:
count = HIDPP_REPORT_LONG_LENGTH - 4;
- else
+ break;
+ case REPORT_ID_HIDPP_SHORT:
count = HIDPP_REPORT_SHORT_LENGTH - 4;
+ break;
+ default:
+ return -EPROTO;
+ }
if (len_buf < count)
count = len_buf;
@@ -1257,6 +1295,131 @@ static int k400_connect(struct hid_device *hdev, bool connected)
return k400_disable_tap_to_click(hidpp);
}
+/* ------------------------------------------------------------------------- */
+/* Logitech G920 Driving Force Racing Wheel for Xbox One */
+/* ------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123
+
+/* Using session ID = 1 */
+#define CMD_G920_FORCE_GET_APERTURE 0x51
+#define CMD_G920_FORCE_SET_APERTURE 0x61
+
+struct g920_private_data {
+ u8 force_feature;
+ u16 range;
+};
+
+static ssize_t g920_range_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hid = to_hid_device(dev);
+ struct hidpp_device *hidpp = hid_get_drvdata(hid);
+ struct g920_private_data *pdata;
+
+ pdata = hidpp->private_data;
+ if (!pdata) {
+ hid_err(hid, "Private driver data not found!\n");
+ return -EINVAL;
+ }
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range);
+}
+
+static ssize_t g920_range_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hid_device *hid = to_hid_device(dev);
+ struct hidpp_device *hidpp = hid_get_drvdata(hid);
+ struct g920_private_data *pdata;
+ struct hidpp_report response;
+ u8 params[2];
+ int ret;
+ u16 range = simple_strtoul(buf, NULL, 10);
+
+ pdata = hidpp->private_data;
+ if (!pdata) {
+ hid_err(hid, "Private driver data not found!\n");
+ return -EINVAL;
+ }
+
+ if (range < 180)
+ range = 180;
+ else if (range > 900)
+ range = 900;
+
+ params[0] = range >> 8;
+ params[1] = range & 0x00FF;
+
+ ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature,
+ CMD_G920_FORCE_SET_APERTURE, params, 2, &response);
+ if (ret)
+ return ret;
+
+ pdata->range = range;
+ return count;
+}
+
+static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, g920_range_show, g920_range_store);
+
+static int g920_allocate(struct hid_device *hdev)
+{
+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+ struct g920_private_data *pdata;
+
+ pdata = devm_kzalloc(&hdev->dev, sizeof(struct g920_private_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ hidpp->private_data = pdata;
+
+ return 0;
+}
+
+static int g920_get_config(struct hidpp_device *hidpp)
+{
+ struct g920_private_data *pdata = hidpp->private_data;
+ struct hidpp_report response;
+ u8 feature_type;
+ u8 feature_index;
+ int ret;
+
+ pdata = hidpp->private_data;
+ if (!pdata) {
+ hid_err(hidpp->hid_dev, "Private driver data not found!\n");
+ return -EINVAL;
+ }
+
+ /* Find feature and store for later use */
+ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK,
+ &feature_index, &feature_type);
+ if (ret)
+ return ret;
+
+ pdata->force_feature = feature_index;
+
+ /* Read current Range */
+ ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+ CMD_G920_FORCE_GET_APERTURE, NULL, 0, &response);
+ if (ret > 0) {
+ hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+ __func__, ret);
+ return -EPROTO;
+ }
+ if (ret)
+ return ret;
+
+ pdata->range = get_unaligned_be16(&response.fap.params[0]);
+
+ /* Create sysfs interface */
+ ret = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range);
+ if (ret)
+ hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d\n", ret);
+
+ return 0;
+}
+
/* -------------------------------------------------------------------------- */
/* Generic HID++ devices */
/* -------------------------------------------------------------------------- */
@@ -1276,6 +1439,25 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
+static int hidpp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+ /* Ensure that Logitech G920 is not given a default fuzz/flat value */
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+ if (usage->type == EV_ABS && (usage->code == ABS_X ||
+ usage->code == ABS_Y || usage->code == ABS_Z ||
+ usage->code == ABS_RZ)) {
+ field->application = HID_GD_MULTIAXIS;
+ }
+ }
+
+ return 0;
+}
+
+
static void hidpp_populate_input(struct hidpp_device *hidpp,
struct input_dev *input, bool origin_is_hid_core)
{
@@ -1347,6 +1529,14 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
/* Generic HID++ processing. */
switch (data[0]) {
+ case REPORT_ID_HIDPP_VERY_LONG:
+ if (size != HIDPP_REPORT_VERY_LONG_LENGTH) {
+ hid_err(hdev, "received hid++ report of bad size (%d)",
+ size);
+ return 1;
+ }
+ ret = hidpp_raw_hidpp_event(hidpp, data, size);
+ break;
case REPORT_ID_HIDPP_LONG:
if (size != HIDPP_REPORT_LONG_LENGTH) {
hid_err(hdev, "received hid++ report of bad size (%d)",
@@ -1393,10 +1583,12 @@ static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying)
else
name = hidpp_get_device_name(hidpp);
- if (!name)
+ if (!name) {
hid_err(hdev, "unable to retrieve the name of the device");
- else
+ } else {
+ dbg_hid("HID++: Got name: %s\n", name);
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
+ }
kfree(name);
}
@@ -1547,6 +1739,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = k400_allocate(hdev);
if (ret)
goto allocate_fail;
+ } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+ ret = g920_allocate(hdev);
+ if (ret)
+ goto allocate_fail;
}
INIT_WORK(&hidpp->work, delayed_work_cb);
@@ -1559,6 +1755,25 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto hid_parse_fail;
}
+ if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
+ connect_mask &= ~HID_CONNECT_HIDINPUT;
+
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+ ret = hid_hw_start(hdev, connect_mask);
+ if (ret) {
+ hid_err(hdev, "hw start failed\n");
+ goto hid_hw_start_fail;
+ }
+ ret = hid_hw_open(hdev);
+ if (ret < 0) {
+ dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
+ __func__, ret);
+ hid_hw_stop(hdev);
+ goto hid_hw_start_fail;
+ }
+ }
+
+
/* Allow incoming packets */
hid_device_io_start(hdev);
@@ -1567,8 +1782,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (!connected) {
ret = -ENODEV;
hid_err(hdev, "Device not connected");
- hid_device_io_stop(hdev);
- goto hid_parse_fail;
+ goto hid_hw_open_failed;
}
hid_info(hdev, "HID++ %u.%u device connected.\n",
@@ -1581,19 +1795,22 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
ret = wtp_get_config(hidpp);
if (ret)
- goto hid_parse_fail;
+ goto hid_hw_open_failed;
+ } else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
+ ret = g920_get_config(hidpp);
+ if (ret)
+ goto hid_hw_open_failed;
}
/* Block incoming packets */
hid_device_io_stop(hdev);
- if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
- connect_mask &= ~HID_CONNECT_HIDINPUT;
-
- ret = hid_hw_start(hdev, connect_mask);
- if (ret) {
- hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
- goto hid_hw_start_fail;
+ if (!(hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
+ ret = hid_hw_start(hdev, connect_mask);
+ if (ret) {
+ hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
+ goto hid_hw_start_fail;
+ }
}
if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
@@ -1605,6 +1822,13 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
+hid_hw_open_failed:
+ hid_device_io_stop(hdev);
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+ device_remove_file(&hdev->dev, &dev_attr_range);
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+ }
hid_hw_start_fail:
hid_parse_fail:
cancel_work_sync(&hidpp->work);
@@ -1618,9 +1842,13 @@ static void hidpp_remove(struct hid_device *hdev)
{
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+ if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
+ device_remove_file(&hdev->dev, &dev_attr_range);
+ hid_hw_close(hdev);
+ }
+ hid_hw_stop(hdev);
cancel_work_sync(&hidpp->work);
mutex_destroy(&hidpp->send_mutex);
- hid_hw_stop(hdev);
}
static const struct hid_device_id hidpp_devices[] = {
@@ -1648,6 +1876,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
+
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
+ .driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
{}
};
@@ -1661,6 +1892,7 @@ static struct hid_driver hidpp_driver = {
.raw_event = hidpp_raw_event,
.input_configured = hidpp_input_configured,
.input_mapping = hidpp_input_mapping,
+ .input_mapped = hidpp_input_mapped,
};
module_hid_driver(hidpp_driver);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 3d664d01305e..296d4991560e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -272,7 +272,7 @@ static ssize_t mt_show_quirks(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct mt_device *td = hid_get_drvdata(hdev);
return sprintf(buf, "%u\n", td->mtclass.quirks);
@@ -282,7 +282,7 @@ static ssize_t mt_set_quirks(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct mt_device *td = hid_get_drvdata(hdev);
unsigned long val;
@@ -357,8 +357,19 @@ static void mt_feature_mapping(struct hid_device *hdev,
break;
}
- td->inputmode = field->report->id;
- td->inputmode_index = usage->usage_index;
+ if (td->inputmode < 0) {
+ td->inputmode = field->report->id;
+ td->inputmode_index = usage->usage_index;
+ } else {
+ /*
+ * Some elan panels wrongly declare 2 input mode
+ * features, and silently ignore when we set the
+ * value in the second field. Skip the second feature
+ * and hope for the best.
+ */
+ dev_info(&hdev->dev,
+ "Ignoring the extra HID_DG_INPUTMODE\n");
+ }
break;
case HID_DG_CONTACTMAX:
@@ -486,6 +497,11 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
mt_store_field(usage, td, hi);
return 1;
case HID_DG_CONFIDENCE:
+ if (cls->name == MT_CLS_WIN_8 &&
+ field->application == HID_DG_TOUCHPAD) {
+ cls->quirks &= ~MT_QUIRK_ALWAYS_VALID;
+ cls->quirks |= MT_QUIRK_VALID_IS_CONFIDENCE;
+ }
mt_store_field(usage, td, hi);
return 1;
case HID_DG_TIPSWITCH:
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 756d1ef9bd99..1b0084d4af2e 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -173,7 +173,7 @@ static ssize_t show_phys_width(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->sensor_physical_width);
@@ -185,7 +185,7 @@ static ssize_t show_phys_height(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->sensor_physical_height);
@@ -197,7 +197,7 @@ static ssize_t show_log_width(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->sensor_logical_width);
@@ -209,7 +209,7 @@ static ssize_t show_log_height(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->sensor_logical_height);
@@ -221,7 +221,7 @@ static ssize_t show_min_width(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->min_width *
@@ -233,7 +233,7 @@ static ssize_t set_min_width(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
@@ -256,7 +256,7 @@ static ssize_t show_min_height(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->min_height *
@@ -268,7 +268,7 @@ static ssize_t set_min_height(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
@@ -292,7 +292,7 @@ static ssize_t show_activate_slack(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->activate_slack);
@@ -302,7 +302,7 @@ static ssize_t set_activate_slack(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
@@ -325,7 +325,7 @@ static ssize_t show_activation_width(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->activation_width *
@@ -337,7 +337,7 @@ static ssize_t set_activation_width(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
@@ -361,7 +361,7 @@ static ssize_t show_activation_height(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", nd->activation_height *
@@ -373,7 +373,7 @@ static ssize_t set_activation_height(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
@@ -397,7 +397,7 @@ static ssize_t show_deactivate_slack(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
return sprintf(buf, "%d\n", -nd->deactivate_slack);
@@ -407,7 +407,7 @@ static ssize_t set_deactivate_slack(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct ntrig_data *nd = hid_get_drvdata(hdev);
unsigned long val;
diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
index e994f9c29012..a802b4f49c7b 100644
--- a/drivers/hid/hid-picolcd_leds.c
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -66,7 +66,7 @@ static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
int i, state = 0;
dev = led_cdev->dev->parent;
- hdev = container_of(dev, struct hid_device, dev);
+ hdev = to_hid_device(dev);
data = hid_get_drvdata(hdev);
if (!data)
return;
@@ -93,7 +93,7 @@ static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_c
int i, value = 0;
dev = led_cdev->dev->parent;
- hdev = container_of(dev, struct hid_device, dev);
+ hdev = to_hid_device(dev);
data = hid_get_drvdata(hdev);
for (i = 0; i < 8; i++)
if (led_cdev == data->led[i]) {
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index 3a207c0ac0e3..f095bf8a3aa9 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(enable, "Enable for the PC-MIDI virtual audio driver");
static ssize_t show_channel(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel);
@@ -116,7 +116,7 @@ static ssize_t show_channel(struct device *dev,
static ssize_t store_channel(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
unsigned channel = 0;
@@ -140,7 +140,7 @@ static struct device_attribute *sysfs_device_attr_channel = {
static ssize_t show_sustain(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain);
@@ -153,7 +153,7 @@ static ssize_t show_sustain(struct device *dev,
static ssize_t store_sustain(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
unsigned sustain = 0;
@@ -179,7 +179,7 @@ static struct device_attribute *sysfs_device_attr_sustain = {
static ssize_t show_octave(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave);
@@ -192,7 +192,7 @@ static ssize_t show_octave(struct device *dev,
static ssize_t store_octave(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct pk_device *pk = hid_get_drvdata(hdev);
int octave = 0;
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
index 1948208fe038..329c5d1270f9 100644
--- a/drivers/hid/hid-roccat-arvo.c
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -191,8 +191,7 @@ static ssize_t arvo_sysfs_write(struct file *fp,
struct kobject *kobj, void const *buf,
loff_t off, size_t count, size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -211,8 +210,7 @@ static ssize_t arvo_sysfs_read(struct file *fp,
struct kobject *kobj, void *buf, loff_t off,
size_t count, size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c
index 02e28e9f4ea7..8155ac5fede2 100644
--- a/drivers/hid/hid-roccat-common.c
+++ b/drivers/hid/hid-roccat-common.c
@@ -134,8 +134,7 @@ ssize_t roccat_common2_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -158,8 +157,7 @@ ssize_t roccat_common2_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct roccat_common2_device *roccat_dev = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c
index bc62ed91e451..02db537f8f3e 100644
--- a/drivers/hid/hid-roccat-isku.c
+++ b/drivers/hid/hid-roccat-isku.c
@@ -121,8 +121,7 @@ static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -144,8 +143,7 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index c29265055ac1..bf4675a27396 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -269,8 +269,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count) {
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
if (off >= sizeof(struct kone_settings))
@@ -294,8 +293,7 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
loff_t off, size_t count) {
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval = 0, difference, old_profile;
@@ -332,8 +330,7 @@ static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
static ssize_t kone_sysfs_read_profilex(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count) {
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
if (off >= sizeof(struct kone_profile))
@@ -353,8 +350,7 @@ static ssize_t kone_sysfs_read_profilex(struct file *fp,
static ssize_t kone_sysfs_write_profilex(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count) {
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
struct kone_profile *profile;
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 5e99fcdc71b9..09e8fc72aa1d 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -87,8 +87,7 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -113,8 +112,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -193,8 +191,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
@@ -212,8 +209,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 966047711fbf..43617fb28b87 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -128,8 +128,7 @@ static ssize_t kovaplus_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -154,8 +153,7 @@ static ssize_t kovaplus_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -221,8 +219,7 @@ static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
@@ -240,8 +237,7 @@ static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
diff --git a/drivers/hid/hid-roccat-lua.c b/drivers/hid/hid-roccat-lua.c
index 65e2e76bf2fe..ac1a7313e259 100644
--- a/drivers/hid/hid-roccat-lua.c
+++ b/drivers/hid/hid-roccat-lua.c
@@ -30,7 +30,7 @@ static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -52,7 +52,7 @@ static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 47d7e74231e5..b30aa7b82bf8 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -90,8 +90,7 @@ static ssize_t pyra_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -116,8 +115,7 @@ static ssize_t pyra_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
@@ -191,8 +189,7 @@ static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
@@ -210,8 +207,7 @@ static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
ssize_t retval;
@@ -248,8 +244,7 @@ static ssize_t pyra_sysfs_write_settings(struct file *fp,
struct kobject *kobj, struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
- struct device *dev =
- container_of(kobj, struct device, kobj)->parent->parent;
+ struct device *dev = kobj_to_dev(kobj)->parent->parent;
struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval = 0;
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 92870cdb52d9..58ed8f25ab21 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -794,6 +794,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA2),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
+ USB_DEVICE_ID_ITE_LENOVO_YOGA900),
+ .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
HID_ANY_ID) },
{ }
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 774cd2210566..9b8db0e0ef1c 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1028,6 +1028,7 @@ struct sony_sc {
struct led_classdev *leds[MAX_LEDS];
unsigned long quirks;
struct work_struct state_worker;
+ void(*send_output_report)(struct sony_sc*);
struct power_supply *battery;
struct power_supply_desc battery_desc;
int device_id;
@@ -1044,6 +1045,7 @@ struct sony_sc {
__u8 battery_charging;
__u8 battery_capacity;
__u8 led_state[MAX_LEDS];
+ __u8 resume_led_state[MAX_LEDS];
__u8 led_delay_on[MAX_LEDS];
__u8 led_delay_off[MAX_LEDS];
__u8 led_count;
@@ -1137,11 +1139,11 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
* the gyroscope values to corresponding axes so we need a
* modified one.
*/
- if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && *rsize == 467) {
+ if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
hid_info(hdev, "Using modified Dualshock 4 report descriptor with gyroscope axes\n");
rdesc = dualshock4_usb_rdesc;
*rsize = sizeof(dualshock4_usb_rdesc);
- } else if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && *rsize == 357) {
+ } else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
hid_info(hdev, "Using modified Dualshock 4 Bluetooth report descriptor\n");
rdesc = dualshock4_bt_rdesc;
*rsize = sizeof(dualshock4_bt_rdesc);
@@ -1549,7 +1551,7 @@ static void sony_led_set_brightness(struct led_classdev *led,
enum led_brightness value)
{
struct device *dev = led->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct sony_sc *drv_data;
int n;
@@ -1591,7 +1593,7 @@ static void sony_led_set_brightness(struct led_classdev *led,
static enum led_brightness sony_led_get_brightness(struct led_classdev *led)
{
struct device *dev = led->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct sony_sc *drv_data;
int n;
@@ -1614,7 +1616,7 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
unsigned long *delay_off)
{
struct device *dev = led->dev->parent;
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct sony_sc *drv_data = hid_get_drvdata(hdev);
int n;
__u8 new_on, new_off;
@@ -1789,7 +1791,7 @@ error_leds:
return ret;
}
-static void sixaxis_state_worker(struct work_struct *work)
+static void sixaxis_send_output_report(struct sony_sc *sc)
{
static const union sixaxis_output_report_01 default_report = {
.buf = {
@@ -1803,7 +1805,6 @@ static void sixaxis_state_worker(struct work_struct *work)
0x00, 0x00, 0x00, 0x00, 0x00
}
};
- struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct sixaxis_output_report *report =
(struct sixaxis_output_report *)sc->output_report_dmabuf;
int n;
@@ -1846,9 +1847,8 @@ static void sixaxis_state_worker(struct work_struct *work)
HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
}
-static void dualshock4_state_worker(struct work_struct *work)
+static void dualshock4_send_output_report(struct sony_sc *sc)
{
- struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct hid_device *hdev = sc->hdev;
__u8 *buf = sc->output_report_dmabuf;
int offset;
@@ -1893,9 +1893,8 @@ static void dualshock4_state_worker(struct work_struct *work)
HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
}
-static void motion_state_worker(struct work_struct *work)
+static void motion_send_output_report(struct sony_sc *sc)
{
- struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct hid_device *hdev = sc->hdev;
struct motion_output_report_02 *report =
(struct motion_output_report_02 *)sc->output_report_dmabuf;
@@ -1914,6 +1913,18 @@ static void motion_state_worker(struct work_struct *work)
hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE);
}
+static inline void sony_send_output_report(struct sony_sc *sc)
+{
+ if (sc->send_output_report)
+ sc->send_output_report(sc);
+}
+
+static void sony_state_worker(struct work_struct *work)
+{
+ struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
+ sc->send_output_report(sc);
+}
+
static int sony_allocate_output_report(struct sony_sc *sc)
{
if ((sc->quirks & SIXAXIS_CONTROLLER) ||
@@ -2241,11 +2252,13 @@ static void sony_release_device_id(struct sony_sc *sc)
}
}
-static inline void sony_init_work(struct sony_sc *sc,
- void (*worker)(struct work_struct *))
+static inline void sony_init_output_report(struct sony_sc *sc,
+ void(*send_output_report)(struct sony_sc*))
{
+ sc->send_output_report = send_output_report;
+
if (!sc->worker_initialized)
- INIT_WORK(&sc->state_worker, worker);
+ INIT_WORK(&sc->state_worker, sony_state_worker);
sc->worker_initialized = 1;
}
@@ -2319,7 +2332,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
ret = sixaxis_set_operational_usb(hdev);
- sony_init_work(sc, sixaxis_state_worker);
+ sony_init_output_report(sc, sixaxis_send_output_report);
} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
/*
@@ -2328,7 +2341,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
ret = sixaxis_set_operational_bt(hdev);
- sony_init_work(sc, sixaxis_state_worker);
+ sony_init_output_report(sc, sixaxis_send_output_report);
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
/*
@@ -2343,9 +2356,9 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}
- sony_init_work(sc, dualshock4_state_worker);
+ sony_init_output_report(sc, dualshock4_send_output_report);
} else if (sc->quirks & MOTION_CONTROLLER) {
- sony_init_work(sc, motion_state_worker);
+ sony_init_output_report(sc, motion_send_output_report);
} else {
ret = 0;
}
@@ -2421,6 +2434,56 @@ static void sony_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
}
+#ifdef CONFIG_PM
+
+static int sony_suspend(struct hid_device *hdev, pm_message_t message)
+{
+ /*
+ * On suspend save the current LED state,
+ * stop running force-feedback and blank the LEDS.
+ */
+ if (SONY_LED_SUPPORT || SONY_FF_SUPPORT) {
+ struct sony_sc *sc = hid_get_drvdata(hdev);
+
+#ifdef CONFIG_SONY_FF
+ sc->left = sc->right = 0;
+#endif
+
+ memcpy(sc->resume_led_state, sc->led_state,
+ sizeof(sc->resume_led_state));
+ memset(sc->led_state, 0, sizeof(sc->led_state));
+
+ sony_send_output_report(sc);
+ }
+
+ return 0;
+}
+
+static int sony_resume(struct hid_device *hdev)
+{
+ /* Restore the state of controller LEDs on resume */
+ if (SONY_LED_SUPPORT) {
+ struct sony_sc *sc = hid_get_drvdata(hdev);
+
+ memcpy(sc->led_state, sc->resume_led_state,
+ sizeof(sc->led_state));
+
+ /*
+ * The Sixaxis and navigation controllers on USB need to be
+ * reinitialized on resume or they won't behave properly.
+ */
+ if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
+ (sc->quirks & NAVIGATION_CONTROLLER_USB))
+ sixaxis_set_operational_usb(sc->hdev);
+
+ sony_set_leds(sc);
+ }
+
+ return 0;
+}
+
+#endif
+
static const struct hid_device_id sony_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER),
.driver_data = SIXAXIS_CONTROLLER_USB },
@@ -2470,7 +2533,13 @@ static struct hid_driver sony_driver = {
.probe = sony_probe,
.remove = sony_remove,
.report_fixup = sony_report_fixup,
- .raw_event = sony_raw_event
+ .raw_event = sony_raw_event,
+
+#ifdef CONFIG_PM
+ .suspend = sony_suspend,
+ .resume = sony_resume,
+ .reset_resume = sony_resume,
+#endif
};
static int __init sony_init(void)
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 3edd4ac36494..ec18768b124a 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -141,7 +141,7 @@ static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cd
enum led_brightness value)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid);
if (!drv_data) {
@@ -160,7 +160,7 @@ static void steelseries_srws1_led_all_set_brightness(struct led_classdev *led_cd
static enum led_brightness steelseries_srws1_led_all_get_brightness(struct led_classdev *led_cdev)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct steelseries_srws1_data *drv_data;
drv_data = hid_get_drvdata(hid);
@@ -177,7 +177,7 @@ static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct steelseries_srws1_data *drv_data = hid_get_drvdata(hid);
int i, state = 0;
@@ -205,7 +205,7 @@ static void steelseries_srws1_led_set_brightness(struct led_classdev *led_cdev,
static enum led_brightness steelseries_srws1_led_get_brightness(struct led_classdev *led_cdev)
{
struct device *dev = led_cdev->dev->parent;
- struct hid_device *hid = container_of(dev, struct hid_device, dev);
+ struct hid_device *hid = to_hid_device(dev);
struct steelseries_srws1_data *drv_data;
int i, value = 0;
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 05e23c417d50..4390eee2ce84 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -296,14 +296,12 @@ static const struct wiimod_ops wiimod_battery = {
static enum led_brightness wiimod_led_get(struct led_classdev *led_dev)
{
- struct wiimote_data *wdata;
struct device *dev = led_dev->dev->parent;
+ struct wiimote_data *wdata = dev_to_wii(dev);
int i;
unsigned long flags;
bool value = false;
- wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
-
for (i = 0; i < 4; ++i) {
if (wdata->leds[i] == led_dev) {
spin_lock_irqsave(&wdata->state.lock, flags);
@@ -319,14 +317,12 @@ static enum led_brightness wiimod_led_get(struct led_classdev *led_dev)
static void wiimod_led_set(struct led_classdev *led_dev,
enum led_brightness value)
{
- struct wiimote_data *wdata;
struct device *dev = led_dev->dev->parent;
+ struct wiimote_data *wdata = dev_to_wii(dev);
int i;
unsigned long flags;
__u8 state, flag;
- wdata = hid_get_drvdata(container_of(dev, struct hid_device, dev));
-
for (i = 0; i < 4; ++i) {
if (wdata->leds[i] == led_dev) {
flag = WIIPROTO_FLAG_LED(i + 1);
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 875694d43e4d..510ca77fe14e 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -256,8 +256,7 @@ enum wiiproto_reqs {
WIIPROTO_REQ_MAX
};
-#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \
- dev))
+#define dev_to_wii(pdev) hid_get_drvdata(to_hid_device(pdev))
void __wiimote_schedule(struct wiimote_data *wdata);
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 10bd8e6e4c9c..b9216938a718 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -151,6 +151,7 @@ struct i2c_hid {
struct i2c_hid_platform_data pdata;
bool irq_wake_enabled;
+ struct mutex reset_lock;
};
static int __i2c_hid_command(struct i2c_client *client,
@@ -356,9 +357,16 @@ static int i2c_hid_hwreset(struct i2c_client *client)
i2c_hid_dbg(ihid, "%s\n", __func__);
+ /*
+ * This prevents sending feature reports while the device is
+ * being reset. Otherwise we may lose the reset complete
+ * interrupt.
+ */
+ mutex_lock(&ihid->reset_lock);
+
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
if (ret)
- return ret;
+ goto out_unlock;
i2c_hid_dbg(ihid, "resetting...\n");
@@ -366,10 +374,11 @@ static int i2c_hid_hwreset(struct i2c_client *client)
if (ret) {
dev_err(&client->dev, "failed to reset device.\n");
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
- return ret;
}
- return 0;
+out_unlock:
+ mutex_unlock(&ihid->reset_lock);
+ return ret;
}
static void i2c_hid_get_input(struct i2c_hid *ihid)
@@ -587,12 +596,15 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
size_t count, unsigned char report_type, bool use_data)
{
struct i2c_client *client = hid->driver_data;
+ struct i2c_hid *ihid = i2c_get_clientdata(client);
int report_id = buf[0];
int ret;
if (report_type == HID_INPUT_REPORT)
return -EINVAL;
+ mutex_lock(&ihid->reset_lock);
+
if (report_id) {
buf++;
count--;
@@ -605,6 +617,8 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
if (report_id && ret >= 0)
ret++; /* add report_id to the number of transfered bytes */
+ mutex_unlock(&ihid->reset_lock);
+
return ret;
}
@@ -990,6 +1004,7 @@ static int i2c_hid_probe(struct i2c_client *client,
ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
init_waitqueue_head(&ihid->wait);
+ mutex_init(&ihid->reset_lock);
/* we need to allocate the command buffer without knowing the maximum
* size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the
@@ -1184,7 +1199,6 @@ MODULE_DEVICE_TABLE(i2c, i2c_hid_id_table);
static struct i2c_driver i2c_hid_driver = {
.driver = {
.name = "i2c_hid",
- .owner = THIS_MODULE,
.pm = &i2c_hid_pm,
.acpi_match_table = ACPI_PTR(i2c_hid_acpi_match),
.of_match_table = of_match_ptr(i2c_hid_of_match),
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 36712e9f56c2..ad71160b9ea4 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -274,10 +274,10 @@ static void hid_irq_in(struct urb *urb)
switch (urb->status) {
case 0: /* success */
- usbhid_mark_busy(usbhid);
usbhid->retry_delay = 0;
if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
break;
+ usbhid_mark_busy(usbhid);
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
hid_input_report(urb->context, HID_INPUT_REPORT,
urb->transfer_buffer,
@@ -477,8 +477,6 @@ static void hid_ctrl(struct urb *urb)
struct usbhid_device *usbhid = hid->driver_data;
int unplug = 0, status = urb->status;
- spin_lock(&usbhid->lock);
-
switch (status) {
case 0: /* success */
if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
@@ -498,6 +496,8 @@ static void hid_ctrl(struct urb *urb)
hid_warn(urb->dev, "ctrl urb status %d received\n", status);
}
+ spin_lock(&usbhid->lock);
+
if (unplug) {
usbhid->ctrltail = usbhid->ctrlhead;
} else {
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 807922b49aa4..fa47d666cfcf 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -96,7 +96,7 @@ struct usbhid_device {
};
#define hid_to_usb_dev(hid_dev) \
- container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
+ to_usb_device(hid_dev->dev.parent->parent)
#endif
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index e06af5b9f59e..5cb21dd91094 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -686,7 +686,7 @@ out:
static ssize_t wacom_led_select_store(struct device *dev, int set_id,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
unsigned int id;
int err;
@@ -714,7 +714,7 @@ static ssize_t wacom_led##SET_ID##_select_store(struct device *dev, \
static ssize_t wacom_led##SET_ID##_select_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+ struct hid_device *hdev = to_hid_device(dev);\
struct wacom *wacom = hid_get_drvdata(hdev); \
return scnprintf(buf, PAGE_SIZE, "%d\n", \
wacom->led.select[SET_ID]); \
@@ -750,7 +750,7 @@ static ssize_t wacom_luminance_store(struct wacom *wacom, u8 *dest,
static ssize_t wacom_##name##_luminance_store(struct device *dev, \
struct device_attribute *attr, const char *buf, size_t count) \
{ \
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);\
+ struct hid_device *hdev = to_hid_device(dev);\
struct wacom *wacom = hid_get_drvdata(hdev); \
\
return wacom_luminance_store(wacom, &wacom->led.field, \
@@ -773,7 +773,7 @@ DEVICE_LUMINANCE_ATTR(buttons, img_lum);
static ssize_t wacom_button_image_store(struct device *dev, int button_id,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
int err;
unsigned len;
@@ -1097,7 +1097,7 @@ static ssize_t wacom_show_speed(struct device *dev,
struct device_attribute
*attr, char *buf)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
return snprintf(buf, PAGE_SIZE, "%i\n", wacom->wacom_wac.bt_high_speed);
@@ -1107,7 +1107,7 @@ static ssize_t wacom_store_speed(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
u8 new_speed;
@@ -1130,8 +1130,8 @@ static ssize_t wacom_show_remote_mode(struct kobject *kobj,
struct kobj_attribute *kattr,
char *buf, int index)
{
- struct device *dev = container_of(kobj->parent, struct device, kobj);
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct device *dev = kobj_to_dev(kobj->parent);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
u8 mode;
@@ -1241,8 +1241,8 @@ static ssize_t wacom_store_unpair_remote(struct kobject *kobj,
const char *buf, size_t count)
{
unsigned char selector = 0;
- struct device *dev = container_of(kobj->parent, struct device, kobj);
- struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+ struct device *dev = kobj_to_dev(kobj->parent);
+ struct hid_device *hdev = to_hid_device(dev);
struct wacom *wacom = hid_get_drvdata(hdev);
int err;
@@ -1353,8 +1353,7 @@ static void wacom_clean_inputs(struct wacom *wacom)
else
input_free_device(wacom->wacom_wac.pad_input);
}
- if (wacom->remote_dir)
- kobject_put(wacom->remote_dir);
+ kobject_put(wacom->remote_dir);
wacom->wacom_wac.pen_input = NULL;
wacom->wacom_wac.touch_input = NULL;
wacom->wacom_wac.pad_input = NULL;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 01a4f05c1642..99ef77fcfb80 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -34,6 +34,9 @@
*/
#define WACOM_CONTACT_AREA_SCALE 2607
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+ int button_count, int mask);
+
/*
* Percent of battery capacity for Graphire.
* 8th value means AC online and show 100% capacity.
@@ -436,16 +439,142 @@ exit:
static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
{
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+ struct wacom_features *features = &wacom_wac->features;
struct hid_report *r;
struct hid_report_enum *re;
re = &(wacom->hdev->report_enum[HID_FEATURE_REPORT]);
- r = re->report_id_hash[WACOM_REPORT_INTUOSREAD];
+ if (features->type == INTUOSHT2)
+ r = re->report_id_hash[WACOM_REPORT_INTUOSHT2_ID];
+ else
+ r = re->report_id_hash[WACOM_REPORT_INTUOS_ID1];
if (r) {
hid_hw_request(wacom->hdev, r, HID_REQ_GET_REPORT);
}
}
+static int wacom_intuos_pad(struct wacom_wac *wacom)
+{
+ struct wacom_features *features = &wacom->features;
+ unsigned char *data = wacom->data;
+ struct input_dev *input = wacom->pad_input;
+ int i;
+ int buttons = 0, nbuttons = features->numbered_buttons;
+ int keys = 0, nkeys = 0;
+ int ring1 = 0, ring2 = 0;
+ int strip1 = 0, strip2 = 0;
+ bool prox = false;
+
+ /* pad packets. Works as a second tool and is always in prox */
+ if (!(data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
+ data[0] == WACOM_REPORT_CINTIQPAD))
+ return 0;
+
+ if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
+ buttons = (data[3] << 1) | (data[2] & 0x01);
+ ring1 = data[1];
+ } else if (features->type == DTK) {
+ buttons = data[6];
+ } else if (features->type == WACOM_13HD) {
+ buttons = (data[4] << 1) | (data[3] & 0x01);
+ } else if (features->type == WACOM_24HD) {
+ buttons = (data[8] << 8) | data[6];
+ ring1 = data[1];
+ ring2 = data[2];
+
+ /*
+ * Three "buttons" are available on the 24HD which are
+ * physically implemented as a touchstrip. Each button
+ * is approximately 3 bits wide with a 2 bit spacing.
+ * The raw touchstrip bits are stored at:
+ * ((data[3] & 0x1f) << 8) | data[4])
+ */
+ nkeys = 3;
+ keys = ((data[3] & 0x1C) ? 1<<2 : 0) |
+ ((data[4] & 0xE0) ? 1<<1 : 0) |
+ ((data[4] & 0x07) ? 1<<0 : 0);
+ } else if (features->type == WACOM_27QHD) {
+ nkeys = 3;
+ keys = data[2] & 0x07;
+
+ input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
+ input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
+ input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
+ } else if (features->type == CINTIQ_HYBRID) {
+ /*
+ * Do not send hardware buttons under Android. They
+ * are already sent to the system through GPIO (and
+ * have different meaning).
+ *
+ * d-pad right -> data[4] & 0x10
+ * d-pad up -> data[4] & 0x20
+ * d-pad left -> data[4] & 0x40
+ * d-pad down -> data[4] & 0x80
+ * d-pad center -> data[3] & 0x01
+ */
+ buttons = (data[4] << 1) | (data[3] & 0x01);
+ } else if (features->type == CINTIQ_COMPANION_2) {
+ /* d-pad right -> data[4] & 0x10
+ * d-pad up -> data[4] & 0x20
+ * d-pad left -> data[4] & 0x40
+ * d-pad down -> data[4] & 0x80
+ * d-pad center -> data[3] & 0x01
+ */
+ buttons = ((data[2] >> 4) << 7) |
+ ((data[1] & 0x04) << 6) |
+ ((data[2] & 0x0F) << 2) |
+ (data[1] & 0x03);
+ } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
+ /*
+ * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
+ * addition to the mechanical switch. Switch data is
+ * stored in data[4], capacitive data in data[5].
+ *
+ * Touch ring mode switch (data[3]) has no capacitive sensor
+ */
+ buttons = (data[4] << 1) | (data[3] & 0x01);
+ ring1 = data[2];
+ } else {
+ if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
+ buttons = (data[8] << 10) | ((data[7] & 0x01) << 9) |
+ (data[6] << 1) | (data[5] & 0x01);
+
+ if (features->type == WACOM_22HD) {
+ nkeys = 3;
+ keys = data[9] & 0x07;
+ }
+ } else {
+ buttons = ((data[6] & 0x10) << 10) |
+ ((data[5] & 0x10) << 9) |
+ ((data[6] & 0x0F) << 4) |
+ (data[5] & 0x0F);
+ }
+ strip1 = ((data[1] & 0x1f) << 8) | data[2];
+ strip2 = ((data[3] & 0x1f) << 8) | data[4];
+ }
+
+ prox = (buttons & ~(~0 << nbuttons)) | (keys & ~(~0 << nkeys)) |
+ (ring1 & 0x80) | (ring2 & 0x80) | strip1 | strip2;
+
+ wacom_report_numbered_buttons(input, nbuttons, buttons);
+
+ for (i = 0; i < nkeys; i++)
+ input_report_key(input, KEY_PROG1 + i, keys & (1 << i));
+
+ input_report_abs(input, ABS_RX, strip1);
+ input_report_abs(input, ABS_RY, strip2);
+
+ input_report_abs(input, ABS_WHEEL, (ring1 & 0x80) ? (ring1 & 0x7f) : 0);
+ input_report_abs(input, ABS_THROTTLE, (ring2 & 0x80) ? (ring2 & 0x7f) : 0);
+
+ input_report_key(input, wacom->tool[1], prox ? 1 : 0);
+ input_report_abs(input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
+
+ input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
+
+ return 1;
+}
+
static int wacom_intuos_inout(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
@@ -755,19 +884,40 @@ static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
return 0;
}
-static void wacom_intuos_general(struct wacom_wac *wacom)
+static int wacom_intuos_general(struct wacom_wac *wacom)
{
struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->pen_input;
- unsigned int t;
+ int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0;
+ unsigned char type = (data[1] >> 1) & 0x0F;
+ unsigned int x, y, distance, t;
- /* general pen packet */
- if ((data[1] & 0xb8) == 0xa0) {
- t = (data[6] << 2) | ((data[7] >> 6) & 3);
- if (features->pressure_max == 2047) {
- t = (t << 1) | (data[1] & 1);
- }
+ if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_CINTIQ &&
+ data[0] != WACOM_REPORT_INTUOS_PEN)
+ return 0;
+
+ x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1);
+ y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1);
+ distance = data[9] >> 2;
+ if (features->type < INTUOS3S) {
+ x >>= 1;
+ y >>= 1;
+ distance >>= 1;
+ }
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+ input_report_abs(input, ABS_DISTANCE, distance);
+
+ switch (type) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ /* general pen packet */
+ t = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | (data[1] & 1);
+ if (features->pressure_max < 2047)
+ t >>= 1;
input_report_abs(input, ABS_PRESSURE, t);
if (features->type != INTUOSHT2) {
input_report_abs(input, ABS_TILT_X,
@@ -777,29 +927,112 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
input_report_key(input, BTN_STYLUS, data[1] & 2);
input_report_key(input, BTN_STYLUS2, data[1] & 4);
input_report_key(input, BTN_TOUCH, t > 10);
- }
+ break;
- /* airbrush second packet */
- if ((data[1] & 0xbc) == 0xb4) {
+ case 0x0a:
+ /* airbrush second packet */
input_report_abs(input, ABS_WHEEL,
(data[6] << 2) | ((data[7] >> 6) & 3));
input_report_abs(input, ABS_TILT_X,
(((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+ break;
+
+ case 0x05:
+ /* Rotation packet */
+ if (features->type >= INTUOS3S) {
+ /* I3 marker pen rotation */
+ t = (data[6] << 3) | ((data[7] >> 5) & 7);
+ t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+ ((t-1) / 2 + 450)) : (450 - t / 2) ;
+ input_report_abs(input, ABS_Z, t);
+ } else {
+ /* 4D mouse 2nd packet */
+ t = (data[6] << 3) | ((data[7] >> 5) & 7);
+ input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
+ ((t - 1) / 2) : -t / 2);
+ }
+ break;
+
+ case 0x04:
+ /* 4D mouse 1st packet */
+ input_report_key(input, BTN_LEFT, data[8] & 0x01);
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
+ input_report_key(input, BTN_RIGHT, data[8] & 0x04);
+
+ input_report_key(input, BTN_SIDE, data[8] & 0x20);
+ input_report_key(input, BTN_EXTRA, data[8] & 0x10);
+ t = (data[6] << 2) | ((data[7] >> 6) & 3);
+ input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
+ break;
+
+ case 0x06:
+ /* I4 mouse */
+ input_report_key(input, BTN_LEFT, data[6] & 0x01);
+ input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
+ input_report_key(input, BTN_RIGHT, data[6] & 0x04);
+ input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
+ - ((data[7] & 0x40) >> 6));
+ input_report_key(input, BTN_SIDE, data[6] & 0x08);
+ input_report_key(input, BTN_EXTRA, data[6] & 0x10);
+
+ input_report_abs(input, ABS_TILT_X,
+ (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
+ input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+ break;
+
+ case 0x08:
+ if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
+ /* 2D mouse packet */
+ input_report_key(input, BTN_LEFT, data[8] & 0x04);
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
+ input_report_key(input, BTN_RIGHT, data[8] & 0x10);
+ input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
+ - ((data[8] & 0x02) >> 1));
+
+ /* I3 2D mouse side buttons */
+ if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
+ input_report_key(input, BTN_SIDE, data[8] & 0x40);
+ input_report_key(input, BTN_EXTRA, data[8] & 0x20);
+ }
+ }
+ else if (wacom->tool[idx] == BTN_TOOL_LENS) {
+ /* Lens cursor packets */
+ input_report_key(input, BTN_LEFT, data[8] & 0x01);
+ input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
+ input_report_key(input, BTN_RIGHT, data[8] & 0x04);
+ input_report_key(input, BTN_SIDE, data[8] & 0x10);
+ input_report_key(input, BTN_EXTRA, data[8] & 0x08);
+ }
+ break;
+
+ case 0x07:
+ case 0x09:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ /* unhandled */
+ break;
}
+
+ input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+ input_report_key(input, wacom->tool[idx], 1);
+ input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ wacom->reporting_data = true;
+ return 2;
}
static int wacom_intuos_irq(struct wacom_wac *wacom)
{
- struct wacom_features *features = &wacom->features;
unsigned char *data = wacom->data;
struct input_dev *input = wacom->pen_input;
- unsigned int t;
- int idx = 0, result;
+ int result;
if (data[0] != WACOM_REPORT_PENABLED &&
- data[0] != WACOM_REPORT_INTUOSREAD &&
- data[0] != WACOM_REPORT_INTUOSWRITE &&
+ data[0] != WACOM_REPORT_INTUOS_ID1 &&
+ data[0] != WACOM_REPORT_INTUOS_ID2 &&
data[0] != WACOM_REPORT_INTUOSPAD &&
data[0] != WACOM_REPORT_INTUOS_PEN &&
data[0] != WACOM_REPORT_CINTIQ &&
@@ -810,339 +1043,22 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
return 0;
}
- /* tool number */
- if (features->type == INTUOS)
- idx = data[1] & 0x01;
-
- /* pad packets. Works as a second tool and is always in prox */
- if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD ||
- data[0] == WACOM_REPORT_CINTIQPAD) {
- input = wacom->pad_input;
- if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
- input_report_key(input, BTN_0, (data[2] & 0x01));
- input_report_key(input, BTN_1, (data[3] & 0x01));
- input_report_key(input, BTN_2, (data[3] & 0x02));
- input_report_key(input, BTN_3, (data[3] & 0x04));
- input_report_key(input, BTN_4, (data[3] & 0x08));
- input_report_key(input, BTN_5, (data[3] & 0x10));
- input_report_key(input, BTN_6, (data[3] & 0x20));
- if (data[1] & 0x80) {
- input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
- } else {
- /* Out of proximity, clear wheel value. */
- input_report_abs(input, ABS_WHEEL, 0);
- }
- if (features->type != INTUOS4S) {
- input_report_key(input, BTN_7, (data[3] & 0x40));
- input_report_key(input, BTN_8, (data[3] & 0x80));
- }
- if (data[1] | (data[2] & 0x01) | data[3]) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else if (features->type == DTK) {
- input_report_key(input, BTN_0, (data[6] & 0x01));
- input_report_key(input, BTN_1, (data[6] & 0x02));
- input_report_key(input, BTN_2, (data[6] & 0x04));
- input_report_key(input, BTN_3, (data[6] & 0x08));
- input_report_key(input, BTN_4, (data[6] & 0x10));
- input_report_key(input, BTN_5, (data[6] & 0x20));
- if (data[6] & 0x3f) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else if (features->type == WACOM_13HD) {
- input_report_key(input, BTN_0, (data[3] & 0x01));
- input_report_key(input, BTN_1, (data[4] & 0x01));
- input_report_key(input, BTN_2, (data[4] & 0x02));
- input_report_key(input, BTN_3, (data[4] & 0x04));
- input_report_key(input, BTN_4, (data[4] & 0x08));
- input_report_key(input, BTN_5, (data[4] & 0x10));
- input_report_key(input, BTN_6, (data[4] & 0x20));
- input_report_key(input, BTN_7, (data[4] & 0x40));
- input_report_key(input, BTN_8, (data[4] & 0x80));
- if ((data[3] & 0x01) | data[4]) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else if (features->type == WACOM_24HD) {
- input_report_key(input, BTN_0, (data[6] & 0x01));
- input_report_key(input, BTN_1, (data[6] & 0x02));
- input_report_key(input, BTN_2, (data[6] & 0x04));
- input_report_key(input, BTN_3, (data[6] & 0x08));
- input_report_key(input, BTN_4, (data[6] & 0x10));
- input_report_key(input, BTN_5, (data[6] & 0x20));
- input_report_key(input, BTN_6, (data[6] & 0x40));
- input_report_key(input, BTN_7, (data[6] & 0x80));
- input_report_key(input, BTN_8, (data[8] & 0x01));
- input_report_key(input, BTN_9, (data[8] & 0x02));
- input_report_key(input, BTN_A, (data[8] & 0x04));
- input_report_key(input, BTN_B, (data[8] & 0x08));
- input_report_key(input, BTN_C, (data[8] & 0x10));
- input_report_key(input, BTN_X, (data[8] & 0x20));
- input_report_key(input, BTN_Y, (data[8] & 0x40));
- input_report_key(input, BTN_Z, (data[8] & 0x80));
-
- /*
- * Three "buttons" are available on the 24HD which are
- * physically implemented as a touchstrip. Each button
- * is approximately 3 bits wide with a 2 bit spacing.
- * The raw touchstrip bits are stored at:
- * ((data[3] & 0x1f) << 8) | data[4])
- */
- input_report_key(input, KEY_PROG1, data[4] & 0x07);
- input_report_key(input, KEY_PROG2, data[4] & 0xE0);
- input_report_key(input, KEY_PROG3, data[3] & 0x1C);
-
- if (data[1] & 0x80) {
- input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
- } else {
- /* Out of proximity, clear wheel value. */
- input_report_abs(input, ABS_WHEEL, 0);
- }
-
- if (data[2] & 0x80) {
- input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
- } else {
- /* Out of proximity, clear second wheel value. */
- input_report_abs(input, ABS_THROTTLE, 0);
- }
-
- if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else if (features->type == WACOM_27QHD) {
- input_report_key(input, KEY_PROG1, data[2] & 0x01);
- input_report_key(input, KEY_PROG2, data[2] & 0x02);
- input_report_key(input, KEY_PROG3, data[2] & 0x04);
-
- input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[4]));
- input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[6]));
- input_report_abs(input, ABS_Z, be16_to_cpup((__be16 *)&data[8]));
- if ((data[2] & 0x07) | data[4] | data[5] | data[6] | data[7] | data[8] | data[9]) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else if (features->type == CINTIQ_HYBRID) {
- /*
- * Do not send hardware buttons under Android. They
- * are already sent to the system through GPIO (and
- * have different meaning).
- */
- input_report_key(input, BTN_1, (data[4] & 0x01));
- input_report_key(input, BTN_2, (data[4] & 0x02));
- input_report_key(input, BTN_3, (data[4] & 0x04));
- input_report_key(input, BTN_4, (data[4] & 0x08));
-
- input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */
- input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */
- input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */
- input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */
- input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */
-
- if (data[4] | (data[3] & 0x01)) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
-
- } else if (features->type == CINTIQ_COMPANION_2) {
- input_report_key(input, BTN_1, (data[1] & 0x02));
- input_report_key(input, BTN_2, (data[2] & 0x01));
- input_report_key(input, BTN_3, (data[2] & 0x02));
- input_report_key(input, BTN_4, (data[2] & 0x04));
- input_report_key(input, BTN_5, (data[2] & 0x08));
- input_report_key(input, BTN_6, (data[1] & 0x04));
-
- input_report_key(input, BTN_7, (data[2] & 0x10)); /* Right */
- input_report_key(input, BTN_8, (data[2] & 0x20)); /* Up */
- input_report_key(input, BTN_9, (data[2] & 0x40)); /* Left */
- input_report_key(input, BTN_A, (data[2] & 0x80)); /* Down */
- input_report_key(input, BTN_0, (data[1] & 0x01)); /* Center */
-
- if (data[2] | (data[1] & 0x07)) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
-
- } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
- int i;
-
- /* Touch ring mode switch has no capacitive sensor */
- input_report_key(input, BTN_0, (data[3] & 0x01));
-
- /*
- * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
- * addition to the mechanical switch. Switch data is
- * stored in data[4], capacitive data in data[5].
- */
- for (i = 0; i < 8; i++)
- input_report_key(input, BTN_1 + i, data[4] & (1 << i));
-
- if (data[2] & 0x80) {
- input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f));
- } else {
- /* Out of proximity, clear wheel value. */
- input_report_abs(input, ABS_WHEEL, 0);
- }
-
- if (data[2] | (data[3] & 0x01) | data[4] | data[5]) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- } else {
- if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
- input_report_key(input, BTN_0, (data[5] & 0x01));
- input_report_key(input, BTN_1, (data[6] & 0x01));
- input_report_key(input, BTN_2, (data[6] & 0x02));
- input_report_key(input, BTN_3, (data[6] & 0x04));
- input_report_key(input, BTN_4, (data[6] & 0x08));
- input_report_key(input, BTN_5, (data[6] & 0x10));
- input_report_key(input, BTN_6, (data[6] & 0x20));
- input_report_key(input, BTN_7, (data[6] & 0x40));
- input_report_key(input, BTN_8, (data[6] & 0x80));
- input_report_key(input, BTN_9, (data[7] & 0x01));
- input_report_key(input, BTN_A, (data[8] & 0x01));
- input_report_key(input, BTN_B, (data[8] & 0x02));
- input_report_key(input, BTN_C, (data[8] & 0x04));
- input_report_key(input, BTN_X, (data[8] & 0x08));
- input_report_key(input, BTN_Y, (data[8] & 0x10));
- input_report_key(input, BTN_Z, (data[8] & 0x20));
- input_report_key(input, BTN_BASE, (data[8] & 0x40));
- input_report_key(input, BTN_BASE2, (data[8] & 0x80));
-
- if (features->type == WACOM_22HD) {
- input_report_key(input, KEY_PROG1, data[9] & 0x01);
- input_report_key(input, KEY_PROG2, data[9] & 0x02);
- input_report_key(input, KEY_PROG3, data[9] & 0x04);
- }
- } else {
- input_report_key(input, BTN_0, (data[5] & 0x01));
- input_report_key(input, BTN_1, (data[5] & 0x02));
- input_report_key(input, BTN_2, (data[5] & 0x04));
- input_report_key(input, BTN_3, (data[5] & 0x08));
- input_report_key(input, BTN_4, (data[6] & 0x01));
- input_report_key(input, BTN_5, (data[6] & 0x02));
- input_report_key(input, BTN_6, (data[6] & 0x04));
- input_report_key(input, BTN_7, (data[6] & 0x08));
- input_report_key(input, BTN_8, (data[5] & 0x10));
- input_report_key(input, BTN_9, (data[6] & 0x10));
- }
- input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
- input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
- if ((data[5] & 0x1f) | data[6] | (data[1] & 0x1f) |
- data[2] | (data[3] & 0x1f) | data[4] | data[8] |
- (data[7] & 0x01)) {
- input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
- } else {
- input_report_abs(input, ABS_MISC, 0);
- }
- }
- return 1;
- }
+ /* process pad events */
+ result = wacom_intuos_pad(wacom);
+ if (result)
+ return result;
/* process in/out prox events */
result = wacom_intuos_inout(wacom);
if (result)
- return result - 1;
-
- if (features->type >= INTUOS3S) {
- input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
- input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
- input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
- } else {
- input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2]));
- input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
- input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
- }
+ return result - 1;
/* process general packets */
- wacom_intuos_general(wacom);
-
- /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */
- if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) {
-
- if (data[1] & 0x02) {
- /* Rotation packet */
- if (features->type >= INTUOS3S) {
- /* I3 marker pen rotation */
- t = (data[6] << 3) | ((data[7] >> 5) & 7);
- t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
- ((t-1) / 2 + 450)) : (450 - t / 2) ;
- input_report_abs(input, ABS_Z, t);
- } else {
- /* 4D mouse rotation packet */
- t = (data[6] << 3) | ((data[7] >> 5) & 7);
- input_report_abs(input, ABS_RZ, (data[7] & 0x20) ?
- ((t - 1) / 2) : -t / 2);
- }
-
- } else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
- /* 4D mouse packet */
- input_report_key(input, BTN_LEFT, data[8] & 0x01);
- input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
- input_report_key(input, BTN_RIGHT, data[8] & 0x04);
-
- input_report_key(input, BTN_SIDE, data[8] & 0x20);
- input_report_key(input, BTN_EXTRA, data[8] & 0x10);
- t = (data[6] << 2) | ((data[7] >> 6) & 3);
- input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
-
- } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
- /* I4 mouse */
- if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
- input_report_key(input, BTN_LEFT, data[6] & 0x01);
- input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
- input_report_key(input, BTN_RIGHT, data[6] & 0x04);
- input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7)
- - ((data[7] & 0x40) >> 6));
- input_report_key(input, BTN_SIDE, data[6] & 0x08);
- input_report_key(input, BTN_EXTRA, data[6] & 0x10);
-
- input_report_abs(input, ABS_TILT_X,
- (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
- input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
- } else {
- /* 2D mouse packet */
- input_report_key(input, BTN_LEFT, data[8] & 0x04);
- input_report_key(input, BTN_MIDDLE, data[8] & 0x08);
- input_report_key(input, BTN_RIGHT, data[8] & 0x10);
- input_report_rel(input, REL_WHEEL, (data[8] & 0x01)
- - ((data[8] & 0x02) >> 1));
-
- /* I3 2D mouse side buttons */
- if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
- input_report_key(input, BTN_SIDE, data[8] & 0x40);
- input_report_key(input, BTN_EXTRA, data[8] & 0x20);
- }
- }
- } else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
- features->type == INTUOS4L || features->type == INTUOS5L ||
- features->type == INTUOSPL) &&
- wacom->tool[idx] == BTN_TOOL_LENS) {
- /* Lens cursor packets */
- input_report_key(input, BTN_LEFT, data[8] & 0x01);
- input_report_key(input, BTN_MIDDLE, data[8] & 0x02);
- input_report_key(input, BTN_RIGHT, data[8] & 0x04);
- input_report_key(input, BTN_SIDE, data[8] & 0x10);
- input_report_key(input, BTN_EXTRA, data[8] & 0x08);
- }
- }
+ result = wacom_intuos_general(wacom);
+ if (result)
+ return result - 1;
- input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
- input_report_key(input, wacom->tool[idx], 1);
- input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
- wacom->reporting_data = true;
- return 1;
+ return 0;
}
static int int_dist(int x1, int y1, int x2, int y2)
@@ -2509,7 +2425,7 @@ void wacom_setup_device_quirks(struct wacom *wacom)
features->quirks |= WACOM_QUIRK_BATTERY;
/* quirk for bamboo touch with 2 low res touches */
- if (features->type == BAMBOO_PT &&
+ if ((features->type == BAMBOO_PT || features->type == BAMBOO_TOUCH) &&
features->pktlen == WACOM_PKGLEN_BBTOUCH) {
features->x_max <<= 5;
features->y_max <<= 5;
@@ -2806,6 +2722,19 @@ static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
__set_bit(BTN_BASE + (i-16), input_dev->keybit);
}
+static void wacom_report_numbered_buttons(struct input_dev *input_dev,
+ int button_count, int mask)
+{
+ int i;
+
+ for (i = 0; i < button_count && i < 10; i++)
+ input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
+ for (i = 10; i < button_count && i < 16; i++)
+ input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
+ for (i = 16; i < button_count && i < 18; i++)
+ input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+}
+
int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac)
{
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 877c24a5df94..25baa7f29599 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -47,8 +47,8 @@
/* wacom data packet report IDs */
#define WACOM_REPORT_PENABLED 2
#define WACOM_REPORT_PENABLED_BT 3
-#define WACOM_REPORT_INTUOSREAD 5
-#define WACOM_REPORT_INTUOSWRITE 6
+#define WACOM_REPORT_INTUOS_ID1 5
+#define WACOM_REPORT_INTUOS_ID2 6
#define WACOM_REPORT_INTUOSPAD 12
#define WACOM_REPORT_INTUOS5PAD 3
#define WACOM_REPORT_DTUSPAD 21
@@ -70,6 +70,7 @@
#define WACOM_REPORT_DEVICE_LIST 16
#define WACOM_REPORT_INTUOS_PEN 16
#define WACOM_REPORT_REMOTE 17
+#define WACOM_REPORT_INTUOSHT2_ID 8
/* device quirks */
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
diff --git a/drivers/hsi/controllers/omap_ssi.c b/drivers/hsi/controllers/omap_ssi.c
index f6d3100b7a32..27b91f14ba7a 100644
--- a/drivers/hsi/controllers/omap_ssi.c
+++ b/drivers/hsi/controllers/omap_ssi.c
@@ -323,11 +323,10 @@ static int __init ssi_add_controller(struct hsi_controller *ssi,
return -ENOMEM;
}
- ssi->id = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
- if (ssi->id < 0) {
- err = ssi->id;
+ err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
+ if (err < 0)
goto out_err;
- }
+ ssi->id = err;
ssi->owner = THIS_MODULE;
ssi->device.parent = &pd->dev;
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index 02e66032ae73..e80a66e20998 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -1147,13 +1147,13 @@ static int __init ssi_port_probe(struct platform_device *pd)
goto error;
}
- cawake_gpio = of_get_named_gpio(np, "ti,ssi-cawake-gpio", 0);
- if (cawake_gpio < 0) {
+ err = of_get_named_gpio(np, "ti,ssi-cawake-gpio", 0);
+ if (err < 0) {
dev_err(&pd->dev, "DT data is missing cawake gpio (err=%d)\n",
- cawake_gpio);
- err = -ENODEV;
+ err);
goto error;
}
+ cawake_gpio = err;
err = devm_gpio_request_one(&port->device, cawake_gpio, GPIOF_DIR_IN,
"cawake");
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 899bede81b31..9d233bbde5e1 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -617,6 +617,10 @@ const struct i2c_algorithm i2c_bit_algo = {
};
EXPORT_SYMBOL(i2c_bit_algo);
+const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
+ .flags = I2C_AQ_NO_CLK_STRETCH,
+};
+
/*
* registering functions to load algorithms at runtime
*/
@@ -635,6 +639,8 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
/* register new adapter to i2c module... */
adap->algo = &i2c_bit_algo;
adap->retries = 3;
+ if (bit_adap->getscl == NULL)
+ adap->quirks = &i2c_bit_quirk_no_clk_stretch;
ret = add_adapter(adap);
if (ret < 0)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 7b0aa82ea38b..0299dfa746a3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -516,7 +516,7 @@ config I2C_EFM32
config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
- depends on PCI && (X86_32 || COMPILE_TEST)
+ depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -532,6 +532,7 @@ config I2C_EG20T
config I2C_EMEV2
tristate "EMMA Mobile series I2C adapter"
depends on HAVE_CLK
+ select I2C_SLAVE
help
If you say yes to this option, support will be included for the
I2C interface on the Renesas Electronics EM/EV family of processors.
@@ -963,11 +964,11 @@ config I2C_XILINX
will be called xilinx_i2c.
config I2C_XLR
- tristate "XLR I2C support"
- depends on CPU_XLR
+ tristate "Netlogic XLR and Sigma Designs I2C support"
+ depends on CPU_XLR || ARCH_TANGOX
help
This driver enables support for the on-chip I2C interface of
- the Netlogic XLR/XLS MIPS processors.
+ the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs.
This driver can also be built as a module. If so, the module
will be called i2c-xlr.
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 10835d1f559b..921d32bfcda8 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -64,6 +64,8 @@
#define AT91_TWI_IADR 0x000c /* Internal Address Register */
#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
+#define AT91_TWI_CWGR_HOLD_MAX 0x1f
+#define AT91_TWI_CWGR_HOLD(x) (((x) & AT91_TWI_CWGR_HOLD_MAX) << 24)
#define AT91_TWI_SR 0x0020 /* Status Register */
#define AT91_TWI_TXCOMP BIT(0) /* Transmission Complete */
@@ -110,6 +112,7 @@ struct at91_twi_pdata {
unsigned clk_offset;
bool has_unre_flag;
bool has_alt_cmd;
+ bool has_hold_field;
struct at_dma_slave dma_slave;
};
@@ -187,10 +190,11 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
*/
static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
{
- int ckdiv, cdiv, div;
+ int ckdiv, cdiv, div, hold = 0;
struct at91_twi_pdata *pdata = dev->pdata;
int offset = pdata->clk_offset;
int max_ckdiv = pdata->clk_max_div;
+ u32 twd_hold_time_ns = 0;
div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
2 * twi_clk) - offset);
@@ -204,8 +208,33 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
cdiv = 255;
}
- dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
- dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
+ if (pdata->has_hold_field) {
+ of_property_read_u32(dev->dev->of_node, "i2c-sda-hold-time-ns",
+ &twd_hold_time_ns);
+
+ /*
+ * hold time = HOLD + 3 x T_peripheral_clock
+ * Use clk rate in kHz to prevent overflows when computing
+ * hold.
+ */
+ hold = DIV_ROUND_UP(twd_hold_time_ns
+ * (clk_get_rate(dev->clk) / 1000), 1000000);
+ hold -= 3;
+ if (hold < 0)
+ hold = 0;
+ if (hold > AT91_TWI_CWGR_HOLD_MAX) {
+ dev_warn(dev->dev,
+ "HOLD field set to its maximum value (%d instead of %d)\n",
+ AT91_TWI_CWGR_HOLD_MAX, hold);
+ hold = AT91_TWI_CWGR_HOLD_MAX;
+ }
+ }
+
+ dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv
+ | AT91_TWI_CWGR_HOLD(hold);
+
+ dev_dbg(dev->dev, "cdiv %d ckdiv %d hold %d (%d ns)\n",
+ cdiv, ckdiv, hold, twd_hold_time_ns);
}
static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
@@ -797,6 +826,7 @@ static struct at91_twi_pdata at91rm9200_config = {
.clk_offset = 3,
.has_unre_flag = true,
.has_alt_cmd = false,
+ .has_hold_field = false,
};
static struct at91_twi_pdata at91sam9261_config = {
@@ -804,6 +834,7 @@ static struct at91_twi_pdata at91sam9261_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
+ .has_hold_field = false,
};
static struct at91_twi_pdata at91sam9260_config = {
@@ -811,6 +842,7 @@ static struct at91_twi_pdata at91sam9260_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
+ .has_hold_field = false,
};
static struct at91_twi_pdata at91sam9g20_config = {
@@ -818,6 +850,7 @@ static struct at91_twi_pdata at91sam9g20_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
+ .has_hold_field = false,
};
static struct at91_twi_pdata at91sam9g10_config = {
@@ -825,6 +858,7 @@ static struct at91_twi_pdata at91sam9g10_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
+ .has_hold_field = false,
};
static const struct platform_device_id at91_twi_devtypes[] = {
@@ -854,6 +888,15 @@ static struct at91_twi_pdata at91sam9x5_config = {
.clk_offset = 4,
.has_unre_flag = false,
.has_alt_cmd = false,
+ .has_hold_field = false,
+};
+
+static struct at91_twi_pdata sama5d4_config = {
+ .clk_max_div = 7,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+ .has_alt_cmd = false,
+ .has_hold_field = true,
};
static struct at91_twi_pdata sama5d2_config = {
@@ -861,6 +904,7 @@ static struct at91_twi_pdata sama5d2_config = {
.clk_offset = 4,
.has_unre_flag = true,
.has_alt_cmd = true,
+ .has_hold_field = true,
};
static const struct of_device_id atmel_twi_dt_ids[] = {
@@ -883,6 +927,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
.compatible = "atmel,at91sam9x5-i2c",
.data = &at91sam9x5_config,
}, {
+ .compatible = "atmel,sama5d4-i2c",
+ .data = &sama5d4_config,
+ }, {
.compatible = "atmel,sama5d2-i2c",
.data = &sama5d2_config,
}, {
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index 3032b89ac60b..818b051d25e6 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -222,6 +222,15 @@ static const struct i2c_algorithm bcm2835_i2c_algo = {
.functionality = bcm2835_i2c_func,
};
+/*
+ * This HW was reported to have problems with clock stretching:
+ * http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html
+ * https://www.raspberrypi.org/forums/viewtopic.php?p=146272
+ */
+static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
+ .flags = I2C_AQ_NO_CLK_STRETCH,
+};
+
static int bcm2835_i2c_probe(struct platform_device *pdev)
{
struct bcm2835_i2c_dev *i2c_dev;
@@ -293,6 +302,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
adap->algo = &bcm2835_i2c_algo;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
+ adap->quirks = &bcm2835_i2c_quirks;
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 8e9637eea512..3711df1d4526 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -25,13 +25,16 @@
#include <linux/version.h>
#define N_DATA_REGS 8
-#define N_DATA_BYTES (N_DATA_REGS * 4)
-/* BSC count register field definitions */
-#define BSC_CNT_REG1_MASK 0x0000003f
-#define BSC_CNT_REG1_SHIFT 0
-#define BSC_CNT_REG2_MASK 0x00000fc0
-#define BSC_CNT_REG2_SHIFT 6
+/*
+ * PER_I2C/BSC count register mask depends on 1 byte/4 byte data register
+ * size. Cable modem and DSL SoCs with Peripheral i2c cores use 1 byte per
+ * data register whereas STB SoCs use 4 byte per data register transfer,
+ * account for this difference in total count per transaction and mask to
+ * use.
+ */
+#define BSC_CNT_REG1_MASK(nb) (nb == 1 ? GENMASK(3, 0) : GENMASK(5, 0))
+#define BSC_CNT_REG1_SHIFT 0
/* BSC CTL register field definitions */
#define BSC_CTL_REG_DTF_MASK 0x00000003
@@ -41,7 +44,7 @@
#define BSC_CTL_REG_INT_EN_SHIFT 6
#define BSC_CTL_REG_DIV_CLK_MASK 0x00000080
-/* BSC_IIC_ENABLE r/w enable and interrupt field defintions */
+/* BSC_IIC_ENABLE r/w enable and interrupt field definitions */
#define BSC_IIC_EN_RESTART_MASK 0x00000040
#define BSC_IIC_EN_NOSTART_MASK 0x00000020
#define BSC_IIC_EN_NOSTOP_MASK 0x00000010
@@ -169,6 +172,7 @@ struct brcmstb_i2c_dev {
struct completion done;
bool is_suspended;
u32 clk_freq_hz;
+ int data_regsz;
};
/* register accessors for both be and le cpu arch */
@@ -186,6 +190,16 @@ struct brcmstb_i2c_dev {
#define bsc_writel(_dev, _val, _reg) \
__bsc_writel(_val, _dev->base + offsetof(struct bsc_regs, _reg))
+static inline int brcmstb_i2c_get_xfersz(struct brcmstb_i2c_dev *dev)
+{
+ return (N_DATA_REGS * dev->data_regsz);
+}
+
+static inline int brcmstb_i2c_get_data_regsz(struct brcmstb_i2c_dev *dev)
+{
+ return dev->data_regsz;
+}
+
static void brcmstb_i2c_enable_disable_irq(struct brcmstb_i2c_dev *dev,
bool int_en)
{
@@ -323,14 +337,16 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
u8 *buf, unsigned int len,
struct i2c_msg *pmsg)
{
- int cnt, byte, rc;
+ int cnt, byte, i, rc;
enum bsc_xfer_cmd cmd;
u32 ctl_reg;
struct bsc_regs *pi2creg = dev->bsc_regmap;
int no_ack = pmsg->flags & I2C_M_IGNORE_NAK;
+ int data_regsz = brcmstb_i2c_get_data_regsz(dev);
+ int xfersz = brcmstb_i2c_get_xfersz(dev);
/* see if the transaction needs to check NACK conditions */
- if (no_ack || len <= N_DATA_BYTES) {
+ if (no_ack || len <= xfersz) {
cmd = (pmsg->flags & I2C_M_RD) ? CMD_RD_NOACK
: CMD_WR_NOACK;
pi2creg->ctlhi_reg |= BSC_CTLHI_REG_IGNORE_ACK_MASK;
@@ -348,20 +364,22 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
pi2creg->ctl_reg = ctl_reg | DTF_RD_MASK;
/* set the read/write length */
- bsc_writel(dev, BSC_CNT_REG1_MASK & (len << BSC_CNT_REG1_SHIFT),
- cnt_reg);
+ bsc_writel(dev, BSC_CNT_REG1_MASK(data_regsz) &
+ (len << BSC_CNT_REG1_SHIFT), cnt_reg);
/* Write data into data_in register */
+
if (cmd == CMD_WR || cmd == CMD_WR_NOACK) {
- for (cnt = 0; cnt < len; cnt += 4) {
+ for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) {
u32 word = 0;
- for (byte = 0; byte < 4; byte++) {
- word >>= 8;
+ for (byte = 0; byte < data_regsz; byte++) {
+ word >>= BITS_PER_BYTE;
if ((cnt + byte) < len)
- word |= buf[cnt + byte] << 24;
+ word |= buf[cnt + byte] <<
+ (BITS_PER_BYTE * (data_regsz - 1));
}
- bsc_writel(dev, word, data_in[cnt >> 2]);
+ bsc_writel(dev, word, data_in[i]);
}
}
@@ -373,14 +391,15 @@ static int brcmstb_i2c_xfer_bsc_data(struct brcmstb_i2c_dev *dev,
return rc;
}
+ /* Read data from data_out register */
if (cmd == CMD_RD || cmd == CMD_RD_NOACK) {
- for (cnt = 0; cnt < len; cnt += 4) {
- u32 data = bsc_readl(dev, data_out[cnt >> 2]);
+ for (cnt = 0, i = 0; cnt < len; cnt += data_regsz, i++) {
+ u32 data = bsc_readl(dev, data_out[i]);
- for (byte = 0; byte < 4 &&
+ for (byte = 0; byte < data_regsz &&
(byte + cnt) < len; byte++) {
buf[cnt + byte] = data & 0xff;
- data >>= 8;
+ data >>= BITS_PER_BYTE;
}
}
}
@@ -448,6 +467,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
int bytes_to_xfer;
u8 *tmp_buf;
int len = 0;
+ int xfersz = brcmstb_i2c_get_xfersz(dev);
if (dev->is_suspended)
return -EBUSY;
@@ -482,9 +502,9 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter,
/* Perform data transfer */
while (len) {
- bytes_to_xfer = min(len, N_DATA_BYTES);
+ bytes_to_xfer = min(len, xfersz);
- if (len <= N_DATA_BYTES && i == (num - 1))
+ if (len <= xfersz && i == (num - 1))
brcmstb_set_i2c_start_stop(dev,
~(COND_START_STOP));
@@ -542,8 +562,12 @@ static void brcmstb_i2c_set_bus_speed(struct brcmstb_i2c_dev *dev)
static void brcmstb_i2c_set_bsc_reg_defaults(struct brcmstb_i2c_dev *dev)
{
- /* 4 byte data register */
- dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK;
+ if (brcmstb_i2c_get_data_regsz(dev) == sizeof(u32))
+ /* set 4 byte data in/out xfers */
+ dev->bsc_regmap->ctlhi_reg = BSC_CTLHI_REG_DATAREG_SIZE_MASK;
+ else
+ dev->bsc_regmap->ctlhi_reg &= ~BSC_CTLHI_REG_DATAREG_SIZE_MASK;
+
bsc_writel(dev, dev->bsc_regmap->ctlhi_reg, ctlhi_reg);
/* set bus speed */
brcmstb_i2c_set_bus_speed(dev);
@@ -608,6 +632,13 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
dev->clk_freq_hz = bsc_clk[0].hz;
}
+ /* set the data in/out register size for compatible SoCs */
+ if (of_device_is_compatible(dev->device->of_node,
+ "brcmstb,brcmper-i2c"))
+ dev->data_regsz = sizeof(u8);
+ else
+ dev->data_regsz = sizeof(u32);
+
brcmstb_i2c_set_bsc_reg_defaults(dev);
/* Add the i2c adapter */
@@ -674,6 +705,7 @@ static SIMPLE_DEV_PM_OPS(brcmstb_i2c_pm, brcmstb_i2c_suspend,
static const struct of_device_id brcmstb_i2c_of_match[] = {
{.compatible = "brcm,brcmstb-i2c"},
+ {.compatible = "brcm,brcmper-i2c"},
{},
};
MODULE_DEVICE_TABLE(of, brcmstb_i2c_of_match);
diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 84deed6571bd..6b08d1607b7a 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/pm_runtime.h>
/* Register offsets for the I2C device. */
#define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */
@@ -96,6 +97,8 @@
CDNS_I2C_IXR_COMP)
#define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000)
+/* timeout for pm runtime autosuspend */
+#define CNDS_I2C_PM_TIMEOUT 1000 /* ms */
#define CDNS_I2C_FIFO_DEPTH 16
/* FIFO depth at which the DATA interrupt occurs */
@@ -128,7 +131,6 @@
* @xfer_done: Transfer complete status
* @p_send_buf: Pointer to transmit buffer
* @p_recv_buf: Pointer to receive buffer
- * @suspended: Flag holding the device's PM status
* @send_count: Number of bytes still expected to send
* @recv_count: Number of bytes still expected to receive
* @curr_recv_count: Number of bytes to be received in current transfer
@@ -141,6 +143,7 @@
* @quirks: flag for broken hold bit usage in r1p10
*/
struct cdns_i2c {
+ struct device *dev;
void __iomem *membase;
struct i2c_adapter adap;
struct i2c_msg *p_msg;
@@ -148,7 +151,6 @@ struct cdns_i2c {
struct completion xfer_done;
unsigned char *p_send_buf;
unsigned char *p_recv_buf;
- u8 suspended;
unsigned int send_count;
unsigned int recv_count;
unsigned int curr_recv_count;
@@ -569,9 +571,14 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
struct cdns_i2c *id = adap->algo_data;
bool hold_quirk;
+ ret = pm_runtime_get_sync(id->dev);
+ if (ret < 0)
+ return ret;
/* Check if the bus is free */
- if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA)
- return -EAGAIN;
+ if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) {
+ ret = -EAGAIN;
+ goto out;
+ }
hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
/*
@@ -590,7 +597,8 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
if (msgs[count].flags & I2C_M_RD) {
dev_warn(adap->dev.parent,
"Can't do repeated start after a receive message\n");
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
+ goto out;
}
}
id->bus_hold_flag = 1;
@@ -608,20 +616,26 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
ret = cdns_i2c_process_msg(id, msgs, adap);
if (ret)
- return ret;
+ goto out;
/* Report the other error interrupts to application */
if (id->err_status) {
cdns_i2c_master_reset(adap);
- if (id->err_status & CDNS_I2C_IXR_NACK)
- return -ENXIO;
-
- return -EIO;
+ if (id->err_status & CDNS_I2C_IXR_NACK) {
+ ret = -ENXIO;
+ goto out;
+ }
+ ret = -EIO;
+ goto out;
}
}
- return num;
+ ret = num;
+out:
+ pm_runtime_mark_last_busy(id->dev);
+ pm_runtime_put_autosuspend(id->dev);
+ return ret;
}
/**
@@ -760,7 +774,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
struct clk_notifier_data *ndata = data;
struct cdns_i2c *id = to_cdns_i2c(nb);
- if (id->suspended)
+ if (pm_runtime_suspended(id->dev))
return NOTIFY_OK;
switch (event) {
@@ -808,14 +822,12 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
*
* Return: 0 always
*/
-static int __maybe_unused cdns_i2c_suspend(struct device *_dev)
+static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev = container_of(_dev,
- struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
clk_disable(xi2c->clk);
- xi2c->suspended = 1;
return 0;
}
@@ -828,26 +840,25 @@ static int __maybe_unused cdns_i2c_suspend(struct device *_dev)
*
* Return: 0 on success and error value on error
*/
-static int __maybe_unused cdns_i2c_resume(struct device *_dev)
+static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
{
- struct platform_device *pdev = container_of(_dev,
- struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
int ret;
ret = clk_enable(xi2c->clk);
if (ret) {
- dev_err(_dev, "Cannot enable clock.\n");
+ dev_err(dev, "Cannot enable clock.\n");
return ret;
}
- xi2c->suspended = 0;
-
return 0;
}
-static SIMPLE_DEV_PM_OPS(cdns_i2c_dev_pm_ops, cdns_i2c_suspend,
- cdns_i2c_resume);
+static const struct dev_pm_ops cdns_i2c_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend,
+ cdns_i2c_runtime_resume, NULL)
+};
static const struct cdns_platform_data r1p10_i2c_def = {
.quirks = CDNS_I2C_BROKEN_HOLD_BIT,
@@ -881,6 +892,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
if (!id)
return -ENOMEM;
+ id->dev = &pdev->dev;
platform_set_drvdata(pdev, id);
match = of_match_node(cdns_i2c_of_match, pdev->dev.of_node);
@@ -913,10 +925,14 @@ static int cdns_i2c_probe(struct platform_device *pdev)
return PTR_ERR(id->clk);
}
ret = clk_prepare_enable(id->clk);
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "Unable to enable clock.\n");
- return ret;
- }
+
+ pm_runtime_enable(id->dev);
+ pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(id->dev);
+ pm_runtime_set_active(id->dev);
+
id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb;
if (clk_notifier_register(id->clk, &id->clk_rate_change_nb))
dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
@@ -966,6 +982,8 @@ static int cdns_i2c_probe(struct platform_device *pdev)
err_clk_dis:
clk_disable_unprepare(id->clk);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
return ret;
}
@@ -984,6 +1002,7 @@ static int cdns_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&id->adap);
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
clk_disable_unprepare(id->clk);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index de7fbbb374cd..ba9732c236c5 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -271,6 +271,17 @@ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
enable ? "en" : "dis");
}
+static unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
+{
+ /*
+ * Clock is not necessary if we got LCNT/HCNT values directly from
+ * the platform code.
+ */
+ if (WARN_ON_ONCE(!dev->get_clk_rate_khz))
+ return 0;
+ return dev->get_clk_rate_khz(dev);
+}
+
/**
* i2c_dw_init() - initialize the designware i2c master hardware
* @dev: device private data
@@ -281,7 +292,6 @@ static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
*/
int i2c_dw_init(struct dw_i2c_dev *dev)
{
- u32 input_clock_khz;
u32 hcnt, lcnt;
u32 reg;
u32 sda_falling_time, scl_falling_time;
@@ -295,8 +305,6 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
}
}
- input_clock_khz = dev->get_clk_rate_khz(dev);
-
reg = dw_readl(dev, DW_IC_COMP_TYPE);
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
/* Configure register endianess access */
@@ -325,12 +333,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
hcnt = dev->ss_hcnt;
lcnt = dev->ss_lcnt;
} else {
- hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+ hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+ lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
4700, /* tLOW = 4.7 us */
scl_falling_time,
0); /* No offset */
@@ -344,12 +352,12 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
hcnt = dev->fs_hcnt;
lcnt = dev->fs_lcnt;
} else {
- hcnt = i2c_dw_scl_hcnt(input_clock_khz,
+ hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(input_clock_khz,
+ lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
1300, /* tLOW = 1.3 us */
scl_falling_time,
0); /* No offset */
@@ -860,6 +868,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter");
+ adap->retries = 3;
adap->algo = &i2c_dw_algo;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 1543d35d228d..7368be000c96 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -162,7 +162,7 @@ static struct dw_pci_controller dw_pci_controllers[] = {
#ifdef CONFIG_PM
static int i2c_dw_pci_suspend(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
i2c_dw_disable(pci_get_drvdata(pdev));
return 0;
@@ -170,7 +170,7 @@ static int i2c_dw_pci_suspend(struct device *dev)
static int i2c_dw_pci_resume(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
return i2c_dw_init(pci_get_drvdata(pdev));
}
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index bf72ae740fc1..438f1b4964c0 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -123,6 +123,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "80860F41", 0 },
{ "808622C1", 0 },
{ "AMD0010", ACCESS_INTR_MASK },
+ { "AMDI0510", 0 },
{ "APMC0D0F", 0 },
{ }
};
@@ -134,6 +135,18 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
}
#endif
+static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
+{
+ if (IS_ERR(i_dev->clk))
+ return PTR_ERR(i_dev->clk);
+
+ if (prepare)
+ return clk_prepare_enable(i_dev->clk);
+
+ clk_disable_unprepare(i_dev->clk);
+ return 0;
+}
+
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -206,16 +219,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
dev->clk = devm_clk_get(&pdev->dev, NULL);
- dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
- if (IS_ERR(dev->clk))
- return PTR_ERR(dev->clk);
- clk_prepare_enable(dev->clk);
+ if (!i2c_dw_plat_prepare_clk(dev, true)) {
+ dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
- if (!dev->sda_hold_time && ht) {
- u32 ic_clk = dev->get_clk_rate_khz(dev);
-
- dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
- 1000000);
+ if (!dev->sda_hold_time && ht)
+ dev->sda_hold_time = div_u64(
+ (u64)dev->get_clk_rate_khz(dev) * ht + 500000,
+ 1000000);
}
if (!dev->tx_fifo_depth) {
@@ -297,7 +307,7 @@ static int dw_i2c_plat_suspend(struct device *dev)
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
i2c_dw_disable(i_dev);
- clk_disable_unprepare(i_dev->clk);
+ i2c_dw_plat_prepare_clk(i_dev, false);
return 0;
}
@@ -307,7 +317,7 @@ static int dw_i2c_plat_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
- clk_prepare_enable(i_dev->clk);
+ i2c_dw_plat_prepare_clk(i_dev, true);
if (!i_dev->pm_runtime_disabled)
i2c_dw_init(i_dev);
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 76e699f9ed97..137125b5eae7 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -795,6 +795,7 @@ static int pch_i2c_probe(struct pci_dev *pdev,
/* base_addr + offset; */
adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
+ pch_adap->dev.of_node = pdev->dev.of_node;
pch_adap->dev.parent = &pdev->dev;
pch_i2c_init(&adap_info->pch_data[i]);
diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index 192ef6b50c79..96bb4e749012 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -71,6 +71,7 @@ struct em_i2c_device {
struct i2c_adapter adap;
struct completion msg_done;
struct clk *sclk;
+ struct i2c_client *slave;
};
static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
@@ -226,22 +227,131 @@ static int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return num;
}
+static bool em_i2c_slave_irq(struct em_i2c_device *priv)
+{
+ u8 status, value;
+ enum i2c_slave_event event;
+ int ret;
+
+ if (!priv->slave)
+ return false;
+
+ status = readb(priv->base + I2C_OFS_IICSE0);
+
+ /* Extension code, do not participate */
+ if (status & I2C_BIT_EXC0) {
+ em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
+ return true;
+ }
+
+ /* Stop detected, we don't know if it's for slave or master */
+ if (status & I2C_BIT_SPD0) {
+ /* Notify slave device */
+ i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
+ /* Pretend we did not handle the interrupt */
+ return false;
+ }
+
+ /* Only handle interrupts addressed to us */
+ if (!(status & I2C_BIT_COI0))
+ return false;
+
+ /* Enable stop interrupts */
+ em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0);
+
+ /* Transmission or Reception */
+ if (status & I2C_BIT_TRC0) {
+ if (status & I2C_BIT_ACKD0) {
+ /* 9 bit interrupt mode */
+ em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0);
+
+ /* Send data */
+ event = status & I2C_BIT_STD0 ?
+ I2C_SLAVE_READ_REQUESTED :
+ I2C_SLAVE_READ_PROCESSED;
+ i2c_slave_event(priv->slave, event, &value);
+ writeb(value, priv->base + I2C_OFS_IIC0);
+ } else {
+ /* NACK, stop transmitting */
+ em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0);
+ }
+ } else {
+ /* 8 bit interrupt mode */
+ em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0,
+ I2C_OFS_IICC0);
+ em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0,
+ I2C_OFS_IICC0);
+
+ if (status & I2C_BIT_STD0) {
+ i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED,
+ &value);
+ } else {
+ /* Recv data */
+ value = readb(priv->base + I2C_OFS_IIC0);
+ ret = i2c_slave_event(priv->slave,
+ I2C_SLAVE_WRITE_RECEIVED, &value);
+ if (ret < 0)
+ em_clear_set_bit(priv, I2C_BIT_ACKE0, 0,
+ I2C_OFS_IICC0);
+ }
+ }
+
+ return true;
+}
+
static irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id)
{
struct em_i2c_device *priv = dev_id;
+ if (em_i2c_slave_irq(priv))
+ return IRQ_HANDLED;
+
complete(&priv->msg_done);
+
return IRQ_HANDLED;
}
static u32 em_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
+}
+
+static int em_i2c_reg_slave(struct i2c_client *slave)
+{
+ struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
+
+ if (priv->slave)
+ return -EBUSY;
+
+ if (slave->flags & I2C_CLIENT_TEN)
+ return -EAFNOSUPPORT;
+
+ priv->slave = slave;
+
+ /* Set slave address */
+ writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0);
+
+ return 0;
+}
+
+static int em_i2c_unreg_slave(struct i2c_client *slave)
+{
+ struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter);
+
+ WARN_ON(!priv->slave);
+
+ writeb(0, priv->base + I2C_OFS_SVA0);
+
+ priv->slave = NULL;
+
+ return 0;
}
static struct i2c_algorithm em_i2c_algo = {
.master_xfer = em_i2c_xfer,
.functionality = em_i2c_func,
+ .reg_slave = em_i2c_reg_slave,
+ .unreg_slave = em_i2c_unreg_slave,
};
static int em_i2c_probe(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index ab492301581a..b6c080334297 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -99,7 +99,7 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
#endif
/* Bus timings (in ns) for bit-banging */
-static struct i2c_timings {
+static struct ibm_iic_timings {
unsigned int hd_sta;
unsigned int su_sto;
unsigned int low;
@@ -241,7 +241,7 @@ static int iic_dc_wait(volatile struct iic_regs __iomem *iic, u8 mask)
static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
- const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0];
+ const struct ibm_iic_timings *t = &timings[dev->fast_mode ? 1 : 0];
u8 mask, v, sda;
int i, res;
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index 3795fe130ef2..379ef9c31664 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -151,10 +151,11 @@
#define INT_FIFO_EMPTYING BIT(12)
#define INT_TRANSACTION_DONE BIT(15)
#define INT_SLAVE_EVENT BIT(16)
+#define INT_MASTER_HALTED BIT(17)
#define INT_TIMING BIT(18)
+#define INT_STOP_DETECTED BIT(19)
#define INT_FIFO_FULL_FILLING (INT_FIFO_FULL | INT_FIFO_FILLING)
-#define INT_FIFO_EMPTY_EMPTYING (INT_FIFO_EMPTY | INT_FIFO_EMPTYING)
/* Level interrupts need clearing after handling instead of before */
#define INT_LEVEL 0x01e00
@@ -177,7 +178,8 @@
INT_FIFO_FULL | \
INT_FIFO_FILLING | \
INT_FIFO_EMPTY | \
- INT_FIFO_EMPTYING)
+ INT_MASTER_HALTED | \
+ INT_STOP_DETECTED)
#define INT_ENABLE_MASK_WAITSTOP (INT_SLAVE_EVENT | \
INT_ADDR_ACK_ERR | \
@@ -511,7 +513,17 @@ static void img_i2c_soft_reset(struct img_i2c *i2c)
SCB_CONTROL_CLK_ENABLE | SCB_CONTROL_SOFT_RESET);
}
-/* enable or release transaction halt for control of repeated starts */
+/*
+ * Enable or release transaction halt for control of repeated starts.
+ * In version 3.3 of the IP when transaction halt is set, an interrupt
+ * will be generated after each byte of a transfer instead of after
+ * every transfer but before the stop bit.
+ * Due to this behaviour we have to be careful that every time we
+ * release the transaction halt we have to re-enable it straight away
+ * so that we only process a single byte, not doing so will result in
+ * all remaining bytes been processed and a stop bit being issued,
+ * which will prevent us having a repeated start.
+ */
static void img_i2c_transaction_halt(struct img_i2c *i2c, bool t_halt)
{
u32 val;
@@ -580,7 +592,6 @@ static void img_i2c_read(struct img_i2c *i2c)
img_i2c_writel(i2c, SCB_READ_ADDR_REG, i2c->msg.addr);
img_i2c_writel(i2c, SCB_READ_COUNT_REG, i2c->msg.len);
- img_i2c_transaction_halt(i2c, false);
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
}
@@ -594,7 +605,6 @@ static void img_i2c_write(struct img_i2c *i2c)
img_i2c_writel(i2c, SCB_WRITE_ADDR_REG, i2c->msg.addr);
img_i2c_writel(i2c, SCB_WRITE_COUNT_REG, i2c->msg.len);
- img_i2c_transaction_halt(i2c, false);
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
img_i2c_write_fifo(i2c);
@@ -750,7 +760,9 @@ static unsigned int img_i2c_atomic(struct img_i2c *i2c,
next_cmd = CMD_RET_ACK;
break;
case CMD_RET_ACK:
- if (i2c->line_status & LINESTAT_ACK_DET) {
+ if (i2c->line_status & LINESTAT_ACK_DET ||
+ (i2c->line_status & LINESTAT_NACK_DET &&
+ i2c->msg.flags & I2C_M_IGNORE_NAK)) {
if (i2c->msg.len == 0) {
next_cmd = CMD_GEN_STOP;
} else if (i2c->msg.flags & I2C_M_RD) {
@@ -858,34 +870,42 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
/* Enable transaction halt on start bit */
if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
- img_i2c_transaction_halt(i2c, true);
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
/* we're no longer interested in the slave event */
i2c->int_enable &= ~INT_SLAVE_EVENT;
}
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
+ if (int_status & INT_STOP_DETECTED) {
+ /* Drain remaining data in FIFO and complete transaction */
+ if (i2c->msg.flags & I2C_M_RD)
+ img_i2c_read_fifo(i2c);
+ return ISR_COMPLETE(0);
+ }
+
if (i2c->msg.flags & I2C_M_RD) {
- if (int_status & INT_FIFO_FULL_FILLING) {
+ if (int_status & (INT_FIFO_FULL_FILLING | INT_MASTER_HALTED)) {
img_i2c_read_fifo(i2c);
if (i2c->msg.len == 0)
return ISR_WAITSTOP;
}
} else {
- if (int_status & INT_FIFO_EMPTY_EMPTYING) {
- /*
- * The write fifo empty indicates that we're in the
- * last byte so it's safe to start a new write
- * transaction without losing any bytes from the
- * previous one.
- * see 2.3.7 Repeated Start Transactions.
- */
+ if (int_status & (INT_FIFO_EMPTY | INT_MASTER_HALTED)) {
if ((int_status & INT_FIFO_EMPTY) &&
i2c->msg.len == 0)
return ISR_WAITSTOP;
img_i2c_write_fifo(i2c);
}
}
+ if (int_status & INT_MASTER_HALTED) {
+ /*
+ * Release and then enable transaction halt, to
+ * allow only a single byte to proceed.
+ */
+ img_i2c_transaction_halt(i2c, false);
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
+ }
return 0;
}
@@ -1017,20 +1037,23 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
return -EIO;
for (i = 0; i < num; i++) {
- if (likely(msgs[i].len))
- continue;
/*
* 0 byte reads are not possible because the slave could try
* and pull the data line low, preventing a stop bit.
*/
- if (unlikely(msgs[i].flags & I2C_M_RD))
+ if (!msgs[i].len && msgs[i].flags & I2C_M_RD)
return -EIO;
/*
* 0 byte writes are possible and used for probing, but we
* cannot do them in automatic mode, so use atomic mode
* instead.
+ *
+ * Also, the I2C_M_IGNORE_NAK mode can only be implemented
+ * in atomic mode.
*/
- atomic = true;
+ if (!msgs[i].len ||
+ (msgs[i].flags & I2C_M_IGNORE_NAK))
+ atomic = true;
}
ret = clk_prepare_enable(i2c->scb_clk);
@@ -1069,12 +1092,31 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
- if (atomic)
+ if (atomic) {
img_i2c_atomic_start(i2c);
- else if (msg->flags & I2C_M_RD)
- img_i2c_read(i2c);
- else
- img_i2c_write(i2c);
+ } else {
+ /*
+ * Enable transaction halt if not the last message in
+ * the queue so that we can control repeated starts.
+ */
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
+
+ if (msg->flags & I2C_M_RD)
+ img_i2c_read(i2c);
+ else
+ img_i2c_write(i2c);
+
+ /*
+ * Release and then enable transaction halt, to
+ * allow only a single byte to proceed.
+ * This doesn't have an effect on the initial transfer
+ * but will allow the following transfers to start
+ * processing if the previous transfer was marked as
+ * complete while the i2c block was halted.
+ */
+ img_i2c_transaction_halt(i2c, false);
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
+ }
spin_unlock_irqrestore(&i2c->lock, flags);
time_left = wait_for_completion_timeout(&i2c->msg_complete,
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index d4d853680ae4..a2b132cef717 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -29,9 +29,6 @@
*
*/
-/** Includes *******************************************************************
-*******************************************************************************/
-
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -53,12 +50,10 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/i2c-imx.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/slab.h>
-/** Defines ********************************************************************
-*******************************************************************************/
-
/* This will be the driver name the kernel reports */
#define DRIVER_NAME "imx-i2c"
@@ -120,8 +115,7 @@
#define I2CR_IEN_OPCODE_0 0x0
#define I2CR_IEN_OPCODE_1 I2CR_IEN
-/** Variables ******************************************************************
-*******************************************************************************/
+#define I2C_PM_TIMEOUT 10 /* ms */
/*
* sorted list of clock divider, register value pairs
@@ -346,7 +340,7 @@ fail_tx:
dma_release_channel(dma->chan_tx);
fail_al:
devm_kfree(dev, dma);
- dev_info(dev, "can't use DMA\n");
+ dev_info(dev, "can't use DMA, using PIO instead.\n");
}
static void i2c_imx_dma_callback(void *arg)
@@ -393,6 +387,7 @@ static int i2c_imx_dma_xfer(struct imx_i2c_struct *i2c_imx,
return 0;
err_submit:
+ dmaengine_terminate_all(dma->chan_using);
err_desc:
dma_unmap_single(chan_dev, dma->dma_buf,
dma->dma_len, dma->dma_data_dir);
@@ -416,9 +411,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
-/** Functions for IMX I2C adapter driver ***************************************
-*******************************************************************************/
-
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
{
unsigned long orig_jiffies = jiffies;
@@ -527,9 +519,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
i2c_imx_set_clk(i2c_imx);
- result = clk_prepare_enable(i2c_imx->clk);
- if (result)
- return result;
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
/* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
@@ -582,7 +571,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
/* Disable I2C controller */
temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- clk_disable_unprepare(i2c_imx->clk);
}
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
@@ -901,6 +889,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
+ if (result < 0)
+ goto out;
+
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx);
if (result) {
@@ -964,6 +956,10 @@ fail0:
/* Stop I2C transfer */
i2c_imx_stop(i2c_imx);
+ pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
+ pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
+
+out:
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
@@ -997,10 +993,8 @@ static void i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
"gpio");
- rinfo->sda_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
- "sda-gpios", 0, NULL);
- rinfo->scl_gpio = of_get_named_gpio_flags(pdev->dev.of_node,
- "scl-gpios", 0, NULL);
+ rinfo->sda_gpio = of_get_named_gpio(pdev->dev.of_node, "sda-gpios", 0);
+ rinfo->scl_gpio = of_get_named_gpio(pdev->dev.of_node, "scl-gpios", 0);
if (!gpio_is_valid(rinfo->sda_gpio) ||
!gpio_is_valid(rinfo->scl_gpio) ||
@@ -1083,7 +1077,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = clk_prepare_enable(i2c_imx->clk);
if (ret) {
- dev_err(&pdev->dev, "can't enable I2C clock\n");
+ dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
return ret;
}
@@ -1107,6 +1101,18 @@ static int i2c_imx_probe(struct platform_device *pdev)
/* Set up adapter data */
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
+ /* Set up platform driver data */
+ platform_set_drvdata(pdev, i2c_imx);
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0)
+ goto rpm_disable;
+
/* Set up clock divider */
i2c_imx->bitrate = IMX_I2C_BIT_RATE;
ret = of_property_read_u32(pdev->dev.of_node,
@@ -1125,12 +1131,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) {
dev_err(&pdev->dev, "registration failed\n");
- goto clk_disable;
+ goto rpm_disable;
}
- /* Set up platform driver data */
- platform_set_drvdata(pdev, i2c_imx);
- clk_disable_unprepare(i2c_imx->clk);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
@@ -1143,6 +1148,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
return 0; /* Return OK */
+rpm_disable:
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+
clk_disable:
clk_disable_unprepare(i2c_imx->clk);
return ret;
@@ -1151,6 +1162,11 @@ clk_disable:
static int i2c_imx_remove(struct platform_device *pdev)
{
struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0)
+ return ret;
/* remove adapter */
dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n");
@@ -1165,17 +1181,54 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
+ clk_disable_unprepare(i2c_imx->clk);
+
+ pm_runtime_put_noidle(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int i2c_imx_runtime_suspend(struct device *dev)
+{
+ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(i2c_imx->clk);
+
return 0;
}
+static int i2c_imx_runtime_resume(struct device *dev)
+{
+ struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(i2c_imx->clk);
+ if (ret)
+ dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
+
+ return ret;
+}
+
+static const struct dev_pm_ops i2c_imx_pm_ops = {
+ SET_RUNTIME_PM_OPS(i2c_imx_runtime_suspend,
+ i2c_imx_runtime_resume, NULL)
+};
+#define I2C_IMX_PM_OPS (&i2c_imx_pm_ops)
+#else
+#define I2C_IMX_PM_OPS NULL
+#endif /* CONFIG_PM */
+
static struct platform_driver i2c_imx_driver = {
.probe = i2c_imx_probe,
.remove = i2c_imx_remove,
- .driver = {
- .name = DRIVER_NAME,
+ .driver = {
+ .name = DRIVER_NAME,
+ .pm = I2C_IMX_PM_OPS,
.of_match_table = i2c_imx_dt_ids,
},
- .id_table = imx_i2c_devtype,
+ .id_table = imx_i2c_devtype,
};
static int __init i2c_adap_imx_init(void)
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index 9b867169142f..aec8e6ce38a4 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -132,6 +132,7 @@ struct mtk_i2c_compatible {
unsigned char pmic_i2c: 1;
unsigned char dcm: 1;
unsigned char auto_restart: 1;
+ unsigned char aux_len_reg: 1;
};
struct mtk_i2c {
@@ -153,6 +154,8 @@ struct mtk_i2c {
enum mtk_trans_op op;
u16 timing_reg;
u16 high_speed_reg;
+ unsigned char auto_restart;
+ bool ignore_restart_irq;
const struct mtk_i2c_compatible *dev_comp;
};
@@ -178,6 +181,7 @@ static const struct mtk_i2c_compatible mt6577_compat = {
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 0,
+ .aux_len_reg = 0,
};
static const struct mtk_i2c_compatible mt6589_compat = {
@@ -185,6 +189,7 @@ static const struct mtk_i2c_compatible mt6589_compat = {
.pmic_i2c = 1,
.dcm = 0,
.auto_restart = 0,
+ .aux_len_reg = 0,
};
static const struct mtk_i2c_compatible mt8173_compat = {
@@ -192,6 +197,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
+ .aux_len_reg = 1,
};
static const struct of_device_id mtk_i2c_of_match[] = {
@@ -373,7 +379,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
i2c->irq_stat = 0;
- if (i2c->dev_comp->auto_restart)
+ if (i2c->auto_restart)
restart_flag = I2C_RS_TRANSFER;
reinit_completion(&i2c->msg_complete);
@@ -411,8 +417,14 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
/* Set transfer and transaction len */
if (i2c->op == I2C_MASTER_WRRD) {
- writew(msgs->len | ((msgs + 1)->len) << 8,
- i2c->base + OFFSET_TRANSFER_LEN);
+ if (i2c->dev_comp->aux_len_reg) {
+ writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);
+ writew((msgs + 1)->len, i2c->base +
+ OFFSET_TRANSFER_LEN_AUX);
+ } else {
+ writew(msgs->len | ((msgs + 1)->len) << 8,
+ i2c->base + OFFSET_TRANSFER_LEN);
+ }
writew(I2C_WRRD_TRANAC_VALUE, i2c->base + OFFSET_TRANSAC_LEN);
} else {
writew(msgs->len, i2c->base + OFFSET_TRANSFER_LEN);
@@ -461,7 +473,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
writel(I2C_DMA_START_EN, i2c->pdmabase + OFFSET_EN);
- if (!i2c->dev_comp->auto_restart) {
+ if (!i2c->auto_restart) {
start_reg = I2C_TRANSAC_START;
} else {
start_reg = I2C_TRANSAC_START | I2C_RS_MUL_TRIG;
@@ -518,6 +530,24 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
if (ret)
return ret;
+ i2c->auto_restart = i2c->dev_comp->auto_restart;
+
+ /* checking if we can skip restart and optimize using WRRD mode */
+ if (i2c->auto_restart && num == 2) {
+ if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD) &&
+ msgs[0].addr == msgs[1].addr) {
+ i2c->auto_restart = 0;
+ }
+ }
+
+ if (i2c->auto_restart && num >= 2 && i2c->speed_hz > MAX_FS_MODE_SPEED)
+ /* ignore the first restart irq after the master code,
+ * otherwise the first transfer will be discarded.
+ */
+ i2c->ignore_restart_irq = true;
+ else
+ i2c->ignore_restart_irq = false;
+
while (left_num--) {
if (!msgs->buf) {
dev_dbg(i2c->dev, "data buffer is NULL.\n");
@@ -530,7 +560,7 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
else
i2c->op = I2C_MASTER_WR;
- if (!i2c->dev_comp->auto_restart) {
+ if (!i2c->auto_restart) {
if (num > 1) {
/* combined two messages into one transaction */
i2c->op = I2C_MASTER_WRRD;
@@ -559,7 +589,7 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
u16 restart_flag = 0;
u16 intr_stat;
- if (i2c->dev_comp->auto_restart)
+ if (i2c->auto_restart)
restart_flag = I2C_RS_TRANSFER;
intr_stat = readw(i2c->base + OFFSET_INTR_STAT);
@@ -571,8 +601,16 @@ static irqreturn_t mtk_i2c_irq(int irqno, void *dev_id)
* i2c->irq_stat need keep the two interrupt value.
*/
i2c->irq_stat |= intr_stat;
- if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
- complete(&i2c->msg_complete);
+
+ if (i2c->ignore_restart_irq && (i2c->irq_stat & restart_flag)) {
+ i2c->ignore_restart_irq = false;
+ i2c->irq_stat = 0;
+ writew(I2C_RS_MUL_CNFG | I2C_RS_MUL_TRIG | I2C_TRANSAC_START,
+ i2c->base + OFFSET_START);
+ } else {
+ if (i2c->irq_stat & (I2C_TRANSAC_COMP | restart_flag))
+ complete(&i2c->msg_complete);
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 630bce68bf38..e04598595073 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -23,6 +23,9 @@
Note: we assume there can only be one device, with one or more
SMBus interfaces.
+ The device can register multiple i2c_adapters (up to PIIX4_MAX_ADAPTERS).
+ For devices supporting multiple ports the i2c_adapter should provide
+ an i2c_algorithm to access them.
*/
#include <linux/module.h>
@@ -37,6 +40,7 @@
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <linux/io.h>
+#include <linux/mutex.h>
/* PIIX4 SMBus address offsets */
@@ -75,6 +79,16 @@
#define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14
+/* Multi-port constants */
+#define PIIX4_MAX_ADAPTERS 4
+
+/* SB800 constants */
+#define SB800_PIIX4_SMB_IDX 0xcd6
+
+/* SB800 port is selected by bits 2:1 of the smb_en register (0x2c) */
+#define SB800_PIIX4_PORT_IDX 0x2c
+#define SB800_PIIX4_PORT_IDX_MASK 0x06
+
/* insmod parameters */
/* If force is set to anything different from 0, we forcibly enable the
@@ -122,8 +136,19 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
{ },
};
+/* SB800 globals */
+static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
+ "SDA0", "SDA2", "SDA3", "SDA4"
+};
+static const char *piix4_aux_port_name_sb800 = "SDA1";
+
struct i2c_piix4_adapdata {
unsigned short smba;
+
+ /* SB800 */
+ bool sb800_main;
+ unsigned short port;
+ struct mutex *mutex;
};
static int piix4_setup(struct pci_dev *PIIX4_dev,
@@ -229,7 +254,6 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
const struct pci_device_id *id, u8 aux)
{
unsigned short piix4_smba;
- unsigned short smba_idx = 0xcd6;
u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status;
u8 i2ccfg, i2ccfg_offset = 0x10;
@@ -251,16 +275,10 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
else
smb_en = (aux) ? 0x28 : 0x2c;
- if (!request_region(smba_idx, 2, "smba_idx")) {
- dev_err(&PIIX4_dev->dev, "SMBus base address index region "
- "0x%x already in use!\n", smba_idx);
- return -EBUSY;
- }
- outb_p(smb_en, smba_idx);
- smba_en_lo = inb_p(smba_idx + 1);
- outb_p(smb_en + 1, smba_idx);
- smba_en_hi = inb_p(smba_idx + 1);
- release_region(smba_idx, 2);
+ outb_p(smb_en, SB800_PIIX4_SMB_IDX);
+ smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+ outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
+ smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
if (!smb_en) {
smb_en_status = smba_en_lo & 0x10;
@@ -483,7 +501,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
outb_p(len, SMBHSTDAT0);
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= len; i++)
outb_p(data->block[i], SMBBLKDAT);
}
@@ -516,7 +534,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
data->block[0] = inb_p(SMBHSTDAT0);
if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
- i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
+ inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */
for (i = 1; i <= data->block[0]; i++)
data->block[i] = inb_p(SMBBLKDAT);
break;
@@ -524,6 +542,43 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
return 0;
}
+/*
+ * Handles access to multiple SMBus ports on the SB800.
+ * The port is selected by bits 2:1 of the smb_en register (0x2c).
+ * Returns negative errno on error.
+ *
+ * Note: The selected port must be returned to the initial selection to avoid
+ * problems on certain systems.
+ */
+static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data *data)
+{
+ struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+ u8 smba_en_lo;
+ u8 port;
+ int retval;
+
+ mutex_lock(adapdata->mutex);
+
+ outb_p(SB800_PIIX4_PORT_IDX, SB800_PIIX4_SMB_IDX);
+ smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
+
+ port = adapdata->port;
+ if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != (port << 1))
+ outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | (port << 1),
+ SB800_PIIX4_SMB_IDX + 1);
+
+ retval = piix4_access(adap, addr, flags, read_write,
+ command, size, data);
+
+ outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
+
+ mutex_unlock(adapdata->mutex);
+
+ return retval;
+}
+
static u32 piix4_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
@@ -536,6 +591,11 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = piix4_func,
};
+static const struct i2c_algorithm piix4_smbus_algorithm_sb800 = {
+ .smbus_xfer = piix4_access_sb800,
+ .functionality = piix4_func,
+};
+
static const struct pci_device_id piix4_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
@@ -561,11 +621,11 @@ static const struct pci_device_id piix4_ids[] = {
MODULE_DEVICE_TABLE (pci, piix4_ids);
-static struct i2c_adapter *piix4_main_adapter;
+static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS];
static struct i2c_adapter *piix4_aux_adapter;
static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
- struct i2c_adapter **padap)
+ const char *name, struct i2c_adapter **padap)
{
struct i2c_adapter *adap;
struct i2c_piix4_adapdata *adapdata;
@@ -594,7 +654,7 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
adap->dev.parent = &dev->dev;
snprintf(adap->name, sizeof(adap->name),
- "SMBus PIIX4 adapter at %04x", smba);
+ "SMBus PIIX4 adapter %s at %04x", name, smba);
i2c_set_adapdata(adap, adapdata);
@@ -611,6 +671,54 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
return 0;
}
+static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
+{
+ struct mutex *mutex;
+ struct i2c_piix4_adapdata *adapdata;
+ int port;
+ int retval;
+
+ mutex = kzalloc(sizeof(*mutex), GFP_KERNEL);
+ if (mutex == NULL)
+ return -ENOMEM;
+
+ mutex_init(mutex);
+
+ for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) {
+ retval = piix4_add_adapter(dev, smba,
+ piix4_main_port_names_sb800[port],
+ &piix4_main_adapters[port]);
+ if (retval < 0)
+ goto error;
+
+ piix4_main_adapters[port]->algo = &piix4_smbus_algorithm_sb800;
+
+ adapdata = i2c_get_adapdata(piix4_main_adapters[port]);
+ adapdata->sb800_main = true;
+ adapdata->port = port;
+ adapdata->mutex = mutex;
+ }
+
+ return retval;
+
+error:
+ dev_err(&dev->dev,
+ "Error setting up SB800 adapters. Unregistering!\n");
+ while (--port >= 0) {
+ adapdata = i2c_get_adapdata(piix4_main_adapters[port]);
+ if (adapdata->smba) {
+ i2c_del_adapter(piix4_main_adapters[port]);
+ kfree(adapdata);
+ kfree(piix4_main_adapters[port]);
+ piix4_main_adapters[port] = NULL;
+ }
+ }
+
+ kfree(mutex);
+
+ return retval;
+}
+
static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int retval;
@@ -618,20 +726,41 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
if ((dev->vendor == PCI_VENDOR_ID_ATI &&
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
dev->revision >= 0x40) ||
- dev->vendor == PCI_VENDOR_ID_AMD)
+ dev->vendor == PCI_VENDOR_ID_AMD) {
+ if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
+ dev_err(&dev->dev,
+ "SMBus base address index region 0x%x already in use!\n",
+ SB800_PIIX4_SMB_IDX);
+ return -EBUSY;
+ }
+
/* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0);
- else
- retval = piix4_setup(dev, id);
+ if (retval < 0) {
+ release_region(SB800_PIIX4_SMB_IDX, 2);
+ return retval;
+ }
- /* If no main SMBus found, give up */
- if (retval < 0)
- return retval;
+ /*
+ * Try to register multiplexed main SMBus adapter,
+ * give up if we can't
+ */
+ retval = piix4_add_adapters_sb800(dev, retval);
+ if (retval < 0) {
+ release_region(SB800_PIIX4_SMB_IDX, 2);
+ return retval;
+ }
+ } else {
+ retval = piix4_setup(dev, id);
+ if (retval < 0)
+ return retval;
- /* Try to register main SMBus adapter, give up if we can't */
- retval = piix4_add_adapter(dev, retval, &piix4_main_adapter);
- if (retval < 0)
- return retval;
+ /* Try to register main SMBus adapter, give up if we can't */
+ retval = piix4_add_adapter(dev, retval, "main",
+ &piix4_main_adapters[0]);
+ if (retval < 0)
+ return retval;
+ }
/* Check for auxiliary SMBus on some AMD chipsets */
retval = -ENODEV;
@@ -654,7 +783,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (retval > 0) {
/* Try to add the aux adapter if it exists,
* piix4_add_adapter will clean up if this fails */
- piix4_add_adapter(dev, retval, &piix4_aux_adapter);
+ piix4_add_adapter(dev, retval, piix4_aux_port_name_sb800,
+ &piix4_aux_adapter);
}
return 0;
@@ -666,7 +796,13 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
if (adapdata->smba) {
i2c_del_adapter(adap);
- release_region(adapdata->smba, SMBIOSIZE);
+ if (adapdata->port == 0) {
+ release_region(adapdata->smba, SMBIOSIZE);
+ if (adapdata->sb800_main) {
+ kfree(adapdata->mutex);
+ release_region(SB800_PIIX4_SMB_IDX, 2);
+ }
+ }
kfree(adapdata);
kfree(adap);
}
@@ -674,9 +810,13 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
static void piix4_remove(struct pci_dev *dev)
{
- if (piix4_main_adapter) {
- piix4_adap_remove(piix4_main_adapter);
- piix4_main_adapter = NULL;
+ int port = PIIX4_MAX_ADAPTERS;
+
+ while (--port >= 0) {
+ if (piix4_main_adapters[port]) {
+ piix4_adap_remove(piix4_main_adapters[port]);
+ piix4_main_adapters[port] = NULL;
+ }
}
if (piix4_aux_adapter) {
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 599c0d7bd906..1abeadc8ab79 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -1,7 +1,8 @@
/*
* Driver for the Renesas RCar I2C unit
*
- * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
+ * Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com>
+ * Copyright (C) 2011-2015 Renesas Electronics Corporation
*
* Copyright (C) 2012-14 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
@@ -9,9 +10,6 @@
* This file is based on the drivers/i2c/busses/i2c-sh7760.c
* (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
*
- * This file used out-of-tree driver i2c-rcar.c
- * Copyright (C) 2011-2012 Renesas Electronics 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.
@@ -33,7 +31,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
/* register offsets */
#define ICSCR 0x00 /* slave ctrl */
@@ -84,6 +81,7 @@
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
+#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF)
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
@@ -94,10 +92,13 @@
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)
#define ID_LAST_MSG (1 << 0)
-#define ID_IOERROR (1 << 1)
+#define ID_FIRST_MSG (1 << 1)
#define ID_DONE (1 << 2)
#define ID_ARBLOST (1 << 3)
#define ID_NACK (1 << 4)
+/* persistent flags */
+#define ID_P_PM_BLOCKED (1 << 31)
+#define ID_P_MASK ID_P_PM_BLOCKED
enum rcar_i2c_type {
I2C_RCAR_GEN1,
@@ -108,10 +109,10 @@ enum rcar_i2c_type {
struct rcar_i2c_priv {
void __iomem *io;
struct i2c_adapter adap;
- struct i2c_msg *msg;
+ struct i2c_msg *msg;
+ int msgs_left;
struct clk *clk;
- spinlock_t lock;
wait_queue_head_t wait;
int pos;
@@ -124,9 +125,6 @@ struct rcar_i2c_priv {
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
#define rcar_i2c_is_recv(p) ((p)->msg->flags & I2C_M_RD)
-#define rcar_i2c_flags_set(p, f) ((p)->flags |= (f))
-#define rcar_i2c_flags_has(p, f) ((p)->flags & (f))
-
#define LOOP_TIMEOUT 1024
@@ -144,9 +142,10 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
{
/* reset master mode */
rcar_i2c_write(priv, ICMIER, 0);
- rcar_i2c_write(priv, ICMCR, 0);
+ rcar_i2c_write(priv, ICMCR, MDBS);
rcar_i2c_write(priv, ICMSR, 0);
- rcar_i2c_write(priv, ICMAR, 0);
+ /* start clock */
+ rcar_i2c_write(priv, ICCCR, priv->icccr);
}
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
@@ -163,15 +162,17 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
return -EBUSY;
}
-static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
- u32 bus_speed,
- struct device *dev)
+static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timings *t)
{
- u32 scgd, cdf;
- u32 round, ick;
- u32 scl;
- u32 cdf_width;
+ u32 scgd, cdf, round, ick, sum, scl, cdf_width;
unsigned long rate;
+ struct device *dev = rcar_i2c_priv_to_dev(priv);
+
+ /* Fall back to previously used values if not supplied */
+ t->bus_freq_hz = t->bus_freq_hz ?: 100000;
+ t->scl_fall_ns = t->scl_fall_ns ?: 35;
+ t->scl_rise_ns = t->scl_rise_ns ?: 200;
+ t->scl_int_delay_ns = t->scl_int_delay_ns ?: 50;
switch (priv->devtype) {
case I2C_RCAR_GEN1:
@@ -195,9 +196,9 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick])
*
* ick : I2C internal clock < 20 MHz
- * ticf : I2C SCL falling time = 35 ns here
- * tr : I2C SCL rising time = 200 ns here
- * intd : LSI internal delay = 50 ns here
+ * ticf : I2C SCL falling time
+ * tr : I2C SCL rising time
+ * intd : LSI internal delay
* clkp : peripheral_clk
* F[] : integer up-valuation
*/
@@ -213,12 +214,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
* it is impossible to calculate large scale
* number on u32. separate it
*
- * F[(ticf + tr + intd) * ick]
- * = F[(35 + 200 + 50)ns * ick]
- * = F[285 * ick / 1000000000]
- * = F[(ick / 1000000) * 285 / 1000]
+ * F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd)
+ * = F[sum * ick / 1000000000]
+ * = F[(ick / 1000000) * sum / 1000]
*/
- round = (ick + 500000) / 1000000 * 285;
+ sum = t->scl_fall_ns + t->scl_rise_ns + t->scl_int_delay_ns;
+ round = (ick + 500000) / 1000000 * sum;
round = (round + 500) / 1000;
/*
@@ -235,7 +236,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
*/
for (scgd = 0; scgd < 0x40; scgd++) {
scl = ick / (20 + (scgd * 8) + round);
- if (scl <= bus_speed)
+ if (scl <= t->bus_freq_hz)
goto scgd_find;
}
dev_err(dev, "it is impossible to calculate best SCL\n");
@@ -243,11 +244,9 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
scgd_find:
dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n",
- scl, bus_speed, clk_get_rate(priv->clk), round, cdf, scgd);
+ scl, t->bus_freq_hz, clk_get_rate(priv->clk), round, cdf, scgd);
- /*
- * keep icccr value
- */
+ /* keep icccr value */
priv->icccr = scgd << cdf_width | cdf;
return 0;
@@ -257,33 +256,44 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
{
int read = !!rcar_i2c_is_recv(priv);
+ priv->pos = 0;
+ if (priv->msgs_left == 1)
+ priv->flags |= ID_LAST_MSG;
+
rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
- rcar_i2c_write(priv, ICMSR, 0);
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+ /*
+ * We don't have a testcase but the HW engineers say that the write order
+ * of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
+ * it didn't cause a drawback for me, let's rather be safe than sorry.
+ */
+ if (priv->flags & ID_FIRST_MSG) {
+ rcar_i2c_write(priv, ICMSR, 0);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+ } else {
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+ rcar_i2c_write(priv, ICMSR, 0);
+ }
rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
}
+static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)
+{
+ priv->msg++;
+ priv->msgs_left--;
+ priv->flags &= ID_P_MASK;
+ rcar_i2c_prepare_msg(priv);
+}
+
/*
* interrupt functions
*/
-static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
+static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
{
struct i2c_msg *msg = priv->msg;
- /*
- * FIXME
- * sometimes, unknown interrupt happened.
- * Do nothing
- */
+ /* FIXME: sometimes, unknown interrupt happened. Do nothing */
if (!(msr & MDE))
- return 0;
-
- /*
- * If address transfer phase finished,
- * goto data phase.
- */
- if (msr & MAT)
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
+ return;
if (priv->pos < msg->len) {
/*
@@ -305,67 +315,50 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
* [ICRXTX] -> [SHIFT] -> [I2C bus]
*/
- if (priv->flags & ID_LAST_MSG)
+ if (priv->flags & ID_LAST_MSG) {
/*
* If current msg is the _LAST_ msg,
* prepare stop condition here.
* ID_DONE will be set on STOP irq.
*/
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
- else
- /*
- * If current msg is _NOT_ last msg,
- * it doesn't call stop phase.
- * thus, there is no STOP irq.
- * return ID_DONE here.
- */
- return ID_DONE;
+ } else {
+ rcar_i2c_next_msg(priv);
+ return;
+ }
}
rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND);
-
- return 0;
}
-static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
+static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
{
struct i2c_msg *msg = priv->msg;
- /*
- * FIXME
- * sometimes, unknown interrupt happened.
- * Do nothing
- */
+ /* FIXME: sometimes, unknown interrupt happened. Do nothing */
if (!(msr & MDR))
- return 0;
+ return;
if (msr & MAT) {
- /*
- * Address transfer phase finished,
- * but, there is no data at this point.
- * Do nothing.
- */
+ /* Address transfer phase finished, but no data at this point. */
} else if (priv->pos < msg->len) {
- /*
- * get received data
- */
+ /* get received data */
msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
priv->pos++;
}
/*
- * If next received data is the _LAST_,
- * go to STOP phase,
- * otherwise, go to DATA phase.
+ * If next received data is the _LAST_, go to STOP phase. Might be
+ * overwritten by REP START when setting up a new msg. Not elegant
+ * but the only stable sequence for REP START I have found so far.
*/
if (priv->pos + 1 >= msg->len)
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
- else
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
-
- rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
- return 0;
+ if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
+ rcar_i2c_next_msg(priv);
+ else
+ rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
}
static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
@@ -426,62 +419,57 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
{
struct rcar_i2c_priv *priv = ptr;
- irqreturn_t result = IRQ_HANDLED;
- u32 msr;
-
- /*-------------- spin lock -----------------*/
- spin_lock(&priv->lock);
+ u32 msr, val;
- if (rcar_i2c_slave_irq(priv))
- goto exit;
+ /* Clear START or STOP as soon as we can */
+ val = rcar_i2c_read(priv, ICMCR);
+ rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
msr = rcar_i2c_read(priv, ICMSR);
/* Only handle interrupts that are currently enabled */
msr &= rcar_i2c_read(priv, ICMIER);
if (!msr) {
- result = IRQ_NONE;
- goto exit;
+ if (rcar_i2c_slave_irq(priv))
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
}
/* Arbitration lost */
if (msr & MAL) {
- rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
+ priv->flags |= ID_DONE | ID_ARBLOST;
goto out;
}
/* Nack */
if (msr & MNR) {
- /* go to stop phase */
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+ /* HW automatically sends STOP after received NACK */
rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP);
- rcar_i2c_flags_set(priv, ID_NACK);
+ priv->flags |= ID_NACK;
goto out;
}
/* Stop */
if (msr & MST) {
- rcar_i2c_flags_set(priv, ID_DONE);
+ priv->msgs_left--; /* The last message also made it */
+ priv->flags |= ID_DONE;
goto out;
}
if (rcar_i2c_is_recv(priv))
- rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
+ rcar_i2c_irq_recv(priv, msr);
else
- rcar_i2c_flags_set(priv, rcar_i2c_irq_send(priv, msr));
+ rcar_i2c_irq_send(priv, msr);
out:
- if (rcar_i2c_flags_has(priv, ID_DONE)) {
+ if (priv->flags & ID_DONE) {
rcar_i2c_write(priv, ICMIER, 0);
rcar_i2c_write(priv, ICMSR, 0);
wake_up(&priv->wait);
}
-exit:
- spin_unlock(&priv->lock);
- /*-------------- spin unlock -----------------*/
-
- return result;
+ return IRQ_HANDLED;
}
static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
@@ -490,22 +478,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
- unsigned long flags;
int i, ret;
- long timeout;
+ long time_left;
pm_runtime_get_sync(dev);
- /*-------------- spin lock -----------------*/
- spin_lock_irqsave(&priv->lock, flags);
-
- rcar_i2c_init(priv);
- /* start clock */
- rcar_i2c_write(priv, ICCCR, priv->icccr);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- /*-------------- spin unlock -----------------*/
-
ret = rcar_i2c_bus_barrier(priv);
if (ret < 0)
goto out;
@@ -514,48 +491,27 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
/* This HW can't send STOP after address phase */
if (msgs[i].len == 0) {
ret = -EOPNOTSUPP;
- break;
- }
-
- /*-------------- spin lock -----------------*/
- spin_lock_irqsave(&priv->lock, flags);
-
- /* init each data */
- priv->msg = &msgs[i];
- priv->pos = 0;
- priv->flags = 0;
- if (i == num - 1)
- rcar_i2c_flags_set(priv, ID_LAST_MSG);
-
- rcar_i2c_prepare_msg(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- /*-------------- spin unlock -----------------*/
-
- timeout = wait_event_timeout(priv->wait,
- rcar_i2c_flags_has(priv, ID_DONE),
- adap->timeout);
- if (!timeout) {
- ret = -ETIMEDOUT;
- break;
- }
-
- if (rcar_i2c_flags_has(priv, ID_NACK)) {
- ret = -ENXIO;
- break;
- }
-
- if (rcar_i2c_flags_has(priv, ID_ARBLOST)) {
- ret = -EAGAIN;
- break;
- }
-
- if (rcar_i2c_flags_has(priv, ID_IOERROR)) {
- ret = -EIO;
- break;
+ goto out;
}
+ }
- ret = i + 1; /* The number of transfer */
+ /* init first message */
+ priv->msg = msgs;
+ priv->msgs_left = num;
+ priv->flags = (priv->flags & ID_P_MASK) | ID_FIRST_MSG;
+ rcar_i2c_prepare_msg(priv);
+
+ time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
+ num * adap->timeout);
+ if (!time_left) {
+ rcar_i2c_init(priv);
+ ret = -ETIMEDOUT;
+ } else if (priv->flags & ID_NACK) {
+ ret = -ENXIO;
+ } else if (priv->flags & ID_ARBLOST) {
+ ret = -EAGAIN;
+ } else {
+ ret = num - priv->msgs_left; /* The number of transfer */
}
out:
pm_runtime_put(dev);
@@ -637,7 +593,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
struct resource *res;
struct device *dev = &pdev->dev;
- u32 bus_speed;
+ struct i2c_timings i2c_t;
int irq, ret;
priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
@@ -650,23 +606,13 @@ static int rcar_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->clk);
}
- bus_speed = 100000; /* default 100 kHz */
- of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed);
-
- priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
-
- ret = rcar_i2c_clock_calculate(priv, bus_speed, dev);
- if (ret < 0)
- return ret;
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->io))
return PTR_ERR(priv->io);
- irq = platform_get_irq(pdev, 0);
+ priv->devtype = (enum rcar_i2c_type)of_match_device(rcar_i2c_dt_ids, dev)->data;
init_waitqueue_head(&priv->wait);
- spin_lock_init(&priv->lock);
adap = &priv->adap;
adap->nr = pdev->id;
@@ -678,26 +624,47 @@ static int rcar_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
- ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0,
- dev_name(dev), priv);
+ i2c_parse_fw_timings(dev, &i2c_t, false);
+
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+ ret = rcar_i2c_clock_calculate(priv, &i2c_t);
+ if (ret < 0)
+ goto out_pm_put;
+
+ rcar_i2c_init(priv);
+
+ /* Don't suspend when multi-master to keep arbitration working */
+ if (of_property_read_bool(dev->of_node, "multi-master"))
+ priv->flags |= ID_P_PM_BLOCKED;
+ else
+ pm_runtime_put(dev);
+
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "cannot get irq %d\n", irq);
- return ret;
+ goto out_pm_disable;
}
- pm_runtime_enable(dev);
platform_set_drvdata(pdev, priv);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(dev, "reg adap failed: %d\n", ret);
- pm_runtime_disable(dev);
- return ret;
+ goto out_pm_disable;
}
dev_info(dev, "probed\n");
return 0;
+
+ out_pm_put:
+ pm_runtime_put(dev);
+ out_pm_disable:
+ pm_runtime_disable(dev);
+ return ret;
}
static int rcar_i2c_remove(struct platform_device *pdev)
@@ -706,6 +673,8 @@ static int rcar_i2c_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
i2c_del_adapter(&priv->adap);
+ if (priv->flags & ID_P_PM_BLOCKED)
+ pm_runtime_put(dev);
pm_runtime_disable(dev);
return 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 5df819610d52..362a6de54833 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -784,7 +784,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
int retry;
int ret;
- pm_runtime_get_sync(&adap->dev);
ret = clk_enable(i2c->clk);
if (ret)
return ret;
@@ -795,7 +794,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
if (ret != -EAGAIN) {
clk_disable(i2c->clk);
- pm_runtime_put(&adap->dev);
return ret;
}
@@ -805,7 +803,6 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
}
clk_disable(i2c->clk);
- pm_runtime_put(&adap->dev);
return -EREMOTEIO;
}
@@ -1256,8 +1253,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
return ret;
}
- pm_runtime_enable(&i2c->adap.dev);
-
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
}
@@ -1273,7 +1268,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
clk_unprepare(i2c->clk);
- pm_runtime_disable(&i2c->adap.dev);
pm_runtime_disable(&pdev->dev);
s3c24xx_i2c_deregister_cpufreq(i2c);
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 25020ec777c9..6ee77159ac57 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -708,8 +708,7 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap,
#ifdef CONFIG_PM_SLEEP
static int st_i2c_suspend(struct device *dev)
{
- struct platform_device *pdev =
- container_of(dev, struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(dev);
struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
if (i2c_dev->busy)
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
index 4c7fc2d47014..210ca82f8aa0 100644
--- a/drivers/i2c/busses/i2c-taos-evm.c
+++ b/drivers/i2c/busses/i2c-taos-evm.c
@@ -130,7 +130,13 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
return 0;
} else {
if (p[0] == 'x') {
- data->byte = simple_strtol(p + 1, NULL, 16);
+ /*
+ * Voluntarily dropping error code of kstrtou8 since all
+ * error code that it could return are invalid according
+ * to Documentation/i2c/fault-codes.
+ */
+ if (kstrtou8(p + 1, 16, &data->byte))
+ return -EPROTO;
return 0;
}
}
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
index e8d03bcfe3e0..f3e5ff8522f0 100644
--- a/drivers/i2c/busses/i2c-uniphier-f.c
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -466,6 +466,11 @@ static int uniphier_fi2c_clk_init(struct device *dev,
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;
+ if (!bus_speed) {
+ dev_err(dev, "clock-freqyency should not be zero\n");
+ return -EINVAL;
+ }
+
if (bus_speed > UNIPHIER_FI2C_MAX_SPEED)
bus_speed = UNIPHIER_FI2C_MAX_SPEED;
@@ -481,6 +486,10 @@ static int uniphier_fi2c_clk_init(struct device *dev,
return ret;
clk_rate = clk_get_rate(priv->clk);
+ if (!clk_rate) {
+ dev_err(dev, "input clock rate should not be zero\n");
+ return -EINVAL;
+ }
uniphier_fi2c_reset(priv);
@@ -531,7 +540,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
ret = uniphier_fi2c_clk_init(dev, priv);
if (ret)
- return ret;
+ goto err;
ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0,
pdev->name, priv);
diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c
index e3c3861c3325..1f4f3f53819c 100644
--- a/drivers/i2c/busses/i2c-uniphier.c
+++ b/drivers/i2c/busses/i2c-uniphier.c
@@ -327,6 +327,11 @@ static int uniphier_i2c_clk_init(struct device *dev,
if (of_property_read_u32(np, "clock-frequency", &bus_speed))
bus_speed = UNIPHIER_I2C_DEFAULT_SPEED;
+ if (!bus_speed) {
+ dev_err(dev, "clock-freqyency should not be zero\n");
+ return -EINVAL;
+ }
+
if (bus_speed > UNIPHIER_I2C_MAX_SPEED)
bus_speed = UNIPHIER_I2C_MAX_SPEED;
@@ -342,6 +347,10 @@ static int uniphier_i2c_clk_init(struct device *dev,
return ret;
clk_rate = clk_get_rate(priv->clk);
+ if (!clk_rate) {
+ dev_err(dev, "input clock rate should not be zero\n");
+ return -EINVAL;
+ }
uniphier_i2c_reset(priv, true);
@@ -388,7 +397,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
ret = uniphier_i2c_clk_init(dev, priv);
if (ret)
- return ret;
+ goto err;
ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
priv);
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 0b20449e48cf..6efd20095d5d 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -70,7 +70,7 @@ struct xiic_i2c {
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_msg *tx_msg;
- spinlock_t lock;
+ struct mutex lock;
unsigned int tx_pos;
unsigned int nmsgs;
enum xilinx_i2c_state state;
@@ -369,7 +369,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
* To find which interrupts are pending; AND interrupts pending with
* interrupts masked.
*/
- spin_lock(&i2c->lock);
+ mutex_lock(&i2c->lock);
isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
pend = isr & ier;
@@ -497,7 +497,7 @@ out:
dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
- spin_unlock(&i2c->lock);
+ mutex_unlock(&i2c->lock);
return IRQ_HANDLED;
}
@@ -662,10 +662,10 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
static void xiic_start_xfer(struct xiic_i2c *i2c)
{
- spin_lock(&i2c->lock);
+ mutex_lock(&i2c->lock);
xiic_reinit(i2c);
__xiic_start_xfer(i2c);
- spin_unlock(&i2c->lock);
+ mutex_unlock(&i2c->lock);
}
static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
@@ -745,7 +745,7 @@ static int xiic_i2c_probe(struct platform_device *pdev)
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
- spin_lock_init(&i2c->lock);
+ mutex_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);
ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr,
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
index 8b36bcfd952d..613c3a4f2c51 100644
--- a/drivers/i2c/busses/i2c-xlr.c
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -17,6 +17,10 @@
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
/* XLR I2C REGISTERS */
#define XLR_I2C_CFG 0x00
@@ -30,6 +34,10 @@
#define XLR_I2C_BYTECNT 0x08
#define XLR_I2C_HDSTATIM 0x09
+/* Sigma Designs additional registers */
+#define XLR_I2C_INT_EN 0x09
+#define XLR_I2C_INT_STAT 0x0a
+
/* XLR I2C REGISTERS FLAGS */
#define XLR_I2C_BUS_BUSY 0x01
#define XLR_I2C_SDOEMPTY 0x02
@@ -63,11 +71,98 @@ static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
return __raw_readl(base + reg);
}
+#define XLR_I2C_FLAG_IRQ 1
+
+struct xlr_i2c_config {
+ u32 flags; /* optional feature support */
+ u32 status_busy; /* value of STATUS[0] when busy */
+ u32 cfg_extra; /* extra CFG bits to set */
+};
+
struct xlr_i2c_private {
struct i2c_adapter adap;
u32 __iomem *iobase;
+ int irq;
+ int pos;
+ struct i2c_msg *msg;
+ const struct xlr_i2c_config *cfg;
+ wait_queue_head_t wait;
+ struct clk *clk;
};
+static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status)
+{
+ return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy;
+}
+
+static int xlr_i2c_idle(struct xlr_i2c_private *priv)
+{
+ return !xlr_i2c_busy(priv, xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS));
+}
+
+static int xlr_i2c_wait(struct xlr_i2c_private *priv, unsigned long timeout)
+{
+ int status;
+ int t;
+
+ t = wait_event_timeout(priv->wait, xlr_i2c_idle(priv),
+ msecs_to_jiffies(timeout));
+ if (!t)
+ return -ETIMEDOUT;
+
+ status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+
+ return status & XLR_I2C_ACK_ERR ? -EIO : 0;
+}
+
+static void xlr_i2c_tx_irq(struct xlr_i2c_private *priv, u32 status)
+{
+ struct i2c_msg *msg = priv->msg;
+
+ if (status & XLR_I2C_SDOEMPTY)
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT,
+ msg->buf[priv->pos++]);
+}
+
+static void xlr_i2c_rx_irq(struct xlr_i2c_private *priv, u32 status)
+{
+ struct i2c_msg *msg = priv->msg;
+
+ if (status & XLR_I2C_RXRDY)
+ msg->buf[priv->pos++] =
+ xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
+}
+
+static irqreturn_t xlr_i2c_irq(int irq, void *dev_id)
+{
+ struct xlr_i2c_private *priv = dev_id;
+ struct i2c_msg *msg = priv->msg;
+ u32 int_stat, status;
+
+ int_stat = xlr_i2c_rdreg(priv->iobase, XLR_I2C_INT_STAT);
+ if (!int_stat)
+ return IRQ_NONE;
+
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, int_stat);
+
+ if (!msg)
+ return IRQ_HANDLED;
+
+ status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
+
+ if (priv->pos < msg->len) {
+ if (msg->flags & I2C_M_RD)
+ xlr_i2c_rx_irq(priv, status);
+ else
+ xlr_i2c_tx_irq(priv, status);
+ }
+
+ if (!xlr_i2c_busy(priv, status))
+ wake_up(&priv->wait);
+
+ return IRQ_HANDLED;
+}
+
static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
u8 *buf, u16 addr)
{
@@ -75,37 +170,48 @@ static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
unsigned long timeout, stoptime, checktime;
u32 i2c_status;
int pos, timedout;
- u8 offset, byte;
+ u8 offset;
+ u32 xfer;
+
+ if (!len)
+ return -EOPNOTSUPP;
offset = buf[0];
xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
+ XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra);
timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
stoptime = jiffies + timeout;
timedout = 0;
- pos = 1;
-retry:
+
if (len == 1) {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
- XLR_I2C_STARTXFR_ND);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
+ xfer = XLR_I2C_STARTXFR_ND;
+ pos = 1;
} else {
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR,
- XLR_I2C_STARTXFR_WR);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 2);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[1]);
+ xfer = XLR_I2C_STARTXFR_WR;
+ pos = 2;
}
+ priv->pos = pos;
+
+retry:
+ /* retry can only happen on the first byte */
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, xfer);
+
+ if (priv->irq > 0)
+ return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
+
while (!timedout) {
checktime = jiffies;
i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
- if (i2c_status & XLR_I2C_SDOEMPTY) {
- pos++;
- /* need to do a empty dataout after the last byte */
- byte = (pos < len) ? buf[pos] : 0;
- xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte);
+ if ((i2c_status & XLR_I2C_SDOEMPTY) && pos < len) {
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos++]);
/* reset timeout on successful xmit */
stoptime = jiffies + timeout;
@@ -121,7 +227,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
- if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len)
+ if (!xlr_i2c_busy(priv, i2c_status) && pos >= len)
return 0;
}
dev_err(&adap->dev, "I2C transmit timeout\n");
@@ -134,12 +240,17 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
u32 i2c_status;
unsigned long timeout, stoptime, checktime;
int nbytes, timedout;
- u8 byte;
- xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
- xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len);
+ if (!len)
+ return -EOPNOTSUPP;
+
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
+ XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
+ priv->pos = 0;
+
timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
stoptime = jiffies + timeout;
timedout = 0;
@@ -147,18 +258,18 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
retry:
xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
+ if (priv->irq > 0)
+ return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
+
while (!timedout) {
checktime = jiffies;
i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
if (i2c_status & XLR_I2C_RXRDY) {
- if (nbytes > len)
+ if (nbytes >= len)
return -EIO; /* should not happen */
- /* we need to do a dummy datain when nbytes == len */
- byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
- if (nbytes < len)
- buf[nbytes] = byte;
- nbytes++;
+ buf[nbytes++] =
+ xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
/* reset timeout on successful read */
stoptime = jiffies + timeout;
@@ -174,7 +285,7 @@ retry:
if (i2c_status & XLR_I2C_ACK_ERR)
return -EIO;
- if ((i2c_status & XLR_I2C_BUS_BUSY) == 0)
+ if (!xlr_i2c_busy(priv, i2c_status))
return 0;
}
@@ -190,8 +301,17 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
int ret = 0;
struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
+ ret = clk_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ if (priv->irq)
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0xf);
+
+
for (i = 0; ret == 0 && i < num; i++) {
msg = &msgs[i];
+ priv->msg = msg;
if (msg->flags & I2C_M_RD)
ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
msg->addr);
@@ -200,13 +320,19 @@ static int xlr_i2c_xfer(struct i2c_adapter *adap,
msg->addr);
}
+ if (priv->irq)
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
+
+ clk_disable(priv->clk);
+ priv->msg = NULL;
+
return (ret != 0) ? ret : num;
}
static u32 xlr_func(struct i2c_adapter *adap)
{
/* Emulate SMBUS over I2C */
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+ return (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_I2C;
}
static struct i2c_algorithm xlr_i2c_algo = {
@@ -214,22 +340,89 @@ static struct i2c_algorithm xlr_i2c_algo = {
.functionality = xlr_func,
};
+static const struct xlr_i2c_config xlr_i2c_config_default = {
+ .status_busy = XLR_I2C_BUS_BUSY,
+ .cfg_extra = 0,
+};
+
+static const struct xlr_i2c_config xlr_i2c_config_tangox = {
+ .flags = XLR_I2C_FLAG_IRQ,
+ .status_busy = 0,
+ .cfg_extra = 1 << 8,
+};
+
+static const struct of_device_id xlr_i2c_dt_ids[] = {
+ {
+ .compatible = "sigma,smp8642-i2c",
+ .data = &xlr_i2c_config_tangox,
+ },
+ { }
+};
+
static int xlr_i2c_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
struct xlr_i2c_private *priv;
struct resource *res;
+ struct clk *clk;
+ unsigned long clk_rate;
+ unsigned long clk_div;
+ u32 busfreq;
+ int irq;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ match = of_match_device(xlr_i2c_dt_ids, &pdev->dev);
+ if (match)
+ priv->cfg = match->data;
+ else
+ priv->cfg = &xlr_i2c_config_default;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->iobase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase);
+ irq = platform_get_irq(pdev, 0);
+
+ if (irq > 0 && (priv->cfg->flags & XLR_I2C_FLAG_IRQ)) {
+ priv->irq = irq;
+
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, 0xf);
+
+ ret = devm_request_irq(&pdev->dev, priv->irq, xlr_i2c_irq,
+ IRQF_SHARED, dev_name(&pdev->dev),
+ priv);
+ if (ret)
+ return ret;
+
+ init_waitqueue_head(&priv->wait);
+ }
+
+ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+ &busfreq))
+ busfreq = 100000;
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(clk)) {
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ return ret;
+
+ clk_rate = clk_get_rate(clk);
+ clk_div = DIV_ROUND_UP(clk_rate, 2 * busfreq);
+ xlr_i2c_wreg(priv->iobase, XLR_I2C_CLKDIV, clk_div);
+
+ clk_disable(clk);
+ priv->clk = clk;
+ }
+
priv->adap.dev.parent = &pdev->dev;
+ priv->adap.dev.of_node = pdev->dev.of_node;
priv->adap.owner = THIS_MODULE;
priv->adap.algo_data = priv;
priv->adap.algo = &xlr_i2c_algo;
@@ -255,6 +448,8 @@ static int xlr_i2c_remove(struct platform_device *pdev)
priv = platform_get_drvdata(pdev);
i2c_del_adapter(&priv->adap);
+ clk_unprepare(priv->clk);
+
return 0;
}
@@ -263,6 +458,7 @@ static struct platform_driver xlr_i2c_driver = {
.remove = xlr_i2c_remove,
.driver = {
.name = "xlr-i2cbus",
+ .of_match_table = xlr_i2c_dt_ids,
},
};
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index ba8eb087f224..ffe715d346d8 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -53,6 +53,7 @@
#include <linux/jump_label.h>
#include <asm/uaccess.h>
#include <linux/err.h>
+#include <linux/property.h>
#include "i2c-core.h"
@@ -1563,6 +1564,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
pm_runtime_no_callbacks(&adap->dev);
+ pm_runtime_enable(&adap->dev);
#ifdef CONFIG_I2C_COMPAT
res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
@@ -1817,6 +1819,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
/* device name is gone after device_unregister */
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
+ pm_runtime_disable(&adap->dev);
+
/* wait until all references to the device are gone
*
* FIXME: This is old code and should ideally be replaced by an
@@ -1839,6 +1843,58 @@ void i2c_del_adapter(struct i2c_adapter *adap)
}
EXPORT_SYMBOL(i2c_del_adapter);
+/**
+ * i2c_parse_fw_timings - get I2C related timing parameters from firmware
+ * @dev: The device to scan for I2C timing properties
+ * @t: the i2c_timings struct to be filled with values
+ * @use_defaults: bool to use sane defaults derived from the I2C specification
+ * when properties are not found, otherwise use 0
+ *
+ * Scan the device for the generic I2C properties describing timing parameters
+ * for the signal and fill the given struct with the results. If a property was
+ * not found and use_defaults was true, then maximum timings are assumed which
+ * are derived from the I2C specification. If use_defaults is not used, the
+ * results will be 0, so drivers can apply their own defaults later. The latter
+ * is mainly intended for avoiding regressions of existing drivers which want
+ * to switch to this function. New drivers almost always should use the defaults.
+ */
+
+void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults)
+{
+ int ret;
+
+ memset(t, 0, sizeof(*t));
+
+ ret = device_property_read_u32(dev, "clock-frequency", &t->bus_freq_hz);
+ if (ret && use_defaults)
+ t->bus_freq_hz = 100000;
+
+ ret = device_property_read_u32(dev, "i2c-scl-rising-time-ns", &t->scl_rise_ns);
+ if (ret && use_defaults) {
+ if (t->bus_freq_hz <= 100000)
+ t->scl_rise_ns = 1000;
+ else if (t->bus_freq_hz <= 400000)
+ t->scl_rise_ns = 300;
+ else
+ t->scl_rise_ns = 120;
+ }
+
+ ret = device_property_read_u32(dev, "i2c-scl-falling-time-ns", &t->scl_fall_ns);
+ if (ret && use_defaults) {
+ if (t->bus_freq_hz <= 400000)
+ t->scl_fall_ns = 300;
+ else
+ t->scl_fall_ns = 120;
+ }
+
+ device_property_read_u32(dev, "i2c-scl-internal-delay-ns", &t->scl_int_delay_ns);
+
+ ret = device_property_read_u32(dev, "i2c-sda-falling-time-ns", &t->sda_fall_ns);
+ if (ret && use_defaults)
+ t->sda_fall_ns = t->scl_fall_ns;
+}
+EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
+
/* ------------------------------------------------------------------------- */
int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index c9cffced00ca..326d07d823a5 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -449,7 +449,7 @@ static void act_open_req_arp_failure(void *handle, struct sk_buff *skb)
{
struct c4iw_ep *ep = handle;
- printk(KERN_ERR MOD "ARP failure duing connect\n");
+ printk(KERN_ERR MOD "ARP failure during connect\n");
kfree_skb(skb);
connect_reply_upcall(ep, -EHOSTUNREACH);
state_set(&ep->com, DEAD);
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 312ffd3d0017..9e385b38debf 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -22,7 +22,8 @@
unsigned long switcher_addr;
struct page **lg_switcher_pages;
-static struct vm_struct *switcher_vma;
+static struct vm_struct *switcher_text_vma;
+static struct vm_struct *switcher_stacks_vma;
/* This One Big lock protects all inter-guest data structures. */
DEFINE_MUTEX(lguest_lock);
@@ -83,54 +84,80 @@ static __init int map_switcher(void)
}
/*
+ * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
+ * It goes in the first page, which we map in momentarily.
+ */
+ memcpy(kmap(lg_switcher_pages[0]), start_switcher_text,
+ end_switcher_text - start_switcher_text);
+ kunmap(lg_switcher_pages[0]);
+
+ /*
* We place the Switcher underneath the fixmap area, which is the
* highest virtual address we can get. This is important, since we
* tell the Guest it can't access this memory, so we want its ceiling
* as high as possible.
*/
- switcher_addr = FIXADDR_START - (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE;
+ switcher_addr = FIXADDR_START - TOTAL_SWITCHER_PAGES*PAGE_SIZE;
/*
- * Now we reserve the "virtual memory area" we want. We might
- * not get it in theory, but in practice it's worked so far.
- * The end address needs +1 because __get_vm_area allocates an
- * extra guard page, so we need space for that.
+ * Now we reserve the "virtual memory area"s we want. We might
+ * not get them in theory, but in practice it's worked so far.
+ *
+ * We want the switcher text to be read-only and executable, and
+ * the stacks to be read-write and non-executable.
*/
- switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
- VM_ALLOC, switcher_addr, switcher_addr
- + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
- if (!switcher_vma) {
+ switcher_text_vma = __get_vm_area(PAGE_SIZE, VM_ALLOC|VM_NO_GUARD,
+ switcher_addr,
+ switcher_addr + PAGE_SIZE);
+
+ if (!switcher_text_vma) {
err = -ENOMEM;
printk("lguest: could not map switcher pages high\n");
goto free_pages;
}
+ switcher_stacks_vma = __get_vm_area(SWITCHER_STACK_PAGES * PAGE_SIZE,
+ VM_ALLOC|VM_NO_GUARD,
+ switcher_addr + PAGE_SIZE,
+ switcher_addr + TOTAL_SWITCHER_PAGES * PAGE_SIZE);
+ if (!switcher_stacks_vma) {
+ err = -ENOMEM;
+ printk("lguest: could not map switcher pages high\n");
+ goto free_text_vma;
+ }
+
/*
* This code actually sets up the pages we've allocated to appear at
* switcher_addr. map_vm_area() takes the vma we allocated above, the
- * kind of pages we're mapping (kernel pages), and a pointer to our
- * array of struct pages.
+ * kind of pages we're mapping (kernel text pages and kernel writable
+ * pages respectively), and a pointer to our array of struct pages.
*/
- err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);
+ err = map_vm_area(switcher_text_vma, PAGE_KERNEL_RX, lg_switcher_pages);
+ if (err) {
+ printk("lguest: text map_vm_area failed: %i\n", err);
+ goto free_vmas;
+ }
+
+ err = map_vm_area(switcher_stacks_vma, PAGE_KERNEL,
+ lg_switcher_pages + SWITCHER_TEXT_PAGES);
if (err) {
- printk("lguest: map_vm_area failed: %i\n", err);
- goto free_vma;
+ printk("lguest: stacks map_vm_area failed: %i\n", err);
+ goto free_vmas;
}
/*
* Now the Switcher is mapped at the right address, we can't fail!
- * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
*/
- memcpy(switcher_vma->addr, start_switcher_text,
- end_switcher_text - start_switcher_text);
-
printk(KERN_INFO "lguest: mapped switcher at %p\n",
- switcher_vma->addr);
+ switcher_text_vma->addr);
/* And we succeeded... */
return 0;
-free_vma:
- vunmap(switcher_vma->addr);
+free_vmas:
+ /* Undoes map_vm_area and __get_vm_area */
+ vunmap(switcher_stacks_vma->addr);
+free_text_vma:
+ vunmap(switcher_text_vma->addr);
free_pages:
i = TOTAL_SWITCHER_PAGES;
free_some_pages:
@@ -148,7 +175,8 @@ static void unmap_switcher(void)
unsigned int i;
/* vunmap() undoes *both* map_vm_area() and __get_vm_area(). */
- vunmap(switcher_vma->addr);
+ vunmap(switcher_text_vma->addr);
+ vunmap(switcher_stacks_vma->addr);
/* Now we just need to free the pages we copied the switcher into */
for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
__free_pages(lg_switcher_pages[i], 0);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index f8e5db0cb5aa..2ea12c6bf659 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -549,13 +549,13 @@ static void *raid0_takeover_raid10(struct mddev *mddev)
* - all mirrors must be already degraded
*/
if (mddev->layout != ((1 << 8) + 2)) {
- printk(KERN_ERR "md/raid0:%s:: Raid0 cannot takover layout: 0x%x\n",
+ printk(KERN_ERR "md/raid0:%s:: Raid0 cannot takeover layout: 0x%x\n",
mdname(mddev),
mddev->layout);
return ERR_PTR(-EINVAL);
}
if (mddev->raid_disks & 1) {
- printk(KERN_ERR "md/raid0:%s: Raid0 cannot takover Raid10 with odd disk number.\n",
+ printk(KERN_ERR "md/raid0:%s: Raid0 cannot takeover Raid10 with odd disk number.\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
index d5837be3e8cf..ea2f3bf7368b 100644
--- a/drivers/media/common/saa7146/saa7146_video.c
+++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -502,7 +502,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuf
/* check if overlay is running */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh != fh) {
- DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
+ DEB_D("refusing to change framebuffer information while overlay is active in another open\n");
return -EBUSY;
}
}
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index feeeb70d841e..ce73a5ec6036 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -685,7 +685,7 @@ static int m88ds3103_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, &client->dev);
if (ret) {
- dev_err(&client->dev, "firmare file '%s' not found\n", fw_file);
+ dev_err(&client->dev, "firmware file '%s' not found\n", fw_file);
goto err;
}
diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c
index 1cf6e52e0105..2b93241d4bc1 100644
--- a/drivers/media/dvb-frontends/si2165.c
+++ b/drivers/media/dvb-frontends/si2165.c
@@ -541,7 +541,7 @@ static int si2165_upload_firmware(struct si2165_state *state)
&offset, block_count);
if (ret < 0) {
dev_err(&state->i2c->dev,
- "%s: firmare could not be uploaded\n",
+ "%s: firmware could not be uploaded\n",
KBUILD_MODNAME);
goto error;
}
@@ -565,7 +565,7 @@ static int si2165_upload_firmware(struct si2165_state *state)
if (len != offset) {
dev_err(&state->i2c->dev,
- "%s: firmare len mismatch %04x != %04x\n",
+ "%s: firmware len mismatch %04x != %04x\n",
KBUILD_MODNAME, len, offset);
ret = -EINVAL;
goto error;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 81e1a5e26efb..525ebfefeee8 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -387,7 +387,7 @@ static int netup_unidvb_dvb_init(struct netup_unidvb_dev *ndev,
vb2_dvb_alloc_frontend(
&ndev->frontends[num], 3) == NULL) {
dev_dbg(&ndev->pci_dev->dev,
- "%s(): unable to to alllocate vb2_dvb_frontend\n",
+ "%s(): unable to allocate vb2_dvb_frontend\n",
__func__);
return -ENOMEM;
}
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c
index 63445ea6b0bf..3f24ecbe2576 100644
--- a/drivers/mfd/88pm80x.c
+++ b/drivers/mfd/88pm80x.c
@@ -135,7 +135,7 @@ EXPORT_SYMBOL_GPL(pm80x_deinit);
#ifdef CONFIG_PM_SLEEP
static int pm80x_suspend(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct pm80x_chip *chip = i2c_get_clientdata(client);
if (chip && chip->wu_flag)
@@ -147,7 +147,7 @@ static int pm80x_suspend(struct device *dev)
static int pm80x_resume(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct pm80x_chip *chip = i2c_get_clientdata(client);
if (chip && chip->wu_flag)
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
index 3269a9990b24..25e1aafae60c 100644
--- a/drivers/mfd/88pm860x-core.c
+++ b/drivers/mfd/88pm860x-core.c
@@ -705,10 +705,12 @@ int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client)
chip->osc_status);
mutex_lock(&chip->osc_lock);
- /*Update voting status */
+ /* Update voting status */
chip->osc_vote &= ~(client);
- /* If reference group is off and this is the last client to release
- * - turn off */
+ /*
+ * If reference group is off and this is the last client to release
+ * - turn off
+ */
if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) &&
(chip->osc_vote == REF_GP_NO_CLIENTS)) {
chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN;
@@ -1218,7 +1220,7 @@ static int pm860x_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
static int pm860x_suspend(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct pm860x_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
@@ -1228,7 +1230,7 @@ static int pm860x_suspend(struct device *dev)
static int pm860x_resume(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct pm860x_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
@@ -1265,6 +1267,7 @@ static struct i2c_driver pm860x_driver = {
static int __init pm860x_i2c_init(void)
{
int ret;
+
ret = i2c_add_driver(&pm860x_driver);
if (ret != 0)
pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 4d92df6ef9fe..9ca66de0c1c1 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -211,7 +211,7 @@ config MFD_DA9062
of the device.
config MFD_DA9063
- bool "Dialog Semiconductor DA9063 PMIC Support"
+ tristate "Dialog Semiconductor DA9063 PMIC Support"
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
@@ -1370,24 +1370,30 @@ config MFD_ARIZONA
bool
config MFD_ARIZONA_I2C
- tristate "Wolfson Microelectronics Arizona platform with I2C"
+ tristate "Cirrus Logic/Wolfson Microelectronics Arizona platform with I2C"
select MFD_ARIZONA
select MFD_CORE
select REGMAP_I2C
depends on I2C
help
- Support for the Wolfson Microelectronics Arizona platform audio SoC
- core functionality controlled via I2C.
+ Support for the Cirrus Logic/Wolfson Microelectronics Arizona platform
+ audio SoC core functionality controlled via I2C.
config MFD_ARIZONA_SPI
- tristate "Wolfson Microelectronics Arizona platform with SPI"
+ tristate "Cirrus Logic/Wolfson Microelectronics Arizona platform with SPI"
select MFD_ARIZONA
select MFD_CORE
select REGMAP_SPI
depends on SPI_MASTER
help
- Support for the Wolfson Microelectronics Arizona platform audio SoC
- core functionality controlled via I2C.
+ Support for the Cirrus Logic/Wolfson Microelectronics Arizona platform
+ audio SoC core functionality controlled via I2C.
+
+config MFD_CS47L24
+ bool "Cirrus Logic CS47L24 and WM1831"
+ depends on MFD_ARIZONA
+ help
+ Support for Cirrus Logic CS47L24 and WM1831 low power audio SoC
config MFD_WM5102
bool "Wolfson Microelectronics WM5102"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a8b76b81b467..0f230a6103f8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -51,6 +51,9 @@ endif
ifeq ($(CONFIG_MFD_WM8998),y)
obj-$(CONFIG_MFD_ARIZONA) += wm8998-tables.o
endif
+ifeq ($(CONFIG_MFD_CS47L24),y)
+obj-$(CONFIG_MFD_ARIZONA) += cs47l24-tables.o
+endif
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
wm831x-objs += wm831x-auxadc.o
@@ -61,7 +64,8 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
-obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o wm8994-regmap.o
+wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o
+obj-$(CONFIG_MFD_WM8994) += wm8994.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 29b6a2d4ac72..3ba19a45f199 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -373,11 +373,8 @@ static int aat2870_i2c_probe(struct i2c_client *client,
aat2870 = devm_kzalloc(&client->dev, sizeof(struct aat2870_data),
GFP_KERNEL);
- if (!aat2870) {
- dev_err(&client->dev,
- "Failed to allocate memory for aat2870\n");
+ if (!aat2870)
return -ENOMEM;
- }
aat2870->dev = &client->dev;
dev_set_drvdata(aat2870->dev, aat2870);
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index f0afb44271f8..6a5a98806cb8 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -381,9 +381,11 @@ static int ab3100_event_registers_startup_state_get(struct device *dev,
u8 *event)
{
struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
+
if (!ab3100->startup_events_read)
return -EAGAIN; /* Try again later */
memcpy(event, ab3100->startup_events, 3);
+
return 0;
}
@@ -858,10 +860,8 @@ static int ab3100_probe(struct i2c_client *client,
int i;
ab3100 = devm_kzalloc(&client->dev, sizeof(struct ab3100), GFP_KERNEL);
- if (!ab3100) {
- dev_err(&client->dev, "could not allocate AB3100 device\n");
+ if (!ab3100)
return -ENOMEM;
- }
/* Initialize data structure */
mutex_init(&ab3100->access_mutex);
@@ -883,20 +883,17 @@ static int ab3100_probe(struct i2c_client *client,
for (i = 0; ids[i].id != 0x0; i++) {
if (ids[i].id == ab3100->chip_id) {
- if (ids[i].name != NULL) {
- snprintf(&ab3100->chip_name[0],
- sizeof(ab3100->chip_name) - 1,
- "AB3100 %s",
- ids[i].name);
+ if (ids[i].name)
break;
- } else {
- dev_err(&client->dev,
- "AB3000 is not supported\n");
- goto exit_no_detect;
- }
+
+ dev_err(&client->dev, "AB3000 is not supported\n");
+ goto exit_no_detect;
}
}
+ snprintf(&ab3100->chip_name[0],
+ sizeof(ab3100->chip_name) - 1, "AB3100 %s", ids[i].name);
+
if (ids[i].id == 0x0) {
dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
ab3100->chip_id);
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index f391c5fee1b0..55b207a4b336 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -188,10 +188,9 @@ static int __init ab3100_otp_probe(struct platform_device *pdev)
int i;
otp = devm_kzalloc(&pdev->dev, sizeof(struct ab3100_otp), GFP_KERNEL);
- if (!otp) {
- dev_err(&pdev->dev, "could not allocate AB3100 OTP device\n");
+ if (!otp)
return -ENOMEM;
- }
+
otp->dev = &pdev->dev;
/* Replace platform data coming in with a local struct */
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index fefbe4cfa61d..f3d689176fc2 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -113,7 +113,7 @@
#define AB8500_SWITCH_OFF_STATUS 0x00
#define AB8500_TURN_ON_STATUS 0x00
-#define AB8505_TURN_ON_STATUS_2 0x04
+#define AB8505_TURN_ON_STATUS_2 0x04
#define AB8500_CH_USBCH_STAT1_REG 0x02
#define VBUS_DET_DBNC100 0x02
@@ -211,7 +211,7 @@ static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
/*
* Put the u8 bank and u8 register together into a an u16.
* The bank on higher 8 bits and register in lower 8 bits.
- * */
+ */
u16 addr = ((u16)bank) << 8 | reg;
dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
@@ -243,8 +243,6 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
u8 reg, u8 *value)
{
int ret;
- /* put the u8 bank and u8 reg together into a an u16.
- * bank on higher 8 bits and reg in lower */
u16 addr = ((u16)bank) << 8 | reg;
mutex_lock(&ab8500->lock);
@@ -278,8 +276,6 @@ static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
u8 reg, u8 bitmask, u8 bitvalues)
{
int ret;
- /* put the u8 bank and u8 reg together into a an u16.
- * bank on higher 8 bits and reg in lower */
u16 addr = ((u16)bank) << 8 | reg;
mutex_lock(&ab8500->lock);
@@ -449,12 +445,12 @@ static void update_latch_offset(u8 *offset, int i)
{
/* Fix inconsistent ITFromLatch25 bit mapping... */
if (unlikely(*offset == 17))
- *offset = 24;
+ *offset = 24;
/* Fix inconsistent ab8540 bit mapping... */
if (unlikely(*offset == 16))
- *offset = 25;
+ *offset = 25;
if ((i == 3) && (*offset >= 24))
- *offset += 2;
+ *offset += 2;
}
static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
@@ -590,12 +586,12 @@ static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
/* If ->irq_base is zero this will give a linear mapping */
ab8500->domain = irq_domain_add_simple(ab8500->dev->of_node,
- num_irqs, 0,
- &ab8500_irq_ops, ab8500);
+ num_irqs, 0,
+ &ab8500_irq_ops, ab8500);
if (!ab8500->domain) {
dev_err(ab8500->dev, "Failed to create irqdomain\n");
- return -ENOSYS;
+ return -ENODEV;
}
return 0;
@@ -609,442 +605,28 @@ int ab8500_suspend(struct ab8500 *ab8500)
return 0;
}
-static struct resource ab8500_gpadc_resources[] = {
- {
- .name = "HW_CONV_END",
- .start = AB8500_INT_GP_HW_ADC_CONV_END,
- .end = AB8500_INT_GP_HW_ADC_CONV_END,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "SW_CONV_END",
- .start = AB8500_INT_GP_SW_ADC_CONV_END,
- .end = AB8500_INT_GP_SW_ADC_CONV_END,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8505_gpadc_resources[] = {
- {
- .name = "SW_CONV_END",
- .start = AB8500_INT_GP_SW_ADC_CONV_END,
- .end = AB8500_INT_GP_SW_ADC_CONV_END,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_rtc_resources[] = {
- {
- .name = "60S",
- .start = AB8500_INT_RTC_60S,
- .end = AB8500_INT_RTC_60S,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ALARM",
- .start = AB8500_INT_RTC_ALARM,
- .end = AB8500_INT_RTC_ALARM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8540_rtc_resources[] = {
- {
- .name = "1S",
- .start = AB8540_INT_RTC_1S,
- .end = AB8540_INT_RTC_1S,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ALARM",
- .start = AB8500_INT_RTC_ALARM,
- .end = AB8500_INT_RTC_ALARM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_poweronkey_db_resources[] = {
- {
- .name = "ONKEY_DBF",
- .start = AB8500_INT_PON_KEY1DB_F,
- .end = AB8500_INT_PON_KEY1DB_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ONKEY_DBR",
- .start = AB8500_INT_PON_KEY1DB_R,
- .end = AB8500_INT_PON_KEY1DB_R,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_av_acc_detect_resources[] = {
- {
- .name = "ACC_DETECT_1DB_F",
- .start = AB8500_INT_ACC_DETECT_1DB_F,
- .end = AB8500_INT_ACC_DETECT_1DB_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ACC_DETECT_1DB_R",
- .start = AB8500_INT_ACC_DETECT_1DB_R,
- .end = AB8500_INT_ACC_DETECT_1DB_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ACC_DETECT_21DB_F",
- .start = AB8500_INT_ACC_DETECT_21DB_F,
- .end = AB8500_INT_ACC_DETECT_21DB_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ACC_DETECT_21DB_R",
- .start = AB8500_INT_ACC_DETECT_21DB_R,
- .end = AB8500_INT_ACC_DETECT_21DB_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ACC_DETECT_22DB_F",
- .start = AB8500_INT_ACC_DETECT_22DB_F,
- .end = AB8500_INT_ACC_DETECT_22DB_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ACC_DETECT_22DB_R",
- .start = AB8500_INT_ACC_DETECT_22DB_R,
- .end = AB8500_INT_ACC_DETECT_22DB_R,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_charger_resources[] = {
- {
- .name = "MAIN_CH_UNPLUG_DET",
- .start = AB8500_INT_MAIN_CH_UNPLUG_DET,
- .end = AB8500_INT_MAIN_CH_UNPLUG_DET,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "MAIN_CHARGE_PLUG_DET",
- .start = AB8500_INT_MAIN_CH_PLUG_DET,
- .end = AB8500_INT_MAIN_CH_PLUG_DET,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_R",
- .start = AB8500_INT_VBUS_DET_R,
- .end = AB8500_INT_VBUS_DET_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_F",
- .start = AB8500_INT_VBUS_DET_F,
- .end = AB8500_INT_VBUS_DET_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_LINK_STATUS",
- .start = AB8500_INT_USB_LINK_STATUS,
- .end = AB8500_INT_USB_LINK_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_OVV",
- .start = AB8500_INT_VBUS_OVV,
- .end = AB8500_INT_VBUS_OVV,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_CH_TH_PROT_R",
- .start = AB8500_INT_USB_CH_TH_PROT_R,
- .end = AB8500_INT_USB_CH_TH_PROT_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_CH_TH_PROT_F",
- .start = AB8500_INT_USB_CH_TH_PROT_F,
- .end = AB8500_INT_USB_CH_TH_PROT_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "MAIN_EXT_CH_NOT_OK",
- .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
- .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "MAIN_CH_TH_PROT_R",
- .start = AB8500_INT_MAIN_CH_TH_PROT_R,
- .end = AB8500_INT_MAIN_CH_TH_PROT_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "MAIN_CH_TH_PROT_F",
- .start = AB8500_INT_MAIN_CH_TH_PROT_F,
- .end = AB8500_INT_MAIN_CH_TH_PROT_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_CHARGER_NOT_OKR",
- .start = AB8500_INT_USB_CHARGER_NOT_OKR,
- .end = AB8500_INT_USB_CHARGER_NOT_OKR,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CH_WD_EXP",
- .start = AB8500_INT_CH_WD_EXP,
- .end = AB8500_INT_CH_WD_EXP,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_CH_DROP_END",
- .start = AB8500_INT_VBUS_CH_DROP_END,
- .end = AB8500_INT_VBUS_CH_DROP_END,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_btemp_resources[] = {
- {
- .name = "BAT_CTRL_INDB",
- .start = AB8500_INT_BAT_CTRL_INDB,
- .end = AB8500_INT_BAT_CTRL_INDB,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BTEMP_LOW",
- .start = AB8500_INT_BTEMP_LOW,
- .end = AB8500_INT_BTEMP_LOW,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BTEMP_HIGH",
- .start = AB8500_INT_BTEMP_HIGH,
- .end = AB8500_INT_BTEMP_HIGH,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BTEMP_LOW_MEDIUM",
- .start = AB8500_INT_BTEMP_LOW_MEDIUM,
- .end = AB8500_INT_BTEMP_LOW_MEDIUM,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BTEMP_MEDIUM_HIGH",
- .start = AB8500_INT_BTEMP_MEDIUM_HIGH,
- .end = AB8500_INT_BTEMP_MEDIUM_HIGH,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_fg_resources[] = {
- {
- .name = "NCONV_ACCU",
- .start = AB8500_INT_CCN_CONV_ACC,
- .end = AB8500_INT_CCN_CONV_ACC,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BATT_OVV",
- .start = AB8500_INT_BATT_OVV,
- .end = AB8500_INT_BATT_OVV,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "LOW_BAT_F",
- .start = AB8500_INT_LOW_BAT_F,
- .end = AB8500_INT_LOW_BAT_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "LOW_BAT_R",
- .start = AB8500_INT_LOW_BAT_R,
- .end = AB8500_INT_LOW_BAT_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CC_INT_CALIB",
- .start = AB8500_INT_CC_INT_CALIB,
- .end = AB8500_INT_CC_INT_CALIB,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CCEOC",
- .start = AB8500_INT_CCEOC,
- .end = AB8500_INT_CCEOC,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_chargalg_resources[] = {};
-
-#ifdef CONFIG_DEBUG_FS
-static struct resource ab8500_debug_resources[] = {
- {
- .name = "IRQ_AB8500",
- /*
- * Number will be filled in. NOTE: this is deliberately
- * not flagged as an IRQ in ordet to avoid remapping using
- * the irqdomain in the MFD core, so that this IRQ passes
- * unremapped to the debug code.
- */
- },
- {
- .name = "IRQ_FIRST",
- .start = AB8500_INT_MAIN_EXT_CH_NOT_OK,
- .end = AB8500_INT_MAIN_EXT_CH_NOT_OK,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "IRQ_LAST",
- .start = AB8500_INT_XTAL32K_KO,
- .end = AB8500_INT_XTAL32K_KO,
- .flags = IORESOURCE_IRQ,
- },
-};
-#endif
-
-static struct resource ab8500_usb_resources[] = {
- {
- .name = "ID_WAKEUP_R",
- .start = AB8500_INT_ID_WAKEUP_R,
- .end = AB8500_INT_ID_WAKEUP_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ID_WAKEUP_F",
- .start = AB8500_INT_ID_WAKEUP_F,
- .end = AB8500_INT_ID_WAKEUP_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_F",
- .start = AB8500_INT_VBUS_DET_F,
- .end = AB8500_INT_VBUS_DET_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_R",
- .start = AB8500_INT_VBUS_DET_R,
- .end = AB8500_INT_VBUS_DET_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_LINK_STATUS",
- .start = AB8500_INT_USB_LINK_STATUS,
- .end = AB8500_INT_USB_LINK_STATUS,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_ADP_PROBE_PLUG",
- .start = AB8500_INT_ADP_PROBE_PLUG,
- .end = AB8500_INT_ADP_PROBE_PLUG,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "USB_ADP_PROBE_UNPLUG",
- .start = AB8500_INT_ADP_PROBE_UNPLUG,
- .end = AB8500_INT_ADP_PROBE_UNPLUG,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8505_iddet_resources[] = {
- {
- .name = "KeyDeglitch",
- .start = AB8505_INT_KEYDEGLITCH,
- .end = AB8505_INT_KEYDEGLITCH,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "KP",
- .start = AB8505_INT_KP,
- .end = AB8505_INT_KP,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "IKP",
- .start = AB8505_INT_IKP,
- .end = AB8505_INT_IKP,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "IKR",
- .start = AB8505_INT_IKR,
- .end = AB8505_INT_IKR,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "KeyStuck",
- .start = AB8505_INT_KEYSTUCK,
- .end = AB8505_INT_KEYSTUCK,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_R",
- .start = AB8500_INT_VBUS_DET_R,
- .end = AB8500_INT_VBUS_DET_R,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBUS_DET_F",
- .start = AB8500_INT_VBUS_DET_F,
- .end = AB8500_INT_VBUS_DET_F,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ID_DET_PLUGR",
- .start = AB8500_INT_ID_DET_PLUGR,
- .end = AB8500_INT_ID_DET_PLUGR,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ID_DET_PLUGF",
- .start = AB8500_INT_ID_DET_PLUGF,
- .end = AB8500_INT_ID_DET_PLUGF,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource ab8500_temp_resources[] = {
- {
- .name = "ABX500_TEMP_WARM",
- .start = AB8500_INT_TEMP_WARM,
- .end = AB8500_INT_TEMP_WARM,
- .flags = IORESOURCE_IRQ,
- },
-};
-
static const struct mfd_cell ab8500_bm_devs[] = {
{
.name = "ab8500-charger",
.of_compatible = "stericsson,ab8500-charger",
- .num_resources = ARRAY_SIZE(ab8500_charger_resources),
- .resources = ab8500_charger_resources,
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
{
.name = "ab8500-btemp",
.of_compatible = "stericsson,ab8500-btemp",
- .num_resources = ARRAY_SIZE(ab8500_btemp_resources),
- .resources = ab8500_btemp_resources,
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
{
.name = "ab8500-fg",
.of_compatible = "stericsson,ab8500-fg",
- .num_resources = ARRAY_SIZE(ab8500_fg_resources),
- .resources = ab8500_fg_resources,
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
{
.name = "ab8500-chargalg",
.of_compatible = "stericsson,ab8500-chargalg",
- .num_resources = ARRAY_SIZE(ab8500_chargalg_resources),
- .resources = ab8500_chargalg_resources,
.platform_data = &ab8500_bm_data,
.pdata_size = sizeof(ab8500_bm_data),
},
@@ -1055,8 +637,6 @@ static const struct mfd_cell ab8500_devs[] = {
{
.name = "ab8500-debug",
.of_compatible = "stericsson,ab8500-debug",
- .num_resources = ARRAY_SIZE(ab8500_debug_resources),
- .resources = ab8500_debug_resources,
},
#endif
{
@@ -1078,27 +658,19 @@ static const struct mfd_cell ab8500_devs[] = {
{
.name = "ab8500-gpadc",
.of_compatible = "stericsson,ab8500-gpadc",
- .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
- .resources = ab8500_gpadc_resources,
},
{
.name = "ab8500-rtc",
.of_compatible = "stericsson,ab8500-rtc",
- .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
- .resources = ab8500_rtc_resources,
},
{
.name = "ab8500-acc-det",
.of_compatible = "stericsson,ab8500-acc-det",
- .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
- .resources = ab8500_av_acc_detect_resources,
},
{
.name = "ab8500-poweron-key",
.of_compatible = "stericsson,ab8500-poweron-key",
- .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
- .resources = ab8500_poweronkey_db_resources,
},
{
.name = "ab8500-pwm",
@@ -1126,14 +698,10 @@ static const struct mfd_cell ab8500_devs[] = {
{
.name = "abx500-temp",
.of_compatible = "stericsson,abx500-temp",
- .num_resources = ARRAY_SIZE(ab8500_temp_resources),
- .resources = ab8500_temp_resources,
},
{
.name = "ab8500-usb",
.of_compatible = "stericsson,ab8500-usb",
- .num_resources = ARRAY_SIZE(ab8500_usb_resources),
- .resources = ab8500_usb_resources,
},
{
.name = "ab8500-codec",
@@ -1145,8 +713,6 @@ static const struct mfd_cell ab9540_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
- .num_resources = ARRAY_SIZE(ab8500_debug_resources),
- .resources = ab8500_debug_resources,
},
#endif
{
@@ -1165,23 +731,15 @@ static const struct mfd_cell ab9540_devs[] = {
{
.name = "ab8500-gpadc",
.of_compatible = "stericsson,ab8500-gpadc",
- .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
- .resources = ab8500_gpadc_resources,
},
{
.name = "ab8500-rtc",
- .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
- .resources = ab8500_rtc_resources,
},
{
.name = "ab8500-acc-det",
- .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
- .resources = ab8500_av_acc_detect_resources,
},
{
.name = "ab8500-poweron-key",
- .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
- .resources = ab8500_poweronkey_db_resources,
},
{
.name = "ab8500-pwm",
@@ -1189,8 +747,6 @@ static const struct mfd_cell ab9540_devs[] = {
},
{
.name = "abx500-temp",
- .num_resources = ARRAY_SIZE(ab8500_temp_resources),
- .resources = ab8500_temp_resources,
},
{
.name = "pinctrl-ab9540",
@@ -1198,16 +754,12 @@ static const struct mfd_cell ab9540_devs[] = {
},
{
.name = "ab9540-usb",
- .num_resources = ARRAY_SIZE(ab8500_usb_resources),
- .resources = ab8500_usb_resources,
},
{
.name = "ab9540-codec",
},
{
.name = "ab-iddet",
- .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
- .resources = ab8505_iddet_resources,
},
};
@@ -1216,8 +768,6 @@ static const struct mfd_cell ab8505_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
- .num_resources = ARRAY_SIZE(ab8500_debug_resources),
- .resources = ab8500_debug_resources,
},
#endif
{
@@ -1233,23 +783,15 @@ static const struct mfd_cell ab8505_devs[] = {
{
.name = "ab8500-gpadc",
.of_compatible = "stericsson,ab8500-gpadc",
- .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
- .resources = ab8505_gpadc_resources,
},
{
.name = "ab8500-rtc",
- .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
- .resources = ab8500_rtc_resources,
},
{
.name = "ab8500-acc-det",
- .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
- .resources = ab8500_av_acc_detect_resources,
},
{
.name = "ab8500-poweron-key",
- .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
- .resources = ab8500_poweronkey_db_resources,
},
{
.name = "ab8500-pwm",
@@ -1260,16 +802,12 @@ static const struct mfd_cell ab8505_devs[] = {
},
{
.name = "ab8500-usb",
- .num_resources = ARRAY_SIZE(ab8500_usb_resources),
- .resources = ab8500_usb_resources,
},
{
.name = "ab8500-codec",
},
{
.name = "ab-iddet",
- .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
- .resources = ab8505_iddet_resources,
},
};
@@ -1277,8 +815,6 @@ static const struct mfd_cell ab8540_devs[] = {
#ifdef CONFIG_DEBUG_FS
{
.name = "ab8500-debug",
- .num_resources = ARRAY_SIZE(ab8500_debug_resources),
- .resources = ab8500_debug_resources,
},
#endif
{
@@ -1297,18 +833,12 @@ static const struct mfd_cell ab8540_devs[] = {
{
.name = "ab8500-gpadc",
.of_compatible = "stericsson,ab8500-gpadc",
- .num_resources = ARRAY_SIZE(ab8505_gpadc_resources),
- .resources = ab8505_gpadc_resources,
},
{
.name = "ab8500-acc-det",
- .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources),
- .resources = ab8500_av_acc_detect_resources,
},
{
.name = "ab8500-poweron-key",
- .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
- .resources = ab8500_poweronkey_db_resources,
},
{
.name = "ab8500-pwm",
@@ -1316,24 +846,18 @@ static const struct mfd_cell ab8540_devs[] = {
},
{
.name = "abx500-temp",
- .num_resources = ARRAY_SIZE(ab8500_temp_resources),
- .resources = ab8500_temp_resources,
},
{
.name = "pinctrl-ab8540",
},
{
.name = "ab8540-usb",
- .num_resources = ARRAY_SIZE(ab8500_usb_resources),
- .resources = ab8500_usb_resources,
},
{
.name = "ab8540-codec",
},
{
.name = "ab-iddet",
- .num_resources = ARRAY_SIZE(ab8505_iddet_resources),
- .resources = ab8505_iddet_resources,
},
};
@@ -1341,8 +865,6 @@ static const struct mfd_cell ab8540_cut1_devs[] = {
{
.name = "ab8500-rtc",
.of_compatible = "stericsson,ab8500-rtc",
- .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
- .resources = ab8500_rtc_resources,
},
};
@@ -1350,8 +872,6 @@ static const struct mfd_cell ab8540_cut2_devs[] = {
{
.name = "ab8540-rtc",
.of_compatible = "stericsson,ab8540-rtc",
- .num_resources = ARRAY_SIZE(ab8540_rtc_resources),
- .resources = ab8540_rtc_resources,
},
};
@@ -1549,7 +1069,7 @@ static struct attribute_group ab9540_attr_group = {
static int ab8500_probe(struct platform_device *pdev)
{
- static const char *switch_off_status[] = {
+ static const char * const switch_off_status[] = {
"Swoff bit programming",
"Thermal protection activation",
"Vbat lower then BattOk falling threshold",
@@ -1558,7 +1078,7 @@ static int ab8500_probe(struct platform_device *pdev)
"Battery level lower than power on reset threshold",
"Power on key 1 pressed longer than 10 seconds",
"DB8500 thermal shutdown"};
- static const char *turn_on_status[] = {
+ static const char * const turn_on_status[] = {
"Battery rising (Vbat)",
"Power On Key 1 dbF",
"Power On Key 2 dbF",
@@ -1750,12 +1270,6 @@ static int ab8500_probe(struct platform_device *pdev)
if (ret)
return ret;
-#ifdef CONFIG_DEBUG_FS
- /* Pass to debugfs */
- ab8500_debug_resources[0].start = ab8500->irq;
- ab8500_debug_resources[0].end = ab8500->irq;
-#endif
-
if (is_ab9540(ab8500))
ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
ARRAY_SIZE(ab9540_devs), NULL,
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index 0236cd7cdce4..69d9fffe5b5c 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -242,8 +242,10 @@ static struct ab8500_prcmu_ranges ab8500_debug_ranges[AB8500_NUM_BANKS] = {
.first = 0x40,
.last = 0x44,
},
- /* 0x80-0x8B is SIM registers and should
- * not be accessed from here */
+ /*
+ * 0x80-0x8B are SIM registers and should
+ * not be accessed from here
+ */
},
},
[AB8500_USB] = {
@@ -587,8 +589,10 @@ static struct ab8500_prcmu_ranges ab8505_debug_ranges[AB8500_NUM_BANKS] = {
.first = 0x40,
.last = 0x48,
},
- /* 0x80-0x8B is SIM registers and should
- * not be accessed from here */
+ /*
+ * 0x80-0x8B are SIM registers and should
+ * not be accessed from here
+ */
},
},
[AB8500_USB] = {
@@ -1306,8 +1310,10 @@ static int ab8500_registers_print(struct device *dev, u32 bank,
if (s) {
seq_printf(s, " [0x%02X/0x%02X]: 0x%02X\n",
bank, reg, value);
- /* Error is not returned here since
- * the output is wanted in any case */
+ /*
+ * Error is not returned here since
+ * the output is wanted in any case
+ */
if (seq_has_overflowed(s))
return 0;
} else {
@@ -2740,10 +2746,9 @@ static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg,
*cfg = loc;
#ifdef ABB_HWREG_DEBUG
- pr_warn("HWREG request: %s, %s,\n"
- " addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n",
- (write) ? "write" : "read",
- REG_FMT_DEC(cfg) ? "decimal" : "hexa",
+ pr_warn("HWREG request: %s, %s,\n", (write) ? "write" : "read",
+ REG_FMT_DEC(cfg) ? "decimal" : "hexa");
+ pr_warn(" addr=0x%08X, mask=0x%X, shift=%d" "value=0x%X\n",
cfg->addr, cfg->mask, cfg->shift, val);
#endif
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index c51c1b188d64..97dcadc8fa8b 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -49,61 +49,61 @@
* OTP register offsets
* Bank : 0x15
*/
-#define AB8500_GPADC_CAL_1 0x0F
-#define AB8500_GPADC_CAL_2 0x10
-#define AB8500_GPADC_CAL_3 0x11
-#define AB8500_GPADC_CAL_4 0x12
-#define AB8500_GPADC_CAL_5 0x13
-#define AB8500_GPADC_CAL_6 0x14
-#define AB8500_GPADC_CAL_7 0x15
+#define AB8500_GPADC_CAL_1 0x0F
+#define AB8500_GPADC_CAL_2 0x10
+#define AB8500_GPADC_CAL_3 0x11
+#define AB8500_GPADC_CAL_4 0x12
+#define AB8500_GPADC_CAL_5 0x13
+#define AB8500_GPADC_CAL_6 0x14
+#define AB8500_GPADC_CAL_7 0x15
/* New calibration for 8540 */
#define AB8540_GPADC_OTP4_REG_7 0x38
#define AB8540_GPADC_OTP4_REG_6 0x39
#define AB8540_GPADC_OTP4_REG_5 0x3A
/* gpadc constants */
-#define EN_VINTCORE12 0x04
-#define EN_VTVOUT 0x02
-#define EN_GPADC 0x01
-#define DIS_GPADC 0x00
-#define AVG_1 0x00
-#define AVG_4 0x20
-#define AVG_8 0x40
-#define AVG_16 0x60
-#define ADC_SW_CONV 0x04
-#define EN_ICHAR 0x80
-#define BTEMP_PULL_UP 0x08
-#define EN_BUF 0x40
-#define DIS_ZERO 0x00
-#define GPADC_BUSY 0x01
-#define EN_FALLING 0x10
-#define EN_TRIG_EDGE 0x02
-#define EN_VBIAS_XTAL_TEMP 0x02
+#define EN_VINTCORE12 0x04
+#define EN_VTVOUT 0x02
+#define EN_GPADC 0x01
+#define DIS_GPADC 0x00
+#define AVG_1 0x00
+#define AVG_4 0x20
+#define AVG_8 0x40
+#define AVG_16 0x60
+#define ADC_SW_CONV 0x04
+#define EN_ICHAR 0x80
+#define BTEMP_PULL_UP 0x08
+#define EN_BUF 0x40
+#define DIS_ZERO 0x00
+#define GPADC_BUSY 0x01
+#define EN_FALLING 0x10
+#define EN_TRIG_EDGE 0x02
+#define EN_VBIAS_XTAL_TEMP 0x02
/* GPADC constants from AB8500 spec, UM0836 */
-#define ADC_RESOLUTION 1024
-#define ADC_CH_BTEMP_MIN 0
-#define ADC_CH_BTEMP_MAX 1350
-#define ADC_CH_DIETEMP_MIN 0
-#define ADC_CH_DIETEMP_MAX 1350
-#define ADC_CH_CHG_V_MIN 0
-#define ADC_CH_CHG_V_MAX 20030
-#define ADC_CH_ACCDET2_MIN 0
-#define ADC_CH_ACCDET2_MAX 2500
-#define ADC_CH_VBAT_MIN 2300
-#define ADC_CH_VBAT_MAX 4800
-#define ADC_CH_CHG_I_MIN 0
-#define ADC_CH_CHG_I_MAX 1500
-#define ADC_CH_BKBAT_MIN 0
-#define ADC_CH_BKBAT_MAX 3200
+#define ADC_RESOLUTION 1024
+#define ADC_CH_BTEMP_MIN 0
+#define ADC_CH_BTEMP_MAX 1350
+#define ADC_CH_DIETEMP_MIN 0
+#define ADC_CH_DIETEMP_MAX 1350
+#define ADC_CH_CHG_V_MIN 0
+#define ADC_CH_CHG_V_MAX 20030
+#define ADC_CH_ACCDET2_MIN 0
+#define ADC_CH_ACCDET2_MAX 2500
+#define ADC_CH_VBAT_MIN 2300
+#define ADC_CH_VBAT_MAX 4800
+#define ADC_CH_CHG_I_MIN 0
+#define ADC_CH_CHG_I_MAX 1500
+#define ADC_CH_BKBAT_MIN 0
+#define ADC_CH_BKBAT_MAX 3200
/* GPADC constants from AB8540 spec */
-#define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat*/
-#define ADC_CH_IBAT_MAX 6000
-#define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat*/
-#define ADC_CH_IBAT_MAX_V 60
-#define IBAT_VDROP_L (-56) /* mV */
-#define IBAT_VDROP_H 56
+#define ADC_CH_IBAT_MIN (-6000) /* mA range measured by ADC for ibat */
+#define ADC_CH_IBAT_MAX 6000
+#define ADC_CH_IBAT_MIN_V (-60) /* mV range measured by ADC for ibat */
+#define ADC_CH_IBAT_MAX_V 60
+#define IBAT_VDROP_L (-56) /* mV */
+#define IBAT_VDROP_H 56
/* This is used to not lose precision when dividing to get gain and offset */
#define CALIB_SCALE 1000
@@ -179,7 +179,7 @@ struct ab8500_gpadc *ab8500_gpadc_get(char *name)
list_for_each_entry(gpadc, &ab8500_gpadc_list, node) {
if (!strcmp(name, dev_name(gpadc->dev)))
- return gpadc;
+ return gpadc;
}
return ERR_PTR(-ENOENT);
@@ -315,11 +315,12 @@ int ab8500_gpadc_sw_hw_convert(struct ab8500_gpadc *gpadc, u8 channel,
ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
trig_edge, trig_timer, conv_type);
-/* On failure retry a second time */
+
+ /* On failure retry a second time */
if (ad_value < 0)
ad_value = ab8500_gpadc_read_raw(gpadc, channel, avg_sample,
trig_edge, trig_timer, conv_type);
-if (ad_value < 0) {
+ if (ad_value < 0) {
dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n",
channel);
return ad_value;
@@ -327,8 +328,9 @@ if (ad_value < 0) {
voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value);
if (voltage < 0)
- dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:"
- " %d AD: 0x%x\n", channel, ad_value);
+ dev_err(gpadc->dev,
+ "GPADC to voltage conversion failed ch: %d AD: 0x%x\n",
+ channel, ad_value);
return voltage;
}
@@ -348,10 +350,9 @@ EXPORT_SYMBOL(ab8500_gpadc_sw_hw_convert);
int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
u8 avg_sample, u8 trig_edge, u8 trig_timer, u8 conv_type)
{
- int raw_data;
- raw_data = ab8500_gpadc_double_read_raw(gpadc, channel,
- avg_sample, trig_edge, trig_timer, conv_type, NULL);
- return raw_data;
+ return ab8500_gpadc_double_read_raw(gpadc, channel, avg_sample,
+ trig_edge, trig_timer, conv_type,
+ NULL);
}
int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
@@ -388,7 +389,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
goto out;
if (!(val & GPADC_BUSY))
break;
- msleep(10);
+ msleep(20);
} while (++looplimit < 10);
if (looplimit >= 10 && (val & GPADC_BUSY)) {
dev_err(gpadc->dev, "gpadc_conversion: GPADC busy");
@@ -421,8 +422,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
val_reg1 |= EN_TRIG_EDGE;
if (trig_edge)
val_reg1 |= EN_FALLING;
- }
- else
+ } else
ret = abx500_set_register_interruptible(gpadc->dev,
AB8500_GPADC, AB8500_GPADC_CTRL2_REG, val);
if (ret < 0) {
@@ -449,7 +449,7 @@ int ab8500_gpadc_double_read_raw(struct ab8500_gpadc *gpadc, u8 channel,
* remove when hardware will be availible
*/
delay_min = 1000; /* Delay in micro seconds */
- delay_max = 10000; /* large range to optimise sleep mode */
+ delay_max = 10000; /* large range optimises sleepmode */
break;
}
/* Intentional fallthrough */
@@ -785,9 +785,10 @@ static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
<< CALIB_SHIFT_IBAT)
/ (ADC_CH_IBAT_MAX_V - ADC_CH_IBAT_MIN_V);
- gpadc->cal_data[ADC_INPUT_IBAT].gain = V_gain * V2A_gain;
- gpadc->cal_data[ADC_INPUT_IBAT].offset = V_offset *
- V2A_gain + V2A_offset;
+ gpadc->cal_data[ADC_INPUT_IBAT].gain =
+ V_gain * V2A_gain;
+ gpadc->cal_data[ADC_INPUT_IBAT].offset =
+ V_offset * V2A_gain + V2A_offset;
} else {
gpadc->cal_data[ADC_INPUT_IBAT].gain = 0;
}
@@ -923,11 +924,10 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
int ret = 0;
struct ab8500_gpadc *gpadc;
- gpadc = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_gpadc), GFP_KERNEL);
- if (!gpadc) {
- dev_err(&pdev->dev, "Error: No memory\n");
+ gpadc = devm_kzalloc(&pdev->dev,
+ sizeof(struct ab8500_gpadc), GFP_KERNEL);
+ if (!gpadc)
return -ENOMEM;
- }
gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END");
if (gpadc->irq_sw < 0)
@@ -1072,18 +1072,19 @@ void ab8540_gpadc_get_otp(struct ab8500_gpadc *gpadc,
*vmain_h = gpadc->cal_data[ADC_INPUT_VMAIN].otp_calib_hi;
*btemp_l = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_lo;
*btemp_h = gpadc->cal_data[ADC_INPUT_BTEMP].otp_calib_hi;
- *vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo;
- *vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi;
- *ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
- *ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
- return ;
+ *vbat_l = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_lo;
+ *vbat_h = gpadc->cal_data[ADC_INPUT_VBAT].otp_calib_hi;
+ *ibat_l = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
+ *ibat_h = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
}
subsys_initcall_sync(ab8500_gpadc_init);
module_exit(ab8500_gpadc_exit);
MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson,"
- "M'boumba Cedric Madianga");
+MODULE_AUTHOR("Arun R Murthy");
+MODULE_AUTHOR("Daniel Willerud");
+MODULE_AUTHOR("Johan Palsson");
+MODULE_AUTHOR("M'boumba Cedric Madianga");
MODULE_ALIAS("platform:ab8500_gpadc");
MODULE_DESCRIPTION("AB8500 GPADC driver");
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index 0d1825696153..b9f0010309f9 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -27,7 +27,7 @@ static void ab8500_power_off(void)
{
sigset_t old;
sigset_t all;
- static char *pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"};
+ static const char * const pss[] = {"ab8500_ac", "pm2301", "ab8500_usb"};
int i;
bool charger_present = false;
union power_supply_propval val;
@@ -68,10 +68,9 @@ static void ab8500_power_off(void)
ret = power_supply_get_property(psy,
POWER_SUPPLY_PROP_TECHNOLOGY, &val);
if (!ret && val.intval != POWER_SUPPLY_TECHNOLOGY_UNKNOWN) {
- printk(KERN_INFO
- "Charger \"%s\" is connected with known battery."
- " Rebooting.\n",
- pss[i]);
+ pr_info("Charger '%s' is connected with known battery",
+ pss[i]);
+ pr_info(" - Rebooting.\n");
machine_restart("charging");
}
power_supply_put(psy);
@@ -161,8 +160,8 @@ static int ab8500_sysctrl_probe(struct platform_device *pdev)
pdata->initial_req_buf_config[j]);
if (ret < 0) {
dev_err(&pdev->dev,
- "unable to set sysClkReq%dRfClkBuf: "
- "%d\n", j + 1, ret);
+ "Can't set sysClkReq%dRfClkBuf: %d\n",
+ j + 1, ret);
}
}
}
diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c
index ae88654595dc..d817f202da5b 100644
--- a/drivers/mfd/adp5520.c
+++ b/drivers/mfd/adp5520.c
@@ -9,10 +9,10 @@
*
* Derived from da903x:
* Copyright (C) 2008 Compulab, Ltd.
- * Mike Rapoport <mike@compulab.co.il>
+ * Mike Rapoport <mike@compulab.co.il>
*
* Copyright (C) 2006-2008 Marvell International Ltd.
- * Eric Miao <eric.miao@marvell.com>
+ * Eric Miao <eric.miao@marvell.com>
*
* Licensed under the GPL-2 or later.
*/
@@ -355,7 +355,7 @@ static struct i2c_driver adp5520_driver = {
},
.probe = adp5520_probe,
.remove = adp5520_remove,
- .id_table = adp5520_id,
+ .id_table = adp5520_id,
};
module_i2c_driver(adp5520_driver);
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index d474732cc65c..5319f252790b 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -238,7 +238,7 @@ static int arizona_poll_reg(struct arizona *arizona,
if ((val & mask) == target)
return 0;
- msleep(1);
+ usleep_range(1000, 5000);
}
dev_err(arizona->dev, "Polling reg %u timed out: %x\n", reg, val);
@@ -279,14 +279,14 @@ static void arizona_disable_reset(struct arizona *arizona)
case WM5110:
case WM8280:
/* Meet requirements for minimum reset duration */
- msleep(5);
+ usleep_range(5000, 10000);
break;
default:
break;
}
gpio_set_value_cansleep(arizona->pdata.reset, 1);
- msleep(1);
+ usleep_range(1000, 5000);
}
}
@@ -598,6 +598,12 @@ static int arizona_runtime_resume(struct device *dev)
goto err;
}
break;
+ case WM1831:
+ case CS47L24:
+ ret = arizona_wait_for_boot(arizona);
+ if (ret != 0)
+ goto err;
+ break;
default:
ret = arizona_wait_for_boot(arizona);
if (ret != 0)
@@ -682,6 +688,9 @@ static int arizona_runtime_suspend(struct device *dev)
}
}
break;
+ case WM1831:
+ case CS47L24:
+ break;
default:
jd_active = arizona_is_jack_det_active(arizona);
if (jd_active < 0)
@@ -852,6 +861,16 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
count++;
}
+ count = 0;
+ of_property_for_each_u32(arizona->dev->of_node, "wlf,out-mono", prop,
+ cur, val) {
+ if (count == ARRAY_SIZE(pdata->out_mono))
+ break;
+
+ pdata->out_mono[count] = !!val;
+ count++;
+ }
+
return 0;
}
@@ -862,6 +881,8 @@ const struct of_device_id arizona_of_match[] = {
{ .compatible = "wlf,wm8997", .data = (void *)WM8997 },
{ .compatible = "wlf,wm8998", .data = (void *)WM8998 },
{ .compatible = "wlf,wm1814", .data = (void *)WM1814 },
+ { .compatible = "wlf,wm1831", .data = (void *)WM1831 },
+ { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
{},
};
EXPORT_SYMBOL_GPL(arizona_of_match);
@@ -919,6 +940,23 @@ static const struct mfd_cell wm5110_devs[] = {
},
};
+static const char * const cs47l24_supplies[] = {
+ "MICVDD",
+ "CPVDD",
+ "SPKVDD",
+};
+
+static const struct mfd_cell cs47l24_devs[] = {
+ { .name = "arizona-gpio" },
+ { .name = "arizona-haptics" },
+ { .name = "arizona-pwm" },
+ {
+ .name = "cs47l24-codec",
+ .parent_supplies = cs47l24_supplies,
+ .num_parent_supplies = ARRAY_SIZE(cs47l24_supplies),
+ },
+};
+
static const char * const wm8997_supplies[] = {
"MICVDD",
"DBVDD2",
@@ -963,7 +1001,7 @@ static const struct mfd_cell wm8998_devs[] = {
int arizona_dev_init(struct arizona *arizona)
{
struct device *dev = arizona->dev;
- const char *type_name;
+ const char *type_name = NULL;
unsigned int reg, val, mask;
int (*apply_patch)(struct arizona *) = NULL;
const struct mfd_cell *subdevs = NULL;
@@ -987,6 +1025,8 @@ int arizona_dev_init(struct arizona *arizona)
case WM8997:
case WM8998:
case WM1814:
+ case WM1831:
+ case CS47L24:
for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++)
arizona->core_supplies[i].supply
= wm5102_core_supplies[i];
@@ -1001,11 +1041,18 @@ int arizona_dev_init(struct arizona *arizona)
/* Mark DCVDD as external, LDO1 driver will clear if internal */
arizona->external_dcvdd = true;
- ret = mfd_add_devices(arizona->dev, -1, early_devs,
- ARRAY_SIZE(early_devs), NULL, 0, NULL);
- if (ret != 0) {
- dev_err(dev, "Failed to add early children: %d\n", ret);
- return ret;
+ switch (arizona->type) {
+ case WM1831:
+ case CS47L24:
+ break; /* No LDO1 regulator */
+ default:
+ ret = mfd_add_devices(arizona->dev, -1, early_devs,
+ ARRAY_SIZE(early_devs), NULL, 0, NULL);
+ if (ret != 0) {
+ dev_err(dev, "Failed to add early children: %d\n", ret);
+ return ret;
+ }
+ break;
}
ret = devm_regulator_bulk_get(dev, arizona->num_core_supplies,
@@ -1069,6 +1116,7 @@ int arizona_dev_init(struct arizona *arizona)
case 0x5102:
case 0x5110:
case 0x6349:
+ case 0x6363:
case 0x8997:
break;
default:
@@ -1084,7 +1132,7 @@ int arizona_dev_init(struct arizona *arizona)
goto err_reset;
}
- msleep(1);
+ usleep_range(1000, 5000);
}
/* Ensure device startup is complete */
@@ -1167,6 +1215,30 @@ int arizona_dev_init(struct arizona *arizona)
n_subdevs = ARRAY_SIZE(wm5110_devs);
}
break;
+ case 0x6363:
+ if (IS_ENABLED(CONFIG_MFD_CS47L24)) {
+ switch (arizona->type) {
+ case CS47L24:
+ type_name = "CS47L24";
+ break;
+
+ case WM1831:
+ type_name = "WM1831";
+ break;
+
+ default:
+ dev_warn(arizona->dev,
+ "CS47L24 registered as %d\n",
+ arizona->type);
+ arizona->type = CS47L24;
+ break;
+ }
+
+ apply_patch = cs47l24_patch;
+ subdevs = cs47l24_devs;
+ n_subdevs = ARRAY_SIZE(cs47l24_devs);
+ }
+ break;
case 0x8997:
if (IS_ENABLED(CONFIG_MFD_WM8997)) {
type_name = "WM8997";
diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c
index 4e3afd1861fc..5fe12961cfe5 100644
--- a/drivers/mfd/arizona-i2c.c
+++ b/drivers/mfd/arizona-i2c.c
@@ -88,7 +88,9 @@ static int arizona_i2c_probe(struct i2c_client *i2c,
static int arizona_i2c_remove(struct i2c_client *i2c)
{
struct arizona *arizona = dev_get_drvdata(&i2c->dev);
+
arizona_dev_exit(arizona);
+
return 0;
}
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 3d425e93ce84..5fef014920a3 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -30,11 +30,13 @@ static int arizona_map_irq(struct arizona *arizona, int irq)
{
int ret;
- ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq);
- if (ret < 0)
- ret = regmap_irq_get_virq(arizona->irq_chip, irq);
+ if (arizona->aod_irq_chip) {
+ ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq);
+ if (ret >= 0)
+ return ret;
+ }
- return ret;
+ return regmap_irq_get_virq(arizona->irq_chip, irq);
}
int arizona_request_irq(struct arizona *arizona, int irq, char *name,
@@ -107,8 +109,8 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
do {
poll = false;
- /* Always handle the AoD domain */
- handle_nested_irq(irq_find_mapping(arizona->virq, 0));
+ if (arizona->aod_irq_chip)
+ handle_nested_irq(irq_find_mapping(arizona->virq, 0));
/*
* Check if one of the main interrupts is asserted and only
@@ -219,6 +221,15 @@ int arizona_irq_init(struct arizona *arizona)
arizona->ctrlif_error = false;
break;
#endif
+#ifdef CONFIG_MFD_CS47L24
+ case WM1831:
+ case CS47L24:
+ aod = NULL;
+ irq = &cs47l24_irq;
+
+ arizona->ctrlif_error = false;
+ break;
+#endif
#ifdef CONFIG_MFD_WM8997
case WM8997:
aod = &wm8997_aod;
@@ -291,13 +302,16 @@ int arizona_irq_init(struct arizona *arizona)
goto err;
}
- ret = regmap_add_irq_chip(arizona->regmap,
- irq_create_mapping(arizona->virq, 0),
- 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_domain;
+ if (aod) {
+ ret = regmap_add_irq_chip(arizona->regmap,
+ irq_create_mapping(arizona->virq, 0),
+ 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;
+ }
}
ret = regmap_add_irq_chip(arizona->regmap,
@@ -309,30 +323,6 @@ int arizona_irq_init(struct arizona *arizona)
goto err_aod;
}
- /* 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);
- if (ret != 0) {
- dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
- arizona->irq, ret);
- goto err_boot_done;
- }
-
- /* 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);
- if (ret != 0) {
- dev_err(arizona->dev,
- "Failed to request CTRLIF_ERR %d: %d\n",
- arizona->irq, ret);
- goto err_ctrlif;
- }
- }
-
/* Used to emulate edge trigger and to work around broken pinmux */
if (arizona->pdata.irq_gpio) {
if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) {
@@ -362,21 +352,42 @@ int arizona_irq_init(struct arizona *arizona)
goto err_main_irq;
}
+ /* 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);
+ if (ret != 0) {
+ dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
+ arizona->irq, ret);
+ goto err_boot_done;
+ }
+
+ /* 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);
+ if (ret != 0) {
+ dev_err(arizona->dev,
+ "Failed to request CTRLIF_ERR %d: %d\n",
+ arizona->irq, ret);
+ goto err_ctrlif;
+ }
+ }
+
return 0;
-err_main_irq:
- if (arizona->ctrlif_error)
- free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
- arizona);
err_ctrlif:
free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
err_boot_done:
+ free_irq(arizona->irq, arizona);
+err_main_irq:
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
arizona->irq_chip);
err_aod:
regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
arizona->aod_irq_chip);
-err_domain:
err:
return ret;
}
diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c
index befbc89bfd34..5c1ccdeb9b70 100644
--- a/drivers/mfd/arizona-spi.c
+++ b/drivers/mfd/arizona-spi.c
@@ -46,6 +46,11 @@ static int arizona_spi_probe(struct spi_device *spi)
if (IS_ENABLED(CONFIG_MFD_WM5110))
regmap_config = &wm5110_spi_regmap;
break;
+ case WM1831:
+ case CS47L24:
+ if (IS_ENABLED(CONFIG_MFD_CS47L24))
+ regmap_config = &cs47l24_spi_regmap;
+ break;
default:
dev_err(&spi->dev, "Unknown device type %ld\n", type);
return -EINVAL;
@@ -89,6 +94,8 @@ static const struct spi_device_id arizona_spi_ids[] = {
{ "wm5102", WM5102 },
{ "wm5110", WM5110 },
{ "wm8280", WM8280 },
+ { "wm1831", WM1831 },
+ { "cs47l24", CS47L24 },
{ },
};
MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h
index 3af12e938f57..198e9cea77f9 100644
--- a/drivers/mfd/arizona.h
+++ b/drivers/mfd/arizona.h
@@ -25,6 +25,8 @@ extern const struct regmap_config wm5102_spi_regmap;
extern const struct regmap_config wm5110_i2c_regmap;
extern const struct regmap_config wm5110_spi_regmap;
+extern const struct regmap_config cs47l24_spi_regmap;
+
extern const struct regmap_config wm8997_i2c_regmap;
extern const struct regmap_config wm8998_i2c_regmap;
@@ -40,6 +42,8 @@ extern const struct regmap_irq_chip wm5110_aod;
extern const struct regmap_irq_chip wm5110_irq;
extern const struct regmap_irq_chip wm5110_revd_irq;
+extern const struct regmap_irq_chip cs47l24_irq;
+
extern const struct regmap_irq_chip wm8997_aod;
extern const struct regmap_irq_chip wm8997_irq;
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
index d001f7e238f5..94d67a6e1eb7 100644
--- a/drivers/mfd/as3711.c
+++ b/drivers/mfd/as3711.c
@@ -136,17 +136,13 @@ static int as3711_i2c_probe(struct i2c_client *client,
} else {
pdata = devm_kzalloc(&client->dev,
sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(&client->dev, "Failed to allocate pdata\n");
+ if (!pdata)
return -ENOMEM;
- }
}
as3711 = devm_kzalloc(&client->dev, sizeof(struct as3711), GFP_KERNEL);
- if (!as3711) {
- dev_err(&client->dev, "Memory allocation failed\n");
+ if (!as3711)
return -ENOMEM;
- }
as3711->dev = &client->dev;
i2c_set_clientdata(client, as3711);
@@ -157,7 +153,8 @@ static int as3711_i2c_probe(struct i2c_client *client,
as3711->regmap = devm_regmap_init_i2c(client, &as3711_regmap_config);
if (IS_ERR(as3711->regmap)) {
ret = PTR_ERR(as3711->regmap);
- dev_err(&client->dev, "regmap initialization failed: %d\n", ret);
+ dev_err(&client->dev,
+ "regmap initialization failed: %d\n", ret);
return ret;
}
@@ -172,12 +169,19 @@ static int as3711_i2c_probe(struct i2c_client *client,
return -ENODEV;
dev_info(as3711->dev, "AS3711 detected: %x:%x\n", id1, id2);
- /* We can reuse as3711_subdevs[], it will be copied in mfd_add_devices() */
+ /*
+ * We can reuse as3711_subdevs[],
+ * it will be copied in mfd_add_devices()
+ */
if (pdata) {
- as3711_subdevs[AS3711_REGULATOR].platform_data = &pdata->regulator;
- as3711_subdevs[AS3711_REGULATOR].pdata_size = sizeof(pdata->regulator);
- as3711_subdevs[AS3711_BACKLIGHT].platform_data = &pdata->backlight;
- as3711_subdevs[AS3711_BACKLIGHT].pdata_size = sizeof(pdata->backlight);
+ as3711_subdevs[AS3711_REGULATOR].platform_data =
+ &pdata->regulator;
+ as3711_subdevs[AS3711_REGULATOR].pdata_size =
+ sizeof(pdata->regulator);
+ as3711_subdevs[AS3711_BACKLIGHT].platform_data =
+ &pdata->backlight;
+ as3711_subdevs[AS3711_BACKLIGHT].pdata_size =
+ sizeof(pdata->backlight);
} else {
as3711_subdevs[AS3711_REGULATOR].platform_data = NULL;
as3711_subdevs[AS3711_REGULATOR].pdata_size = 0;
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index 924ea90494ae..e1f597f97f86 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -405,6 +405,8 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
goto scrub;
}
+ device_init_wakeup(as3722->dev, true);
+
dev_dbg(as3722->dev, "AS3722 core driver initialized successfully\n");
return 0;
@@ -422,6 +424,29 @@ static int as3722_i2c_remove(struct i2c_client *i2c)
return 0;
}
+static int __maybe_unused as3722_i2c_suspend(struct device *dev)
+{
+ struct as3722 *as3722 = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(as3722->chip_irq);
+ disable_irq(as3722->chip_irq);
+
+ return 0;
+}
+
+static int __maybe_unused as3722_i2c_resume(struct device *dev)
+{
+ struct as3722 *as3722 = dev_get_drvdata(dev);
+
+ enable_irq(as3722->chip_irq);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(as3722->chip_irq);
+
+ return 0;
+}
+
static const struct of_device_id as3722_of_match[] = {
{ .compatible = "ams,as3722", },
{},
@@ -434,10 +459,15 @@ static const struct i2c_device_id as3722_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);
+static const struct dev_pm_ops as3722_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(as3722_i2c_suspend, as3722_i2c_resume)
+};
+
static struct i2c_driver as3722_i2c_driver = {
.driver = {
.name = "as3722",
.of_match_table = as3722_of_match,
+ .pm = &as3722_pm_ops,
},
.probe = as3722_i2c_probe,
.remove = as3722_i2c_remove,
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index a726f01e3b02..4dca6bc61f5b 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -167,7 +167,6 @@ static void asic3_irq_demux(struct irq_desc *desc)
base = ASIC3_GPIO_A_BASE
+ bank * ASIC3_GPIO_BASE_INCR;
-
spin_lock_irqsave(&asic->lock, flags);
istat = asic3_read_register(asic,
base +
@@ -502,7 +501,8 @@ static int asic3_gpio_get(struct gpio_chip *chip,
return -EINVAL;
}
- return asic3_read_register(asic, gpio_base + ASIC3_GPIO_STATUS) & mask;
+ return !!(asic3_read_register(asic,
+ gpio_base + ASIC3_GPIO_STATUS) & mask);
}
static void asic3_gpio_set(struct gpio_chip *chip,
@@ -536,8 +536,6 @@ static void asic3_gpio_set(struct gpio_chip *chip,
asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg);
spin_unlock_irqrestore(&asic->lock, flags);
-
- return;
}
static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -665,18 +663,18 @@ static int ds1wm_enable(struct platform_device *pdev)
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
- msleep(1);
+ usleep_range(1000, 5000);
/* Reset and enable DS1WM */
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
ASIC3_EXTCF_OWM_RESET, 1);
- msleep(1);
+ usleep_range(1000, 5000);
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
ASIC3_EXTCF_OWM_RESET, 0);
- msleep(1);
+ usleep_range(1000, 5000);
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
ASIC3_EXTCF_OWM_EN, 1);
- msleep(1);
+ usleep_range(1000, 5000);
return 0;
}
@@ -757,7 +755,7 @@ static int asic3_mmc_enable(struct platform_device *pdev)
* when HCLK is stopped.
*/
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
- msleep(1);
+ usleep_range(1000, 5000);
/* HCLK 24.576 MHz, BCLK 12.288 MHz: */
asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
@@ -765,7 +763,7 @@ static int asic3_mmc_enable(struct platform_device *pdev)
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
- msleep(1);
+ usleep_range(1000, 5000);
asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
ASIC3_EXTCF_SD_MEM_ENABLE, 1);
@@ -841,7 +839,7 @@ static int asic3_leds_suspend(struct platform_device *pdev)
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0)
- msleep(1);
+ usleep_range(1000, 5000);
asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
@@ -900,8 +898,8 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
/* MMC */
if (mem_sdio) {
- asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
- mem_sdio->start,
+ asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >>
+ asic->bus_shift) + mem_sdio->start,
ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
if (!asic->tmio_cnf) {
ret = -ENOMEM;
@@ -962,10 +960,8 @@ static int __init asic3_probe(struct platform_device *pdev)
asic = devm_kzalloc(&pdev->dev,
sizeof(struct asic3), GFP_KERNEL);
- if (asic == NULL) {
- printk(KERN_ERR "kzalloc failed\n");
+ if (!asic)
return -ENOMEM;
- }
spin_lock_init(&asic->lock);
platform_set_drvdata(pdev, asic);
@@ -1074,7 +1070,9 @@ static struct platform_driver asic3_device_driver = {
static int __init asic3_init(void)
{
int retval = 0;
+
retval = platform_driver_probe(&asic3_device_driver, asic3_probe);
+
return retval;
}
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 56a466469664..9f70de1e4c70 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -292,7 +292,7 @@ static int cros_ec_i2c_probe(struct i2c_client *client,
struct cros_ec_device *ec_dev = NULL;
int err;
- ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
+ ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
if (!ec_dev)
return -ENOMEM;
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 6a0f6ec67c6b..ebe9b9477cb2 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -113,7 +113,7 @@ static int terminate_request(struct cros_ec_device *ec_dev)
trans.delay_usecs = ec_spi->end_of_msg_delay;
spi_message_add_tail(&trans, &msg);
- ret = spi_sync(ec_spi->spi, &msg);
+ ret = spi_sync_locked(ec_spi->spi, &msg);
/* Reset end-of-response timer */
ec_spi->last_transfer_ns = ktime_get_ns();
@@ -147,7 +147,7 @@ static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n)
spi_message_init(&msg);
spi_message_add_tail(&trans, &msg);
- ret = spi_sync(ec_spi->spi, &msg);
+ ret = spi_sync_locked(ec_spi->spi, &msg);
if (ret < 0)
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
@@ -175,7 +175,7 @@ static int cros_ec_spi_receive_packet(struct cros_ec_device *ec_dev,
unsigned long deadline;
int todo;
- BUG_ON(EC_MSG_PREAMBLE_COUNT > ec_dev->din_size);
+ BUG_ON(ec_dev->din_size < EC_MSG_PREAMBLE_COUNT);
/* Receive data until we see the header byte */
deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
@@ -283,7 +283,7 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
unsigned long deadline;
int todo;
- BUG_ON(EC_MSG_PREAMBLE_COUNT > ec_dev->din_size);
+ BUG_ON(ec_dev->din_size < EC_MSG_PREAMBLE_COUNT);
/* Receive data until we see the header byte */
deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
@@ -391,10 +391,10 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
}
rx_buf = kzalloc(len, GFP_KERNEL);
- if (!rx_buf) {
- ret = -ENOMEM;
- goto exit;
- }
+ if (!rx_buf)
+ return -ENOMEM;
+
+ spi_bus_lock(ec_spi->spi->master);
/*
* Leave a gap between CS assertion and clocking of data to allow the
@@ -414,7 +414,7 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
trans.len = len;
trans.cs_change = 1;
spi_message_add_tail(&trans, &msg);
- ret = spi_sync(ec_spi->spi, &msg);
+ ret = spi_sync_locked(ec_spi->spi, &msg);
/* Get the response */
if (!ret) {
@@ -440,6 +440,9 @@ static int cros_ec_pkt_xfer_spi(struct cros_ec_device *ec_dev,
}
final_ret = terminate_request(ec_dev);
+
+ spi_bus_unlock(ec_spi->spi->master);
+
if (!ret)
ret = final_ret;
if (ret < 0)
@@ -520,10 +523,10 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
}
rx_buf = kzalloc(len, GFP_KERNEL);
- if (!rx_buf) {
- ret = -ENOMEM;
- goto exit;
- }
+ if (!rx_buf)
+ return -ENOMEM;
+
+ spi_bus_lock(ec_spi->spi->master);
/* Transmit phase - send our message */
debug_packet(ec_dev->dev, "out", ec_dev->dout, len);
@@ -534,7 +537,7 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
trans.cs_change = 1;
spi_message_init(&msg);
spi_message_add_tail(&trans, &msg);
- ret = spi_sync(ec_spi->spi, &msg);
+ ret = spi_sync_locked(ec_spi->spi, &msg);
/* Get the response */
if (!ret) {
@@ -560,6 +563,9 @@ static int cros_ec_cmd_xfer_spi(struct cros_ec_device *ec_dev,
}
final_ret = terminate_request(ec_dev);
+
+ spi_bus_unlock(ec_spi->spi->master);
+
if (!ret)
ret = final_ret;
if (ret < 0)
diff --git a/drivers/mfd/cs47l24-tables.c b/drivers/mfd/cs47l24-tables.c
new file mode 100644
index 000000000000..870800657594
--- /dev/null
+++ b/drivers/mfd/cs47l24-tables.c
@@ -0,0 +1,1629 @@
+/*
+ * Data tables for CS47L24 codec
+ *
+ * Copyright 2015 Cirrus Logic, Inc.
+ *
+ * Author: Richard Fitzgerald <rf@opensource.wolfsonmicro.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/module.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/registers.h>
+#include <linux/device.h>
+
+#include "arizona.h"
+
+#define CS47L24_NUM_ISR 5
+
+static const struct reg_sequence cs47l24_reva_patch[] = {
+ { 0x80, 0x3 },
+ { 0x27C, 0x0010 },
+ { 0x221, 0x0070 },
+ { 0x80, 0x0 },
+};
+
+int cs47l24_patch(struct arizona *arizona)
+{
+ return regmap_register_patch(arizona->regmap,
+ cs47l24_reva_patch,
+ ARRAY_SIZE(cs47l24_reva_patch));
+}
+EXPORT_SYMBOL_GPL(cs47l24_patch);
+
+static const struct regmap_irq cs47l24_irqs[ARIZONA_NUM_IRQ] = {
+ [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 },
+ [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 },
+
+ [ARIZONA_IRQ_DSP3_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP3_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP2_RAM_RDY] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP2_RAM_RDY_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ8] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ8_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ7] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ7_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ6] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ6_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ5] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ5_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ4] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ4_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ3] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ3_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ2] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1
+ },
+ [ARIZONA_IRQ_DSP_IRQ1] = {
+ .reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1
+ },
+
+ [ARIZONA_IRQ_SPK_OVERHEAT_WARN] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_WARN_EINT1
+ },
+ [ARIZONA_IRQ_SPK_OVERHEAT] = {
+ .reg_offset = 2, .mask = ARIZONA_SPK_OVERHEAT_EINT1
+ },
+ [ARIZONA_IRQ_WSEQ_DONE] = {
+ .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1
+ },
+ [ARIZONA_IRQ_DRC2_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_DRC1_SIG_DET] = {
+ .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1
+ },
+ [ARIZONA_IRQ_ASRC2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_ASRC1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_UNDERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_OVERCLOCKED] = {
+ .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_LOCK] = {
+ .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1
+ },
+ [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = {
+ .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1
+ },
+
+ [ARIZONA_IRQ_CTRLIF_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_CTRLIF_ERR_EINT1
+ },
+ [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_MIXER_DROPPED_SAMPLE_EINT1
+ },
+ [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ASYNC_CLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_SYSCLK_ENA_LOW] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_SYSCLK_ENA_LOW_EINT1
+ },
+ [ARIZONA_IRQ_ISRC1_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC1_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC2_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC2_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_ISRC3_CFG_ERR] = {
+ .reg_offset = 3, .mask = ARIZONA_V2_ISRC3_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1R_DONE_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_DONE] = {
+ .reg_offset = 3, .mask = ARIZONA_HP1L_DONE_EINT1
+ },
+
+ [ARIZONA_IRQ_BOOT_DONE] = {
+ .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1
+ },
+ [ARIZONA_IRQ_ASRC_CFG_ERR] = {
+ .reg_offset = 4, .mask = ARIZONA_V2_ASRC_CFG_ERR_EINT1
+ },
+ [ARIZONA_IRQ_FLL2_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1
+ },
+ [ARIZONA_IRQ_FLL1_CLOCK_OK] = {
+ .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1
+ },
+
+ [ARIZONA_IRQ_DSP_SHARED_WR_COLL] = {
+ .reg_offset = 5, .mask = ARIZONA_DSP_SHARED_WR_COLL_EINT1
+ },
+ [ARIZONA_IRQ_SPK_SHUTDOWN] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK_SHUTDOWN_EINT1
+ },
+ [ARIZONA_IRQ_SPK1R_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1R_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_SPK1L_SHORT] = {
+ .reg_offset = 5, .mask = ARIZONA_SPK1L_SHORT_EINT1
+ },
+ [ARIZONA_IRQ_HP1R_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1R_SC_POS_EINT1
+ },
+ [ARIZONA_IRQ_HP1L_SC_POS] = {
+ .reg_offset = 5, .mask = ARIZONA_HP1L_SC_POS_EINT1
+ },
+};
+
+const struct regmap_irq_chip cs47l24_irq = {
+ .name = "cs47l24 IRQ",
+ .status_base = ARIZONA_INTERRUPT_STATUS_1,
+ .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK,
+ .ack_base = ARIZONA_INTERRUPT_STATUS_1,
+ .num_regs = 6,
+ .irqs = cs47l24_irqs,
+ .num_irqs = ARRAY_SIZE(cs47l24_irqs),
+};
+EXPORT_SYMBOL_GPL(cs47l24_irq);
+
+static const struct reg_default cs47l24_reg_default[] = {
+ { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */
+ { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */
+ { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */
+ { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */
+ { 0x00000023, 0x1000 }, /* R35 - Tone Generator 4 */
+ { 0x00000024, 0x0000 }, /* R36 - Tone Generator 5 */
+ { 0x00000030, 0x0000 }, /* R48 - PWM Drive 1 */
+ { 0x00000031, 0x0100 }, /* R49 - PWM Drive 2 */
+ { 0x00000032, 0x0100 }, /* R50 - PWM Drive 3 */
+ { 0x00000041, 0x0000 }, /* R65 - Sequence control */
+ { 0x00000061, 0x01FF }, /* R97 - Sample Rate Sequence Select 1 */
+ { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */
+ { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */
+ { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */
+ { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */
+ { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
+ { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
+ { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */
+ { 0x00000093, 0x0000 }, /* R147 - Haptics phase 1 duration */
+ { 0x00000094, 0x0000 }, /* R148 - Haptics phase 2 intensity */
+ { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */
+ { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */
+ { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */
+ { 0x00000100, 0x0002 }, /* R256 - Clock 32k 1 */
+ { 0x00000101, 0x0504 }, /* R257 - System Clock 1 */
+ { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */
+ { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */
+ { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */
+ { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */
+ { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */
+ { 0x00000114, 0x0011 }, /* R276 - Async sample rate 2 */
+ { 0x00000149, 0x0000 }, /* R329 - Output system clock */
+ { 0x0000014A, 0x0000 }, /* R330 - Output async clock */
+ { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */
+ { 0x00000153, 0x0000 }, /* R339 - Rate Estimator 2 */
+ { 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */
+ { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */
+ { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */
+ { 0x00000171, 0x0002 }, /* R369 - FLL1 Control 1 */
+ { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */
+ { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */
+ { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */
+ { 0x00000175, 0x0006 }, /* R373 - FLL1 Control 5 */
+ { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */
+ { 0x00000177, 0x0281 }, /* R375 - FLL1 Loop Filter Test 1 */
+ { 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */
+ { 0x00000179, 0x0000 }, /* R376 - FLL1 Control 7 */
+ { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */
+ { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */
+ { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */
+ { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */
+ { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */
+ { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */
+ { 0x00000187, 0x0001 }, /* R390 - FLL1 Synchroniser 7 */
+ { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */
+ { 0x0000018A, 0x000C }, /* R394 - FLL1 GPIO Clock */
+ { 0x00000191, 0x0002 }, /* R401 - FLL2 Control 1 */
+ { 0x00000192, 0x0008 }, /* R402 - FLL2 Control 2 */
+ { 0x00000193, 0x0018 }, /* R403 - FLL2 Control 3 */
+ { 0x00000194, 0x007D }, /* R404 - FLL2 Control 4 */
+ { 0x00000195, 0x000C }, /* R405 - FLL2 Control 5 */
+ { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */
+ { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */
+ { 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */
+ { 0x00000199, 0x0000 }, /* R408 - FLL2 Control 7 */
+ { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */
+ { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */
+ { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */
+ { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */
+ { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */
+ { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */
+ { 0x000001A7, 0x0001 }, /* R422 - FLL2 Synchroniser 7 */
+ { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */
+ { 0x000001AA, 0x000C }, /* R426 - FLL2 GPIO Clock */
+ { 0x00000218, 0x00E6 }, /* R536 - Mic Bias Ctrl 1 */
+ { 0x00000219, 0x00E6 }, /* R537 - Mic Bias Ctrl 2 */
+ { 0x00000300, 0x0000 }, /* R768 - Input Enables */
+ { 0x00000308, 0x0000 }, /* R776 - Input Rate */
+ { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */
+ { 0x0000030C, 0x0002 }, /* R780 - HPF Control */
+ { 0x00000310, 0x2000 }, /* R784 - IN1L Control */
+ { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */
+ { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */
+ { 0x00000314, 0x0000 }, /* R788 - IN1R Control */
+ { 0x00000315, 0x0180 }, /* R789 - ADC Digital Volume 1R */
+ { 0x00000316, 0x0000 }, /* R790 - DMIC1R Control */
+ { 0x00000318, 0x2000 }, /* R792 - IN2L Control */
+ { 0x00000319, 0x0180 }, /* R793 - ADC Digital Volume 2L */
+ { 0x0000031A, 0x0000 }, /* R794 - DMIC2L Control */
+ { 0x0000031C, 0x0000 }, /* R796 - IN2R Control */
+ { 0x0000031D, 0x0180 }, /* R797 - ADC Digital Volume 2R */
+ { 0x0000031E, 0x0000 }, /* R798 - DMIC2R Control */
+ { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */
+ { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */
+ { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */
+ { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */
+ { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */
+ { 0x00000412, 0x0081 }, /* R1042 - DAC Volume Limit 1L */
+ { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */
+ { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */
+ { 0x00000416, 0x0081 }, /* R1046 - DAC Volume Limit 1R */
+ { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */
+ { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */
+ { 0x0000042A, 0x0081 }, /* R1066 - Out Volume 4L */
+ { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */
+ { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */
+ { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */
+ { 0x000004A0, 0x3480 }, /* R1184 - HP1 Short Circuit Ctrl */
+ { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */
+ { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */
+ { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */
+ { 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */
+ { 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */
+ { 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */
+ { 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */
+ { 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */
+ { 0x00000509, 0x0000 }, /* R1289 - AIF1 Frame Ctrl 3 */
+ { 0x0000050A, 0x0001 }, /* R1290 - AIF1 Frame Ctrl 4 */
+ { 0x0000050B, 0x0002 }, /* R1291 - AIF1 Frame Ctrl 5 */
+ { 0x0000050C, 0x0003 }, /* R1292 - AIF1 Frame Ctrl 6 */
+ { 0x0000050D, 0x0004 }, /* R1293 - AIF1 Frame Ctrl 7 */
+ { 0x0000050E, 0x0005 }, /* R1294 - AIF1 Frame Ctrl 8 */
+ { 0x0000050F, 0x0006 }, /* R1295 - AIF1 Frame Ctrl 9 */
+ { 0x00000510, 0x0007 }, /* R1296 - AIF1 Frame Ctrl 10 */
+ { 0x00000511, 0x0000 }, /* R1297 - AIF1 Frame Ctrl 11 */
+ { 0x00000512, 0x0001 }, /* R1298 - AIF1 Frame Ctrl 12 */
+ { 0x00000513, 0x0002 }, /* R1299 - AIF1 Frame Ctrl 13 */
+ { 0x00000514, 0x0003 }, /* R1300 - AIF1 Frame Ctrl 14 */
+ { 0x00000515, 0x0004 }, /* R1301 - AIF1 Frame Ctrl 15 */
+ { 0x00000516, 0x0005 }, /* R1302 - AIF1 Frame Ctrl 16 */
+ { 0x00000517, 0x0006 }, /* R1303 - AIF1 Frame Ctrl 17 */
+ { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */
+ { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */
+ { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */
+ { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */
+ { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */
+ { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */
+ { 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */
+ { 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */
+ { 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */
+ { 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */
+ { 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 */
+ { 0x00000581, 0x0008 }, /* R1409 - AIF3 Tx Pin Ctrl */
+ { 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */
+ { 0x00000583, 0x0000 }, /* R1411 - AIF3 Rate Ctrl */
+ { 0x00000584, 0x0000 }, /* R1412 - AIF3 Format */
+ { 0x00000586, 0x0040 }, /* R1414 - AIF3 Rx BCLK Rate */
+ { 0x00000587, 0x1818 }, /* R1415 - AIF3 Frame Ctrl 1 */
+ { 0x00000588, 0x1818 }, /* R1416 - AIF3 Frame Ctrl 2 */
+ { 0x00000589, 0x0000 }, /* R1417 - AIF3 Frame Ctrl 3 */
+ { 0x0000058A, 0x0001 }, /* R1418 - AIF3 Frame Ctrl 4 */
+ { 0x00000591, 0x0000 }, /* R1425 - AIF3 Frame Ctrl 11 */
+ { 0x00000592, 0x0001 }, /* R1426 - AIF3 Frame Ctrl 12 */
+ { 0x00000599, 0x0000 }, /* R1433 - AIF3 Tx Enables */
+ { 0x0000059A, 0x0000 }, /* R1434 - AIF3 Rx Enables */
+ { 0x00000640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */
+ { 0x00000641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */
+ { 0x00000642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */
+ { 0x00000643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */
+ { 0x00000644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */
+ { 0x00000645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */
+ { 0x00000646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */
+ { 0x00000647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */
+ { 0x00000648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */
+ { 0x00000649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */
+ { 0x0000064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */
+ { 0x0000064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */
+ { 0x0000064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */
+ { 0x0000064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */
+ { 0x0000064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */
+ { 0x0000064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */
+ { 0x00000680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */
+ { 0x00000681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */
+ { 0x00000682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */
+ { 0x00000683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */
+ { 0x00000684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */
+ { 0x00000685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */
+ { 0x00000686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */
+ { 0x00000687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */
+ { 0x00000688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */
+ { 0x00000689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */
+ { 0x0000068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */
+ { 0x0000068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */
+ { 0x0000068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */
+ { 0x0000068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */
+ { 0x0000068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */
+ { 0x0000068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */
+ { 0x000006B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */
+ { 0x000006B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */
+ { 0x000006B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */
+ { 0x000006B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */
+ { 0x000006B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */
+ { 0x000006B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */
+ { 0x000006B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */
+ { 0x000006B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */
+ { 0x00000700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */
+ { 0x00000701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */
+ { 0x00000702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */
+ { 0x00000703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */
+ { 0x00000704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */
+ { 0x00000705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */
+ { 0x00000706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */
+ { 0x00000707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */
+ { 0x00000708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */
+ { 0x00000709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */
+ { 0x0000070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */
+ { 0x0000070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */
+ { 0x0000070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */
+ { 0x0000070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */
+ { 0x0000070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */
+ { 0x0000070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */
+ { 0x00000710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */
+ { 0x00000711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */
+ { 0x00000712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */
+ { 0x00000713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */
+ { 0x00000714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */
+ { 0x00000715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */
+ { 0x00000716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */
+ { 0x00000717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */
+ { 0x00000718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */
+ { 0x00000719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */
+ { 0x0000071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */
+ { 0x0000071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */
+ { 0x0000071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */
+ { 0x0000071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */
+ { 0x0000071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */
+ { 0x0000071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */
+ { 0x00000720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */
+ { 0x00000721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */
+ { 0x00000722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */
+ { 0x00000723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */
+ { 0x00000724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */
+ { 0x00000725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */
+ { 0x00000726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */
+ { 0x00000727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */
+ { 0x00000728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */
+ { 0x00000729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */
+ { 0x0000072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */
+ { 0x0000072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */
+ { 0x0000072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */
+ { 0x0000072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */
+ { 0x0000072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */
+ { 0x0000072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */
+ { 0x00000730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */
+ { 0x00000731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */
+ { 0x00000732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */
+ { 0x00000733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */
+ { 0x00000734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */
+ { 0x00000735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */
+ { 0x00000736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */
+ { 0x00000737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */
+ { 0x00000738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */
+ { 0x00000739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */
+ { 0x0000073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */
+ { 0x0000073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */
+ { 0x0000073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */
+ { 0x0000073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */
+ { 0x0000073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */
+ { 0x0000073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */
+ { 0x00000740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */
+ { 0x00000741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */
+ { 0x00000742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */
+ { 0x00000743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */
+ { 0x00000744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */
+ { 0x00000745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */
+ { 0x00000746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */
+ { 0x00000747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */
+ { 0x00000748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */
+ { 0x00000749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */
+ { 0x0000074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */
+ { 0x0000074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */
+ { 0x0000074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */
+ { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */
+ { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */
+ { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */
+ { 0x00000750, 0x0000 }, /* R1872 - AIF2TX3MIX Input 1 Source */
+ { 0x00000751, 0x0080 }, /* R1873 - AIF2TX3MIX Input 1 Volume */
+ { 0x00000752, 0x0000 }, /* R1874 - AIF2TX3MIX Input 2 Source */
+ { 0x00000753, 0x0080 }, /* R1875 - AIF2TX3MIX Input 2 Volume */
+ { 0x00000754, 0x0000 }, /* R1876 - AIF2TX3MIX Input 3 Source */
+ { 0x00000755, 0x0080 }, /* R1877 - AIF2TX3MIX Input 3 Volume */
+ { 0x00000756, 0x0000 }, /* R1878 - AIF2TX3MIX Input 4 Source */
+ { 0x00000757, 0x0080 }, /* R1879 - AIF2TX3MIX Input 4 Volume */
+ { 0x00000758, 0x0000 }, /* R1880 - AIF2TX4MIX Input 1 Source */
+ { 0x00000759, 0x0080 }, /* R1881 - AIF2TX4MIX Input 1 Volume */
+ { 0x0000075A, 0x0000 }, /* R1882 - AIF2TX4MIX Input 2 Source */
+ { 0x0000075B, 0x0080 }, /* R1883 - AIF2TX4MIX Input 2 Volume */
+ { 0x0000075C, 0x0000 }, /* R1884 - AIF2TX4MIX Input 3 Source */
+ { 0x0000075D, 0x0080 }, /* R1885 - AIF2TX4MIX Input 3 Volume */
+ { 0x0000075E, 0x0000 }, /* R1886 - AIF2TX4MIX Input 4 Source */
+ { 0x0000075F, 0x0080 }, /* R1887 - AIF2TX4MIX Input 4 Volume */
+ { 0x00000760, 0x0000 }, /* R1888 - AIF2TX5MIX Input 1 Source */
+ { 0x00000761, 0x0080 }, /* R1889 - AIF2TX5MIX Input 1 Volume */
+ { 0x00000762, 0x0000 }, /* R1890 - AIF2TX5MIX Input 2 Source */
+ { 0x00000763, 0x0080 }, /* R1891 - AIF2TX5MIX Input 2 Volume */
+ { 0x00000764, 0x0000 }, /* R1892 - AIF2TX5MIX Input 3 Source */
+ { 0x00000765, 0x0080 }, /* R1893 - AIF2TX5MIX Input 3 Volume */
+ { 0x00000766, 0x0000 }, /* R1894 - AIF2TX5MIX Input 4 Source */
+ { 0x00000767, 0x0080 }, /* R1895 - AIF2TX5MIX Input 4 Volume */
+ { 0x00000768, 0x0000 }, /* R1896 - AIF2TX6MIX Input 1 Source */
+ { 0x00000769, 0x0080 }, /* R1897 - AIF2TX6MIX Input 1 Volume */
+ { 0x0000076A, 0x0000 }, /* R1898 - AIF2TX6MIX Input 2 Source */
+ { 0x0000076B, 0x0080 }, /* R1899 - AIF2TX6MIX Input 2 Volume */
+ { 0x0000076C, 0x0000 }, /* R1900 - AIF2TX6MIX Input 3 Source */
+ { 0x0000076D, 0x0080 }, /* R1901 - AIF2TX6MIX Input 3 Volume */
+ { 0x0000076E, 0x0000 }, /* R1902 - AIF2TX6MIX Input 4 Source */
+ { 0x0000076F, 0x0080 }, /* R1903 - AIF2TX6MIX Input 4 Volume */
+ { 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */
+ { 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */
+ { 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */
+ { 0x00000783, 0x0080 }, /* R1923 - AIF3TX1MIX Input 2 Volume */
+ { 0x00000784, 0x0000 }, /* R1924 - AIF3TX1MIX Input 3 Source */
+ { 0x00000785, 0x0080 }, /* R1925 - AIF3TX1MIX Input 3 Volume */
+ { 0x00000786, 0x0000 }, /* R1926 - AIF3TX1MIX Input 4 Source */
+ { 0x00000787, 0x0080 }, /* R1927 - AIF3TX1MIX Input 4 Volume */
+ { 0x00000788, 0x0000 }, /* R1928 - AIF3TX2MIX Input 1 Source */
+ { 0x00000789, 0x0080 }, /* R1929 - AIF3TX2MIX Input 1 Volume */
+ { 0x0000078A, 0x0000 }, /* R1930 - AIF3TX2MIX Input 2 Source */
+ { 0x0000078B, 0x0080 }, /* R1931 - AIF3TX2MIX Input 2 Volume */
+ { 0x0000078C, 0x0000 }, /* R1932 - AIF3TX2MIX Input 3 Source */
+ { 0x0000078D, 0x0080 }, /* R1933 - AIF3TX2MIX Input 3 Volume */
+ { 0x0000078E, 0x0000 }, /* R1934 - AIF3TX2MIX Input 4 Source */
+ { 0x0000078F, 0x0080 }, /* R1935 - AIF3TX2MIX Input 4 Volume */
+ { 0x00000880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */
+ { 0x00000881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */
+ { 0x00000882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */
+ { 0x00000883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */
+ { 0x00000884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */
+ { 0x00000885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */
+ { 0x00000886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */
+ { 0x00000887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */
+ { 0x00000888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */
+ { 0x00000889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */
+ { 0x0000088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */
+ { 0x0000088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */
+ { 0x0000088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */
+ { 0x0000088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */
+ { 0x0000088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */
+ { 0x0000088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */
+ { 0x000008C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */
+ { 0x000008C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */
+ { 0x000008C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */
+ { 0x000008C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */
+ { 0x000008C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */
+ { 0x000008C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */
+ { 0x000008C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */
+ { 0x000008C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */
+ { 0x000008C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */
+ { 0x000008C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */
+ { 0x000008CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */
+ { 0x000008CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */
+ { 0x000008CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */
+ { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */
+ { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */
+ { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */
+ { 0x000008D0, 0x0000 }, /* R2256 - DRC2LMIX Input 1 Source */
+ { 0x000008D1, 0x0080 }, /* R2257 - DRC2LMIX Input 1 Volume */
+ { 0x000008D2, 0x0000 }, /* R2258 - DRC2LMIX Input 2 Source */
+ { 0x000008D3, 0x0080 }, /* R2259 - DRC2LMIX Input 2 Volume */
+ { 0x000008D4, 0x0000 }, /* R2260 - DRC2LMIX Input 3 Source */
+ { 0x000008D5, 0x0080 }, /* R2261 - DRC2LMIX Input 3 Volume */
+ { 0x000008D6, 0x0000 }, /* R2262 - DRC2LMIX Input 4 Source */
+ { 0x000008D7, 0x0080 }, /* R2263 - DRC2LMIX Input 4 Volume */
+ { 0x000008D8, 0x0000 }, /* R2264 - DRC2RMIX Input 1 Source */
+ { 0x000008D9, 0x0080 }, /* R2265 - DRC2RMIX Input 1 Volume */
+ { 0x000008DA, 0x0000 }, /* R2266 - DRC2RMIX Input 2 Source */
+ { 0x000008DB, 0x0080 }, /* R2267 - DRC2RMIX Input 2 Volume */
+ { 0x000008DC, 0x0000 }, /* R2268 - DRC2RMIX Input 3 Source */
+ { 0x000008DD, 0x0080 }, /* R2269 - DRC2RMIX Input 3 Volume */
+ { 0x000008DE, 0x0000 }, /* R2270 - DRC2RMIX Input 4 Source */
+ { 0x000008DF, 0x0080 }, /* R2271 - DRC2RMIX Input 4 Volume */
+ { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */
+ { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */
+ { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */
+ { 0x00000903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */
+ { 0x00000904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */
+ { 0x00000905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */
+ { 0x00000906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */
+ { 0x00000907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */
+ { 0x00000908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */
+ { 0x00000909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */
+ { 0x0000090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */
+ { 0x0000090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */
+ { 0x0000090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */
+ { 0x0000090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */
+ { 0x0000090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */
+ { 0x0000090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */
+ { 0x00000910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */
+ { 0x00000911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */
+ { 0x00000912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */
+ { 0x00000913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */
+ { 0x00000914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */
+ { 0x00000915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */
+ { 0x00000916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */
+ { 0x00000917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */
+ { 0x00000918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */
+ { 0x00000919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */
+ { 0x0000091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */
+ { 0x0000091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */
+ { 0x0000091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */
+ { 0x0000091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */
+ { 0x0000091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */
+ { 0x0000091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */
+ { 0x00000980, 0x0000 }, /* R2432 - DSP2LMIX Input 1 Source */
+ { 0x00000981, 0x0080 }, /* R2433 - DSP2LMIX Input 1 Volume */
+ { 0x00000982, 0x0000 }, /* R2434 - DSP2LMIX Input 2 Source */
+ { 0x00000983, 0x0080 }, /* R2435 - DSP2LMIX Input 2 Volume */
+ { 0x00000984, 0x0000 }, /* R2436 - DSP2LMIX Input 3 Source */
+ { 0x00000985, 0x0080 }, /* R2437 - DSP2LMIX Input 3 Volume */
+ { 0x00000986, 0x0000 }, /* R2438 - DSP2LMIX Input 4 Source */
+ { 0x00000987, 0x0080 }, /* R2439 - DSP2LMIX Input 4 Volume */
+ { 0x00000988, 0x0000 }, /* R2440 - DSP2RMIX Input 1 Source */
+ { 0x00000989, 0x0080 }, /* R2441 - DSP2RMIX Input 1 Volume */
+ { 0x0000098A, 0x0000 }, /* R2442 - DSP2RMIX Input 2 Source */
+ { 0x0000098B, 0x0080 }, /* R2443 - DSP2RMIX Input 2 Volume */
+ { 0x0000098C, 0x0000 }, /* R2444 - DSP2RMIX Input 3 Source */
+ { 0x0000098D, 0x0080 }, /* R2445 - DSP2RMIX Input 3 Volume */
+ { 0x0000098E, 0x0000 }, /* R2446 - DSP2RMIX Input 4 Source */
+ { 0x0000098F, 0x0080 }, /* R2447 - DSP2RMIX Input 4 Volume */
+ { 0x00000990, 0x0000 }, /* R2448 - DSP2AUX1MIX Input 1 Source */
+ { 0x00000998, 0x0000 }, /* R2456 - DSP2AUX2MIX Input 1 Source */
+ { 0x000009A0, 0x0000 }, /* R2464 - DSP2AUX3MIX Input 1 Source */
+ { 0x000009A8, 0x0000 }, /* R2472 - DSP2AUX4MIX Input 1 Source */
+ { 0x000009B0, 0x0000 }, /* R2480 - DSP2AUX5MIX Input 1 Source */
+ { 0x000009B8, 0x0000 }, /* R2488 - DSP2AUX6MIX Input 1 Source */
+ { 0x000009C0, 0x0000 }, /* R2496 - DSP3LMIX Input 1 Source */
+ { 0x000009C1, 0x0080 }, /* R2497 - DSP3LMIX Input 1 Volume */
+ { 0x000009C2, 0x0000 }, /* R2498 - DSP3LMIX Input 2 Source */
+ { 0x000009C3, 0x0080 }, /* R2499 - DSP3LMIX Input 2 Volume */
+ { 0x000009C4, 0x0000 }, /* R2500 - DSP3LMIX Input 3 Source */
+ { 0x000009C5, 0x0080 }, /* R2501 - DSP3LMIX Input 3 Volume */
+ { 0x000009C6, 0x0000 }, /* R2502 - DSP3LMIX Input 4 Source */
+ { 0x000009C7, 0x0080 }, /* R2503 - DSP3LMIX Input 4 Volume */
+ { 0x000009C8, 0x0000 }, /* R2504 - DSP3RMIX Input 1 Source */
+ { 0x000009C9, 0x0080 }, /* R2505 - DSP3RMIX Input 1 Volume */
+ { 0x000009CA, 0x0000 }, /* R2506 - DSP3RMIX Input 2 Source */
+ { 0x000009CB, 0x0080 }, /* R2507 - DSP3RMIX Input 2 Volume */
+ { 0x000009CC, 0x0000 }, /* R2508 - DSP3RMIX Input 3 Source */
+ { 0x000009CD, 0x0080 }, /* R2509 - DSP3RMIX Input 3 Volume */
+ { 0x000009CE, 0x0000 }, /* R2510 - DSP3RMIX Input 4 Source */
+ { 0x000009CF, 0x0080 }, /* R2511 - DSP3RMIX Input 4 Volume */
+ { 0x000009D0, 0x0000 }, /* R2512 - DSP3AUX1MIX Input 1 Source */
+ { 0x000009D8, 0x0000 }, /* R2520 - DSP3AUX2MIX Input 1 Source */
+ { 0x000009E0, 0x0000 }, /* R2528 - DSP3AUX3MIX Input 1 Source */
+ { 0x000009E8, 0x0000 }, /* R2536 - DSP3AUX4MIX Input 1 Source */
+ { 0x000009F0, 0x0000 }, /* R2544 - DSP3AUX5MIX Input 1 Source */
+ { 0x000009F8, 0x0000 }, /* R2552 - DSP3AUX6MIX Input 1 Source */
+ { 0x00000A80, 0x0000 }, /* R2688 - ASRC1LMIX Input 1 Source */
+ { 0x00000A88, 0x0000 }, /* R2696 - ASRC1RMIX Input 1 Source */
+ { 0x00000A90, 0x0000 }, /* R2704 - ASRC2LMIX Input 1 Source */
+ { 0x00000A98, 0x0000 }, /* R2712 - ASRC2RMIX Input 1 Source */
+ { 0x00000B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */
+ { 0x00000B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */
+ { 0x00000B10, 0x0000 }, /* R2832 - ISRC1DEC3MIX Input 1 Source */
+ { 0x00000B18, 0x0000 }, /* R2840 - ISRC1DEC4MIX Input 1 Source */
+ { 0x00000B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */
+ { 0x00000B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */
+ { 0x00000B30, 0x0000 }, /* R2864 - ISRC1INT3MIX Input 1 Source */
+ { 0x00000B38, 0x0000 }, /* R2872 - ISRC1INT4MIX Input 1 Source */
+ { 0x00000B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */
+ { 0x00000B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */
+ { 0x00000B50, 0x0000 }, /* R2896 - ISRC2DEC3MIX Input 1 Source */
+ { 0x00000B58, 0x0000 }, /* R2904 - ISRC2DEC4MIX Input 1 Source */
+ { 0x00000B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */
+ { 0x00000B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */
+ { 0x00000B70, 0x0000 }, /* R2928 - ISRC2INT3MIX Input 1 Source */
+ { 0x00000B78, 0x0000 }, /* R2936 - ISRC2INT4MIX Input 1 Source */
+ { 0x00000B80, 0x0000 }, /* R2944 - ISRC3DEC1MIX Input 1 Source */
+ { 0x00000B88, 0x0000 }, /* R2952 - ISRC3DEC2MIX Input 1 Source */
+ { 0x00000B90, 0x0000 }, /* R2960 - ISRC3DEC3MIX Input 1 Source */
+ { 0x00000B98, 0x0000 }, /* R2968 - ISRC3DEC4MIX Input 1 Source */
+ { 0x00000BA0, 0x0000 }, /* R2976 - ISRC3INT1MIX Input 1 Source */
+ { 0x00000BA8, 0x0000 }, /* R2984 - ISRC3INT2MIX Input 1 Source */
+ { 0x00000BB0, 0x0000 }, /* R2992 - ISRC3INT3MIX Input 1 Source */
+ { 0x00000BB8, 0x0000 }, /* R3000 - ISRC3INT4MIX Input 1 Source */
+ { 0x00000C00, 0xA101 }, /* R3072 - GPIO1 CTRL */
+ { 0x00000C01, 0xA101 }, /* R3073 - GPIO2 CTRL */
+ { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */
+ { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */
+ { 0x00000C20, 0x0002 }, /* R3104 - Misc Pad Ctrl 1 */
+ { 0x00000C21, 0x8001 }, /* R3105 - Misc Pad Ctrl 2 */
+ { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */
+ { 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */
+ { 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */
+ { 0x00000C25, 0x0000 }, /* R3109 - Misc Pad Ctrl 6 */
+ { 0x00000C30, 0x0404 }, /* R3120 - Misc Pad Ctrl 7 */
+ { 0x00000C32, 0x0404 }, /* R3122 - Misc Pad Ctrl 9 */
+ { 0x00000C33, 0x0404 }, /* R3123 - Misc Pad Ctrl 10 */
+ { 0x00000C34, 0x0404 }, /* R3124 - Misc Pad Ctrl 11 */
+ { 0x00000C35, 0x0404 }, /* R3125 - Misc Pad Ctrl 12 */
+ { 0x00000C36, 0x0400 }, /* R3126 - Misc Pad Ctrl 13 */
+ { 0x00000C37, 0x0404 }, /* R3127 - Misc Pad Ctrl 14 */
+ { 0x00000C39, 0x0400 }, /* R3129 - Misc Pad Ctrl 16 */
+ { 0x00000D08, 0x0007 }, /* R3336 - Interrupt Status 1 Mask */
+ { 0x00000D09, 0x06FF }, /* R3337 - Interrupt Status 2 Mask */
+ { 0x00000D0A, 0xCFEF }, /* R3338 - Interrupt Status 3 Mask */
+ { 0x00000D0B, 0xFFC3 }, /* R3339 - Interrupt Status 4 Mask */
+ { 0x00000D0C, 0x000B }, /* R3340 - Interrupt Status 5 Mask */
+ { 0x00000D0D, 0xD005 }, /* R3341 - Interrupt Status 6 Mask */
+ { 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */
+ { 0x00000D18, 0x0007 }, /* R3352 - IRQ2 Status 1 Mask */
+ { 0x00000D19, 0x06FF }, /* R3353 - IRQ2 Status 2 Mask */
+ { 0x00000D1A, 0xCFEF }, /* R3354 - IRQ2 Status 3 Mask */
+ { 0x00000D1B, 0xFFC3 }, /* R3355 - IRQ2 Status 4 Mask */
+ { 0x00000D1C, 0x000B }, /* R3356 - IRQ2 Status 5 Mask */
+ { 0x00000D1D, 0xD005 }, /* R3357 - IRQ2 Status 6 Mask */
+ { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */
+ { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */
+ { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */
+ { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */
+ { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */
+ { 0x00000E13, 0x03FE }, /* R3603 - EQ1_4 */
+ { 0x00000E14, 0x00E0 }, /* R3604 - EQ1_5 */
+ { 0x00000E15, 0x1EC4 }, /* R3605 - EQ1_6 */
+ { 0x00000E16, 0xF136 }, /* R3606 - EQ1_7 */
+ { 0x00000E17, 0x0409 }, /* R3607 - EQ1_8 */
+ { 0x00000E18, 0x04CC }, /* R3608 - EQ1_9 */
+ { 0x00000E19, 0x1C9B }, /* R3609 - EQ1_10 */
+ { 0x00000E1A, 0xF337 }, /* R3610 - EQ1_11 */
+ { 0x00000E1B, 0x040B }, /* R3611 - EQ1_12 */
+ { 0x00000E1C, 0x0CBB }, /* R3612 - EQ1_13 */
+ { 0x00000E1D, 0x16F8 }, /* R3613 - EQ1_14 */
+ { 0x00000E1E, 0xF7D9 }, /* R3614 - EQ1_15 */
+ { 0x00000E1F, 0x040A }, /* R3615 - EQ1_16 */
+ { 0x00000E20, 0x1F14 }, /* R3616 - EQ1_17 */
+ { 0x00000E21, 0x058C }, /* R3617 - EQ1_18 */
+ { 0x00000E22, 0x0563 }, /* R3618 - EQ1_19 */
+ { 0x00000E23, 0x4000 }, /* R3619 - EQ1_20 */
+ { 0x00000E24, 0x0B75 }, /* R3620 - EQ1_21 */
+ { 0x00000E26, 0x6318 }, /* R3622 - EQ2_1 */
+ { 0x00000E27, 0x6300 }, /* R3623 - EQ2_2 */
+ { 0x00000E28, 0x0FC8 }, /* R3624 - EQ2_3 */
+ { 0x00000E29, 0x03FE }, /* R3625 - EQ2_4 */
+ { 0x00000E2A, 0x00E0 }, /* R3626 - EQ2_5 */
+ { 0x00000E2B, 0x1EC4 }, /* R3627 - EQ2_6 */
+ { 0x00000E2C, 0xF136 }, /* R3628 - EQ2_7 */
+ { 0x00000E2D, 0x0409 }, /* R3629 - EQ2_8 */
+ { 0x00000E2E, 0x04CC }, /* R3630 - EQ2_9 */
+ { 0x00000E2F, 0x1C9B }, /* R3631 - EQ2_10 */
+ { 0x00000E30, 0xF337 }, /* R3632 - EQ2_11 */
+ { 0x00000E31, 0x040B }, /* R3633 - EQ2_12 */
+ { 0x00000E32, 0x0CBB }, /* R3634 - EQ2_13 */
+ { 0x00000E33, 0x16F8 }, /* R3635 - EQ2_14 */
+ { 0x00000E34, 0xF7D9 }, /* R3636 - EQ2_15 */
+ { 0x00000E35, 0x040A }, /* R3637 - EQ2_16 */
+ { 0x00000E36, 0x1F14 }, /* R3638 - EQ2_17 */
+ { 0x00000E37, 0x058C }, /* R3639 - EQ2_18 */
+ { 0x00000E38, 0x0563 }, /* R3640 - EQ2_19 */
+ { 0x00000E39, 0x4000 }, /* R3641 - EQ2_20 */
+ { 0x00000E3A, 0x0B75 }, /* R3642 - EQ2_21 */
+ { 0x00000E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */
+ { 0x00000E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */
+ { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */
+ { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */
+ { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */
+ { 0x00000E89, 0x0018 }, /* R3721 - DRC2 ctrl1 */
+ { 0x00000E8A, 0x0933 }, /* R3722 - DRC2 ctrl2 */
+ { 0x00000E8B, 0x0018 }, /* R3723 - DRC2 ctrl3 */
+ { 0x00000E8C, 0x0000 }, /* R3724 - DRC2 ctrl4 */
+ { 0x00000E8D, 0x0000 }, /* R3725 - DRC2 ctrl5 */
+ { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */
+ { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */
+ { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */
+ { 0x00000EC5, 0x0000 }, /* R3781 - HPLPF2_2 */
+ { 0x00000EC8, 0x0000 }, /* R3784 - HPLPF3_1 */
+ { 0x00000EC9, 0x0000 }, /* R3785 - HPLPF3_2 */
+ { 0x00000ECC, 0x0000 }, /* R3788 - HPLPF4_1 */
+ { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */
+ { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */
+ { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */
+ { 0x00000EE3, 0x4000 }, /* R3811 - ASRC_RATE2 */
+ { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */
+ { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */
+ { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */
+ { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */
+ { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */
+ { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */
+ { 0x00000EF6, 0x0000 }, /* R3830 - ISRC 3 CTRL 1 */
+ { 0x00000EF7, 0x0000 }, /* R3831 - ISRC 3 CTRL 2 */
+ { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */
+ { 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */
+ { 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */
+};
+
+static bool cs47l24_is_adsp_memory(unsigned int reg)
+{
+ switch (reg) {
+ case 0x200000 ... 0x205fff: /* DSP2 PM */
+ case 0x280000 ... 0x281fff: /* DSP2 ZM */
+ case 0x290000 ... 0x2a7fff: /* DSP2 XM */
+ case 0x2a8000 ... 0x2b3fff: /* DSP2 YM */
+ case 0x300000 ... 0x308fff: /* DSP3 PM */
+ case 0x380000 ... 0x381fff: /* DSP3 ZM */
+ case 0x390000 ... 0x3a7fff: /* DSP3 XM */
+ case 0x3a8000 ... 0x3b3fff: /* DSP3 YM */
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l24_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ARIZONA_SOFTWARE_RESET:
+ case ARIZONA_DEVICE_REVISION:
+ case ARIZONA_CTRL_IF_SPI_CFG_1:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_0:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_1:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_2:
+ case ARIZONA_TONE_GENERATOR_1:
+ case ARIZONA_TONE_GENERATOR_2:
+ case ARIZONA_TONE_GENERATOR_3:
+ case ARIZONA_TONE_GENERATOR_4:
+ case ARIZONA_TONE_GENERATOR_5:
+ case ARIZONA_PWM_DRIVE_1:
+ case ARIZONA_PWM_DRIVE_2:
+ case ARIZONA_PWM_DRIVE_3:
+ case ARIZONA_SEQUENCE_CONTROL:
+ case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+ case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+ case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+ case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+ case ARIZONA_COMFORT_NOISE_GENERATOR:
+ case ARIZONA_HAPTICS_CONTROL_1:
+ case ARIZONA_HAPTICS_CONTROL_2:
+ case ARIZONA_HAPTICS_PHASE_1_INTENSITY:
+ case ARIZONA_HAPTICS_PHASE_1_DURATION:
+ case ARIZONA_HAPTICS_PHASE_2_INTENSITY:
+ case ARIZONA_HAPTICS_PHASE_2_DURATION:
+ case ARIZONA_HAPTICS_PHASE_3_INTENSITY:
+ case ARIZONA_HAPTICS_PHASE_3_DURATION:
+ case ARIZONA_HAPTICS_STATUS:
+ case ARIZONA_CLOCK_32K_1:
+ case ARIZONA_SYSTEM_CLOCK_1:
+ case ARIZONA_SAMPLE_RATE_1:
+ case ARIZONA_SAMPLE_RATE_2:
+ case ARIZONA_SAMPLE_RATE_3:
+ case ARIZONA_SAMPLE_RATE_1_STATUS:
+ case ARIZONA_SAMPLE_RATE_2_STATUS:
+ case ARIZONA_SAMPLE_RATE_3_STATUS:
+ case ARIZONA_ASYNC_CLOCK_1:
+ case ARIZONA_ASYNC_SAMPLE_RATE_1:
+ case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case ARIZONA_ASYNC_SAMPLE_RATE_2:
+ case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case ARIZONA_OUTPUT_SYSTEM_CLOCK:
+ case ARIZONA_OUTPUT_ASYNC_CLOCK:
+ case ARIZONA_RATE_ESTIMATOR_1:
+ case ARIZONA_RATE_ESTIMATOR_2:
+ case ARIZONA_RATE_ESTIMATOR_3:
+ case ARIZONA_RATE_ESTIMATOR_4:
+ case ARIZONA_RATE_ESTIMATOR_5:
+ case ARIZONA_FLL1_CONTROL_1:
+ case ARIZONA_FLL1_CONTROL_2:
+ case ARIZONA_FLL1_CONTROL_3:
+ case ARIZONA_FLL1_CONTROL_4:
+ case ARIZONA_FLL1_CONTROL_5:
+ case ARIZONA_FLL1_CONTROL_6:
+ case ARIZONA_FLL1_CONTROL_7:
+ case ARIZONA_FLL1_LOOP_FILTER_TEST_1:
+ case ARIZONA_FLL1_NCO_TEST_0:
+ case ARIZONA_FLL1_SYNCHRONISER_1:
+ case ARIZONA_FLL1_SYNCHRONISER_2:
+ case ARIZONA_FLL1_SYNCHRONISER_3:
+ case ARIZONA_FLL1_SYNCHRONISER_4:
+ case ARIZONA_FLL1_SYNCHRONISER_5:
+ case ARIZONA_FLL1_SYNCHRONISER_6:
+ case ARIZONA_FLL1_SYNCHRONISER_7:
+ case ARIZONA_FLL1_SPREAD_SPECTRUM:
+ case ARIZONA_FLL1_GPIO_CLOCK:
+ case ARIZONA_FLL2_CONTROL_1:
+ case ARIZONA_FLL2_CONTROL_2:
+ case ARIZONA_FLL2_CONTROL_3:
+ case ARIZONA_FLL2_CONTROL_4:
+ case ARIZONA_FLL2_CONTROL_5:
+ case ARIZONA_FLL2_CONTROL_6:
+ case ARIZONA_FLL2_CONTROL_7:
+ case ARIZONA_FLL2_LOOP_FILTER_TEST_1:
+ case ARIZONA_FLL2_NCO_TEST_0:
+ case ARIZONA_FLL2_SYNCHRONISER_1:
+ case ARIZONA_FLL2_SYNCHRONISER_2:
+ case ARIZONA_FLL2_SYNCHRONISER_3:
+ case ARIZONA_FLL2_SYNCHRONISER_4:
+ case ARIZONA_FLL2_SYNCHRONISER_5:
+ case ARIZONA_FLL2_SYNCHRONISER_6:
+ case ARIZONA_FLL2_SYNCHRONISER_7:
+ case ARIZONA_FLL2_SPREAD_SPECTRUM:
+ case ARIZONA_FLL2_GPIO_CLOCK:
+ case ARIZONA_MIC_BIAS_CTRL_1:
+ case ARIZONA_MIC_BIAS_CTRL_2:
+ case ARIZONA_HP_CTRL_1L:
+ case ARIZONA_HP_CTRL_1R:
+ case ARIZONA_INPUT_ENABLES:
+ case ARIZONA_INPUT_ENABLES_STATUS:
+ case ARIZONA_INPUT_RATE:
+ case ARIZONA_INPUT_VOLUME_RAMP:
+ case ARIZONA_HPF_CONTROL:
+ case ARIZONA_IN1L_CONTROL:
+ case ARIZONA_ADC_DIGITAL_VOLUME_1L:
+ case ARIZONA_DMIC1L_CONTROL:
+ case ARIZONA_IN1R_CONTROL:
+ case ARIZONA_ADC_DIGITAL_VOLUME_1R:
+ case ARIZONA_DMIC1R_CONTROL:
+ case ARIZONA_IN2L_CONTROL:
+ case ARIZONA_ADC_DIGITAL_VOLUME_2L:
+ case ARIZONA_DMIC2L_CONTROL:
+ case ARIZONA_IN2R_CONTROL:
+ case ARIZONA_ADC_DIGITAL_VOLUME_2R:
+ case ARIZONA_DMIC2R_CONTROL:
+ case ARIZONA_OUTPUT_ENABLES_1:
+ case ARIZONA_OUTPUT_STATUS_1:
+ case ARIZONA_RAW_OUTPUT_STATUS_1:
+ case ARIZONA_OUTPUT_RATE_1:
+ case ARIZONA_OUTPUT_VOLUME_RAMP:
+ case ARIZONA_OUTPUT_PATH_CONFIG_1L:
+ case ARIZONA_DAC_DIGITAL_VOLUME_1L:
+ case ARIZONA_DAC_VOLUME_LIMIT_1L:
+ case ARIZONA_NOISE_GATE_SELECT_1L:
+ case ARIZONA_DAC_DIGITAL_VOLUME_1R:
+ case ARIZONA_DAC_VOLUME_LIMIT_1R:
+ case ARIZONA_NOISE_GATE_SELECT_1R:
+ case ARIZONA_DAC_DIGITAL_VOLUME_4L:
+ case ARIZONA_OUT_VOLUME_4L:
+ case ARIZONA_NOISE_GATE_SELECT_4L:
+ case ARIZONA_DAC_AEC_CONTROL_1:
+ case ARIZONA_NOISE_GATE_CONTROL:
+ case ARIZONA_HP1_SHORT_CIRCUIT_CTRL:
+ case ARIZONA_AIF1_BCLK_CTRL:
+ case ARIZONA_AIF1_TX_PIN_CTRL:
+ case ARIZONA_AIF1_RX_PIN_CTRL:
+ case ARIZONA_AIF1_RATE_CTRL:
+ case ARIZONA_AIF1_FORMAT:
+ case ARIZONA_AIF1_RX_BCLK_RATE:
+ case ARIZONA_AIF1_FRAME_CTRL_1:
+ case ARIZONA_AIF1_FRAME_CTRL_2:
+ case ARIZONA_AIF1_FRAME_CTRL_3:
+ case ARIZONA_AIF1_FRAME_CTRL_4:
+ case ARIZONA_AIF1_FRAME_CTRL_5:
+ case ARIZONA_AIF1_FRAME_CTRL_6:
+ case ARIZONA_AIF1_FRAME_CTRL_7:
+ case ARIZONA_AIF1_FRAME_CTRL_8:
+ case ARIZONA_AIF1_FRAME_CTRL_9:
+ case ARIZONA_AIF1_FRAME_CTRL_10:
+ case ARIZONA_AIF1_FRAME_CTRL_11:
+ case ARIZONA_AIF1_FRAME_CTRL_12:
+ case ARIZONA_AIF1_FRAME_CTRL_13:
+ case ARIZONA_AIF1_FRAME_CTRL_14:
+ case ARIZONA_AIF1_FRAME_CTRL_15:
+ case ARIZONA_AIF1_FRAME_CTRL_16:
+ case ARIZONA_AIF1_FRAME_CTRL_17:
+ case ARIZONA_AIF1_FRAME_CTRL_18:
+ case ARIZONA_AIF1_TX_ENABLES:
+ case ARIZONA_AIF1_RX_ENABLES:
+ case ARIZONA_AIF2_BCLK_CTRL:
+ case ARIZONA_AIF2_TX_PIN_CTRL:
+ case ARIZONA_AIF2_RX_PIN_CTRL:
+ case ARIZONA_AIF2_RATE_CTRL:
+ case ARIZONA_AIF2_FORMAT:
+ case ARIZONA_AIF2_RX_BCLK_RATE:
+ case ARIZONA_AIF2_FRAME_CTRL_1:
+ 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:
+ case ARIZONA_AIF3_TX_PIN_CTRL:
+ case ARIZONA_AIF3_RX_PIN_CTRL:
+ case ARIZONA_AIF3_RATE_CTRL:
+ case ARIZONA_AIF3_FORMAT:
+ case ARIZONA_AIF3_RX_BCLK_RATE:
+ case ARIZONA_AIF3_FRAME_CTRL_1:
+ case ARIZONA_AIF3_FRAME_CTRL_2:
+ case ARIZONA_AIF3_FRAME_CTRL_3:
+ case ARIZONA_AIF3_FRAME_CTRL_4:
+ case ARIZONA_AIF3_FRAME_CTRL_11:
+ case ARIZONA_AIF3_FRAME_CTRL_12:
+ case ARIZONA_AIF3_TX_ENABLES:
+ case ARIZONA_AIF3_RX_ENABLES:
+ case ARIZONA_PWM1MIX_INPUT_1_SOURCE:
+ case ARIZONA_PWM1MIX_INPUT_1_VOLUME:
+ case ARIZONA_PWM1MIX_INPUT_2_SOURCE:
+ case ARIZONA_PWM1MIX_INPUT_2_VOLUME:
+ case ARIZONA_PWM1MIX_INPUT_3_SOURCE:
+ case ARIZONA_PWM1MIX_INPUT_3_VOLUME:
+ case ARIZONA_PWM1MIX_INPUT_4_SOURCE:
+ case ARIZONA_PWM1MIX_INPUT_4_VOLUME:
+ case ARIZONA_PWM2MIX_INPUT_1_SOURCE:
+ case ARIZONA_PWM2MIX_INPUT_1_VOLUME:
+ case ARIZONA_PWM2MIX_INPUT_2_SOURCE:
+ case ARIZONA_PWM2MIX_INPUT_2_VOLUME:
+ case ARIZONA_PWM2MIX_INPUT_3_SOURCE:
+ case ARIZONA_PWM2MIX_INPUT_3_VOLUME:
+ case ARIZONA_PWM2MIX_INPUT_4_SOURCE:
+ case ARIZONA_PWM2MIX_INPUT_4_VOLUME:
+ case ARIZONA_OUT1LMIX_INPUT_1_SOURCE:
+ case ARIZONA_OUT1LMIX_INPUT_1_VOLUME:
+ case ARIZONA_OUT1LMIX_INPUT_2_SOURCE:
+ case ARIZONA_OUT1LMIX_INPUT_2_VOLUME:
+ case ARIZONA_OUT1LMIX_INPUT_3_SOURCE:
+ case ARIZONA_OUT1LMIX_INPUT_3_VOLUME:
+ case ARIZONA_OUT1LMIX_INPUT_4_SOURCE:
+ case ARIZONA_OUT1LMIX_INPUT_4_VOLUME:
+ case ARIZONA_OUT1RMIX_INPUT_1_SOURCE:
+ case ARIZONA_OUT1RMIX_INPUT_1_VOLUME:
+ case ARIZONA_OUT1RMIX_INPUT_2_SOURCE:
+ case ARIZONA_OUT1RMIX_INPUT_2_VOLUME:
+ case ARIZONA_OUT1RMIX_INPUT_3_SOURCE:
+ case ARIZONA_OUT1RMIX_INPUT_3_VOLUME:
+ case ARIZONA_OUT1RMIX_INPUT_4_SOURCE:
+ case ARIZONA_OUT1RMIX_INPUT_4_VOLUME:
+ case ARIZONA_OUT4LMIX_INPUT_1_SOURCE:
+ case ARIZONA_OUT4LMIX_INPUT_1_VOLUME:
+ case ARIZONA_OUT4LMIX_INPUT_2_SOURCE:
+ case ARIZONA_OUT4LMIX_INPUT_2_VOLUME:
+ case ARIZONA_OUT4LMIX_INPUT_3_SOURCE:
+ case ARIZONA_OUT4LMIX_INPUT_3_VOLUME:
+ case ARIZONA_OUT4LMIX_INPUT_4_SOURCE:
+ case ARIZONA_OUT4LMIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX3MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX3MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX3MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX3MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX3MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX3MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX3MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX3MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX4MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX4MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX4MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX4MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX4MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX4MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX4MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX4MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX5MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX5MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX5MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX5MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX5MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX5MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX5MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX5MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF2TX6MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF2TX6MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF2TX6MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF2TX6MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF2TX6MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF2TX6MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF2TX6MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF2TX6MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF3TX1MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF3TX1MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF3TX1MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF3TX1MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF3TX1MIX_INPUT_4_VOLUME:
+ case ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE:
+ case ARIZONA_AIF3TX2MIX_INPUT_1_VOLUME:
+ case ARIZONA_AIF3TX2MIX_INPUT_2_SOURCE:
+ case ARIZONA_AIF3TX2MIX_INPUT_2_VOLUME:
+ case ARIZONA_AIF3TX2MIX_INPUT_3_SOURCE:
+ case ARIZONA_AIF3TX2MIX_INPUT_3_VOLUME:
+ case ARIZONA_AIF3TX2MIX_INPUT_4_SOURCE:
+ case ARIZONA_AIF3TX2MIX_INPUT_4_VOLUME:
+ case ARIZONA_EQ1MIX_INPUT_1_SOURCE:
+ case ARIZONA_EQ1MIX_INPUT_1_VOLUME:
+ case ARIZONA_EQ1MIX_INPUT_2_SOURCE:
+ case ARIZONA_EQ1MIX_INPUT_2_VOLUME:
+ case ARIZONA_EQ1MIX_INPUT_3_SOURCE:
+ case ARIZONA_EQ1MIX_INPUT_3_VOLUME:
+ case ARIZONA_EQ1MIX_INPUT_4_SOURCE:
+ case ARIZONA_EQ1MIX_INPUT_4_VOLUME:
+ case ARIZONA_EQ2MIX_INPUT_1_SOURCE:
+ case ARIZONA_EQ2MIX_INPUT_1_VOLUME:
+ case ARIZONA_EQ2MIX_INPUT_2_SOURCE:
+ case ARIZONA_EQ2MIX_INPUT_2_VOLUME:
+ case ARIZONA_EQ2MIX_INPUT_3_SOURCE:
+ case ARIZONA_EQ2MIX_INPUT_3_VOLUME:
+ case ARIZONA_EQ2MIX_INPUT_4_SOURCE:
+ case ARIZONA_EQ2MIX_INPUT_4_VOLUME:
+ case ARIZONA_DRC1LMIX_INPUT_1_SOURCE:
+ case ARIZONA_DRC1LMIX_INPUT_1_VOLUME:
+ case ARIZONA_DRC1LMIX_INPUT_2_SOURCE:
+ case ARIZONA_DRC1LMIX_INPUT_2_VOLUME:
+ case ARIZONA_DRC1LMIX_INPUT_3_SOURCE:
+ case ARIZONA_DRC1LMIX_INPUT_3_VOLUME:
+ case ARIZONA_DRC1LMIX_INPUT_4_SOURCE:
+ case ARIZONA_DRC1LMIX_INPUT_4_VOLUME:
+ case ARIZONA_DRC1RMIX_INPUT_1_SOURCE:
+ case ARIZONA_DRC1RMIX_INPUT_1_VOLUME:
+ case ARIZONA_DRC1RMIX_INPUT_2_SOURCE:
+ case ARIZONA_DRC1RMIX_INPUT_2_VOLUME:
+ case ARIZONA_DRC1RMIX_INPUT_3_SOURCE:
+ case ARIZONA_DRC1RMIX_INPUT_3_VOLUME:
+ case ARIZONA_DRC1RMIX_INPUT_4_SOURCE:
+ case ARIZONA_DRC1RMIX_INPUT_4_VOLUME:
+ case ARIZONA_DRC2LMIX_INPUT_1_SOURCE:
+ case ARIZONA_DRC2LMIX_INPUT_1_VOLUME:
+ case ARIZONA_DRC2LMIX_INPUT_2_SOURCE:
+ case ARIZONA_DRC2LMIX_INPUT_2_VOLUME:
+ case ARIZONA_DRC2LMIX_INPUT_3_SOURCE:
+ case ARIZONA_DRC2LMIX_INPUT_3_VOLUME:
+ case ARIZONA_DRC2LMIX_INPUT_4_SOURCE:
+ case ARIZONA_DRC2LMIX_INPUT_4_VOLUME:
+ case ARIZONA_DRC2RMIX_INPUT_1_SOURCE:
+ case ARIZONA_DRC2RMIX_INPUT_1_VOLUME:
+ case ARIZONA_DRC2RMIX_INPUT_2_SOURCE:
+ case ARIZONA_DRC2RMIX_INPUT_2_VOLUME:
+ case ARIZONA_DRC2RMIX_INPUT_3_SOURCE:
+ case ARIZONA_DRC2RMIX_INPUT_3_VOLUME:
+ case ARIZONA_DRC2RMIX_INPUT_4_SOURCE:
+ case ARIZONA_DRC2RMIX_INPUT_4_VOLUME:
+ case ARIZONA_HPLP1MIX_INPUT_1_SOURCE:
+ case ARIZONA_HPLP1MIX_INPUT_1_VOLUME:
+ case ARIZONA_HPLP1MIX_INPUT_2_SOURCE:
+ case ARIZONA_HPLP1MIX_INPUT_2_VOLUME:
+ case ARIZONA_HPLP1MIX_INPUT_3_SOURCE:
+ case ARIZONA_HPLP1MIX_INPUT_3_VOLUME:
+ case ARIZONA_HPLP1MIX_INPUT_4_SOURCE:
+ case ARIZONA_HPLP1MIX_INPUT_4_VOLUME:
+ case ARIZONA_HPLP2MIX_INPUT_1_SOURCE:
+ case ARIZONA_HPLP2MIX_INPUT_1_VOLUME:
+ case ARIZONA_HPLP2MIX_INPUT_2_SOURCE:
+ case ARIZONA_HPLP2MIX_INPUT_2_VOLUME:
+ case ARIZONA_HPLP2MIX_INPUT_3_SOURCE:
+ case ARIZONA_HPLP2MIX_INPUT_3_VOLUME:
+ case ARIZONA_HPLP2MIX_INPUT_4_SOURCE:
+ case ARIZONA_HPLP2MIX_INPUT_4_VOLUME:
+ case ARIZONA_HPLP3MIX_INPUT_1_SOURCE:
+ case ARIZONA_HPLP3MIX_INPUT_1_VOLUME:
+ case ARIZONA_HPLP3MIX_INPUT_2_SOURCE:
+ case ARIZONA_HPLP3MIX_INPUT_2_VOLUME:
+ case ARIZONA_HPLP3MIX_INPUT_3_SOURCE:
+ case ARIZONA_HPLP3MIX_INPUT_3_VOLUME:
+ case ARIZONA_HPLP3MIX_INPUT_4_SOURCE:
+ case ARIZONA_HPLP3MIX_INPUT_4_VOLUME:
+ case ARIZONA_HPLP4MIX_INPUT_1_SOURCE:
+ case ARIZONA_HPLP4MIX_INPUT_1_VOLUME:
+ case ARIZONA_HPLP4MIX_INPUT_2_SOURCE:
+ case ARIZONA_HPLP4MIX_INPUT_2_VOLUME:
+ case ARIZONA_HPLP4MIX_INPUT_3_SOURCE:
+ case ARIZONA_HPLP4MIX_INPUT_3_VOLUME:
+ case ARIZONA_HPLP4MIX_INPUT_4_SOURCE:
+ case ARIZONA_HPLP4MIX_INPUT_4_VOLUME:
+ case ARIZONA_DSP2LMIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2LMIX_INPUT_1_VOLUME:
+ case ARIZONA_DSP2LMIX_INPUT_2_SOURCE:
+ case ARIZONA_DSP2LMIX_INPUT_2_VOLUME:
+ case ARIZONA_DSP2LMIX_INPUT_3_SOURCE:
+ case ARIZONA_DSP2LMIX_INPUT_3_VOLUME:
+ case ARIZONA_DSP2LMIX_INPUT_4_SOURCE:
+ case ARIZONA_DSP2LMIX_INPUT_4_VOLUME:
+ case ARIZONA_DSP2RMIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2RMIX_INPUT_1_VOLUME:
+ case ARIZONA_DSP2RMIX_INPUT_2_SOURCE:
+ case ARIZONA_DSP2RMIX_INPUT_2_VOLUME:
+ case ARIZONA_DSP2RMIX_INPUT_3_SOURCE:
+ case ARIZONA_DSP2RMIX_INPUT_3_VOLUME:
+ case ARIZONA_DSP2RMIX_INPUT_4_SOURCE:
+ case ARIZONA_DSP2RMIX_INPUT_4_VOLUME:
+ case ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3LMIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3LMIX_INPUT_1_VOLUME:
+ case ARIZONA_DSP3LMIX_INPUT_2_SOURCE:
+ case ARIZONA_DSP3LMIX_INPUT_2_VOLUME:
+ case ARIZONA_DSP3LMIX_INPUT_3_SOURCE:
+ case ARIZONA_DSP3LMIX_INPUT_3_VOLUME:
+ case ARIZONA_DSP3LMIX_INPUT_4_SOURCE:
+ case ARIZONA_DSP3LMIX_INPUT_4_VOLUME:
+ case ARIZONA_DSP3RMIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3RMIX_INPUT_1_VOLUME:
+ case ARIZONA_DSP3RMIX_INPUT_2_SOURCE:
+ case ARIZONA_DSP3RMIX_INPUT_2_VOLUME:
+ case ARIZONA_DSP3RMIX_INPUT_3_SOURCE:
+ case ARIZONA_DSP3RMIX_INPUT_3_VOLUME:
+ case ARIZONA_DSP3RMIX_INPUT_4_SOURCE:
+ case ARIZONA_DSP3RMIX_INPUT_4_VOLUME:
+ case ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3AUX2MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3AUX3MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3AUX4MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3AUX5MIX_INPUT_1_SOURCE:
+ case ARIZONA_DSP3AUX6MIX_INPUT_1_SOURCE:
+ case ARIZONA_ASRC1LMIX_INPUT_1_SOURCE:
+ case ARIZONA_ASRC1RMIX_INPUT_1_SOURCE:
+ case ARIZONA_ASRC2LMIX_INPUT_1_SOURCE:
+ case ARIZONA_ASRC2RMIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE:
+ case ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE:
+ case ARIZONA_GPIO1_CTRL:
+ case ARIZONA_GPIO2_CTRL:
+ case ARIZONA_IRQ_CTRL_1:
+ case ARIZONA_GPIO_DEBOUNCE_CONFIG:
+ case ARIZONA_MISC_PAD_CTRL_1:
+ case ARIZONA_MISC_PAD_CTRL_2:
+ case ARIZONA_MISC_PAD_CTRL_3:
+ case ARIZONA_MISC_PAD_CTRL_4:
+ case ARIZONA_MISC_PAD_CTRL_5:
+ case ARIZONA_MISC_PAD_CTRL_6:
+ case ARIZONA_MISC_PAD_CTRL_7:
+ case ARIZONA_MISC_PAD_CTRL_9:
+ case ARIZONA_MISC_PAD_CTRL_10:
+ case ARIZONA_MISC_PAD_CTRL_11:
+ case ARIZONA_MISC_PAD_CTRL_12:
+ case ARIZONA_MISC_PAD_CTRL_13:
+ case ARIZONA_MISC_PAD_CTRL_14:
+ case ARIZONA_MISC_PAD_CTRL_16:
+ case ARIZONA_INTERRUPT_STATUS_1:
+ case ARIZONA_INTERRUPT_STATUS_2:
+ case ARIZONA_INTERRUPT_STATUS_3:
+ case ARIZONA_INTERRUPT_STATUS_4:
+ case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
+ 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:
+ case ARIZONA_INTERRUPT_STATUS_6_MASK:
+ case ARIZONA_INTERRUPT_CONTROL:
+ case ARIZONA_IRQ2_STATUS_1:
+ case ARIZONA_IRQ2_STATUS_2:
+ case ARIZONA_IRQ2_STATUS_3:
+ case ARIZONA_IRQ2_STATUS_4:
+ case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
+ case ARIZONA_IRQ2_STATUS_1_MASK:
+ case ARIZONA_IRQ2_STATUS_2_MASK:
+ case ARIZONA_IRQ2_STATUS_3_MASK:
+ case ARIZONA_IRQ2_STATUS_4_MASK:
+ case ARIZONA_IRQ2_STATUS_5_MASK:
+ case ARIZONA_IRQ2_STATUS_6_MASK:
+ case ARIZONA_IRQ2_CONTROL:
+ case ARIZONA_INTERRUPT_RAW_STATUS_2:
+ case ARIZONA_INTERRUPT_RAW_STATUS_3:
+ case ARIZONA_INTERRUPT_RAW_STATUS_4:
+ case ARIZONA_INTERRUPT_RAW_STATUS_5:
+ case ARIZONA_INTERRUPT_RAW_STATUS_6:
+ case ARIZONA_INTERRUPT_RAW_STATUS_7:
+ case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
+ case ARIZONA_IRQ_PIN_STATUS:
+ case ARIZONA_FX_CTRL1:
+ case ARIZONA_FX_CTRL2:
+ case ARIZONA_EQ1_1:
+ case ARIZONA_EQ1_2:
+ case ARIZONA_EQ1_3:
+ case ARIZONA_EQ1_4:
+ case ARIZONA_EQ1_5:
+ case ARIZONA_EQ1_6:
+ case ARIZONA_EQ1_7:
+ case ARIZONA_EQ1_8:
+ case ARIZONA_EQ1_9:
+ case ARIZONA_EQ1_10:
+ case ARIZONA_EQ1_11:
+ case ARIZONA_EQ1_12:
+ case ARIZONA_EQ1_13:
+ case ARIZONA_EQ1_14:
+ case ARIZONA_EQ1_15:
+ case ARIZONA_EQ1_16:
+ case ARIZONA_EQ1_17:
+ case ARIZONA_EQ1_18:
+ case ARIZONA_EQ1_19:
+ case ARIZONA_EQ1_20:
+ case ARIZONA_EQ1_21:
+ case ARIZONA_EQ2_1:
+ case ARIZONA_EQ2_2:
+ case ARIZONA_EQ2_3:
+ case ARIZONA_EQ2_4:
+ case ARIZONA_EQ2_5:
+ case ARIZONA_EQ2_6:
+ case ARIZONA_EQ2_7:
+ case ARIZONA_EQ2_8:
+ case ARIZONA_EQ2_9:
+ case ARIZONA_EQ2_10:
+ case ARIZONA_EQ2_11:
+ case ARIZONA_EQ2_12:
+ case ARIZONA_EQ2_13:
+ case ARIZONA_EQ2_14:
+ case ARIZONA_EQ2_15:
+ case ARIZONA_EQ2_16:
+ case ARIZONA_EQ2_17:
+ case ARIZONA_EQ2_18:
+ case ARIZONA_EQ2_19:
+ case ARIZONA_EQ2_20:
+ case ARIZONA_EQ2_21:
+ case ARIZONA_DRC1_CTRL1:
+ case ARIZONA_DRC1_CTRL2:
+ case ARIZONA_DRC1_CTRL3:
+ case ARIZONA_DRC1_CTRL4:
+ case ARIZONA_DRC1_CTRL5:
+ case ARIZONA_DRC2_CTRL1:
+ case ARIZONA_DRC2_CTRL2:
+ case ARIZONA_DRC2_CTRL3:
+ case ARIZONA_DRC2_CTRL4:
+ case ARIZONA_DRC2_CTRL5:
+ case ARIZONA_HPLPF1_1:
+ case ARIZONA_HPLPF1_2:
+ case ARIZONA_HPLPF2_1:
+ case ARIZONA_HPLPF2_2:
+ case ARIZONA_HPLPF3_1:
+ case ARIZONA_HPLPF3_2:
+ case ARIZONA_HPLPF4_1:
+ case ARIZONA_HPLPF4_2:
+ case ARIZONA_ASRC_ENABLE:
+ case ARIZONA_ASRC_STATUS:
+ case ARIZONA_ASRC_RATE1:
+ case ARIZONA_ASRC_RATE2:
+ case ARIZONA_ISRC_1_CTRL_1:
+ case ARIZONA_ISRC_1_CTRL_2:
+ case ARIZONA_ISRC_1_CTRL_3:
+ case ARIZONA_ISRC_2_CTRL_1:
+ case ARIZONA_ISRC_2_CTRL_2:
+ case ARIZONA_ISRC_2_CTRL_3:
+ case ARIZONA_ISRC_3_CTRL_1:
+ case ARIZONA_ISRC_3_CTRL_2:
+ case ARIZONA_ISRC_3_CTRL_3:
+ case ARIZONA_DSP2_CONTROL_1:
+ case ARIZONA_DSP2_CLOCKING_1:
+ case ARIZONA_DSP2_STATUS_1:
+ case ARIZONA_DSP2_STATUS_2:
+ case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_STATUS_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_1:
+ case ARIZONA_DSP2_WDMA_BUFFER_2:
+ case ARIZONA_DSP2_WDMA_BUFFER_3:
+ case ARIZONA_DSP2_WDMA_BUFFER_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_5:
+ case ARIZONA_DSP2_WDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_BUFFER_7:
+ case ARIZONA_DSP2_WDMA_BUFFER_8:
+ case ARIZONA_DSP2_RDMA_BUFFER_1:
+ case ARIZONA_DSP2_RDMA_BUFFER_2:
+ case ARIZONA_DSP2_RDMA_BUFFER_3:
+ case ARIZONA_DSP2_RDMA_BUFFER_4:
+ case ARIZONA_DSP2_RDMA_BUFFER_5:
+ case ARIZONA_DSP2_RDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_CONFIG_1:
+ case ARIZONA_DSP2_WDMA_CONFIG_2:
+ case ARIZONA_DSP2_WDMA_OFFSET_1:
+ case ARIZONA_DSP2_RDMA_CONFIG_1:
+ case ARIZONA_DSP2_RDMA_OFFSET_1:
+ case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
+ case ARIZONA_DSP2_SCRATCH_0:
+ case ARIZONA_DSP2_SCRATCH_1:
+ case ARIZONA_DSP2_SCRATCH_2:
+ case ARIZONA_DSP2_SCRATCH_3:
+ case ARIZONA_DSP3_CONTROL_1:
+ case ARIZONA_DSP3_CLOCKING_1:
+ case ARIZONA_DSP3_STATUS_1:
+ case ARIZONA_DSP3_STATUS_2:
+ case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_STATUS_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_1:
+ case ARIZONA_DSP3_WDMA_BUFFER_2:
+ case ARIZONA_DSP3_WDMA_BUFFER_3:
+ case ARIZONA_DSP3_WDMA_BUFFER_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_5:
+ case ARIZONA_DSP3_WDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_BUFFER_7:
+ case ARIZONA_DSP3_WDMA_BUFFER_8:
+ case ARIZONA_DSP3_RDMA_BUFFER_1:
+ case ARIZONA_DSP3_RDMA_BUFFER_2:
+ case ARIZONA_DSP3_RDMA_BUFFER_3:
+ case ARIZONA_DSP3_RDMA_BUFFER_4:
+ case ARIZONA_DSP3_RDMA_BUFFER_5:
+ case ARIZONA_DSP3_RDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_CONFIG_1:
+ case ARIZONA_DSP3_WDMA_CONFIG_2:
+ case ARIZONA_DSP3_WDMA_OFFSET_1:
+ case ARIZONA_DSP3_RDMA_CONFIG_1:
+ case ARIZONA_DSP3_RDMA_OFFSET_1:
+ case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
+ case ARIZONA_DSP3_SCRATCH_0:
+ case ARIZONA_DSP3_SCRATCH_1:
+ case ARIZONA_DSP3_SCRATCH_2:
+ case ARIZONA_DSP3_SCRATCH_3:
+ return true;
+ default:
+ return cs47l24_is_adsp_memory(reg);
+ }
+}
+
+static bool cs47l24_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ARIZONA_SOFTWARE_RESET:
+ case ARIZONA_DEVICE_REVISION:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_0:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_1:
+ case ARIZONA_WRITE_SEQUENCER_CTRL_2:
+ case ARIZONA_HAPTICS_STATUS:
+ case ARIZONA_SAMPLE_RATE_1_STATUS:
+ case ARIZONA_SAMPLE_RATE_2_STATUS:
+ case ARIZONA_SAMPLE_RATE_3_STATUS:
+ case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case ARIZONA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case ARIZONA_HP_CTRL_1L:
+ case ARIZONA_HP_CTRL_1R:
+ case ARIZONA_INPUT_ENABLES_STATUS:
+ case ARIZONA_OUTPUT_STATUS_1:
+ case ARIZONA_RAW_OUTPUT_STATUS_1:
+ case ARIZONA_INTERRUPT_STATUS_1:
+ case ARIZONA_INTERRUPT_STATUS_2:
+ case ARIZONA_INTERRUPT_STATUS_3:
+ case ARIZONA_INTERRUPT_STATUS_4:
+ case ARIZONA_INTERRUPT_STATUS_5:
+ case ARIZONA_INTERRUPT_STATUS_6:
+ case ARIZONA_IRQ2_STATUS_1:
+ case ARIZONA_IRQ2_STATUS_2:
+ case ARIZONA_IRQ2_STATUS_3:
+ case ARIZONA_IRQ2_STATUS_4:
+ case ARIZONA_IRQ2_STATUS_5:
+ case ARIZONA_IRQ2_STATUS_6:
+ case ARIZONA_INTERRUPT_RAW_STATUS_2:
+ case ARIZONA_INTERRUPT_RAW_STATUS_3:
+ case ARIZONA_INTERRUPT_RAW_STATUS_4:
+ case ARIZONA_INTERRUPT_RAW_STATUS_5:
+ case ARIZONA_INTERRUPT_RAW_STATUS_6:
+ case ARIZONA_INTERRUPT_RAW_STATUS_7:
+ case ARIZONA_INTERRUPT_RAW_STATUS_8:
+ case ARIZONA_INTERRUPT_RAW_STATUS_9:
+ case ARIZONA_IRQ_PIN_STATUS:
+ case ARIZONA_FX_CTRL2:
+ case ARIZONA_ASRC_STATUS:
+ case ARIZONA_DSP2_STATUS_1:
+ case ARIZONA_DSP2_STATUS_2:
+ case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_STATUS_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_1:
+ case ARIZONA_DSP2_WDMA_BUFFER_2:
+ case ARIZONA_DSP2_WDMA_BUFFER_3:
+ case ARIZONA_DSP2_WDMA_BUFFER_4:
+ case ARIZONA_DSP2_WDMA_BUFFER_5:
+ case ARIZONA_DSP2_WDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_BUFFER_7:
+ case ARIZONA_DSP2_WDMA_BUFFER_8:
+ case ARIZONA_DSP2_RDMA_BUFFER_1:
+ case ARIZONA_DSP2_RDMA_BUFFER_2:
+ case ARIZONA_DSP2_RDMA_BUFFER_3:
+ case ARIZONA_DSP2_RDMA_BUFFER_4:
+ case ARIZONA_DSP2_RDMA_BUFFER_5:
+ case ARIZONA_DSP2_RDMA_BUFFER_6:
+ case ARIZONA_DSP2_WDMA_CONFIG_1:
+ case ARIZONA_DSP2_WDMA_CONFIG_2:
+ case ARIZONA_DSP2_WDMA_OFFSET_1:
+ case ARIZONA_DSP2_RDMA_CONFIG_1:
+ case ARIZONA_DSP2_RDMA_OFFSET_1:
+ case ARIZONA_DSP2_EXTERNAL_START_SELECT_1:
+ case ARIZONA_DSP2_SCRATCH_0:
+ case ARIZONA_DSP2_SCRATCH_1:
+ case ARIZONA_DSP2_SCRATCH_2:
+ case ARIZONA_DSP2_SCRATCH_3:
+ case ARIZONA_DSP2_CLOCKING_1:
+ case ARIZONA_DSP3_STATUS_1:
+ case ARIZONA_DSP3_STATUS_2:
+ case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_STATUS_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_1:
+ case ARIZONA_DSP3_WDMA_BUFFER_2:
+ case ARIZONA_DSP3_WDMA_BUFFER_3:
+ case ARIZONA_DSP3_WDMA_BUFFER_4:
+ case ARIZONA_DSP3_WDMA_BUFFER_5:
+ case ARIZONA_DSP3_WDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_BUFFER_7:
+ case ARIZONA_DSP3_WDMA_BUFFER_8:
+ case ARIZONA_DSP3_RDMA_BUFFER_1:
+ case ARIZONA_DSP3_RDMA_BUFFER_2:
+ case ARIZONA_DSP3_RDMA_BUFFER_3:
+ case ARIZONA_DSP3_RDMA_BUFFER_4:
+ case ARIZONA_DSP3_RDMA_BUFFER_5:
+ case ARIZONA_DSP3_RDMA_BUFFER_6:
+ case ARIZONA_DSP3_WDMA_CONFIG_1:
+ case ARIZONA_DSP3_WDMA_CONFIG_2:
+ case ARIZONA_DSP3_WDMA_OFFSET_1:
+ case ARIZONA_DSP3_RDMA_CONFIG_1:
+ case ARIZONA_DSP3_RDMA_OFFSET_1:
+ case ARIZONA_DSP3_EXTERNAL_START_SELECT_1:
+ case ARIZONA_DSP3_SCRATCH_0:
+ case ARIZONA_DSP3_SCRATCH_1:
+ case ARIZONA_DSP3_SCRATCH_2:
+ case ARIZONA_DSP3_SCRATCH_3:
+ case ARIZONA_DSP3_CLOCKING_1:
+ return true;
+ default:
+ return cs47l24_is_adsp_memory(reg);
+ }
+}
+
+#define CS47L24_MAX_REGISTER 0x3b3fff
+
+const struct regmap_config cs47l24_spi_regmap = {
+ .reg_bits = 32,
+ .pad_bits = 16,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = CS47L24_MAX_REGISTER,
+ .readable_reg = cs47l24_readable_register,
+ .volatile_reg = cs47l24_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l24_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l24_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l24_spi_regmap);
+
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index be91cb5d6e78..f9d277ff4aaf 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -60,6 +60,7 @@ static int cs5535_mfd_res_enable(struct platform_device *pdev)
static int cs5535_mfd_res_disable(struct platform_device *pdev)
{
struct resource *res;
+
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res) {
dev_err(&pdev->dev, "can't fetch device resource info\n");
@@ -114,7 +115,10 @@ static struct mfd_cell cs5535_mfd_cells[] = {
#ifdef CONFIG_OLPC
static void cs5535_clone_olpc_cells(void)
{
- const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
+ static const char *acpi_clones[] = {
+ "olpc-xo1-pm-acpi",
+ "olpc-xo1-sci-acpi"
+ };
if (!machine_is_olpc())
return;
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 37e4426ef061..09f367571c58 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -2,10 +2,10 @@
* Base driver for Dialog Semiconductor DA9030/DA9034
*
* Copyright (C) 2008 Compulab, Ltd.
- * Mike Rapoport <mike@compulab.co.il>
+ * Mike Rapoport <mike@compulab.co.il>
*
* Copyright (C) 2006-2008 Marvell International Ltd.
- * Eric Miao <eric.miao@marvell.com>
+ * Eric Miao <eric.miao@marvell.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -60,7 +60,7 @@ struct da903x_chip_ops {
struct da903x_chip {
struct i2c_client *client;
struct device *dev;
- struct da903x_chip_ops *ops;
+ const struct da903x_chip_ops *ops;
int type;
uint32_t events_mask;
@@ -424,7 +424,7 @@ static irqreturn_t da903x_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static struct da903x_chip_ops da903x_ops[] = {
+static const struct da903x_chip_ops da903x_ops[] = {
[0] = {
.init_chip = da9030_init_chip,
.unmask_events = da9030_unmask_events,
@@ -565,6 +565,6 @@ static void __exit da903x_exit(void)
module_exit(da903x_exit);
MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034");
-MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
- "Mike Rapoport <mike@compulab.co.il>");
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 2697ffb08009..578e881067a5 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -70,7 +70,7 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
case DA9053_BA:
case DA9053_BB:
/* A dummy read to a safe register address. */
- if (!i2c_safe_reg(reg))
+ if (!i2c_safe_reg(reg))
return regmap_read(da9052->regmap,
DA9052_PARK_REGISTER,
&val);
diff --git a/drivers/mfd/da9052-irq.c b/drivers/mfd/da9052-irq.c
index f4cb4613140b..cd4ca849ca44 100644
--- a/drivers/mfd/da9052-irq.c
+++ b/drivers/mfd/da9052-irq.c
@@ -283,7 +283,7 @@ regmap_err:
int da9052_irq_exit(struct da9052 *da9052)
{
- da9052_free_irq(da9052, DA9052_IRQ_ADC_EOM , da9052);
+ da9052_free_irq(da9052, DA9052_IRQ_ADC_EOM, da9052);
regmap_del_irq_chip(da9052->chip_irq, da9052->irq_data);
return 0;
diff --git a/drivers/mfd/davinci_voicecodec.c b/drivers/mfd/davinci_voicecodec.c
index 9bbc642a7b9d..dff2f19296b8 100644
--- a/drivers/mfd/davinci_voicecodec.c
+++ b/drivers/mfd/davinci_voicecodec.c
@@ -47,11 +47,8 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
davinci_vc = devm_kzalloc(&pdev->dev,
sizeof(struct davinci_vc), GFP_KERNEL);
- if (!davinci_vc) {
- dev_dbg(&pdev->dev,
- "could not allocate memory for private data\n");
+ if (!davinci_vc)
return -ENOMEM;
- }
davinci_vc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(davinci_vc->clk)) {
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
index 4c826f78acd0..bf3e0b21b247 100644
--- a/drivers/mfd/dm355evm_msp.c
+++ b/drivers/mfd/dm355evm_msp.c
@@ -147,7 +147,7 @@ static int msp_gpio_get(struct gpio_chip *chip, unsigned offset)
return status;
if (reg == DM355EVM_MSP_LED)
msp_led_cache = status;
- return status & MSP_GPIO_MASK(offset);
+ return !!(status & MSP_GPIO_MASK(offset));
}
static int msp_gpio_out(struct gpio_chip *chip, unsigned offset, int value)
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index 6ccaf90d98fd..e4f4a31b76d9 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -163,7 +163,7 @@ static int egpio_get(struct gpio_chip *chip, unsigned offset)
value = egpio_readw(ei, reg);
pr_debug("readw(%p + %x) = %x\n",
ei->base_addr, reg << ei->bus_shift, value);
- return value & bit;
+ return !!(value & bit);
}
static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index b514f3cf140d..bd3aa4578346 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -55,6 +55,7 @@
* document number TBD : Coleto Creek
* document number TBD : Wildcat Point-LP
* document number TBD : 9 Series
+ * document number TBD : Lewisburg
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -213,6 +214,7 @@ enum lpc_chipsets {
LPC_COLETO, /* Coleto Creek */
LPC_WPT_LP, /* Wildcat Point-LP */
LPC_BRASWELL, /* Braswell SoC */
+ LPC_LEWISBURG, /* Lewisburg */
LPC_9S, /* 9 Series */
};
@@ -521,6 +523,10 @@ static struct lpc_ich_info lpc_chipset_info[] = {
.name = "Braswell SoC",
.iTCO_version = 3,
},
+ [LPC_LEWISBURG] = {
+ .name = "Lewisburg",
+ .iTCO_version = 2,
+ },
[LPC_9S] = {
.name = "9 Series",
.iTCO_version = 2,
@@ -757,6 +763,15 @@ static const struct pci_device_id lpc_ich_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP},
{ PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP},
+ { PCI_VDEVICE(INTEL, 0xa1c1), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c2), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c3), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c4), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c5), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c6), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa1c7), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa242), LPC_LEWISBURG},
+ { PCI_VDEVICE(INTEL, 0xa243), LPC_LEWISBURG},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, lpc_ich_ids);
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 56e216dedc91..2280b3fdcf68 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -495,7 +495,7 @@ MODULE_DEVICE_TABLE(i2c, max14577_i2c_id);
#ifdef CONFIG_PM_SLEEP
static int max14577_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max14577 *max14577 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -516,7 +516,7 @@ static int max14577_suspend(struct device *dev)
static int max14577_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max14577 *max14577 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index d19be64cd32b..d959ebbb2194 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -352,7 +352,7 @@ MODULE_DEVICE_TABLE(i2c, max77686_i2c_id);
#ifdef CONFIG_PM_SLEEP
static int max77686_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -374,7 +374,7 @@ static int max77686_suspend(struct device *dev)
static int max77686_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77686_dev *max77686 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index 007f729e150b..b83b7a7da1ae 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -334,7 +334,7 @@ MODULE_DEVICE_TABLE(i2c, max77693_i2c_id);
static int max77693_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev)) {
@@ -347,7 +347,7 @@ static int max77693_suspend(struct device *dev)
static int max77693_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77693 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev)) {
diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c
index 586098f1b233..7cfc95b49c5d 100644
--- a/drivers/mfd/max77843.c
+++ b/drivers/mfd/max77843.c
@@ -197,7 +197,7 @@ MODULE_DEVICE_TABLE(i2c, max77843_id);
static int __maybe_unused max77843_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
disable_irq(max77843->irq);
@@ -209,7 +209,7 @@ static int __maybe_unused max77843_suspend(struct device *dev)
static int __maybe_unused max77843_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max77693_dev *max77843 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
index b0fe8103e401..70443b161a5b 100644
--- a/drivers/mfd/max8925-i2c.c
+++ b/drivers/mfd/max8925-i2c.c
@@ -215,7 +215,7 @@ static int max8925_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
static int max8925_suspend(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct max8925_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
@@ -225,7 +225,7 @@ static int max8925_suspend(struct device *dev)
static int max8925_resume(struct device *dev)
{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *client = to_i2c_client(dev);
struct max8925_chip *chip = i2c_get_clientdata(client);
if (device_may_wakeup(dev) && chip->wakeup_flag)
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 156ed6f92aa3..f316348e3d98 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -437,7 +437,7 @@ static u8 max8997_dumpaddr_haptic[] = {
static int max8997_freeze(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
int i;
@@ -459,7 +459,7 @@ static int max8997_freeze(struct device *dev)
static int max8997_restore(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
int i;
@@ -481,7 +481,7 @@ static int max8997_restore(struct device *dev)
static int max8997_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -491,7 +491,7 @@ static int max8997_suspend(struct device *dev)
static int max8997_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index a7afe3bf27fc..ab28b29400f6 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -274,7 +274,7 @@ MODULE_DEVICE_TABLE(i2c, max8998_i2c_id);
static int max8998_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -284,7 +284,7 @@ static int max8998_suspend(struct device *dev)
static int max8998_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -344,7 +344,7 @@ static struct max8998_reg_dump max8998_dump[] = {
/* Save registers before hibernation */
static int max8998_freeze(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
int i;
for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
@@ -357,7 +357,7 @@ static int max8998_freeze(struct device *dev)
/* Restore registers after hibernation */
static int max8998_restore(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
int i;
for (i = 0; i < ARRAY_SIZE(max8998_dump); i++)
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 3f9f4c874d2a..d7f54e492aa6 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -383,16 +383,16 @@ static int mc13xxx_probe_flags_dt(struct mc13xxx *mc13xxx)
if (!np)
return -ENODEV;
- if (of_get_property(np, "fsl,mc13xxx-uses-adc", NULL))
+ if (of_property_read_bool(np, "fsl,mc13xxx-uses-adc"))
mc13xxx->flags |= MC13XXX_USE_ADC;
- if (of_get_property(np, "fsl,mc13xxx-uses-codec", NULL))
+ if (of_property_read_bool(np, "fsl,mc13xxx-uses-codec"))
mc13xxx->flags |= MC13XXX_USE_CODEC;
- if (of_get_property(np, "fsl,mc13xxx-uses-rtc", NULL))
+ if (of_property_read_bool(np, "fsl,mc13xxx-uses-rtc"))
mc13xxx->flags |= MC13XXX_USE_RTC;
- if (of_get_property(np, "fsl,mc13xxx-uses-touch", NULL))
+ if (of_property_read_bool(np, "fsl,mc13xxx-uses-touch"))
mc13xxx->flags |= MC13XXX_USE_TOUCHSCREEN;
return 0;
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index af6ac1c4b45c..8653e8b9bb4f 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -127,7 +127,9 @@ static int pmic_spmi_probe(struct spmi_device *sdev)
if (IS_ERR(regmap))
return PTR_ERR(regmap);
- pmic_spmi_show_revid(regmap, &sdev->dev);
+ /* Only the first slave id for a PMIC contains this information */
+ if (sdev->usid % 2 == 0)
+ pmic_spmi_show_revid(regmap, &sdev->dev);
return of_platform_populate(root, NULL, NULL, &sdev->dev);
}
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
index 207a3bd68559..1be47ad6441b 100644
--- a/drivers/mfd/qcom_rpm.c
+++ b/drivers/mfd/qcom_rpm.c
@@ -495,6 +495,8 @@ static int qcom_rpm_probe(struct platform_device *pdev)
}
match = of_match_device(qcom_rpm_of_match, &pdev->dev);
+ if (!match)
+ return -ENODEV;
rpm->data = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 989076d6cb83..400e1d7d8d08 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -29,6 +29,7 @@
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
#include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h>
@@ -67,7 +68,7 @@ static const struct mfd_cell s5m8767_devs[] = {
static const struct mfd_cell s2mps11_devs[] = {
{
- .name = "s2mps11-pmic",
+ .name = "s2mps11-regulator",
}, {
.name = "s2mps14-rtc",
}, {
@@ -77,7 +78,7 @@ static const struct mfd_cell s2mps11_devs[] = {
};
static const struct mfd_cell s2mps13_devs[] = {
- { .name = "s2mps13-pmic", },
+ { .name = "s2mps13-regulator", },
{ .name = "s2mps13-rtc", },
{
.name = "s2mps13-clk",
@@ -87,7 +88,7 @@ static const struct mfd_cell s2mps13_devs[] = {
static const struct mfd_cell s2mps14_devs[] = {
{
- .name = "s2mps14-pmic",
+ .name = "s2mps14-regulator",
}, {
.name = "s2mps14-rtc",
}, {
@@ -96,6 +97,17 @@ static const struct mfd_cell s2mps14_devs[] = {
}
};
+static const struct mfd_cell s2mps15_devs[] = {
+ {
+ .name = "s2mps15-regulator",
+ }, {
+ .name = "s2mps15-rtc",
+ }, {
+ .name = "s2mps13-clk",
+ .of_compatible = "samsung,s2mps13-clk",
+ },
+};
+
static const struct mfd_cell s2mpa01_devs[] = {
{
.name = "s2mpa01-pmic",
@@ -104,7 +116,7 @@ static const struct mfd_cell s2mpa01_devs[] = {
static const struct mfd_cell s2mpu02_devs[] = {
{
- .name = "s2mpu02-pmic",
+ .name = "s2mpu02-regulator",
},
};
@@ -122,6 +134,9 @@ static const struct of_device_id sec_dt_match[] = {
.compatible = "samsung,s2mps14-pmic",
.data = (void *)S2MPS14X,
}, {
+ .compatible = "samsung,s2mps15-pmic",
+ .data = (void *)S2MPS15X,
+ }, {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
@@ -223,6 +238,15 @@ static const struct regmap_config s2mps14_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
+static const struct regmap_config s2mps15_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S2MPS15_REG_LDODSCH4,
+ .volatile_reg = s2mps11_volatile,
+ .cache_type = REGCACHE_FLAT,
+};
+
static const struct regmap_config s2mpu02_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -384,6 +408,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
case S2MPS14X:
regmap = &s2mps14_regmap_config;
break;
+ case S2MPS15X:
+ regmap = &s2mps15_regmap_config;
+ break;
case S5M8763X:
regmap = &s5m8763_regmap_config;
break;
@@ -442,6 +469,10 @@ static int sec_pmic_probe(struct i2c_client *i2c,
sec_devs = s2mps14_devs;
num_sec_devs = ARRAY_SIZE(s2mps14_devs);
break;
+ case S2MPS15X:
+ sec_devs = s2mps15_devs;
+ num_sec_devs = ARRAY_SIZE(s2mps15_devs);
+ break;
case S2MPU02:
sec_devs = s2mpu02_devs;
num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
@@ -505,7 +536,7 @@ static void sec_pmic_shutdown(struct i2c_client *i2c)
#ifdef CONFIG_PM_SLEEP
static int sec_pmic_suspend(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
@@ -526,7 +557,7 @@ static int sec_pmic_suspend(struct device *dev)
static int sec_pmic_resume(struct device *dev)
{
- struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+ struct i2c_client *i2c = to_i2c_client(dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
if (device_may_wakeup(dev))
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 806fa8dbb22d..d77de431cc50 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -407,6 +407,11 @@ static const struct regmap_irq_chip s2mps14_irq_chip = {
S2MPS1X_IRQ_CHIP_COMMON_DATA,
};
+static const struct regmap_irq_chip s2mps15_irq_chip = {
+ .name = "s2mps15",
+ S2MPS1X_IRQ_CHIP_COMMON_DATA,
+};
+
static const struct regmap_irq_chip s2mpu02_irq_chip = {
.name = "s2mpu02",
.irqs = s2mpu02_irqs,
@@ -466,6 +471,9 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
case S2MPS14X:
sec_irq_chip = &s2mps14_irq_chip;
break;
+ case S2MPS15X:
+ sec_irq_chip = &s2mps15_irq_chip;
+ break;
case S2MPU02:
sec_irq_chip = &s2mpu02_irq_chip;
break;
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index b3e5c6f45105..9292202039ee 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -372,12 +372,6 @@ static struct platform_driver sta2x11_sctl_platform_driver = {
.probe = sta2x11_sctl_probe,
};
-static int __init sta2x11_sctl_init(void)
-{
- pr_info("%s\n", __func__);
- return platform_driver_register(&sta2x11_sctl_platform_driver);
-}
-
static struct platform_driver sta2x11_platform_driver = {
.driver = {
.name = STA2X11_MFD_APBREG_NAME,
@@ -385,12 +379,6 @@ static struct platform_driver sta2x11_platform_driver = {
.probe = sta2x11_apbreg_probe,
};
-static int __init sta2x11_apbreg_init(void)
-{
- pr_info("%s\n", __func__);
- return platform_driver_register(&sta2x11_platform_driver);
-}
-
static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
.driver = {
.name = STA2X11_MFD_APB_SOC_REGS_NAME,
@@ -398,12 +386,6 @@ static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
.probe = sta2x11_apb_soc_regs_probe,
};
-static int __init sta2x11_apb_soc_regs_init(void)
-{
- pr_info("%s\n", __func__);
- return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
-}
-
static struct platform_driver sta2x11_scr_platform_driver = {
.driver = {
.name = STA2X11_MFD_SCR_NAME,
@@ -411,13 +393,18 @@ static struct platform_driver sta2x11_scr_platform_driver = {
.probe = sta2x11_scr_probe,
};
-static int __init sta2x11_scr_init(void)
+static struct platform_driver * const drivers[] = {
+ &sta2x11_platform_driver,
+ &sta2x11_sctl_platform_driver,
+ &sta2x11_apb_soc_regs_platform_driver,
+ &sta2x11_scr_platform_driver,
+};
+
+static int __init sta2x11_drivers_init(void)
{
- pr_info("%s\n", __func__);
- return platform_driver_register(&sta2x11_scr_platform_driver);
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
-
/*
* What follows are the PCI devices that host the above pdevs.
* Each logic block is 4kB and they are all consecutive: we use this info.
@@ -664,10 +651,7 @@ static int __init sta2x11_mfd_init(void)
* prepares platform drivers very early and probe the PCI device later,
* but before other PCI devices.
*/
-subsys_initcall(sta2x11_apbreg_init);
-subsys_initcall(sta2x11_sctl_init);
-subsys_initcall(sta2x11_apb_soc_regs_init);
-subsys_initcall(sta2x11_scr_init);
+subsys_initcall(sta2x11_drivers_init);
rootfs_initcall(sta2x11_mfd_init);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 176bf0fa2685..b7aabeefab07 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -47,6 +47,7 @@ static struct syscon *of_syscon_register(struct device_node *np)
struct syscon *syscon;
struct regmap *regmap;
void __iomem *base;
+ u32 reg_io_width;
int ret;
struct regmap_config syscon_config = syscon_regmap_config;
@@ -69,6 +70,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
else if (of_property_read_bool(np, "little-endian"))
syscon_config.val_format_endian = REGMAP_ENDIAN_LITTLE;
+ /*
+ * search for reg-io-width property in DT. If it is not provided,
+ * default to 4 bytes. regmap_init_mmio will return an error if values
+ * are invalid so there is no need to check them here.
+ */
+ ret = of_property_read_u32(np, "reg-io-width", &reg_io_width);
+ if (ret)
+ reg_io_width = 4;
+
+ syscon_config.reg_stride = reg_io_width;
+ syscon_config.val_bits = reg_io_width * 8;
+
regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) {
pr_err("regmap init failed\n");
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 8c84a513016b..1ecbfa40d1b3 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -437,8 +437,8 @@ static int tc6393xb_gpio_get(struct gpio_chip *chip,
struct tc6393xb *tc6393xb = container_of(chip, struct tc6393xb, gpio);
/* XXX: does dsr also represent inputs? */
- return tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
- & TC_GPIO_BIT(offset);
+ return !!(tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
+ & TC_GPIO_BIT(offset));
}
static void __tc6393xb_gpio_set(struct gpio_chip *chip,
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index 448f0a182dc4..677a127619d4 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -499,11 +499,11 @@ static int tps65010_gpio_get(struct gpio_chip *chip, unsigned offset)
if (offset < 4) {
value = i2c_smbus_read_byte_data(tps->client, TPS_DEFGPIO);
if (value < 0)
- return 0;
+ return value;
if (value & (1 << (offset + 4))) /* output */
return !(value & (1 << offset));
else /* input */
- return (value & (1 << offset));
+ return !!(value & (1 << offset));
}
/* REVISIT we *could* report LED1/nPG and LED2 state ... */
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index f691d7ecad52..e0dd83fb95d3 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -133,7 +133,7 @@ static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
val = ucb1x00_reg_read(ucb, UCB_IO_DATA);
ucb1x00_disable(ucb);
- return val & (1 << offset);
+ return !!(val & (1 << offset));
}
static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 2bb2d0467a92..c18e11f42b3f 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -762,9 +762,9 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
{ 0x00000210, 0x0184 }, /* R528 - LDO1 Control 1 */
{ 0x00000213, 0x03E4 }, /* R531 - LDO2 Control 1 */
- { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
- { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
- { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */
+ { 0x00000218, 0x00E6 }, /* R536 - Mic Bias Ctrl 1 */
+ { 0x00000219, 0x00E6 }, /* R537 - Mic Bias Ctrl 2 */
+ { 0x0000021A, 0x00E6 }, /* R538 - Mic Bias Ctrl 3 */
{ 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */
{ 0x0000029B, 0x0028 }, /* R667 - Headphone Detect 1 */
{ 0x000002A2, 0x0000 }, /* R674 - Micd clamp control */
diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c
index b90f3e06b6c9..ebac0027f8e0 100644
--- a/drivers/mfd/wm831x-otp.c
+++ b/drivers/mfd/wm831x-otp.c
@@ -47,20 +47,14 @@ static ssize_t wm831x_unique_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct wm831x *wm831x = dev_get_drvdata(dev);
- int i, rval;
+ int rval;
char id[WM831X_UNIQUE_ID_LEN];
- ssize_t ret = 0;
rval = wm831x_unique_id_read(wm831x, id);
if (rval < 0)
return 0;
- for (i = 0; i < WM831X_UNIQUE_ID_LEN; i++)
- ret += sprintf(&buf[ret], "%02x", buf[i]);
-
- ret += sprintf(&buf[ret], "\n");
-
- return ret;
+ return sprintf(buf, "%*phN\n", WM831X_UNIQUE_ID_LEN, id);
}
static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL);
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index a0bbb6b9f5aa..94da913b151d 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1239,7 +1239,7 @@ static int i40evf_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed,
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
- dev_err(&adapter->pdev->dev, "Cannot confiure RSS, command %d pending\n",
+ dev_err(&adapter->pdev->dev, "Cannot configure RSS, command %d pending\n",
adapter->current_op);
return -EBUSY;
}
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 9582c5703b3c..91a469d55b8f 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -597,7 +597,7 @@ static u64 __of_translate_address(struct device_node *dev,
pbus = of_match_bus(parent);
pbus->count_cells(dev, &pna, &pns);
if (!OF_CHECK_COUNTS(pna, pns)) {
- printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+ pr_err("prom_parse: Bad cell count for %s\n",
of_node_full_name(dev));
break;
}
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 53826b84e0ec..c647bd1b6903 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -646,6 +646,7 @@ void of_changeset_init(struct of_changeset *ocs)
memset(ocs, 0, sizeof(*ocs));
INIT_LIST_HEAD(&ocs->entries);
}
+EXPORT_SYMBOL_GPL(of_changeset_init);
/**
* of_changeset_destroy - Destroy a changeset
@@ -662,20 +663,9 @@ void of_changeset_destroy(struct of_changeset *ocs)
list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
__of_changeset_entry_destroy(ce);
}
+EXPORT_SYMBOL_GPL(of_changeset_destroy);
-/**
- * of_changeset_apply - Applies a changeset
- *
- * @ocs: changeset pointer
- *
- * Applies a changeset to the live tree.
- * Any side-effects of live tree state changes are applied here on
- * sucess, like creation/destruction of devices and side-effects
- * like creation of sysfs properties and directories.
- * Returns 0 on success, a negative error value in case of an error.
- * On error the partially applied effects are reverted.
- */
-int of_changeset_apply(struct of_changeset *ocs)
+int __of_changeset_apply(struct of_changeset *ocs)
{
struct of_changeset_entry *ce;
int ret;
@@ -704,17 +694,30 @@ int of_changeset_apply(struct of_changeset *ocs)
}
/**
- * of_changeset_revert - Reverts an applied changeset
+ * of_changeset_apply - Applies a changeset
*
* @ocs: changeset pointer
*
- * Reverts a changeset returning the state of the tree to what it
- * was before the application.
- * Any side-effects like creation/destruction of devices and
- * removal of sysfs properties and directories are applied.
+ * Applies a changeset to the live tree.
+ * Any side-effects of live tree state changes are applied here on
+ * success, like creation/destruction of devices and side-effects
+ * like creation of sysfs properties and directories.
* Returns 0 on success, a negative error value in case of an error.
+ * On error the partially applied effects are reverted.
*/
-int of_changeset_revert(struct of_changeset *ocs)
+int of_changeset_apply(struct of_changeset *ocs)
+{
+ int ret;
+
+ mutex_lock(&of_mutex);
+ ret = __of_changeset_apply(ocs);
+ mutex_unlock(&of_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_changeset_apply);
+
+int __of_changeset_revert(struct of_changeset *ocs)
{
struct of_changeset_entry *ce;
int ret;
@@ -742,6 +745,29 @@ int of_changeset_revert(struct of_changeset *ocs)
}
/**
+ * of_changeset_revert - Reverts an applied changeset
+ *
+ * @ocs: changeset pointer
+ *
+ * Reverts a changeset returning the state of the tree to what it
+ * was before the application.
+ * Any side-effects like creation/destruction of devices and
+ * removal of sysfs properties and directories are applied.
+ * Returns 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_revert(struct of_changeset *ocs)
+{
+ int ret;
+
+ mutex_lock(&of_mutex);
+ ret = __of_changeset_revert(ocs);
+ mutex_unlock(&of_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_changeset_revert);
+
+/**
* of_changeset_action - Perform a changeset action
*
* @ocs: changeset pointer
@@ -779,3 +805,4 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action,
list_add_tail(&ce->node, &ocs->entries);
return 0;
}
+EXPORT_SYMBOL_GPL(of_changeset_action);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 4fa916dffc91..706e3ff67f8b 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -473,6 +473,7 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource_table);
struct of_intc_desc {
struct list_head list;
+ of_irq_init_cb_t irq_init_cb;
struct device_node *dev;
struct device_node *interrupt_parent;
};
@@ -486,6 +487,7 @@ struct of_intc_desc {
*/
void __init of_irq_init(const struct of_device_id *matches)
{
+ const struct of_device_id *match;
struct device_node *np, *parent = NULL;
struct of_intc_desc *desc, *temp_desc;
struct list_head intc_desc_list, intc_parent_list;
@@ -493,10 +495,15 @@ void __init of_irq_init(const struct of_device_id *matches)
INIT_LIST_HEAD(&intc_desc_list);
INIT_LIST_HEAD(&intc_parent_list);
- for_each_matching_node(np, matches) {
+ for_each_matching_node_and_match(np, matches, &match) {
if (!of_find_property(np, "interrupt-controller", NULL) ||
!of_device_is_available(np))
continue;
+
+ if (WARN(!match->data, "of_irq_init: no init function for %s\n",
+ match->compatible))
+ continue;
+
/*
* Here, we allocate and populate an of_intc_desc with the node
* pointer, interrupt-parent device_node etc.
@@ -507,6 +514,7 @@ void __init of_irq_init(const struct of_device_id *matches)
goto err;
}
+ desc->irq_init_cb = match->data;
desc->dev = of_node_get(np);
desc->interrupt_parent = of_irq_find_parent(np);
if (desc->interrupt_parent == np)
@@ -526,27 +534,18 @@ void __init of_irq_init(const struct of_device_id *matches)
* The assumption is that NULL parent means a root controller.
*/
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
- const struct of_device_id *match;
int ret;
- of_irq_init_cb_t irq_init_cb;
if (desc->interrupt_parent != parent)
continue;
list_del(&desc->list);
- match = of_match_node(matches, desc->dev);
- if (WARN(!match->data,
- "of_irq_init: no init function for %s\n",
- match->compatible)) {
- kfree(desc);
- continue;
- }
- pr_debug("of_irq_init: init %s @ %p, parent %p\n",
- match->compatible,
+ pr_debug("of_irq_init: init %s (%p), parent %p\n",
+ desc->dev->full_name,
desc->dev, desc->interrupt_parent);
- irq_init_cb = (of_irq_init_cb_t)match->data;
- ret = irq_init_cb(desc->dev, desc->interrupt_parent);
+ ret = desc->irq_init_cb(desc->dev,
+ desc->interrupt_parent);
if (ret) {
kfree(desc);
continue;
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 8e882e706cd8..829469faeb23 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -45,6 +45,8 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
extern int of_property_notify(int action, struct device_node *np,
struct property *prop, struct property *old_prop);
extern void of_node_release(struct kobject *kobj);
+extern int __of_changeset_apply(struct of_changeset *ocs);
+extern int __of_changeset_revert(struct of_changeset *ocs);
#else /* CONFIG_OF_DYNAMIC */
static inline int of_property_notify(int action, struct device_node *np,
struct property *prop, struct property *old_prop)
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 54e5af9d7377..82250815e9a5 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -379,9 +379,9 @@ int of_overlay_create(struct device_node *tree)
}
/* apply the changeset */
- err = of_changeset_apply(&ov->cset);
+ err = __of_changeset_apply(&ov->cset);
if (err) {
- pr_err("%s: of_changeset_apply() failed for tree@%s\n",
+ pr_err("%s: __of_changeset_apply() failed for tree@%s\n",
__func__, tree->full_name);
goto err_revert_overlay;
}
@@ -511,7 +511,7 @@ int of_overlay_destroy(int id)
list_del(&ov->node);
- of_changeset_revert(&ov->cset);
+ __of_changeset_revert(&ov->cset);
of_free_overlay_info(ov);
idr_remove(&ov_idr, id);
of_changeset_destroy(&ov->cset);
@@ -542,7 +542,7 @@ int of_overlay_destroy_all(void)
/* the tail of list is guaranteed to be safe to remove */
list_for_each_entry_safe_reverse(ov, ovn, &ov_list, node) {
list_del(&ov->node);
- of_changeset_revert(&ov->cset);
+ __of_changeset_revert(&ov->cset);
of_free_overlay_info(ov);
idr_remove(&ov_idr, ov->id);
kfree(ov);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index af98343614d8..8d103e4968be 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -31,6 +31,7 @@ const struct of_device_id of_default_bus_match_table[] = {
#endif /* CONFIG_ARM_AMBA */
{} /* Empty terminated list */
};
+EXPORT_SYMBOL(of_default_bus_match_table);
static int of_dev_node_match(struct device *dev, void *data)
{
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index e16ea5717b7f..979b6e415cea 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -530,18 +530,14 @@ static void __init of_unittest_changeset(void)
unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
- mutex_lock(&of_mutex);
unittest(!of_changeset_apply(&chgset), "apply failed\n");
- mutex_unlock(&of_mutex);
/* Make sure node names are constructed correctly */
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
"'%s' not added\n", n21->full_name);
of_node_put(np);
- mutex_lock(&of_mutex);
unittest(!of_changeset_revert(&chgset), "revert failed\n");
- mutex_unlock(&of_mutex);
of_changeset_destroy(&chgset);
#endif
@@ -757,6 +753,11 @@ static void __init of_unittest_match_node(void)
}
}
+static struct resource test_bus_res = {
+ .start = 0xfffffff8,
+ .end = 0xfffffff9,
+ .flags = IORESOURCE_MEM,
+};
static const struct platform_device_info test_bus_info = {
.name = "unittest-bus",
};
@@ -800,6 +801,15 @@ static void __init of_unittest_platform_populate(void)
return;
test_bus->dev.of_node = np;
+ /*
+ * Add a dummy resource to the test bus node after it is
+ * registered to catch problems with un-inserted resources. The
+ * DT code doesn't insert the resources, and it has caused the
+ * kernel to oops in the past. This makes sure the same bug
+ * doesn't crop up again.
+ */
+ platform_device_add_resources(test_bus, &test_bus_res, 1);
+
of_platform_populate(np, match, NULL, &test_bus->dev);
for_each_child_of_node(np, child) {
for_each_child_of_node(child, grandchild)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 237d7aa73e8c..1ddd13cc0c07 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -160,22 +160,16 @@ config BATTERY_SBS
config BATTERY_BQ27XXX
tristate "BQ27xxx battery driver"
help
- Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips.
+ Say Y here to enable support for batteries with BQ27xxx chips.
config BATTERY_BQ27XXX_I2C
- bool "BQ27xxx I2C support"
+ tristate "BQ27xxx I2C support"
depends on BATTERY_BQ27XXX
depends on I2C
default y
help
- Say Y here to enable support for batteries with BQ27xxx (I2C) chips.
-
-config BATTERY_BQ27XXX_PLATFORM
- bool "BQ27xxx HDQ support"
- depends on BATTERY_BQ27XXX
- default y
- help
- Say Y here to enable support for batteries with BQ27xxx (HDQ) chips.
+ Say Y here to enable support for batteries with BQ27xxx chips
+ connected over an I2C bus.
config BATTERY_DA9030
tristate "DA9030 battery driver"
@@ -508,8 +502,7 @@ config AXP20X_POWER
This driver provides support for the power supply features of
AXP20x PMIC.
-source "drivers/power/reset/Kconfig"
-
endif # POWER_SUPPLY
+source "drivers/power/reset/Kconfig"
source "drivers/power/avs/Kconfig"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b656638f8b39..0e4eab55f8d7 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
+obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 4afd76848bce..27e89536689a 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1704,7 +1704,7 @@ error_4:
error_3:
bq2415x_power_supply_exit(bq);
error_2:
- if (bq && bq->notify_node)
+ if (bq)
of_node_put(bq->notify_node);
kfree(name);
error_1:
@@ -1724,9 +1724,7 @@ static int bq2415x_remove(struct i2c_client *client)
if (bq->nb.notifier_call)
power_supply_unreg_notifier(&bq->nb);
- if (bq->notify_node)
- of_node_put(bq->notify_node);
-
+ of_node_put(bq->notify_node);
bq2415x_sysfs_exit(bq);
bq2415x_power_supply_exit(bq);
diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c
index 880233ce9343..6b027a418943 100644
--- a/drivers/power/bq27xxx_battery.c
+++ b/drivers/power/bq27xxx_battery.c
@@ -45,11 +45,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
-#include <linux/idr.h>
-#include <linux/i2c.h>
#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <asm/unaligned.h>
#include <linux/power/bq27xxx_battery.h>
@@ -78,11 +74,6 @@
#define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */
#define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */
-struct bq27xxx_device_info;
-struct bq27xxx_access_methods {
- int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single);
-};
-
#define INVALID_REG_ADDR 0xff
/*
@@ -110,40 +101,6 @@ enum bq27xxx_reg_index {
BQ27XXX_REG_AP, /* Average Power */
};
-struct bq27xxx_reg_cache {
- int temperature;
- int time_to_empty;
- int time_to_empty_avg;
- int time_to_full;
- int charge_full;
- int cycle_count;
- int capacity;
- int energy;
- int flags;
- int power_avg;
- int health;
-};
-
-struct bq27xxx_device_info {
- struct device *dev;
- int id;
- enum bq27xxx_chip chip;
-
- struct bq27xxx_reg_cache cache;
- int charge_design_full;
-
- unsigned long last_update;
- struct delayed_work work;
-
- struct power_supply *bat;
-
- struct bq27xxx_access_methods bus;
-
- struct mutex lock;
-
- u8 *regs;
-};
-
/* Register mappings */
static u8 bq27000_regs[] = {
0x00, /* CONTROL */
@@ -198,10 +155,10 @@ static u8 bq27500_regs[] = {
INVALID_REG_ADDR, /* TTECP - NA */
0x0c, /* NAC */
0x12, /* LMD(FCC) */
- 0x1e, /* CYCT */
+ 0x2a, /* CYCT */
INVALID_REG_ADDR, /* AE - NA */
- 0x20, /* SOC(RSOC) */
- 0x2e, /* DCAP(ILMD) */
+ 0x2c, /* SOC(RSOC) */
+ 0x3c, /* DCAP(ILMD) */
INVALID_REG_ADDR, /* AP - NA */
};
@@ -242,7 +199,7 @@ static u8 bq27541_regs[] = {
INVALID_REG_ADDR, /* AE - NA */
0x2c, /* SOC(RSOC) */
0x3c, /* DCAP */
- 0x76, /* AP */
+ 0x24, /* AP */
};
static u8 bq27545_regs[] = {
@@ -471,7 +428,10 @@ static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di)
{
int soc;
- soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ soc = bq27xxx_read(di, BQ27XXX_REG_SOC, true);
+ else
+ soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false);
if (soc < 0)
dev_dbg(di->dev, "error reading State-of-Charge\n");
@@ -536,7 +496,10 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
{
int dcap;
- dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
+ if (di->chip == BQ27000 || di->chip == BQ27010)
+ dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true);
+ else
+ dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false);
if (dcap < 0) {
dev_dbg(di->dev, "error reading initial last measured discharge\n");
@@ -544,7 +507,7 @@ static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di)
}
if (di->chip == BQ27000 || di->chip == BQ27010)
- dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
+ dcap = (dcap << 8) * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS;
else
dcap *= 1000;
@@ -710,7 +673,7 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di)
return POWER_SUPPLY_HEALTH_GOOD;
}
-static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+void bq27xxx_battery_update(struct bq27xxx_device_info *di)
{
struct bq27xxx_reg_cache cache = {0, };
bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010;
@@ -722,7 +685,7 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
if (cache.flags >= 0) {
cache.temperature = bq27xxx_battery_read_temperature(di);
if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) {
- dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
+ dev_info_once(di->dev, "battery is not calibrated! ignoring capacity values\n");
cache.capacity = -ENODATA;
cache.energy = -ENODATA;
cache.time_to_empty = -ENODATA;
@@ -761,6 +724,7 @@ static void bq27xxx_battery_update(struct bq27xxx_device_info *di)
di->last_update = jiffies;
}
+EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
static void bq27xxx_battery_poll(struct work_struct *work)
{
@@ -991,32 +955,30 @@ static void bq27xxx_external_power_changed(struct power_supply *psy)
schedule_delayed_work(&di->work, 0);
}
-static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
- const char *name)
+int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{
- int ret;
struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = { .drv_data = di, };
+ INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
+ mutex_init(&di->lock);
+ di->regs = bq27xxx_regs[di->chip];
+
psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL);
if (!psy_desc)
return -ENOMEM;
- psy_desc->name = name;
+ psy_desc->name = di->name;
psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
psy_desc->properties = bq27xxx_battery_props[di->chip].props;
psy_desc->num_properties = bq27xxx_battery_props[di->chip].size;
psy_desc->get_property = bq27xxx_battery_get_property;
psy_desc->external_power_changed = bq27xxx_external_power_changed;
- INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll);
- mutex_init(&di->lock);
-
di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
- ret = PTR_ERR(di->bat);
- dev_err(di->dev, "failed to register battery: %d\n", ret);
- return ret;
+ dev_err(di->dev, "failed to register battery\n");
+ return PTR_ERR(di->bat);
}
dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
@@ -1025,8 +987,9 @@ static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di,
return 0;
}
+EXPORT_SYMBOL_GPL(bq27xxx_battery_setup);
-static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di)
+void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
{
/*
* power_supply_unregister call bq27xxx_battery_get_property which
@@ -1042,192 +1005,7 @@ static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di)
mutex_destroy(&di->lock);
}
-
-/* i2c specific code */
-#ifdef CONFIG_BATTERY_BQ27XXX_I2C
-
-/* If the system has several batteries we need a different name for each
- * of them...
- */
-static DEFINE_IDR(battery_id);
-static DEFINE_MUTEX(battery_mutex);
-
-static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
-{
- struct bq27xxx_device_info *di = data;
-
- bq27xxx_battery_update(di);
-
- return IRQ_HANDLED;
-}
-
-static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
- bool single)
-{
- struct i2c_client *client = to_i2c_client(di->dev);
- struct i2c_msg msg[2];
- unsigned char data[2];
- int ret;
-
- if (!client->adapter)
- return -ENODEV;
-
- msg[0].addr = client->addr;
- msg[0].flags = 0;
- msg[0].buf = &reg;
- msg[0].len = sizeof(reg);
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].buf = data;
- if (single)
- msg[1].len = 1;
- else
- msg[1].len = 2;
-
- ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
- if (ret < 0)
- return ret;
-
- if (!single)
- ret = get_unaligned_le16(data);
- else
- ret = data[0];
-
- return ret;
-}
-
-static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- char *name;
- struct bq27xxx_device_info *di;
- int num;
- int retval = 0;
-
- /* Get new ID for the new battery device */
- mutex_lock(&battery_mutex);
- num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
- mutex_unlock(&battery_mutex);
- if (num < 0)
- return num;
-
- name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
- if (!name) {
- retval = -ENOMEM;
- goto batt_failed;
- }
-
- di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
- if (!di) {
- retval = -ENOMEM;
- goto batt_failed;
- }
-
- di->id = num;
- di->dev = &client->dev;
- di->chip = id->driver_data;
- di->bus.read = &bq27xxx_battery_i2c_read;
- di->regs = bq27xxx_regs[di->chip];
-
- retval = bq27xxx_powersupply_init(di, name);
- if (retval)
- goto batt_failed;
-
- /* Schedule a polling after about 1 min */
- schedule_delayed_work(&di->work, 60 * HZ);
-
- i2c_set_clientdata(client, di);
-
- if (client->irq) {
- retval = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, bq27xxx_battery_irq_handler_thread,
- IRQF_ONESHOT,
- name, di);
- if (retval) {
- dev_err(&client->dev,
- "Unable to register IRQ %d error %d\n",
- client->irq, retval);
- return retval;
- }
- }
-
- return 0;
-
-batt_failed:
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, num);
- mutex_unlock(&battery_mutex);
-
- return retval;
-}
-
-static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
-{
- struct bq27xxx_device_info *di = i2c_get_clientdata(client);
-
- bq27xxx_powersupply_unregister(di);
-
- mutex_lock(&battery_mutex);
- idr_remove(&battery_id, di->id);
- mutex_unlock(&battery_mutex);
-
- return 0;
-}
-
-static const struct i2c_device_id bq27xxx_id[] = {
- { "bq27200", BQ27000 },
- { "bq27210", BQ27010 },
- { "bq27500", BQ27500 },
- { "bq27510", BQ27500 },
- { "bq27520", BQ27500 },
- { "bq27530", BQ27530 },
- { "bq27531", BQ27530 },
- { "bq27541", BQ27541 },
- { "bq27542", BQ27541 },
- { "bq27546", BQ27541 },
- { "bq27742", BQ27541 },
- { "bq27545", BQ27545 },
- { "bq27421", BQ27421 },
- { "bq27425", BQ27421 },
- { "bq27441", BQ27421 },
- { "bq27621", BQ27421 },
- {},
-};
-MODULE_DEVICE_TABLE(i2c, bq27xxx_id);
-
-static struct i2c_driver bq27xxx_battery_i2c_driver = {
- .driver = {
- .name = "bq27xxx-battery",
- },
- .probe = bq27xxx_battery_i2c_probe,
- .remove = bq27xxx_battery_i2c_remove,
- .id_table = bq27xxx_id,
-};
-
-static inline int bq27xxx_battery_i2c_init(void)
-{
- int ret = i2c_add_driver(&bq27xxx_battery_i2c_driver);
-
- if (ret)
- pr_err("Unable to register BQ27xxx i2c driver\n");
-
- return ret;
-}
-
-static inline void bq27xxx_battery_i2c_exit(void)
-{
- i2c_del_driver(&bq27xxx_battery_i2c_driver);
-}
-
-#else
-
-static inline int bq27xxx_battery_i2c_init(void) { return 0; }
-static inline void bq27xxx_battery_i2c_exit(void) {};
-
-#endif
-
-/* platform specific code */
-#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
+EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
static int bq27xxx_battery_platform_read(struct bq27xxx_device_info *di, u8 reg,
bool single)
@@ -1267,7 +1045,6 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
{
struct bq27xxx_device_info *di;
struct bq27xxx_platform_data *pdata = pdev->dev.platform_data;
- const char *name;
if (!pdata) {
dev_err(&pdev->dev, "no platform_data supplied\n");
@@ -1292,83 +1069,36 @@ static int bq27xxx_battery_platform_probe(struct platform_device *pdev)
di->dev = &pdev->dev;
di->chip = pdata->chip;
- di->regs = bq27xxx_regs[di->chip];
-
- name = pdata->name ?: dev_name(&pdev->dev);
- di->bus.read = &bq27xxx_battery_platform_read;
+ di->name = pdata->name ?: dev_name(&pdev->dev);
+ di->bus.read = bq27xxx_battery_platform_read;
- return bq27xxx_powersupply_init(di, name);
+ return bq27xxx_battery_setup(di);
}
static int bq27xxx_battery_platform_remove(struct platform_device *pdev)
{
struct bq27xxx_device_info *di = platform_get_drvdata(pdev);
- bq27xxx_powersupply_unregister(di);
+ bq27xxx_battery_teardown(di);
return 0;
}
+static const struct platform_device_id bq27xxx_battery_platform_id_table[] = {
+ { "bq27000-battery", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, bq27xxx_battery_platform_id_table);
+
static struct platform_driver bq27xxx_battery_platform_driver = {
.probe = bq27xxx_battery_platform_probe,
.remove = bq27xxx_battery_platform_remove,
.driver = {
.name = "bq27000-battery",
},
+ .id_table = bq27xxx_battery_platform_id_table,
};
-
-static inline int bq27xxx_battery_platform_init(void)
-{
- int ret = platform_driver_register(&bq27xxx_battery_platform_driver);
-
- if (ret)
- pr_err("Unable to register BQ27xxx platform driver\n");
-
- return ret;
-}
-
-static inline void bq27xxx_battery_platform_exit(void)
-{
- platform_driver_unregister(&bq27xxx_battery_platform_driver);
-}
-
-#else
-
-static inline int bq27xxx_battery_platform_init(void) { return 0; }
-static inline void bq27xxx_battery_platform_exit(void) {};
-
-#endif
-
-/*
- * Module stuff
- */
-
-static int __init bq27xxx_battery_init(void)
-{
- int ret;
-
- ret = bq27xxx_battery_i2c_init();
- if (ret)
- return ret;
-
- ret = bq27xxx_battery_platform_init();
- if (ret)
- bq27xxx_battery_i2c_exit();
-
- return ret;
-}
-module_init(bq27xxx_battery_init);
-
-static void __exit bq27xxx_battery_exit(void)
-{
- bq27xxx_battery_platform_exit();
- bq27xxx_battery_i2c_exit();
-}
-module_exit(bq27xxx_battery_exit);
-
-#ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM
-MODULE_ALIAS("platform:bq27000-battery");
-#endif
+module_platform_driver(bq27xxx_battery_platform_driver);
MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
MODULE_DESCRIPTION("BQ27xxx battery monitor driver");
diff --git a/drivers/power/bq27xxx_battery_i2c.c b/drivers/power/bq27xxx_battery_i2c.c
new file mode 100644
index 000000000000..9429e66be096
--- /dev/null
+++ b/drivers/power/bq27xxx_battery_i2c.c
@@ -0,0 +1,150 @@
+/*
+ * SCI Reset driver for Keystone based devices
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Andrew F. Davis <afd@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <asm/unaligned.h>
+
+#include <linux/power/bq27xxx_battery.h>
+
+static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
+{
+ struct bq27xxx_device_info *di = data;
+
+ bq27xxx_battery_update(di);
+
+ return IRQ_HANDLED;
+}
+
+static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg,
+ bool single)
+{
+ struct i2c_client *client = to_i2c_client(di->dev);
+ struct i2c_msg msg[2];
+ unsigned char data[2];
+ int ret;
+
+ if (!client->adapter)
+ return -ENODEV;
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].buf = &reg;
+ msg[0].len = sizeof(reg);
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = data;
+ if (single)
+ msg[1].len = 1;
+ else
+ msg[1].len = 2;
+
+ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (ret < 0)
+ return ret;
+
+ if (!single)
+ ret = get_unaligned_le16(data);
+ else
+ ret = data[0];
+
+ return ret;
+}
+
+static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct bq27xxx_device_info *di;
+ int ret;
+
+ di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
+ if (!di)
+ return -ENOMEM;
+
+ di->dev = &client->dev;
+ di->chip = id->driver_data;
+ di->name = id->name;
+ di->bus.read = bq27xxx_battery_i2c_read;
+
+ ret = bq27xxx_battery_setup(di);
+ if (ret)
+ return ret;
+
+ /* Schedule a polling after about 1 min */
+ schedule_delayed_work(&di->work, 60 * HZ);
+
+ i2c_set_clientdata(client, di);
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, bq27xxx_battery_irq_handler_thread,
+ IRQF_ONESHOT,
+ di->name, di);
+ if (ret) {
+ dev_err(&client->dev,
+ "Unable to register IRQ %d error %d\n",
+ client->irq, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
+{
+ struct bq27xxx_device_info *di = i2c_get_clientdata(client);
+
+ bq27xxx_battery_teardown(di);
+
+ return 0;
+}
+
+static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
+ { "bq27200", BQ27000 },
+ { "bq27210", BQ27010 },
+ { "bq27500", BQ27500 },
+ { "bq27510", BQ27500 },
+ { "bq27520", BQ27500 },
+ { "bq27530", BQ27530 },
+ { "bq27531", BQ27530 },
+ { "bq27541", BQ27541 },
+ { "bq27542", BQ27541 },
+ { "bq27546", BQ27541 },
+ { "bq27742", BQ27541 },
+ { "bq27545", BQ27545 },
+ { "bq27421", BQ27421 },
+ { "bq27425", BQ27421 },
+ { "bq27441", BQ27421 },
+ { "bq27621", BQ27421 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
+
+static struct i2c_driver bq27xxx_battery_i2c_driver = {
+ .driver = {
+ .name = "bq27xxx-battery",
+ },
+ .probe = bq27xxx_battery_i2c_probe,
+ .remove = bq27xxx_battery_i2c_remove,
+ .id_table = bq27xxx_i2c_id_table,
+};
+module_i2c_driver(bq27xxx_battery_i2c_driver);
+
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
+MODULE_DESCRIPTION("BQ27xxx battery monitor i2c driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index ed4d756d21e4..a1b7e0592245 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -59,7 +59,7 @@ struct ds278x_info {
struct i2c_client *client;
struct power_supply *battery;
struct power_supply_desc battery_desc;
- struct ds278x_battery_ops *ops;
+ const struct ds278x_battery_ops *ops;
struct delayed_work bat_work;
int id;
int rsns;
@@ -361,7 +361,7 @@ enum ds278x_num_id {
DS2786,
};
-static struct ds278x_battery_ops ds278x_ops[] = {
+static const struct ds278x_battery_ops ds278x_ops[] = {
[DS2782] = {
.get_battery_current = ds2782_get_current,
.get_battery_voltage = ds2782_get_voltage,
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c
index fedc5818fab7..edb36bf781b0 100644
--- a/drivers/power/generic-adc-battery.c
+++ b/drivers/power/generic-adc-battery.c
@@ -206,7 +206,7 @@ static void gab_work(struct work_struct *work)
bool is_plugged;
int status;
- delayed_work = container_of(work, struct delayed_work, work);
+ delayed_work = to_delayed_work(work);
adc_bat = container_of(delayed_work, struct gab, bat_work);
pdata = adc_bat->pdata;
status = adc_bat->status;
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index f2a7d970388f..46a292aa182d 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -76,7 +76,7 @@ static inline int isp1704_read(struct isp1704_charger *isp, u32 reg)
return usb_phy_io_read(isp->phy, reg);
}
-static inline int isp1704_write(struct isp1704_charger *isp, u32 val, u32 reg)
+static inline int isp1704_write(struct isp1704_charger *isp, u32 reg, u32 val)
{
return usb_phy_io_write(isp->phy, val, reg);
}
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 6d39d52040d4..17876caf31e5 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -291,10 +291,10 @@ static int max8903_probe(struct platform_device *pdev)
if (pdata->dc_valid) {
ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok),
- NULL, max8903_dcin,
- IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING,
- "MAX8903 DC IN", data);
+ NULL, max8903_dcin,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "MAX8903 DC IN", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for DC (%d)\n",
gpio_to_irq(pdata->dok), ret);
@@ -304,10 +304,10 @@ static int max8903_probe(struct platform_device *pdev)
if (pdata->usb_valid) {
ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok),
- NULL, max8903_usbin,
- IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING,
- "MAX8903 USB IN", data);
+ NULL, max8903_usbin,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "MAX8903 USB IN", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for USB (%d)\n",
gpio_to_irq(pdata->uok), ret);
@@ -317,10 +317,10 @@ static int max8903_probe(struct platform_device *pdev)
if (pdata->flt) {
ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt),
- NULL, max8903_fault,
- IRQF_TRIGGER_FALLING |
- IRQF_TRIGGER_RISING,
- "MAX8903 Fault", data);
+ NULL, max8903_fault,
+ IRQF_TRIGGER_FALLING |
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "MAX8903 Fault", data);
if (ret) {
dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
gpio_to_irq(pdata->flt), ret);
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c
index 3f6b5dd7c3d4..1b5d450586d1 100644
--- a/drivers/power/reset/at91-reset.c
+++ b/drivers/power/reset/at91-reset.c
@@ -198,6 +198,7 @@ static int __init at91_reset_probe(struct platform_device *pdev)
at91_ramc_base[idx] = of_iomap(np, 0);
if (!at91_ramc_base[idx]) {
dev_err(&pdev->dev, "Could not map ram controller address\n");
+ of_node_put(np);
return -ENODEV;
}
idx++;
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c
index 83c42ea88f2b..57246cdbd042 100644
--- a/drivers/power/test_power.c
+++ b/drivers/power/test_power.c
@@ -301,6 +301,8 @@ static int map_get_value(struct battery_property_map *map, const char *key,
buf[MAX_KEYLENGTH-1] = '\0';
cr = strnlen(buf, MAX_KEYLENGTH) - 1;
+ if (cr < 0)
+ return def_val;
if (buf[cr] == '\n')
buf[cr] = '\0';
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8df0b0e62976..2805b014ae31 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -588,10 +588,10 @@ config REGULATOR_S2MPA01
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11
- tristate "Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage regulator"
+ tristate "Samsung S2MPS11/13/14/15/S2MPU02 voltage regulator"
depends on MFD_SEC_CORE
help
- This driver supports a Samsung S2MPS11/S2MPS13/S2MPS14/S2MPU02 voltage
+ This driver supports a Samsung S2MPS11/13/14/15/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.
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 72fc3c32db49..3242ffc0cb25 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -32,6 +32,7 @@
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps13.h>
#include <linux/mfd/samsung/s2mps14.h>
+#include <linux/mfd/samsung/s2mps15.h>
#include <linux/mfd/samsung/s2mpu02.h>
/* The highest number of possible regulators for supported devices. */
@@ -661,6 +662,133 @@ static const struct regulator_desc s2mps14_regulators[] = {
S2MPS14_BUCK1235_START_SEL),
};
+static struct regulator_ops s2mps15_reg_ldo_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static struct regulator_ops s2mps15_reg_buck_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
+#define regulator_desc_s2mps15_ldo(num, range) { \
+ .name = "LDO"#num, \
+ .id = S2MPS15_LDO##num, \
+ .ops = &s2mps15_reg_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .linear_ranges = range, \
+ .n_linear_ranges = ARRAY_SIZE(range), \
+ .n_voltages = S2MPS15_LDO_N_VOLTAGES, \
+ .vsel_reg = S2MPS15_REG_L1CTRL + num - 1, \
+ .vsel_mask = S2MPS15_LDO_VSEL_MASK, \
+ .enable_reg = S2MPS15_REG_L1CTRL + num - 1, \
+ .enable_mask = S2MPS15_ENABLE_MASK \
+}
+
+#define regulator_desc_s2mps15_buck(num, range) { \
+ .name = "BUCK"#num, \
+ .id = S2MPS15_BUCK##num, \
+ .ops = &s2mps15_reg_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .linear_ranges = range, \
+ .n_linear_ranges = ARRAY_SIZE(range), \
+ .ramp_delay = 12500, \
+ .n_voltages = S2MPS15_BUCK_N_VOLTAGES, \
+ .vsel_reg = S2MPS15_REG_B1CTRL2 + ((num - 1) * 2), \
+ .vsel_mask = S2MPS15_BUCK_VSEL_MASK, \
+ .enable_reg = S2MPS15_REG_B1CTRL1 + ((num - 1) * 2), \
+ .enable_mask = S2MPS15_ENABLE_MASK \
+}
+
+/* voltage range for s2mps15 LDO 3, 5, 15, 16, 18, 20, 23 and 27 */
+static const struct regulator_linear_range s2mps15_ldo_voltage_ranges1[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0xc, 0x38, 25000),
+};
+
+/* voltage range for s2mps15 LDO 2, 6, 14, 17, 19, 21, 24 and 25 */
+static const struct regulator_linear_range s2mps15_ldo_voltage_ranges2[] = {
+ REGULATOR_LINEAR_RANGE(1800000, 0x0, 0x3f, 25000),
+};
+
+/* voltage range for s2mps15 LDO 4, 11, 12, 13, 22 and 26 */
+static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = {
+ REGULATOR_LINEAR_RANGE(700000, 0x0, 0x34, 12500),
+};
+
+/* voltage range for s2mps15 LDO 7, 8, 9 and 10 */
+static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = {
+ REGULATOR_LINEAR_RANGE(700000, 0xc, 0x18, 25000),
+};
+
+/* voltage range for s2mps15 LDO 1 */
+static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x0, 0x20, 12500),
+};
+
+/* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */
+static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x20, 0xb0, 6250),
+};
+
+/* voltage range for s2mps15 BUCK 8, 9 and 10 */
+static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = {
+ REGULATOR_LINEAR_RANGE(1000000, 0x20, 0xc0, 12500),
+};
+
+static const struct regulator_desc s2mps15_regulators[] = {
+ regulator_desc_s2mps15_ldo(1, s2mps15_ldo_voltage_ranges5),
+ regulator_desc_s2mps15_ldo(2, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(3, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(4, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(5, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(6, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(7, s2mps15_ldo_voltage_ranges4),
+ regulator_desc_s2mps15_ldo(8, s2mps15_ldo_voltage_ranges4),
+ regulator_desc_s2mps15_ldo(9, s2mps15_ldo_voltage_ranges4),
+ regulator_desc_s2mps15_ldo(10, s2mps15_ldo_voltage_ranges4),
+ regulator_desc_s2mps15_ldo(11, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(12, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(13, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(14, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(15, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(16, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(17, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(18, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(19, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(20, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(21, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(22, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(23, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_ldo(24, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(25, s2mps15_ldo_voltage_ranges2),
+ regulator_desc_s2mps15_ldo(26, s2mps15_ldo_voltage_ranges3),
+ regulator_desc_s2mps15_ldo(27, s2mps15_ldo_voltage_ranges1),
+ regulator_desc_s2mps15_buck(1, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(2, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(3, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(4, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(5, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(6, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(7, s2mps15_buck_voltage_ranges1),
+ regulator_desc_s2mps15_buck(8, s2mps15_buck_voltage_ranges2),
+ regulator_desc_s2mps15_buck(9, s2mps15_buck_voltage_ranges2),
+ regulator_desc_s2mps15_buck(10, s2mps15_buck_voltage_ranges2),
+};
+
static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
struct regulator_dev *rdev)
{
@@ -974,6 +1102,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
regulators = s2mps14_regulators;
BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
+ case S2MPS15X:
+ s2mps11->rdev_num = ARRAY_SIZE(s2mps15_regulators);
+ regulators = s2mps15_regulators;
+ break;
case S2MPU02:
s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
regulators = s2mpu02_regulators;
@@ -1067,10 +1199,11 @@ out:
}
static const struct platform_device_id s2mps11_pmic_id[] = {
- { "s2mps11-pmic", S2MPS11X},
- { "s2mps13-pmic", S2MPS13X},
- { "s2mps14-pmic", S2MPS14X},
- { "s2mpu02-pmic", S2MPU02},
+ { "s2mps11-regulator", S2MPS11X},
+ { "s2mps13-regulator", S2MPS13X},
+ { "s2mps14-regulator", S2MPS14X},
+ { "s2mps15-regulator", S2MPS15X},
+ { "s2mpu02-regulator", S2MPU02},
{ },
};
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
@@ -1097,5 +1230,5 @@ module_exit(s2mps11_pmic_exit);
/* Module information */
MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPU02 Regulator Driver");
+MODULE_DESCRIPTION("SAMSUNG S2MPS11/S2MPS14/S2MPS15/S2MPU02 Regulator Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index f2504b4eef34..0d68a85dd429 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -188,6 +188,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
val &= S5M_ALARM0_STATUS;
break;
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2,
@@ -219,9 +220,22 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
return ret;
}
- data |= info->regs->rtc_udr_mask;
- if (info->device_type == S5M8763X || info->device_type == S5M8767X)
- data |= S5M_RTC_TIME_EN_MASK;
+ switch (info->device_type) {
+ case S5M8763X:
+ case S5M8767X:
+ data |= info->regs->rtc_udr_mask | S5M_RTC_TIME_EN_MASK;
+ case S2MPS15X:
+ /* As per UM, for write time register, set WUDR bit to high */
+ data |= S2MPS15_RTC_WUDR_MASK;
+ break;
+ case S2MPS14X:
+ case S2MPS13X:
+ data |= info->regs->rtc_udr_mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+
ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
if (ret < 0) {
@@ -252,6 +266,11 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
case S5M8767X:
data &= ~S5M_RTC_TIME_EN_MASK;
break;
+ case S2MPS15X:
+ /* As per UM, for write alarm, set A_UDR(bit[4]) to high
+ * rtc_udr_mask above sets bit[4]
+ */
+ break;
case S2MPS14X:
data |= S2MPS_RTC_RUDR_MASK;
break;
@@ -317,7 +336,8 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
u8 data[info->regs->regs_count];
int ret;
- if (info->device_type == S2MPS14X || info->device_type == S2MPS13X) {
+ if (info->device_type == S2MPS15X || info->device_type == S2MPS14X ||
+ info->device_type == S2MPS13X) {
ret = regmap_update_bits(info->regmap,
info->regs->rtc_udr_update,
S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
@@ -339,6 +359,7 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode);
@@ -366,6 +387,7 @@ static int s5m_rtc_set_time(struct device *dev, struct rtc_time *tm)
s5m8763_tm_to_data(tm, data);
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
ret = s5m8767_tm_to_data(tm, data);
@@ -414,6 +436,7 @@ static int s5m_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
@@ -463,6 +486,7 @@ static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info)
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
for (i = 0; i < info->regs->regs_count; i++)
@@ -508,6 +532,7 @@ static int s5m_rtc_start_alarm(struct s5m_rtc_info *info)
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
data[RTC_SEC] |= ALARM_ENABLE_MASK;
@@ -548,6 +573,7 @@ static int s5m_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
break;
case S5M8767X:
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
s5m8767_tm_to_data(&alrm->time, data);
@@ -631,6 +657,7 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
break;
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
@@ -679,6 +706,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
switch (platform_get_device_id(pdev)->driver_data) {
+ case S2MPS15X:
case S2MPS14X:
case S2MPS13X:
regmap_cfg = &s2mps14_rtc_regmap_config;
@@ -805,6 +833,7 @@ static const struct platform_device_id s5m_rtc_id[] = {
{ "s5m-rtc", S5M8767X },
{ "s2mps13-rtc", S2MPS13X },
{ "s2mps14-rtc", S2MPS14X },
+ { "s2mps15-rtc", S2MPS15X },
{ },
};
MODULE_DEVICE_TABLE(platform, s5m_rtc_id);
diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c
index bc1b80ec6afe..1a7b5caa127b 100644
--- a/drivers/soc/ti/knav_dma.c
+++ b/drivers/soc/ti/knav_dma.c
@@ -389,7 +389,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name,
*dma_instance = dma_node->name;
index = of_property_match_string(np, "ti,navigator-dma-names", name);
if (index < 0) {
- dev_err(kdev->dev, "No 'ti,navigator-dma-names' propery\n");
+ dev_err(kdev->dev, "No 'ti,navigator-dma-names' property\n");
return -ENODEV;
}
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 98ffe71e8af2..510e559c060e 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -566,11 +566,13 @@ static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev,
mutex_lock(&data->lock);
error = adp8860_read(data->client, ADP8860_PH1LEVL, &reg_val);
- ret_val = reg_val;
- error |= adp8860_read(data->client, ADP8860_PH1LEVH, &reg_val);
+ if (!error) {
+ ret_val = reg_val;
+ error = adp8860_read(data->client, ADP8860_PH1LEVH, &reg_val);
+ }
mutex_unlock(&data->lock);
- if (error < 0)
+ if (error)
return error;
/* Return 13-bit conversion value for the first light sensor */
@@ -621,10 +623,12 @@ static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev,
/* Set user supplied ambient light zone */
mutex_lock(&data->lock);
- adp8860_read(data->client, ADP8860_CFGR, &reg_val);
- reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
- reg_val |= (val - 1) << CFGR_BLV_SHIFT;
- adp8860_write(data->client, ADP8860_CFGR, reg_val);
+ ret = adp8860_read(data->client, ADP8860_CFGR, &reg_val);
+ if (!ret) {
+ reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
+ reg_val |= (val - 1) << CFGR_BLV_SHIFT;
+ adp8860_write(data->client, ADP8860_CFGR, reg_val);
+ }
mutex_unlock(&data->lock);
}
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 9d738352d7d4..21acac90fd77 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -807,10 +807,12 @@ static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
/* Set user supplied ambient light zone */
mutex_lock(&data->lock);
- adp8870_read(data->client, ADP8870_CFGR, &reg_val);
- reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
- reg_val |= (val - 1) << CFGR_BLV_SHIFT;
- adp8870_write(data->client, ADP8870_CFGR, reg_val);
+ ret = adp8870_read(data->client, ADP8870_CFGR, &reg_val);
+ if (!ret) {
+ reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
+ reg_val |= (val - 1) << CFGR_BLV_SHIFT;
+ adp8870_write(data->client, ADP8870_CFGR, reg_val);
+ }
mutex_unlock(&data->lock);
}
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
index 5fbbc2ebdf93..18134416b154 100644
--- a/drivers/video/backlight/gpio_backlight.c
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -89,6 +89,7 @@ static int gpio_backlight_probe(struct platform_device *pdev)
struct backlight_device *bl;
struct gpio_backlight *gbl;
struct device_node *np = pdev->dev.of_node;
+ unsigned long flags = GPIOF_DIR_OUT;
int ret;
if (!pdata && !np) {
@@ -114,9 +115,12 @@ static int gpio_backlight_probe(struct platform_device *pdev)
gbl->def_value = pdata->def_value;
}
- ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT |
- (gbl->active ? GPIOF_INIT_LOW
- : GPIOF_INIT_HIGH),
+ if (gbl->active)
+ flags |= gbl->def_value ? GPIOF_INIT_HIGH : GPIOF_INIT_LOW;
+ else
+ flags |= gbl->def_value ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH;
+
+ ret = devm_gpio_request_one(gbl->dev, gbl->gpio, flags,
pdata ? pdata->name : "backlight");
if (ret < 0) {
dev_err(&pdev->dev, "unable to request GPIO\n");
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index ae3c6b6fd5db..64f9e1b8655f 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -198,7 +198,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
struct platform_pwm_backlight_data defdata;
struct backlight_properties props;
struct backlight_device *bl;
+ struct device_node *node = pdev->dev.of_node;
struct pwm_bl_data *pb;
+ int initial_blank = FB_BLANK_UNBLANK;
int ret;
if (!data) {
@@ -242,7 +244,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->enabled = false;
pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
- GPIOD_OUT_HIGH);
+ GPIOD_ASIS);
if (IS_ERR(pb->enable_gpio)) {
ret = PTR_ERR(pb->enable_gpio);
goto err_alloc;
@@ -264,15 +266,32 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->enable_gpio = gpio_to_desc(data->enable_gpio);
}
+ if (pb->enable_gpio) {
+ /*
+ * If the driver is probed from the device tree and there is a
+ * phandle link pointing to the backlight node, it is safe to
+ * assume that another driver will enable the backlight at the
+ * appropriate time. Therefore, if it is disabled, keep it so.
+ */
+ if (node && node->phandle &&
+ gpiod_get_direction(pb->enable_gpio) == GPIOF_DIR_OUT &&
+ gpiod_get_value(pb->enable_gpio) == 0)
+ initial_blank = FB_BLANK_POWERDOWN;
+ else
+ gpiod_direction_output(pb->enable_gpio, 1);
+ }
+
pb->power_supply = devm_regulator_get(&pdev->dev, "power");
if (IS_ERR(pb->power_supply)) {
ret = PTR_ERR(pb->power_supply);
goto err_alloc;
}
+ if (node && node->phandle && !regulator_is_enabled(pb->power_supply))
+ initial_blank = FB_BLANK_POWERDOWN;
+
pb->pwm = devm_pwm_get(&pdev->dev, NULL);
- if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER
- && !pdev->dev.of_node) {
+ if (IS_ERR(pb->pwm) && PTR_ERR(pb->pwm) != -EPROBE_DEFER && !node) {
dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
pb->legacy = true;
pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
@@ -309,6 +328,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
ret = PTR_ERR(bl);
+ if (pb->legacy)
+ pwm_free(pb->pwm);
goto err_alloc;
}
@@ -320,6 +341,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
}
bl->props.brightness = data->dft_brightness;
+ bl->props.power = initial_blank;
backlight_update_status(bl);
platform_set_drvdata(pdev, bl);
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 61d72bffd402..fd524ad860a5 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -320,10 +320,19 @@ static int tps65217_bl_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id tps65217_bl_of_match[] = {
+ { .compatible = "ti,tps65217-bl", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, tps65217_bl_of_match);
+#endif
+
static struct platform_driver tps65217_bl_driver = {
.probe = tps65217_bl_probe,
.driver = {
.name = "tps65217-bl",
+ .of_match_table = of_match_ptr(tps65217_bl_of_match),
},
};