summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpica/aclocal.h1
-rw-r--r--drivers/acpi/acpica/acnamesp.h17
-rw-r--r--drivers/acpi/acpica/acutils.h2
-rw-r--r--drivers/acpi/acpica/dbinput.c10
-rw-r--r--drivers/acpi/acpica/dbmethod.c8
-rw-r--r--drivers/acpi/acpica/dbxface.c10
-rw-r--r--drivers/acpi/acpica/dsfield.c34
-rw-r--r--drivers/acpi/acpica/hwregs.c9
-rw-r--r--drivers/acpi/acpica/hwsleep.c11
-rw-r--r--drivers/acpi/acpica/nsaccess.c13
-rw-r--r--drivers/acpi/acpica/psloop.c43
-rw-r--r--drivers/acpi/acpica/tbdata.c4
-rw-r--r--drivers/acpi/acpica/utdelete.c7
-rw-r--r--drivers/acpi/acpica/utstrsuppt.c26
-rw-r--r--drivers/acpi/acpica/utstrtoul64.c2
-rw-r--r--drivers/acpi/pmic/intel_pmic_crc.c109
-rw-r--r--drivers/ata/ahci_platform.c1
-rw-r--r--drivers/block/DAC960.c42
-rw-r--r--drivers/block/pktcdvd.c1
-rw-r--r--drivers/block/rbd.c125
-rw-r--r--drivers/block/zram/zram_drv.c7
-rw-r--r--drivers/bus/Kconfig10
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/sun50i-de2.c48
-rw-r--r--drivers/bus/ti-sysc.c64
-rw-r--r--drivers/char/rtc.c13
-rw-r--r--drivers/clk/davinci/psc-da830.c3
-rw-r--r--drivers/clk/davinci/psc-da850.c3
-rw-r--r--drivers/clk/davinci/psc-dm365.c3
-rw-r--r--drivers/clk/davinci/psc-dm644x.c3
-rw-r--r--drivers/clk/davinci/psc-dm646x.c3
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c167
-rw-r--r--drivers/clk/ti/clk-7xx.c1
-rw-r--r--drivers/cpufreq/Kconfig.arm14
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/cpufreq_governor.c12
-rw-r--r--drivers/cpufreq/exynos5440-cpufreq.c452
-rw-r--r--drivers/cpuidle/governors/menu.c45
-rw-r--r--drivers/crypto/caam/sg_sw_qm2.h2
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h2
-rw-r--r--drivers/edac/edac_mc.c1
-rw-r--r--drivers/firmware/arm_scmi/perf.c5
-rw-r--r--drivers/firmware/efi/libstub/Makefile1
-rw-r--r--drivers/firmware/psci_checker.c83
-rw-r--r--drivers/firmware/raspberrypi.c29
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-madera.c206
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c43
-rw-r--r--drivers/gpu/drm/i915/Kconfig1
-rw-r--r--drivers/gpu/drm/i915/i915_gem_userptr.c13
-rw-r--r--drivers/gpu/drm/i915/i915_utils.h2
-rw-r--r--drivers/gpu/drm/i915/intel_display.h24
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_mn.c22
-rw-r--r--drivers/hid/Kconfig10
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c40
-rw-r--r--drivers/hid/hid-cougar.c312
-rw-r--r--drivers/hid/hid-elan.c235
-rw-r--r--drivers/hid/hid-ids.h5
-rw-r--r--drivers/hid/hid-input.c3
-rw-r--r--drivers/hid/hid-microsoft.c49
-rw-r--r--drivers/hid/hid-multitouch.c989
-rw-r--r--drivers/hid/hid-ntrig.c2
-rw-r--r--drivers/hid/hid-redragon.c26
-rw-r--r--drivers/hid/hid-sony.c164
-rw-r--r--drivers/hid/hid-wiimote-core.c14
-rw-r--r--drivers/hid/hid-wiimote-modules.c440
-rw-r--r--drivers/hid/hid-wiimote.h3
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c57
-rw-r--r--drivers/hid/intel-ish-hid/ipc/ipc.c9
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c13
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/hbm.c2
-rw-r--r--drivers/hid/usbhid/hid-core.c7
-rw-r--r--drivers/hid/wacom_sys.c123
-rw-r--r--drivers/hid/wacom_wac.c20
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/raspberrypi-hwmon.c166
-rw-r--r--drivers/i2c/busses/Kconfig42
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c40
-rw-r--r--drivers/i2c/busses/i2c-brcmstb.c8
-rw-r--r--drivers/i2c/busses/i2c-davinci.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-baytrail.c10
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c91
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h24
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c223
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c17
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c68
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c62
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c22
-rw-r--r--drivers/i2c/busses/i2c-fsi.c752
-rw-r--r--drivers/i2c/busses/i2c-gpio.c97
-rw-r--r--drivers/i2c/busses/i2c-i801.c4
-rw-r--r--drivers/i2c/busses/i2c-imx.c23
-rw-r--r--drivers/i2c/busses/i2c-mxs.c8
-rw-r--r--drivers/i2c/busses/i2c-owl.c495
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c3
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c17
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c673
-rw-r--r--drivers/i2c/busses/i2c-rcar.c73
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c4
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c10
-rw-r--r--drivers/i2c/busses/i2c-sprd.c8
-rw-r--r--drivers/i2c/busses/i2c-stu300.c12
-rw-r--r--drivers/i2c/busses/i2c-tegra.c90
-rw-r--r--drivers/i2c/busses/i2c-xlr.c11
-rw-r--r--drivers/i2c/i2c-core-acpi.c19
-rw-r--r--drivers/i2c/i2c-core-base.c85
-rw-r--r--drivers/i2c/i2c-core-slave.c8
-rw-r--r--drivers/i2c/i2c-mux.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-mlxcpld.c28
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca9541.c75
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c51
-rw-r--r--drivers/ide/hpt366.c5
-rw-r--r--drivers/ide/ide-floppy.c1
-rw-r--r--drivers/ide/ide-io.c4
-rw-r--r--drivers/ide/ide-probe.c1
-rw-r--r--drivers/ide/ide-tape.c2
-rw-r--r--drivers/ide/ide-taskfile.c3
-rw-r--r--drivers/ide/sis5513.c1
-rw-r--r--drivers/iio/temperature/mlx90614.c4
-rw-r--r--drivers/infiniband/core/umem_odp.c33
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.c11
-rw-r--r--drivers/infiniband/hw/mlx5/odp.c2
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/serio/ams_delta_serio.c198
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c4
-rw-r--r--drivers/irqchip/irq-renesas-h8s.c6
-rw-r--r--drivers/irqchip/irq-xtensa-mx.c2
-rw-r--r--drivers/irqchip/irq-xtensa-pic.c2
-rw-r--r--drivers/md/bcache/Kconfig7
-rw-r--r--drivers/md/bcache/alloc.c39
-rw-r--r--drivers/md/bcache/bcache.h210
-rw-r--r--drivers/md/bcache/bset.c142
-rw-r--r--drivers/md/bcache/bset.h146
-rw-r--r--drivers/md/bcache/btree.c72
-rw-r--r--drivers/md/bcache/btree.h86
-rw-r--r--drivers/md/bcache/closure.c6
-rw-r--r--drivers/md/bcache/closure.h6
-rw-r--r--drivers/md/bcache/debug.c23
-rw-r--r--drivers/md/bcache/debug.h6
-rw-r--r--drivers/md/bcache/extents.c37
-rw-r--r--drivers/md/bcache/extents.h6
-rw-r--r--drivers/md/bcache/io.c24
-rw-r--r--drivers/md/bcache/journal.c27
-rw-r--r--drivers/md/bcache/journal.h28
-rw-r--r--drivers/md/bcache/movinggc.c14
-rw-r--r--drivers/md/bcache/request.c61
-rw-r--r--drivers/md/bcache/request.h18
-rw-r--r--drivers/md/bcache/stats.c15
-rw-r--r--drivers/md/bcache/stats.h15
-rw-r--r--drivers/md/bcache/super.c107
-rw-r--r--drivers/md/bcache/sysfs.c36
-rw-r--r--drivers/md/bcache/sysfs.h6
-rw-r--r--drivers/md/bcache/util.c133
-rw-r--r--drivers/md/bcache/util.h41
-rw-r--r--drivers/md/bcache/writeback.c30
-rw-r--r--drivers/md/bcache/writeback.h19
-rw-r--r--drivers/media/cec/cec-notifier.c11
-rw-r--r--drivers/media/dvb-frontends/af9013.c8
-rw-r--r--drivers/media/dvb-frontends/drxk_hard.c4
-rw-r--r--drivers/media/dvb-frontends/rtl2830.c12
-rw-r--r--drivers/media/dvb-frontends/tda1004x.c6
-rw-r--r--drivers/media/platform/Kconfig11
-rw-r--r--drivers/media/platform/Makefile2
-rw-r--r--drivers/media/platform/cros-ec-cec/Makefile1
-rw-r--r--drivers/media/platform/cros-ec-cec/cros-ec-cec.c347
-rw-r--r--drivers/media/tuners/tda18271-common.c8
-rw-r--r--drivers/memory/tegra/mc.c16
-rw-r--r--drivers/memory/ti-emif-pm.c33
-rw-r--r--drivers/mfd/88pm860x-i2c.c8
-rw-r--r--drivers/mfd/Kconfig83
-rw-r--r--drivers/mfd/Makefile17
-rw-r--r--drivers/mfd/arizona-core.c34
-rw-r--r--drivers/mfd/as3722.c12
-rw-r--r--drivers/mfd/axp20x-i2c.c2
-rw-r--r--drivers/mfd/axp20x.c28
-rw-r--r--drivers/mfd/cros_ec_dev.c32
-rw-r--r--drivers/mfd/cs47l35-tables.c1609
-rw-r--r--drivers/mfd/cs47l85-tables.c3009
-rw-r--r--drivers/mfd/cs47l90-tables.c2674
-rw-r--r--drivers/mfd/da9063-core.c44
-rw-r--r--drivers/mfd/da9063-i2c.c239
-rw-r--r--drivers/mfd/da9063-irq.c264
-rw-r--r--drivers/mfd/dln2.c10
-rw-r--r--drivers/mfd/hi655x-pmic.c2
-rw-r--r--drivers/mfd/intel-lpss-pci.c13
-rw-r--r--drivers/mfd/kempld-core.c15
-rw-r--r--drivers/mfd/madera-core.c609
-rw-r--r--drivers/mfd/madera-i2c.c140
-rw-r--r--drivers/mfd/madera-spi.c139
-rw-r--r--drivers/mfd/madera.h44
-rw-r--r--drivers/mfd/rave-sp.c119
-rw-r--r--drivers/mfd/rohm-bd718x7.c211
-rw-r--r--drivers/mfd/sec-core.c1
-rw-r--r--drivers/mfd/sm501.c1
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c3
-rw-r--r--drivers/mfd/wm8994-core.c15
-rw-r--r--drivers/misc/eeprom/at24.c17
-rw-r--r--drivers/misc/mic/scif/scif_dma.c7
-rw-r--r--drivers/misc/sgi-gru/grutlbpurge.c7
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c13
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c9
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h1
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/pci/pci-acpi.c6
-rw-r--r--drivers/pci/quirks.c12
-rw-r--r--drivers/pinctrl/Kconfig1
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/cirrus/Kconfig14
-rw-r--r--drivers/pinctrl/cirrus/Makefile13
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l35.c45
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l85.c59
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-cs47l90.c57
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera-core.c1076
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera.h41
-rw-r--r--drivers/platform/chrome/Kconfig20
-rw-r--r--drivers/platform/chrome/Makefile2
-rw-r--r--drivers/platform/chrome/chromeos_tbmc.c10
-rw-r--r--drivers/platform/chrome/cros_ec_i2c.c (renamed from drivers/mfd/cros_ec_i2c.c)0
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c40
-rw-r--r--drivers/platform/chrome/cros_ec_spi.c (renamed from drivers/mfd/cros_ec_spi.c)0
-rw-r--r--drivers/platform/mellanox/Kconfig11
-rw-r--r--drivers/platform/mellanox/Makefile1
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c60
-rw-r--r--drivers/platform/mellanox/mlxreg-io.c245
-rw-r--r--drivers/platform/x86/Kconfig16
-rw-r--r--drivers/platform/x86/Makefile2
-rw-r--r--drivers/platform/x86/acer-wmi.c7
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c1
-rw-r--r--drivers/platform/x86/asus-wireless.c24
-rw-r--r--drivers/platform/x86/asus-wmi.c34
-rw-r--r--drivers/platform/x86/dell-smbios-base.c35
-rw-r--r--drivers/platform/x86/dell-smbios-smm.c4
-rw-r--r--drivers/platform/x86/dell-smbios-wmi.c2
-rw-r--r--drivers/platform/x86/ideapad-laptop.c18
-rw-r--r--drivers/platform/x86/intel-hid.c178
-rw-r--r--drivers/platform/x86/intel-vbtn.c5
-rw-r--r--drivers/platform/x86/intel_ips.c5
-rw-r--r--drivers/platform/x86/intel_pmc_core.c120
-rw-r--r--drivers/platform/x86/intel_pmc_core.h6
-rw-r--r--drivers/platform/x86/intel_punit_ipc.c1
-rw-r--r--drivers/platform/x86/mlx-platform.c486
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c136
-rw-r--r--drivers/platform/x86/toshiba_acpi.c33
-rw-r--r--drivers/platform/x86/touchscreen_dmi.c (renamed from drivers/platform/x86/silead_dmi.c)639
-rw-r--r--drivers/platform/x86/wmi.c9
-rw-r--r--drivers/power/reset/Kconfig11
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/gemini-poweroff.c12
-rw-r--r--drivers/power/reset/qcom-pon.c91
-rw-r--r--drivers/power/reset/vexpress-poweroff.c12
-rw-r--r--drivers/power/reset/zx-reboot.c1
-rw-r--r--drivers/power/supply/Kconfig23
-rw-r--r--drivers/power/supply/Makefile2
-rw-r--r--drivers/power/supply/ab8500_fg.c14
-rw-r--r--drivers/power/supply/adp5061.c745
-rw-r--r--drivers/power/supply/axp20x_usb_power.c1
-rw-r--r--drivers/power/supply/axp288_charger.c2
-rw-r--r--drivers/power/supply/bq27xxx_battery.c3
-rw-r--r--drivers/power/supply/cros_usbpd-charger.c545
-rw-r--r--drivers/power/supply/ds2760_battery.c348
-rw-r--r--drivers/power/supply/generic-adc-battery.c25
-rw-r--r--drivers/power/supply/lego_ev3_battery.c20
-rw-r--r--drivers/power/supply/max1721x_battery.c2
-rw-r--r--drivers/power/supply/max77693_charger.c1
-rw-r--r--drivers/power/supply/power_supply_core.c11
-rw-r--r--drivers/power/supply/sbs-battery.c67
-rw-r--r--drivers/power/supply/tps65217_charger.c22
-rw-r--r--drivers/power/supply/wm8350_power.c3
-rw-r--r--drivers/rapidio/devices/rio_mport_cdev.c2
-rw-r--r--drivers/regulator/da9063-regulator.c84
-rw-r--r--drivers/reset/Kconfig19
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/reset-qcom-aoss.c133
-rw-r--r--drivers/reset/reset-simple.c1
-rw-r--r--drivers/reset/reset-uniphier-usb3.c171
-rw-r--r--drivers/reset/reset-uniphier.c9
-rw-r--r--drivers/rtc/Kconfig21
-rw-r--r--drivers/rtc/class.c5
-rw-r--r--drivers/rtc/interface.c97
-rw-r--r--drivers/rtc/rtc-armada38x.c23
-rw-r--r--drivers/rtc/rtc-bq4802.c4
-rw-r--r--drivers/rtc/rtc-core.h14
-rw-r--r--drivers/rtc/rtc-dev.c8
-rw-r--r--drivers/rtc/rtc-ds1307.c18
-rw-r--r--drivers/rtc/rtc-ds1685.c590
-rw-r--r--drivers/rtc/rtc-isl1208.c192
-rw-r--r--drivers/rtc/rtc-m48t59.c4
-rw-r--r--drivers/rtc/rtc-max77686.c20
-rw-r--r--drivers/rtc/rtc-max8997.c20
-rw-r--r--drivers/rtc/rtc-max8998.c20
-rw-r--r--drivers/rtc/rtc-omap.c23
-rw-r--r--drivers/rtc/rtc-pcf2127.c68
-rw-r--r--drivers/rtc/rtc-pcf85063.c21
-rw-r--r--drivers/rtc/rtc-s5m.c22
-rw-r--r--drivers/rtc/rtc-sa1100.c1
-rw-r--r--drivers/rtc/rtc-sh.c90
-rw-r--r--drivers/rtc/rtc-snvs.c105
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c20
-rw-r--r--drivers/rtc/rtc-sysfs.c43
-rw-r--r--drivers/rtc/rtc-test.c2
-rw-r--r--drivers/soc/bcm/brcmstb/pm/pm-arm.c16
-rw-r--r--drivers/soc/fsl/Kconfig15
-rw-r--r--drivers/soc/fsl/Makefile1
-rw-r--r--drivers/soc/fsl/dpio/Makefile (renamed from drivers/staging/fsl-mc/bus/dpio/Makefile)0
-rw-r--r--drivers/soc/fsl/dpio/dpio-cmd.h (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h)0
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-driver.c)2
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-service.c)2
-rw-r--r--drivers/soc/fsl/dpio/dpio.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio.c)0
-rw-r--r--drivers/soc/fsl/dpio/dpio.h (renamed from drivers/staging/fsl-mc/bus/dpio/dpio.h)0
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.c (renamed from drivers/staging/fsl-mc/bus/dpio/qbman-portal.c)2
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.h (renamed from drivers/staging/fsl-mc/bus/dpio/qbman-portal.h)2
-rw-r--r--drivers/soc/fsl/qbman/Kconfig2
-rw-r--r--drivers/soc/fsl/qe/Kconfig2
-rw-r--r--drivers/soc/fsl/qe/gpio.c28
-rw-r--r--drivers/soc/imx/gpc.c18
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c81
-rw-r--r--drivers/soc/renesas/Makefile3
-rw-r--r--drivers/soc/renesas/r9a06g032-smp.c96
-rw-r--r--drivers/soc/renesas/rcar-sysc.c64
-rw-r--r--drivers/soc/sunxi/sunxi_sram.c87
-rw-r--r--drivers/soc/ti/Kconfig14
-rw-r--r--drivers/soc/ti/pm33xx.c16
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c76
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c4
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h22
-rw-r--r--drivers/staging/fsl-mc/Kconfig2
-rw-r--r--drivers/staging/fsl-mc/Makefile3
-rw-r--r--drivers/staging/fsl-mc/bus/Kconfig16
-rw-r--r--drivers/staging/fsl-mc/bus/Makefile9
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt135
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-fd.h426
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-global.h177
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-io.h115
-rw-r--r--drivers/tee/optee/Kconfig8
-rw-r--r--drivers/tee/optee/core.c2
-rw-r--r--drivers/tee/optee/rpc.c2
-rw-r--r--drivers/tty/sysrq.c2
-rw-r--r--drivers/tty/tty_io.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c7
-rw-r--r--drivers/usb/host/ohci-exynos.c6
-rw-r--r--drivers/video/backlight/adp8860_bl.c1
-rw-r--r--drivers/video/backlight/pwm_bl.c232
-rw-r--r--drivers/w1/slaves/Kconfig12
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2760.c175
-rw-r--r--drivers/w1/slaves/w1_ds2760.h59
-rw-r--r--drivers/w1/w1.c3
-rw-r--r--drivers/watchdog/kempld_wdt.c5
-rw-r--r--drivers/xen/gntdev.c44
359 files changed, 22258 insertions, 6212 deletions
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index c5367bf5487f..0f28a38a43ea 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -164,6 +164,7 @@ struct acpi_namespace_node {
#define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */
#define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */
#define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */
+#define ANOBJ_NODE_EARLY_INIT 0x80 /* acpi_exec only: Node was create via init file (-fi) */
#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */
#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 3825df923480..bbb3b4d1e796 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -25,14 +25,15 @@
/* Flags for acpi_ns_lookup, acpi_ns_search_and_enter */
#define ACPI_NS_NO_UPSEARCH 0
-#define ACPI_NS_SEARCH_PARENT 0x01
-#define ACPI_NS_DONT_OPEN_SCOPE 0x02
-#define ACPI_NS_NO_PEER_SEARCH 0x04
-#define ACPI_NS_ERROR_IF_FOUND 0x08
-#define ACPI_NS_PREFIX_IS_SCOPE 0x10
-#define ACPI_NS_EXTERNAL 0x20
-#define ACPI_NS_TEMPORARY 0x40
-#define ACPI_NS_OVERRIDE_IF_FOUND 0x80
+#define ACPI_NS_SEARCH_PARENT 0x0001
+#define ACPI_NS_DONT_OPEN_SCOPE 0x0002
+#define ACPI_NS_NO_PEER_SEARCH 0x0004
+#define ACPI_NS_ERROR_IF_FOUND 0x0008
+#define ACPI_NS_PREFIX_IS_SCOPE 0x0010
+#define ACPI_NS_EXTERNAL 0x0020
+#define ACPI_NS_TEMPORARY 0x0040
+#define ACPI_NS_OVERRIDE_IF_FOUND 0x0080
+#define ACPI_NS_EARLY_INIT 0x0100
/* Flags for acpi_ns_walk_namespace */
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 2733cd4e418c..3374d41582b5 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -180,6 +180,8 @@ char acpi_ut_remove_leading_zeros(char **string);
u8 acpi_ut_detect_hex_prefix(char **string);
+void acpi_ut_remove_hex_prefix(char **string);
+
u8 acpi_ut_detect_octal_prefix(char **string);
/*
diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c
index 556ff59bbbfc..3e5f95390f0d 100644
--- a/drivers/acpi/acpica/dbinput.c
+++ b/drivers/acpi/acpica/dbinput.c
@@ -763,7 +763,12 @@ acpi_db_command_dispatch(char *input_buffer,
case CMD_DISASSEMBLE:
case CMD_DISASM:
+#ifdef ACPI_DISASSEMBLER
(void)acpi_db_disassemble_method(acpi_gbl_db_args[1]);
+#else
+ acpi_os_printf
+ ("The AML Disassembler is not configured/present\n");
+#endif
break;
case CMD_DUMP:
@@ -872,7 +877,12 @@ acpi_db_command_dispatch(char *input_buffer,
case CMD_LIST:
+#ifdef ACPI_DISASSEMBLER
acpi_db_disassemble_aml(acpi_gbl_db_args[1], op);
+#else
+ acpi_os_printf
+ ("The AML Disassembler is not configured/present\n");
+#endif
break;
case CMD_LOCKS:
diff --git a/drivers/acpi/acpica/dbmethod.c b/drivers/acpi/acpica/dbmethod.c
index 9fcecf104ba0..d8b7a0fe92ec 100644
--- a/drivers/acpi/acpica/dbmethod.c
+++ b/drivers/acpi/acpica/dbmethod.c
@@ -216,6 +216,7 @@ cleanup:
acpi_ut_remove_reference(obj_desc);
}
+#ifdef ACPI_DISASSEMBLER
/*******************************************************************************
*
* FUNCTION: acpi_db_disassemble_aml
@@ -242,9 +243,8 @@ void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op)
if (statements) {
num_statements = strtoul(statements, NULL, 0);
}
-#ifdef ACPI_DISASSEMBLER
+
acpi_dm_disassemble(NULL, op, num_statements);
-#endif
}
/*******************************************************************************
@@ -317,8 +317,6 @@ acpi_status acpi_db_disassemble_method(char *name)
walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE;
status = acpi_ps_parse_aml(walk_state);
-
-#ifdef ACPI_DISASSEMBLER
(void)acpi_dm_parse_deferred_ops(op);
/* Now we can disassemble the method */
@@ -326,7 +324,6 @@ acpi_status acpi_db_disassemble_method(char *name)
acpi_gbl_dm_opt_verbose = FALSE;
acpi_dm_disassemble(NULL, op, 0);
acpi_gbl_dm_opt_verbose = TRUE;
-#endif
acpi_ps_delete_parse_tree(op);
@@ -337,6 +334,7 @@ acpi_status acpi_db_disassemble_method(char *name)
acpi_ut_release_owner_id(&obj_desc->method.owner_id);
return (AE_OK);
}
+#endif
/*******************************************************************************
*
diff --git a/drivers/acpi/acpica/dbxface.c b/drivers/acpi/acpica/dbxface.c
index 4647aa8efecb..f2526726daf6 100644
--- a/drivers/acpi/acpica/dbxface.c
+++ b/drivers/acpi/acpica/dbxface.c
@@ -10,6 +10,7 @@
#include "amlcode.h"
#include "acdebug.h"
#include "acinterp.h"
+#include "acparser.h"
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbxface")
@@ -262,10 +263,17 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
}
}
- /* Now we can display it */
+ /* Now we can disassemble and display it */
#ifdef ACPI_DISASSEMBLER
acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
+#else
+ /*
+ * The AML Disassembler is not configured - at least we can
+ * display the opcode value and name
+ */
+ acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode,
+ acpi_ps_get_opcode_name(op->common.aml_opcode));
#endif
if ((op->common.aml_opcode == AML_IF_OP) ||
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 7c937595dfcb..30fe89545d6a 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -15,6 +15,10 @@
#include "acnamesp.h"
#include "acparser.h"
+#ifdef ACPI_EXEC_APP
+#include "aecommon.h"
+#endif
+
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsfield")
@@ -259,6 +263,13 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
u64 position;
union acpi_parse_object *child;
+#ifdef ACPI_EXEC_APP
+ u64 value = 0;
+ union acpi_operand_object *result_desc;
+ union acpi_operand_object *obj_desc;
+ char *name_path;
+#endif
+
ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
/* First field starts at bit zero */
@@ -391,6 +402,25 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+#ifdef ACPI_EXEC_APP
+ name_path =
+ acpi_ns_get_external_pathname(info->
+ field_node);
+ obj_desc =
+ acpi_ut_create_integer_object
+ (value);
+ if (ACPI_SUCCESS
+ (ae_lookup_init_file_entry
+ (name_path, &value))) {
+ acpi_ex_write_data_to_field
+ (obj_desc,
+ acpi_ns_get_attached_object
+ (info->field_node),
+ &result_desc);
+ }
+ acpi_ut_remove_reference(obj_desc);
+ ACPI_FREE(name_path);
+#endif
}
}
@@ -573,7 +603,9 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
-
+#ifdef ACPI_EXEC_APP
+ flags |= ACPI_NS_OVERRIDE_IF_FOUND;
+#endif
/*
* Walk the list of entries in the field_list
* Note: field_list can be of zero length. In this case, Arg will be NULL.
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
index 3de794bcf8fa..69603ba52a3a 100644
--- a/drivers/acpi/acpica/hwregs.c
+++ b/drivers/acpi/acpica/hwregs.c
@@ -528,13 +528,18 @@ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
status =
acpi_hw_read(&value64, &acpi_gbl_FADT.xpm2_control_block);
- value = (u32)value64;
+ if (ACPI_SUCCESS(status)) {
+ value = (u32)value64;
+ }
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_hw_read(&value64, &acpi_gbl_FADT.xpm_timer_block);
- value = (u32)value64;
+ if (ACPI_SUCCESS(status)) {
+ value = (u32)value64;
+ }
+
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index fe9d46d81750..d8b8fc2ff563 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -56,14 +56,9 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- /*
- * If the target sleep state is S5, clear all GPEs and fixed events too
- */
- if (sleep_state == ACPI_STATE_S5) {
- status = acpi_hw_clear_acpi_status();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ status = acpi_hw_clear_acpi_status();
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 83a593e2155d..e3f10afde5ff 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -558,6 +558,14 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
(char *)&current_node->name,
current_node));
}
+#ifdef ACPI_EXEC_APP
+ if ((status == AE_ALREADY_EXISTS) &&
+ (this_node->flags & ANOBJ_NODE_EARLY_INIT)) {
+ this_node->flags &= ~ANOBJ_NODE_EARLY_INIT;
+ status = AE_OK;
+ }
+#endif
+
#ifdef ACPI_ASL_COMPILER
/*
* If this ACPI name already exists within the namespace as an
@@ -676,6 +684,11 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
}
}
}
+#ifdef ACPI_EXEC_APP
+ if (flags & ACPI_NS_EARLY_INIT) {
+ this_node->flags |= ANOBJ_NODE_EARLY_INIT;
+ }
+#endif
*return_node = this_node;
return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 44f35ab3347d..34fc2f7476ed 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -22,6 +22,7 @@
#include "acdispat.h"
#include "amlcode.h"
#include "acconvert.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psloop")
@@ -527,12 +528,18 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- if (walk_state->opcode == AML_SCOPE_OP) {
+ if (acpi_ns_opens_scope
+ (acpi_ps_get_opcode_info
+ (walk_state->opcode)->object_type)) {
/*
- * If the scope op fails to parse, skip the body of the
- * scope op because the parse failure indicates that the
- * device may not exist.
+ * If the scope/device op fails to parse, skip the body of
+ * the scope op because the parse failure indicates that
+ * the device may not exist.
*/
+ ACPI_ERROR((AE_INFO,
+ "Skip parsing opcode %s",
+ acpi_ps_get_opcode_name
+ (walk_state->opcode)));
walk_state->parser_state.aml =
walk_state->aml + 1;
walk_state->parser_state.aml =
@@ -540,8 +547,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
(&walk_state->parser_state);
walk_state->aml =
walk_state->parser_state.aml;
- ACPI_ERROR((AE_INFO,
- "Skipping Scope block"));
}
continue;
@@ -709,20 +714,20 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
} else
if ((walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)
- && status != AE_CTRL_TRANSFER
- && ACPI_FAILURE(status)) {
+ && (ACPI_AML_EXCEPTION(status)
+ || status == AE_ALREADY_EXISTS
+ || status == AE_NOT_FOUND)) {
/*
- * ACPI_PARSE_MODULE_LEVEL flag means that we are currently
- * loading a table by executing it as a control method.
- * However, if we encounter an error while loading the table,
- * we need to keep trying to load the table rather than
- * aborting the table load (setting the status to AE_OK
- * continues the table load). If we get a failure at this
- * point, it means that the dispatcher got an error while
- * processing Op (most likely an AML operand error) or a
- * control method was called from module level and the
- * dispatcher returned AE_CTRL_TRANSFER. In the latter case,
- * leave the status alone, there's nothing wrong with it.
+ * ACPI_PARSE_MODULE_LEVEL flag means that we
+ * are currently loading a table by executing
+ * it as a control method. However, if we
+ * encounter an error while loading the table,
+ * we need to keep trying to load the table
+ * rather than aborting the table load (setting
+ * the status to AE_OK continues the table
+ * load). If we get a failure at this point, it
+ * means that the dispatcher got an error while
+ * trying to execute the Op.
*/
status = AE_OK;
}
diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c
index 51891f9fb057..862149c8a208 100644
--- a/drivers/acpi/acpica/tbdata.c
+++ b/drivers/acpi/acpica/tbdata.c
@@ -516,9 +516,9 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
acpi_tb_check_duplication(table_desc, table_index);
if (ACPI_FAILURE(status)) {
if (status != AE_CTRL_TERMINATE) {
- ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
+ ACPI_EXCEPTION((AE_INFO, status,
"%4.4s 0x%8.8X%8.8X"
- " Table is duplicated",
+ " Table is already loaded",
acpi_ut_valid_nameseg
(table_desc->signature.
ascii) ? table_desc->
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index 118f3ff1fbb5..8cc4392c61f3 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -355,6 +355,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
u16 original_count;
u16 new_count = 0;
acpi_cpu_flags lock_flags;
+ char *message;
ACPI_FUNCTION_NAME(ut_update_ref_count);
@@ -391,6 +392,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
object, object->common.type,
acpi_ut_get_object_type_name(object),
new_count));
+ message = "Incremement";
break;
case REF_DECREMENT:
@@ -420,6 +422,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
if (new_count == 0) {
acpi_ut_delete_internal_obj(object);
}
+ message = "Decrement";
break;
default:
@@ -436,8 +439,8 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
*/
if (new_count > ACPI_MAX_REFERENCE_COUNT) {
ACPI_WARNING((AE_INFO,
- "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
- new_count, object, object->common.type));
+ "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s",
+ new_count, object, object->common.type, message));
}
}
diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c
index 954f8e3e35cd..05ff20049b87 100644
--- a/drivers/acpi/acpica/utstrsuppt.c
+++ b/drivers/acpi/acpica/utstrsuppt.c
@@ -231,14 +231,34 @@ char acpi_ut_remove_whitespace(char **string)
u8 acpi_ut_detect_hex_prefix(char **string)
{
+ char *initial_position = *string;
+ acpi_ut_remove_hex_prefix(string);
+ if (*string != initial_position) {
+ return (TRUE); /* String is past leading 0x */
+ }
+
+ return (FALSE); /* Not a hex string */
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_remove_hex_prefix
+ *
+ * PARAMETERS: string - Pointer to input ASCII string
+ *
+ * RETURN: none
+ *
+ * DESCRIPTION: Remove a hex "0x" prefix
+ *
+ ******************************************************************************/
+
+void acpi_ut_remove_hex_prefix(char **string)
+{
if ((**string == ACPI_ASCII_ZERO) &&
(tolower((int)*(*string + 1)) == 'x')) {
*string += 2; /* Go past the leading 0x */
- return (TRUE);
}
-
- return (FALSE); /* Not a hex string */
}
/*******************************************************************************
diff --git a/drivers/acpi/acpica/utstrtoul64.c b/drivers/acpi/acpica/utstrtoul64.c
index 8fadad242db6..5fde619a8bbd 100644
--- a/drivers/acpi/acpica/utstrtoul64.c
+++ b/drivers/acpi/acpica/utstrtoul64.c
@@ -218,7 +218,7 @@ u64 acpi_ut_implicit_strtoul64(char *string)
* implicit conversions, and the "0x" prefix is "not allowed".
* However, allow a "0x" prefix as an ACPI extension.
*/
- acpi_ut_detect_hex_prefix(&string);
+ acpi_ut_remove_hex_prefix(&string);
if (!acpi_ut_remove_leading_zeros(&string)) {
return_VALUE(0);
diff --git a/drivers/acpi/pmic/intel_pmic_crc.c b/drivers/acpi/pmic/intel_pmic_crc.c
index 7ffa74048107..22c9e374c923 100644
--- a/drivers/acpi/pmic/intel_pmic_crc.c
+++ b/drivers/acpi/pmic/intel_pmic_crc.c
@@ -25,16 +25,121 @@
#define PMIC_A0LOCK_REG 0xc5
static struct pmic_table power_table[] = {
+/* {
+ .address = 0x00,
+ .reg = ??,
+ .bit = ??,
+ }, ** VSYS */
+ {
+ .address = 0x04,
+ .reg = 0x63,
+ .bit = 0x00,
+ }, /* SYSX -> VSYS_SX */
+ {
+ .address = 0x08,
+ .reg = 0x62,
+ .bit = 0x00,
+ }, /* SYSU -> VSYS_U */
+ {
+ .address = 0x0c,
+ .reg = 0x64,
+ .bit = 0x00,
+ }, /* SYSS -> VSYS_S */
+ {
+ .address = 0x10,
+ .reg = 0x6a,
+ .bit = 0x00,
+ }, /* V50S -> V5P0S */
+ {
+ .address = 0x14,
+ .reg = 0x6b,
+ .bit = 0x00,
+ }, /* HOST -> VHOST, USB2/3 host */
+ {
+ .address = 0x18,
+ .reg = 0x6c,
+ .bit = 0x00,
+ }, /* VBUS -> VBUS, USB2/3 OTG */
+ {
+ .address = 0x1c,
+ .reg = 0x6d,
+ .bit = 0x00,
+ }, /* HDMI -> VHDMI */
+/* {
+ .address = 0x20,
+ .reg = ??,
+ .bit = ??,
+ }, ** S285 */
{
.address = 0x24,
.reg = 0x66,
.bit = 0x00,
- },
+ }, /* X285 -> V2P85SX, camera */
+/* {
+ .address = 0x28,
+ .reg = ??,
+ .bit = ??,
+ }, ** V33A */
+ {
+ .address = 0x2c,
+ .reg = 0x69,
+ .bit = 0x00,
+ }, /* V33S -> V3P3S, display/ssd/audio */
+ {
+ .address = 0x30,
+ .reg = 0x68,
+ .bit = 0x00,
+ }, /* V33U -> V3P3U, SDIO wifi&bt */
+/* {
+ .address = 0x34 .. 0x40,
+ .reg = ??,
+ .bit = ??,
+ }, ** V33I, V18A, REFQ, V12A */
+ {
+ .address = 0x44,
+ .reg = 0x5c,
+ .bit = 0x00,
+ }, /* V18S -> V1P8S, SOC/USB PHY/SIM */
{
.address = 0x48,
.reg = 0x5d,
.bit = 0x00,
- },
+ }, /* V18X -> V1P8SX, eMMC/camara/audio */
+ {
+ .address = 0x4c,
+ .reg = 0x5b,
+ .bit = 0x00,
+ }, /* V18U -> V1P8U, LPDDR */
+ {
+ .address = 0x50,
+ .reg = 0x61,
+ .bit = 0x00,
+ }, /* V12X -> V1P2SX, SOC SFR */
+ {
+ .address = 0x54,
+ .reg = 0x60,
+ .bit = 0x00,
+ }, /* V12S -> V1P2S, MIPI */
+/* {
+ .address = 0x58,
+ .reg = ??,
+ .bit = ??,
+ }, ** V10A */
+ {
+ .address = 0x5c,
+ .reg = 0x56,
+ .bit = 0x00,
+ }, /* V10S -> V1P0S, SOC GFX */
+ {
+ .address = 0x60,
+ .reg = 0x57,
+ .bit = 0x00,
+ }, /* V10X -> V1P0SX, SOC display/DDR IO/PCIe */
+ {
+ .address = 0x64,
+ .reg = 0x59,
+ .bit = 0x00,
+ }, /* V105 -> V1P05S, L2 SRAM */
};
static struct pmic_table thermal_table[] = {
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 99f9a895a459..564570ea3e27 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -75,7 +75,6 @@ static const struct of_device_id ahci_of_match[] = {
{ .compatible = "generic-ahci", },
/* Keep the following compatibles for device tree compatibility */
{ .compatible = "snps,spear-ahci", },
- { .compatible = "snps,exynos5440-ahci", },
{ .compatible = "ibm,476gtr-ahci", },
{ .compatible = "snps,dwc-ahci", },
{ .compatible = "hisilicon,hisi-ahci", },
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index f99e5c883368..581312ac375f 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -2428,16 +2428,20 @@ static bool DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
{
DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
- unsigned char *ReadCacheStatus[] = { "Read Cache Disabled",
- "Read Cache Enabled",
- "Read Ahead Enabled",
- "Intelligent Read Ahead Enabled",
- "-", "-", "-", "-" };
- unsigned char *WriteCacheStatus[] = { "Write Cache Disabled",
- "Logical Device Read Only",
- "Write Cache Enabled",
- "Intelligent Write Cache Enabled",
- "-", "-", "-", "-" };
+ static const unsigned char *ReadCacheStatus[] = {
+ "Read Cache Disabled",
+ "Read Cache Enabled",
+ "Read Ahead Enabled",
+ "Intelligent Read Ahead Enabled",
+ "-", "-", "-", "-"
+ };
+ static const unsigned char *WriteCacheStatus[] = {
+ "Write Cache Disabled",
+ "Logical Device Read Only",
+ "Write Cache Enabled",
+ "Intelligent Write Cache Enabled",
+ "-", "-", "-", "-"
+ };
unsigned char *GeometryTranslation;
if (LogicalDeviceInfo == NULL) continue;
switch (LogicalDeviceInfo->DriveGeometry)
@@ -4339,14 +4343,16 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
static void DAC960_V2_ReadWriteError(DAC960_Command_T *Command)
{
DAC960_Controller_T *Controller = Command->Controller;
- unsigned char *SenseErrors[] = { "NO SENSE", "RECOVERED ERROR",
- "NOT READY", "MEDIUM ERROR",
- "HARDWARE ERROR", "ILLEGAL REQUEST",
- "UNIT ATTENTION", "DATA PROTECT",
- "BLANK CHECK", "VENDOR-SPECIFIC",
- "COPY ABORTED", "ABORTED COMMAND",
- "EQUAL", "VOLUME OVERFLOW",
- "MISCOMPARE", "RESERVED" };
+ static const unsigned char *SenseErrors[] = {
+ "NO SENSE", "RECOVERED ERROR",
+ "NOT READY", "MEDIUM ERROR",
+ "HARDWARE ERROR", "ILLEGAL REQUEST",
+ "UNIT ATTENTION", "DATA PROTECT",
+ "BLANK CHECK", "VENDOR-SPECIFIC",
+ "COPY ABORTED", "ABORTED COMMAND",
+ "EQUAL", "VOLUME OVERFLOW",
+ "MISCOMPARE", "RESERVED"
+ };
unsigned char *CommandName = "UNKNOWN";
switch (Command->CommandType)
{
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index e285413d4a75..6f1d25c1eb64 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2740,6 +2740,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
pd->write_congestion_on = write_congestion_on;
pd->write_congestion_off = write_congestion_off;
+ ret = -ENOMEM;
disk = alloc_disk(1);
if (!disk)
goto out_mem;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d81c653b9bf6..7915f3b03736 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -181,6 +181,7 @@ struct rbd_image_header {
struct rbd_spec {
u64 pool_id;
const char *pool_name;
+ const char *pool_ns; /* NULL if default, never "" */
const char *image_id;
const char *image_name;
@@ -735,6 +736,7 @@ enum {
Opt_lock_timeout,
Opt_last_int,
/* int args above */
+ Opt_pool_ns,
Opt_last_string,
/* string args above */
Opt_read_only,
@@ -749,6 +751,7 @@ static match_table_t rbd_opts_tokens = {
{Opt_queue_depth, "queue_depth=%d"},
{Opt_lock_timeout, "lock_timeout=%d"},
/* int args above */
+ {Opt_pool_ns, "_pool_ns=%s"},
/* string args above */
{Opt_read_only, "read_only"},
{Opt_read_only, "ro"}, /* Alternate spelling */
@@ -776,9 +779,14 @@ struct rbd_options {
#define RBD_EXCLUSIVE_DEFAULT false
#define RBD_TRIM_DEFAULT true
+struct parse_rbd_opts_ctx {
+ struct rbd_spec *spec;
+ struct rbd_options *opts;
+};
+
static int parse_rbd_opts_token(char *c, void *private)
{
- struct rbd_options *rbd_opts = private;
+ struct parse_rbd_opts_ctx *pctx = private;
substring_t argstr[MAX_OPT_ARGS];
int token, intval, ret;
@@ -786,7 +794,7 @@ static int parse_rbd_opts_token(char *c, void *private)
if (token < Opt_last_int) {
ret = match_int(&argstr[0], &intval);
if (ret < 0) {
- pr_err("bad mount option arg (not int) at '%s'\n", c);
+ pr_err("bad option arg (not int) at '%s'\n", c);
return ret;
}
dout("got int token %d val %d\n", token, intval);
@@ -802,7 +810,7 @@ static int parse_rbd_opts_token(char *c, void *private)
pr_err("queue_depth out of range\n");
return -EINVAL;
}
- rbd_opts->queue_depth = intval;
+ pctx->opts->queue_depth = intval;
break;
case Opt_lock_timeout:
/* 0 is "wait forever" (i.e. infinite timeout) */
@@ -810,22 +818,28 @@ static int parse_rbd_opts_token(char *c, void *private)
pr_err("lock_timeout out of range\n");
return -EINVAL;
}
- rbd_opts->lock_timeout = msecs_to_jiffies(intval * 1000);
+ pctx->opts->lock_timeout = msecs_to_jiffies(intval * 1000);
+ break;
+ case Opt_pool_ns:
+ kfree(pctx->spec->pool_ns);
+ pctx->spec->pool_ns = match_strdup(argstr);
+ if (!pctx->spec->pool_ns)
+ return -ENOMEM;
break;
case Opt_read_only:
- rbd_opts->read_only = true;
+ pctx->opts->read_only = true;
break;
case Opt_read_write:
- rbd_opts->read_only = false;
+ pctx->opts->read_only = false;
break;
case Opt_lock_on_read:
- rbd_opts->lock_on_read = true;
+ pctx->opts->lock_on_read = true;
break;
case Opt_exclusive:
- rbd_opts->exclusive = true;
+ pctx->opts->exclusive = true;
break;
case Opt_notrim:
- rbd_opts->trim = false;
+ pctx->opts->trim = false;
break;
default:
/* libceph prints "bad option" msg */
@@ -1452,7 +1466,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
struct ceph_osd_request *osd_req = obj_request->osd_req;
osd_req->r_flags = CEPH_OSD_FLAG_WRITE;
- ktime_get_real_ts(&osd_req->r_mtime);
+ ktime_get_real_ts64(&osd_req->r_mtime);
osd_req->r_data_offset = obj_request->ex.oe_off;
}
@@ -1475,7 +1489,13 @@ rbd_osd_req_create(struct rbd_obj_request *obj_req, unsigned int num_ops)
req->r_callback = rbd_osd_req_callback;
req->r_priv = obj_req;
+ /*
+ * Data objects may be stored in a separate pool, but always in
+ * the same namespace in that pool as the header in its pool.
+ */
+ ceph_oloc_copy(&req->r_base_oloc, &rbd_dev->header_oloc);
req->r_base_oloc.pool = rbd_dev->layout.pool_id;
+
if (ceph_oid_aprintf(&req->r_base_oid, GFP_NOIO, name_format,
rbd_dev->header.object_prefix, obj_req->ex.oe_objno))
goto err_req;
@@ -4119,6 +4139,14 @@ static ssize_t rbd_pool_id_show(struct device *dev,
(unsigned long long) rbd_dev->spec->pool_id);
}
+static ssize_t rbd_pool_ns_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+
+ return sprintf(buf, "%s\n", rbd_dev->spec->pool_ns ?: "");
+}
+
static ssize_t rbd_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -4217,6 +4245,7 @@ static DEVICE_ATTR(cluster_fsid, 0444, rbd_cluster_fsid_show, NULL);
static DEVICE_ATTR(config_info, 0400, rbd_config_info_show, NULL);
static DEVICE_ATTR(pool, 0444, rbd_pool_show, NULL);
static DEVICE_ATTR(pool_id, 0444, rbd_pool_id_show, NULL);
+static DEVICE_ATTR(pool_ns, 0444, rbd_pool_ns_show, NULL);
static DEVICE_ATTR(name, 0444, rbd_name_show, NULL);
static DEVICE_ATTR(image_id, 0444, rbd_image_id_show, NULL);
static DEVICE_ATTR(refresh, 0200, NULL, rbd_image_refresh);
@@ -4235,6 +4264,7 @@ static struct attribute *rbd_attrs[] = {
&dev_attr_config_info.attr,
&dev_attr_pool.attr,
&dev_attr_pool_id.attr,
+ &dev_attr_pool_ns.attr,
&dev_attr_name.attr,
&dev_attr_image_id.attr,
&dev_attr_current_snap.attr,
@@ -4295,6 +4325,7 @@ static void rbd_spec_free(struct kref *kref)
struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref);
kfree(spec->pool_name);
+ kfree(spec->pool_ns);
kfree(spec->image_id);
kfree(spec->image_name);
kfree(spec->snap_name);
@@ -4353,6 +4384,12 @@ static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc,
rbd_dev->header.data_pool_id = CEPH_NOPOOL;
ceph_oid_init(&rbd_dev->header_oid);
rbd_dev->header_oloc.pool = spec->pool_id;
+ if (spec->pool_ns) {
+ WARN_ON(!*spec->pool_ns);
+ rbd_dev->header_oloc.pool_ns =
+ ceph_find_or_create_string(spec->pool_ns,
+ strlen(spec->pool_ns));
+ }
mutex_init(&rbd_dev->watch_mutex);
rbd_dev->watch_state = RBD_WATCH_STATE_UNREGISTERED;
@@ -4633,6 +4670,17 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
parent_spec->pool_id = pool_id;
parent_spec->image_id = image_id;
parent_spec->snap_id = snap_id;
+
+ /* TODO: support cloning across namespaces */
+ if (rbd_dev->spec->pool_ns) {
+ parent_spec->pool_ns = kstrdup(rbd_dev->spec->pool_ns,
+ GFP_KERNEL);
+ if (!parent_spec->pool_ns) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
+ }
+
rbd_dev->parent_spec = parent_spec;
parent_spec = NULL; /* rbd_dev now owns this */
} else {
@@ -5146,8 +5194,7 @@ static int rbd_add_parse_args(const char *buf,
const char *mon_addrs;
char *snap_name;
size_t mon_addrs_size;
- struct rbd_spec *spec = NULL;
- struct rbd_options *rbd_opts = NULL;
+ struct parse_rbd_opts_ctx pctx = { 0 };
struct ceph_options *copts;
int ret;
@@ -5171,22 +5218,22 @@ static int rbd_add_parse_args(const char *buf,
goto out_err;
}
- spec = rbd_spec_alloc();
- if (!spec)
+ pctx.spec = rbd_spec_alloc();
+ if (!pctx.spec)
goto out_mem;
- spec->pool_name = dup_token(&buf, NULL);
- if (!spec->pool_name)
+ pctx.spec->pool_name = dup_token(&buf, NULL);
+ if (!pctx.spec->pool_name)
goto out_mem;
- if (!*spec->pool_name) {
+ if (!*pctx.spec->pool_name) {
rbd_warn(NULL, "no pool name provided");
goto out_err;
}
- spec->image_name = dup_token(&buf, NULL);
- if (!spec->image_name)
+ pctx.spec->image_name = dup_token(&buf, NULL);
+ if (!pctx.spec->image_name)
goto out_mem;
- if (!*spec->image_name) {
+ if (!*pctx.spec->image_name) {
rbd_warn(NULL, "no image name provided");
goto out_err;
}
@@ -5207,24 +5254,24 @@ static int rbd_add_parse_args(const char *buf,
if (!snap_name)
goto out_mem;
*(snap_name + len) = '\0';
- spec->snap_name = snap_name;
+ pctx.spec->snap_name = snap_name;
/* Initialize all rbd options to the defaults */
- rbd_opts = kzalloc(sizeof (*rbd_opts), GFP_KERNEL);
- if (!rbd_opts)
+ pctx.opts = kzalloc(sizeof(*pctx.opts), GFP_KERNEL);
+ if (!pctx.opts)
goto out_mem;
- rbd_opts->read_only = RBD_READ_ONLY_DEFAULT;
- rbd_opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT;
- rbd_opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT;
- rbd_opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT;
- rbd_opts->exclusive = RBD_EXCLUSIVE_DEFAULT;
- rbd_opts->trim = RBD_TRIM_DEFAULT;
+ pctx.opts->read_only = RBD_READ_ONLY_DEFAULT;
+ pctx.opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT;
+ pctx.opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT;
+ pctx.opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT;
+ pctx.opts->exclusive = RBD_EXCLUSIVE_DEFAULT;
+ pctx.opts->trim = RBD_TRIM_DEFAULT;
copts = ceph_parse_options(options, mon_addrs,
- mon_addrs + mon_addrs_size - 1,
- parse_rbd_opts_token, rbd_opts);
+ mon_addrs + mon_addrs_size - 1,
+ parse_rbd_opts_token, &pctx);
if (IS_ERR(copts)) {
ret = PTR_ERR(copts);
goto out_err;
@@ -5232,15 +5279,15 @@ static int rbd_add_parse_args(const char *buf,
kfree(options);
*ceph_opts = copts;
- *opts = rbd_opts;
- *rbd_spec = spec;
+ *opts = pctx.opts;
+ *rbd_spec = pctx.spec;
return 0;
out_mem:
ret = -ENOMEM;
out_err:
- kfree(rbd_opts);
- rbd_spec_put(spec);
+ kfree(pctx.opts);
+ rbd_spec_put(pctx.spec);
kfree(options);
return ret;
@@ -5586,8 +5633,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
ret = rbd_register_watch(rbd_dev);
if (ret) {
if (ret == -ENOENT)
- pr_info("image %s/%s does not exist\n",
+ pr_info("image %s/%s%s%s does not exist\n",
rbd_dev->spec->pool_name,
+ rbd_dev->spec->pool_ns ?: "",
+ rbd_dev->spec->pool_ns ? "/" : "",
rbd_dev->spec->image_name);
goto err_out_format;
}
@@ -5609,8 +5658,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
ret = rbd_spec_fill_names(rbd_dev);
if (ret) {
if (ret == -ENOENT)
- pr_info("snap %s/%s@%s does not exist\n",
+ pr_info("snap %s/%s%s%s@%s does not exist\n",
rbd_dev->spec->pool_name,
+ rbd_dev->spec->pool_ns ?: "",
+ rbd_dev->spec->pool_ns ? "/" : "",
rbd_dev->spec->image_name,
rbd_dev->spec->snap_name);
goto err_out_probe;
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index c7acf74253a1..a1d6b5597c17 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -337,6 +337,7 @@ static ssize_t backing_dev_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
char *file_name;
+ size_t sz;
struct file *backing_dev = NULL;
struct inode *inode;
struct address_space *mapping;
@@ -357,7 +358,11 @@ static ssize_t backing_dev_store(struct device *dev,
goto out;
}
- strlcpy(file_name, buf, len);
+ strlcpy(file_name, buf, PATH_MAX);
+ /* ignore trailing newline */
+ sz = strlen(file_name);
+ if (sz > 0 && file_name[sz - 1] == '\n')
+ file_name[sz - 1] = 0x00;
backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0);
if (IS_ERR(backing_dev)) {
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index d1c0b60e9326..1851112ccc29 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -103,6 +103,16 @@ config SIMPLE_PM_BUS
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
+config SUN50I_DE2_BUS
+ bool "Allwinner A64 DE2 Bus Driver"
+ default ARM64
+ depends on ARCH_SUNXI
+ select SUNXI_SRAM
+ help
+ Say y here to enable support for Allwinner A64 DE2 bus driver. It's
+ mostly transparent, but a SRAM region needs to be claimed in the SRAM
+ controller to make the all blocks in the DE2 part accessible.
+
config SUNXI_RSB
tristate "Allwinner sunXi Reduced Serial Bus Driver"
default MACH_SUN8I || MACH_SUN9I || ARM64
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index b8f036cca7ff..ca300b1914ce 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
+obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c
new file mode 100644
index 000000000000..672518741f86
--- /dev/null
+++ b/drivers/bus/sun50i-de2.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A64 Display Engine 2.0 Bus Driver
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+
+static int sun50i_de2_bus_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ ret = sunxi_sram_claim(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
+ return ret;
+ }
+
+ of_platform_populate(np, NULL, NULL, &pdev->dev);
+
+ return 0;
+}
+
+static int sun50i_de2_bus_remove(struct platform_device *pdev)
+{
+ sunxi_sram_release(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id sun50i_de2_bus_of_match[] = {
+ { .compatible = "allwinner,sun50i-a64-de2", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun50i_de2_bus_driver = {
+ .probe = sun50i_de2_bus_probe,
+ .remove = sun50i_de2_bus_remove,
+ .driver = {
+ .name = "sun50i-de2-bus",
+ .of_match_table = sun50i_de2_bus_of_match,
+ },
+};
+
+builtin_platform_driver(sun50i_de2_bus_driver);
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 80d60f43db56..c9bac9dc4637 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -23,11 +23,14 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <linux/iopoll.h>
#include <linux/platform_data/ti-sysc.h>
#include <dt-bindings/bus/ti-sysc.h>
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
static const char * const reg_names[] = { "rev", "sysc", "syss", };
enum sysc_clocks {
@@ -88,6 +91,11 @@ struct sysc {
struct delayed_work idle_work;
};
+void sysc_write(struct sysc *ddata, int offset, u32 value)
+{
+ writel_relaxed(value, ddata->module_va + offset);
+}
+
static u32 sysc_read(struct sysc *ddata, int offset)
{
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
@@ -943,6 +951,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
}
}
+static int sysc_reset(struct sysc *ddata)
+{
+ int offset = ddata->offsets[SYSC_SYSCONFIG];
+ int val;
+
+ if (ddata->legacy_mode || offset < 0 ||
+ ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ return 0;
+
+ /*
+ * Currently only support reset status in sysstatus.
+ * Warn and return error in all other cases
+ */
+ if (!ddata->cfg.syss_mask) {
+ dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
+ return -EINVAL;
+ }
+
+ val = sysc_read(ddata, offset);
+ val |= (0x1 << ddata->cap->regbits->srst_shift);
+ sysc_write(ddata, offset, val);
+
+ /* Poll on reset status */
+ offset = ddata->offsets[SYSC_SYSSTATUS];
+
+ return readl_poll_timeout(ddata->module_va + offset, val,
+ (val & ddata->cfg.syss_mask) == 0x0,
+ 100, MAX_MODULE_SOFTRESET_WAIT);
+}
+
/* At this point the module is configured enough to read the revision */
static int sysc_init_module(struct sysc *ddata)
{
@@ -960,6 +998,14 @@ static int sysc_init_module(struct sysc *ddata)
return 0;
}
+ error = sysc_reset(ddata);
+ if (error) {
+ dev_err(ddata->dev, "Reset failed with %d\n", error);
+ pm_runtime_put_sync(ddata->dev);
+
+ return error;
+ }
+
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
@@ -1552,6 +1598,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
.regbits = &sysc_regbits_omap4_usb_host_fs,
};
+static const struct sysc_regbits sysc_regbits_dra7_mcan = {
+ .dmadisable_shift = -ENODEV,
+ .midle_shift = -ENODEV,
+ .sidle_shift = -ENODEV,
+ .clkact_shift = -ENODEV,
+ .enwkup_shift = 4,
+ .srst_shift = 0,
+ .emufree_shift = -ENODEV,
+ .autoidle_shift = -ENODEV,
+};
+
+static const struct sysc_capabilities sysc_dra7_mcan = {
+ .type = TI_SYSC_DRA7_MCAN,
+ .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
+ .regbits = &sysc_regbits_dra7_mcan,
+};
+
static int sysc_init_pdata(struct sysc *ddata)
{
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -1743,6 +1806,7 @@ static const struct of_device_id sysc_match[] = {
{ .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
{ .compatible = "ti,sysc-usb-host-fs",
.data = &sysc_omap4_usb_host_fs, },
+ { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
{ },
};
MODULE_DEVICE_TABLE(of, sysc_match);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 94fedeeec035..4948c8bda6b1 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -193,14 +193,6 @@ static unsigned long rtc_freq; /* Current periodic IRQ rate */
static unsigned long rtc_irq_data; /* our output to the world */
static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
-#ifdef RTC_IRQ
-/*
- * rtc_task_lock nests inside rtc_lock.
- */
-static DEFINE_SPINLOCK(rtc_task_lock);
-static rtc_task_t *rtc_callback;
-#endif
-
/*
* If this driver ever becomes modularised, it will be really nice
* to make the epoch retain its value across module reload...
@@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
spin_unlock(&rtc_lock);
- /* Now do the rest of the actions */
- spin_lock(&rtc_task_lock);
- if (rtc_callback)
- rtc_callback->func(rtc_callback->private_data);
- spin_unlock(&rtc_task_lock);
wake_up_interruptible(&rtc_wait);
kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c
index 081b039fcb02..6481337382a6 100644
--- a/drivers/clk/davinci/psc-da830.c
+++ b/drivers/clk/davinci/psc-da830.c
@@ -14,6 +14,7 @@
#include "psc.h"
+LPSC_CLKDEV1(aemif_clkdev, NULL, "ti-aemif");
LPSC_CLKDEV1(spi0_clkdev, NULL, "spi_davinci.0");
LPSC_CLKDEV1(mmcsd_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
@@ -22,7 +23,7 @@ static const struct davinci_lpsc_clk_info da830_psc0_info[] = {
LPSC(0, 0, tpcc, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
LPSC(1, 0, tptc0, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
LPSC(2, 0, tptc1, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
- LPSC(3, 0, aemif, pll0_sysclk3, NULL, LPSC_ALWAYS_ENABLED),
+ LPSC(3, 0, aemif, pll0_sysclk3, aemif_clkdev, LPSC_ALWAYS_ENABLED),
LPSC(4, 0, spi0, pll0_sysclk2, spi0_clkdev, 0),
LPSC(5, 0, mmcsd, pll0_sysclk2, mmcsd_clkdev, 0),
LPSC(6, 0, aintc, pll0_sysclk4, NULL, LPSC_ALWAYS_ENABLED),
diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
index d196dcbed560..5a18bca464cd 100644
--- a/drivers/clk/davinci/psc-da850.c
+++ b/drivers/clk/davinci/psc-da850.c
@@ -16,8 +16,7 @@
#include "psc.h"
-LPSC_CLKDEV2(emifa_clkdev, NULL, "ti-aemif",
- "aemif", "davinci_nand.0");
+LPSC_CLKDEV1(emifa_clkdev, NULL, "ti-aemif");
LPSC_CLKDEV1(spi0_clkdev, NULL, "spi_davinci.0");
LPSC_CLKDEV1(mmcsd0_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c
index 8c73086cc676..c75424f4ea3b 100644
--- a/drivers/clk/davinci/psc-dm365.c
+++ b/drivers/clk/davinci/psc-dm365.c
@@ -21,7 +21,8 @@ LPSC_CLKDEV1(mmcsd1_clkdev, NULL, "da830-mmc.1");
LPSC_CLKDEV1(asp0_clkdev, NULL, "davinci-mcbsp");
LPSC_CLKDEV1(usb_clkdev, "usb", NULL);
LPSC_CLKDEV1(spi2_clkdev, NULL, "spi_davinci.2");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mmcsd0_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(i2c_clkdev, NULL, "i2c_davinci.1");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c
index fc0230e3a3d6..0cea6e0bd5f0 100644
--- a/drivers/clk/davinci/psc-dm644x.c
+++ b/drivers/clk/davinci/psc-dm644x.c
@@ -21,7 +21,8 @@ LPSC_CLKDEV2(emac_clkdev, NULL, "davinci_emac.1",
"fck", "davinci_mdio.0");
LPSC_CLKDEV1(usb_clkdev, "usb", NULL);
LPSC_CLKDEV1(ide_clkdev, NULL, "palm_bk3710");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mmcsd_clkdev, NULL, "dm6441-mmc.0");
LPSC_CLKDEV1(asp0_clkdev, NULL, "davinci-mcbsp");
LPSC_CLKDEV1(i2c_clkdev, NULL, "i2c_davinci.1");
diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c
index c3f82ed70a80..20012dc7471a 100644
--- a/drivers/clk/davinci/psc-dm646x.c
+++ b/drivers/clk/davinci/psc-dm646x.c
@@ -18,7 +18,8 @@
LPSC_CLKDEV1(ide_clkdev, NULL, "palm_bk3710");
LPSC_CLKDEV2(emac_clkdev, NULL, "davinci_emac.1",
"fck", "davinci_mdio.0");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mcasp0_clkdev, NULL, "davinci-mcasp.0");
LPSC_CLKDEV1(mcasp1_clkdev, NULL, "davinci-mcasp.1");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 513826393158..1a4e6b787978 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
-obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
deleted file mode 100644
index b08bd54c5e76..000000000000
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * Author: Thomas Abraham <thomas.ab@samsung.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.
- *
- * Common Clock Framework support for Exynos5440 SoC.
-*/
-
-#include <dt-bindings/clock/exynos5440.h>
-#include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include "clk.h"
-#include "clk-pll.h"
-
-#define CLKEN_OV_VAL 0xf8
-#define CPU_CLK_STATUS 0xfc
-#define MISC_DOUT1 0x558
-
-static void __iomem *reg_base;
-
-/* parent clock name list */
-PNAME(mout_armclk_p) = { "cplla", "cpllb" };
-PNAME(mout_spi_p) = { "div125", "div200" };
-
-/* fixed rate clocks generated outside the soc */
-static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
- FRATE(0, "xtal", NULL, 0, 0),
-};
-
-/* fixed rate clocks */
-static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
- FRATE(0, "ppll", NULL, 0, 1000000000),
- FRATE(0, "usb_phy0", NULL, 0, 60000000),
- FRATE(0, "usb_phy1", NULL, 0, 60000000),
- FRATE(0, "usb_ohci12", NULL, 0, 12000000),
- FRATE(0, "usb_ohci48", NULL, 0, 48000000),
-};
-
-/* fixed factor clocks */
-static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
- FFACTOR(0, "div250", "ppll", 1, 4, 0),
- FFACTOR(0, "div200", "ppll", 1, 5, 0),
- FFACTOR(0, "div125", "div250", 1, 2, 0),
-};
-
-/* mux clocks */
-static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
- MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
- MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1),
-};
-
-/* divider clocks */
-static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
- DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
-};
-
-/* gate clocks */
-static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
- GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
- GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
- GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
- GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
- GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
- GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
- GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
- GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
- GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
- GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
- GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
- GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
- GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
- GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
- GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
- GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
- GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
- GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
- GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
- GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
-};
-
-static const struct of_device_id ext_clk_match[] __initconst = {
- { .compatible = "samsung,clock-xtal", .data = (void *)0, },
- {},
-};
-
-static int exynos5440_clk_restart_notify(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- u32 val, status;
-
- status = readl_relaxed(reg_base + 0xbc);
- val = readl_relaxed(reg_base + 0xcc);
- val = (val & 0xffff0000) | (status & 0xffff);
- writel_relaxed(val, reg_base + 0xcc);
-
- return NOTIFY_DONE;
-}
-
-/*
- * Exynos5440 Clock restart notifier, handles restart functionality
- */
-static struct notifier_block exynos5440_clk_restart_handler = {
- .notifier_call = exynos5440_clk_restart_notify,
- .priority = 128,
-};
-
-static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
- PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL),
- PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
-};
-
-/*
- * Clock aliases for legacy clkdev look-up.
- */
-static const struct samsung_clock_alias exynos5440_aliases[] __initconst = {
- ALIAS(CLK_ARM_CLK, NULL, "armclk"),
-};
-
-/* register exynos5440 clocks */
-static void __init exynos5440_clk_init(struct device_node *np)
-{
- struct samsung_clk_provider *ctx;
-
- reg_base = of_iomap(np, 0);
- if (!reg_base) {
- pr_err("%s: failed to map clock controller registers,"
- " aborting clock initialization\n", __func__);
- return;
- }
-
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-
- samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
- ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
-
- samsung_clk_register_pll(ctx, exynos5440_plls,
- ARRAY_SIZE(exynos5440_plls), ctx->reg_base);
-
- samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
- ARRAY_SIZE(exynos5440_fixed_rate_clks));
- samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
- ARRAY_SIZE(exynos5440_fixed_factor_clks));
- samsung_clk_register_mux(ctx, exynos5440_mux_clks,
- ARRAY_SIZE(exynos5440_mux_clks));
- samsung_clk_register_div(ctx, exynos5440_div_clks,
- ARRAY_SIZE(exynos5440_div_clks));
- samsung_clk_register_gate(ctx, exynos5440_gate_clks,
- ARRAY_SIZE(exynos5440_gate_clks));
- samsung_clk_register_alias(ctx, exynos5440_aliases,
- ARRAY_SIZE(exynos5440_aliases));
-
- samsung_clk_of_add_provider(np, ctx);
-
- if (register_restart_handler(&exynos5440_clk_restart_handler))
- pr_warn("exynos5440 clock can't register restart handler\n");
-
- pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
- pr_info("exynos5440 clock initialization complete\n");
-}
-CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index fb249a1637a5..71a122b2dc67 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -708,6 +708,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
{ DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
{ DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" },
{ DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" },
+ { DRA7_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk"},
{ 0 },
};
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 52f5f1a2040c..0cd8eb76ad59 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -71,20 +71,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ
Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
-config ARM_EXYNOS5440_CPUFREQ
- tristate "SAMSUNG EXYNOS5440"
- depends on SOC_EXYNOS5440
- depends on HAVE_CLK && OF
- select PM_OPP
- default y
- help
- This adds the CPUFreq driver for Samsung EXYNOS5440
- SoC. The nature of exynos5440 clock controller is
- different than previous exynos controllers so not using
- the common exynos framework.
-
- If in doubt, say N.
-
config ARM_HIGHBANK_CPUFREQ
tristate "Calxeda Highbank-based"
depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index fb4a2ecac43b..c1ffeabe4ecf 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 1d50e97d49f1..6d53f7d9fc7a 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -555,12 +555,20 @@ EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
{
- struct policy_dbs_info *policy_dbs = policy->governor_data;
+ struct policy_dbs_info *policy_dbs;
+
+ /* Protect gov->gdbs_data against cpufreq_dbs_governor_exit() */
+ mutex_lock(&gov_dbs_data_mutex);
+ policy_dbs = policy->governor_data;
+ if (!policy_dbs)
+ goto out;
mutex_lock(&policy_dbs->update_mutex);
cpufreq_policy_apply_limits(policy);
gov_update_sample_delay(policy_dbs, 0);
-
mutex_unlock(&policy_dbs->update_mutex);
+
+out:
+ mutex_unlock(&gov_dbs_data_mutex);
}
EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
deleted file mode 100644
index 932caa386ece..000000000000
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Amit Daniel Kachhap <amit.daniel@samsung.com>
- *
- * EXYNOS5440 - CPU frequency scaling support
- *
- * 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/clk.h>
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/pm_opp.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* Register definitions */
-#define XMU_DVFS_CTRL 0x0060
-#define XMU_PMU_P0_7 0x0064
-#define XMU_C0_3_PSTATE 0x0090
-#define XMU_P_LIMIT 0x00a0
-#define XMU_P_STATUS 0x00a4
-#define XMU_PMUEVTEN 0x00d0
-#define XMU_PMUIRQEN 0x00d4
-#define XMU_PMUIRQ 0x00d8
-
-/* PMU mask and shift definations */
-#define P_VALUE_MASK 0x7
-
-#define XMU_DVFS_CTRL_EN_SHIFT 0
-
-#define P0_7_CPUCLKDEV_SHIFT 21
-#define P0_7_CPUCLKDEV_MASK 0x7
-#define P0_7_ATBCLKDEV_SHIFT 18
-#define P0_7_ATBCLKDEV_MASK 0x7
-#define P0_7_CSCLKDEV_SHIFT 15
-#define P0_7_CSCLKDEV_MASK 0x7
-#define P0_7_CPUEMA_SHIFT 28
-#define P0_7_CPUEMA_MASK 0xf
-#define P0_7_L2EMA_SHIFT 24
-#define P0_7_L2EMA_MASK 0xf
-#define P0_7_VDD_SHIFT 8
-#define P0_7_VDD_MASK 0x7f
-#define P0_7_FREQ_SHIFT 0
-#define P0_7_FREQ_MASK 0xff
-
-#define C0_3_PSTATE_VALID_SHIFT 8
-#define C0_3_PSTATE_CURR_SHIFT 4
-#define C0_3_PSTATE_NEW_SHIFT 0
-
-#define PSTATE_CHANGED_EVTEN_SHIFT 0
-
-#define PSTATE_CHANGED_IRQEN_SHIFT 0
-
-#define PSTATE_CHANGED_SHIFT 0
-
-/* some constant values for clock divider calculation */
-#define CPU_DIV_FREQ_MAX 500
-#define CPU_DBG_FREQ_MAX 375
-#define CPU_ATB_FREQ_MAX 500
-
-#define PMIC_LOW_VOLT 0x30
-#define PMIC_HIGH_VOLT 0x28
-
-#define CPUEMA_HIGH 0x2
-#define CPUEMA_MID 0x4
-#define CPUEMA_LOW 0x7
-
-#define L2EMA_HIGH 0x1
-#define L2EMA_MID 0x3
-#define L2EMA_LOW 0x4
-
-#define DIV_TAB_MAX 2
-/* frequency unit is 20MHZ */
-#define FREQ_UNIT 20
-#define MAX_VOLTAGE 1550000 /* In microvolt */
-#define VOLTAGE_STEP 12500 /* In microvolt */
-
-#define CPUFREQ_NAME "exynos5440_dvfs"
-#define DEF_TRANS_LATENCY 100000
-
-enum cpufreq_level_index {
- L0, L1, L2, L3, L4,
- L5, L6, L7, L8, L9,
-};
-#define CPUFREQ_LEVEL_END (L7 + 1)
-
-struct exynos_dvfs_data {
- void __iomem *base;
- struct resource *mem;
- int irq;
- struct clk *cpu_clk;
- unsigned int latency;
- struct cpufreq_frequency_table *freq_table;
- unsigned int freq_count;
- struct device *dev;
- bool dvfs_enabled;
- struct work_struct irq_work;
-};
-
-static struct exynos_dvfs_data *dvfs_info;
-static DEFINE_MUTEX(cpufreq_lock);
-static struct cpufreq_freqs freqs;
-
-static int init_div_table(void)
-{
- struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table;
- unsigned int tmp, clk_div, ema_div, freq, volt_id, idx;
- struct dev_pm_opp *opp;
-
- cpufreq_for_each_entry_idx(pos, freq_tbl, idx) {
- opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
- pos->frequency * 1000, true);
- if (IS_ERR(opp)) {
- dev_err(dvfs_info->dev,
- "failed to find valid OPP for %u KHZ\n",
- pos->frequency);
- return PTR_ERR(opp);
- }
-
- freq = pos->frequency / 1000; /* In MHZ */
- clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK)
- << P0_7_CPUCLKDEV_SHIFT;
- clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK)
- << P0_7_ATBCLKDEV_SHIFT;
- clk_div |= ((freq / CPU_DBG_FREQ_MAX) & P0_7_CSCLKDEV_MASK)
- << P0_7_CSCLKDEV_SHIFT;
-
- /* Calculate EMA */
- volt_id = dev_pm_opp_get_voltage(opp);
-
- volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
- if (volt_id < PMIC_HIGH_VOLT) {
- ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
- (L2EMA_HIGH << P0_7_L2EMA_SHIFT);
- } else if (volt_id > PMIC_LOW_VOLT) {
- ema_div = (CPUEMA_LOW << P0_7_CPUEMA_SHIFT) |
- (L2EMA_LOW << P0_7_L2EMA_SHIFT);
- } else {
- ema_div = (CPUEMA_MID << P0_7_CPUEMA_SHIFT) |
- (L2EMA_MID << P0_7_L2EMA_SHIFT);
- }
-
- tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT)
- | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT));
-
- __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx);
- dev_pm_opp_put(opp);
- }
-
- return 0;
-}
-
-static void exynos_enable_dvfs(unsigned int cur_frequency)
-{
- unsigned int tmp, cpu;
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
- struct cpufreq_frequency_table *pos;
- /* Disable DVFS */
- __raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL);
-
- /* Enable PSTATE Change Event */
- tmp = __raw_readl(dvfs_info->base + XMU_PMUEVTEN);
- tmp |= (1 << PSTATE_CHANGED_EVTEN_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_PMUEVTEN);
-
- /* Enable PSTATE Change IRQ */
- tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQEN);
- tmp |= (1 << PSTATE_CHANGED_IRQEN_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN);
-
- /* Set initial performance index */
- cpufreq_for_each_entry(pos, freq_table)
- if (pos->frequency == cur_frequency)
- break;
-
- if (pos->frequency == CPUFREQ_TABLE_END) {
- dev_crit(dvfs_info->dev, "Boot up frequency not supported\n");
- /* Assign the highest frequency */
- pos = freq_table;
- cur_frequency = pos->frequency;
- }
-
- dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ",
- cur_frequency);
-
- for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
- tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
- tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
- tmp |= ((pos - freq_table) << C0_3_PSTATE_NEW_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
- }
-
- /* Enable DVFS */
- __raw_writel(1 << XMU_DVFS_CTRL_EN_SHIFT,
- dvfs_info->base + XMU_DVFS_CTRL);
-}
-
-static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
-{
- unsigned int tmp;
- int i;
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
- mutex_lock(&cpufreq_lock);
-
- freqs.old = policy->cur;
- freqs.new = freq_table[index].frequency;
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
- /* Set the target frequency in all C0_3_PSTATE register */
- for_each_cpu(i, policy->cpus) {
- tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
- tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
- tmp |= (index << C0_3_PSTATE_NEW_SHIFT);
-
- __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
- }
- mutex_unlock(&cpufreq_lock);
- return 0;
-}
-
-static void exynos_cpufreq_work(struct work_struct *work)
-{
- unsigned int cur_pstate, index;
- struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
- /* Ensure we can access cpufreq structures */
- if (unlikely(dvfs_info->dvfs_enabled == false))
- goto skip_work;
-
- mutex_lock(&cpufreq_lock);
- freqs.old = policy->cur;
-
- cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS);
- if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1)
- index = (cur_pstate >> C0_3_PSTATE_CURR_SHIFT) & P_VALUE_MASK;
- else
- index = (cur_pstate >> C0_3_PSTATE_NEW_SHIFT) & P_VALUE_MASK;
-
- if (likely(index < dvfs_info->freq_count)) {
- freqs.new = freq_table[index].frequency;
- } else {
- dev_crit(dvfs_info->dev, "New frequency out of range\n");
- freqs.new = freqs.old;
- }
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
- cpufreq_cpu_put(policy);
- mutex_unlock(&cpufreq_lock);
-skip_work:
- enable_irq(dvfs_info->irq);
-}
-
-static irqreturn_t exynos_cpufreq_irq(int irq, void *id)
-{
- unsigned int tmp;
-
- tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQ);
- if (tmp >> PSTATE_CHANGED_SHIFT & 0x1) {
- __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQ);
- disable_irq_nosync(irq);
- schedule_work(&dvfs_info->irq_work);
- }
- return IRQ_HANDLED;
-}
-
-static void exynos_sort_descend_freq_table(void)
-{
- struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
- int i = 0, index;
- unsigned int tmp_freq;
- /*
- * Exynos5440 clock controller state logic expects the cpufreq table to
- * be in descending order. But the OPP library constructs the table in
- * ascending order. So to make the table descending we just need to
- * swap the i element with the N - i element.
- */
- for (i = 0; i < dvfs_info->freq_count / 2; i++) {
- index = dvfs_info->freq_count - i - 1;
- tmp_freq = freq_tbl[i].frequency;
- freq_tbl[i].frequency = freq_tbl[index].frequency;
- freq_tbl[index].frequency = tmp_freq;
- }
-}
-
-static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- policy->clk = dvfs_info->cpu_clk;
- return cpufreq_generic_init(policy, dvfs_info->freq_table,
- dvfs_info->latency);
-}
-
-static struct cpufreq_driver exynos_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION |
- CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = exynos_target,
- .get = cpufreq_generic_get,
- .init = exynos_cpufreq_cpu_init,
- .name = CPUFREQ_NAME,
- .attr = cpufreq_generic_attr,
-};
-
-static const struct of_device_id exynos_cpufreq_match[] = {
- {
- .compatible = "samsung,exynos5440-cpufreq",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, exynos_cpufreq_match);
-
-static int exynos_cpufreq_probe(struct platform_device *pdev)
-{
- int ret = -EINVAL;
- struct device_node *np;
- struct resource res;
- unsigned int cur_frequency;
-
- np = pdev->dev.of_node;
- if (!np)
- return -ENODEV;
-
- dvfs_info = devm_kzalloc(&pdev->dev, sizeof(*dvfs_info), GFP_KERNEL);
- if (!dvfs_info) {
- ret = -ENOMEM;
- goto err_put_node;
- }
-
- dvfs_info->dev = &pdev->dev;
-
- ret = of_address_to_resource(np, 0, &res);
- if (ret)
- goto err_put_node;
-
- dvfs_info->base = devm_ioremap_resource(dvfs_info->dev, &res);
- if (IS_ERR(dvfs_info->base)) {
- ret = PTR_ERR(dvfs_info->base);
- goto err_put_node;
- }
-
- dvfs_info->irq = irq_of_parse_and_map(np, 0);
- if (!dvfs_info->irq) {
- dev_err(dvfs_info->dev, "No cpufreq irq found\n");
- ret = -ENODEV;
- goto err_put_node;
- }
-
- ret = dev_pm_opp_of_add_table(dvfs_info->dev);
- if (ret) {
- dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
- goto err_put_node;
- }
-
- ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
- &dvfs_info->freq_table);
- if (ret) {
- dev_err(dvfs_info->dev,
- "failed to init cpufreq table: %d\n", ret);
- goto err_free_opp;
- }
- dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
- exynos_sort_descend_freq_table();
-
- if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
- dvfs_info->latency = DEF_TRANS_LATENCY;
-
- dvfs_info->cpu_clk = devm_clk_get(dvfs_info->dev, "armclk");
- if (IS_ERR(dvfs_info->cpu_clk)) {
- dev_err(dvfs_info->dev, "Failed to get cpu clock\n");
- ret = PTR_ERR(dvfs_info->cpu_clk);
- goto err_free_table;
- }
-
- cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
- if (!cur_frequency) {
- dev_err(dvfs_info->dev, "Failed to get clock rate\n");
- ret = -EINVAL;
- goto err_free_table;
- }
- cur_frequency /= 1000;
-
- INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work);
- ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq,
- exynos_cpufreq_irq, IRQF_TRIGGER_NONE,
- CPUFREQ_NAME, dvfs_info);
- if (ret) {
- dev_err(dvfs_info->dev, "Failed to register IRQ\n");
- goto err_free_table;
- }
-
- ret = init_div_table();
- if (ret) {
- dev_err(dvfs_info->dev, "Failed to initialise div table\n");
- goto err_free_table;
- }
-
- exynos_enable_dvfs(cur_frequency);
- ret = cpufreq_register_driver(&exynos_driver);
- if (ret) {
- dev_err(dvfs_info->dev,
- "%s: failed to register cpufreq driver\n", __func__);
- goto err_free_table;
- }
-
- of_node_put(np);
- dvfs_info->dvfs_enabled = true;
- return 0;
-
-err_free_table:
- dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
-err_free_opp:
- dev_pm_opp_of_remove_table(dvfs_info->dev);
-err_put_node:
- of_node_put(np);
- dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
- return ret;
-}
-
-static int exynos_cpufreq_remove(struct platform_device *pdev)
-{
- cpufreq_unregister_driver(&exynos_driver);
- dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
- dev_pm_opp_of_remove_table(dvfs_info->dev);
- return 0;
-}
-
-static struct platform_driver exynos_cpufreq_platdrv = {
- .driver = {
- .name = "exynos5440-cpufreq",
- .of_match_table = exynos_cpufreq_match,
- },
- .probe = exynos_cpufreq_probe,
- .remove = exynos_cpufreq_remove,
-};
-module_platform_driver(exynos_cpufreq_platdrv);
-
-MODULE_AUTHOR("Amit Daniel Kachhap <amit.daniel@samsung.com>");
-MODULE_DESCRIPTION("Exynos5440 cpufreq driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aef60d160eb..110483f0e3fb 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -328,9 +328,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
unsigned int polling_threshold;
/*
- * We want to default to C1 (hlt), not to busy polling
- * unless the timer is happening really really soon, or
- * C1's exit latency exceeds the user configured limit.
+ * Default to a physical idle state, not to busy polling, unless
+ * a timer is going to trigger really really soon.
*/
polling_threshold = max_t(unsigned int, 20, s->target_residency);
if (data->next_timer_us > polling_threshold &&
@@ -349,14 +348,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
* If the tick is already stopped, the cost of possible short
* idle duration misprediction is much higher, because the CPU
* may be stuck in a shallow idle state for a long time as a
- * result of it. In that case say we might mispredict and try
- * to force the CPU into a state for which we would have stopped
- * the tick, unless a timer is going to expire really soon
- * anyway.
+ * result of it. In that case say we might mispredict and use
+ * the known time till the closest timer event for the idle
+ * state selection.
*/
if (data->predicted_us < TICK_USEC)
- data->predicted_us = min_t(unsigned int, TICK_USEC,
- ktime_to_us(delta_next));
+ data->predicted_us = ktime_to_us(delta_next);
} else {
/*
* Use the performance multiplier and the user-configurable
@@ -381,8 +378,22 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
continue;
if (idx == -1)
idx = i; /* first enabled state */
- if (s->target_residency > data->predicted_us)
- break;
+ if (s->target_residency > data->predicted_us) {
+ if (!tick_nohz_tick_stopped())
+ break;
+
+ /*
+ * If the state selected so far is shallow and this
+ * state's target residency matches the time till the
+ * closest timer event, select this one to avoid getting
+ * stuck in the shallow one for too long.
+ */
+ if (drv->states[idx].target_residency < TICK_USEC &&
+ s->target_residency <= ktime_to_us(delta_next))
+ idx = i;
+
+ goto out;
+ }
if (s->exit_latency > latency_req) {
/*
* If we break out of the loop for latency reasons, use
@@ -403,14 +414,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
* Don't stop the tick if the selected state is a polling one or if the
* expected idle duration is shorter than the tick period length.
*/
- if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
- expected_interval < TICK_USEC) {
+ if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
+ expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) {
unsigned int delta_next_us = ktime_to_us(delta_next);
*stop_tick = false;
- if (!tick_nohz_tick_stopped() && idx > 0 &&
- drv->states[idx].target_residency > delta_next_us) {
+ if (idx > 0 && drv->states[idx].target_residency > delta_next_us) {
/*
* The tick is not going to be stopped and the target
* residency of the state to be returned is not within
@@ -418,8 +428,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
* tick, so try to correct that.
*/
for (i = idx - 1; i >= 0; i--) {
- if (drv->states[i].disabled ||
- dev->states_usage[i].disable)
+ if (drv->states[i].disabled ||
+ dev->states_usage[i].disable)
continue;
idx = i;
@@ -429,6 +439,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
}
}
+out:
data->last_state_idx = idx;
return data->last_state_idx;
diff --git a/drivers/crypto/caam/sg_sw_qm2.h b/drivers/crypto/caam/sg_sw_qm2.h
index 31b440757146..b5b4c12179df 100644
--- a/drivers/crypto/caam/sg_sw_qm2.h
+++ b/drivers/crypto/caam/sg_sw_qm2.h
@@ -35,7 +35,7 @@
#ifndef _SG_SW_QM2_H_
#define _SG_SW_QM2_H_
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
static inline void dma_to_qm_sg_one(struct dpaa2_sg_entry *qm_sg_ptr,
dma_addr_t dma, u32 len, u16 offset)
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index e586ffab8358..dbfa9fce33e0 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -12,7 +12,7 @@
#include "ctrl.h"
#include "regs.h"
#include "sg_sw_qm2.h"
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
struct sec4_sg_entry {
u64 ptr;
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 3bb82e511eca..7d3edd713932 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -215,6 +215,7 @@ const char * const edac_mem_types[] = {
[MEM_LRDDR3] = "Load-Reduced-DDR3-RAM",
[MEM_DDR4] = "Unbuffered-DDR4",
[MEM_RDDR4] = "Registered-DDR4",
+ [MEM_LRDDR4] = "Load-Reduced-DDR4-RAM",
[MEM_NVDIMM] = "Non-volatile-RAM",
};
EXPORT_SYMBOL_GPL(edac_mem_types);
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 2a219b1261b1..721e6c57beae 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -363,8 +363,6 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
return domain;
dom = pi->dom_info + domain;
- if (!dom)
- return -EIO;
for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
freq = opp->perf * dom->mult_factor;
@@ -394,9 +392,6 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
return domain;
dom = pi->dom_info + domain;
- if (!dom)
- return -EIO;
-
/* uS to nS */
return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
}
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 88c322d7c71e..14c40a7750d1 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -24,6 +24,7 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \
-D__NO_FORTIFY \
$(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector) \
+ -D__DISABLE_EXPORTS
GCOV_PROFILE := n
KASAN_SANITIZE := n
diff --git a/drivers/firmware/psci_checker.c b/drivers/firmware/psci_checker.c
index bb1c068bff19..346943657962 100644
--- a/drivers/firmware/psci_checker.c
+++ b/drivers/firmware/psci_checker.c
@@ -77,28 +77,6 @@ static int psci_ops_check(void)
return 0;
}
-static int find_cpu_groups(const struct cpumask *cpus,
- const struct cpumask **cpu_groups)
-{
- unsigned int nb = 0;
- cpumask_var_t tmp;
-
- if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
- return -ENOMEM;
- cpumask_copy(tmp, cpus);
-
- while (!cpumask_empty(tmp)) {
- const struct cpumask *cpu_group =
- topology_core_cpumask(cpumask_any(tmp));
-
- cpu_groups[nb++] = cpu_group;
- cpumask_andnot(tmp, tmp, cpu_group);
- }
-
- free_cpumask_var(tmp);
- return nb;
-}
-
/*
* offlined_cpus is a temporary array but passing it as an argument avoids
* multiple allocations.
@@ -166,29 +144,66 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
return err;
}
+static void free_cpu_groups(int num, cpumask_var_t **pcpu_groups)
+{
+ int i;
+ cpumask_var_t *cpu_groups = *pcpu_groups;
+
+ for (i = 0; i < num; ++i)
+ free_cpumask_var(cpu_groups[i]);
+ kfree(cpu_groups);
+}
+
+static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
+{
+ int num_groups = 0;
+ cpumask_var_t tmp, *cpu_groups;
+
+ if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
+ return -ENOMEM;
+
+ cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
+ GFP_KERNEL);
+ if (!cpu_groups)
+ return -ENOMEM;
+
+ cpumask_copy(tmp, cpu_online_mask);
+
+ while (!cpumask_empty(tmp)) {
+ const struct cpumask *cpu_group =
+ topology_core_cpumask(cpumask_any(tmp));
+
+ if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
+ free_cpu_groups(num_groups, &cpu_groups);
+ return -ENOMEM;
+ }
+ cpumask_copy(cpu_groups[num_groups++], cpu_group);
+ cpumask_andnot(tmp, tmp, cpu_group);
+ }
+
+ free_cpumask_var(tmp);
+ *pcpu_groups = cpu_groups;
+
+ return num_groups;
+}
+
static int hotplug_tests(void)
{
- int err;
- cpumask_var_t offlined_cpus;
- int i, nb_cpu_group;
- const struct cpumask **cpu_groups;
+ int i, nb_cpu_group, err = -ENOMEM;
+ cpumask_var_t offlined_cpus, *cpu_groups;
char *page_buf;
- err = -ENOMEM;
if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
return err;
- /* We may have up to nb_available_cpus cpu_groups. */
- cpu_groups = kmalloc_array(nb_available_cpus, sizeof(*cpu_groups),
- GFP_KERNEL);
- if (!cpu_groups)
+
+ nb_cpu_group = alloc_init_cpu_groups(&cpu_groups);
+ if (nb_cpu_group < 0)
goto out_free_cpus;
page_buf = (char *)__get_free_page(GFP_KERNEL);
if (!page_buf)
goto out_free_cpu_groups;
err = 0;
- nb_cpu_group = find_cpu_groups(cpu_online_mask, cpu_groups);
-
/*
* Of course the last CPU cannot be powered down and cpu_down() should
* refuse doing that.
@@ -212,7 +227,7 @@ static int hotplug_tests(void)
free_page((unsigned long)page_buf);
out_free_cpu_groups:
- kfree(cpu_groups);
+ free_cpu_groups(nb_cpu_group, &cpu_groups);
out_free_cpus:
free_cpumask_var(offlined_cpus);
return err;
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 6692888f04cf..a200a2174611 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -21,6 +21,10 @@
#define MBOX_DATA28(msg) ((msg) & ~0xf)
#define MBOX_CHAN_PROPERTY 8
+#define MAX_RPI_FW_PROP_BUF_SIZE 32
+
+static struct platform_device *rpi_hwmon;
+
struct rpi_firmware {
struct mbox_client cl;
struct mbox_chan *chan; /* The property channel. */
@@ -143,18 +147,22 @@ int rpi_firmware_property(struct rpi_firmware *fw,
/* Single tags are very small (generally 8 bytes), so the
* stack should be safe.
*/
- u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
+ u8 data[sizeof(struct rpi_firmware_property_tag_header) +
+ MAX_RPI_FW_PROP_BUF_SIZE];
struct rpi_firmware_property_tag_header *header =
(struct rpi_firmware_property_tag_header *)data;
int ret;
+ if (WARN_ON(buf_size > sizeof(data) - sizeof(*header)))
+ return -EINVAL;
+
header->tag = tag;
header->buf_size = buf_size;
header->req_resp_size = 0;
memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
tag_data, buf_size);
- ret = rpi_firmware_property_list(fw, &data, sizeof(data));
+ ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header));
memcpy(tag_data,
data + sizeof(struct rpi_firmware_property_tag_header),
buf_size);
@@ -183,6 +191,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
}
}
+static void
+rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+{
+ u32 packet;
+ int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
+ &packet, sizeof(packet));
+
+ if (ret)
+ return;
+
+ rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
+ -1, NULL, 0);
+}
+
static int rpi_firmware_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -209,6 +231,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fw);
rpi_firmware_print_firmware_revision(fw);
+ rpi_register_hwmon_driver(dev, fw);
return 0;
}
@@ -217,6 +240,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
+ platform_device_unregister(rpi_hwmon);
+ rpi_hwmon = NULL;
mbox_free_channel(fw->chan);
return 0;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f7a0f576f918..4f52c3a8ec99 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1049,6 +1049,12 @@ config GPIO_LP87565
This driver can also be built as a module. If so, the module will be
called gpio-lp87565.
+config GPIO_MADERA
+ tristate "Cirrus Logic Madera class codecs"
+ depends on PINCTRL_MADERA
+ help
+ Support for GPIOs on Cirrus Logic Madera class codecs.
+
config GPIO_MAX77620
tristate "GPIO support for PMIC MAX77620 and MAX20024"
depends on MFD_MAX77620
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fc77989371be..c256aff66a65 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
+obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c
new file mode 100644
index 000000000000..7ba68d1a0932
--- /dev/null
+++ b/drivers/gpio/gpio-madera.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GPIO support for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/pdata.h>
+#include <linux/mfd/madera/registers.h>
+
+struct madera_gpio {
+ struct madera *madera;
+ /* storage space for the gpio_chip we're using */
+ struct gpio_chip gpio_chip;
+};
+
+static int madera_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+ struct madera *madera = madera_gpio->madera;
+ unsigned int reg_offset = 2 * offset;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset,
+ &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & MADERA_GP1_DIR_MASK);
+}
+
+static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
+{
+ struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+ struct madera *madera = madera_gpio->madera;
+ unsigned int reg_offset = 2 * offset;
+
+ return regmap_update_bits(madera->regmap,
+ MADERA_GPIO1_CTRL_2 + reg_offset,
+ MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
+}
+
+static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+ struct madera *madera = madera_gpio->madera;
+ unsigned int reg_offset = 2 * offset;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset,
+ &val);
+ if (ret < 0)
+ return ret;
+
+ return !!(val & MADERA_GP1_LVL_MASK);
+}
+
+static int madera_gpio_direction_out(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+ struct madera *madera = madera_gpio->madera;
+ unsigned int reg_offset = 2 * offset;
+ unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
+ int ret;
+
+ ret = regmap_update_bits(madera->regmap,
+ MADERA_GPIO1_CTRL_2 + reg_offset,
+ MADERA_GP1_DIR_MASK, 0);
+ if (ret < 0)
+ return ret;
+
+ return regmap_update_bits(madera->regmap,
+ MADERA_GPIO1_CTRL_1 + reg_offset,
+ MADERA_GP1_LVL_MASK, reg_val);
+}
+
+static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+ struct madera *madera = madera_gpio->madera;
+ unsigned int reg_offset = 2 * offset;
+ unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
+ int ret;
+
+ ret = regmap_update_bits(madera->regmap,
+ MADERA_GPIO1_CTRL_1 + reg_offset,
+ MADERA_GP1_LVL_MASK, reg_val);
+
+ /* set() doesn't return an error so log a warning */
+ if (ret)
+ dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
+ MADERA_GPIO1_CTRL_1 + reg_offset, ret);
+}
+
+static struct gpio_chip madera_gpio_chip = {
+ .label = "madera",
+ .owner = THIS_MODULE,
+ .request = gpiochip_generic_request,
+ .free = gpiochip_generic_free,
+ .get_direction = madera_gpio_get_direction,
+ .direction_input = madera_gpio_direction_in,
+ .get = madera_gpio_get,
+ .direction_output = madera_gpio_direction_out,
+ .set = madera_gpio_set,
+ .set_config = gpiochip_generic_config,
+ .can_sleep = true,
+};
+
+static int madera_gpio_probe(struct platform_device *pdev)
+{
+ struct madera *madera = dev_get_drvdata(pdev->dev.parent);
+ struct madera_pdata *pdata = dev_get_platdata(madera->dev);
+ struct madera_gpio *madera_gpio;
+ int ret;
+
+ madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
+ GFP_KERNEL);
+ if (!madera_gpio)
+ return -ENOMEM;
+
+ madera_gpio->madera = madera;
+
+ /* Construct suitable gpio_chip from the template in madera_gpio_chip */
+ madera_gpio->gpio_chip = madera_gpio_chip;
+ madera_gpio->gpio_chip.parent = pdev->dev.parent;
+
+ switch (madera->type) {
+ case CS47L35:
+ madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
+ break;
+ case CS47L85:
+ case WM1840:
+ madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
+ break;
+ case CS47L90:
+ case CS47L91:
+ madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
+ return -EINVAL;
+ }
+
+ /* We want to be usable on systems that don't use devicetree or acpi */
+ if (pdata && pdata->gpio_base)
+ madera_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+ madera_gpio->gpio_chip.base = -1;
+
+ ret = devm_gpiochip_add_data(&pdev->dev,
+ &madera_gpio->gpio_chip,
+ madera_gpio);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+ return ret;
+ }
+
+ /*
+ * This is part of a composite MFD device which can only be used with
+ * the corresponding pinctrl driver. On all supported silicon the GPIO
+ * to pinctrl mapping is fixed in the silicon, so we register it
+ * explicitly instead of requiring a redundant gpio-ranges in the
+ * devicetree.
+ * In any case we also want to work on systems that don't use devicetree
+ * or acpi.
+ */
+ ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl",
+ 0, 0, madera_gpio->gpio_chip.ngpio);
+ if (ret) {
+ dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver madera_gpio_driver = {
+ .driver = {
+ .name = "madera-gpio",
+ },
+ .probe = madera_gpio_probe,
+};
+
+module_platform_driver(madera_gpio_driver);
+
+MODULE_SOFTDEP("pre: pinctrl-madera");
+MODULE_DESCRIPTION("GPIO interface for Madera codecs");
+MODULE_AUTHOR("Nariman Poushin <nariman@opensource.cirrus.com>");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:madera-gpio");
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
index a365ea2383d1..e55508b39496 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
@@ -178,12 +178,18 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
*
* @amn: our notifier
*/
-static void amdgpu_mn_read_lock(struct amdgpu_mn *amn)
+static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
{
- mutex_lock(&amn->read_lock);
+ if (blockable)
+ mutex_lock(&amn->read_lock);
+ else if (!mutex_trylock(&amn->read_lock))
+ return -EAGAIN;
+
if (atomic_inc_return(&amn->recursion) == 1)
down_read_non_owner(&amn->lock);
mutex_unlock(&amn->read_lock);
+
+ return 0;
}
/**
@@ -239,10 +245,11 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
* Block for operations on BOs to finish and mark pages as accessed and
* potentially dirty.
*/
-static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
+static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
struct interval_tree_node *it;
@@ -250,17 +257,28 @@ static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
/* notification is exclusive, but interval is inclusive */
end -= 1;
- amdgpu_mn_read_lock(amn);
+ /* TODO we should be able to split locking for interval tree and
+ * amdgpu_mn_invalidate_node
+ */
+ if (amdgpu_mn_read_lock(amn, blockable))
+ return -EAGAIN;
it = interval_tree_iter_first(&amn->objects, start, end);
while (it) {
struct amdgpu_mn_node *node;
+ if (!blockable) {
+ amdgpu_mn_read_unlock(amn);
+ return -EAGAIN;
+ }
+
node = container_of(it, struct amdgpu_mn_node, it);
it = interval_tree_iter_next(it, start, end);
amdgpu_mn_invalidate_node(node, start, end);
}
+
+ return 0;
}
/**
@@ -275,10 +293,11 @@ static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
* necessitates evicting all user-mode queues of the process. The BOs
* are restorted in amdgpu_mn_invalidate_range_end_hsa.
*/
-static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
+static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
struct interval_tree_node *it;
@@ -286,13 +305,19 @@ static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
/* notification is exclusive, but interval is inclusive */
end -= 1;
- amdgpu_mn_read_lock(amn);
+ if (amdgpu_mn_read_lock(amn, blockable))
+ return -EAGAIN;
it = interval_tree_iter_first(&amn->objects, start, end);
while (it) {
struct amdgpu_mn_node *node;
struct amdgpu_bo *bo;
+ if (!blockable) {
+ amdgpu_mn_read_unlock(amn);
+ return -EAGAIN;
+ }
+
node = container_of(it, struct amdgpu_mn_node, it);
it = interval_tree_iter_next(it, start, end);
@@ -304,6 +329,8 @@ static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
amdgpu_amdkfd_evict_userptr(mem, mm);
}
}
+
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 5c607f2c707b..33a458b7f1fc 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -24,6 +24,7 @@ config DRM_I915
select IOSF_MBI
select CRC32
select SND_HDA_I915 if SND_HDA_CORE
+ select CEC_CORE if CEC_NOTIFIER
help
Choose this option if you have a system that has "Intel Graphics
Media Accelerator" or "HD Graphics" integrated graphics,
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c
index dcd6e230d16a..2c9b284036d1 100644
--- a/drivers/gpu/drm/i915/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/i915_gem_userptr.c
@@ -112,10 +112,11 @@ static void del_object(struct i915_mmu_object *mo)
mo->attached = false;
}
-static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
+static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct i915_mmu_notifier *mn =
container_of(_mn, struct i915_mmu_notifier, mn);
@@ -124,7 +125,7 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
LIST_HEAD(cancelled);
if (RB_EMPTY_ROOT(&mn->objects.rb_root))
- return;
+ return 0;
/* interval ranges are inclusive, but invalidate range is exclusive */
end--;
@@ -132,6 +133,10 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
spin_lock(&mn->lock);
it = interval_tree_iter_first(&mn->objects, start, end);
while (it) {
+ if (!blockable) {
+ spin_unlock(&mn->lock);
+ return -EAGAIN;
+ }
/* The mmu_object is released late when destroying the
* GEM object so it is entirely possible to gain a
* reference on an object in the process of being freed
@@ -154,6 +159,8 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
if (!list_empty(&cancelled))
flush_workqueue(mn->wq);
+
+ return 0;
}
static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 00165ad55fb3..395dd2511568 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -43,7 +43,7 @@
#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
__stringify(x), (long)(x))
-#if GCC_VERSION >= 70000
+#if defined(GCC_VERSION) && GCC_VERSION >= 70000
#define add_overflows(A, B) \
__builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0)
#else
diff --git a/drivers/gpu/drm/i915/intel_display.h b/drivers/gpu/drm/i915/intel_display.h
index 9292001cdd14..138a1bc1818c 100644
--- a/drivers/gpu/drm/i915/intel_display.h
+++ b/drivers/gpu/drm/i915/intel_display.h
@@ -126,6 +126,30 @@ enum port {
#define port_name(p) ((p) + 'A')
+/*
+ * Ports identifier referenced from other drivers.
+ * Expected to remain stable over time
+ */
+static inline const char *port_identifier(enum port port)
+{
+ switch (port) {
+ case PORT_A:
+ return "Port A";
+ case PORT_B:
+ return "Port B";
+ case PORT_C:
+ return "Port C";
+ case PORT_D:
+ return "Port D";
+ case PORT_E:
+ return "Port E";
+ case PORT_F:
+ return "Port F";
+ default:
+ return "<invalid>";
+ }
+}
+
enum tc_port {
PORT_TC_NONE = -1,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 17af06d8a43e..8fc61e96754f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -39,6 +39,7 @@
#include <drm/drm_dp_mst_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_atomic.h>
+#include <media/cec-notifier.h>
/**
* __wait_for - magic wait macro
@@ -1016,6 +1017,7 @@ struct intel_hdmi {
bool has_audio;
bool rgb_quant_range_selectable;
struct intel_connector *attached_connector;
+ struct cec_notifier *cec_notifier;
};
struct intel_dp_mst_encoder;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 8363fbd18ee8..a9076402dcb0 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1899,6 +1899,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
connected = true;
}
+ cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
+
return connected;
}
@@ -1907,6 +1909,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
{
enum drm_connector_status status;
struct drm_i915_private *dev_priv = to_i915(connector->dev);
+ struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
@@ -1922,6 +1925,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+ if (status != connector_status_connected)
+ cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
+
return status;
}
@@ -2062,6 +2068,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
static void intel_hdmi_destroy(struct drm_connector *connector)
{
+ if (intel_attached_hdmi(connector)->cec_notifier)
+ cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
kfree(to_intel_connector(connector)->detect_edid);
drm_connector_cleanup(connector);
kfree(connector);
@@ -2382,6 +2390,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
}
+
+ intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
+ port_identifier(port));
+ if (!intel_hdmi->cec_notifier)
+ DRM_DEBUG_KMS("CEC notifier get failed\n");
}
void intel_hdmi_init(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c
index abd24975c9b1..f8b35df44c60 100644
--- a/drivers/gpu/drm/radeon/radeon_mn.c
+++ b/drivers/gpu/drm/radeon/radeon_mn.c
@@ -118,19 +118,27 @@ static void radeon_mn_release(struct mmu_notifier *mn,
* We block for all BOs between start and end to be idle and
* unmap them by move them into system domain again.
*/
-static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
+static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct radeon_mn *rmn = container_of(mn, struct radeon_mn, mn);
struct ttm_operation_ctx ctx = { false, false };
struct interval_tree_node *it;
+ int ret = 0;
/* notification is exclusive, but interval is inclusive */
end -= 1;
- mutex_lock(&rmn->lock);
+ /* TODO we should be able to split locking for interval tree and
+ * the tear down.
+ */
+ if (blockable)
+ mutex_lock(&rmn->lock);
+ else if (!mutex_trylock(&rmn->lock))
+ return -EAGAIN;
it = interval_tree_iter_first(&rmn->objects, start, end);
while (it) {
@@ -138,6 +146,11 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
struct radeon_bo *bo;
long r;
+ if (!blockable) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
+
node = container_of(it, struct radeon_mn_node, it);
it = interval_tree_iter_next(it, start, end);
@@ -166,7 +179,10 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
}
}
+out_unlock:
mutex_unlock(&rmn->lock);
+
+ return ret;
}
static const struct mmu_notifier_ops radeon_mn_ops = {
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index a49a10437c40..61e1953ff921 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -207,6 +207,16 @@ config HID_CORSAIR
- Vengeance K90
- Scimitar PRO RGB
+config HID_COUGAR
+ tristate "Cougar devices"
+ depends on HID
+ help
+ Support for Cougar devices that are not fully compliant with the
+ HID standard.
+
+ Supported devices:
+ - Cougar 500k Gaming Keyboard
+
config HID_PRODIKEYS
tristate "Prodikeys PC-MIDI Keyboard support"
depends on HID && SND
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 511e1cbff768..bd7ac53b75c5 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o
obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
+obj-$(CONFIG_HID_COUGAR) += hid-cougar.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 3942ee61bd1c..3da354af7a0a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type)
usage = parser->local.usage[0];
- if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- hid_err(parser->device, "collection stack overflow\n");
- return -EINVAL;
+ if (parser->collection_stack_ptr == parser->collection_stack_size) {
+ unsigned int *collection_stack;
+ unsigned int new_size = parser->collection_stack_size +
+ HID_COLLECTION_STACK_SIZE;
+
+ collection_stack = krealloc(parser->collection_stack,
+ new_size * sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!collection_stack)
+ return -ENOMEM;
+
+ parser->collection_stack = collection_stack;
+ parser->collection_stack_size = new_size;
}
if (parser->device->maxcollection == parser->device->collection_size) {
@@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid)
break;
}
+ kfree(parser->collection_stack);
vfree(parser);
return 0;
}
@@ -1939,6 +1950,29 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
return hid_match_device(hdev, hdrv) != NULL;
}
+/**
+ * hid_compare_device_paths - check if both devices share the same path
+ * @hdev_a: hid device
+ * @hdev_b: hid device
+ * @separator: char to use as separator
+ *
+ * Check if two devices share the same path up to the last occurrence of
+ * the separator char. Both paths must exist (i.e., zero-length paths
+ * don't match).
+ */
+bool hid_compare_device_paths(struct hid_device *hdev_a,
+ struct hid_device *hdev_b, char separator)
+{
+ int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
+ int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
+
+ if (n1 != n2 || n1 <= 0 || n2 <= 0)
+ return false;
+
+ return !strncmp(hdev_a->phys, hdev_b->phys, n1);
+}
+EXPORT_SYMBOL_GPL(hid_compare_device_paths);
+
static int hid_device_probe(struct device *dev)
{
struct hid_driver *hdrv = to_hid_driver(dev->driver);
diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c
new file mode 100644
index 000000000000..ad2e87de7dc5
--- /dev/null
+++ b/drivers/hid/hid-cougar.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * HID driver for Cougar 500k Gaming Keyboard
+ *
+ * Copyright (c) 2018 Daniel M. Lambea <dmlambea@gmail.com>
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+MODULE_AUTHOR("Daniel M. Lambea <dmlambea@gmail.com>");
+MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard");
+MODULE_LICENSE("GPL");
+MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18");
+
+static int cougar_g6_is_space = 1;
+module_param_named(g6_is_space, cougar_g6_is_space, int, 0600);
+MODULE_PARM_DESC(g6_is_space,
+ "If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)");
+
+
+#define COUGAR_VENDOR_USAGE 0xff00ff00
+
+#define COUGAR_FIELD_CODE 1
+#define COUGAR_FIELD_ACTION 2
+
+#define COUGAR_KEY_G1 0x83
+#define COUGAR_KEY_G2 0x84
+#define COUGAR_KEY_G3 0x85
+#define COUGAR_KEY_G4 0x86
+#define COUGAR_KEY_G5 0x87
+#define COUGAR_KEY_G6 0x78
+#define COUGAR_KEY_FN 0x0d
+#define COUGAR_KEY_MR 0x6f
+#define COUGAR_KEY_M1 0x80
+#define COUGAR_KEY_M2 0x81
+#define COUGAR_KEY_M3 0x82
+#define COUGAR_KEY_LEDS 0x67
+#define COUGAR_KEY_LOCK 0x6e
+
+
+/* Default key mappings. The special key COUGAR_KEY_G6 is defined first
+ * because it is more frequent to use the spacebar rather than any other
+ * special keys. Depending on the value of the parameter 'g6_is_space',
+ * the mapping will be updated in the probe function.
+ */
+static unsigned char cougar_mapping[][2] = {
+ { COUGAR_KEY_G6, KEY_SPACE },
+ { COUGAR_KEY_G1, KEY_F13 },
+ { COUGAR_KEY_G2, KEY_F14 },
+ { COUGAR_KEY_G3, KEY_F15 },
+ { COUGAR_KEY_G4, KEY_F16 },
+ { COUGAR_KEY_G5, KEY_F17 },
+ { COUGAR_KEY_LOCK, KEY_SCREENLOCK },
+/* The following keys are handled by the hardware itself, so no special
+ * treatment is required:
+ { COUGAR_KEY_FN, KEY_RESERVED },
+ { COUGAR_KEY_MR, KEY_RESERVED },
+ { COUGAR_KEY_M1, KEY_RESERVED },
+ { COUGAR_KEY_M2, KEY_RESERVED },
+ { COUGAR_KEY_M3, KEY_RESERVED },
+ { COUGAR_KEY_LEDS, KEY_RESERVED },
+*/
+ { 0, 0 },
+};
+
+struct cougar_shared {
+ struct list_head list;
+ struct kref kref;
+ bool enabled;
+ struct hid_device *dev;
+ struct input_dev *input;
+};
+
+struct cougar {
+ bool special_intf;
+ struct cougar_shared *shared;
+};
+
+static LIST_HEAD(cougar_udev_list);
+static DEFINE_MUTEX(cougar_udev_list_lock);
+
+static void cougar_fix_g6_mapping(struct hid_device *hdev)
+{
+ int i;
+
+ for (i = 0; cougar_mapping[i][0]; i++) {
+ if (cougar_mapping[i][0] == COUGAR_KEY_G6) {
+ cougar_mapping[i][1] =
+ cougar_g6_is_space ? KEY_SPACE : KEY_F18;
+ hid_info(hdev, "G6 mapped to %s\n",
+ cougar_g6_is_space ? "space" : "F18");
+ return;
+ }
+ }
+ hid_warn(hdev, "no mapping defined for G6/spacebar");
+}
+
+/*
+ * Constant-friendly rdesc fixup for mouse interface
+ */
+static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+ unsigned int *rsize)
+{
+ if (rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+ (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) {
+ hid_info(hdev,
+ "usage count exceeds max: fixing up report descriptor\n");
+ rdesc[115] = ((HID_MAX_USAGES-1) & 0xff);
+ rdesc[116] = ((HID_MAX_USAGES-1) >> 8);
+ }
+ return rdesc;
+}
+
+static struct cougar_shared *cougar_get_shared_data(struct hid_device *hdev)
+{
+ struct cougar_shared *shared;
+
+ /* Try to find an already-probed interface from the same device */
+ list_for_each_entry(shared, &cougar_udev_list, list) {
+ if (hid_compare_device_paths(hdev, shared->dev, '/')) {
+ kref_get(&shared->kref);
+ return shared;
+ }
+ }
+ return NULL;
+}
+
+static void cougar_release_shared_data(struct kref *kref)
+{
+ struct cougar_shared *shared = container_of(kref,
+ struct cougar_shared, kref);
+
+ mutex_lock(&cougar_udev_list_lock);
+ list_del(&shared->list);
+ mutex_unlock(&cougar_udev_list_lock);
+
+ kfree(shared);
+}
+
+static void cougar_remove_shared_data(void *resource)
+{
+ struct cougar *cougar = resource;
+
+ if (cougar->shared) {
+ kref_put(&cougar->shared->kref, cougar_release_shared_data);
+ cougar->shared = NULL;
+ }
+}
+
+/*
+ * Bind the device group's shared data to this cougar struct.
+ * If no shared data exists for this group, create and initialize it.
+ */
+static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar)
+{
+ struct cougar_shared *shared;
+ int error = 0;
+
+ mutex_lock(&cougar_udev_list_lock);
+
+ shared = cougar_get_shared_data(hdev);
+ if (!shared) {
+ shared = kzalloc(sizeof(*shared), GFP_KERNEL);
+ if (!shared) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ kref_init(&shared->kref);
+ shared->dev = hdev;
+ list_add_tail(&shared->list, &cougar_udev_list);
+ }
+
+ cougar->shared = shared;
+
+ error = devm_add_action(&hdev->dev, cougar_remove_shared_data, cougar);
+ if (error) {
+ mutex_unlock(&cougar_udev_list_lock);
+ cougar_remove_shared_data(cougar);
+ return error;
+ }
+
+out:
+ mutex_unlock(&cougar_udev_list_lock);
+ return error;
+}
+
+static int cougar_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
+ struct cougar *cougar;
+ struct hid_input *next, *hidinput = NULL;
+ unsigned int connect_mask;
+ int error;
+
+ cougar = devm_kzalloc(&hdev->dev, sizeof(*cougar), GFP_KERNEL);
+ if (!cougar)
+ return -ENOMEM;
+ hid_set_drvdata(hdev, cougar);
+
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "parse failed\n");
+ goto fail;
+ }
+
+ if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+ cougar->special_intf = true;
+ connect_mask = HID_CONNECT_HIDRAW;
+ } else
+ connect_mask = HID_CONNECT_DEFAULT;
+
+ error = hid_hw_start(hdev, connect_mask);
+ if (error) {
+ hid_err(hdev, "hw start failed\n");
+ goto fail;
+ }
+
+ error = cougar_bind_shared_data(hdev, cougar);
+ if (error)
+ goto fail_stop_and_cleanup;
+
+ /* The custom vendor interface will use the hid_input registered
+ * for the keyboard interface, in order to send translated key codes
+ * to it.
+ */
+ if (hdev->collection->usage == HID_GD_KEYBOARD) {
+ cougar_fix_g6_mapping(hdev);
+ list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) {
+ if (hidinput->registered && hidinput->input != NULL) {
+ cougar->shared->input = hidinput->input;
+ cougar->shared->enabled = true;
+ break;
+ }
+ }
+ } else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+ error = hid_hw_open(hdev);
+ if (error)
+ goto fail_stop_and_cleanup;
+ }
+ return 0;
+
+fail_stop_and_cleanup:
+ hid_hw_stop(hdev);
+fail:
+ hid_set_drvdata(hdev, NULL);
+ return error;
+}
+
+/*
+ * Convert events from vendor intf to input key events
+ */
+static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct cougar *cougar;
+ unsigned char code, action;
+ int i;
+
+ cougar = hid_get_drvdata(hdev);
+ if (!cougar->special_intf || !cougar->shared ||
+ !cougar->shared->input || !cougar->shared->enabled)
+ return 0;
+
+ code = data[COUGAR_FIELD_CODE];
+ action = data[COUGAR_FIELD_ACTION];
+ for (i = 0; cougar_mapping[i][0]; i++) {
+ if (code == cougar_mapping[i][0]) {
+ input_event(cougar->shared->input, EV_KEY,
+ cougar_mapping[i][1], action);
+ input_sync(cougar->shared->input);
+ return 0;
+ }
+ }
+ hid_warn(hdev, "unmapped special key code %x: ignoring\n", code);
+ return 0;
+}
+
+static void cougar_remove(struct hid_device *hdev)
+{
+ struct cougar *cougar = hid_get_drvdata(hdev);
+
+ if (cougar) {
+ /* Stop the vendor intf to process more events */
+ if (cougar->shared)
+ cougar->shared->enabled = false;
+ if (cougar->special_intf)
+ hid_hw_close(hdev);
+ }
+ hid_hw_stop(hdev);
+}
+
+static struct hid_device_id cougar_id_table[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
+ USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
+ {}
+};
+MODULE_DEVICE_TABLE(hid, cougar_id_table);
+
+static struct hid_driver cougar_driver = {
+ .name = "cougar",
+ .id_table = cougar_id_table,
+ .report_fixup = cougar_report_fixup,
+ .probe = cougar_probe,
+ .remove = cougar_remove,
+ .raw_event = cougar_raw_event,
+};
+
+module_hid_driver(cougar_driver);
diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
index 803a725785cf..07e26c3567eb 100644
--- a/drivers/hid/hid-elan.c
+++ b/drivers/hid/hid-elan.c
@@ -19,38 +19,49 @@
#include "hid-ids.h"
+#define ELAN_MT_I2C 0x5d
#define ELAN_SINGLE_FINGER 0x81
#define ELAN_MT_FIRST_FINGER 0x82
#define ELAN_MT_SECOND_FINGER 0x83
#define ELAN_INPUT_REPORT_SIZE 8
+#define ELAN_I2C_REPORT_SIZE 32
+#define ELAN_FINGER_DATA_LEN 5
+#define ELAN_MAX_FINGERS 5
+#define ELAN_MAX_PRESSURE 255
+#define ELAN_TP_USB_INTF 1
+
+#define ELAN_FEATURE_REPORT 0x0d
+#define ELAN_FEATURE_SIZE 5
+#define ELAN_PARAM_MAX_X 6
+#define ELAN_PARAM_MAX_Y 7
+#define ELAN_PARAM_RES 8
#define ELAN_MUTE_LED_REPORT 0xBC
#define ELAN_LED_REPORT_SIZE 8
-struct elan_touchpad_settings {
- u8 max_fingers;
- u16 max_x;
- u16 max_y;
- u8 max_area_x;
- u8 max_area_y;
- u8 max_w;
- int usb_bInterfaceNumber;
-};
+#define ELAN_HAS_LED BIT(0)
struct elan_drvdata {
struct input_dev *input;
u8 prev_report[ELAN_INPUT_REPORT_SIZE];
struct led_classdev mute_led;
u8 mute_led_state;
- struct elan_touchpad_settings *settings;
+ u16 max_x;
+ u16 max_y;
+ u16 res_x;
+ u16 res_y;
};
static int is_not_elan_touchpad(struct hid_device *hdev)
{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+ if (hdev->bus == BUS_USB) {
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+ return (intf->altsetting->desc.bInterfaceNumber !=
+ ELAN_TP_USB_INTF);
+ }
- return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
+ return 0;
}
static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -62,12 +73,86 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->report->id == ELAN_SINGLE_FINGER ||
field->report->id == ELAN_MT_FIRST_FINGER ||
- field->report->id == ELAN_MT_SECOND_FINGER)
+ field->report->id == ELAN_MT_SECOND_FINGER ||
+ field->report->id == ELAN_MT_I2C)
return -1;
return 0;
}
+static int elan_get_device_param(struct hid_device *hdev,
+ unsigned char *dmabuf, unsigned char param)
+{
+ int ret;
+
+ dmabuf[0] = ELAN_FEATURE_REPORT;
+ dmabuf[1] = 0x05;
+ dmabuf[2] = 0x03;
+ dmabuf[3] = param;
+ dmabuf[4] = 0x01;
+
+ ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+ ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+ if (ret != ELAN_FEATURE_SIZE) {
+ hid_err(hdev, "Set report error for parm %d: %d\n", param, ret);
+ return ret;
+ }
+
+ ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+ ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+ HID_REQ_GET_REPORT);
+ if (ret != ELAN_FEATURE_SIZE) {
+ hid_err(hdev, "Get report error for parm %d: %d\n", param, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static unsigned int elan_convert_res(char val)
+{
+ /*
+ * (value from firmware) * 10 + 790 = dpi
+ * dpi * 10 / 254 = dots/mm
+ */
+ return (val * 10 + 790) * 10 / 254;
+}
+
+static int elan_get_device_params(struct hid_device *hdev)
+{
+ struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+ unsigned char *dmabuf;
+ int ret;
+
+ dmabuf = kmalloc(ELAN_FEATURE_SIZE, GFP_KERNEL);
+ if (!dmabuf)
+ return -ENOMEM;
+
+ ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_X);
+ if (ret)
+ goto err;
+
+ drvdata->max_x = (dmabuf[4] << 8) | dmabuf[3];
+
+ ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_Y);
+ if (ret)
+ goto err;
+
+ drvdata->max_y = (dmabuf[4] << 8) | dmabuf[3];
+
+ ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_RES);
+ if (ret)
+ goto err;
+
+ drvdata->res_x = elan_convert_res(dmabuf[3]);
+ drvdata->res_y = elan_convert_res(dmabuf[4]);
+
+err:
+ kfree(dmabuf);
+ return ret;
+}
+
static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
int ret;
@@ -77,6 +162,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
if (is_not_elan_touchpad(hdev))
return 0;
+ ret = elan_get_device_params(hdev);
+ if (ret)
+ return ret;
+
input = devm_input_allocate_device(&hdev->dev);
if (!input)
return -ENOMEM;
@@ -90,25 +179,25 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
input->id.version = hdev->version;
input->dev.parent = &hdev->dev;
- input_set_abs_params(input, ABS_MT_POSITION_X, 0,
- drvdata->settings->max_x, 0, 0);
- input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
- drvdata->settings->max_y, 0, 0);
- input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
- drvdata->settings->max_fingers, 0, 0);
- input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
- drvdata->settings->max_w, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, drvdata->max_x,
+ 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, drvdata->max_y,
+ 0, 0);
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE,
+ 0, 0);
__set_bit(BTN_LEFT, input->keybit);
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
- INPUT_MT_POINTER);
+ ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
if (ret) {
hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
return ret;
}
+ input_abs_set_res(input, ABS_X, drvdata->res_x);
+ input_abs_set_res(input, ABS_Y, drvdata->res_y);
+
ret = input_register_device(input);
if (ret) {
hid_err(hdev, "Failed to register elan input device: %d\n",
@@ -126,7 +215,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
unsigned int slot_num)
{
struct input_dev *input = drvdata->input;
- int x, y, w;
+ int x, y, p;
bool active = !!data;
@@ -134,17 +223,17 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
if (active) {
x = ((data[0] & 0xF0) << 4) | data[1];
- y = drvdata->settings->max_y -
+ y = drvdata->max_y -
(((data[0] & 0x07) << 8) | data[2]);
- w = data[4];
+ p = data[4];
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
- input_report_abs(input, ABS_TOOL_WIDTH, w);
+ input_report_abs(input, ABS_MT_PRESSURE, p);
}
}
-static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
+static void elan_usb_report_input(struct elan_drvdata *drvdata, u8 *data)
{
int i;
struct input_dev *input = drvdata->input;
@@ -162,7 +251,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
* byte 5: x8 x7 x6 x5 x4 x3 x2 x1
* byte 6: y8 y7 y6 y5 y4 y3 y2 y1
* byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
- * byte 8: w8 w7 w6 w5 w4 w3 w2 w1
+ * byte 8: p8 p7 p6 p5 p4 p3 p2 p1
*
* packet structure for ELAN_MT_SECOND_FINGER:
*
@@ -171,19 +260,21 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
* byte 3: x8 x7 x6 x5 x4 x3 x2 x1
* byte 4: y8 y7 y6 y5 y4 y3 y2 y1
* byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
- * byte 6: w8 w7 w6 w5 w4 w3 w2 w1
+ * byte 6: p8 p7 p6 p5 p4 p3 p2 p1
* byte 7: 0 0 0 0 0 0 0 0
* byte 8: 0 0 0 0 0 0 0 0
*
* f5-f1: finger touch bits
* L: clickpad button
- * sy / sx: not sure yet, but this looks like rectangular
- * area for finger
- * w: looks like finger width
+ * sy / sx: finger width / height expressed in traces, the total number
+ * of traces can be queried by doing a HID_REQ_SET_REPORT
+ * { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the
+ * returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces.
+ * p: pressure
*/
if (data[0] == ELAN_SINGLE_FINGER) {
- for (i = 0; i < drvdata->settings->max_fingers; i++) {
+ for (i = 0; i < ELAN_MAX_FINGERS; i++) {
if (data[2] & BIT(i + 3))
elan_report_mt_slot(drvdata, data + 3, i);
else
@@ -210,7 +301,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
if (prev_report[0] != ELAN_MT_FIRST_FINGER)
return;
- for (i = 0; i < drvdata->settings->max_fingers; i++) {
+ for (i = 0; i < ELAN_MAX_FINGERS; i++) {
if (prev_report[2] & BIT(i + 3)) {
if (!first) {
first = 1;
@@ -229,6 +320,46 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
input_sync(input);
}
+static void elan_i2c_report_input(struct elan_drvdata *drvdata, u8 *data)
+{
+ struct input_dev *input = drvdata->input;
+ u8 *finger_data;
+ int i;
+
+ /*
+ * Elan MT touchpads in i2c mode send finger data in the same format
+ * as in USB mode, but then with all fingers in a single packet.
+ *
+ * packet structure for ELAN_MT_I2C:
+ *
+ * byte 1: 1 0 0 1 1 1 0 1 // 0x5d
+ * byte 2: f5 f4 f3 f2 f1 0 0 L
+ * byte 3: x12 x11 x10 x9 0? y11 y10 y9
+ * byte 4: x8 x7 x6 x5 x4 x3 x2 x1
+ * byte 5: y8 y7 y6 y5 y4 y3 y2 y1
+ * byte 6: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
+ * byte 7: p8 p7 p6 p5 p4 p3 p2 p1
+ * byte 8-12: Same as byte 3-7 for second finger down
+ * byte 13-17: Same as byte 3-7 for third finger down
+ * byte 18-22: Same as byte 3-7 for fourth finger down
+ * byte 23-27: Same as byte 3-7 for fifth finger down
+ */
+
+ finger_data = data + 2;
+ for (i = 0; i < ELAN_MAX_FINGERS; i++) {
+ if (data[1] & BIT(i + 3)) {
+ elan_report_mt_slot(drvdata, finger_data, i);
+ finger_data += ELAN_FINGER_DATA_LEN;
+ } else {
+ elan_report_mt_slot(drvdata, NULL, i);
+ }
+ }
+
+ input_report_key(input, BTN_LEFT, data[1] & 0x01);
+ input_mt_sync_frame(input);
+ input_sync(input);
+}
+
static int elan_raw_event(struct hid_device *hdev,
struct hid_report *report, u8 *data, int size)
{
@@ -241,11 +372,16 @@ static int elan_raw_event(struct hid_device *hdev,
data[0] == ELAN_MT_FIRST_FINGER ||
data[0] == ELAN_MT_SECOND_FINGER) {
if (size == ELAN_INPUT_REPORT_SIZE) {
- elan_report_input(drvdata, data);
+ elan_usb_report_input(drvdata, data);
return 1;
}
}
+ if (data[0] == ELAN_MT_I2C && size == ELAN_I2C_REPORT_SIZE) {
+ elan_i2c_report_input(drvdata, data);
+ return 1;
+ }
+
return 0;
}
@@ -343,7 +479,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (!drvdata)
return -ENOMEM;
- drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
hid_set_drvdata(hdev, drvdata);
ret = hid_parse(hdev);
@@ -371,9 +506,11 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret)
goto err;
- ret = elan_init_mute_led(hdev);
- if (ret)
- goto err;
+ if (id->driver_data & ELAN_HAS_LED) {
+ ret = elan_init_mute_led(hdev);
+ if (ret)
+ goto err;
+ }
return 0;
err:
@@ -386,22 +523,14 @@ static void elan_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
}
-static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
- .max_fingers = 5,
- .max_x = 2930,
- .max_y = 1250,
- .max_area_x = 15,
- .max_area_y = 15,
- .max_w = 255,
- .usb_bInterfaceNumber = 1,
-};
-
static const struct hid_device_id elan_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2),
+ .driver_data = ELAN_HAS_LED },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
- (kernel_ulong_t)&hp_x2_10_touchpad_data},
+ .driver_data = ELAN_HAS_LED },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) },
{ }
};
-
MODULE_DEVICE_TABLE(hid, elan_devices);
static struct hid_driver elan_driver = {
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c7981ddd8776..79bdf0c7e351 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -369,6 +369,8 @@
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
#define USB_VENDOR_ID_ELAN 0x04f3
+#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
+#define USB_DEVICE_ID_HP_X2 0x074d
#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
#define USB_VENDOR_ID_ELECOM 0x056e
@@ -1001,6 +1003,9 @@
#define USB_VENDOR_ID_SINO_LITE 0x1345
#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
+#define USB_VENDOR_ID_SOLID_YEAR 0x060b
+#define USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD 0x500a
+
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index ab93dd5927c3..4e94ea3e280a 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1550,6 +1550,9 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid,
case HID_GD_WIRELESS_RADIO_CTLS:
suffix = "Wireless Radio Control";
break;
+ case HID_GD_SYSTEM_MULTIAXIS:
+ suffix = "System Multi Axis";
+ break;
default:
break;
}
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 96e7d3231d2f..72d983626afd 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -22,12 +22,13 @@
#include "hid-ids.h"
-#define MS_HIDINPUT 0x01
-#define MS_ERGONOMY 0x02
-#define MS_PRESENTER 0x04
-#define MS_RDESC 0x08
-#define MS_NOGET 0x10
-#define MS_DUPLICATE_USAGES 0x20
+#define MS_HIDINPUT BIT(0)
+#define MS_ERGONOMY BIT(1)
+#define MS_PRESENTER BIT(2)
+#define MS_RDESC BIT(3)
+#define MS_NOGET BIT(4)
+#define MS_DUPLICATE_USAGES BIT(5)
+#define MS_SURFACE_DIAL BIT(6)
static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
@@ -130,6 +131,30 @@ static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
return 1;
}
+static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
+{
+ switch (usage->hid & HID_USAGE_PAGE) {
+ case 0xff070000:
+ /* fall-through */
+ case HID_UP_DIGITIZER:
+ /* ignore those axis */
+ return -1;
+ case HID_UP_GENDESK:
+ switch (usage->hid) {
+ case HID_GD_X:
+ /* fall-through */
+ case HID_GD_Y:
+ /* fall-through */
+ case HID_GD_RFKILL_BTN:
+ /* ignore those axis */
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
@@ -146,6 +171,13 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
ms_presenter_8k_quirk(hi, usage, bit, max))
return 1;
+ if (quirks & MS_SURFACE_DIAL) {
+ int ret = ms_surface_dial_quirk(hi, field, usage, bit, max);
+
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -229,6 +261,9 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (quirks & MS_NOGET)
hdev->quirks |= HID_QUIRK_NOGET;
+ if (quirks & MS_SURFACE_DIAL)
+ hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
@@ -281,6 +316,8 @@ static const struct hid_device_id ms_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
+ .driver_data = MS_SURFACE_DIAL },
{ }
};
MODULE_DEVICE_TABLE(hid, ms_devices);
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 45968f7970f8..40fbb7c52723 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -28,14 +28,11 @@
*/
/*
- * This driver is regularly tested thanks to the tool hid-test[1].
- * This tool relies on hid-replay[2] and a database of hid devices[3].
+ * This driver is regularly tested thanks to the test suite in hid-tools[1].
* Please run these regression tests before patching this module so that
* your patch won't break existing known devices.
*
- * [1] https://github.com/bentiss/hid-test
- * [2] https://github.com/bentiss/hid-replay
- * [3] https://github.com/bentiss/hid-devices
+ * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
*/
#include <linux/device.h>
@@ -90,13 +87,54 @@ enum latency_mode {
#define MT_IO_FLAGS_ACTIVE_SLOTS 1
#define MT_IO_FLAGS_PENDING_SLOTS 2
-struct mt_slot {
- __s32 x, y, cx, cy, p, w, h, a;
- __s32 contactid; /* the device ContactID assigned to this slot */
- bool touch_state; /* is the touch valid? */
- bool inrange_state; /* is the finger in proximity of the sensor? */
- bool confidence_state; /* is the touch made by a finger? */
- bool has_azimuth; /* the contact reports azimuth */
+static const bool mtrue = true; /* default for true */
+static const bool mfalse; /* default for false */
+static const __s32 mzero; /* default for 0 */
+
+#define DEFAULT_TRUE ((void *)&mtrue)
+#define DEFAULT_FALSE ((void *)&mfalse)
+#define DEFAULT_ZERO ((void *)&mzero)
+
+struct mt_usages {
+ struct list_head list;
+ __s32 *x, *y, *cx, *cy, *p, *w, *h, *a;
+ __s32 *contactid; /* the device ContactID assigned to this slot */
+ bool *tip_state; /* is the touch valid? */
+ bool *inrange_state; /* is the finger in proximity of the sensor? */
+ bool *confidence_state; /* is the touch made by a finger? */
+};
+
+struct mt_application {
+ struct list_head list;
+ unsigned int application;
+ struct list_head mt_usages; /* mt usages list */
+
+ __s32 quirks;
+
+ __s32 *scantime; /* scantime reported */
+ __s32 scantime_logical_max; /* max value for raw scantime */
+
+ __s32 *raw_cc; /* contact count in the report */
+ int left_button_state; /* left button state */
+ unsigned int mt_flags; /* flags to pass to input-mt */
+
+ unsigned long *pending_palm_slots; /* slots where we reported palm
+ * and need to release */
+
+ __u8 num_received; /* how many contacts we received */
+ __u8 num_expected; /* expected last contact index */
+ __u8 buttons_count; /* number of physical buttons per touchpad */
+ __u8 touches_by_report; /* how many touches are present in one report:
+ * 1 means we should use a serial protocol
+ * > 1 means hybrid (multitouch) protocol
+ */
+
+ __s32 dev_time; /* the scan time provided by the device */
+ unsigned long jiffies; /* the frame's jiffies */
+ int timestamp; /* the timestamp to be sent */
+ int prev_scantime; /* scantime reported previously */
+
+ bool have_contact_count;
};
struct mt_class {
@@ -111,46 +149,30 @@ struct mt_class {
bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
};
-struct mt_fields {
- unsigned usages[HID_MAX_FIELDS];
- unsigned int length;
+struct mt_report_data {
+ struct list_head list;
+ struct hid_report *report;
+ struct mt_application *application;
+ bool is_mt_collection;
};
struct mt_device {
- struct mt_slot curdata; /* placeholder of incoming data */
struct mt_class mtclass; /* our mt device class */
struct timer_list release_timer; /* to release sticky fingers */
struct hid_device *hdev; /* hid_device we're attached to */
- struct mt_fields *fields; /* temporary placeholder for storing the
- multitouch fields */
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
- int cc_index; /* contact count field index in the report */
- int cc_value_index; /* contact count value index in the field */
- int scantime_index; /* scantime field index in the report */
- int scantime_val_index; /* scantime value index in the field */
- int prev_scantime; /* scantime reported in the previous packet */
- int left_button_state; /* left button state */
- unsigned last_slot_field; /* the last field of a slot */
- unsigned mt_report_id; /* the report ID of the multitouch device */
__u8 inputmode_value; /* InputMode HID feature value */
- __u8 num_received; /* how many contacts we received */
- __u8 num_expected; /* expected last contact index */
__u8 maxcontacts;
- __u8 touches_by_report; /* how many touches are present in one report:
- * 1 means we should use a serial protocol
- * > 1 means hybrid (multitouch) protocol */
- __u8 buttons_count; /* number of physical buttons per touchpad */
bool is_buttonpad; /* is this device a button pad? */
bool serial_maybe; /* need to check for serial protocol */
- bool curvalid; /* is the current contact valid? */
- unsigned mt_flags; /* flags to pass to input-mt */
- __s32 dev_time; /* the scan time provided by the device */
- unsigned long jiffies; /* the frame's jiffies */
- int timestamp; /* the timestamp to be sent */
+
+ struct list_head applications;
+ struct list_head reports;
};
-static void mt_post_parse_default_settings(struct mt_device *td);
-static void mt_post_parse(struct mt_device *td);
+static void mt_post_parse_default_settings(struct mt_device *td,
+ struct mt_application *app);
+static void mt_post_parse(struct mt_device *td, struct mt_application *app);
/* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001
@@ -203,15 +225,16 @@ static void mt_post_parse(struct mt_device *td);
* to a valid contact that was just read.
*/
-static int cypress_compute_slot(struct mt_device *td)
+static int cypress_compute_slot(struct mt_application *application,
+ struct mt_usages *slot)
{
- if (td->curdata.contactid != 0 || td->num_received == 0)
- return td->curdata.contactid;
+ if (*slot->contactid != 0 || application->num_received == 0)
+ return *slot->contactid;
else
return -1;
}
-static struct mt_class mt_classes[] = {
+static const struct mt_class mt_classes[] = {
{ .name = MT_CLS_DEFAULT,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_CONTACT_CNT_ACCURATE },
@@ -353,6 +376,7 @@ static ssize_t mt_set_quirks(struct device *dev,
{
struct hid_device *hdev = to_hid_device(dev);
struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_application *application;
unsigned long val;
@@ -361,8 +385,11 @@ static ssize_t mt_set_quirks(struct device *dev,
td->mtclass.quirks = val;
- if (td->cc_index < 0)
- td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+ list_for_each_entry(application, &td->applications, list) {
+ application->quirks = val;
+ if (!application->have_contact_count)
+ application->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+ }
return count;
}
@@ -457,41 +484,199 @@ static void set_abs(struct input_dev *input, unsigned int code,
input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
}
-static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
- struct hid_input *hi)
+static struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
+ struct mt_application *application)
+{
+ struct mt_usages *usage;
+
+ usage = devm_kzalloc(&hdev->dev, sizeof(*usage), GFP_KERNEL);
+ if (!usage)
+ return NULL;
+
+ /* set some defaults so we do not need to check for null pointers */
+ usage->x = DEFAULT_ZERO;
+ usage->y = DEFAULT_ZERO;
+ usage->cx = DEFAULT_ZERO;
+ usage->cy = DEFAULT_ZERO;
+ usage->p = DEFAULT_ZERO;
+ usage->w = DEFAULT_ZERO;
+ usage->h = DEFAULT_ZERO;
+ usage->a = DEFAULT_ZERO;
+ usage->contactid = DEFAULT_ZERO;
+ usage->tip_state = DEFAULT_FALSE;
+ usage->inrange_state = DEFAULT_FALSE;
+ usage->confidence_state = DEFAULT_TRUE;
+
+ list_add_tail(&usage->list, &application->mt_usages);
+
+ return usage;
+}
+
+static struct mt_application *mt_allocate_application(struct mt_device *td,
+ unsigned int application)
+{
+ struct mt_application *mt_application;
+
+ mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
+ GFP_KERNEL);
+ if (!mt_application)
+ return NULL;
+
+ mt_application->application = application;
+ INIT_LIST_HEAD(&mt_application->mt_usages);
+
+ if (application == HID_DG_TOUCHSCREEN)
+ mt_application->mt_flags |= INPUT_MT_DIRECT;
+
+ /*
+ * Model touchscreens providing buttons as touchpads.
+ */
+ if (application == HID_DG_TOUCHPAD) {
+ mt_application->mt_flags |= INPUT_MT_POINTER;
+ td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
+ }
+
+ mt_application->scantime = DEFAULT_ZERO;
+ mt_application->raw_cc = DEFAULT_ZERO;
+ mt_application->quirks = td->mtclass.quirks;
+
+ list_add_tail(&mt_application->list, &td->applications);
+
+ return mt_application;
+}
+
+static struct mt_application *mt_find_application(struct mt_device *td,
+ unsigned int application)
+{
+ struct mt_application *tmp, *mt_application = NULL;
+
+ list_for_each_entry(tmp, &td->applications, list) {
+ if (application == tmp->application) {
+ mt_application = tmp;
+ break;
+ }
+ }
+
+ if (!mt_application)
+ mt_application = mt_allocate_application(td, application);
+
+ return mt_application;
+}
+
+static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
+ struct hid_report *report)
+{
+ struct mt_report_data *rdata;
+ struct hid_field *field;
+ int r, n;
+
+ rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL);
+ if (!rdata)
+ return NULL;
+
+ rdata->report = report;
+ rdata->application = mt_find_application(td, report->application);
+
+ if (!rdata->application) {
+ devm_kfree(&td->hdev->dev, rdata);
+ return NULL;
+ }
+
+ for (r = 0; r < report->maxfield; r++) {
+ field = report->field[r];
+
+ if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
+ continue;
+
+ for (n = 0; n < field->report_count; n++) {
+ if (field->usage[n].hid == HID_DG_CONTACTID)
+ rdata->is_mt_collection = true;
+ }
+ }
+
+ list_add_tail(&rdata->list, &td->reports);
+
+ return rdata;
+}
+
+static struct mt_report_data *mt_find_report_data(struct mt_device *td,
+ struct hid_report *report)
{
- struct mt_fields *f = td->fields;
+ struct mt_report_data *tmp, *rdata = NULL;
- if (f->length >= HID_MAX_FIELDS)
+ list_for_each_entry(tmp, &td->reports, list) {
+ if (report == tmp->report) {
+ rdata = tmp;
+ break;
+ }
+ }
+
+ if (!rdata)
+ rdata = mt_allocate_report_data(td, report);
+
+ return rdata;
+}
+
+static void mt_store_field(struct hid_device *hdev,
+ struct mt_application *application,
+ __s32 *value,
+ size_t offset)
+{
+ struct mt_usages *usage;
+ __s32 **target;
+
+ if (list_empty(&application->mt_usages))
+ usage = mt_allocate_usage(hdev, application);
+ else
+ usage = list_last_entry(&application->mt_usages,
+ struct mt_usages,
+ list);
+
+ if (!usage)
return;
- f->usages[f->length++] = usage->hid;
+ target = (__s32 **)((char *)usage + offset);
+
+ /* the value has already been filled, create a new slot */
+ if (*target != DEFAULT_TRUE &&
+ *target != DEFAULT_FALSE &&
+ *target != DEFAULT_ZERO) {
+ usage = mt_allocate_usage(hdev, application);
+ if (!usage)
+ return;
+
+ target = (__s32 **)((char *)usage + offset);
+ }
+
+ *target = value;
}
+#define MT_STORE_FIELD(__name) \
+ mt_store_field(hdev, app, \
+ &field->value[usage->usage_index], \
+ offsetof(struct mt_usages, __name))
+
static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
- unsigned long **bit, int *max)
+ unsigned long **bit, int *max, struct mt_application *app)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
int code;
struct hid_usage *prev_usage = NULL;
- if (field->application == HID_DG_TOUCHSCREEN)
- td->mt_flags |= INPUT_MT_DIRECT;
-
/*
* Model touchscreens providing buttons as touchpads.
*/
- if (field->application == HID_DG_TOUCHPAD ||
+ if (field->application == HID_DG_TOUCHSCREEN &&
(usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
- td->mt_flags |= INPUT_MT_POINTER;
+ app->mt_flags |= INPUT_MT_POINTER;
td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
}
/* count the buttons on touchpads */
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
- td->buttons_count++;
+ app->buttons_count++;
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];
@@ -502,33 +687,40 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
switch (usage->hid) {
case HID_GD_X:
if (prev_usage && (prev_usage->hid == usage->hid)) {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOOL_X);
- set_abs(hi->input, ABS_MT_TOOL_X, field,
- cls->sn_move);
+ code = ABS_MT_TOOL_X;
+ MT_STORE_FIELD(cx);
} else {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_POSITION_X);
- set_abs(hi->input, ABS_MT_POSITION_X, field,
- cls->sn_move);
+ code = ABS_MT_POSITION_X;
+ MT_STORE_FIELD(x);
+ }
+
+ set_abs(hi->input, code, field, cls->sn_move);
+
+ /*
+ * A system multi-axis that exports X and Y has a high
+ * chance of being used directly on a surface
+ */
+ if (field->application == HID_GD_SYSTEM_MULTIAXIS) {
+ __set_bit(INPUT_PROP_DIRECT,
+ hi->input->propbit);
+ input_set_abs_params(hi->input,
+ ABS_MT_TOOL_TYPE,
+ MT_TOOL_DIAL,
+ MT_TOOL_DIAL, 0, 0);
}
- mt_store_field(usage, td, hi);
return 1;
case HID_GD_Y:
if (prev_usage && (prev_usage->hid == usage->hid)) {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOOL_Y);
- set_abs(hi->input, ABS_MT_TOOL_Y, field,
- cls->sn_move);
+ code = ABS_MT_TOOL_Y;
+ MT_STORE_FIELD(cy);
} else {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_POSITION_Y);
- set_abs(hi->input, ABS_MT_POSITION_Y, field,
- cls->sn_move);
+ code = ABS_MT_POSITION_Y;
+ MT_STORE_FIELD(y);
}
- mt_store_field(usage, td, hi);
+ set_abs(hi->input, code, field, cls->sn_move);
+
return 1;
}
return 0;
@@ -536,43 +728,45 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_DIGITIZER:
switch (usage->hid) {
case HID_DG_INRANGE:
- if (cls->quirks & MT_QUIRK_HOVERING) {
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_DISTANCE);
+ if (app->quirks & MT_QUIRK_HOVERING) {
input_set_abs_params(hi->input,
ABS_MT_DISTANCE, 0, 1, 0, 0);
}
- mt_store_field(usage, td, hi);
+ MT_STORE_FIELD(inrange_state);
return 1;
case HID_DG_CONFIDENCE:
if ((cls->name == MT_CLS_WIN_8 ||
cls->name == MT_CLS_WIN_8_DUAL) &&
- field->application == HID_DG_TOUCHPAD)
- cls->quirks |= MT_QUIRK_CONFIDENCE;
- mt_store_field(usage, td, hi);
+ (field->application == HID_DG_TOUCHPAD ||
+ field->application == HID_DG_TOUCHSCREEN))
+ app->quirks |= MT_QUIRK_CONFIDENCE;
+
+ if (app->quirks & MT_QUIRK_CONFIDENCE)
+ input_set_abs_params(hi->input,
+ ABS_MT_TOOL_TYPE,
+ MT_TOOL_FINGER,
+ MT_TOOL_PALM, 0, 0);
+
+ MT_STORE_FIELD(confidence_state);
return 1;
case HID_DG_TIPSWITCH:
- hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
- input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
- mt_store_field(usage, td, hi);
+ if (field->application != HID_GD_SYSTEM_MULTIAXIS)
+ input_set_capability(hi->input,
+ EV_KEY, BTN_TOUCH);
+ MT_STORE_FIELD(tip_state);
return 1;
case HID_DG_CONTACTID:
- mt_store_field(usage, td, hi);
- td->touches_by_report++;
- td->mt_report_id = field->report->id;
+ MT_STORE_FIELD(contactid);
+ app->touches_by_report++;
return 1;
case HID_DG_WIDTH:
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOUCH_MAJOR);
- if (!(cls->quirks & MT_QUIRK_NO_AREA))
+ if (!(app->quirks & MT_QUIRK_NO_AREA))
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
cls->sn_width);
- mt_store_field(usage, td, hi);
+ MT_STORE_FIELD(w);
return 1;
case HID_DG_HEIGHT:
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_TOUCH_MINOR);
- if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
+ if (!(app->quirks & MT_QUIRK_NO_AREA)) {
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
cls->sn_height);
@@ -585,41 +779,23 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
input_set_abs_params(hi->input,
ABS_MT_ORIENTATION, 0, 1, 0, 0);
}
- mt_store_field(usage, td, hi);
+ MT_STORE_FIELD(h);
return 1;
case HID_DG_TIPPRESSURE:
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_PRESSURE);
set_abs(hi->input, ABS_MT_PRESSURE, field,
cls->sn_pressure);
- mt_store_field(usage, td, hi);
+ MT_STORE_FIELD(p);
return 1;
case HID_DG_SCANTIME:
- hid_map_usage(hi, usage, bit, max,
- EV_MSC, MSC_TIMESTAMP);
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
- /* Ignore if indexes are out of bounds. */
- if (field->index >= field->report->maxfield ||
- usage->usage_index >= field->report_count)
- return 1;
- td->scantime_index = field->index;
- td->scantime_val_index = usage->usage_index;
- /*
- * We don't set td->last_slot_field as scan time is
- * global to the report.
- */
+ app->scantime = &field->value[usage->usage_index];
+ app->scantime_logical_max = field->logical_maximum;
return 1;
case HID_DG_CONTACTCOUNT:
- /* Ignore if indexes are out of bounds. */
- if (field->index >= field->report->maxfield ||
- usage->usage_index >= field->report_count)
- return 1;
- td->cc_index = field->index;
- td->cc_value_index = usage->usage_index;
+ app->have_contact_count = true;
+ app->raw_cc = &field->value[usage->usage_index];
return 1;
case HID_DG_AZIMUTH:
- hid_map_usage(hi, usage, bit, max,
- EV_ABS, ABS_MT_ORIENTATION);
/*
* Azimuth has the range of [0, MAX) representing a full
* revolution. Set ABS_MT_ORIENTATION to a quarter of
@@ -630,11 +806,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
field->logical_maximum / 4,
cls->sn_move ?
field->logical_maximum / cls->sn_move : 0, 0);
- mt_store_field(usage, td, hi);
+ MT_STORE_FIELD(a);
return 1;
case HID_DG_CONTACTMAX:
- /* we don't set td->last_slot_field as contactcount and
- * contact max are global to the report */
+ /* contact max are global to the report */
return -1;
case HID_DG_TOUCH:
/* Legacy devices use TIPSWITCH and not TOUCH.
@@ -650,10 +825,14 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* MS PTP spec says that external buttons left and right have
* usages 2 and 3.
*/
- if ((cls->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+ if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
field->application == HID_DG_TOUCHPAD &&
(usage->hid & HID_USAGE) > 1)
code--;
+
+ if (field->application == HID_GD_SYSTEM_MULTIAXIS)
+ code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
+
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
input_set_capability(hi->input, EV_KEY, code);
return 1;
@@ -666,110 +845,68 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0;
}
-static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
+static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
+ struct mt_usages *slot,
+ struct input_dev *input)
{
- __s32 quirks = td->mtclass.quirks;
+ __s32 quirks = app->quirks;
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
- return td->curdata.contactid;
+ return *slot->contactid;
if (quirks & MT_QUIRK_CYPRESS)
- return cypress_compute_slot(td);
+ return cypress_compute_slot(app, slot);
if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
- return td->num_received;
+ return app->num_received;
if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
- return td->curdata.contactid - 1;
+ return *slot->contactid - 1;
- return input_mt_get_slot_by_key(input, td->curdata.contactid);
+ return input_mt_get_slot_by_key(input, *slot->contactid);
}
-/*
- * this function is called when a whole contact has been processed,
- * so that it can assign it to a slot and store the data there
- */
-static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
+static void mt_release_pending_palms(struct mt_device *td,
+ struct mt_application *app,
+ struct input_dev *input)
{
- if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
- td->num_received >= td->num_expected)
- return;
-
- if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
- int active;
- int slotnum = mt_compute_slot(td, input);
- struct mt_slot *s = &td->curdata;
- struct input_mt *mt = input->mt;
+ int slotnum;
+ bool need_sync = false;
- if (slotnum < 0 || slotnum >= td->maxcontacts)
- return;
-
- if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
- struct input_mt_slot *slot = &mt->slots[slotnum];
- if (input_mt_is_active(slot) &&
- input_mt_is_used(mt, slot))
- return;
- }
-
- if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
- s->confidence_state = true;
- active = (s->touch_state || s->inrange_state) &&
- s->confidence_state;
+ for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) {
+ clear_bit(slotnum, app->pending_palm_slots);
input_mt_slot(input, slotnum);
- input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
- if (active) {
- /* this finger is in proximity of the sensor */
- int wide = (s->w > s->h);
- int major = max(s->w, s->h);
- int minor = min(s->w, s->h);
- int orientation = wide;
+ input_mt_report_slot_state(input, MT_TOOL_PALM, false);
- if (s->has_azimuth)
- orientation = s->a;
-
- /*
- * divided by two to match visual scale of touch
- * for devices with this quirk
- */
- if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
- major = major >> 1;
- minor = minor >> 1;
- }
-
- input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
- input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
- input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
- input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
- input_event(input, EV_ABS, ABS_MT_DISTANCE,
- !s->touch_state);
- input_event(input, EV_ABS, ABS_MT_ORIENTATION,
- orientation);
- input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
- input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
- input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
-
- set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
- }
+ need_sync = true;
}
- td->num_received++;
+ if (need_sync) {
+ input_mt_sync_frame(input);
+ input_sync(input);
+ }
}
/*
* this function is called when a whole packet has been received and processed,
* so that it can decide what to send to the input layer.
*/
-static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
+ struct input_dev *input)
{
- if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
- input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
+ if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
+ input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
input_mt_sync_frame(input);
- input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
+ input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
input_sync(input);
- td->num_received = 0;
- td->left_button_state = 0;
+
+ mt_release_pending_palms(td, app, input);
+
+ app->num_received = 0;
+ app->left_button_state = 0;
+
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
else
@@ -777,17 +914,15 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
}
-static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
- __s32 value)
+static int mt_compute_timestamp(struct mt_application *app, __s32 value)
{
- long delta = value - td->dev_time;
- unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
+ long delta = value - app->prev_scantime;
+ unsigned long jdelta = jiffies_to_usecs(jiffies - app->jiffies);
- td->jiffies = jiffies;
- td->dev_time = value;
+ app->jiffies = jiffies;
if (delta < 0)
- delta += field->logical_maximum;
+ delta += app->scantime_logical_max;
/* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
delta *= 100;
@@ -796,7 +931,7 @@ static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
/* No data received for a while, resync the timestamp. */
return 0;
else
- return td->timestamp + delta;
+ return app->timestamp + delta;
}
static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
@@ -809,63 +944,90 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
return 1;
}
-static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
- struct hid_usage *usage, __s32 value,
- bool first_packet)
+static int mt_process_slot(struct mt_device *td, struct input_dev *input,
+ struct mt_application *app,
+ struct mt_usages *slot)
{
- struct mt_device *td = hid_get_drvdata(hid);
- __s32 quirks = td->mtclass.quirks;
- struct input_dev *input = field->hidinput->input;
+ struct input_mt *mt = input->mt;
+ __s32 quirks = app->quirks;
+ bool valid = true;
+ bool confidence_state = true;
+ bool inrange_state = false;
+ int active;
+ int slotnum;
+ int tool = MT_TOOL_FINGER;
+
+ if (!slot)
+ return -EINVAL;
- if (hid->claimed & HID_CLAIMED_INPUT) {
- switch (usage->hid) {
- case HID_DG_INRANGE:
- if (quirks & MT_QUIRK_VALID_IS_INRANGE)
- td->curvalid = value;
- if (quirks & MT_QUIRK_HOVERING)
- td->curdata.inrange_state = value;
- break;
- case HID_DG_TIPSWITCH:
- if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
- td->curvalid = value;
- td->curdata.touch_state = value;
- break;
- case HID_DG_CONFIDENCE:
- if (quirks & MT_QUIRK_CONFIDENCE)
- td->curdata.confidence_state = value;
- if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
- td->curvalid = value;
- break;
- case HID_DG_CONTACTID:
- td->curdata.contactid = value;
- break;
- case HID_DG_TIPPRESSURE:
- td->curdata.p = value;
- break;
- case HID_GD_X:
- if (usage->code == ABS_MT_TOOL_X)
- td->curdata.cx = value;
- else
- td->curdata.x = value;
- break;
- case HID_GD_Y:
- if (usage->code == ABS_MT_TOOL_Y)
- td->curdata.cy = value;
- else
- td->curdata.y = value;
- break;
- case HID_DG_WIDTH:
- td->curdata.w = value;
- break;
- case HID_DG_HEIGHT:
- td->curdata.h = value;
- break;
- case HID_DG_SCANTIME:
- td->timestamp = mt_compute_timestamp(td, field, value);
- break;
- case HID_DG_CONTACTCOUNT:
- break;
- case HID_DG_AZIMUTH:
+ if ((quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
+ app->num_received >= app->num_expected)
+ return -EAGAIN;
+
+ if (!(quirks & MT_QUIRK_ALWAYS_VALID)) {
+ if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+ valid = *slot->inrange_state;
+ if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+ valid = *slot->tip_state;
+ if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
+ valid = *slot->confidence_state;
+
+ if (!valid)
+ return 0;
+ }
+
+ slotnum = mt_compute_slot(td, app, slot, input);
+ if (slotnum < 0 || slotnum >= td->maxcontacts)
+ return 0;
+
+ if ((quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+ struct input_mt_slot *i_slot = &mt->slots[slotnum];
+
+ if (input_mt_is_active(i_slot) &&
+ input_mt_is_used(mt, i_slot))
+ return -EAGAIN;
+ }
+
+ if (quirks & MT_QUIRK_CONFIDENCE)
+ confidence_state = *slot->confidence_state;
+
+ if (quirks & MT_QUIRK_HOVERING)
+ inrange_state = *slot->inrange_state;
+
+ active = *slot->tip_state || inrange_state;
+
+ if (app->application == HID_GD_SYSTEM_MULTIAXIS)
+ tool = MT_TOOL_DIAL;
+ else if (unlikely(!confidence_state)) {
+ tool = MT_TOOL_PALM;
+ if (!active &&
+ input_mt_is_active(&mt->slots[slotnum])) {
+ /*
+ * The non-confidence was reported for
+ * previously valid contact that is also no
+ * longer valid. We can't simply report
+ * lift-off as userspace will not be aware
+ * of non-confidence, so we need to split
+ * it into 2 events: active MT_TOOL_PALM
+ * and a separate liftoff.
+ */
+ active = true;
+ set_bit(slotnum, app->pending_palm_slots);
+ }
+ }
+
+ input_mt_slot(input, slotnum);
+ input_mt_report_slot_state(input, tool, active);
+ if (active) {
+ /* this finger is in proximity of the sensor */
+ int wide = (*slot->w > *slot->h);
+ int major = max(*slot->w, *slot->h);
+ int minor = min(*slot->w, *slot->h);
+ int orientation = wide;
+ int max_azimuth;
+ int azimuth;
+
+ if (slot->a != DEFAULT_ZERO) {
/*
* Azimuth is counter-clockwise and ranges from [0, MAX)
* (a full revolution). Convert it to clockwise ranging
@@ -876,77 +1038,107 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
* out of range to [-MAX/2, MAX/2] to report an upside
* down ellipsis.
*/
- if (value > field->logical_maximum / 2)
- value -= field->logical_maximum;
- td->curdata.a = -value;
- td->curdata.has_azimuth = true;
- break;
- case HID_DG_TOUCH:
- /* do nothing */
- break;
+ azimuth = *slot->a;
+ max_azimuth = input_abs_get_max(input,
+ ABS_MT_ORIENTATION);
+ if (azimuth > max_azimuth * 2)
+ azimuth -= max_azimuth * 4;
+ orientation = -azimuth;
+ }
- default:
+ if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
/*
- * For Win8 PTP touchpads we should only look at
- * non finger/touch events in the first_packet of
- * a (possible) multi-packet frame.
+ * divided by two to match visual scale of touch
+ * for devices with this quirk
*/
- if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
- !first_packet)
- return;
+ major = major >> 1;
+ minor = minor >> 1;
+ }
- /*
- * For Win8 PTP touchpads we map both the clickpad click
- * and any "external" left buttons to BTN_LEFT if a
- * device claims to have both we need to report 1 for
- * BTN_LEFT if either is pressed, so we or all values
- * together and report the result in mt_sync_frame().
- */
- if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
- usage->type == EV_KEY && usage->code == BTN_LEFT) {
- td->left_button_state |= value;
- return;
- }
+ input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
+ input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
+ input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
+ input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
+ input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
+ input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
+ input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p);
+ input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+ input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+
+ set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
+ }
- if (usage->type)
- input_event(input, usage->type, usage->code,
- value);
+ return 0;
+}
+
+static void mt_process_mt_event(struct hid_device *hid,
+ struct mt_application *app,
+ struct hid_field *field,
+ struct hid_usage *usage,
+ __s32 value,
+ bool first_packet)
+{
+ __s32 quirks = app->quirks;
+ struct input_dev *input = field->hidinput->input;
+
+ if (!usage->type || !(hid->claimed & HID_CLAIMED_INPUT))
+ return;
+
+ if (quirks & MT_QUIRK_WIN8_PTP_BUTTONS) {
+
+ /*
+ * For Win8 PTP touchpads we should only look at
+ * non finger/touch events in the first_packet of a
+ * (possible) multi-packet frame.
+ */
+ if (!first_packet)
return;
- }
- if (usage->usage_index + 1 == field->report_count) {
- /* we only take into account the last report. */
- if (usage->hid == td->last_slot_field)
- mt_complete_slot(td, field->hidinput->input);
+ /*
+ * For Win8 PTP touchpads we map both the clickpad click
+ * and any "external" left buttons to BTN_LEFT if a
+ * device claims to have both we need to report 1 for
+ * BTN_LEFT if either is pressed, so we or all values
+ * together and report the result in mt_sync_frame().
+ */
+ if (usage->type == EV_KEY && usage->code == BTN_LEFT) {
+ app->left_button_state |= value;
+ return;
}
-
}
+
+ input_event(input, usage->type, usage->code, value);
}
-static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
+static void mt_touch_report(struct hid_device *hid,
+ struct mt_report_data *rdata)
{
struct mt_device *td = hid_get_drvdata(hid);
+ struct hid_report *report = rdata->report;
+ struct mt_application *app = rdata->application;
struct hid_field *field;
+ struct input_dev *input;
+ struct mt_usages *slot;
bool first_packet;
unsigned count;
- int r, n, scantime = 0;
+ int r, n;
+ int scantime = 0;
+ int contact_count = -1;
/* sticky fingers release in progress, abort */
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
return;
+ scantime = *app->scantime;
+ app->timestamp = mt_compute_timestamp(app, scantime);
+ if (app->raw_cc != DEFAULT_ZERO)
+ contact_count = *app->raw_cc;
+
/*
* Includes multi-packet support where subsequent
* packets are sent with zero contactcount.
*/
- if (td->scantime_index >= 0) {
- field = report->field[td->scantime_index];
- scantime = field->value[td->scantime_val_index];
- }
- if (td->cc_index >= 0) {
- struct hid_field *field = report->field[td->cc_index];
- int value = field->value[td->cc_value_index];
-
+ if (contact_count >= 0) {
/*
* For Win8 PTPs the first packet (td->num_received == 0) may
* have a contactcount of 0 if there only is a button event.
@@ -954,16 +1146,25 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
* of a possible multi-packet frame be checking that the
* timestamp has changed.
*/
- if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
- td->num_received == 0 && td->prev_scantime != scantime)
- td->num_expected = value;
+ if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+ app->num_received == 0 &&
+ app->prev_scantime != scantime)
+ app->num_expected = contact_count;
/* A non 0 contact count always indicates a first packet */
- else if (value)
- td->num_expected = value;
+ else if (contact_count)
+ app->num_expected = contact_count;
+ }
+ app->prev_scantime = scantime;
+
+ first_packet = app->num_received == 0;
+
+ input = report->field[0]->hidinput->input;
+
+ list_for_each_entry(slot, &app->mt_usages, list) {
+ if (!mt_process_slot(td, input, app, slot))
+ app->num_received++;
}
- td->prev_scantime = scantime;
- first_packet = td->num_received == 0;
for (r = 0; r < report->maxfield; r++) {
field = report->field[r];
count = field->report_count;
@@ -972,12 +1173,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
continue;
for (n = 0; n < count; n++)
- mt_process_mt_event(hid, field, &field->usage[n],
- field->value[n], first_packet);
+ mt_process_mt_event(hid, app, field,
+ &field->usage[n], field->value[n],
+ first_packet);
}
- if (td->num_received >= td->num_expected)
- mt_sync_frame(td, report->field[0]->hidinput->input);
+ if (app->num_received >= app->num_expected)
+ mt_sync_frame(td, app, input);
/*
* Windows 8 specs says 2 things:
@@ -997,7 +1199,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
* only affect laggish machines and the ones that have a firmware
* defect.
*/
- if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
+ if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
mod_timer(&td->release_timer,
jiffies + msecs_to_jiffies(100));
@@ -1009,7 +1211,8 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
}
static int mt_touch_input_configured(struct hid_device *hdev,
- struct hid_input *hi)
+ struct hid_input *hi,
+ struct mt_application *app)
{
struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass;
@@ -1019,28 +1222,36 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
- mt_post_parse(td);
+ mt_post_parse(td, app);
if (td->serial_maybe)
- mt_post_parse_default_settings(td);
+ mt_post_parse_default_settings(td, app);
if (cls->is_indirect)
- td->mt_flags |= INPUT_MT_POINTER;
+ app->mt_flags |= INPUT_MT_POINTER;
- if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
- td->mt_flags |= INPUT_MT_DROP_UNUSED;
+ if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+ app->mt_flags |= INPUT_MT_DROP_UNUSED;
/* check for clickpads */
- if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
+ if ((app->mt_flags & INPUT_MT_POINTER) &&
+ (app->buttons_count == 1))
td->is_buttonpad = true;
if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+ app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
+ BITS_TO_LONGS(td->maxcontacts),
+ sizeof(long),
+ GFP_KERNEL);
+ if (!app->pending_palm_slots)
+ return -ENOMEM;
+
+ ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
if (ret)
return ret;
- td->mt_flags = 0;
+ app->mt_flags = 0;
return 0;
}
@@ -1051,6 +1262,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
unsigned long **bit, int *max)
{
struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_application *application;
+ struct mt_report_data *rdata;
+
+ rdata = mt_find_report_data(td, field->report);
+ if (!rdata) {
+ hid_err(hdev, "failed to allocate data for report\n");
+ return 0;
+ }
+
+ application = rdata->application;
/*
* If mtclass.export_all_inputs is not set, only map fields from
@@ -1066,8 +1287,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
field->application != HID_GD_SYSTEM_CONTROL &&
field->application != HID_CP_CONSUMER_CONTROL &&
field->application != HID_GD_WIRELESS_RADIO_CTLS &&
+ field->application != HID_GD_SYSTEM_MULTIAXIS &&
!(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
+ application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
return -1;
/*
@@ -1076,7 +1298,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* map usages to input keys.
*/
if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
+ application->quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
(usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
set_bit(EV_REP, hi->input->evbit);
if (field->flags & HID_MAIN_ITEM_VARIABLE)
@@ -1093,23 +1315,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1;
}
- /*
- * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
- * for the stylus.
- * The check for mt_report_id ensures we don't process
- * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
- * collection, but within the report ID.
- */
- if (field->physical == HID_DG_STYLUS)
- return 0;
- else if ((field->physical == 0) &&
- (field->report->id != td->mt_report_id) &&
- (td->mt_report_id != -1))
- return 0;
-
- if (field->application == HID_DG_TOUCHSCREEN ||
- field->application == HID_DG_TOUCHPAD)
- return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+ if (rdata->is_mt_collection)
+ return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
+ application);
/* let hid-core decide for the others */
return 0;
@@ -1119,15 +1327,11 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- /*
- * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
- * for the stylus.
- */
- if (field->physical == HID_DG_STYLUS)
- return 0;
+ struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_report_data *rdata;
- if (field->application == HID_DG_TOUCHSCREEN ||
- field->application == HID_DG_TOUCHPAD) {
+ rdata = mt_find_report_data(td, field->report);
+ if (rdata && rdata->is_mt_collection) {
/* We own these mappings, tell hid-input to ignore them */
return -1;
}
@@ -1140,8 +1344,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct mt_device *td = hid_get_drvdata(hid);
+ struct mt_report_data *rdata;
- if (field->report->id == td->mt_report_id)
+ rdata = mt_find_report_data(td, field->report);
+ if (rdata && rdata->is_mt_collection)
return mt_touch_event(hid, field, usage, value);
return 0;
@@ -1151,12 +1357,14 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
{
struct mt_device *td = hid_get_drvdata(hid);
struct hid_field *field = report->field[0];
+ struct mt_report_data *rdata;
if (!(hid->claimed & HID_CLAIMED_INPUT))
return;
- if (report->id == td->mt_report_id)
- return mt_touch_report(hid, report);
+ rdata = mt_find_report_data(td, report);
+ if (rdata && rdata->is_mt_collection)
+ return mt_touch_report(hid, rdata);
if (field && field->hidinput && field->hidinput->input)
input_sync(field->hidinput->input);
@@ -1197,9 +1405,9 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
return true;
case HID_DG_CONTACTMAX:
- if (td->mtclass.maxcontacts) {
+ if (cls->maxcontacts) {
max = min_t(int, field->logical_maximum,
- td->mtclass.maxcontacts);
+ cls->maxcontacts);
if (field->value[index] != max) {
field->value[index] = max;
return true;
@@ -1259,12 +1467,13 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
}
}
-static void mt_post_parse_default_settings(struct mt_device *td)
+static void mt_post_parse_default_settings(struct mt_device *td,
+ struct mt_application *app)
{
- __s32 quirks = td->mtclass.quirks;
+ __s32 quirks = app->quirks;
/* unknown serial device needs special quirks */
- if (td->touches_by_report == 1) {
+ if (list_is_singular(&app->mt_usages)) {
quirks |= MT_QUIRK_ALWAYS_VALID;
quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
@@ -1272,21 +1481,13 @@ static void mt_post_parse_default_settings(struct mt_device *td)
quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
- td->mtclass.quirks = quirks;
+ app->quirks = quirks;
}
-static void mt_post_parse(struct mt_device *td)
+static void mt_post_parse(struct mt_device *td, struct mt_application *app)
{
- struct mt_fields *f = td->fields;
- struct mt_class *cls = &td->mtclass;
-
- if (td->touches_by_report > 0) {
- int field_count_per_touch = f->length / td->touches_by_report;
- td->last_slot_field = f->usages[field_count_per_touch - 1];
- }
-
- if (td->cc_index < 0)
- cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+ if (!app->have_contact_count)
+ app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
}
static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
@@ -1295,13 +1496,24 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
char *name;
const char *suffix = NULL;
unsigned int application = 0;
+ struct mt_report_data *rdata;
+ struct mt_application *mt_application = NULL;
struct hid_report *report;
int ret;
list_for_each_entry(report, &hi->reports, hidinput_list) {
application = report->application;
- if (report->id == td->mt_report_id) {
- ret = mt_touch_input_configured(hdev, hi);
+ rdata = mt_find_report_data(td, report);
+ if (!rdata) {
+ hid_err(hdev, "failed to allocate data for report\n");
+ return -ENOMEM;
+ }
+
+ mt_application = rdata->application;
+
+ if (rdata->is_mt_collection) {
+ ret = mt_touch_input_configured(hdev, hi,
+ mt_application);
if (ret)
return ret;
}
@@ -1327,6 +1539,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
case HID_GD_SYSTEM_CONTROL:
case HID_CP_CONSUMER_CONTROL:
case HID_GD_WIRELESS_RADIO_CTLS:
+ case HID_GD_SYSTEM_MULTIAXIS:
/* already handled by hid core */
break;
case HID_DG_TOUCHSCREEN:
@@ -1390,6 +1603,7 @@ static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
static void mt_release_contacts(struct hid_device *hid)
{
struct hid_input *hidinput;
+ struct mt_application *application;
struct mt_device *td = hid_get_drvdata(hid);
list_for_each_entry(hidinput, &hid->inputs, list) {
@@ -1409,7 +1623,9 @@ static void mt_release_contacts(struct hid_device *hid)
}
}
- td->num_received = 0;
+ list_for_each_entry(application, &td->applications, list) {
+ application->num_received = 0;
+ }
}
static void mt_expired_timeout(struct timer_list *t)
@@ -1432,7 +1648,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret, i;
struct mt_device *td;
- struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+ const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
for (i = 0; mt_classes[i].name ; i++) {
if (id->driver_data == mt_classes[i].name) {
@@ -1449,17 +1665,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td->hdev = hdev;
td->mtclass = *mtclass;
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
- td->cc_index = -1;
- td->scantime_index = -1;
- td->mt_report_id = -1;
hid_set_drvdata(hdev, td);
- td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
- GFP_KERNEL);
- if (!td->fields) {
- dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
- return -ENOMEM;
- }
+ INIT_LIST_HEAD(&td->applications);
+ INIT_LIST_HEAD(&td->reports);
if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
td->serial_maybe = true;
@@ -1496,10 +1705,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
- /* release .fields memory as it is not used anymore */
- devm_kfree(&hdev->dev, td->fields);
- td->fields = NULL;
-
return 0;
}
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 43b1c7234316..9bc6f4867cb3 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -955,6 +955,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = sysfs_create_group(&hdev->dev.kobj,
&ntrig_attribute_group);
+ if (ret)
+ hid_err(hdev, "cannot create sysfs group\n");
return 0;
err_free:
diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c
index daf59578bf93..73c9d4c4fa34 100644
--- a/drivers/hid/hid-redragon.c
+++ b/drivers/hid/hid-redragon.c
@@ -44,29 +44,6 @@ static __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc,
return rdesc;
}
-static int redragon_probe(struct hid_device *dev,
- const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(dev);
- if (ret) {
- hid_err(dev, "parse failed\n");
- return ret;
- }
-
- /* do not register unused input device */
- if (dev->maxapplication == 1)
- return 0;
-
- ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
- if (ret) {
- hid_err(dev, "hw start failed\n");
- return ret;
- }
-
- return 0;
-}
static const struct hid_device_id redragon_devices[] = {
{HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_REDRAGON_ASURA)},
{}
@@ -77,8 +54,7 @@ MODULE_DEVICE_TABLE(hid, redragon_devices);
static struct hid_driver redragon_driver = {
.name = "redragon",
.id_table = redragon_devices,
- .report_fixup = redragon_report_fixup,
- .probe = redragon_probe
+ .report_fixup = redragon_report_fixup
};
module_hid_driver(redragon_driver);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index e475c5073c99..9671a4bad643 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1353,7 +1353,7 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
char *name;
int ret;
- sc->touchpad = input_allocate_device();
+ sc->touchpad = devm_input_allocate_device(&sc->hdev->dev);
if (!sc->touchpad)
return -ENOMEM;
@@ -1370,11 +1370,9 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
* DS4 compatible non-Sony devices with different names.
*/
name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX);
- name = kzalloc(name_sz, GFP_KERNEL);
- if (!name) {
- ret = -ENOMEM;
- goto err;
- }
+ name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
sc->touchpad->name = name;
@@ -1403,34 +1401,13 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER);
if (ret < 0)
- goto err;
+ return ret;
ret = input_register_device(sc->touchpad);
if (ret < 0)
- goto err;
+ return ret;
return 0;
-
-err:
- kfree(sc->touchpad->name);
- sc->touchpad->name = NULL;
-
- input_free_device(sc->touchpad);
- sc->touchpad = NULL;
-
- return ret;
-}
-
-static void sony_unregister_touchpad(struct sony_sc *sc)
-{
- if (!sc->touchpad)
- return;
-
- kfree(sc->touchpad->name);
- sc->touchpad->name = NULL;
-
- input_unregister_device(sc->touchpad);
- sc->touchpad = NULL;
}
static int sony_register_sensors(struct sony_sc *sc)
@@ -1440,7 +1417,7 @@ static int sony_register_sensors(struct sony_sc *sc)
int ret;
int range;
- sc->sensor_dev = input_allocate_device();
+ sc->sensor_dev = devm_input_allocate_device(&sc->hdev->dev);
if (!sc->sensor_dev)
return -ENOMEM;
@@ -1457,11 +1434,9 @@ static int sony_register_sensors(struct sony_sc *sc)
* DS4 compatible non-Sony devices with different names.
*/
name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX);
- name = kzalloc(name_sz, GFP_KERNEL);
- if (!name) {
- ret = -ENOMEM;
- goto err;
- }
+ name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name);
sc->sensor_dev->name = name;
@@ -1503,33 +1478,11 @@ static int sony_register_sensors(struct sony_sc *sc)
ret = input_register_device(sc->sensor_dev);
if (ret < 0)
- goto err;
+ return ret;
return 0;
-
-err:
- kfree(sc->sensor_dev->name);
- sc->sensor_dev->name = NULL;
-
- input_free_device(sc->sensor_dev);
- sc->sensor_dev = NULL;
-
- return ret;
}
-static void sony_unregister_sensors(struct sony_sc *sc)
-{
- if (!sc->sensor_dev)
- return;
-
- kfree(sc->sensor_dev->name);
- sc->sensor_dev->name = NULL;
-
- input_unregister_device(sc->sensor_dev);
- sc->sensor_dev = NULL;
-}
-
-
/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
@@ -1987,25 +1940,6 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
return 0;
}
-static void sony_leds_remove(struct sony_sc *sc)
-{
- struct led_classdev *led;
- int n;
-
- BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
-
- for (n = 0; n < sc->led_count; n++) {
- led = sc->leds[n];
- sc->leds[n] = NULL;
- if (!led)
- continue;
- led_classdev_unregister(led);
- kfree(led);
- }
-
- sc->led_count = 0;
-}
-
static int sony_leds_init(struct sony_sc *sc)
{
struct hid_device *hdev = sc->hdev;
@@ -2078,11 +2012,10 @@ static int sony_leds_init(struct sony_sc *sc)
if (use_ds4_names)
name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
- led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
+ led = devm_kzalloc(&hdev->dev, sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
if (!led) {
hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
- ret = -ENOMEM;
- goto error_leds;
+ return -ENOMEM;
}
name = (void *)(&led[1]);
@@ -2103,21 +2036,14 @@ static int sony_leds_init(struct sony_sc *sc)
sc->leds[n] = led;
- ret = led_classdev_register(&hdev->dev, led);
+ ret = devm_led_classdev_register(&hdev->dev, led);
if (ret) {
hid_err(hdev, "Failed to register LED %d\n", n);
- sc->leds[n] = NULL;
- kfree(led);
- goto error_leds;
+ return ret;
}
}
- return ret;
-
-error_leds:
- sony_leds_remove(sc);
-
- return ret;
+ return 0;
}
static void sixaxis_send_output_report(struct sony_sc *sc)
@@ -2276,16 +2202,20 @@ static int sony_allocate_output_report(struct sony_sc *sc)
if ((sc->quirks & SIXAXIS_CONTROLLER) ||
(sc->quirks & NAVIGATION_CONTROLLER))
sc->output_report_dmabuf =
- kmalloc(sizeof(union sixaxis_output_report_01),
+ devm_kmalloc(&sc->hdev->dev,
+ sizeof(union sixaxis_output_report_01),
GFP_KERNEL);
else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
- sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
+ sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+ DS4_OUTPUT_REPORT_0x11_SIZE,
GFP_KERNEL);
else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE))
- sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
+ sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+ DS4_OUTPUT_REPORT_0x05_SIZE,
GFP_KERNEL);
else if (sc->quirks & MOTION_CONTROLLER)
- sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
+ sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+ MOTION_REPORT_0x02_SIZE,
GFP_KERNEL);
else
return 0;
@@ -2392,36 +2322,21 @@ static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
sc->battery_desc.get_property = sony_battery_get_property;
sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
sc->battery_desc.use_for_apm = 0;
- sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
- sc->mac_address, sc->device_id);
+ sc->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+ battery_str_fmt, sc->mac_address, sc->device_id);
if (!sc->battery_desc.name)
return -ENOMEM;
- sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
+ sc->battery = devm_power_supply_register(&hdev->dev, &sc->battery_desc,
&psy_cfg);
if (IS_ERR(sc->battery)) {
ret = PTR_ERR(sc->battery);
hid_err(hdev, "Unable to register battery device\n");
- goto err_free;
+ return ret;
}
power_supply_powers(sc->battery, &hdev->dev);
return 0;
-
-err_free:
- kfree(sc->battery_desc.name);
- sc->battery_desc.name = NULL;
- return ret;
-}
-
-static void sony_battery_remove(struct sony_sc *sc)
-{
- if (!sc->battery_desc.name)
- return;
-
- power_supply_unregister(sc->battery);
- kfree(sc->battery_desc.name);
- sc->battery_desc.name = NULL;
}
/*
@@ -2879,16 +2794,7 @@ err_stop:
device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
if (sc->hw_version)
device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
- if (sc->quirks & SONY_LED_SUPPORT)
- sony_leds_remove(sc);
- if (sc->quirks & SONY_BATTERY_SUPPORT)
- sony_battery_remove(sc);
- if (sc->touchpad)
- sony_unregister_touchpad(sc);
- if (sc->sensor_dev)
- sony_unregister_sensors(sc);
sony_cancel_work_sync(sc);
- kfree(sc->output_report_dmabuf);
sony_remove_dev_list(sc);
sony_release_device_id(sc);
hid_hw_stop(hdev);
@@ -2965,18 +2871,6 @@ static void sony_remove(struct hid_device *hdev)
hid_hw_close(hdev);
- if (sc->quirks & SONY_LED_SUPPORT)
- sony_leds_remove(sc);
-
- if (sc->quirks & SONY_BATTERY_SUPPORT)
- sony_battery_remove(sc);
-
- if (sc->touchpad)
- sony_unregister_touchpad(sc);
-
- if (sc->sensor_dev)
- sony_unregister_sensors(sc);
-
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
@@ -2988,8 +2882,6 @@ static void sony_remove(struct hid_device *hdev)
sony_cancel_work_sync(sc);
- kfree(sc->output_report_dmabuf);
-
sony_remove_dev_list(sc);
sony_release_device_id(sc);
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 579884ebd94d..7780da4fe897 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -455,6 +455,12 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
return WIIMOTE_EXT_BALANCE_BOARD;
if (rmem[4] == 0x01 && rmem[5] == 0x20)
return WIIMOTE_EXT_PRO_CONTROLLER;
+ if (rmem[0] == 0x01 && rmem[1] == 0x00 &&
+ rmem[4] == 0x01 && rmem[5] == 0x03)
+ return WIIMOTE_EXT_DRUMS;
+ if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
+ rmem[4] == 0x01 && rmem[5] == 0x03)
+ return WIIMOTE_EXT_GUITAR;
return WIIMOTE_EXT_UNKNOWN;
}
@@ -488,6 +494,8 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
/* map MP with correct pass-through mode */
switch (exttype) {
case WIIMOTE_EXT_CLASSIC_CONTROLLER:
+ case WIIMOTE_EXT_DRUMS:
+ case WIIMOTE_EXT_GUITAR:
wmem = 0x07;
break;
case WIIMOTE_EXT_NUNCHUK:
@@ -1075,6 +1083,8 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
[WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
+ [WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums",
+ [WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar",
};
/*
@@ -1660,6 +1670,10 @@ static ssize_t wiimote_ext_show(struct device *dev,
return sprintf(buf, "balanceboard\n");
case WIIMOTE_EXT_PRO_CONTROLLER:
return sprintf(buf, "procontroller\n");
+ case WIIMOTE_EXT_DRUMS:
+ return sprintf(buf, "drums\n");
+ case WIIMOTE_EXT_GUITAR:
+ return sprintf(buf, "guitar\n");
case WIIMOTE_EXT_UNKNOWN:
/* fallthrough */
default:
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index c830ed39348f..aa72eb9a8e2f 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -1950,6 +1950,444 @@ static const struct wiimod_ops wiimod_pro = {
};
/*
+ * Drums
+ * Guitar-Hero, Rock-Band and other games came bundled with drums which can
+ * be plugged as extension to a Wiimote. Drum-reports are still not entirely
+ * figured out, but the most important information is known.
+ * We create a separate device for drums and report all information via this
+ * input device.
+ */
+
+static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
+ __u8 none, __u8 which,
+ __u8 pressure, __u8 onoff,
+ __u8 *store, __u16 code,
+ __u8 which_code)
+{
+ static const __u8 default_pressure = 3;
+
+ if (!none && which == which_code) {
+ *store = pressure;
+ input_report_abs(wdata->extension.input, code, *store);
+ } else if (onoff != !!*store) {
+ *store = onoff ? default_pressure : 0;
+ input_report_abs(wdata->extension.input, code, *store);
+ }
+}
+
+static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+ __u8 pressure, which, none, hhp, sx, sy;
+ __u8 o, r, y, g, b, bass, bm, bp;
+
+ /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:0> |
+ * 2 | 0 | 0 | SY <5:0> |
+ * -----+-----+-----+-----------------------------+-----+
+ * 3 | HPP | NON | WHICH <5:1> | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | O | R | Y | G | B | BSS | 1 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * All buttons are 0 if pressed
+ *
+ * With Motion+ enabled, the following bits will get invalid:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:1> |XXXXX|
+ * 2 | 0 | 0 | SY <5:1> |XXXXX|
+ * -----+-----+-----+-----------------------------+-----+
+ * 3 | HPP | NON | WHICH <5:1> | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 4 | SOFT <7:5> | 0 | 1 | 1 | 0 | ? |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | ? | 1 | 1 | B- | 1 | B+ | 1 |XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | O | R | Y | G | B | BSS |XXXXX|XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+ pressure = 7 - (ext[3] >> 5);
+ which = (ext[2] >> 1) & 0x1f;
+ none = !!(ext[2] & 0x40);
+ hhp = !(ext[2] & 0x80);
+ sx = ext[0] & 0x3f;
+ sy = ext[1] & 0x3f;
+ o = !(ext[5] & 0x80);
+ r = !(ext[5] & 0x40);
+ y = !(ext[5] & 0x20);
+ g = !(ext[5] & 0x10);
+ b = !(ext[5] & 0x08);
+ bass = !(ext[5] & 0x04);
+ bm = !(ext[4] & 0x10);
+ bp = !(ext[4] & 0x04);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+ sx &= 0x3e;
+ sy &= 0x3e;
+ }
+
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ o, &wdata->state.pressure_drums[0],
+ ABS_HAT2Y, 0x0e);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ r, &wdata->state.pressure_drums[1],
+ ABS_HAT0X, 0x19);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ y, &wdata->state.pressure_drums[2],
+ ABS_HAT2X, 0x11);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ g, &wdata->state.pressure_drums[3],
+ ABS_HAT1X, 0x12);
+ wiimod_drums_report_pressure(wdata, none, which, pressure,
+ b, &wdata->state.pressure_drums[4],
+ ABS_HAT0Y, 0x0f);
+
+ /* Bass shares pressure with hi-hat (set via hhp) */
+ wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure,
+ bass, &wdata->state.pressure_drums[5],
+ ABS_HAT3X, 0x1b);
+ /* Hi-hat has no on/off values, just pressure. Force to off/0. */
+ wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure,
+ 0, &wdata->state.pressure_drums[6],
+ ABS_HAT3Y, 0x0e);
+
+ input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+
+ input_report_key(wdata->extension.input, BTN_START, bp);
+ input_report_key(wdata->extension.input, BTN_SELECT, bm);
+
+ input_sync(wdata->extension.input);
+}
+
+static int wiimod_drums_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_drums_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_drums_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ int ret;
+
+ wdata->extension.input = input_allocate_device();
+ if (!wdata->extension.input)
+ return -ENOMEM;
+
+ input_set_drvdata(wdata->extension.input, wdata);
+ wdata->extension.input->open = wiimod_drums_open;
+ wdata->extension.input->close = wiimod_drums_close;
+ wdata->extension.input->dev.parent = &wdata->hdev->dev;
+ wdata->extension.input->id.bustype = wdata->hdev->bus;
+ wdata->extension.input->id.vendor = wdata->hdev->vendor;
+ wdata->extension.input->id.product = wdata->hdev->product;
+ wdata->extension.input->id.version = wdata->hdev->version;
+ wdata->extension.input->name = WIIMOTE_NAME " Drums";
+
+ set_bit(EV_KEY, wdata->extension.input->evbit);
+ set_bit(BTN_START, wdata->extension.input->keybit);
+ set_bit(BTN_SELECT, wdata->extension.input->keybit);
+
+ set_bit(EV_ABS, wdata->extension.input->evbit);
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT2X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT3X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0X, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0Y, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1X, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT2X, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT2Y, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT3X, 0, 7, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT3Y, 0, 7, 0, 0);
+
+ ret = input_register_device(wdata->extension.input);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ input_free_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+ return ret;
+}
+
+static void wiimod_drums_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ if (!wdata->extension.input)
+ return;
+
+ input_unregister_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_drums = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_drums_probe,
+ .remove = wiimod_drums_remove,
+ .in_ext = wiimod_drums_in_ext,
+};
+
+/*
+ * Guitar
+ * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
+ * be plugged as extension to a Wiimote.
+ * We create a separate device for guitars and report all information via this
+ * input device.
+ */
+
+enum wiimod_guitar_keys {
+ WIIMOD_GUITAR_KEY_G,
+ WIIMOD_GUITAR_KEY_R,
+ WIIMOD_GUITAR_KEY_Y,
+ WIIMOD_GUITAR_KEY_B,
+ WIIMOD_GUITAR_KEY_O,
+ WIIMOD_GUITAR_KEY_UP,
+ WIIMOD_GUITAR_KEY_DOWN,
+ WIIMOD_GUITAR_KEY_PLUS,
+ WIIMOD_GUITAR_KEY_MINUS,
+ WIIMOD_GUITAR_KEY_NUM,
+};
+
+static const __u16 wiimod_guitar_map[] = {
+ BTN_1, /* WIIMOD_GUITAR_KEY_G */
+ BTN_2, /* WIIMOD_GUITAR_KEY_R */
+ BTN_3, /* WIIMOD_GUITAR_KEY_Y */
+ BTN_4, /* WIIMOD_GUITAR_KEY_B */
+ BTN_5, /* WIIMOD_GUITAR_KEY_O */
+ BTN_DPAD_UP, /* WIIMOD_GUITAR_KEY_UP */
+ BTN_DPAD_DOWN, /* WIIMOD_GUITAR_KEY_DOWN */
+ BTN_START, /* WIIMOD_GUITAR_KEY_PLUS */
+ BTN_SELECT, /* WIIMOD_GUITAR_KEY_MINUS */
+};
+
+static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+ __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu;
+
+ /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:0> |
+ * 2 | 0 | 0 | SY <5:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 3 | 0 | 0 | 0 | TB <4:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 4 | 0 | 0 | 0 | WB <4:0> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BO | BR | BB | BG | BY | 1 | 1 | BU |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * All buttons are 0 if pressed
+ *
+ * With Motion+ enabled, it will look like this:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 1 | 0 | 0 | SX <5:1> | BU |
+ * 2 | 0 | 0 | SY <5:1> | 1 |
+ * -----+-----+-----+-----+-----------------------+-----+
+ * 3 | 0 | 0 | 0 | TB <4:0> |
+ * -----+-----+-----+-----+-----------------------------+
+ * 4 | 0 | 0 | 0 | WB <4:0> |
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 5 | 1 | BD | 1 | B- | 1 | B+ | 1 |XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ * 6 | BO | BR | BB | BG | BY | 1 |XXXXX|XXXXX|
+ * -----+-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+
+ sx = ext[0] & 0x3f;
+ sy = ext[1] & 0x3f;
+ tb = ext[2] & 0x1f;
+ wb = ext[3] & 0x1f;
+ bd = !(ext[4] & 0x40);
+ bm = !(ext[4] & 0x10);
+ bp = !(ext[4] & 0x04);
+ bo = !(ext[5] & 0x80);
+ br = !(ext[5] & 0x40);
+ bb = !(ext[5] & 0x20);
+ bg = !(ext[5] & 0x10);
+ by = !(ext[5] & 0x08);
+ bu = !(ext[5] & 0x01);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+ bu = !(ext[0] & 0x01);
+ sx &= 0x3e;
+ sy &= 0x3e;
+ }
+
+ input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+ input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+ input_report_abs(wdata->extension.input, ABS_HAT0X, tb);
+ input_report_abs(wdata->extension.input, ABS_HAT1X, wb - 0x10);
+
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_G],
+ bg);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_R],
+ br);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_Y],
+ by);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_B],
+ bb);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_O],
+ bo);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_UP],
+ bu);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_DOWN],
+ bd);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_PLUS],
+ bp);
+ input_report_key(wdata->extension.input,
+ wiimod_guitar_map[WIIMOD_GUITAR_KEY_MINUS],
+ bm);
+
+ input_sync(wdata->extension.input);
+}
+
+static int wiimod_guitar_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_guitar_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_guitar_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ int ret, i;
+
+ wdata->extension.input = input_allocate_device();
+ if (!wdata->extension.input)
+ return -ENOMEM;
+
+ input_set_drvdata(wdata->extension.input, wdata);
+ wdata->extension.input->open = wiimod_guitar_open;
+ wdata->extension.input->close = wiimod_guitar_close;
+ wdata->extension.input->dev.parent = &wdata->hdev->dev;
+ wdata->extension.input->id.bustype = wdata->hdev->bus;
+ wdata->extension.input->id.vendor = wdata->hdev->vendor;
+ wdata->extension.input->id.product = wdata->hdev->product;
+ wdata->extension.input->id.version = wdata->hdev->version;
+ wdata->extension.input->name = WIIMOTE_NAME " Guitar";
+
+ set_bit(EV_KEY, wdata->extension.input->evbit);
+ for (i = 0; i < WIIMOD_GUITAR_KEY_NUM; ++i)
+ set_bit(wiimod_guitar_map[i],
+ wdata->extension.input->keybit);
+
+ set_bit(EV_ABS, wdata->extension.input->evbit);
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, -32, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0X, 0, 0x1f, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1X, 0, 0x0f, 1, 1);
+
+ ret = input_register_device(wdata->extension.input);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ input_free_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+ return ret;
+}
+
+static void wiimod_guitar_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ if (!wdata->extension.input)
+ return;
+
+ input_unregister_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_guitar = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_guitar_probe,
+ .remove = wiimod_guitar_remove,
+ .in_ext = wiimod_guitar_in_ext,
+};
+
+/*
* Builtin Motion Plus
* This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
* disables polling for Motion-Plus. This should be set only for devices which
@@ -2201,4 +2639,6 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
[WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
+ [WIIMOTE_EXT_DRUMS] = &wiimod_drums,
+ [WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
};
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 510ca77fe14e..3bf3d3cc1c38 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -89,6 +89,8 @@ enum wiimote_exttype {
WIIMOTE_EXT_CLASSIC_CONTROLLER,
WIIMOTE_EXT_BALANCE_BOARD,
WIIMOTE_EXT_PRO_CONTROLLER,
+ WIIMOTE_EXT_DRUMS,
+ WIIMOTE_EXT_GUITAR,
WIIMOTE_EXT_NUM,
};
@@ -137,6 +139,7 @@ struct wiimote_state {
/* calibration/cache data */
__u16 calib_bboard[4][3];
__s16 calib_pro_sticks[4];
+ __u8 pressure_drums[7];
__u8 cache_rumble;
};
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index eae0cb3ddec6..2ce194a84868 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1002,18 +1002,18 @@ static int i2c_hid_probe(struct i2c_client *client,
return client->irq;
}
- ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+ ihid = devm_kzalloc(&client->dev, sizeof(*ihid), GFP_KERNEL);
if (!ihid)
return -ENOMEM;
if (client->dev.of_node) {
ret = i2c_hid_of_probe(client, &ihid->pdata);
if (ret)
- goto err;
+ return ret;
} else if (!platform_data) {
ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
if (ret)
- goto err;
+ return ret;
} else {
ihid->pdata = *platform_data;
}
@@ -1021,21 +1021,20 @@ static int i2c_hid_probe(struct i2c_client *client,
/* Parse platform agnostic common properties from ACPI / device tree */
i2c_hid_fwnode_probe(client, &ihid->pdata);
- ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
- if (IS_ERR(ihid->pdata.supply)) {
- ret = PTR_ERR(ihid->pdata.supply);
- if (ret != -EPROBE_DEFER)
- dev_err(&client->dev, "Failed to get regulator: %d\n",
- ret);
- goto err;
- }
+ ihid->pdata.supplies[0].supply = "vdd";
+ ihid->pdata.supplies[1].supply = "vddl";
+
+ ret = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
+ if (ret)
+ return ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
+ if (ret < 0)
+ return ret;
- ret = regulator_enable(ihid->pdata.supply);
- if (ret < 0) {
- dev_err(&client->dev, "Failed to enable regulator: %d\n",
- ret);
- goto err;
- }
if (ihid->pdata.post_power_delay_ms)
msleep(ihid->pdata.post_power_delay_ms);
@@ -1122,11 +1121,9 @@ err_pm:
pm_runtime_disable(&client->dev);
err_regulator:
- regulator_disable(ihid->pdata.supply);
-
-err:
+ regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
i2c_hid_free_buffers(ihid);
- kfree(ihid);
return ret;
}
@@ -1148,9 +1145,8 @@ static int i2c_hid_remove(struct i2c_client *client)
if (ihid->bufsize)
i2c_hid_free_buffers(ihid);
- regulator_disable(ihid->pdata.supply);
-
- kfree(ihid);
+ regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
return 0;
}
@@ -1201,9 +1197,8 @@ static int i2c_hid_suspend(struct device *dev)
hid_warn(hid, "Failed to enable irq wake: %d\n",
wake_status);
} else {
- ret = regulator_disable(ihid->pdata.supply);
- if (ret < 0)
- hid_warn(hid, "Failed to disable supply: %d\n", ret);
+ regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
}
return 0;
@@ -1218,9 +1213,11 @@ static int i2c_hid_resume(struct device *dev)
int wake_status;
if (!device_may_wakeup(&client->dev)) {
- ret = regulator_enable(ihid->pdata.supply);
- if (ret < 0)
- hid_warn(hid, "Failed to enable supply: %d\n", ret);
+ ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+ ihid->pdata.supplies);
+ if (ret)
+ hid_warn(hid, "Failed to enable supplies: %d\n", ret);
+
if (ihid->pdata.post_power_delay_ms)
msleep(ihid->pdata.post_power_delay_ms);
} else if (ihid->irq_wake_enabled) {
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
index 9a60ec13cb10..bfbca7ec54ce 100644
--- a/drivers/hid/intel-ish-hid/ipc/ipc.c
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -907,8 +907,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
struct ishtp_device *dev;
int i;
- dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw),
- GFP_KERNEL);
+ dev = devm_kzalloc(&pdev->dev,
+ sizeof(struct ishtp_device) + sizeof(struct ish_hw),
+ GFP_KERNEL);
if (!dev)
return NULL;
@@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) {
struct wr_msg_ctl_info *tx_buf;
- tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL);
+ tx_buf = devm_kzalloc(&pdev->dev,
+ sizeof(struct wr_msg_ctl_info),
+ GFP_KERNEL);
if (!tx_buf) {
/*
* IPC buffers may be limited or not available
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index a2c53ea3b5ed..050f9872f5c0 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -95,6 +95,13 @@ static int ish_init(struct ishtp_device *dev)
return 0;
}
+static const struct pci_device_id ish_invalid_pci_ids[] = {
+ /* Mehlow platform special pci ids */
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA309)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA30A)},
+ {}
+};
+
/**
* ish_probe() - PCI driver probe callback
* @pdev: pci device
@@ -110,6 +117,10 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ish_hw *hw;
int ret;
+ /* Check for invalid platforms for ISH support */
+ if (pci_dev_present(ish_invalid_pci_ids))
+ return -ENODEV;
+
/* enable pci dev */
ret = pci_enable_device(pdev);
if (ret) {
@@ -172,7 +183,6 @@ free_irq:
free_irq(pdev->irq, dev);
free_device:
pci_iounmap(pdev, hw->mem_addr);
- kfree(dev);
release_regions:
pci_release_regions(pdev);
disable_device:
@@ -202,7 +212,6 @@ static void ish_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_clear_master(pdev);
pci_disable_device(pdev);
- kfree(ishtp_dev);
}
static struct device __maybe_unused *ish_resume_device;
diff --git a/drivers/hid/intel-ish-hid/ishtp/hbm.c b/drivers/hid/intel-ish-hid/ishtp/hbm.c
index ae4a69f7f2f4..8b5dd580ceec 100644
--- a/drivers/hid/intel-ish-hid/ishtp/hbm.c
+++ b/drivers/hid/intel-ish-hid/ishtp/hbm.c
@@ -298,7 +298,6 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
struct ishtp_msg_hdr *ishtp_hdr = &hdr;
const size_t len = sizeof(struct hbm_flow_control);
int rv;
- unsigned int num_frags;
unsigned long flags;
spin_lock_irqsave(&cl->fc_spinlock, flags);
@@ -314,7 +313,6 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
return 0;
}
- num_frags = cl->recv_msg_num_frags;
cl->recv_msg_num_frags = 0;
rv = ishtp_write_message(dev, ishtp_hdr, data);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index af0e0d061b15..11103efebbaa 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -480,6 +480,7 @@ static void hid_ctrl(struct urb *urb)
{
struct hid_device *hid = urb->context;
struct usbhid_device *usbhid = hid->driver_data;
+ unsigned long flags;
int unplug = 0, status = urb->status;
switch (status) {
@@ -501,7 +502,7 @@ static void hid_ctrl(struct urb *urb)
hid_warn(urb->dev, "ctrl urb status %d received\n", status);
}
- spin_lock(&usbhid->lock);
+ spin_lock_irqsave(&usbhid->lock, flags);
if (unplug) {
usbhid->ctrltail = usbhid->ctrlhead;
@@ -511,13 +512,13 @@ static void hid_ctrl(struct urb *urb)
if (usbhid->ctrlhead != usbhid->ctrltail &&
hid_submit_ctrl(hid) == 0) {
/* Successfully submitted next urb in queue */
- spin_unlock(&usbhid->lock);
+ spin_unlock_irqrestore(&usbhid->lock, flags);
return;
}
}
clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
- spin_unlock(&usbhid->lock);
+ spin_unlock_irqrestore(&usbhid->lock, flags);
usb_autopm_put_interface_async(usbhid->intf);
wake_up(&usbhid->wait);
}
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index d6797535fff9..0bdd85d486fe 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -210,6 +210,57 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
return hidinput_calc_abs_res(&field, ABS_X);
}
+static void wacom_hid_usage_quirk(struct hid_device *hdev,
+ struct hid_field *field, struct hid_usage *usage)
+{
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+ /*
+ * The Dell Canvas 27 needs to be switched to its vendor-defined
+ * report to provide the best resolution.
+ */
+ if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+ hdev->product == 0x4200 &&
+ field->application == HID_UP_MSVENDOR) {
+ wacom->wacom_wac.mode_report = field->report->id;
+ wacom->wacom_wac.mode_value = 2;
+ }
+
+ /*
+ * ISDv4 devices which predate HID's adoption of the
+ * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+ * position instead. We can accurately detect if a
+ * usage with that value should be HID_DG_BARRELSWITCH2
+ * based on the surrounding usages, which have remained
+ * constant across generations.
+ */
+ if (features->type == HID_GENERIC &&
+ usage->hid == 0x000D0000 &&
+ field->application == HID_DG_PEN &&
+ field->physical == HID_DG_STYLUS) {
+ int i = usage->usage_index;
+
+ if (i-4 >= 0 && i+1 < field->maxusage &&
+ field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+ field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+ field->usage[i-2].hid == HID_DG_ERASER &&
+ field->usage[i-1].hid == HID_DG_INVERT &&
+ field->usage[i+1].hid == HID_DG_INRANGE) {
+ usage->hid = HID_DG_BARRELSWITCH2;
+ }
+ }
+
+ /* 2nd-generation Intuos Pro Large has incorrect Y maximum */
+ if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+ hdev->product == 0x0358 &&
+ WACOM_PEN_FIELD(field) &&
+ equivalent_usage == HID_GD_Y) {
+ field->logical_maximum = 43200;
+ }
+}
+
static void wacom_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage)
{
@@ -221,6 +272,8 @@ static void wacom_feature_mapping(struct hid_device *hdev,
int ret;
u32 n;
+ wacom_hid_usage_quirk(hdev, field, usage);
+
switch (equivalent_usage) {
case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */
@@ -300,13 +353,6 @@ static void wacom_feature_mapping(struct hid_device *hdev,
kfree(data);
break;
}
-
- if (hdev->vendor == USB_VENDOR_ID_WACOM &&
- hdev->product == 0x4200 /* Dell Canvas 27 */ &&
- field->application == HID_UP_MSVENDOR) {
- wacom->wacom_wac.mode_report = field->report->id;
- wacom->wacom_wac.mode_value = 2;
- }
}
/*
@@ -348,6 +394,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
struct wacom_features *features = &wacom->wacom_wac.features;
bool finger = WACOM_FINGER_FIELD(field);
bool pen = WACOM_PEN_FIELD(field);
+ unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
/*
* Requiring Stylus Usage will ignore boot mouse
@@ -361,49 +408,9 @@ static void wacom_usage_mapping(struct hid_device *hdev,
else
return;
- /*
- * Bamboo models do not support HID_DG_CONTACTMAX.
- * And, Bamboo Pen only descriptor contains touch.
- */
- if (features->type > BAMBOO_PT) {
- /* ISDv4 touch devices at least supports one touch point */
- if (finger && !features->touch_max)
- features->touch_max = 1;
- }
-
- /*
- * ISDv4 devices which predate HID's adoption of the
- * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
- * position instead. We can accurately detect if a
- * usage with that value should be HID_DG_BARRELSWITCH2
- * based on the surrounding usages, which have remained
- * constant across generations.
- */
- if (features->type == HID_GENERIC &&
- usage->hid == 0x000D0000 &&
- field->application == HID_DG_PEN &&
- field->physical == HID_DG_STYLUS) {
- int i = usage->usage_index;
+ wacom_hid_usage_quirk(hdev, field, usage);
- if (i-4 >= 0 && i+1 < field->maxusage &&
- field->usage[i-4].hid == HID_DG_TIPSWITCH &&
- field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
- field->usage[i-2].hid == HID_DG_ERASER &&
- field->usage[i-1].hid == HID_DG_INVERT &&
- field->usage[i+1].hid == HID_DG_INRANGE) {
- usage->hid = HID_DG_BARRELSWITCH2;
- }
- }
-
- /* 2nd-generation Intuos Pro Large has incorrect Y maximum */
- if (hdev->vendor == USB_VENDOR_ID_WACOM &&
- hdev->product == 0x0358 &&
- WACOM_PEN_FIELD(field) &&
- wacom_equivalent_usage(usage->hid) == HID_GD_Y) {
- field->logical_maximum = 43200;
- }
-
- switch (usage->hid) {
+ switch (equivalent_usage) {
case HID_GD_X:
features->x_max = field->logical_maximum;
if (finger) {
@@ -703,18 +710,6 @@ struct wacom_hdev_data {
static LIST_HEAD(wacom_udev_list);
static DEFINE_MUTEX(wacom_udev_list_lock);
-static bool compare_device_paths(struct hid_device *hdev_a,
- struct hid_device *hdev_b, char separator)
-{
- int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
- int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
-
- if (n1 != n2 || n1 <= 0 || n2 <= 0)
- return false;
-
- return !strncmp(hdev_a->phys, hdev_b->phys, n1);
-}
-
static bool wacom_are_sibling(struct hid_device *hdev,
struct hid_device *sibling)
{
@@ -737,10 +732,10 @@ static bool wacom_are_sibling(struct hid_device *hdev,
* the same physical parent device path.
*/
if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
- if (!compare_device_paths(hdev, sibling, '/'))
+ if (!hid_compare_device_paths(hdev, sibling, '/'))
return false;
} else {
- if (!compare_device_paths(hdev, sibling, '.'))
+ if (!hid_compare_device_paths(hdev, sibling, '.'))
return false;
}
@@ -787,7 +782,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
/* Try to find an already-probed interface from the same device */
list_for_each_entry(data, &wacom_udev_list, list) {
- if (compare_device_paths(hdev, data->dev, '/')) {
+ if (hid_compare_device_paths(hdev, data->dev, '/')) {
kref_get(&data->kref);
return data;
}
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index ad7afa74d365..e0a06be5ef5c 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -4357,19 +4357,19 @@ static const struct wacom_features wacom_features_0x5E =
.check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
static const struct wacom_features wacom_features_0x90 =
{ "Wacom ISDv4 90", 26202, 16325, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
static const struct wacom_features wacom_features_0x93 =
{ "Wacom ISDv4 93", 26202, 16325, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
static const struct wacom_features wacom_features_0x97 =
{ "Wacom ISDv4 97", 26202, 16325, 511, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
static const struct wacom_features wacom_features_0x9A =
{ "Wacom ISDv4 9A", 26202, 16325, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
static const struct wacom_features wacom_features_0x9F =
{ "Wacom ISDv4 9F", 26202, 16325, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
static const struct wacom_features wacom_features_0xE2 =
{ "Wacom ISDv4 E2", 26202, 16325, 255, 0,
TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -4384,13 +4384,13 @@ static const struct wacom_features wacom_features_0xE6 =
TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
static const struct wacom_features wacom_features_0xEC =
{ "Wacom ISDv4 EC", 25710, 14500, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
static const struct wacom_features wacom_features_0xED =
{ "Wacom ISDv4 ED", 26202, 16325, 255, 0,
- TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
static const struct wacom_features wacom_features_0xEF =
{ "Wacom ISDv4 EF", 26202, 16325, 255, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
static const struct wacom_features wacom_features_0x100 =
{ "Wacom ISDv4 100", 26202, 16325, 255, 0,
MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -4408,10 +4408,10 @@ static const struct wacom_features wacom_features_0x10F =
MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
static const struct wacom_features wacom_features_0x116 =
{ "Wacom ISDv4 116", 26202, 16325, 255, 0,
- TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
static const struct wacom_features wacom_features_0x12C =
{ "Wacom ISDv4 12C", 27848, 15752, 2047, 0,
- TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+ TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
static const struct wacom_features wacom_features_0x4001 =
{ "Wacom ISDv4 4001", 26202, 16325, 255, 0,
MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ccf42663a908..81da17a42dc9 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1320,6 +1320,16 @@ config SENSORS_PWM_FAN
This driver can also be built as a module. If so, the module
will be called pwm-fan.
+config SENSORS_RASPBERRYPI_HWMON
+ tristate "Raspberry Pi voltage monitor"
+ depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
+ help
+ If you say yes here you get support for voltage sensor on the
+ Raspberry Pi.
+
+ This driver can also be built as a module. If so, the module
+ will be called raspberrypi-hwmon.
+
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 842c92f83ce6..93f7f41ea4ad 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -143,6 +143,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
new file mode 100644
index 000000000000..fb4e4a6bb1f6
--- /dev/null
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi voltage sensor driver
+ *
+ * Based on firmware/raspberrypi.c by Noralf Trønnes
+ *
+ * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define UNDERVOLTAGE_STICKY_BIT BIT(16)
+
+struct rpi_hwmon_data {
+ struct device *hwmon_dev;
+ struct rpi_firmware *fw;
+ u32 last_throttled;
+ struct delayed_work get_values_poll_work;
+};
+
+static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
+{
+ u32 new_uv, old_uv, value;
+ int ret;
+
+ /* Request firmware to clear sticky bits */
+ value = 0xffff;
+
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &value, sizeof(value));
+ if (ret) {
+ dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
+ ret);
+ return;
+ }
+
+ new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+ old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+ data->last_throttled = value;
+
+ if (new_uv == old_uv)
+ return;
+
+ if (new_uv)
+ dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
+ else
+ dev_info(data->hwmon_dev, "Voltage normalised\n");
+
+ sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
+}
+
+static void get_values_poll(struct work_struct *work)
+{
+ struct rpi_hwmon_data *data;
+
+ data = container_of(work, struct rpi_hwmon_data,
+ get_values_poll_work.work);
+
+ rpi_firmware_get_throttled(data);
+
+ /*
+ * We can't run faster than the sticky shift (100ms) since we get
+ * flipping in the sticky bits that are cleared.
+ */
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+}
+
+static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rpi_hwmon_data *data = dev_get_drvdata(dev);
+
+ *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+ return 0;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static const u32 rpi_in_config[] = {
+ HWMON_I_LCRIT_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info rpi_in = {
+ .type = hwmon_in,
+ .config = rpi_in_config,
+};
+
+static const struct hwmon_channel_info *rpi_info[] = {
+ &rpi_in,
+ NULL
+};
+
+static const struct hwmon_ops rpi_hwmon_ops = {
+ .is_visible = rpi_is_visible,
+ .read = rpi_read,
+};
+
+static const struct hwmon_chip_info rpi_chip_info = {
+ .ops = &rpi_hwmon_ops,
+ .info = rpi_info,
+};
+
+static int rpi_hwmon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rpi_hwmon_data *data;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Parent driver assure that firmware is correct */
+ data->fw = dev_get_drvdata(dev->parent);
+
+ /* Init throttled */
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &data->last_throttled,
+ sizeof(data->last_throttled));
+
+ data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
+ data,
+ &rpi_chip_info,
+ NULL);
+
+ INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+ platform_set_drvdata(pdev, data);
+
+ if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+
+ return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int rpi_hwmon_remove(struct platform_device *pdev)
+{
+ struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&data->get_values_poll_work);
+
+ return 0;
+}
+
+static struct platform_driver rpi_hwmon_driver = {
+ .probe = rpi_hwmon_probe,
+ .remove = rpi_hwmon_remove,
+ .driver = {
+ .name = "raspberrypi-hwmon",
+ },
+};
+module_platform_driver(rpi_hwmon_driver);
+
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4f8df2ec87b1..451d4ae50e66 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -116,24 +116,21 @@ config I2C_I801
DH89xxCC (PCH)
Panther Point (PCH)
Lynx Point (PCH)
- Lynx Point-LP (PCH)
Avoton (SOC)
Wellsburg (PCH)
Coleto Creek (PCH)
Wildcat Point (PCH)
- Wildcat Point-LP (PCH)
BayTrail (SOC)
Braswell (SOC)
- Sunrise Point-H (PCH)
- Sunrise Point-LP (PCH)
- Kaby Lake-H (PCH)
+ Sunrise Point (PCH)
+ Kaby Lake (PCH)
DNV (SOC)
Broxton (SOC)
Lewisburg (PCH)
Gemini Lake (SOC)
- Cannon Lake-H (PCH)
- Cannon Lake-LP (PCH)
+ Cannon Lake (PCH)
Cedar Fork (PCH)
+ Ice Lake (PCH)
This driver can also be built as a module. If so, the module
will be called i2c-i801.
@@ -762,6 +759,13 @@ config I2C_OMAP
Like OMAP1510/1610/1710/5912 and OMAP242x.
For details see http://www.ti.com/omap.
+config I2C_OWL
+ tristate "Actions Semiconductor Owl I2C Controller"
+ depends on ARCH_ACTIONS || COMPILE_TEST
+ help
+ Say Y here if you want to use the I2C bus controller on
+ the Actions Semiconductor Owl SoC's.
+
config I2C_PASEMI
tristate "PA Semi SMBus interface"
depends on PPC_PASEMI && PCI
@@ -828,6 +832,19 @@ config I2C_PXA_SLAVE
is necessary for systems where the PXA may be a target on the
I2C bus.
+config I2C_QCOM_GENI
+ tristate "Qualcomm Technologies Inc.'s GENI based I2C controller"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on QCOM_GENI_SE
+ help
+ This driver supports GENI serial engine based I2C controller in
+ master mode on the Qualcomm Technologies Inc.'s SoCs. If you say
+ yes to this option, support will be included for the built-in I2C
+ interface on the Qualcomm Technologies Inc.'s SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-qcom-geni.
+
config I2C_QUP
tristate "Qualcomm QUP based I2C controller"
depends on ARCH_QCOM
@@ -1330,4 +1347,15 @@ config I2C_ZX2967
This driver can also be built as a module. If so, the module will be
called i2c-zx2967.
+config I2C_FSI
+ tristate "FSI I2C driver"
+ depends on FSI
+ help
+ Driver for FSI bus attached I2C masters. These are I2C masters that
+ are connected to the system over an FSI bus, instead of the more
+ common PCI or MMIO interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called as i2c-fsi.
+
endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 5a869144a0c5..18b26af82b1c 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
+obj-$(CONFIG_I2C_OWL) += i2c-owl.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
@@ -83,6 +84,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
+obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o
obj-$(CONFIG_I2C_QUP) += i2c-qup.o
obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
@@ -137,5 +139,6 @@ obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
+obj-$(CONFIG_I2C_FSI) += i2c-fsi.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 95a80a8f81b5..134567f3019f 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -384,6 +384,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
if (status)
return status;
len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
+ /* fall through */
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < len; i++) {
status = amd_ec_read(smbus, AMD_SMB_DATA + i,
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 60e4d0e939a3..a4f956c6d567 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -111,22 +111,22 @@
#define ASPEED_I2CD_DEV_ADDR_MASK GENMASK(6, 0)
enum aspeed_i2c_master_state {
+ ASPEED_I2C_MASTER_INACTIVE,
ASPEED_I2C_MASTER_START,
ASPEED_I2C_MASTER_TX_FIRST,
ASPEED_I2C_MASTER_TX,
ASPEED_I2C_MASTER_RX_FIRST,
ASPEED_I2C_MASTER_RX,
ASPEED_I2C_MASTER_STOP,
- ASPEED_I2C_MASTER_INACTIVE,
};
enum aspeed_i2c_slave_state {
+ ASPEED_I2C_SLAVE_STOP,
ASPEED_I2C_SLAVE_START,
ASPEED_I2C_SLAVE_READ_REQUESTED,
ASPEED_I2C_SLAVE_READ_PROCESSED,
ASPEED_I2C_SLAVE_WRITE_REQUESTED,
ASPEED_I2C_SLAVE_WRITE_RECEIVED,
- ASPEED_I2C_SLAVE_STOP,
};
struct aspeed_i2c_bus {
@@ -234,7 +234,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
bool irq_handled = true;
u8 value;
- spin_lock(&bus->lock);
if (!slave) {
irq_handled = false;
goto out;
@@ -325,7 +324,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
writel(status_ack, bus->base + ASPEED_I2C_INTR_STS_REG);
out:
- spin_unlock(&bus->lock);
return irq_handled;
}
#endif /* CONFIG_I2C_SLAVE */
@@ -389,7 +387,6 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
u8 recv_byte;
int ret;
- spin_lock(&bus->lock);
irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
/* Ack all interrupt bits. */
writel(irq_status, bus->base + ASPEED_I2C_INTR_STS_REG);
@@ -407,7 +404,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
*/
ret = aspeed_i2c_is_irq_error(irq_status);
if (ret < 0) {
- dev_dbg(bus->dev, "received error interrupt: 0x%08x",
+ dev_dbg(bus->dev, "received error interrupt: 0x%08x\n",
irq_status);
bus->cmd_err = ret;
bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
@@ -416,7 +413,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
/* We are in an invalid state; reset bus to a known state. */
if (!bus->msgs) {
- dev_err(bus->dev, "bus in unknown state");
+ dev_err(bus->dev, "bus in unknown state\n");
bus->cmd_err = -EIO;
if (bus->master_state != ASPEED_I2C_MASTER_STOP)
aspeed_i2c_do_stop(bus);
@@ -431,7 +428,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
*/
if (bus->master_state == ASPEED_I2C_MASTER_START) {
if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {
- pr_devel("no slave present at %02x", msg->addr);
+ pr_devel("no slave present at %02x\n", msg->addr);
status_ack |= ASPEED_I2CD_INTR_TX_NAK;
bus->cmd_err = -ENXIO;
aspeed_i2c_do_stop(bus);
@@ -451,11 +448,11 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
switch (bus->master_state) {
case ASPEED_I2C_MASTER_TX:
if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_NAK)) {
- dev_dbg(bus->dev, "slave NACKed TX");
+ dev_dbg(bus->dev, "slave NACKed TX\n");
status_ack |= ASPEED_I2CD_INTR_TX_NAK;
goto error_and_stop;
} else if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {
- dev_err(bus->dev, "slave failed to ACK TX");
+ dev_err(bus->dev, "slave failed to ACK TX\n");
goto error_and_stop;
}
status_ack |= ASPEED_I2CD_INTR_TX_ACK;
@@ -478,7 +475,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
/* fallthrough intended */
case ASPEED_I2C_MASTER_RX:
if (unlikely(!(irq_status & ASPEED_I2CD_INTR_RX_DONE))) {
- dev_err(bus->dev, "master failed to RX");
+ dev_err(bus->dev, "master failed to RX\n");
goto error_and_stop;
}
status_ack |= ASPEED_I2CD_INTR_RX_DONE;
@@ -509,7 +506,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
goto out_no_complete;
case ASPEED_I2C_MASTER_STOP:
if (unlikely(!(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))) {
- dev_err(bus->dev, "master failed to STOP");
+ dev_err(bus->dev, "master failed to STOP\n");
bus->cmd_err = -EIO;
/* Do not STOP as we have already tried. */
} else {
@@ -520,7 +517,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
goto out_complete;
case ASPEED_I2C_MASTER_INACTIVE:
dev_err(bus->dev,
- "master received interrupt 0x%08x, but is inactive",
+ "master received interrupt 0x%08x, but is inactive\n",
irq_status);
bus->cmd_err = -EIO;
/* Do not STOP as we should be inactive. */
@@ -547,22 +544,29 @@ out_no_complete:
dev_err(bus->dev,
"irq handled != irq. expected 0x%08x, but was 0x%08x\n",
irq_status, status_ack);
- spin_unlock(&bus->lock);
return !!irq_status;
}
static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
{
struct aspeed_i2c_bus *bus = dev_id;
+ bool ret;
+
+ spin_lock(&bus->lock);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
if (aspeed_i2c_slave_irq(bus)) {
dev_dbg(bus->dev, "irq handled by slave.\n");
- return IRQ_HANDLED;
+ ret = true;
+ goto out;
}
#endif /* CONFIG_I2C_SLAVE */
- return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE;
+ ret = aspeed_i2c_master_irq(bus);
+
+out:
+ spin_unlock(&bus->lock);
+ return ret ? IRQ_HANDLED : IRQ_NONE;
}
static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
@@ -851,7 +855,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
if (IS_ERR(bus->rst)) {
dev_err(&pdev->dev,
- "missing or invalid reset controller device tree entry");
+ "missing or invalid reset controller device tree entry\n");
return PTR_ERR(bus->rst);
}
reset_control_deassert(bus->rst);
@@ -868,7 +872,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
if (!match)
bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val;
else
- bus->get_clk_reg_val = match->data;
+ bus->get_clk_reg_val = (u32 (*)(u32))match->data;
/* Initialize the I2C adapter */
spin_lock_init(&bus->lock);
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 78792b4d6437..826d32049996 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -689,9 +689,9 @@ static int brcmstb_i2c_suspend(struct device *dev)
{
struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
- i2c_lock_adapter(&i2c_dev->adapter);
+ i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = true;
- i2c_unlock_adapter(&i2c_dev->adapter);
+ i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
@@ -700,10 +700,10 @@ static int brcmstb_i2c_resume(struct device *dev)
{
struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
- i2c_lock_adapter(&i2c_dev->adapter);
+ i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
brcmstb_i2c_set_bsc_reg_defaults(i2c_dev);
i2c_dev->is_suspended = false;
- i2c_unlock_adapter(&i2c_dev->adapter);
+ i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 7379043711df..11caafa0e050 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -718,14 +718,14 @@ static int i2c_davinci_cpufreq_transition(struct notifier_block *nb,
dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
- i2c_lock_adapter(&dev->adapter);
+ i2c_lock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
if (val == CPUFREQ_PRECHANGE) {
davinci_i2c_reset_ctrl(dev, 0);
} else if (val == CPUFREQ_POSTCHANGE) {
i2c_davinci_calc_clk_dividers(dev);
davinci_i2c_reset_ctrl(dev, 1);
}
- i2c_unlock_adapter(&dev->adapter);
+ i2c_unlock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-designware-baytrail.c b/drivers/i2c/busses/i2c-designware-baytrail.c
index dbda8c9c8a1c..a2a275cfc1f6 100644
--- a/drivers/i2c/busses/i2c-designware-baytrail.c
+++ b/drivers/i2c/busses/i2c-designware-baytrail.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Intel BayTrail PMIC I2C bus semaphore implementaion
* Copyright (c) 2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
*/
#include <linux/delay.h>
#include <linux/device.h>
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index 48914dfc8ce8..69ec4a791f23 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Synopsys DesignWare I2C adapter driver.
*
@@ -6,20 +7,6 @@
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
#include <linux/clk.h>
#include <linux/delay.h>
@@ -31,6 +18,7 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/swab.h>
#include "i2c-designware-core.h"
@@ -94,6 +82,40 @@ void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
}
}
+/**
+ * i2c_dw_set_reg_access() - Set register access flags
+ * @dev: device private data
+ *
+ * Autodetects needed register access mode and sets access flags accordingly.
+ * This must be called before doing any other register access.
+ */
+int i2c_dw_set_reg_access(struct dw_i2c_dev *dev)
+{
+ u32 reg;
+ int ret;
+
+ ret = i2c_dw_acquire_lock(dev);
+ if (ret)
+ return ret;
+
+ reg = dw_readl(dev, DW_IC_COMP_TYPE);
+ i2c_dw_release_lock(dev);
+
+ if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
+ /* Configure register endianess access */
+ dev->flags |= ACCESS_SWAP;
+ } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
+ /* Configure register access mode 16bit */
+ dev->flags |= ACCESS_16BIT;
+ } else if (reg != DW_IC_COMP_TYPE_VALUE) {
+ dev_err(dev->dev,
+ "Unknown Synopsys component type: 0x%08x\n", reg);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
{
/*
@@ -149,6 +171,47 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
}
+int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
+{
+ u32 reg;
+ int ret;
+
+ ret = i2c_dw_acquire_lock(dev);
+ if (ret)
+ return ret;
+
+ /* Configure SDA Hold Time if required */
+ reg = dw_readl(dev, DW_IC_COMP_VERSION);
+ if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
+ if (!dev->sda_hold_time) {
+ /* Keep previous hold time setting if no one set it */
+ dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
+ }
+
+ /*
+ * Workaround for avoiding TX arbitration lost in case I2C
+ * slave pulls SDA down "too quickly" after falling egde of
+ * SCL by enabling non-zero SDA RX hold. Specification says it
+ * extends incoming SDA low to high transition while SCL is
+ * high but it apprears to help also above issue.
+ */
+ if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
+ dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
+
+ dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n",
+ dev->sda_hold_time & ~(u32)DW_IC_SDA_HOLD_RX_MASK,
+ dev->sda_hold_time >> DW_IC_SDA_HOLD_RX_SHIFT);
+ } else if (dev->sda_hold_time) {
+ dev_warn(dev->dev,
+ "Hardware too old to adjust SDA hold time.\n");
+ dev->sda_hold_time = 0;
+ }
+
+ i2c_dw_release_lock(dev);
+
+ return 0;
+}
+
void __i2c_dw_disable(struct dw_i2c_dev *dev)
{
int timeout = 100;
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index d690e648bc01..e367b1af4ab2 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Synopsys DesignWare I2C adapter driver.
*
@@ -6,20 +7,6 @@
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
#include <linux/i2c.h>
@@ -212,7 +199,8 @@
* @tx_fifo_depth: depth of the hardware tx fifo
* @rx_fifo_depth: depth of the hardware rx fifo
* @rx_outstanding: current master-rx elements in tx fifo
- * @clk_freq: bus clock frequency
+ * @timings: bus clock frequency, SDA hold and other timings
+ * @sda_hold_time: SDA hold value
* @ss_hcnt: standard speed HCNT value
* @ss_lcnt: standard speed LCNT value
* @fs_hcnt: fast speed HCNT value
@@ -264,10 +252,8 @@ struct dw_i2c_dev {
unsigned int tx_fifo_depth;
unsigned int rx_fifo_depth;
int rx_outstanding;
- u32 clk_freq;
+ struct i2c_timings timings;
u32 sda_hold_time;
- u32 sda_falling_time;
- u32 scl_falling_time;
u16 ss_hcnt;
u16 ss_lcnt;
u16 fs_hcnt;
@@ -295,8 +281,10 @@ struct dw_i2c_dev {
u32 dw_readl(struct dw_i2c_dev *dev, int offset);
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+int i2c_dw_set_reg_access(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
+int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 27436a937492..e18442b9973a 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Synopsys DesignWare I2C adapter driver (master only).
*
@@ -6,20 +7,6 @@
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
#include <linux/delay.h>
#include <linux/err.h>
@@ -45,90 +32,79 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
dw_writel(dev, dev->master_cfg, DW_IC_CON);
}
-/**
- * i2c_dw_init() - Initialize the designware I2C master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- */
-static int i2c_dw_init_master(struct dw_i2c_dev *dev)
+static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
{
- u32 hcnt, lcnt;
- u32 reg, comp_param1;
+ u32 ic_clk = i2c_dw_clk_rate(dev);
+ const char *mode_str, *fp_str = "";
+ u32 comp_param1;
u32 sda_falling_time, scl_falling_time;
+ struct i2c_timings *t = &dev->timings;
int ret;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
-
- reg = dw_readl(dev, DW_IC_COMP_TYPE);
- if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
- /* Configure register endianess access */
- dev->flags |= ACCESS_SWAP;
- } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
- /* Configure register access mode 16bit */
- dev->flags |= ACCESS_16BIT;
- } else if (reg != DW_IC_COMP_TYPE_VALUE) {
- dev_err(dev->dev,
- "Unknown Synopsys component type: 0x%08x\n", reg);
- i2c_dw_release_lock(dev);
- return -ENODEV;
- }
-
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
+ i2c_dw_release_lock(dev);
- /* Disable the adapter */
- __i2c_dw_disable(dev);
-
- /* Set standard and fast speed deviders for high/low periods */
-
- sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
- scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
+ /* Set standard and fast speed dividers for high/low periods */
+ sda_falling_time = t->sda_fall_ns ?: 300; /* ns */
+ scl_falling_time = t->scl_fall_ns ?: 300; /* ns */
- /* Set SCL timing parameters for standard-mode */
- if (dev->ss_hcnt && dev->ss_lcnt) {
- hcnt = dev->ss_hcnt;
- lcnt = dev->ss_lcnt;
- } else {
- hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
+ /* Calculate SCL timing parameters for standard mode if not set */
+ if (!dev->ss_hcnt || !dev->ss_lcnt) {
+ dev->ss_hcnt =
+ i2c_dw_scl_hcnt(ic_clk,
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
+ dev->ss_lcnt =
+ i2c_dw_scl_lcnt(ic_clk,
4700, /* tLOW = 4.7 us */
scl_falling_time,
0); /* No offset */
}
- dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
- dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
- /* Set SCL timing parameters for fast-mode or fast-mode plus */
- if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
- hcnt = dev->fp_hcnt;
- lcnt = dev->fp_lcnt;
- } else if (dev->fs_hcnt && dev->fs_lcnt) {
- hcnt = dev->fs_hcnt;
- lcnt = dev->fs_lcnt;
- } else {
- hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
+ dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n",
+ dev->ss_hcnt, dev->ss_lcnt);
+
+ /*
+ * Set SCL timing parameters for fast mode or fast mode plus. Only
+ * difference is the timing parameter values since the registers are
+ * the same.
+ */
+ if (t->bus_freq_hz == 1000000) {
+ /*
+ * Check are fast mode plus parameters available and use
+ * fast mode if not.
+ */
+ if (dev->fp_hcnt && dev->fp_lcnt) {
+ dev->fs_hcnt = dev->fp_hcnt;
+ dev->fs_lcnt = dev->fp_lcnt;
+ fp_str = " Plus";
+ }
+ }
+ /*
+ * Calculate SCL timing parameters for fast mode if not set. They are
+ * needed also in high speed mode.
+ */
+ if (!dev->fs_hcnt || !dev->fs_lcnt) {
+ dev->fs_hcnt =
+ i2c_dw_scl_hcnt(ic_clk,
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
0, /* 0: DW default, 1: Ideal */
0); /* No offset */
- lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
+ dev->fs_lcnt =
+ i2c_dw_scl_lcnt(ic_clk,
1300, /* tLOW = 1.3 us */
scl_falling_time,
0); /* No offset */
}
- dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
- dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+ dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
+ fp_str, dev->fs_hcnt, dev->fs_lcnt);
+ /* Check is high speed possible and fall back to fast mode if not */
if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
DW_IC_CON_SPEED_HIGH) {
if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
@@ -136,37 +112,70 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
dev_err(dev->dev, "High Speed not supported!\n");
dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+ dev->hs_hcnt = 0;
+ dev->hs_lcnt = 0;
} else if (dev->hs_hcnt && dev->hs_lcnt) {
- hcnt = dev->hs_hcnt;
- lcnt = dev->hs_lcnt;
- dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
- dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
- dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
- hcnt, lcnt);
+ dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n",
+ dev->hs_hcnt, dev->hs_lcnt);
}
}
- /* Configure SDA Hold Time if required */
- reg = dw_readl(dev, DW_IC_COMP_VERSION);
- if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
- if (!dev->sda_hold_time) {
- /* Keep previous hold time setting if no one set it */
- dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
- }
- /*
- * Workaround for avoiding TX arbitration lost in case I2C
- * slave pulls SDA down "too quickly" after falling egde of
- * SCL by enabling non-zero SDA RX hold. Specification says it
- * extends incoming SDA low to high transition while SCL is
- * high but it apprears to help also above issue.
- */
- if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
- dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
- dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
- } else if (dev->sda_hold_time) {
- dev_warn(dev->dev,
- "Hardware too old to adjust SDA hold time.\n");
+ ret = i2c_dw_set_sda_hold(dev);
+ if (ret)
+ goto out;
+
+ switch (dev->master_cfg & DW_IC_CON_SPEED_MASK) {
+ case DW_IC_CON_SPEED_STD:
+ mode_str = "Standard Mode";
+ break;
+ case DW_IC_CON_SPEED_HIGH:
+ mode_str = "High Speed Mode";
+ break;
+ default:
+ mode_str = "Fast Mode";
}
+ dev_dbg(dev->dev, "Bus speed: %s%s\n", mode_str, fp_str);
+
+out:
+ return ret;
+}
+
+/**
+ * i2c_dw_init() - Initialize the designware I2C master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+static int i2c_dw_init_master(struct dw_i2c_dev *dev)
+{
+ int ret;
+
+ ret = i2c_dw_acquire_lock(dev);
+ if (ret)
+ return ret;
+
+ /* Disable the adapter */
+ __i2c_dw_disable(dev);
+
+ /* Write standard speed timing parameters */
+ dw_writel(dev, dev->ss_hcnt, DW_IC_SS_SCL_HCNT);
+ dw_writel(dev, dev->ss_lcnt, DW_IC_SS_SCL_LCNT);
+
+ /* Write fast mode/fast mode plus timing parameters */
+ dw_writel(dev, dev->fs_hcnt, DW_IC_FS_SCL_HCNT);
+ dw_writel(dev, dev->fs_lcnt, DW_IC_FS_SCL_LCNT);
+
+ /* Write high speed timing parameters if supported */
+ if (dev->hs_hcnt && dev->hs_lcnt) {
+ dw_writel(dev, dev->hs_hcnt, DW_IC_HS_SCL_HCNT);
+ dw_writel(dev, dev->hs_lcnt, DW_IC_HS_SCL_LCNT);
+ }
+
+ /* Write SDA hold time if supported */
+ if (dev->sda_hold_time)
+ dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
i2c_dw_configure_fifo_master(dev);
i2c_dw_release_lock(dev);
@@ -253,13 +262,6 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
break;
}
- if (msgs[dev->msg_write_idx].len == 0) {
- dev_err(dev->dev,
- "%s: invalid message length\n", __func__);
- dev->msg_err = -EINVAL;
- break;
- }
-
if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
/* new i2c_msg */
buf = msgs[dev->msg_write_idx].buf;
@@ -502,6 +504,10 @@ static const struct i2c_algorithm i2c_dw_algo = {
.functionality = i2c_dw_func,
};
+static const struct i2c_adapter_quirks i2c_dw_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{
u32 stat;
@@ -681,6 +687,14 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
dev->disable = i2c_dw_disable;
dev->disable_int = i2c_dw_disable_int;
+ ret = i2c_dw_set_reg_access(dev);
+ if (ret)
+ return ret;
+
+ ret = i2c_dw_set_timings_master(dev);
+ if (ret)
+ return ret;
+
ret = dev->init(dev);
if (ret)
return ret;
@@ -689,6 +703,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
"Synopsys DesignWare I2C adapter");
adap->retries = 3;
adap->algo = &i2c_dw_algo;
+ adap->quirks = &i2c_dw_quirks;
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 86e1bd0b82e9..d50f80487214 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Synopsys DesignWare I2C adapter driver (master only).
*
@@ -7,22 +8,7 @@
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
* Copyright (C) 2011, 2015, 2016 Intel Corporation.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
-
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -105,6 +91,7 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
case 0x0817:
c->bus_cfg &= ~DW_IC_CON_SPEED_MASK;
c->bus_cfg |= DW_IC_CON_SPEED_STD;
+ /* fall through */
case 0x0818:
case 0x0819:
c->bus_num = pdev->device - 0x817 + 3;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 5660daf6c92e..1a8d2da5b000 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Synopsys DesignWare I2C adapter driver.
*
@@ -6,20 +7,6 @@
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
#include <linux/acpi.h>
#include <linux/clk-provider.h>
@@ -96,6 +83,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
static int dw_i2c_acpi_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ struct i2c_timings *t = &dev->timings;
u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
const struct acpi_device_id *id;
@@ -115,7 +103,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
- switch (dev->clk_freq) {
+ switch (t->bus_freq_hz) {
case 100000:
dev->sda_hold_time = ss_ht;
break;
@@ -175,6 +163,8 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
{
+ struct i2c_timings *t = &dev->timings;
+
dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
@@ -182,7 +172,7 @@ static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
dev->mode = DW_IC_MASTER;
- switch (dev->clk_freq) {
+ switch (t->bus_freq_hz) {
case 100000:
dev->master_cfg |= DW_IC_CON_SPEED_STD;
break;
@@ -240,7 +230,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct i2c_adapter *adap;
struct dw_i2c_dev *dev;
- u32 acpi_speed, ht = 0;
+ struct i2c_timings *t;
+ u32 acpi_speed;
struct resource *mem;
int i, irq, ret;
static const int supported_speeds[] = {
@@ -272,18 +263,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
reset_control_deassert(dev->rst);
}
- if (pdata) {
- dev->clk_freq = pdata->i2c_scl_freq;
- } else {
- device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
- &ht);
- device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
- &dev->sda_falling_time);
- device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
- &dev->scl_falling_time);
- device_property_read_u32(&pdev->dev, "clock-frequency",
- &dev->clk_freq);
- }
+ t = &dev->timings;
+ if (pdata)
+ t->bus_freq_hz = pdata->i2c_scl_freq;
+ else
+ i2c_parse_fw_timings(&pdev->dev, t, false);
acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
/*
@@ -300,12 +284,12 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
* Find bus speed from the "clock-frequency" device property, ACPI
* or by using fast mode if neither is set.
*/
- if (acpi_speed && dev->clk_freq)
- dev->clk_freq = min(dev->clk_freq, acpi_speed);
- else if (acpi_speed || dev->clk_freq)
- dev->clk_freq = max(dev->clk_freq, acpi_speed);
+ if (acpi_speed && t->bus_freq_hz)
+ t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed);
+ else if (acpi_speed || t->bus_freq_hz)
+ t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
else
- dev->clk_freq = 400000;
+ t->bus_freq_hz = 400000;
if (has_acpi_companion(&pdev->dev))
dw_i2c_acpi_configure(pdev);
@@ -314,11 +298,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
* Only standard mode at 100kHz, fast mode at 400kHz,
* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
*/
- if (dev->clk_freq != 100000 && dev->clk_freq != 400000
- && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
+ if (t->bus_freq_hz != 100000 && t->bus_freq_hz != 400000 &&
+ t->bus_freq_hz != 1000000 && t->bus_freq_hz != 3400000) {
dev_err(&pdev->dev,
"%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n",
- dev->clk_freq);
+ t->bus_freq_hz);
ret = -EINVAL;
goto exit_reset;
}
@@ -334,12 +318,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_prepare_clk(dev, true)) {
+ u64 clk_khz;
+
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+ clk_khz = dev->get_clk_rate_khz(dev);
- if (!dev->sda_hold_time && ht)
- dev->sda_hold_time = div_u64(
- (u64)dev->get_clk_rate_khz(dev) * ht + 500000,
- 1000000);
+ if (!dev->sda_hold_time && t->sda_hold_ns)
+ dev->sda_hold_time =
+ div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
}
dw_i2c_set_fifo_size(dev, pdev->id);
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index 8ce2cd368477..e7f9305b2dd9 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -1,23 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Synopsys DesignWare I2C adapter driver (slave only).
*
* Based on the Synopsys DesignWare I2C adapter driver (master).
*
* Copyright (C) 2016 Synopsys Inc.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
*/
#include <linux/delay.h>
#include <linux/err.h>
@@ -51,53 +38,18 @@ static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
*/
static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
{
- u32 reg, comp_param1;
int ret;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
- reg = dw_readl(dev, DW_IC_COMP_TYPE);
- if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
- /* Configure register endianness access. */
- dev->flags |= ACCESS_SWAP;
- } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
- /* Configure register access mode 16bit. */
- dev->flags |= ACCESS_16BIT;
- } else if (reg != DW_IC_COMP_TYPE_VALUE) {
- dev_err(dev->dev,
- "Unknown Synopsys component type: 0x%08x\n", reg);
- i2c_dw_release_lock(dev);
- return -ENODEV;
- }
-
- comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
-
/* Disable the adapter. */
__i2c_dw_disable(dev);
- /* Configure SDA Hold Time if required. */
- reg = dw_readl(dev, DW_IC_COMP_VERSION);
- if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
- if (!dev->sda_hold_time) {
- /* Keep previous hold time setting if no one set it. */
- dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
- }
- /*
- * Workaround for avoiding TX arbitration lost in case I2C
- * slave pulls SDA down "too quickly" after falling egde of
- * SCL by enabling non-zero SDA RX hold. Specification says it
- * extends incoming SDA low to high transition while SCL is
- * high but it apprears to help also above issue.
- */
- if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
- dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
+ /* Write SDA hold time if supported */
+ if (dev->sda_hold_time)
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
- } else {
- dev_warn(dev->dev,
- "Hardware too old to adjust SDA hold time.\n");
- }
i2c_dw_configure_fifo_slave(dev);
i2c_dw_release_lock(dev);
@@ -299,6 +251,14 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
dev->disable = i2c_dw_disable;
dev->disable_int = i2c_dw_disable_int;
+ ret = i2c_dw_set_reg_access(dev);
+ if (ret)
+ return ret;
+
+ ret = i2c_dw_set_sda_hold(dev);
+ if (ret)
+ return ret;
+
ret = dev->init(dev);
if (ret)
return ret;
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index de82ad8ff534..c1ce2299a76e 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -176,7 +176,10 @@
#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100))
-#define HSI2C_EXYNOS7 BIT(0)
+enum i2c_type_exynos {
+ I2C_TYPE_EXYNOS5,
+ I2C_TYPE_EXYNOS7,
+};
struct exynos5_i2c {
struct i2c_adapter adap;
@@ -212,27 +215,30 @@ struct exynos5_i2c {
/**
* struct exynos_hsi2c_variant - platform specific HSI2C driver data
* @fifo_depth: the fifo depth supported by the HSI2C module
+ * @hw: the hardware variant of Exynos I2C controller
*
* Specifies platform specific configuration of HSI2C module.
* Note: A structure for driver specific platform data is used for future
* expansion of its usage.
*/
struct exynos_hsi2c_variant {
- unsigned int fifo_depth;
- unsigned int hw;
+ unsigned int fifo_depth;
+ enum i2c_type_exynos hw;
};
static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
.fifo_depth = 64,
+ .hw = I2C_TYPE_EXYNOS5,
};
static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
.fifo_depth = 16,
+ .hw = I2C_TYPE_EXYNOS5,
};
static const struct exynos_hsi2c_variant exynos7_hsi2c_data = {
.fifo_depth = 16,
- .hw = HSI2C_EXYNOS7,
+ .hw = I2C_TYPE_EXYNOS7,
};
static const struct of_device_id exynos5_i2c_match[] = {
@@ -300,7 +306,7 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
*/
t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
temp = clkin / op_clk - 8 - t_ftl_cycle;
- if (i2c->variant->hw != HSI2C_EXYNOS7)
+ if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
temp -= t_ftl_cycle;
div = temp / 512;
clk_cycle = temp / (div + 1) - 2;
@@ -424,7 +430,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
writel(int_status, i2c->regs + HSI2C_INT_STATUS);
/* handle interrupt related to the transfer status */
- if (i2c->variant->hw == HSI2C_EXYNOS7) {
+ if (i2c->variant->hw == I2C_TYPE_EXYNOS7) {
if (int_status & HSI2C_INT_TRANS_DONE) {
i2c->trans_done = 1;
i2c->state = 0;
@@ -571,7 +577,7 @@ static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
{
unsigned long timeout;
- if (i2c->variant->hw != HSI2C_EXYNOS7)
+ if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
return;
/*
@@ -612,7 +618,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
unsigned long flags;
unsigned short trig_lvl;
- if (i2c->variant->hw == HSI2C_EXYNOS7)
+ if (i2c->variant->hw == I2C_TYPE_EXYNOS7)
int_en |= HSI2C_INT_I2C_TRANS;
else
int_en |= HSI2C_INT_I2C;
diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
new file mode 100644
index 000000000000..1e2be2219a60
--- /dev/null
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -0,0 +1,752 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * FSI-attached I2C master algorithm
+ *
+ * Copyright 2018 IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fsi.h>
+#include <linux/i2c.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define FSI_ENGID_I2C 0x7
+
+#define I2C_DEFAULT_CLK_DIV 6
+
+/* i2c registers */
+#define I2C_FSI_FIFO 0x00
+#define I2C_FSI_CMD 0x04
+#define I2C_FSI_MODE 0x08
+#define I2C_FSI_WATER_MARK 0x0C
+#define I2C_FSI_INT_MASK 0x10
+#define I2C_FSI_INT_COND 0x14
+#define I2C_FSI_OR_INT_MASK 0x14
+#define I2C_FSI_INTS 0x18
+#define I2C_FSI_AND_INT_MASK 0x18
+#define I2C_FSI_STAT 0x1C
+#define I2C_FSI_RESET_I2C 0x1C
+#define I2C_FSI_ESTAT 0x20
+#define I2C_FSI_RESET_ERR 0x20
+#define I2C_FSI_RESID_LEN 0x24
+#define I2C_FSI_SET_SCL 0x24
+#define I2C_FSI_PORT_BUSY 0x28
+#define I2C_FSI_RESET_SCL 0x2C
+#define I2C_FSI_SET_SDA 0x30
+#define I2C_FSI_RESET_SDA 0x34
+
+/* cmd register */
+#define I2C_CMD_WITH_START BIT(31)
+#define I2C_CMD_WITH_ADDR BIT(30)
+#define I2C_CMD_RD_CONT BIT(29)
+#define I2C_CMD_WITH_STOP BIT(28)
+#define I2C_CMD_FORCELAUNCH BIT(27)
+#define I2C_CMD_ADDR GENMASK(23, 17)
+#define I2C_CMD_READ BIT(16)
+#define I2C_CMD_LEN GENMASK(15, 0)
+
+/* mode register */
+#define I2C_MODE_CLKDIV GENMASK(31, 16)
+#define I2C_MODE_PORT GENMASK(15, 10)
+#define I2C_MODE_ENHANCED BIT(3)
+#define I2C_MODE_DIAG BIT(2)
+#define I2C_MODE_PACE_ALLOW BIT(1)
+#define I2C_MODE_WRAP BIT(0)
+
+/* watermark register */
+#define I2C_WATERMARK_HI GENMASK(15, 12)
+#define I2C_WATERMARK_LO GENMASK(7, 4)
+
+#define I2C_FIFO_HI_LVL 4
+#define I2C_FIFO_LO_LVL 4
+
+/* interrupt register */
+#define I2C_INT_INV_CMD BIT(15)
+#define I2C_INT_PARITY BIT(14)
+#define I2C_INT_BE_OVERRUN BIT(13)
+#define I2C_INT_BE_ACCESS BIT(12)
+#define I2C_INT_LOST_ARB BIT(11)
+#define I2C_INT_NACK BIT(10)
+#define I2C_INT_DAT_REQ BIT(9)
+#define I2C_INT_CMD_COMP BIT(8)
+#define I2C_INT_STOP_ERR BIT(7)
+#define I2C_INT_BUSY BIT(6)
+#define I2C_INT_IDLE BIT(5)
+
+/* status register */
+#define I2C_STAT_INV_CMD BIT(31)
+#define I2C_STAT_PARITY BIT(30)
+#define I2C_STAT_BE_OVERRUN BIT(29)
+#define I2C_STAT_BE_ACCESS BIT(28)
+#define I2C_STAT_LOST_ARB BIT(27)
+#define I2C_STAT_NACK BIT(26)
+#define I2C_STAT_DAT_REQ BIT(25)
+#define I2C_STAT_CMD_COMP BIT(24)
+#define I2C_STAT_STOP_ERR BIT(23)
+#define I2C_STAT_MAX_PORT GENMASK(19, 16)
+#define I2C_STAT_ANY_INT BIT(15)
+#define I2C_STAT_SCL_IN BIT(11)
+#define I2C_STAT_SDA_IN BIT(10)
+#define I2C_STAT_PORT_BUSY BIT(9)
+#define I2C_STAT_SELF_BUSY BIT(8)
+#define I2C_STAT_FIFO_COUNT GENMASK(7, 0)
+
+#define I2C_STAT_ERR (I2C_STAT_INV_CMD | \
+ I2C_STAT_PARITY | \
+ I2C_STAT_BE_OVERRUN | \
+ I2C_STAT_BE_ACCESS | \
+ I2C_STAT_LOST_ARB | \
+ I2C_STAT_NACK | \
+ I2C_STAT_STOP_ERR)
+#define I2C_STAT_ANY_RESP (I2C_STAT_ERR | \
+ I2C_STAT_DAT_REQ | \
+ I2C_STAT_CMD_COMP)
+
+/* extended status register */
+#define I2C_ESTAT_FIFO_SZ GENMASK(31, 24)
+#define I2C_ESTAT_SCL_IN_SY BIT(15)
+#define I2C_ESTAT_SDA_IN_SY BIT(14)
+#define I2C_ESTAT_S_SCL BIT(13)
+#define I2C_ESTAT_S_SDA BIT(12)
+#define I2C_ESTAT_M_SCL BIT(11)
+#define I2C_ESTAT_M_SDA BIT(10)
+#define I2C_ESTAT_HI_WATER BIT(9)
+#define I2C_ESTAT_LO_WATER BIT(8)
+#define I2C_ESTAT_PORT_BUSY BIT(7)
+#define I2C_ESTAT_SELF_BUSY BIT(6)
+#define I2C_ESTAT_VERSION GENMASK(4, 0)
+
+/* port busy register */
+#define I2C_PORT_BUSY_RESET BIT(31)
+
+/* wait for command complete or data request */
+#define I2C_CMD_SLEEP_MAX_US 500
+#define I2C_CMD_SLEEP_MIN_US 50
+
+/* wait after reset; choose time from legacy driver */
+#define I2C_RESET_SLEEP_MAX_US 2000
+#define I2C_RESET_SLEEP_MIN_US 1000
+
+/* choose timeout length from legacy driver; it's well tested */
+#define I2C_ABORT_TIMEOUT msecs_to_jiffies(100)
+
+struct fsi_i2c_master {
+ struct fsi_device *fsi;
+ u8 fifo_size;
+ struct list_head ports;
+ struct mutex lock;
+};
+
+struct fsi_i2c_port {
+ struct list_head list;
+ struct i2c_adapter adapter;
+ struct fsi_i2c_master *master;
+ u16 port;
+ u16 xfrd;
+};
+
+static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
+ u32 *data)
+{
+ int rc;
+ __be32 data_be;
+
+ rc = fsi_device_read(fsi, reg, &data_be, sizeof(data_be));
+ if (rc)
+ return rc;
+
+ *data = be32_to_cpu(data_be);
+
+ return 0;
+}
+
+static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
+ u32 *data)
+{
+ __be32 data_be = cpu_to_be32p(data);
+
+ return fsi_device_write(fsi, reg, &data_be, sizeof(data_be));
+}
+
+static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
+{
+ int rc;
+ u32 mode = I2C_MODE_ENHANCED, extended_status, watermark;
+ u32 interrupt = 0;
+
+ /* since we use polling, disable interrupts */
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_INT_MASK, &interrupt);
+ if (rc)
+ return rc;
+
+ mode |= FIELD_PREP(I2C_MODE_CLKDIV, I2C_DEFAULT_CLK_DIV);
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return rc;
+
+ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_ESTAT, &extended_status);
+ if (rc)
+ return rc;
+
+ i2c->fifo_size = FIELD_GET(I2C_ESTAT_FIFO_SZ, extended_status);
+ watermark = FIELD_PREP(I2C_WATERMARK_HI,
+ i2c->fifo_size - I2C_FIFO_HI_LVL);
+ watermark |= FIELD_PREP(I2C_WATERMARK_LO, I2C_FIFO_LO_LVL);
+
+ return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_WATER_MARK, &watermark);
+}
+
+static int fsi_i2c_set_port(struct fsi_i2c_port *port)
+{
+ int rc;
+ struct fsi_device *fsi = port->master->fsi;
+ u32 mode, dummy = 0;
+
+ rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return rc;
+
+ if (FIELD_GET(I2C_MODE_PORT, mode) == port->port)
+ return 0;
+
+ mode = (mode & ~I2C_MODE_PORT) | FIELD_PREP(I2C_MODE_PORT, port->port);
+ rc = fsi_i2c_write_reg(fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return rc;
+
+ /* reset engine when port is changed */
+ return fsi_i2c_write_reg(fsi, I2C_FSI_RESET_ERR, &dummy);
+}
+
+static int fsi_i2c_start(struct fsi_i2c_port *port, struct i2c_msg *msg,
+ bool stop)
+{
+ struct fsi_i2c_master *i2c = port->master;
+ u32 cmd = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR;
+
+ port->xfrd = 0;
+
+ if (msg->flags & I2C_M_RD)
+ cmd |= I2C_CMD_READ;
+
+ if (stop || msg->flags & I2C_M_STOP)
+ cmd |= I2C_CMD_WITH_STOP;
+
+ cmd |= FIELD_PREP(I2C_CMD_ADDR, msg->addr);
+ cmd |= FIELD_PREP(I2C_CMD_LEN, msg->len);
+
+ return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_CMD, &cmd);
+}
+
+static int fsi_i2c_get_op_bytes(int op_bytes)
+{
+ /* fsi is limited to max 4 byte aligned ops */
+ if (op_bytes > 4)
+ return 4;
+ else if (op_bytes == 3)
+ return 2;
+ return op_bytes;
+}
+
+static int fsi_i2c_write_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
+ u8 fifo_count)
+{
+ int write;
+ int rc;
+ struct fsi_i2c_master *i2c = port->master;
+ int bytes_to_write = i2c->fifo_size - fifo_count;
+ int bytes_remaining = msg->len - port->xfrd;
+
+ bytes_to_write = min(bytes_to_write, bytes_remaining);
+
+ while (bytes_to_write) {
+ write = fsi_i2c_get_op_bytes(bytes_to_write);
+
+ rc = fsi_device_write(i2c->fsi, I2C_FSI_FIFO,
+ &msg->buf[port->xfrd], write);
+ if (rc)
+ return rc;
+
+ port->xfrd += write;
+ bytes_to_write -= write;
+ }
+
+ return 0;
+}
+
+static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
+ u8 fifo_count)
+{
+ int read;
+ int rc;
+ struct fsi_i2c_master *i2c = port->master;
+ int bytes_to_read;
+ int xfr_remaining = msg->len - port->xfrd;
+ u32 dummy;
+
+ bytes_to_read = min_t(int, fifo_count, xfr_remaining);
+
+ while (bytes_to_read) {
+ read = fsi_i2c_get_op_bytes(bytes_to_read);
+
+ if (xfr_remaining) {
+ rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO,
+ &msg->buf[port->xfrd], read);
+ if (rc)
+ return rc;
+
+ port->xfrd += read;
+ xfr_remaining -= read;
+ } else {
+ /* no more buffer but data in fifo, need to clear it */
+ rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, &dummy,
+ read);
+ if (rc)
+ return rc;
+ }
+
+ bytes_to_read -= read;
+ }
+
+ return 0;
+}
+
+static int fsi_i2c_get_scl(struct i2c_adapter *adap)
+{
+ u32 stat = 0;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+
+ return !!(stat & I2C_STAT_SCL_IN);
+}
+
+static void fsi_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+ u32 dummy = 0;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ if (val)
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy);
+ else
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy);
+}
+
+static int fsi_i2c_get_sda(struct i2c_adapter *adap)
+{
+ u32 stat = 0;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+
+ return !!(stat & I2C_STAT_SDA_IN);
+}
+
+static void fsi_i2c_set_sda(struct i2c_adapter *adap, int val)
+{
+ u32 dummy = 0;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ if (val)
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy);
+ else
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SDA, &dummy);
+}
+
+static void fsi_i2c_prepare_recovery(struct i2c_adapter *adap)
+{
+ int rc;
+ u32 mode;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return;
+
+ mode |= I2C_MODE_DIAG;
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+}
+
+static void fsi_i2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+ int rc;
+ u32 mode;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *i2c = port->master;
+
+ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return;
+
+ mode &= ~I2C_MODE_DIAG;
+ fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+}
+
+static int fsi_i2c_reset_bus(struct fsi_i2c_master *i2c,
+ struct fsi_i2c_port *port)
+{
+ int rc;
+ u32 stat, dummy = 0;
+
+ /* force bus reset, ignore errors */
+ i2c_recover_bus(&port->adapter);
+
+ /* reset errors */
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy);
+ if (rc)
+ return rc;
+
+ /* wait for command complete */
+ usleep_range(I2C_RESET_SLEEP_MIN_US, I2C_RESET_SLEEP_MAX_US);
+
+ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+ if (rc)
+ return rc;
+
+ if (stat & I2C_STAT_CMD_COMP)
+ return 0;
+
+ /* failed to get command complete; reset engine again */
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy);
+ if (rc)
+ return rc;
+
+ /* re-init engine again */
+ return fsi_i2c_dev_init(i2c);
+}
+
+static int fsi_i2c_reset_engine(struct fsi_i2c_master *i2c, u16 port)
+{
+ int rc;
+ u32 mode, dummy = 0;
+
+ /* reset engine */
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy);
+ if (rc)
+ return rc;
+
+ /* re-init engine */
+ rc = fsi_i2c_dev_init(i2c);
+ if (rc)
+ return rc;
+
+ rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return rc;
+
+ /* set port; default after reset is 0 */
+ if (port) {
+ mode &= ~I2C_MODE_PORT;
+ mode |= FIELD_PREP(I2C_MODE_PORT, port);
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+ if (rc)
+ return rc;
+ }
+
+ /* reset busy register; hw workaround */
+ dummy = I2C_PORT_BUSY_RESET;
+ rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_PORT_BUSY, &dummy);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static int fsi_i2c_abort(struct fsi_i2c_port *port, u32 status)
+{
+ int rc;
+ unsigned long start;
+ u32 cmd = I2C_CMD_WITH_STOP;
+ u32 stat;
+ struct fsi_i2c_master *i2c = port->master;
+ struct fsi_device *fsi = i2c->fsi;
+
+ rc = fsi_i2c_reset_engine(i2c, port->port);
+ if (rc)
+ return rc;
+
+ rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &stat);
+ if (rc)
+ return rc;
+
+ /* if sda is low, peform full bus reset */
+ if (!(stat & I2C_STAT_SDA_IN)) {
+ rc = fsi_i2c_reset_bus(i2c, port);
+ if (rc)
+ return rc;
+ }
+
+ /* skip final stop command for these errors */
+ if (status & (I2C_STAT_PARITY | I2C_STAT_LOST_ARB | I2C_STAT_STOP_ERR))
+ return 0;
+
+ /* write stop command */
+ rc = fsi_i2c_write_reg(fsi, I2C_FSI_CMD, &cmd);
+ if (rc)
+ return rc;
+
+ /* wait until we see command complete in the master */
+ start = jiffies;
+
+ do {
+ rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &status);
+ if (rc)
+ return rc;
+
+ if (status & I2C_STAT_CMD_COMP)
+ return 0;
+
+ usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US);
+ } while (time_after(start + I2C_ABORT_TIMEOUT, jiffies));
+
+ return -ETIMEDOUT;
+}
+
+static int fsi_i2c_handle_status(struct fsi_i2c_port *port,
+ struct i2c_msg *msg, u32 status)
+{
+ int rc;
+ u8 fifo_count;
+
+ if (status & I2C_STAT_ERR) {
+ rc = fsi_i2c_abort(port, status);
+ if (rc)
+ return rc;
+
+ if (status & I2C_STAT_INV_CMD)
+ return -EINVAL;
+
+ if (status & (I2C_STAT_PARITY | I2C_STAT_BE_OVERRUN |
+ I2C_STAT_BE_ACCESS))
+ return -EPROTO;
+
+ if (status & I2C_STAT_NACK)
+ return -ENXIO;
+
+ if (status & I2C_STAT_LOST_ARB)
+ return -EAGAIN;
+
+ if (status & I2C_STAT_STOP_ERR)
+ return -EBADMSG;
+
+ return -EIO;
+ }
+
+ if (status & I2C_STAT_DAT_REQ) {
+ fifo_count = FIELD_GET(I2C_STAT_FIFO_COUNT, status);
+
+ if (msg->flags & I2C_M_RD)
+ return fsi_i2c_read_fifo(port, msg, fifo_count);
+
+ return fsi_i2c_write_fifo(port, msg, fifo_count);
+ }
+
+ if (status & I2C_STAT_CMD_COMP) {
+ if (port->xfrd < msg->len)
+ return -ENODATA;
+
+ return msg->len;
+ }
+
+ return 0;
+}
+
+static int fsi_i2c_wait(struct fsi_i2c_port *port, struct i2c_msg *msg,
+ unsigned long timeout)
+{
+ u32 status = 0;
+ int rc;
+ unsigned long start = jiffies;
+
+ do {
+ rc = fsi_i2c_read_reg(port->master->fsi, I2C_FSI_STAT,
+ &status);
+ if (rc)
+ return rc;
+
+ if (status & I2C_STAT_ANY_RESP) {
+ rc = fsi_i2c_handle_status(port, msg, status);
+ if (rc < 0)
+ return rc;
+
+ /* cmd complete and all data xfrd */
+ if (rc == msg->len)
+ return 0;
+
+ /* need to xfr more data, but maybe don't need wait */
+ continue;
+ }
+
+ usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US);
+ } while (time_after(start + timeout, jiffies));
+
+ return -ETIMEDOUT;
+}
+
+static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ int i, rc;
+ unsigned long start_time;
+ struct fsi_i2c_port *port = adap->algo_data;
+ struct fsi_i2c_master *master = port->master;
+ struct i2c_msg *msg;
+
+ mutex_lock(&master->lock);
+
+ rc = fsi_i2c_set_port(port);
+ if (rc)
+ goto unlock;
+
+ for (i = 0; i < num; i++) {
+ msg = msgs + i;
+ start_time = jiffies;
+
+ rc = fsi_i2c_start(port, msg, i == num - 1);
+ if (rc)
+ goto unlock;
+
+ rc = fsi_i2c_wait(port, msg,
+ adap->timeout - (jiffies - start_time));
+ if (rc)
+ goto unlock;
+ }
+
+unlock:
+ mutex_unlock(&master->lock);
+ return rc ? : num;
+}
+
+static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING |
+ I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static struct i2c_bus_recovery_info fsi_i2c_bus_recovery_info = {
+ .recover_bus = i2c_generic_scl_recovery,
+ .get_scl = fsi_i2c_get_scl,
+ .set_scl = fsi_i2c_set_scl,
+ .get_sda = fsi_i2c_get_sda,
+ .set_sda = fsi_i2c_set_sda,
+ .prepare_recovery = fsi_i2c_prepare_recovery,
+ .unprepare_recovery = fsi_i2c_unprepare_recovery,
+};
+
+static const struct i2c_algorithm fsi_i2c_algorithm = {
+ .master_xfer = fsi_i2c_xfer,
+ .functionality = fsi_i2c_functionality,
+};
+
+static int fsi_i2c_probe(struct device *dev)
+{
+ struct fsi_i2c_master *i2c;
+ struct fsi_i2c_port *port;
+ struct device_node *np;
+ int rc;
+ u32 port_no;
+
+ i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return -ENOMEM;
+
+ mutex_init(&i2c->lock);
+ i2c->fsi = to_fsi_dev(dev);
+ INIT_LIST_HEAD(&i2c->ports);
+
+ rc = fsi_i2c_dev_init(i2c);
+ if (rc)
+ return rc;
+
+ /* Add adapter for each i2c port of the master. */
+ for_each_available_child_of_node(dev->of_node, np) {
+ rc = of_property_read_u32(np, "reg", &port_no);
+ if (rc || port_no > USHRT_MAX)
+ continue;
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ if (!port)
+ break;
+
+ port->master = i2c;
+ port->port = port_no;
+
+ port->adapter.owner = THIS_MODULE;
+ port->adapter.dev.of_node = np;
+ port->adapter.dev.parent = dev;
+ port->adapter.algo = &fsi_i2c_algorithm;
+ port->adapter.bus_recovery_info = &fsi_i2c_bus_recovery_info;
+ port->adapter.algo_data = port;
+
+ snprintf(port->adapter.name, sizeof(port->adapter.name),
+ "i2c_bus-%u", port_no);
+
+ rc = i2c_add_adapter(&port->adapter);
+ if (rc < 0) {
+ dev_err(dev, "Failed to register adapter: %d\n", rc);
+ kfree(port);
+ continue;
+ }
+
+ list_add(&port->list, &i2c->ports);
+ }
+
+ dev_set_drvdata(dev, i2c);
+
+ return 0;
+}
+
+static int fsi_i2c_remove(struct device *dev)
+{
+ struct fsi_i2c_master *i2c = dev_get_drvdata(dev);
+ struct fsi_i2c_port *port, *tmp;
+
+ list_for_each_entry_safe(port, tmp, &i2c->ports, list) {
+ list_del(&port->list);
+ i2c_del_adapter(&port->adapter);
+ kfree(port);
+ }
+
+ return 0;
+}
+
+static const struct fsi_device_id fsi_i2c_ids[] = {
+ { FSI_ENGID_I2C, FSI_VERSION_ANY },
+ { }
+};
+
+static struct fsi_driver fsi_i2c_driver = {
+ .id_table = fsi_i2c_ids,
+ .drv = {
+ .name = "i2c-fsi",
+ .bus = &fsi_bus_type,
+ .probe = fsi_i2c_probe,
+ .remove = fsi_i2c_remove,
+ },
+};
+
+module_fsi_driver(fsi_i2c_driver);
+
+MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
+MODULE_DESCRIPTION("FSI attached I2C master");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 66f85bbf3591..c008d209f0b8 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -78,49 +78,43 @@ static struct dentry *i2c_gpio_debug_dir;
#define getscl(bd) ((bd)->getscl((bd)->data))
#define WIRE_ATTRIBUTE(wire) \
-static int fops_##wire##_get(void *data, u64 *val) \
-{ \
- struct i2c_gpio_private_data *priv = data; \
- \
- i2c_lock_adapter(&priv->adap); \
- *val = get##wire(&priv->bit_data); \
- i2c_unlock_adapter(&priv->adap); \
- return 0; \
-} \
-static int fops_##wire##_set(void *data, u64 val) \
-{ \
- struct i2c_gpio_private_data *priv = data; \
- \
- i2c_lock_adapter(&priv->adap); \
- set##wire(&priv->bit_data, val); \
- i2c_unlock_adapter(&priv->adap); \
- return 0; \
-} \
+static int fops_##wire##_get(void *data, u64 *val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ *val = get##wire(&priv->bit_data); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
+static int fops_##wire##_set(void *data, u64 val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ set##wire(&priv->bit_data, val); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
DEFINE_DEBUGFS_ATTRIBUTE(fops_##wire, fops_##wire##_get, fops_##wire##_set, "%llu\n")
WIRE_ATTRIBUTE(scl);
WIRE_ATTRIBUTE(sda);
-static int fops_incomplete_transfer_set(void *data, u64 addr)
+static void i2c_gpio_incomplete_transfer(struct i2c_gpio_private_data *priv,
+ u32 pattern, u8 pattern_size)
{
- struct i2c_gpio_private_data *priv = data;
struct i2c_algo_bit_data *bit_data = &priv->bit_data;
- int i, pattern;
+ int i;
- if (addr > 0x7f)
- return -EINVAL;
-
- /* ADDR (7 bit) + RD (1 bit) + SDA hi (1 bit) */
- pattern = (addr << 2) | 3;
-
- i2c_lock_adapter(&priv->adap);
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
/* START condition */
setsda(bit_data, 0);
udelay(bit_data->udelay);
- /* Send ADDR+RD, request ACK, don't send STOP */
- for (i = 8; i >= 0; i--) {
+ /* Send pattern, request ACK, don't send STOP */
+ for (i = pattern_size - 1; i >= 0; i--) {
setscl(bit_data, 0);
udelay(bit_data->udelay / 2);
setsda(bit_data, (pattern >> i) & 1);
@@ -129,11 +123,44 @@ static int fops_incomplete_transfer_set(void *data, u64 addr)
udelay(bit_data->udelay);
}
- i2c_unlock_adapter(&priv->adap);
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
+}
+
+static int fops_incomplete_addr_phase_set(void *data, u64 addr)
+{
+ struct i2c_gpio_private_data *priv = data;
+ u32 pattern;
+
+ if (addr > 0x7f)
+ return -EINVAL;
+
+ /* ADDR (7 bit) + RD (1 bit) + Client ACK, keep SDA hi (1 bit) */
+ pattern = (addr << 2) | 3;
+
+ i2c_gpio_incomplete_transfer(priv, pattern, 9);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_addr_phase, NULL, fops_incomplete_addr_phase_set, "%llu\n");
+
+static int fops_incomplete_write_byte_set(void *data, u64 addr)
+{
+ struct i2c_gpio_private_data *priv = data;
+ u32 pattern;
+
+ if (addr > 0x7f)
+ return -EINVAL;
+
+ /* ADDR (7 bit) + WR (1 bit) + Client ACK (1 bit) */
+ pattern = (addr << 2) | 1;
+ /* 0x00 (8 bit) + Client ACK, keep SDA hi (1 bit) */
+ pattern = (pattern << 9) | 1;
+
+ i2c_gpio_incomplete_transfer(priv, pattern, 18);
return 0;
}
-DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_transfer, NULL, fops_incomplete_transfer_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_write_byte, NULL, fops_incomplete_write_byte_set, "%llu\n");
static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
{
@@ -156,8 +183,10 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl);
debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);
- debugfs_create_file_unsafe("incomplete_transfer", 0200, priv->debug_dir,
- priv, &fops_incomplete_transfer);
+ debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir,
+ priv, &fops_incomplete_addr_phase);
+ debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir,
+ priv, &fops_incomplete_write_byte);
}
static void i2c_gpio_fault_injector_exit(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index aa726607645e..941c223f6491 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -70,6 +70,7 @@
* Cannon Lake-H (PCH) 0xa323 32 hard yes yes yes
* Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes
* Cedar Fork (PCH) 0x18df 32 hard yes yes yes
+ * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -220,6 +221,7 @@
#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0
#define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4
+#define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3
#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
@@ -1034,6 +1036,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) },
{ 0, }
};
@@ -1518,6 +1521,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_CDF_SMBUS:
case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ;
priv->features |= FEATURE_SMBUS_PEC;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 498c5e891649..c406700789e1 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -421,10 +421,14 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
return -EAGAIN;
}
- if (for_busy && (temp & I2SR_IBB))
+ if (for_busy && (temp & I2SR_IBB)) {
+ i2c_imx->stopped = 0;
break;
- if (!for_busy && !(temp & I2SR_IBB))
+ }
+ if (!for_busy && !(temp & I2SR_IBB)) {
+ i2c_imx->stopped = 1;
break;
+ }
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C bus is busy\n", __func__);
@@ -538,7 +542,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
result = i2c_imx_bus_busy(i2c_imx, 1);
if (result)
return result;
- i2c_imx->stopped = 0;
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
temp &= ~I2CR_DMAEN;
@@ -567,10 +570,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
udelay(i2c_imx->disable_delay);
}
- if (!i2c_imx->stopped) {
+ if (!i2c_imx->stopped)
i2c_imx_bus_busy(i2c_imx, 0);
- i2c_imx->stopped = 1;
- }
/* Disable I2C controller */
temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
@@ -668,9 +669,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- temp |= I2CR_DMAEN;
- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
dma->chan_using = dma->chan_rx;
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -727,7 +725,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_bus_busy(i2c_imx, 0);
- i2c_imx->stopped = 1;
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -783,6 +780,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
+ int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data;
dev_dbg(&i2c_imx->adapter.dev,
"<%s> write slave address: addr=0x%x\n",
@@ -809,12 +807,14 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
*/
if ((msgs->len - 1) || block_data)
temp &= ~I2CR_TXAK;
+ if (use_dma)
+ temp |= I2CR_DMAEN;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
- if (i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data)
+ if (use_dma)
return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
/* read data */
@@ -850,7 +850,6 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_bus_busy(i2c_imx, 0);
- i2c_imx->stopped = 1;
} else {
/*
* For i2c master receiver repeat restart operation like:
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 642c58946d8d..7d79317a1046 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -567,9 +567,6 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
msg->addr, msg->len, msg->flags, stop);
- if (msg->len == 0)
- return -EINVAL;
-
/*
* The MX28 I2C IP block can only do PIO READ for transfer of to up
* 4 bytes of length. The write transfer is not limited as it can use
@@ -683,6 +680,10 @@ static const struct i2c_algorithm mxs_i2c_algo = {
.functionality = mxs_i2c_func,
};
+static const struct i2c_adapter_quirks mxs_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed)
{
/* The I2C block clock runs at 24MHz */
@@ -854,6 +855,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
adap->owner = THIS_MODULE;
adap->algo = &mxs_i2c_algo;
+ adap->quirks = &mxs_i2c_quirks;
adap->dev.parent = dev;
adap->nr = pdev->id;
adap->dev.of_node = pdev->dev.of_node;
diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c
new file mode 100644
index 000000000000..96b4572e6d9c
--- /dev/null
+++ b/drivers/i2c/busses/i2c-owl.c
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Actions Semiconductor Owl SoC's I2C driver
+ *
+ * Copyright (c) 2014 Actions Semi Inc.
+ * Author: David Liu <liuwei@actions-semi.com>
+ *
+ * Copyright (c) 2018 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* I2C registers */
+#define OWL_I2C_REG_CTL 0x0000
+#define OWL_I2C_REG_CLKDIV 0x0004
+#define OWL_I2C_REG_STAT 0x0008
+#define OWL_I2C_REG_ADDR 0x000C
+#define OWL_I2C_REG_TXDAT 0x0010
+#define OWL_I2C_REG_RXDAT 0x0014
+#define OWL_I2C_REG_CMD 0x0018
+#define OWL_I2C_REG_FIFOCTL 0x001C
+#define OWL_I2C_REG_FIFOSTAT 0x0020
+#define OWL_I2C_REG_DATCNT 0x0024
+#define OWL_I2C_REG_RCNT 0x0028
+
+/* I2Cx_CTL Bit Mask */
+#define OWL_I2C_CTL_RB BIT(1)
+#define OWL_I2C_CTL_GBCC(x) (((x) & 0x3) << 2)
+#define OWL_I2C_CTL_GBCC_NONE OWL_I2C_CTL_GBCC(0)
+#define OWL_I2C_CTL_GBCC_START OWL_I2C_CTL_GBCC(1)
+#define OWL_I2C_CTL_GBCC_STOP OWL_I2C_CTL_GBCC(2)
+#define OWL_I2C_CTL_GBCC_RSTART OWL_I2C_CTL_GBCC(3)
+#define OWL_I2C_CTL_IRQE BIT(5)
+#define OWL_I2C_CTL_EN BIT(7)
+#define OWL_I2C_CTL_AE BIT(8)
+#define OWL_I2C_CTL_SHSM BIT(10)
+
+#define OWL_I2C_DIV_FACTOR(x) ((x) & 0xff)
+
+/* I2Cx_STAT Bit Mask */
+#define OWL_I2C_STAT_RACK BIT(0)
+#define OWL_I2C_STAT_BEB BIT(1)
+#define OWL_I2C_STAT_IRQP BIT(2)
+#define OWL_I2C_STAT_LAB BIT(3)
+#define OWL_I2C_STAT_STPD BIT(4)
+#define OWL_I2C_STAT_STAD BIT(5)
+#define OWL_I2C_STAT_BBB BIT(6)
+#define OWL_I2C_STAT_TCB BIT(7)
+#define OWL_I2C_STAT_LBST BIT(8)
+#define OWL_I2C_STAT_SAMB BIT(9)
+#define OWL_I2C_STAT_SRGC BIT(10)
+
+/* I2Cx_CMD Bit Mask */
+#define OWL_I2C_CMD_SBE BIT(0)
+#define OWL_I2C_CMD_RBE BIT(4)
+#define OWL_I2C_CMD_DE BIT(8)
+#define OWL_I2C_CMD_NS BIT(9)
+#define OWL_I2C_CMD_SE BIT(10)
+#define OWL_I2C_CMD_MSS BIT(11)
+#define OWL_I2C_CMD_WRS BIT(12)
+#define OWL_I2C_CMD_SECL BIT(15)
+
+#define OWL_I2C_CMD_AS(x) (((x) & 0x7) << 1)
+#define OWL_I2C_CMD_SAS(x) (((x) & 0x7) << 5)
+
+/* I2Cx_FIFOCTL Bit Mask */
+#define OWL_I2C_FIFOCTL_NIB BIT(0)
+#define OWL_I2C_FIFOCTL_RFR BIT(1)
+#define OWL_I2C_FIFOCTL_TFR BIT(2)
+
+/* I2Cc_FIFOSTAT Bit Mask */
+#define OWL_I2C_FIFOSTAT_RNB BIT(1)
+#define OWL_I2C_FIFOSTAT_RFE BIT(2)
+#define OWL_I2C_FIFOSTAT_TFF BIT(5)
+#define OWL_I2C_FIFOSTAT_TFD GENMASK(23, 16)
+#define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8)
+
+/* I2C bus timeout */
+#define OWL_I2C_TIMEOUT msecs_to_jiffies(4 * 1000)
+
+#define OWL_I2C_MAX_RETRIES 50
+
+#define OWL_I2C_DEF_SPEED_HZ 100000
+#define OWL_I2C_MAX_SPEED_HZ 400000
+
+struct owl_i2c_dev {
+ struct i2c_adapter adap;
+ struct i2c_msg *msg;
+ struct completion msg_complete;
+ struct clk *clk;
+ spinlock_t lock;
+ void __iomem *base;
+ unsigned long clk_rate;
+ u32 bus_freq;
+ u32 msg_ptr;
+ int err;
+};
+
+static void owl_i2c_update_reg(void __iomem *reg, unsigned int val, bool state)
+{
+ unsigned int regval;
+
+ regval = readl(reg);
+
+ if (state)
+ regval |= val;
+ else
+ regval &= ~val;
+
+ writel(regval, reg);
+}
+
+static void owl_i2c_reset(struct owl_i2c_dev *i2c_dev)
+{
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+ OWL_I2C_CTL_EN, false);
+ mdelay(1);
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+ OWL_I2C_CTL_EN, true);
+
+ /* Clear status registers */
+ writel(0, i2c_dev->base + OWL_I2C_REG_STAT);
+}
+
+static int owl_i2c_reset_fifo(struct owl_i2c_dev *i2c_dev)
+{
+ unsigned int val, timeout = 0;
+
+ /* Reset FIFO */
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+ OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR,
+ true);
+
+ /* Wait 50ms for FIFO reset complete */
+ do {
+ val = readl(i2c_dev->base + OWL_I2C_REG_FIFOCTL);
+ if (!(val & (OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR)))
+ break;
+ usleep_range(500, 1000);
+ } while (timeout++ < OWL_I2C_MAX_RETRIES);
+
+ if (timeout > OWL_I2C_MAX_RETRIES) {
+ dev_err(&i2c_dev->adap.dev, "FIFO reset timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
+{
+ unsigned int val;
+
+ val = DIV_ROUND_UP(i2c_dev->clk_rate, i2c_dev->bus_freq * 16);
+
+ /* Set clock divider factor */
+ writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
+}
+
+static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
+{
+ struct owl_i2c_dev *i2c_dev = _dev;
+ struct i2c_msg *msg = i2c_dev->msg;
+ unsigned long flags;
+ unsigned int stat, fifostat;
+
+ spin_lock_irqsave(&i2c_dev->lock, flags);
+
+ i2c_dev->err = 0;
+
+ /* Handle NACK from slave */
+ fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
+ if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
+ i2c_dev->err = -ENXIO;
+ goto stop;
+ }
+
+ /* Handle bus error */
+ stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
+ if (stat & OWL_I2C_STAT_BEB) {
+ i2c_dev->err = -EIO;
+ goto stop;
+ }
+
+ /* Handle FIFO read */
+ if (msg->flags & I2C_M_RD) {
+ while ((readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+ OWL_I2C_FIFOSTAT_RFE) && i2c_dev->msg_ptr < msg->len) {
+ msg->buf[i2c_dev->msg_ptr++] = readl(i2c_dev->base +
+ OWL_I2C_REG_RXDAT);
+ }
+ } else {
+ /* Handle the remaining bytes which were not sent */
+ while (!(readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+ OWL_I2C_FIFOSTAT_TFF) && i2c_dev->msg_ptr < msg->len) {
+ writel(msg->buf[i2c_dev->msg_ptr++],
+ i2c_dev->base + OWL_I2C_REG_TXDAT);
+ }
+ }
+
+stop:
+ /* Clear pending interrupts */
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
+ OWL_I2C_STAT_IRQP, true);
+
+ complete_all(&i2c_dev->msg_complete);
+ spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static u32 owl_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
+{
+ struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+ unsigned long timeout;
+
+ /* Check for Bus busy */
+ timeout = jiffies + OWL_I2C_TIMEOUT;
+ while (readl(i2c_dev->base + OWL_I2C_REG_STAT) & OWL_I2C_STAT_BBB) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(&adap->dev, "Bus busy timeout\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+ struct i2c_msg *msg;
+ unsigned long time_left, flags;
+ unsigned int i2c_cmd, val;
+ unsigned int addr;
+ int ret, idx;
+
+ spin_lock_irqsave(&i2c_dev->lock, flags);
+
+ /* Reset I2C controller */
+ owl_i2c_reset(i2c_dev);
+
+ /* Set bus frequency */
+ owl_i2c_set_freq(i2c_dev);
+
+ /*
+ * Spinlock should be released before calling reset FIFO and
+ * bus busy check since those functions may sleep
+ */
+ spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+ /* Reset FIFO */
+ ret = owl_i2c_reset_fifo(i2c_dev);
+ if (ret)
+ goto unlocked_err_exit;
+
+ /* Check for bus busy */
+ ret = owl_i2c_check_bus_busy(adap);
+ if (ret)
+ goto unlocked_err_exit;
+
+ spin_lock_irqsave(&i2c_dev->lock, flags);
+
+ /* Check for Arbitration lost */
+ val = readl(i2c_dev->base + OWL_I2C_REG_STAT);
+ if (val & OWL_I2C_STAT_LAB) {
+ val &= ~OWL_I2C_STAT_LAB;
+ writel(val, i2c_dev->base + OWL_I2C_REG_STAT);
+ ret = -EAGAIN;
+ goto err_exit;
+ }
+
+ reinit_completion(&i2c_dev->msg_complete);
+
+ /* Enable I2C controller interrupt */
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+ OWL_I2C_CTL_IRQE, true);
+
+ /*
+ * Select: FIFO enable, Master mode, Stop enable, Data count enable,
+ * Send start bit
+ */
+ i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE |
+ OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE;
+
+ /* Handle repeated start condition */
+ if (num > 1) {
+ /* Set internal address length and enable repeated start */
+ i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) |
+ OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE;
+
+ /* Write slave address */
+ addr = i2c_8bit_addr_from_msg(&msgs[0]);
+ writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+ /* Write internal register address */
+ for (idx = 0; idx < msgs[0].len; idx++)
+ writel(msgs[0].buf[idx],
+ i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+ msg = &msgs[1];
+ } else {
+ /* Set address length */
+ i2c_cmd |= OWL_I2C_CMD_AS(1);
+ msg = &msgs[0];
+ }
+
+ i2c_dev->msg = msg;
+ i2c_dev->msg_ptr = 0;
+
+ /* Set data count for the message */
+ writel(msg->len, i2c_dev->base + OWL_I2C_REG_DATCNT);
+
+ addr = i2c_8bit_addr_from_msg(msg);
+ writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+ if (!(msg->flags & I2C_M_RD)) {
+ /* Write data to FIFO */
+ for (idx = 0; idx < msg->len; idx++) {
+ /* Check for FIFO full */
+ if (readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+ OWL_I2C_FIFOSTAT_TFF)
+ break;
+
+ writel(msg->buf[idx],
+ i2c_dev->base + OWL_I2C_REG_TXDAT);
+ }
+
+ i2c_dev->msg_ptr = idx;
+ }
+
+ /* Ignore the NACK if needed */
+ if (msg->flags & I2C_M_IGNORE_NAK)
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+ OWL_I2C_FIFOCTL_NIB, true);
+ else
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+ OWL_I2C_FIFOCTL_NIB, false);
+
+ /* Start the transfer */
+ writel(i2c_cmd, i2c_dev->base + OWL_I2C_REG_CMD);
+
+ spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+ time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
+ adap->timeout);
+
+ spin_lock_irqsave(&i2c_dev->lock, flags);
+ if (time_left == 0) {
+ dev_err(&adap->dev, "Transaction timed out\n");
+ /* Send stop condition and release the bus */
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+ OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
+ true);
+ ret = -ETIMEDOUT;
+ goto err_exit;
+ }
+
+ ret = i2c_dev->err < 0 ? i2c_dev->err : num;
+
+err_exit:
+ spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+unlocked_err_exit:
+ /* Disable I2C controller */
+ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+ OWL_I2C_CTL_EN, false);
+
+ return ret;
+}
+
+static const struct i2c_algorithm owl_i2c_algorithm = {
+ .master_xfer = owl_i2c_master_xfer,
+ .functionality = owl_i2c_func,
+};
+
+static const struct i2c_adapter_quirks owl_i2c_quirks = {
+ .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST,
+ .max_read_len = 240,
+ .max_write_len = 240,
+ .max_comb_1st_msg_len = 6,
+ .max_comb_2nd_msg_len = 240,
+};
+
+static int owl_i2c_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct owl_i2c_dev *i2c_dev;
+ struct resource *res;
+ int ret, irq;
+
+ i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL);
+ if (!i2c_dev)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ i2c_dev->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(i2c_dev->base))
+ return PTR_ERR(i2c_dev->base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(dev, "failed to get IRQ number\n");
+ return irq;
+ }
+
+ if (of_property_read_u32(dev->of_node, "clock-frequency",
+ &i2c_dev->bus_freq))
+ i2c_dev->bus_freq = OWL_I2C_DEF_SPEED_HZ;
+
+ /* We support only frequencies of 100k and 400k for now */
+ if (i2c_dev->bus_freq != OWL_I2C_DEF_SPEED_HZ &&
+ i2c_dev->bus_freq != OWL_I2C_MAX_SPEED_HZ) {
+ dev_err(dev, "invalid clock-frequency %d\n", i2c_dev->bus_freq);
+ return -EINVAL;
+ }
+
+ i2c_dev->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(i2c_dev->clk)) {
+ dev_err(dev, "failed to get clock\n");
+ return PTR_ERR(i2c_dev->clk);
+ }
+
+ ret = clk_prepare_enable(i2c_dev->clk);
+ if (ret)
+ return ret;
+
+ i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk);
+ if (!i2c_dev->clk_rate) {
+ dev_err(dev, "input clock rate should not be zero\n");
+ ret = -EINVAL;
+ goto disable_clk;
+ }
+
+ init_completion(&i2c_dev->msg_complete);
+ spin_lock_init(&i2c_dev->lock);
+ i2c_dev->adap.owner = THIS_MODULE;
+ i2c_dev->adap.algo = &owl_i2c_algorithm;
+ i2c_dev->adap.timeout = OWL_I2C_TIMEOUT;
+ i2c_dev->adap.quirks = &owl_i2c_quirks;
+ i2c_dev->adap.dev.parent = dev;
+ i2c_dev->adap.dev.of_node = dev->of_node;
+ snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
+ "%s", "OWL I2C adapter");
+ i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
+
+ platform_set_drvdata(pdev, i2c_dev);
+
+ ret = devm_request_irq(dev, irq, owl_i2c_interrupt, 0, pdev->name,
+ i2c_dev);
+ if (ret) {
+ dev_err(dev, "failed to request irq %d\n", irq);
+ goto disable_clk;
+ }
+
+ return i2c_add_adapter(&i2c_dev->adap);
+
+disable_clk:
+ clk_disable_unprepare(i2c_dev->clk);
+
+ return ret;
+}
+
+static const struct of_device_id owl_i2c_of_match[] = {
+ { .compatible = "actions,s900-i2c" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, owl_i2c_of_match);
+
+static struct platform_driver owl_i2c_driver = {
+ .probe = owl_i2c_probe,
+ .driver = {
+ .name = "owl-i2c",
+ .of_match_table = of_match_ptr(owl_i2c_of_match),
+ },
+};
+module_platform_driver(owl_i2c_driver);
+
+MODULE_AUTHOR("David Liu <liuwei@actions-semi.com>");
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_DESCRIPTION("Actions Semiconductor Owl SoC's I2C driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index 55fd5c6f3cca..50803e5d995b 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -365,7 +365,6 @@ static int pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
- smbus->adapter.nr = PCI_FUNC(dev->devfn);
/* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = &dev->dev;
@@ -373,7 +372,7 @@ static int pasemi_smb_probe(struct pci_dev *dev,
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
(CLK_100K_DIV & CTL_CLK_M)));
- error = i2c_add_numbered_adapter(&smbus->adapter);
+ error = i2c_add_adapter(&smbus->adapter);
if (error)
goto out_release_region;
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index dae8ac618a52..0829cb696d9d 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -444,16 +444,6 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
{
enum pmcmsptwi_xfer_result retval;
- if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) ||
- (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) ||
- (cmd->type == MSP_TWI_CMD_WRITE_READ &&
- (cmd->read_len == 0 || cmd->write_len == 0))) {
- dev_err(&pmcmsptwi_adapter.dev,
- "%s: Cannot transfer less than 1 byte\n",
- __func__);
- return -EINVAL;
- }
-
mutex_lock(&data->lock);
dev_dbg(&pmcmsptwi_adapter.dev,
"Setting address to 0x%04x\n", cmd->addr);
@@ -532,11 +522,6 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
cmd.write_data = msg->buf;
}
- if (msg->len == 0) {
- dev_err(&adap->dev, "Zero-byte messages unsupported\n");
- return -EINVAL;
- }
-
cmd.addr = msg->addr;
if (msg->flags & I2C_M_TEN) {
@@ -578,7 +563,7 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
}
static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
- .flags = I2C_AQ_COMB_WRITE_THEN_READ,
+ .flags = I2C_AQ_COMB_WRITE_THEN_READ | I2C_AQ_NO_ZERO_LEN,
.max_write_len = MSP_MAX_BYTES_PER_RW,
.max_read_len = MSP_MAX_BYTES_PER_RW,
.max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
new file mode 100644
index 000000000000..36732eb688a4
--- /dev/null
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/qcom-geni-se.h>
+#include <linux/spinlock.h>
+
+#define SE_I2C_TX_TRANS_LEN 0x26c
+#define SE_I2C_RX_TRANS_LEN 0x270
+#define SE_I2C_SCL_COUNTERS 0x278
+
+#define SE_I2C_ERR (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
+ M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
+#define SE_I2C_ABORT BIT(1)
+
+/* M_CMD OP codes for I2C */
+#define I2C_WRITE 0x1
+#define I2C_READ 0x2
+#define I2C_WRITE_READ 0x3
+#define I2C_ADDR_ONLY 0x4
+#define I2C_BUS_CLEAR 0x6
+#define I2C_STOP_ON_BUS 0x7
+/* M_CMD params for I2C */
+#define PRE_CMD_DELAY BIT(0)
+#define TIMESTAMP_BEFORE BIT(1)
+#define STOP_STRETCH BIT(2)
+#define TIMESTAMP_AFTER BIT(3)
+#define POST_COMMAND_DELAY BIT(4)
+#define IGNORE_ADD_NACK BIT(6)
+#define READ_FINISHED_WITH_ACK BIT(7)
+#define BYPASS_ADDR_PHASE BIT(8)
+#define SLV_ADDR_MSK GENMASK(15, 9)
+#define SLV_ADDR_SHFT 9
+/* I2C SCL COUNTER fields */
+#define HIGH_COUNTER_MSK GENMASK(29, 20)
+#define HIGH_COUNTER_SHFT 20
+#define LOW_COUNTER_MSK GENMASK(19, 10)
+#define LOW_COUNTER_SHFT 10
+#define CYCLE_COUNTER_MSK GENMASK(9, 0)
+
+enum geni_i2c_err_code {
+ GP_IRQ0,
+ NACK,
+ GP_IRQ2,
+ BUS_PROTO,
+ ARB_LOST,
+ GP_IRQ5,
+ GENI_OVERRUN,
+ GENI_ILLEGAL_CMD,
+ GENI_ABORT_DONE,
+ GENI_TIMEOUT,
+};
+
+#define DM_I2C_CB_ERR ((BIT(NACK) | BIT(BUS_PROTO) | BIT(ARB_LOST)) \
+ << 5)
+
+#define I2C_AUTO_SUSPEND_DELAY 250
+#define KHZ(freq) (1000 * freq)
+#define PACKING_BYTES_PW 4
+
+#define ABORT_TIMEOUT HZ
+#define XFER_TIMEOUT HZ
+#define RST_TIMEOUT HZ
+
+struct geni_i2c_dev {
+ struct geni_se se;
+ u32 tx_wm;
+ int irq;
+ int err;
+ struct i2c_adapter adap;
+ struct completion done;
+ struct i2c_msg *cur;
+ int cur_wr;
+ int cur_rd;
+ spinlock_t lock;
+ u32 clk_freq_out;
+ const struct geni_i2c_clk_fld *clk_fld;
+ int suspended;
+};
+
+struct geni_i2c_err_log {
+ int err;
+ const char *msg;
+};
+
+static const struct geni_i2c_err_log gi2c_log[] = {
+ [GP_IRQ0] = {-EIO, "Unknown I2C err GP_IRQ0"},
+ [NACK] = {-ENXIO, "NACK: slv unresponsive, check its power/reset-ln"},
+ [GP_IRQ2] = {-EIO, "Unknown I2C err GP IRQ2"},
+ [BUS_PROTO] = {-EPROTO, "Bus proto err, noisy/unepxected start/stop"},
+ [ARB_LOST] = {-EAGAIN, "Bus arbitration lost, clock line undriveable"},
+ [GP_IRQ5] = {-EIO, "Unknown I2C err GP IRQ5"},
+ [GENI_OVERRUN] = {-EIO, "Cmd overrun, check GENI cmd-state machine"},
+ [GENI_ILLEGAL_CMD] = {-EIO, "Illegal cmd, check GENI cmd-state machine"},
+ [GENI_ABORT_DONE] = {-ETIMEDOUT, "Abort after timeout successful"},
+ [GENI_TIMEOUT] = {-ETIMEDOUT, "I2C TXN timed out"},
+};
+
+struct geni_i2c_clk_fld {
+ u32 clk_freq_out;
+ u8 clk_div;
+ u8 t_high_cnt;
+ u8 t_low_cnt;
+ u8 t_cycle_cnt;
+};
+
+/*
+ * Hardware uses the underlying formula to calculate time periods of
+ * SCL clock cycle. Firmware uses some additional cycles excluded from the
+ * below formula and it is confirmed that the time periods are within
+ * specification limits.
+ *
+ * time of high period of SCL: t_high = (t_high_cnt * clk_div) / source_clock
+ * time of low period of SCL: t_low = (t_low_cnt * clk_div) / source_clock
+ * time of full period of SCL: t_cycle = (t_cycle_cnt * clk_div) / source_clock
+ * clk_freq_out = t / t_cycle
+ * source_clock = 19.2 MHz
+ */
+static const struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
+ {KHZ(100), 7, 10, 11, 26},
+ {KHZ(400), 2, 5, 12, 24},
+ {KHZ(1000), 1, 3, 9, 18},
+};
+
+static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c)
+{
+ int i;
+ const struct geni_i2c_clk_fld *itr = geni_i2c_clk_map;
+
+ for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) {
+ if (itr->clk_freq_out == gi2c->clk_freq_out) {
+ gi2c->clk_fld = itr;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c)
+{
+ const struct geni_i2c_clk_fld *itr = gi2c->clk_fld;
+ u32 val;
+
+ writel_relaxed(0, gi2c->se.base + SE_GENI_CLK_SEL);
+
+ val = (itr->clk_div << CLK_DIV_SHFT) | SER_CLK_EN;
+ writel_relaxed(val, gi2c->se.base + GENI_SER_M_CLK_CFG);
+
+ val = itr->t_high_cnt << HIGH_COUNTER_SHFT;
+ val |= itr->t_low_cnt << LOW_COUNTER_SHFT;
+ val |= itr->t_cycle_cnt;
+ writel_relaxed(val, gi2c->se.base + SE_I2C_SCL_COUNTERS);
+}
+
+static void geni_i2c_err_misc(struct geni_i2c_dev *gi2c)
+{
+ u32 m_cmd = readl_relaxed(gi2c->se.base + SE_GENI_M_CMD0);
+ u32 m_stat = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+ u32 geni_s = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+ u32 geni_ios = readl_relaxed(gi2c->se.base + SE_GENI_IOS);
+ u32 dma = readl_relaxed(gi2c->se.base + SE_GENI_DMA_MODE_EN);
+ u32 rx_st, tx_st;
+
+ if (dma) {
+ rx_st = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+ tx_st = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+ } else {
+ rx_st = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFO_STATUS);
+ tx_st = readl_relaxed(gi2c->se.base + SE_GENI_TX_FIFO_STATUS);
+ }
+ dev_dbg(gi2c->se.dev, "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
+ dma, tx_st, rx_st, m_stat);
+ dev_dbg(gi2c->se.dev, "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
+ m_cmd, geni_s, geni_ios);
+}
+
+static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
+{
+ if (!gi2c->err)
+ gi2c->err = gi2c_log[err].err;
+ if (gi2c->cur)
+ dev_dbg(gi2c->se.dev, "len:%d, slv-addr:0x%x, RD/WR:%d\n",
+ gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags);
+
+ if (err != NACK && err != GENI_ABORT_DONE) {
+ dev_err(gi2c->se.dev, "%s\n", gi2c_log[err].msg);
+ geni_i2c_err_misc(gi2c);
+ }
+}
+
+static irqreturn_t geni_i2c_irq(int irq, void *dev)
+{
+ struct geni_i2c_dev *gi2c = dev;
+ int j;
+ u32 m_stat;
+ u32 rx_st;
+ u32 dm_tx_st;
+ u32 dm_rx_st;
+ u32 dma;
+ struct i2c_msg *cur;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gi2c->lock, flags);
+ m_stat = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+ rx_st = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFO_STATUS);
+ dm_tx_st = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+ dm_rx_st = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+ dma = readl_relaxed(gi2c->se.base + SE_GENI_DMA_MODE_EN);
+ cur = gi2c->cur;
+
+ if (!cur ||
+ m_stat & (M_CMD_FAILURE_EN | M_CMD_ABORT_EN) ||
+ dm_rx_st & (DM_I2C_CB_ERR)) {
+ if (m_stat & M_GP_IRQ_1_EN)
+ geni_i2c_err(gi2c, NACK);
+ if (m_stat & M_GP_IRQ_3_EN)
+ geni_i2c_err(gi2c, BUS_PROTO);
+ if (m_stat & M_GP_IRQ_4_EN)
+ geni_i2c_err(gi2c, ARB_LOST);
+ if (m_stat & M_CMD_OVERRUN_EN)
+ geni_i2c_err(gi2c, GENI_OVERRUN);
+ if (m_stat & M_ILLEGAL_CMD_EN)
+ geni_i2c_err(gi2c, GENI_ILLEGAL_CMD);
+ if (m_stat & M_CMD_ABORT_EN)
+ geni_i2c_err(gi2c, GENI_ABORT_DONE);
+ if (m_stat & M_GP_IRQ_0_EN)
+ geni_i2c_err(gi2c, GP_IRQ0);
+
+ /* Disable the TX Watermark interrupt to stop TX */
+ if (!dma)
+ writel_relaxed(0, gi2c->se.base +
+ SE_GENI_TX_WATERMARK_REG);
+ goto irqret;
+ }
+
+ if (dma) {
+ dev_dbg(gi2c->se.dev, "i2c dma tx:0x%x, dma rx:0x%x\n",
+ dm_tx_st, dm_rx_st);
+ goto irqret;
+ }
+
+ if (cur->flags & I2C_M_RD &&
+ m_stat & (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) {
+ u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
+
+ for (j = 0; j < rxcnt; j++) {
+ u32 val;
+ int p = 0;
+
+ val = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFOn);
+ while (gi2c->cur_rd < cur->len && p < sizeof(val)) {
+ cur->buf[gi2c->cur_rd++] = val & 0xff;
+ val >>= 8;
+ p++;
+ }
+ if (gi2c->cur_rd == cur->len)
+ break;
+ }
+ } else if (!(cur->flags & I2C_M_RD) &&
+ m_stat & M_TX_FIFO_WATERMARK_EN) {
+ for (j = 0; j < gi2c->tx_wm; j++) {
+ u32 temp;
+ u32 val = 0;
+ int p = 0;
+
+ while (gi2c->cur_wr < cur->len && p < sizeof(val)) {
+ temp = cur->buf[gi2c->cur_wr++];
+ val |= temp << (p * 8);
+ p++;
+ }
+ writel_relaxed(val, gi2c->se.base + SE_GENI_TX_FIFOn);
+ /* TX Complete, Disable the TX Watermark interrupt */
+ if (gi2c->cur_wr == cur->len) {
+ writel_relaxed(0, gi2c->se.base +
+ SE_GENI_TX_WATERMARK_REG);
+ break;
+ }
+ }
+ }
+irqret:
+ if (m_stat)
+ writel_relaxed(m_stat, gi2c->se.base + SE_GENI_M_IRQ_CLEAR);
+
+ if (dma) {
+ if (dm_tx_st)
+ writel_relaxed(dm_tx_st, gi2c->se.base +
+ SE_DMA_TX_IRQ_CLR);
+ if (dm_rx_st)
+ writel_relaxed(dm_rx_st, gi2c->se.base +
+ SE_DMA_RX_IRQ_CLR);
+ }
+ /* if this is err with done-bit not set, handle that through timeout. */
+ if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN)
+ complete(&gi2c->done);
+ else if (dm_tx_st & TX_DMA_DONE || dm_tx_st & TX_RESET_DONE)
+ complete(&gi2c->done);
+ else if (dm_rx_st & RX_DMA_DONE || dm_rx_st & RX_RESET_DONE)
+ complete(&gi2c->done);
+
+ spin_unlock_irqrestore(&gi2c->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static void geni_i2c_abort_xfer(struct geni_i2c_dev *gi2c)
+{
+ u32 val;
+ unsigned long time_left = ABORT_TIMEOUT;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gi2c->lock, flags);
+ geni_i2c_err(gi2c, GENI_TIMEOUT);
+ gi2c->cur = NULL;
+ geni_se_abort_m_cmd(&gi2c->se);
+ spin_unlock_irqrestore(&gi2c->lock, flags);
+ do {
+ time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+ val = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+ } while (!(val & M_CMD_ABORT_EN) && time_left);
+
+ if (!(val & M_CMD_ABORT_EN))
+ dev_err(gi2c->se.dev, "Timeout abort_m_cmd\n");
+}
+
+static void geni_i2c_rx_fsm_rst(struct geni_i2c_dev *gi2c)
+{
+ u32 val;
+ unsigned long time_left = RST_TIMEOUT;
+
+ writel_relaxed(1, gi2c->se.base + SE_DMA_RX_FSM_RST);
+ do {
+ time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+ val = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+ } while (!(val & RX_RESET_DONE) && time_left);
+
+ if (!(val & RX_RESET_DONE))
+ dev_err(gi2c->se.dev, "Timeout resetting RX_FSM\n");
+}
+
+static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c)
+{
+ u32 val;
+ unsigned long time_left = RST_TIMEOUT;
+
+ writel_relaxed(1, gi2c->se.base + SE_DMA_TX_FSM_RST);
+ do {
+ time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+ val = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+ } while (!(val & TX_RESET_DONE) && time_left);
+
+ if (!(val & TX_RESET_DONE))
+ dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
+}
+
+static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
+ u32 m_param)
+{
+ dma_addr_t rx_dma;
+ enum geni_se_xfer_mode mode;
+ unsigned long time_left = XFER_TIMEOUT;
+
+ gi2c->cur = msg;
+ mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
+ geni_se_select_mode(&gi2c->se, mode);
+ writel_relaxed(msg->len, gi2c->se.base + SE_I2C_RX_TRANS_LEN);
+ geni_se_setup_m_cmd(&gi2c->se, I2C_READ, m_param);
+ if (mode == GENI_SE_DMA) {
+ int ret;
+
+ ret = geni_se_rx_dma_prep(&gi2c->se, msg->buf, msg->len,
+ &rx_dma);
+ if (ret) {
+ mode = GENI_SE_FIFO;
+ geni_se_select_mode(&gi2c->se, mode);
+ }
+ }
+
+ time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
+ if (!time_left)
+ geni_i2c_abort_xfer(gi2c);
+
+ gi2c->cur_rd = 0;
+ if (mode == GENI_SE_DMA) {
+ if (gi2c->err)
+ geni_i2c_rx_fsm_rst(gi2c);
+ geni_se_rx_dma_unprep(&gi2c->se, rx_dma, msg->len);
+ }
+ return gi2c->err;
+}
+
+static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
+ u32 m_param)
+{
+ dma_addr_t tx_dma;
+ enum geni_se_xfer_mode mode;
+ unsigned long time_left;
+
+ gi2c->cur = msg;
+ mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
+ geni_se_select_mode(&gi2c->se, mode);
+ writel_relaxed(msg->len, gi2c->se.base + SE_I2C_TX_TRANS_LEN);
+ geni_se_setup_m_cmd(&gi2c->se, I2C_WRITE, m_param);
+ if (mode == GENI_SE_DMA) {
+ int ret;
+
+ ret = geni_se_tx_dma_prep(&gi2c->se, msg->buf, msg->len,
+ &tx_dma);
+ if (ret) {
+ mode = GENI_SE_FIFO;
+ geni_se_select_mode(&gi2c->se, mode);
+ }
+ }
+
+ if (mode == GENI_SE_FIFO) /* Get FIFO IRQ */
+ writel_relaxed(1, gi2c->se.base + SE_GENI_TX_WATERMARK_REG);
+
+ time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
+ if (!time_left)
+ geni_i2c_abort_xfer(gi2c);
+
+ gi2c->cur_wr = 0;
+ if (mode == GENI_SE_DMA) {
+ if (gi2c->err)
+ geni_i2c_tx_fsm_rst(gi2c);
+ geni_se_tx_dma_unprep(&gi2c->se, tx_dma, msg->len);
+ }
+ return gi2c->err;
+}
+
+static int geni_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msgs[],
+ int num)
+{
+ struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
+ int i, ret;
+
+ gi2c->err = 0;
+ reinit_completion(&gi2c->done);
+ ret = pm_runtime_get_sync(gi2c->se.dev);
+ if (ret < 0) {
+ dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret);
+ pm_runtime_put_noidle(gi2c->se.dev);
+ /* Set device in suspended since resume failed */
+ pm_runtime_set_suspended(gi2c->se.dev);
+ return ret;
+ }
+
+ qcom_geni_i2c_conf(gi2c);
+ for (i = 0; i < num; i++) {
+ u32 m_param = i < (num - 1) ? STOP_STRETCH : 0;
+
+ m_param |= ((msgs[i].addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK);
+
+ if (msgs[i].flags & I2C_M_RD)
+ ret = geni_i2c_rx_one_msg(gi2c, &msgs[i], m_param);
+ else
+ ret = geni_i2c_tx_one_msg(gi2c, &msgs[i], m_param);
+
+ if (ret)
+ break;
+ }
+ if (ret == 0)
+ ret = num;
+
+ pm_runtime_mark_last_busy(gi2c->se.dev);
+ pm_runtime_put_autosuspend(gi2c->se.dev);
+ gi2c->cur = NULL;
+ gi2c->err = 0;
+ return ret;
+}
+
+static u32 geni_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static const struct i2c_algorithm geni_i2c_algo = {
+ .master_xfer = geni_i2c_xfer,
+ .functionality = geni_i2c_func,
+};
+
+static int geni_i2c_probe(struct platform_device *pdev)
+{
+ struct geni_i2c_dev *gi2c;
+ struct resource *res;
+ u32 proto, tx_depth;
+ int ret;
+
+ gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
+ if (!gi2c)
+ return -ENOMEM;
+
+ gi2c->se.dev = &pdev->dev;
+ gi2c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ gi2c->se.base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(gi2c->se.base))
+ return PTR_ERR(gi2c->se.base);
+
+ gi2c->se.clk = devm_clk_get(&pdev->dev, "se");
+ if (IS_ERR(gi2c->se.clk)) {
+ ret = PTR_ERR(gi2c->se.clk);
+ dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret);
+ return ret;
+ }
+
+ ret = device_property_read_u32(&pdev->dev, "clock-frequency",
+ &gi2c->clk_freq_out);
+ if (ret) {
+ dev_info(&pdev->dev,
+ "Bus frequency not specified, default to 100kHz.\n");
+ gi2c->clk_freq_out = KHZ(100);
+ }
+
+ gi2c->irq = platform_get_irq(pdev, 0);
+ if (gi2c->irq < 0) {
+ dev_err(&pdev->dev, "IRQ error for i2c-geni\n");
+ return gi2c->irq;
+ }
+
+ ret = geni_i2c_clk_map_idx(gi2c);
+ if (ret) {
+ dev_err(&pdev->dev, "Invalid clk frequency %d Hz: %d\n",
+ gi2c->clk_freq_out, ret);
+ return ret;
+ }
+
+ gi2c->adap.algo = &geni_i2c_algo;
+ init_completion(&gi2c->done);
+ spin_lock_init(&gi2c->lock);
+ platform_set_drvdata(pdev, gi2c);
+ ret = devm_request_irq(&pdev->dev, gi2c->irq, geni_i2c_irq,
+ IRQF_TRIGGER_HIGH, "i2c_geni", gi2c);
+ if (ret) {
+ dev_err(&pdev->dev, "Request_irq failed:%d: err:%d\n",
+ gi2c->irq, ret);
+ return ret;
+ }
+ /* Disable the interrupt so that the system can enter low-power mode */
+ disable_irq(gi2c->irq);
+ i2c_set_adapdata(&gi2c->adap, gi2c);
+ gi2c->adap.dev.parent = &pdev->dev;
+ gi2c->adap.dev.of_node = pdev->dev.of_node;
+ strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
+
+ ret = geni_se_resources_on(&gi2c->se);
+ if (ret) {
+ dev_err(&pdev->dev, "Error turning on resources %d\n", ret);
+ return ret;
+ }
+ proto = geni_se_read_proto(&gi2c->se);
+ tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se);
+ if (proto != GENI_SE_I2C) {
+ dev_err(&pdev->dev, "Invalid proto %d\n", proto);
+ geni_se_resources_off(&gi2c->se);
+ return -ENXIO;
+ }
+ gi2c->tx_wm = tx_depth - 1;
+ geni_se_init(&gi2c->se, gi2c->tx_wm, tx_depth);
+ geni_se_config_packing(&gi2c->se, BITS_PER_BYTE, PACKING_BYTES_PW,
+ true, true, true);
+ ret = geni_se_resources_off(&gi2c->se);
+ if (ret) {
+ dev_err(&pdev->dev, "Error turning off resources %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
+
+ ret = i2c_add_adapter(&gi2c->adap);
+ if (ret) {
+ dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret);
+ return ret;
+ }
+
+ gi2c->suspended = 1;
+ pm_runtime_set_suspended(gi2c->se.dev);
+ pm_runtime_set_autosuspend_delay(gi2c->se.dev, I2C_AUTO_SUSPEND_DELAY);
+ pm_runtime_use_autosuspend(gi2c->se.dev);
+ pm_runtime_enable(gi2c->se.dev);
+
+ return 0;
+}
+
+static int geni_i2c_remove(struct platform_device *pdev)
+{
+ struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(gi2c->se.dev);
+ i2c_del_adapter(&gi2c->adap);
+ return 0;
+}
+
+static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
+{
+ int ret;
+ struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+ disable_irq(gi2c->irq);
+ ret = geni_se_resources_off(&gi2c->se);
+ if (ret) {
+ enable_irq(gi2c->irq);
+ return ret;
+
+ } else {
+ gi2c->suspended = 1;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
+{
+ int ret;
+ struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+ ret = geni_se_resources_on(&gi2c->se);
+ if (ret)
+ return ret;
+
+ enable_irq(gi2c->irq);
+ gi2c->suspended = 0;
+ return 0;
+}
+
+static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
+{
+ struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+ if (!gi2c->suspended) {
+ geni_i2c_runtime_suspend(dev);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ pm_runtime_enable(dev);
+ }
+ return 0;
+}
+
+static const struct dev_pm_ops geni_i2c_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, NULL)
+ SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume,
+ NULL)
+};
+
+static const struct of_device_id geni_i2c_dt_match[] = {
+ { .compatible = "qcom,geni-i2c" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
+
+static struct platform_driver geni_i2c_driver = {
+ .probe = geni_i2c_probe,
+ .remove = geni_i2c_remove,
+ .driver = {
+ .name = "geni_i2c",
+ .pm = &geni_i2c_pm_ops,
+ .of_match_table = geni_i2c_dt_match,
+ },
+};
+
+module_platform_driver(geni_i2c_driver);
+
+MODULE_DESCRIPTION("I2C Controller Driver for GENI based QUP cores");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 3c1c817f6968..43ad933df0f0 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -19,6 +19,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
@@ -112,9 +113,10 @@
#define ID_ARBLOST (1 << 3)
#define ID_NACK (1 << 4)
/* persistent flags */
-#define ID_P_NO_RXDMA (1 << 30) /* HW forbids RXDMA sometimes */
-#define ID_P_PM_BLOCKED (1 << 31)
-#define ID_P_MASK (ID_P_PM_BLOCKED | ID_P_NO_RXDMA)
+#define ID_P_REP_AFTER_RD BIT(29)
+#define ID_P_NO_RXDMA BIT(30) /* HW forbids RXDMA sometimes */
+#define ID_P_PM_BLOCKED BIT(31)
+#define ID_P_MASK GENMASK(31, 29)
enum rcar_i2c_type {
I2C_RCAR_GEN1,
@@ -183,8 +185,6 @@ static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val)
rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
};
-/* No get_sda, because the HW only reports its bus free logic, not SDA itself */
-
static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
@@ -197,10 +197,19 @@ static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
};
+static int rcar_i2c_get_bus_free(struct i2c_adapter *adap)
+{
+ struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ return !(rcar_i2c_read(priv, ICMCR) & FSDA);
+
+};
+
static struct i2c_bus_recovery_info rcar_i2c_bri = {
.get_scl = rcar_i2c_get_scl,
.set_scl = rcar_i2c_set_scl,
.set_sda = rcar_i2c_set_sda,
+ .get_bus_free = rcar_i2c_get_bus_free,
.recover_bus = i2c_generic_scl_recovery,
};
static void rcar_i2c_init(struct rcar_i2c_priv *priv)
@@ -215,7 +224,7 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{
- int i, ret;
+ int i;
for (i = 0; i < LOOP_TIMEOUT; i++) {
/* make sure that bus is not busy */
@@ -226,13 +235,7 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
/* Waiting did not help, try to recover */
priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL;
- ret = i2c_recover_bus(&priv->adap);
-
- /* No failure when recovering, so check bus busy bit again */
- if (ret == 0)
- ret = (rcar_i2c_read(priv, ICMCR) & FSDA) ? -EBUSY : 0;
-
- return ret;
+ return i2c_recover_bus(&priv->adap);
}
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timings *t)
@@ -343,7 +346,10 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
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);
+ if (priv->flags & ID_P_REP_AFTER_RD)
+ priv->flags &= ~ID_P_REP_AFTER_RD;
+ 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);
@@ -548,15 +554,15 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
priv->pos++;
}
- /*
- * 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 you want to change this code, make sure sending one transfer with
- * four messages (WR-RD-WR-RD) works!
- */
- if (priv->pos + 1 >= msg->len)
- rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+ /* If next received data is the _LAST_, go to new phase. */
+ if (priv->pos + 1 == msg->len) {
+ if (priv->flags & ID_LAST_MSG) {
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+ } else {
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+ priv->flags |= ID_P_REP_AFTER_RD;
+ }
+ }
if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
rcar_i2c_next_msg(priv);
@@ -624,9 +630,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
struct rcar_i2c_priv *priv = ptr;
u32 msr, val;
- /* 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);
+ /* Clear START or STOP immediately, except for REPSTART after read */
+ if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) {
+ val = rcar_i2c_read(priv, ICMCR);
+ rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
+ }
msr = rcar_i2c_read(priv, ICMSR);
@@ -795,14 +803,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
if (ret < 0)
goto out;
- for (i = 0; i < num; i++) {
- /* This HW can't send STOP after address phase */
- if (msgs[i].len == 0) {
- ret = -EOPNOTSUPP;
- goto out;
- }
+ for (i = 0; i < num; i++)
rcar_i2c_request_dma(priv, msgs + i);
- }
/* init first message */
priv->msg = msgs;
@@ -889,6 +891,10 @@ static const struct i2c_algorithm rcar_i2c_algo = {
.unreg_slave = rcar_unreg_slave,
};
+static const struct i2c_adapter_quirks rcar_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static const struct of_device_id rcar_i2c_dt_ids[] = {
{ .compatible = "renesas,i2c-r8a7778", .data = (void *)I2C_RCAR_GEN1 },
{ .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
@@ -942,6 +948,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
adap->dev.parent = dev;
adap->dev.of_node = dev->of_node;
adap->bus_recovery_info = &rcar_i2c_bri;
+ adap->quirks = &rcar_i2c_quirks;
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9fe2b6951895..2f2e28d60ef5 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -919,9 +919,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
(val == CPUFREQ_PRECHANGE && delta_f > 0)) {
- i2c_lock_adapter(&i2c->adap);
+ i2c_lock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
ret = s3c24xx_i2c_clockrate(i2c, &got);
- i2c_unlock_adapter(&i2c->adap);
+ i2c_unlock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
if (ret < 0)
dev_err(i2c->dev, "cannot find frequency (%d)\n", ret);
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 5fda4188a9e5..9c7f6f8ceb22 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -613,11 +613,6 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)
static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
bool do_init)
{
- if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
- dev_err(pd->dev, "Unsupported zero length i2c read\n");
- return -EOPNOTSUPP;
- }
-
if (do_init) {
/* Initialize channel registers */
iic_wr(pd, ICCR, ICCR_SCP);
@@ -758,6 +753,10 @@ static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
.master_xfer = sh_mobile_i2c_xfer,
};
+static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN_READ,
+};
+
/*
* r8a7740 chip has lasting errata on I2C I/O pad reset.
* this is work-around for it.
@@ -925,6 +924,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
adap->owner = THIS_MODULE;
adap->algo = &sh_mobile_i2c_algorithm;
+ adap->quirks = &sh_mobile_i2c_quirks;
adap->dev.parent = &dev->dev;
adap->retries = 5;
adap->nr = dev->id;
diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c
index 4053259bccb8..a94e724f51dc 100644
--- a/drivers/i2c/busses/i2c-sprd.c
+++ b/drivers/i2c/busses/i2c-sprd.c
@@ -590,9 +590,9 @@ static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
- i2c_lock_adapter(&i2c_dev->adap);
+ i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = true;
- i2c_unlock_adapter(&i2c_dev->adap);
+ i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
return pm_runtime_force_suspend(pdev);
}
@@ -601,9 +601,9 @@ static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
- i2c_lock_adapter(&i2c_dev->adap);
+ i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
i2c_dev->is_suspended = false;
- i2c_unlock_adapter(&i2c_dev->adap);
+ i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
return pm_runtime_force_resume(pdev);
}
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index fce52bdab2b7..5503fa171df0 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -673,12 +673,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
msg->addr, msg->len, msg->flags, stop);
}
- /* Zero-length messages are not supported by this hardware */
- if (msg->len == 0) {
- ret = -EINVAL;
- goto exit_disable;
- }
-
/*
* For some reason, sending the address sometimes fails when running
* on the 13 MHz clock. No interrupt arrives. This is a work around,
@@ -863,6 +857,10 @@ static const struct i2c_algorithm stu300_algo = {
.functionality = stu300_func,
};
+static const struct i2c_adapter_quirks stu300_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static int stu300_probe(struct platform_device *pdev)
{
struct stu300_dev *dev;
@@ -920,6 +918,8 @@ static int stu300_probe(struct platform_device *pdev)
adap->algo = &stu300_algo;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
+ adap->quirks = &stu300_quirks;
+
i2c_set_adapdata(adap, dev);
/* i2c device drivers may be active on return from add_adapter() */
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 797def5319f1..60c8561fbe65 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -115,6 +115,18 @@
#define I2C_CONFIG_LOAD_TIMEOUT 1000000
+#define I2C_MST_FIFO_CONTROL 0x0b4
+#define I2C_MST_FIFO_CONTROL_RX_FLUSH BIT(0)
+#define I2C_MST_FIFO_CONTROL_TX_FLUSH BIT(1)
+#define I2C_MST_FIFO_CONTROL_RX_TRIG(x) (((x) - 1) << 4)
+#define I2C_MST_FIFO_CONTROL_TX_TRIG(x) (((x) - 1) << 16)
+
+#define I2C_MST_FIFO_STATUS 0x0b8
+#define I2C_MST_FIFO_STATUS_RX_MASK 0xff
+#define I2C_MST_FIFO_STATUS_RX_SHIFT 0
+#define I2C_MST_FIFO_STATUS_TX_MASK 0xff0000
+#define I2C_MST_FIFO_STATUS_TX_SHIFT 16
+
/*
* msg_end_type: The bus control which need to be send at end of transfer.
* @MSG_END_STOP: Send stop pulse at end of transfer.
@@ -154,6 +166,7 @@ struct tegra_i2c_hw_feature {
u16 clk_divisor_fast_plus_mode;
bool has_multi_master_mode;
bool has_slcg_override_reg;
+ bool has_mst_fifo;
};
/**
@@ -266,13 +279,24 @@ static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
{
unsigned long timeout = jiffies + HZ;
- u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
+ unsigned int offset;
+ u32 mask, val;
+
+ if (i2c_dev->hw->has_mst_fifo) {
+ mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
+ I2C_MST_FIFO_CONTROL_RX_FLUSH;
+ offset = I2C_MST_FIFO_CONTROL;
+ } else {
+ mask = I2C_FIFO_CONTROL_TX_FLUSH |
+ I2C_FIFO_CONTROL_RX_FLUSH;
+ offset = I2C_FIFO_CONTROL;
+ }
- val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
- i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+ val = i2c_readl(i2c_dev, offset);
+ val |= mask;
+ i2c_writel(i2c_dev, val, offset);
- while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
- (I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
+ while (i2c_readl(i2c_dev, offset) & mask) {
if (time_after(jiffies, timeout)) {
dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
return -ETIMEDOUT;
@@ -290,9 +314,15 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
size_t buf_remaining = i2c_dev->msg_buf_remaining;
int words_to_transfer;
- val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
- rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
- I2C_FIFO_STATUS_RX_SHIFT;
+ if (i2c_dev->hw->has_mst_fifo) {
+ val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+ rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >>
+ I2C_MST_FIFO_STATUS_RX_SHIFT;
+ } else {
+ val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+ rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
+ I2C_FIFO_STATUS_RX_SHIFT;
+ }
/* Rounds down to not include partial word at the end of buf */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
@@ -321,6 +351,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0);
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf;
+
return 0;
}
@@ -332,9 +363,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
size_t buf_remaining = i2c_dev->msg_buf_remaining;
int words_to_transfer;
- val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
- tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
- I2C_FIFO_STATUS_TX_SHIFT;
+ if (i2c_dev->hw->has_mst_fifo) {
+ val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+ tx_fifo_avail = (val & I2C_MST_FIFO_STATUS_TX_MASK) >>
+ I2C_MST_FIFO_STATUS_TX_SHIFT;
+ } else {
+ val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+ tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
+ I2C_FIFO_STATUS_TX_SHIFT;
+ }
/* Rounds down to not include partial word at the end of buf */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
@@ -516,9 +553,15 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
}
- val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
- 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
- i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+ if (i2c_dev->hw->has_mst_fifo) {
+ val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) |
+ I2C_MST_FIFO_CONTROL_RX_TRIG(1);
+ i2c_writel(i2c_dev, val, I2C_MST_FIFO_CONTROL);
+ } else {
+ val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+ 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+ i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+ }
err = tegra_i2c_flush_fifos(i2c_dev);
if (err)
@@ -802,6 +845,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
+ .has_mst_fifo = false,
};
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -814,6 +858,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
+ .has_mst_fifo = false,
};
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -826,6 +871,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
.has_config_load_reg = false,
.has_multi_master_mode = false,
.has_slcg_override_reg = false,
+ .has_mst_fifo = false,
};
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -838,6 +884,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
.has_config_load_reg = true,
.has_multi_master_mode = false,
.has_slcg_override_reg = true,
+ .has_mst_fifo = false,
};
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -850,10 +897,25 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
.has_config_load_reg = true,
.has_multi_master_mode = true,
.has_slcg_override_reg = true,
+ .has_mst_fifo = false,
+};
+
+static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
+ .has_continue_xfer_support = true,
+ .has_per_pkt_xfer_complete_irq = true,
+ .has_single_clk_source = true,
+ .clk_divisor_hs_mode = 1,
+ .clk_divisor_std_fast_mode = 0x19,
+ .clk_divisor_fast_plus_mode = 0x10,
+ .has_config_load_reg = true,
+ .has_multi_master_mode = true,
+ .has_slcg_override_reg = true,
+ .has_mst_fifo = true,
};
/* Match table for of_platform binding */
static const struct of_device_id tegra_i2c_of_match[] = {
+ { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c
index 484bfa15d58e..34cd4b308540 100644
--- a/drivers/i2c/busses/i2c-xlr.c
+++ b/drivers/i2c/busses/i2c-xlr.c
@@ -173,9 +173,6 @@ static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len,
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);
@@ -241,9 +238,6 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
unsigned long timeout, stoptime, checktime;
int nbytes, timedout;
- 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);
@@ -340,6 +334,10 @@ static const struct i2c_algorithm xlr_i2c_algo = {
.functionality = xlr_func,
};
+static const struct i2c_adapter_quirks xlr_i2c_quirks = {
+ .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
static const struct xlr_i2c_config xlr_i2c_config_default = {
.status_busy = XLR_I2C_BUS_BUSY,
.cfg_extra = 0,
@@ -427,6 +425,7 @@ static int xlr_i2c_probe(struct platform_device *pdev)
priv->adap.owner = THIS_MODULE;
priv->adap.algo_data = priv;
priv->adap.algo = &xlr_i2c_algo;
+ priv->adap.quirks = &xlr_i2c_quirks;
priv->adap.nr = pdev->id;
priv->adap.class = I2C_CLASS_HWMON;
snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 7c3b4740b94b..32affd3fa8bd 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -453,8 +453,12 @@ static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
else
dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",
data_len, client->addr, cmd, ret);
- } else {
+ /* 2 transfers must have completed successfully */
+ } else if (ret == 2) {
memcpy(data, buffer, data_len);
+ ret = 0;
+ } else {
+ ret = -EIO;
}
kfree(buffer);
@@ -482,11 +486,16 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
msgs[0].buf = buffer;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (ret < 0)
- dev_err(&client->adapter->dev, "i2c write failed\n");
kfree(buffer);
- return ret;
+
+ if (ret < 0) {
+ dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret);
+ return ret;
+ }
+
+ /* 1 transfer must have completed successfully */
+ return (ret == 1) ? 0 : -EIO;
}
static acpi_status
@@ -590,8 +599,6 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command,
if (action == ACPI_READ) {
status = acpi_gsb_i2c_read_bytes(client, command,
gsb->data, info->access_length);
- if (status > 0)
- status = 0;
} else {
status = acpi_gsb_i2c_write_bytes(client, command,
gsb->data, info->access_length);
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 15c95aaa484c..5a937109a289 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -158,6 +158,22 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
gpiod_set_value_cansleep(adap->bus_recovery_info->sda_gpiod, val);
}
+static int i2c_generic_bus_free(struct i2c_adapter *adap)
+{
+ struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+ int ret = -EOPNOTSUPP;
+
+ if (bri->get_bus_free)
+ ret = bri->get_bus_free(adap);
+ else if (bri->get_sda)
+ ret = bri->get_sda(adap);
+
+ if (ret < 0)
+ return ret;
+
+ return ret ? 0 : -EBUSY;
+}
+
/*
* We are generating clock pulses. ndelay() determines durating of clk pulses.
* We will generate clock with rate 100 KHz and so duration of both clock levels
@@ -169,21 +185,28 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
int i2c_generic_scl_recovery(struct i2c_adapter *adap)
{
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
- int i = 0, val = 1, ret = 0;
+ int i = 0, scl = 1, ret;
if (bri->prepare_recovery)
bri->prepare_recovery(adap);
- bri->set_scl(adap, val);
+ /*
+ * If we can set SDA, we will always create a STOP to ensure additional
+ * pulses will do no harm. This is achieved by letting SDA follow SCL
+ * half a cycle later. Check the 'incomplete_write_byte' fault injector
+ * for details.
+ */
+ bri->set_scl(adap, scl);
+ ndelay(RECOVERY_NDELAY / 2);
if (bri->set_sda)
- bri->set_sda(adap, 1);
- ndelay(RECOVERY_NDELAY);
+ bri->set_sda(adap, scl);
+ ndelay(RECOVERY_NDELAY / 2);
/*
* By this time SCL is high, as we need to give 9 falling-rising edges
*/
while (i++ < RECOVERY_CLK_CNT * 2) {
- if (val) {
+ if (scl) {
/* SCL shouldn't be low here */
if (!bri->get_scl(adap)) {
dev_err(&adap->dev,
@@ -191,41 +214,27 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
ret = -EBUSY;
break;
}
- /* Break if SDA is high */
- if (bri->get_sda && bri->get_sda(adap))
- break;
}
- val = !val;
- bri->set_scl(adap, val);
-
- /*
- * If we can set SDA, we will always create STOP here to ensure
- * the additional pulses will do no harm. This is achieved by
- * letting SDA follow SCL half a cycle later.
- */
+ scl = !scl;
+ bri->set_scl(adap, scl);
+ /* Creating STOP again, see above */
ndelay(RECOVERY_NDELAY / 2);
if (bri->set_sda)
- bri->set_sda(adap, val);
+ bri->set_sda(adap, scl);
ndelay(RECOVERY_NDELAY / 2);
- }
- /* check if recovery actually succeeded */
- if (bri->get_sda && !bri->get_sda(adap))
- ret = -EBUSY;
-
- /* If all went well, send STOP for a sane bus state. */
- if (ret == 0 && bri->set_sda) {
- bri->set_scl(adap, 0);
- ndelay(RECOVERY_NDELAY / 2);
- bri->set_sda(adap, 0);
- ndelay(RECOVERY_NDELAY / 2);
- bri->set_scl(adap, 1);
- ndelay(RECOVERY_NDELAY / 2);
- bri->set_sda(adap, 1);
- ndelay(RECOVERY_NDELAY / 2);
+ if (scl) {
+ ret = i2c_generic_bus_free(adap);
+ if (ret == 0)
+ break;
+ }
}
+ /* If we can't check bus status, assume recovery worked */
+ if (ret == -EOPNOTSUPP)
+ ret = 0;
+
if (bri->unprepare_recovery)
bri->unprepare_recovery(adap);
@@ -274,6 +283,10 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
err_str = "no {get|set}_scl() found";
goto err;
}
+ if (!bri->set_sda && !bri->get_sda) {
+ err_str = "either get_sda() or set_sda() needed";
+ goto err;
+ }
}
return;
@@ -1563,6 +1576,8 @@ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_de
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;
+
+ device_property_read_u32(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns);
}
EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
@@ -1826,9 +1841,15 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
if (msgs[i].flags & I2C_M_RD) {
if (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))
return i2c_quirk_error(adap, &msgs[i], "msg too long");
+
+ if (q->flags & I2C_AQ_NO_ZERO_LEN_READ && len == 0)
+ return i2c_quirk_error(adap, &msgs[i], "no zero length");
} else {
if (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))
return i2c_quirk_error(adap, &msgs[i], "msg too long");
+
+ if (q->flags & I2C_AQ_NO_ZERO_LEN_WRITE && len == 0)
+ return i2c_quirk_error(adap, &msgs[i], "no zero length");
}
}
diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c
index 4a78c65e9971..47a9f70a24a9 100644
--- a/drivers/i2c/i2c-core-slave.c
+++ b/drivers/i2c/i2c-core-slave.c
@@ -47,9 +47,9 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
client->slave_cb = slave_cb;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
ret = client->adapter->algo->reg_slave(client);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
if (ret) {
client->slave_cb = NULL;
@@ -69,9 +69,9 @@ int i2c_slave_unregister(struct i2c_client *client)
return -EOPNOTSUPP;
}
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
ret = client->adapter->algo->unreg_slave(client);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
if (ret == 0)
client->slave_cb = NULL;
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 29646aa6132e..f330690b4125 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -87,8 +87,8 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
ret = muxc->select(muxc, priv->chan_id);
if (ret >= 0)
- ret = parent->algo->smbus_xfer(parent, addr, flags,
- read_write, command, size, data);
+ ret = __i2c_smbus_xfer(parent, addr, flags,
+ read_write, command, size, data);
if (muxc->deselect)
muxc->deselect(muxc, priv->chan_id);
diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
index 12ad8d65faf6..f2bf3e57ed67 100644
--- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c
+++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
@@ -94,31 +94,11 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
struct i2c_client *client, u8 val)
{
struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
- int ret = -ENODEV;
-
- if (adap->algo->master_xfer) {
- struct i2c_msg msg;
- u8 msgbuf[] = {pdata->sel_reg_addr, val};
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = 2;
- msg.buf = msgbuf;
- ret = __i2c_transfer(adap, &msg, 1);
-
- if (ret >= 0 && ret != 1)
- ret = -EREMOTEIO;
- } else if (adap->algo->smbus_xfer) {
- union i2c_smbus_data data;
-
- data.byte = val;
- ret = adap->algo->smbus_xfer(adap, client->addr,
- client->flags, I2C_SMBUS_WRITE,
- pdata->sel_reg_addr,
- I2C_SMBUS_BYTE_DATA, &data);
- }
+ union i2c_smbus_data data = { .byte = val };
- return ret;
+ return __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_WRITE, pdata->sel_reg_addr,
+ I2C_SMBUS_BYTE_DATA, &data);
}
static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index 6a39adaf433f..9e75d6b9140b 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -99,31 +99,11 @@ MODULE_DEVICE_TABLE(of, pca9541_of_match);
static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
{
struct i2c_adapter *adap = client->adapter;
- int ret;
-
- if (adap->algo->master_xfer) {
- struct i2c_msg msg;
- char buf[2];
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = 2;
- buf[0] = command;
- buf[1] = val;
- msg.buf = buf;
- ret = __i2c_transfer(adap, &msg, 1);
- } else {
- union i2c_smbus_data data;
-
- data.byte = val;
- ret = adap->algo->smbus_xfer(adap, client->addr,
- client->flags,
- I2C_SMBUS_WRITE,
- command,
- I2C_SMBUS_BYTE_DATA, &data);
- }
+ union i2c_smbus_data data = { .byte = val };
- return ret;
+ return __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_BYTE_DATA, &data);
}
/*
@@ -133,41 +113,14 @@ static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
static int pca9541_reg_read(struct i2c_client *client, u8 command)
{
struct i2c_adapter *adap = client->adapter;
+ union i2c_smbus_data data;
int ret;
- u8 val;
-
- if (adap->algo->master_xfer) {
- struct i2c_msg msg[2] = {
- {
- .addr = client->addr,
- .flags = 0,
- .len = 1,
- .buf = &command
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = &val
- }
- };
- ret = __i2c_transfer(adap, msg, 2);
- if (ret == 2)
- ret = val;
- else if (ret >= 0)
- ret = -EIO;
- } else {
- union i2c_smbus_data data;
-
- ret = adap->algo->smbus_xfer(adap, client->addr,
- client->flags,
- I2C_SMBUS_READ,
- command,
- I2C_SMBUS_BYTE_DATA, &data);
- if (!ret)
- ret = data.byte;
- }
- return ret;
+
+ ret = __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_BYTE_DATA, &data);
+
+ return ret ?: data.byte;
}
/*
@@ -345,11 +298,11 @@ static int pca9541_probe(struct i2c_client *client,
/*
* I2C accesses are unprotected here.
- * We have to lock the adapter before releasing the bus.
+ * We have to lock the I2C segment before releasing the bus.
*/
- i2c_lock_adapter(adap);
+ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
pca9541_release_bus(client);
- i2c_unlock_adapter(adap);
+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
/* Create mux adapter */
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index fbc748027087..24bd9275fde5 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -220,30 +220,11 @@ MODULE_DEVICE_TABLE(of, pca954x_of_match);
static int pca954x_reg_write(struct i2c_adapter *adap,
struct i2c_client *client, u8 val)
{
- int ret = -ENODEV;
-
- if (adap->algo->master_xfer) {
- struct i2c_msg msg;
- char buf[1];
-
- msg.addr = client->addr;
- msg.flags = 0;
- msg.len = 1;
- buf[0] = val;
- msg.buf = buf;
- ret = __i2c_transfer(adap, &msg, 1);
-
- if (ret >= 0 && ret != 1)
- ret = -EREMOTEIO;
- } else {
- union i2c_smbus_data data;
- ret = adap->algo->smbus_xfer(adap, client->addr,
- client->flags,
- I2C_SMBUS_WRITE,
- val, I2C_SMBUS_BYTE, &data);
- }
+ union i2c_smbus_data dummy;
- return ret;
+ return __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_WRITE, val,
+ I2C_SMBUS_BYTE, &dummy);
}
static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
@@ -368,7 +349,8 @@ static int pca954x_probe(struct i2c_client *client,
{
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
- struct device_node *of_node = client->dev.of_node;
+ struct device *dev = &client->dev;
+ struct device_node *np = dev->of_node;
bool idle_disconnect_dt;
struct gpio_desc *gpio;
int num, force, class;
@@ -379,8 +361,7 @@ static int pca954x_probe(struct i2c_client *client,
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
return -ENODEV;
- muxc = i2c_mux_alloc(adap, &client->dev,
- PCA954X_MAX_NCHANS, sizeof(*data), 0,
+ muxc = i2c_mux_alloc(adap, dev, PCA954X_MAX_NCHANS, sizeof(*data), 0,
pca954x_select_chan, pca954x_deselect_mux);
if (!muxc)
return -ENOMEM;
@@ -390,7 +371,7 @@ static int pca954x_probe(struct i2c_client *client,
data->client = client;
/* Reset the mux if a reset GPIO is specified. */
- gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
+ gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
@@ -400,7 +381,7 @@ static int pca954x_probe(struct i2c_client *client,
udelay(1);
}
- data->chip = of_device_get_match_data(&client->dev);
+ data->chip = of_device_get_match_data(dev);
if (!data->chip)
data->chip = &chips[id->driver_data];
@@ -414,8 +395,7 @@ static int pca954x_probe(struct i2c_client *client,
if (!ret &&
(id.manufacturer_id != data->chip->id.manufacturer_id ||
id.part_id != data->chip->id.part_id)) {
- dev_warn(&client->dev,
- "unexpected device id %03x-%03x-%x\n",
+ dev_warn(dev, "unexpected device id %03x-%03x-%x\n",
id.manufacturer_id, id.part_id,
id.die_revision);
return -ENODEV;
@@ -427,14 +407,14 @@ static int pca954x_probe(struct i2c_client *client,
* initializes the mux to disconnected state.
*/
if (i2c_smbus_write_byte(client, 0) < 0) {
- dev_warn(&client->dev, "probe failed\n");
+ dev_warn(dev, "probe failed\n");
return -ENODEV;
}
data->last_chan = 0; /* force the first selection */
- idle_disconnect_dt = of_node &&
- of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
+ idle_disconnect_dt = np &&
+ of_property_read_bool(np, "i2c-mux-idle-disconnect");
ret = pca954x_irq_setup(muxc);
if (ret)
@@ -465,7 +445,7 @@ static int pca954x_probe(struct i2c_client *client,
}
if (data->irq) {
- ret = devm_request_threaded_irq(&client->dev, data->client->irq,
+ ret = devm_request_threaded_irq(dev, data->client->irq,
NULL, pca954x_irq_handler,
IRQF_ONESHOT | IRQF_SHARED,
"pca954x", data);
@@ -473,8 +453,7 @@ static int pca954x_probe(struct i2c_client *client,
goto fail_cleanup;
}
- dev_info(&client->dev,
- "registered %d multiplexed busses for I2C %s %s\n",
+ dev_info(dev, "registered %d multiplexed busses for I2C %s %s\n",
num, data->chip->muxtype == pca954x_ismux
? "mux" : "switch", client->name);
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index e52c58c29d9a..4d565b0c5a6e 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -574,13 +574,14 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
if (!HPT370_ALLOW_ATA100_5 ||
check_in_drive_list(drive, bad_ata100_5))
return ATA_UDMA4;
+ /* else: fall through */
case HPT372 :
case HPT372A:
case HPT372N:
case HPT374 :
if (ata_id_is_sata(drive->id))
mask &= ~0x0e;
- /* Fall thru */
+ /* fall through */
default:
return mask;
}
@@ -600,7 +601,7 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
case HPT374 :
if (ata_id_is_sata(drive->id))
return 0x00;
- /* Fall thru */
+ /* else: fall through */
default:
return 0x07;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 5bd2aafc3753..a8df300f949c 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -427,6 +427,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
* (maintains previous driver behaviour)
*/
break;
+ /* else: fall through */
case CAPACITY_CURRENT:
/* Normal Zip/LS-120 disks */
if (memcmp(cap_desc, &floppy->cap_desc, 8))
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a444bad7a2aa..0d93e0cfbeaf 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -460,7 +460,6 @@ void do_ide_request(struct request_queue *q)
struct ide_host *host = hwif->host;
struct request *rq = NULL;
ide_startstop_t startstop;
- unsigned long queue_run_ms = 3; /* old plug delay */
spin_unlock_irq(q->queue_lock);
@@ -480,9 +479,6 @@ repeat:
prev_port = hwif->host->cur_port;
if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
time_after(drive->sleep, jiffies)) {
- unsigned long left = jiffies - drive->sleep;
-
- queue_run_ms = jiffies_to_msecs(left + 1);
ide_unlock_port(hwif);
goto plug_device;
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 416a2f353071..3b75a7b7a284 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -142,6 +142,7 @@ static void ide_classify_atapi_dev(ide_drive_t *drive)
}
/* Early cdrom models used zero */
type = ide_cdrom;
+ /* fall through */
case ide_cdrom:
drive->dev_flags |= IDE_DFLAG_REMOVABLE;
#ifdef CONFIG_PPC
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index aee7b46d2330..34c1165226a4 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -1746,7 +1746,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
{
unsigned long t;
int speed;
- int buffer_size;
u16 *ctl = (u16 *)&tape->caps[12];
ide_debug_log(IDE_DBG_FUNC, "minor: %d", minor);
@@ -1781,7 +1780,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
*ctl /= 2;
tape->buffer_size = *ctl * tape->blk_size;
}
- buffer_size = tape->buffer_size;
/* select the "best" DSC read/write polling freq */
speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 89b29028d315..c21d5c50ae3a 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -128,7 +128,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
return pre_task_out_intr(drive, cmd);
}
handler = task_pio_intr;
- /* fall-through */
+ /* fall through */
case ATA_PROT_NODATA:
if (handler == NULL)
handler = task_no_data_intr;
@@ -140,6 +140,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
hwif->expiry = dma_ops->dma_timer_expiry;
ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD);
dma_ops->dma_start(drive);
+ /* fall through */
default:
return ide_started;
}
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index c3062b53056f..024bc7ba49ee 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -494,6 +494,7 @@ static int init_chipset_sis5513(struct pci_dev *dev)
pci_read_config_byte(dev, 0x09, &reg);
if ((reg & 0x0f) != 0x00)
pci_write_config_byte(dev, 0x09, reg&0xf0);
+ /* fall through */
case ATA_16:
/* force per drive recovery and active timings
needed on ATA_33 and below chips */
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index d619e8634a00..13a4cec64ea8 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -433,11 +433,11 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
dev_dbg(&data->client->dev, "Requesting wake-up");
- i2c_lock_adapter(data->client->adapter);
+ i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
gpiod_direction_output(data->wakeup_gpio, 0);
msleep(MLX90614_TIMING_WAKEUP);
gpiod_direction_input(data->wakeup_gpio);
- i2c_unlock_adapter(data->client->adapter);
+ i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
data->ready_timestamp = jiffies +
msecs_to_jiffies(MLX90614_TIMING_STARTUP);
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index 182436b92ba9..6ec748eccff7 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -186,6 +186,7 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,
rbt_ib_umem_for_each_in_range(&context->umem_tree, 0,
ULLONG_MAX,
ib_umem_notifier_release_trampoline,
+ true,
NULL);
up_read(&context->umem_rwsem);
}
@@ -207,22 +208,31 @@ static int invalidate_range_start_trampoline(struct ib_umem *item, u64 start,
return 0;
}
-static void ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct ib_ucontext *context = container_of(mn, struct ib_ucontext, mn);
+ int ret;
if (!context->invalidate_range)
- return;
+ return 0;
+
+ if (blockable)
+ down_read(&context->umem_rwsem);
+ else if (!down_read_trylock(&context->umem_rwsem))
+ return -EAGAIN;
ib_ucontext_notifier_start_account(context);
- down_read(&context->umem_rwsem);
- rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
+ ret = rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
end,
- invalidate_range_start_trampoline, NULL);
+ invalidate_range_start_trampoline,
+ blockable, NULL);
up_read(&context->umem_rwsem);
+
+ return ret;
}
static int invalidate_range_end_trampoline(struct ib_umem *item, u64 start,
@@ -242,10 +252,15 @@ static void ib_umem_notifier_invalidate_range_end(struct mmu_notifier *mn,
if (!context->invalidate_range)
return;
+ /*
+ * TODO: we currently bail out if there is any sleepable work to be done
+ * in ib_umem_notifier_invalidate_range_start so we shouldn't really block
+ * here. But this is ugly and fragile.
+ */
down_read(&context->umem_rwsem);
rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
end,
- invalidate_range_end_trampoline, NULL);
+ invalidate_range_end_trampoline, true, NULL);
up_read(&context->umem_rwsem);
ib_ucontext_notifier_end_account(context);
}
@@ -798,6 +813,7 @@ EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);
int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
u64 start, u64 last,
umem_call_back cb,
+ bool blockable,
void *cookie)
{
int ret_val = 0;
@@ -809,6 +825,9 @@ int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
for (node = rbt_ib_umem_iter_first(root, start, last - 1);
node; node = next) {
+ /* TODO move the blockable decision up to the callback */
+ if (!blockable)
+ return -EAGAIN;
next = rbt_ib_umem_iter_next(node, start, last - 1);
umem = container_of(node, struct ib_umem_odp, interval_tree);
ret_val = cb(umem->umem, start, last, cookie) || ret_val;
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c
index 70aceefe14d5..e1c7996c018e 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -67,9 +67,9 @@ struct mmu_rb_handler {
static unsigned long mmu_node_start(struct mmu_rb_node *);
static unsigned long mmu_node_last(struct mmu_rb_node *);
-static void mmu_notifier_range_start(struct mmu_notifier *,
+static int mmu_notifier_range_start(struct mmu_notifier *,
struct mm_struct *,
- unsigned long, unsigned long);
+ unsigned long, unsigned long, bool);
static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
unsigned long, unsigned long);
static void do_remove(struct mmu_rb_handler *handler,
@@ -284,10 +284,11 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
handler->ops->remove(handler->ops_arg, node);
}
-static void mmu_notifier_range_start(struct mmu_notifier *mn,
+static int mmu_notifier_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct mmu_rb_handler *handler =
container_of(mn, struct mmu_rb_handler, mn);
@@ -313,6 +314,8 @@ static void mmu_notifier_range_start(struct mmu_notifier *mn,
if (added)
queue_work(handler->wq, &handler->del_work);
+
+ return 0;
}
/*
diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c
index f1a87a690a4c..d216e0d2921d 100644
--- a/drivers/infiniband/hw/mlx5/odp.c
+++ b/drivers/infiniband/hw/mlx5/odp.c
@@ -488,7 +488,7 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
down_read(&ctx->umem_rwsem);
rbt_ib_umem_for_each_in_range(&ctx->umem_tree, 0, ULLONG_MAX,
- mr_leaf_free, imr);
+ mr_leaf_free, true, imr);
up_read(&ctx->umem_rwsem);
wait_event(imr->q_leaf_free, !atomic_read(&imr->num_leaf_free));
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 6bd97ffee761..4713957b0cbb 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -721,7 +721,7 @@ config KEYBOARD_CROS_EC
help
Say Y here to enable the matrix keyboard used by ChromeOS devices
and implemented on the ChromeOS EC. You must enable one bus option
- (MFD_CROS_EC_I2C or MFD_CROS_EC_SPI) to use this.
+ (CROS_EC_I2C or CROS_EC_SPI) to use this.
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 3df501c3421b..f8663d7891f2 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -20,32 +20,33 @@
* However, when used with the E3 mailboard that producecs non-standard
* scancodes, a custom key table must be prepared and loaded from userspace.
*/
-#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
-
-#include <mach/ams-delta-fiq.h>
+#define DRIVER_NAME "ams-delta-serio"
MODULE_AUTHOR("Matt Callow");
MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
MODULE_LICENSE("GPL");
-static struct serio *ams_delta_serio;
+struct ams_delta_serio {
+ struct serio *serio;
+ struct regulator *vcc;
+ unsigned int *fiq_buffer;
+};
-static int check_data(int data)
+static int check_data(struct serio *serio, int data)
{
int i, parity = 0;
/* check valid stop bit */
if (!(data & 0x400)) {
- dev_warn(&ams_delta_serio->dev,
- "invalid stop bit, data=0x%X\n",
- data);
+ dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
return SERIO_FRAME;
}
/* calculate the parity */
@@ -55,9 +56,9 @@ static int check_data(int data)
}
/* it should be odd */
if (!(parity & 0x01)) {
- dev_warn(&ams_delta_serio->dev,
- "parity check failed, data=0x%X parity=0x%X\n",
- data, parity);
+ dev_warn(&serio->dev,
+ "parity check failed, data=0x%X parity=0x%X\n", data,
+ parity);
return SERIO_PARITY;
}
return 0;
@@ -65,127 +66,130 @@ static int check_data(int data)
static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
{
- int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
+ struct ams_delta_serio *priv = dev_id;
+ int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
int data, dfl;
u8 scancode;
- fiq_buffer[FIQ_IRQ_PEND] = 0;
+ priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
/*
* Read data from the circular buffer, check it
* and then pass it on the serio
*/
- while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
+ while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
- data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
- fiq_buffer[FIQ_KEYS_CNT]--;
- if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
- fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+ data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
+ priv->fiq_buffer[FIQ_KEYS_CNT]--;
+ if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
+ priv->fiq_buffer[FIQ_BUF_LEN])
+ priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
- dfl = check_data(data);
+ dfl = check_data(priv->serio, data);
scancode = (u8) (data >> 1) & 0xFF;
- serio_interrupt(ams_delta_serio, scancode, dfl);
+ serio_interrupt(priv->serio, scancode, dfl);
}
return IRQ_HANDLED;
}
static int ams_delta_serio_open(struct serio *serio)
{
- /* enable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1);
+ struct ams_delta_serio *priv = serio->port_data;
- return 0;
+ /* enable keyboard */
+ return regulator_enable(priv->vcc);
}
static void ams_delta_serio_close(struct serio *serio)
{
+ struct ams_delta_serio *priv = serio->port_data;
+
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ regulator_disable(priv->vcc);
}
-static const struct gpio ams_delta_gpios[] __initconst_or_module = {
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
- .flags = GPIOF_DIR_IN,
- .label = "serio-data",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
- .flags = GPIOF_DIR_IN,
- .label = "serio-clock",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-dataout",
- },
-};
-
-static int __init ams_delta_serio_init(void)
+static int ams_delta_serio_init(struct platform_device *pdev)
{
- int err;
-
- if (!machine_is_ams_delta())
- return -ENODEV;
+ struct ams_delta_serio *priv;
+ struct serio *serio;
+ int irq, err;
- ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
- if (!ams_delta_serio)
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
return -ENOMEM;
- ams_delta_serio->id.type = SERIO_8042;
- ams_delta_serio->open = ams_delta_serio_open;
- ams_delta_serio->close = ams_delta_serio_close;
- strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
- sizeof(ams_delta_serio->name));
- strlcpy(ams_delta_serio->phys, "GPIO/serio0",
- sizeof(ams_delta_serio->phys));
-
- err = gpio_request_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
- if (err) {
- pr_err("ams_delta_serio: Couldn't request gpio pins\n");
- goto serio;
+ priv->fiq_buffer = pdev->dev.platform_data;
+ if (!priv->fiq_buffer)
+ return -EINVAL;
+
+ priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
+ if (IS_ERR(priv->vcc)) {
+ err = PTR_ERR(priv->vcc);
+ dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
+ /*
+ * When running on a non-dt platform and requested regulator
+ * is not available, devm_regulator_get() never returns
+ * -EPROBE_DEFER as it is not able to justify if the regulator
+ * may still appear later. On the other hand, the board can
+ * still set full constriants flag at late_initcall in order
+ * to instruct devm_regulator_get() to returnn a dummy one
+ * if sufficient. Hence, if we get -ENODEV here, let's convert
+ * it to -EPROBE_DEFER and wait for the board to decide or
+ * let Deferred Probe infrastructure handle this error.
+ */
+ if (err == -ENODEV)
+ err = -EPROBE_DEFER;
+ return err;
}
- err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
- "ams-delta-serio", 0);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
+
+ err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
+ IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
if (err < 0) {
- pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
- gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
- goto gpio;
+ dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
+ return err;
}
- /*
- * Since GPIO register handling for keyboard clock pin is performed
- * at FIQ level, switch back from edge to simple interrupt handler
- * to avoid bad interaction.
- */
- irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- handle_simple_irq);
- serio_register_port(ams_delta_serio);
- dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
+ serio = kzalloc(sizeof(*serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ priv->serio = serio;
+
+ serio->id.type = SERIO_8042;
+ serio->open = ams_delta_serio_open;
+ serio->close = ams_delta_serio_close;
+ strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+ strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+ serio->dev.parent = &pdev->dev;
+ serio->port_data = priv;
+
+ serio_register_port(serio);
+
+ platform_set_drvdata(pdev, priv);
+
+ dev_info(&serio->dev, "%s\n", serio->name);
return 0;
-gpio:
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
-serio:
- kfree(ams_delta_serio);
- return err;
}
-module_init(ams_delta_serio_init);
-static void __exit ams_delta_serio_exit(void)
+static int ams_delta_serio_exit(struct platform_device *pdev)
{
- serio_unregister_port(ams_delta_serio);
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
+ struct ams_delta_serio *priv = platform_get_drvdata(pdev);
+
+ serio_unregister_port(priv->serio);
+
+ return 0;
}
-module_exit(ams_delta_serio_exit);
+
+static struct platform_driver ams_delta_serio_driver = {
+ .probe = ams_delta_serio_init,
+ .remove = ams_delta_serio_exit,
+ .driver = {
+ .name = DRIVER_NAME
+ },
+};
+module_platform_driver(ams_delta_serio_driver);
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index bda0500c9b57..714affdd742f 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
msg[1].len = len;
msg[1].buf = buf;
- i2c_lock_adapter(adap);
+ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
for (i = 0; i < 2; i++) {
if (__i2c_transfer(adap, &msg[i], 1) < 0) {
@@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
}
}
- i2c_unlock_adapter(adap);
+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
return ret;
}
diff --git a/drivers/irqchip/irq-renesas-h8s.c b/drivers/irqchip/irq-renesas-h8s.c
index aed31afb0216..85234d456638 100644
--- a/drivers/irqchip/irq-renesas-h8s.c
+++ b/drivers/irqchip/irq-renesas-h8s.c
@@ -12,7 +12,7 @@
#include <asm/io.h>
static void *intc_baseaddr;
-#define IPRA ((unsigned long)intc_baseaddr)
+#define IPRA (intc_baseaddr)
static const unsigned char ipr_table[] = {
0x03, 0x02, 0x01, 0x00, 0x13, 0x12, 0x11, 0x10, /* 16 - 23 */
@@ -34,7 +34,7 @@ static const unsigned char ipr_table[] = {
static void h8s_disable_irq(struct irq_data *data)
{
int pos;
- unsigned int addr;
+ void __iomem *addr;
unsigned short pri;
int irq = data->irq;
@@ -48,7 +48,7 @@ static void h8s_disable_irq(struct irq_data *data)
static void h8s_enable_irq(struct irq_data *data)
{
int pos;
- unsigned int addr;
+ void __iomem *addr;
unsigned short pri;
int irq = data->irq;
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c
index a15a9510c904..e539500752d4 100644
--- a/drivers/irqchip/irq-xtensa-mx.c
+++ b/drivers/irqchip/irq-xtensa-mx.c
@@ -98,14 +98,12 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
static void xtensa_mx_irq_enable(struct irq_data *d)
{
- variant_irq_enable(d->hwirq);
xtensa_mx_irq_unmask(d);
}
static void xtensa_mx_irq_disable(struct irq_data *d)
{
xtensa_mx_irq_mask(d);
- variant_irq_disable(d->hwirq);
}
static void xtensa_mx_irq_ack(struct irq_data *d)
diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c
index f728755fa292..000cb5462bcf 100644
--- a/drivers/irqchip/irq-xtensa-pic.c
+++ b/drivers/irqchip/irq-xtensa-pic.c
@@ -55,14 +55,12 @@ static void xtensa_irq_unmask(struct irq_data *d)
static void xtensa_irq_enable(struct irq_data *d)
{
- variant_irq_enable(d->hwirq);
xtensa_irq_unmask(d);
}
static void xtensa_irq_disable(struct irq_data *d)
{
xtensa_irq_mask(d);
- variant_irq_disable(d->hwirq);
}
static void xtensa_irq_ack(struct irq_data *d)
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
index 17bf109c58e9..f6e0a8b3a61e 100644
--- a/drivers/md/bcache/Kconfig
+++ b/drivers/md/bcache/Kconfig
@@ -1,7 +1,8 @@
config BCACHE
tristate "Block device as cache"
- ---help---
+ select CRC64
+ help
Allows a block device to be used as cache for other devices; uses
a btree for indexing and the layout is optimized for SSDs.
@@ -10,7 +11,7 @@ config BCACHE
config BCACHE_DEBUG
bool "Bcache debugging"
depends on BCACHE
- ---help---
+ help
Don't select this option unless you're a developer
Enables extra debugging tools, allows expensive runtime checks to be
@@ -20,7 +21,7 @@ config BCACHE_CLOSURES_DEBUG
bool "Debug closures"
depends on BCACHE
select DEBUG_FS
- ---help---
+ help
Keeps all active closures in a linked list and provides a debugfs
interface to list them, which makes it possible to see asynchronous
operations that get stuck.
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index 7fa2631b422c..7a28232d868b 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -87,8 +87,8 @@ void bch_rescale_priorities(struct cache_set *c, int sectors)
{
struct cache *ca;
struct bucket *b;
- unsigned next = c->nbuckets * c->sb.bucket_size / 1024;
- unsigned i;
+ unsigned int next = c->nbuckets * c->sb.bucket_size / 1024;
+ unsigned int i;
int r;
atomic_sub(sectors, &c->rescale);
@@ -169,7 +169,7 @@ static void bch_invalidate_one_bucket(struct cache *ca, struct bucket *b)
#define bucket_prio(b) \
({ \
- unsigned min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; \
+ unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; \
\
(b->prio - ca->set->min_prio + min_prio) * GC_SECTORS_USED(b); \
})
@@ -244,6 +244,7 @@ static void invalidate_buckets_random(struct cache *ca)
while (!fifo_full(&ca->free_inc)) {
size_t n;
+
get_random_bytes(&n, sizeof(n));
n %= (size_t) (ca->sb.nbuckets - ca->sb.first_bucket);
@@ -301,7 +302,7 @@ do { \
static int bch_allocator_push(struct cache *ca, long bucket)
{
- unsigned i;
+ unsigned int i;
/* Prios/gens are actually the most important reserve */
if (fifo_push(&ca->free[RESERVE_PRIO], bucket))
@@ -385,7 +386,7 @@ out:
/* Allocation */
-long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait)
+long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait)
{
DEFINE_WAIT(w);
struct bucket *b;
@@ -421,7 +422,7 @@ out:
if (expensive_debug_checks(ca->set)) {
size_t iter;
long i;
- unsigned j;
+ unsigned int j;
for (iter = 0; iter < prio_buckets(ca) * 2; iter++)
BUG_ON(ca->prio_buckets[iter] == (uint64_t) r);
@@ -470,14 +471,14 @@ void __bch_bucket_free(struct cache *ca, struct bucket *b)
void bch_bucket_free(struct cache_set *c, struct bkey *k)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
__bch_bucket_free(PTR_CACHE(c, k, i),
PTR_BUCKET(c, k, i));
}
-int __bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
+int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
struct bkey *k, int n, bool wait)
{
int i;
@@ -510,10 +511,11 @@ err:
return -1;
}
-int bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
+int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
struct bkey *k, int n, bool wait)
{
int ret;
+
mutex_lock(&c->bucket_lock);
ret = __bch_bucket_alloc_set(c, reserve, k, n, wait);
mutex_unlock(&c->bucket_lock);
@@ -524,8 +526,8 @@ int bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
struct open_bucket {
struct list_head list;
- unsigned last_write_point;
- unsigned sectors_free;
+ unsigned int last_write_point;
+ unsigned int sectors_free;
BKEY_PADDED(key);
};
@@ -556,7 +558,7 @@ struct open_bucket {
*/
static struct open_bucket *pick_data_bucket(struct cache_set *c,
const struct bkey *search,
- unsigned write_point,
+ unsigned int write_point,
struct bkey *alloc)
{
struct open_bucket *ret, *ret_task = NULL;
@@ -595,12 +597,16 @@ found:
*
* If s->writeback is true, will not fail.
*/
-bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned sectors,
- unsigned write_point, unsigned write_prio, bool wait)
+bool bch_alloc_sectors(struct cache_set *c,
+ struct bkey *k,
+ unsigned int sectors,
+ unsigned int write_point,
+ unsigned int write_prio,
+ bool wait)
{
struct open_bucket *b;
BKEY_PADDED(key) alloc;
- unsigned i;
+ unsigned int i;
/*
* We might have to allocate a new bucket, which we can't do with a
@@ -613,7 +619,7 @@ bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned sectors,
spin_lock(&c->data_bucket_lock);
while (!(b = pick_data_bucket(c, k, write_point, &alloc.key))) {
- unsigned watermark = write_prio
+ unsigned int watermark = write_prio
? RESERVE_MOVINGGC
: RESERVE_NONE;
@@ -702,6 +708,7 @@ int bch_open_buckets_alloc(struct cache_set *c)
for (i = 0; i < MAX_OPEN_BUCKETS; i++) {
struct open_bucket *b = kzalloc(sizeof(*b), GFP_KERNEL);
+
if (!b)
return -ENOMEM;
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 05f82ff6f016..83504dd8100a 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -252,7 +252,7 @@ struct bcache_device {
struct kobject kobj;
struct cache_set *c;
- unsigned id;
+ unsigned int id;
#define BCACHEDEVNAME_SIZE 12
char name[BCACHEDEVNAME_SIZE];
@@ -264,18 +264,19 @@ struct bcache_device {
#define BCACHE_DEV_UNLINK_DONE 2
#define BCACHE_DEV_WB_RUNNING 3
#define BCACHE_DEV_RATE_DW_RUNNING 4
- unsigned nr_stripes;
- unsigned stripe_size;
+ unsigned int nr_stripes;
+ unsigned int stripe_size;
atomic_t *stripe_sectors_dirty;
unsigned long *full_dirty_stripes;
struct bio_set bio_split;
- unsigned data_csum:1;
+ unsigned int data_csum:1;
- int (*cache_miss)(struct btree *, struct search *,
- struct bio *, unsigned);
- int (*ioctl) (struct bcache_device *, fmode_t, unsigned, unsigned long);
+ int (*cache_miss)(struct btree *b, struct search *s,
+ struct bio *bio, unsigned int sectors);
+ int (*ioctl)(struct bcache_device *d, fmode_t mode,
+ unsigned int cmd, unsigned long arg);
};
struct io {
@@ -284,7 +285,7 @@ struct io {
struct list_head lru;
unsigned long jiffies;
- unsigned sequential;
+ unsigned int sequential;
sector_t last;
};
@@ -358,18 +359,18 @@ struct cached_dev {
struct cache_accounting accounting;
/* The rest of this all shows up in sysfs */
- unsigned sequential_cutoff;
- unsigned readahead;
+ unsigned int sequential_cutoff;
+ unsigned int readahead;
- unsigned io_disable:1;
- unsigned verify:1;
- unsigned bypass_torture_test:1;
+ unsigned int io_disable:1;
+ unsigned int verify:1;
+ unsigned int bypass_torture_test:1;
- unsigned partial_stripes_expensive:1;
- unsigned writeback_metadata:1;
- unsigned writeback_running:1;
+ unsigned int partial_stripes_expensive:1;
+ unsigned int writeback_metadata:1;
+ unsigned int writeback_running:1;
unsigned char writeback_percent;
- unsigned writeback_delay;
+ unsigned int writeback_delay;
uint64_t writeback_rate_target;
int64_t writeback_rate_proportional;
@@ -377,16 +378,16 @@ struct cached_dev {
int64_t writeback_rate_integral_scaled;
int32_t writeback_rate_change;
- unsigned writeback_rate_update_seconds;
- unsigned writeback_rate_i_term_inverse;
- unsigned writeback_rate_p_term_inverse;
- unsigned writeback_rate_minimum;
+ unsigned int writeback_rate_update_seconds;
+ unsigned int writeback_rate_i_term_inverse;
+ unsigned int writeback_rate_p_term_inverse;
+ unsigned int writeback_rate_minimum;
enum stop_on_failure stop_when_cache_set_failed;
#define DEFAULT_CACHED_DEV_ERROR_LIMIT 64
atomic_t io_errors;
- unsigned error_limit;
- unsigned offline_seconds;
+ unsigned int error_limit;
+ unsigned int offline_seconds;
char backing_dev_name[BDEVNAME_SIZE];
};
@@ -447,7 +448,7 @@ struct cache {
* until a gc finishes - otherwise we could pointlessly burn a ton of
* cpu
*/
- unsigned invalidate_needs_gc;
+ unsigned int invalidate_needs_gc;
bool discard; /* Get rid of? */
@@ -472,7 +473,7 @@ struct gc_stat {
size_t nkeys;
uint64_t data; /* sectors */
- unsigned in_use; /* percent */
+ unsigned int in_use; /* percent */
};
/*
@@ -518,7 +519,7 @@ struct cache_set {
int caches_loaded;
struct bcache_device **devices;
- unsigned devices_max_used;
+ unsigned int devices_max_used;
atomic_t attached_dev_nr;
struct list_head cached_devs;
uint64_t cached_dev_sectors;
@@ -548,7 +549,7 @@ struct cache_set {
* Default number of pages for a new btree node - may be less than a
* full bucket
*/
- unsigned btree_pages;
+ unsigned int btree_pages;
/*
* Lists of struct btrees; lru is the list for structs that have memory
@@ -571,7 +572,7 @@ struct cache_set {
struct list_head btree_cache_freed;
/* Number of elements in btree_cache + btree_cache_freeable lists */
- unsigned btree_cache_used;
+ unsigned int btree_cache_used;
/*
* If we need to allocate memory for a new btree node and that
@@ -613,8 +614,8 @@ struct cache_set {
uint16_t min_prio;
/*
- * max(gen - last_gc) for all buckets. When it gets too big we have to gc
- * to keep gens from wrapping around.
+ * max(gen - last_gc) for all buckets. When it gets too big we have to
+ * gc to keep gens from wrapping around.
*/
uint8_t need_gc;
struct gc_stat gc_stats;
@@ -649,7 +650,7 @@ struct cache_set {
struct mutex verify_lock;
#endif
- unsigned nr_uuids;
+ unsigned int nr_uuids;
struct uuid_entry *uuids;
BKEY_PADDED(uuid_bucket);
struct closure uuid_write;
@@ -670,12 +671,12 @@ struct cache_set {
struct journal journal;
#define CONGESTED_MAX 1024
- unsigned congested_last_us;
+ unsigned int congested_last_us;
atomic_t congested;
/* The rest of this all shows up in sysfs */
- unsigned congested_read_threshold_us;
- unsigned congested_write_threshold_us;
+ unsigned int congested_read_threshold_us;
+ unsigned int congested_write_threshold_us;
struct time_stats btree_gc_time;
struct time_stats btree_split_time;
@@ -694,16 +695,16 @@ struct cache_set {
ON_ERROR_PANIC,
} on_error;
#define DEFAULT_IO_ERROR_LIMIT 8
- unsigned error_limit;
- unsigned error_decay;
+ unsigned int error_limit;
+ unsigned int error_decay;
unsigned short journal_delay_ms;
bool expensive_debug_checks;
- unsigned verify:1;
- unsigned key_merging_disabled:1;
- unsigned gc_always_rewrite:1;
- unsigned shrinker_disabled:1;
- unsigned copy_gc_enabled:1;
+ unsigned int verify:1;
+ unsigned int key_merging_disabled:1;
+ unsigned int gc_always_rewrite:1;
+ unsigned int shrinker_disabled:1;
+ unsigned int copy_gc_enabled:1;
#define BUCKET_HASH_BITS 12
struct hlist_head bucket_hash[1 << BUCKET_HASH_BITS];
@@ -712,7 +713,7 @@ struct cache_set {
};
struct bbio {
- unsigned submit_time_us;
+ unsigned int submit_time_us;
union {
struct bkey key;
uint64_t _pad[3];
@@ -729,10 +730,10 @@ struct bbio {
#define btree_bytes(c) ((c)->btree_pages * PAGE_SIZE)
#define btree_blocks(b) \
- ((unsigned) (KEY_SIZE(&b->key) >> (b)->c->block_bits))
+ ((unsigned int) (KEY_SIZE(&b->key) >> (b)->c->block_bits))
#define btree_default_blocks(c) \
- ((unsigned) ((PAGE_SECTORS * (c)->btree_pages) >> (c)->block_bits))
+ ((unsigned int) ((PAGE_SECTORS * (c)->btree_pages) >> (c)->block_bits))
#define bucket_pages(c) ((c)->sb.bucket_size / PAGE_SECTORS)
#define bucket_bytes(c) ((c)->sb.bucket_size << 9)
@@ -761,21 +762,21 @@ static inline sector_t bucket_remainder(struct cache_set *c, sector_t s)
static inline struct cache *PTR_CACHE(struct cache_set *c,
const struct bkey *k,
- unsigned ptr)
+ unsigned int ptr)
{
return c->cache[PTR_DEV(k, ptr)];
}
static inline size_t PTR_BUCKET_NR(struct cache_set *c,
const struct bkey *k,
- unsigned ptr)
+ unsigned int ptr)
{
return sector_to_bucket(c, PTR_OFFSET(k, ptr));
}
static inline struct bucket *PTR_BUCKET(struct cache_set *c,
const struct bkey *k,
- unsigned ptr)
+ unsigned int ptr)
{
return PTR_CACHE(c, k, ptr)->buckets + PTR_BUCKET_NR(c, k, ptr);
}
@@ -783,17 +784,18 @@ static inline struct bucket *PTR_BUCKET(struct cache_set *c,
static inline uint8_t gen_after(uint8_t a, uint8_t b)
{
uint8_t r = a - b;
+
return r > 128U ? 0 : r;
}
static inline uint8_t ptr_stale(struct cache_set *c, const struct bkey *k,
- unsigned i)
+ unsigned int i)
{
return gen_after(PTR_BUCKET(c, k, i)->gen, PTR_GEN(k, i));
}
static inline bool ptr_available(struct cache_set *c, const struct bkey *k,
- unsigned i)
+ unsigned int i)
{
return (PTR_DEV(k, i) < MAX_CACHES_PER_SET) && PTR_CACHE(c, k, i);
}
@@ -879,16 +881,16 @@ static inline uint8_t bucket_gc_gen(struct bucket *b)
#define BUCKET_GC_GEN_MAX 96U
#define kobj_attribute_write(n, fn) \
- static struct kobj_attribute ksysfs_##n = __ATTR(n, S_IWUSR, NULL, fn)
+ static struct kobj_attribute ksysfs_##n = __ATTR(n, 0200, NULL, fn)
#define kobj_attribute_rw(n, show, store) \
static struct kobj_attribute ksysfs_##n = \
- __ATTR(n, S_IWUSR|S_IRUSR, show, store)
+ __ATTR(n, 0600, show, store)
static inline void wake_up_allocators(struct cache_set *c)
{
struct cache *ca;
- unsigned i;
+ unsigned int i;
for_each_cache(ca, c, i)
wake_up_process(ca->alloc_thread);
@@ -924,40 +926,43 @@ static inline void wait_for_kthread_stop(void)
/* Forward declarations */
void bch_count_backing_io_errors(struct cached_dev *dc, struct bio *bio);
-void bch_count_io_errors(struct cache *, blk_status_t, int, const char *);
-void bch_bbio_count_io_errors(struct cache_set *, struct bio *,
- blk_status_t, const char *);
-void bch_bbio_endio(struct cache_set *, struct bio *, blk_status_t,
- const char *);
-void bch_bbio_free(struct bio *, struct cache_set *);
-struct bio *bch_bbio_alloc(struct cache_set *);
-
-void __bch_submit_bbio(struct bio *, struct cache_set *);
-void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned);
-
-uint8_t bch_inc_gen(struct cache *, struct bucket *);
-void bch_rescale_priorities(struct cache_set *, int);
-
-bool bch_can_invalidate_bucket(struct cache *, struct bucket *);
-void __bch_invalidate_one_bucket(struct cache *, struct bucket *);
-
-void __bch_bucket_free(struct cache *, struct bucket *);
-void bch_bucket_free(struct cache_set *, struct bkey *);
-
-long bch_bucket_alloc(struct cache *, unsigned, bool);
-int __bch_bucket_alloc_set(struct cache_set *, unsigned,
- struct bkey *, int, bool);
-int bch_bucket_alloc_set(struct cache_set *, unsigned,
- struct bkey *, int, bool);
-bool bch_alloc_sectors(struct cache_set *, struct bkey *, unsigned,
- unsigned, unsigned, bool);
+void bch_count_io_errors(struct cache *ca, blk_status_t error,
+ int is_read, const char *m);
+void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
+ blk_status_t error, const char *m);
+void bch_bbio_endio(struct cache_set *c, struct bio *bio,
+ blk_status_t error, const char *m);
+void bch_bbio_free(struct bio *bio, struct cache_set *c);
+struct bio *bch_bbio_alloc(struct cache_set *c);
+
+void __bch_submit_bbio(struct bio *bio, struct cache_set *c);
+void bch_submit_bbio(struct bio *bio, struct cache_set *c,
+ struct bkey *k, unsigned int ptr);
+
+uint8_t bch_inc_gen(struct cache *ca, struct bucket *b);
+void bch_rescale_priorities(struct cache_set *c, int sectors);
+
+bool bch_can_invalidate_bucket(struct cache *ca, struct bucket *b);
+void __bch_invalidate_one_bucket(struct cache *ca, struct bucket *b);
+
+void __bch_bucket_free(struct cache *ca, struct bucket *b);
+void bch_bucket_free(struct cache_set *c, struct bkey *k);
+
+long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait);
+int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
+ struct bkey *k, int n, bool wait);
+int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
+ struct bkey *k, int n, bool wait);
+bool bch_alloc_sectors(struct cache_set *c, struct bkey *k,
+ unsigned int sectors, unsigned int write_point,
+ unsigned int write_prio, bool wait);
bool bch_cached_dev_error(struct cached_dev *dc);
__printf(2, 3)
-bool bch_cache_set_error(struct cache_set *, const char *, ...);
+bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...);
-void bch_prio_write(struct cache *);
-void bch_write_bdev_super(struct cached_dev *, struct closure *);
+void bch_prio_write(struct cache *ca);
+void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
extern struct workqueue_struct *bcache_wq;
extern struct mutex bch_register_lock;
@@ -969,30 +974,31 @@ extern struct kobj_type bch_cache_set_ktype;
extern struct kobj_type bch_cache_set_internal_ktype;
extern struct kobj_type bch_cache_ktype;
-void bch_cached_dev_release(struct kobject *);
-void bch_flash_dev_release(struct kobject *);
-void bch_cache_set_release(struct kobject *);
-void bch_cache_release(struct kobject *);
+void bch_cached_dev_release(struct kobject *kobj);
+void bch_flash_dev_release(struct kobject *kobj);
+void bch_cache_set_release(struct kobject *kobj);
+void bch_cache_release(struct kobject *kobj);
-int bch_uuid_write(struct cache_set *);
-void bcache_write_super(struct cache_set *);
+int bch_uuid_write(struct cache_set *c);
+void bcache_write_super(struct cache_set *c);
int bch_flash_dev_create(struct cache_set *c, uint64_t size);
-int bch_cached_dev_attach(struct cached_dev *, struct cache_set *, uint8_t *);
-void bch_cached_dev_detach(struct cached_dev *);
-void bch_cached_dev_run(struct cached_dev *);
-void bcache_device_stop(struct bcache_device *);
-
-void bch_cache_set_unregister(struct cache_set *);
-void bch_cache_set_stop(struct cache_set *);
-
-struct cache_set *bch_cache_set_alloc(struct cache_sb *);
-void bch_btree_cache_free(struct cache_set *);
-int bch_btree_cache_alloc(struct cache_set *);
-void bch_moving_init_cache_set(struct cache_set *);
-int bch_open_buckets_alloc(struct cache_set *);
-void bch_open_buckets_free(struct cache_set *);
+int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
+ uint8_t *set_uuid);
+void bch_cached_dev_detach(struct cached_dev *dc);
+void bch_cached_dev_run(struct cached_dev *dc);
+void bcache_device_stop(struct bcache_device *d);
+
+void bch_cache_set_unregister(struct cache_set *c);
+void bch_cache_set_stop(struct cache_set *c);
+
+struct cache_set *bch_cache_set_alloc(struct cache_sb *sb);
+void bch_btree_cache_free(struct cache_set *c);
+int bch_btree_cache_alloc(struct cache_set *c);
+void bch_moving_init_cache_set(struct cache_set *c);
+int bch_open_buckets_alloc(struct cache_set *c);
+void bch_open_buckets_free(struct cache_set *c);
int bch_cache_allocator_start(struct cache *ca);
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 596c93b44e9b..8f07fa6e1739 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -18,31 +18,31 @@
#ifdef CONFIG_BCACHE_DEBUG
-void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned set)
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set)
{
struct bkey *k, *next;
for (k = i->start; k < bset_bkey_last(i); k = next) {
next = bkey_next(k);
- printk(KERN_ERR "block %u key %u/%u: ", set,
- (unsigned) ((u64 *) k - i->d), i->keys);
+ pr_err("block %u key %u/%u: ", set,
+ (unsigned int) ((u64 *) k - i->d), i->keys);
if (b->ops->key_dump)
b->ops->key_dump(b, k);
else
- printk("%llu:%llu\n", KEY_INODE(k), KEY_OFFSET(k));
+ pr_err("%llu:%llu\n", KEY_INODE(k), KEY_OFFSET(k));
if (next < bset_bkey_last(i) &&
bkey_cmp(k, b->ops->is_extents ?
&START_KEY(next) : next) > 0)
- printk(KERN_ERR "Key skipped backwards\n");
+ pr_err("Key skipped backwards\n");
}
}
void bch_dump_bucket(struct btree_keys *b)
{
- unsigned i;
+ unsigned int i;
console_lock();
for (i = 0; i <= b->nsets; i++)
@@ -53,7 +53,7 @@ void bch_dump_bucket(struct btree_keys *b)
int __bch_count_data(struct btree_keys *b)
{
- unsigned ret = 0;
+ unsigned int ret = 0;
struct btree_iter iter;
struct bkey *k;
@@ -128,7 +128,7 @@ static inline void bch_btree_iter_next_check(struct btree_iter *iter) {}
/* Keylists */
-int __bch_keylist_realloc(struct keylist *l, unsigned u64s)
+int __bch_keylist_realloc(struct keylist *l, unsigned int u64s)
{
size_t oldsize = bch_keylist_nkeys(l);
size_t newsize = oldsize + u64s;
@@ -180,7 +180,7 @@ void bch_keylist_pop_front(struct keylist *l)
/* Key/pointer manipulation */
void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
- unsigned i)
+ unsigned int i)
{
BUG_ON(i > KEY_PTRS(src));
@@ -194,7 +194,7 @@ void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
bool __bch_cut_front(const struct bkey *where, struct bkey *k)
{
- unsigned i, len = 0;
+ unsigned int i, len = 0;
if (bkey_cmp(where, &START_KEY(k)) <= 0)
return false;
@@ -214,7 +214,7 @@ bool __bch_cut_front(const struct bkey *where, struct bkey *k)
bool __bch_cut_back(const struct bkey *where, struct bkey *k)
{
- unsigned len = 0;
+ unsigned int len = 0;
if (bkey_cmp(where, k) >= 0)
return false;
@@ -240,9 +240,9 @@ bool __bch_cut_back(const struct bkey *where, struct bkey *k)
#define BKEY_MANTISSA_MASK ((1 << BKEY_MANTISSA_BITS) - 1)
struct bkey_float {
- unsigned exponent:BKEY_EXPONENT_BITS;
- unsigned m:BKEY_MID_BITS;
- unsigned mantissa:BKEY_MANTISSA_BITS;
+ unsigned int exponent:BKEY_EXPONENT_BITS;
+ unsigned int m:BKEY_MID_BITS;
+ unsigned int mantissa:BKEY_MANTISSA_BITS;
} __packed;
/*
@@ -311,7 +311,9 @@ void bch_btree_keys_free(struct btree_keys *b)
}
EXPORT_SYMBOL(bch_btree_keys_free);
-int bch_btree_keys_alloc(struct btree_keys *b, unsigned page_order, gfp_t gfp)
+int bch_btree_keys_alloc(struct btree_keys *b,
+ unsigned int page_order,
+ gfp_t gfp)
{
struct bset_tree *t = b->set;
@@ -345,7 +347,7 @@ EXPORT_SYMBOL(bch_btree_keys_alloc);
void bch_btree_keys_init(struct btree_keys *b, const struct btree_keys_ops *ops,
bool *expensive_debug_checks)
{
- unsigned i;
+ unsigned int i;
b->ops = ops;
b->expensive_debug_checks = expensive_debug_checks;
@@ -370,7 +372,7 @@ EXPORT_SYMBOL(bch_btree_keys_init);
* return array index next to j when does in-order traverse
* of a binary tree which is stored in a linear array
*/
-static unsigned inorder_next(unsigned j, unsigned size)
+static unsigned int inorder_next(unsigned int j, unsigned int size)
{
if (j * 2 + 1 < size) {
j = j * 2 + 1;
@@ -387,7 +389,7 @@ static unsigned inorder_next(unsigned j, unsigned size)
* return array index previous to j when does in-order traverse
* of a binary tree which is stored in a linear array
*/
-static unsigned inorder_prev(unsigned j, unsigned size)
+static unsigned int inorder_prev(unsigned int j, unsigned int size)
{
if (j * 2 < size) {
j = j * 2;
@@ -400,7 +402,8 @@ static unsigned inorder_prev(unsigned j, unsigned size)
return j;
}
-/* I have no idea why this code works... and I'm the one who wrote it
+/*
+ * I have no idea why this code works... and I'm the one who wrote it
*
* However, I do know what it does:
* Given a binary tree constructed in an array (i.e. how you normally implement
@@ -413,10 +416,12 @@ static unsigned inorder_prev(unsigned j, unsigned size)
* extra is a function of size:
* extra = (size - rounddown_pow_of_two(size - 1)) << 1;
*/
-static unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
+static unsigned int __to_inorder(unsigned int j,
+ unsigned int size,
+ unsigned int extra)
{
- unsigned b = fls(j);
- unsigned shift = fls(size - 1) - b;
+ unsigned int b = fls(j);
+ unsigned int shift = fls(size - 1) - b;
j ^= 1U << (b - 1);
j <<= 1;
@@ -433,14 +438,16 @@ static unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
* Return the cacheline index in bset_tree->data, where j is index
* from a linear array which stores the auxiliar binary tree
*/
-static unsigned to_inorder(unsigned j, struct bset_tree *t)
+static unsigned int to_inorder(unsigned int j, struct bset_tree *t)
{
return __to_inorder(j, t->size, t->extra);
}
-static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
+static unsigned int __inorder_to_tree(unsigned int j,
+ unsigned int size,
+ unsigned int extra)
{
- unsigned shift;
+ unsigned int shift;
if (j > extra)
j += j - extra;
@@ -457,7 +464,7 @@ static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
* Return an index from a linear array which stores the auxiliar binary
* tree, j is the cacheline index of t->data.
*/
-static unsigned inorder_to_tree(unsigned j, struct bset_tree *t)
+static unsigned int inorder_to_tree(unsigned int j, struct bset_tree *t)
{
return __inorder_to_tree(j, t->size, t->extra);
}
@@ -468,14 +475,15 @@ void inorder_test(void)
unsigned long done = 0;
ktime_t start = ktime_get();
- for (unsigned size = 2;
+ for (unsigned int size = 2;
size < 65536000;
size++) {
- unsigned extra = (size - rounddown_pow_of_two(size - 1)) << 1;
- unsigned i = 1, j = rounddown_pow_of_two(size - 1);
+ unsigned int extra =
+ (size - rounddown_pow_of_two(size - 1)) << 1;
+ unsigned int i = 1, j = rounddown_pow_of_two(size - 1);
if (!(size % 4096))
- printk(KERN_NOTICE "loop %u, %llu per us\n", size,
+ pr_notice("loop %u, %llu per us\n", size,
done / ktime_us_delta(ktime_get(), start));
while (1) {
@@ -518,30 +526,31 @@ void inorder_test(void)
* of the previous key so we can walk backwards to it from t->tree[j]'s key.
*/
-static struct bkey *cacheline_to_bkey(struct bset_tree *t, unsigned cacheline,
- unsigned offset)
+static struct bkey *cacheline_to_bkey(struct bset_tree *t,
+ unsigned int cacheline,
+ unsigned int offset)
{
return ((void *) t->data) + cacheline * BSET_CACHELINE + offset * 8;
}
-static unsigned bkey_to_cacheline(struct bset_tree *t, struct bkey *k)
+static unsigned int bkey_to_cacheline(struct bset_tree *t, struct bkey *k)
{
return ((void *) k - (void *) t->data) / BSET_CACHELINE;
}
-static unsigned bkey_to_cacheline_offset(struct bset_tree *t,
- unsigned cacheline,
+static unsigned int bkey_to_cacheline_offset(struct bset_tree *t,
+ unsigned int cacheline,
struct bkey *k)
{
return (u64 *) k - (u64 *) cacheline_to_bkey(t, cacheline, 0);
}
-static struct bkey *tree_to_bkey(struct bset_tree *t, unsigned j)
+static struct bkey *tree_to_bkey(struct bset_tree *t, unsigned int j)
{
return cacheline_to_bkey(t, to_inorder(j, t), t->tree[j].m);
}
-static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned j)
+static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned int j)
{
return (void *) (((uint64_t *) tree_to_bkey(t, j)) - t->prev[j]);
}
@@ -550,7 +559,7 @@ static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned j)
* For the write set - the one we're currently inserting keys into - we don't
* maintain a full search tree, we just keep a simple lookup table in t->prev.
*/
-static struct bkey *table_to_bkey(struct bset_tree *t, unsigned cacheline)
+static struct bkey *table_to_bkey(struct bset_tree *t, unsigned int cacheline)
{
return cacheline_to_bkey(t, cacheline, t->prev[cacheline]);
}
@@ -576,14 +585,15 @@ static inline uint64_t shrd128(uint64_t high, uint64_t low, uint8_t shift)
* See make_bfloat() to check when most significant bit of f->exponent
* is set or not.
*/
-static inline unsigned bfloat_mantissa(const struct bkey *k,
+static inline unsigned int bfloat_mantissa(const struct bkey *k,
struct bkey_float *f)
{
const uint64_t *p = &k->low - (f->exponent >> 6);
+
return shrd128(p[-1], p[0], f->exponent & 63) & BKEY_MANTISSA_MASK;
}
-static void make_bfloat(struct bset_tree *t, unsigned j)
+static void make_bfloat(struct bset_tree *t, unsigned int j)
{
struct bkey_float *f = &t->tree[j];
struct bkey *m = tree_to_bkey(t, j);
@@ -631,7 +641,7 @@ static void make_bfloat(struct bset_tree *t, unsigned j)
static void bset_alloc_tree(struct btree_keys *b, struct bset_tree *t)
{
if (t != b->set) {
- unsigned j = roundup(t[-1].size,
+ unsigned int j = roundup(t[-1].size,
64 / sizeof(struct bkey_float));
t->tree = t[-1].tree + j;
@@ -686,13 +696,13 @@ void bch_bset_build_written_tree(struct btree_keys *b)
{
struct bset_tree *t = bset_tree_last(b);
struct bkey *prev = NULL, *k = t->data->start;
- unsigned j, cacheline = 1;
+ unsigned int j, cacheline = 1;
b->last_set_unwritten = 0;
bset_alloc_tree(b, t);
- t->size = min_t(unsigned,
+ t->size = min_t(unsigned int,
bkey_to_cacheline(t, bset_bkey_last(t->data)),
b->set->tree + btree_keys_cachelines(b) - t->tree);
@@ -732,7 +742,7 @@ EXPORT_SYMBOL(bch_bset_build_written_tree);
void bch_bset_fix_invalidated_key(struct btree_keys *b, struct bkey *k)
{
struct bset_tree *t;
- unsigned inorder, j = 1;
+ unsigned int inorder, j = 1;
for (t = b->set; t <= bset_tree_last(b); t++)
if (k < bset_bkey_last(t->data))
@@ -779,14 +789,15 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
struct bset_tree *t,
struct bkey *k)
{
- unsigned shift = bkey_u64s(k);
- unsigned j = bkey_to_cacheline(t, k);
+ unsigned int shift = bkey_u64s(k);
+ unsigned int j = bkey_to_cacheline(t, k);
/* We're getting called from btree_split() or btree_gc, just bail out */
if (!t->size)
return;
- /* k is the key we just inserted; we need to find the entry in the
+ /*
+ * k is the key we just inserted; we need to find the entry in the
* lookup table for the first key that is strictly greater than k:
* it's either k's cacheline or the next one
*/
@@ -794,7 +805,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
table_to_bkey(t, j) <= k)
j++;
- /* Adjust all the lookup table entries, and find a new key for any that
+ /*
+ * Adjust all the lookup table entries, and find a new key for any that
* have gotten too big
*/
for (; j < t->size; j++) {
@@ -819,7 +831,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
k != bset_bkey_last(t->data);
k = bkey_next(k))
if (t->size == bkey_to_cacheline(t, k)) {
- t->prev[t->size] = bkey_to_cacheline_offset(t, t->size, k);
+ t->prev[t->size] =
+ bkey_to_cacheline_offset(t, t->size, k);
t->size++;
}
}
@@ -867,10 +880,10 @@ void bch_bset_insert(struct btree_keys *b, struct bkey *where,
}
EXPORT_SYMBOL(bch_bset_insert);
-unsigned bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
+unsigned int bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
struct bkey *replace_key)
{
- unsigned status = BTREE_INSERT_STATUS_NO_INSERT;
+ unsigned int status = BTREE_INSERT_STATUS_NO_INSERT;
struct bset *i = bset_tree_last(b)->data;
struct bkey *m, *prev = NULL;
struct btree_iter iter;
@@ -922,10 +935,10 @@ struct bset_search_iter {
static struct bset_search_iter bset_search_write_set(struct bset_tree *t,
const struct bkey *search)
{
- unsigned li = 0, ri = t->size;
+ unsigned int li = 0, ri = t->size;
while (li + 1 != ri) {
- unsigned m = (li + ri) >> 1;
+ unsigned int m = (li + ri) >> 1;
if (bkey_cmp(table_to_bkey(t, m), search) > 0)
ri = m;
@@ -944,7 +957,7 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
{
struct bkey *l, *r;
struct bkey_float *f;
- unsigned inorder, j, n = 1;
+ unsigned int inorder, j, n = 1;
do {
/*
@@ -958,7 +971,8 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
* p = 0;
* but a branch instruction is avoided.
*/
- unsigned p = n << 4;
+ unsigned int p = n << 4;
+
p &= ((int) (p - t->size)) >> 31;
prefetch(&t->tree[p]);
@@ -978,7 +992,7 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
* to work - that's done in make_bfloat()
*/
if (likely(f->exponent != 127))
- n = j * 2 + (((unsigned)
+ n = j * 2 + (((unsigned int)
(f->mantissa -
bfloat_mantissa(search, f))) >> 31);
else
@@ -1109,6 +1123,7 @@ static struct bkey *__bch_btree_iter_init(struct btree_keys *b,
struct bset_tree *start)
{
struct bkey *ret = NULL;
+
iter->size = ARRAY_SIZE(iter->data);
iter->used = 0;
@@ -1184,7 +1199,8 @@ void bch_bset_sort_state_free(struct bset_sort_state *state)
mempool_exit(&state->pool);
}
-int bch_bset_sort_state_init(struct bset_sort_state *state, unsigned page_order)
+int bch_bset_sort_state_init(struct bset_sort_state *state,
+ unsigned int page_order)
{
spin_lock_init(&state->time.lock);
@@ -1237,7 +1253,7 @@ static void btree_mergesort(struct btree_keys *b, struct bset *out,
}
static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
- unsigned start, unsigned order, bool fixup,
+ unsigned int start, unsigned int order, bool fixup,
struct bset_sort_state *state)
{
uint64_t start_time;
@@ -1288,7 +1304,7 @@ static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
bch_time_stats_update(&state->time, start_time);
}
-void bch_btree_sort_partial(struct btree_keys *b, unsigned start,
+void bch_btree_sort_partial(struct btree_keys *b, unsigned int start,
struct bset_sort_state *state)
{
size_t order = b->page_order, keys = 0;
@@ -1298,7 +1314,7 @@ void bch_btree_sort_partial(struct btree_keys *b, unsigned start,
__bch_btree_iter_init(b, &iter, NULL, &b->set[start]);
if (start) {
- unsigned i;
+ unsigned int i;
for (i = start; i <= b->nsets; i++)
keys += b->set[i].data->keys;
@@ -1323,8 +1339,8 @@ void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
struct bset_sort_state *state)
{
uint64_t start_time = local_clock();
-
struct btree_iter iter;
+
bch_btree_iter_init(b, &iter, NULL);
btree_mergesort(b, new->set->data, &iter, false, true);
@@ -1338,7 +1354,7 @@ void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
void bch_btree_sort_lazy(struct btree_keys *b, struct bset_sort_state *state)
{
- unsigned crit = SORT_CRIT;
+ unsigned int crit = SORT_CRIT;
int i;
/* Don't sort if nothing to do */
@@ -1367,7 +1383,7 @@ EXPORT_SYMBOL(bch_btree_sort_lazy);
void bch_btree_keys_stats(struct btree_keys *b, struct bset_stats *stats)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i <= b->nsets; i++) {
struct bset_tree *t = &b->set[i];
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index b867f2200495..bac76aabca6d 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -163,10 +163,10 @@ struct bset_tree {
*/
/* size of the binary tree and prev array */
- unsigned size;
+ unsigned int size;
/* function of size - precalculated for to_inorder() */
- unsigned extra;
+ unsigned int extra;
/* copy of the last key in the set */
struct bkey end;
@@ -187,18 +187,25 @@ struct bset_tree {
};
struct btree_keys_ops {
- bool (*sort_cmp)(struct btree_iter_set,
- struct btree_iter_set);
- struct bkey *(*sort_fixup)(struct btree_iter *, struct bkey *);
- bool (*insert_fixup)(struct btree_keys *, struct bkey *,
- struct btree_iter *, struct bkey *);
- bool (*key_invalid)(struct btree_keys *,
- const struct bkey *);
- bool (*key_bad)(struct btree_keys *, const struct bkey *);
- bool (*key_merge)(struct btree_keys *,
- struct bkey *, struct bkey *);
- void (*key_to_text)(char *, size_t, const struct bkey *);
- void (*key_dump)(struct btree_keys *, const struct bkey *);
+ bool (*sort_cmp)(struct btree_iter_set l,
+ struct btree_iter_set r);
+ struct bkey *(*sort_fixup)(struct btree_iter *iter,
+ struct bkey *tmp);
+ bool (*insert_fixup)(struct btree_keys *b,
+ struct bkey *insert,
+ struct btree_iter *iter,
+ struct bkey *replace_key);
+ bool (*key_invalid)(struct btree_keys *bk,
+ const struct bkey *k);
+ bool (*key_bad)(struct btree_keys *bk,
+ const struct bkey *k);
+ bool (*key_merge)(struct btree_keys *bk,
+ struct bkey *l, struct bkey *r);
+ void (*key_to_text)(char *buf,
+ size_t size,
+ const struct bkey *k);
+ void (*key_dump)(struct btree_keys *keys,
+ const struct bkey *k);
/*
* Only used for deciding whether to use START_KEY(k) or just the key
@@ -211,7 +218,7 @@ struct btree_keys {
const struct btree_keys_ops *ops;
uint8_t page_order;
uint8_t nsets;
- unsigned last_set_unwritten:1;
+ unsigned int last_set_unwritten:1;
bool *expensive_debug_checks;
/*
@@ -239,12 +246,14 @@ static inline bool bkey_written(struct btree_keys *b, struct bkey *k)
return !b->last_set_unwritten || k < b->set[b->nsets].data->start;
}
-static inline unsigned bset_byte_offset(struct btree_keys *b, struct bset *i)
+static inline unsigned int bset_byte_offset(struct btree_keys *b,
+ struct bset *i)
{
return ((size_t) i) - ((size_t) b->set->data);
}
-static inline unsigned bset_sector_offset(struct btree_keys *b, struct bset *i)
+static inline unsigned int bset_sector_offset(struct btree_keys *b,
+ struct bset *i)
{
return bset_byte_offset(b, i) >> 9;
}
@@ -273,25 +282,27 @@ static inline size_t bch_btree_keys_u64s_remaining(struct btree_keys *b)
}
static inline struct bset *bset_next_set(struct btree_keys *b,
- unsigned block_bytes)
+ unsigned int block_bytes)
{
struct bset *i = bset_tree_last(b)->data;
return ((void *) i) + roundup(set_bytes(i), block_bytes);
}
-void bch_btree_keys_free(struct btree_keys *);
-int bch_btree_keys_alloc(struct btree_keys *, unsigned, gfp_t);
-void bch_btree_keys_init(struct btree_keys *, const struct btree_keys_ops *,
- bool *);
-
-void bch_bset_init_next(struct btree_keys *, struct bset *, uint64_t);
-void bch_bset_build_written_tree(struct btree_keys *);
-void bch_bset_fix_invalidated_key(struct btree_keys *, struct bkey *);
-bool bch_bkey_try_merge(struct btree_keys *, struct bkey *, struct bkey *);
-void bch_bset_insert(struct btree_keys *, struct bkey *, struct bkey *);
-unsigned bch_btree_insert_key(struct btree_keys *, struct bkey *,
- struct bkey *);
+void bch_btree_keys_free(struct btree_keys *b);
+int bch_btree_keys_alloc(struct btree_keys *b, unsigned int page_order,
+ gfp_t gfp);
+void bch_btree_keys_init(struct btree_keys *b, const struct btree_keys_ops *ops,
+ bool *expensive_debug_checks);
+
+void bch_bset_init_next(struct btree_keys *b, struct bset *i, uint64_t magic);
+void bch_bset_build_written_tree(struct btree_keys *b);
+void bch_bset_fix_invalidated_key(struct btree_keys *b, struct bkey *k);
+bool bch_bkey_try_merge(struct btree_keys *b, struct bkey *l, struct bkey *r);
+void bch_bset_insert(struct btree_keys *b, struct bkey *where,
+ struct bkey *insert);
+unsigned int bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
+ struct bkey *replace_key);
enum {
BTREE_INSERT_STATUS_NO_INSERT = 0,
@@ -313,18 +324,21 @@ struct btree_iter {
} data[MAX_BSETS];
};
-typedef bool (*ptr_filter_fn)(struct btree_keys *, const struct bkey *);
+typedef bool (*ptr_filter_fn)(struct btree_keys *b, const struct bkey *k);
-struct bkey *bch_btree_iter_next(struct btree_iter *);
-struct bkey *bch_btree_iter_next_filter(struct btree_iter *,
- struct btree_keys *, ptr_filter_fn);
+struct bkey *bch_btree_iter_next(struct btree_iter *iter);
+struct bkey *bch_btree_iter_next_filter(struct btree_iter *iter,
+ struct btree_keys *b,
+ ptr_filter_fn fn);
-void bch_btree_iter_push(struct btree_iter *, struct bkey *, struct bkey *);
-struct bkey *bch_btree_iter_init(struct btree_keys *, struct btree_iter *,
- struct bkey *);
+void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k,
+ struct bkey *end);
+struct bkey *bch_btree_iter_init(struct btree_keys *b,
+ struct btree_iter *iter,
+ struct bkey *search);
-struct bkey *__bch_bset_search(struct btree_keys *, struct bset_tree *,
- const struct bkey *);
+struct bkey *__bch_bset_search(struct btree_keys *b, struct bset_tree *t,
+ const struct bkey *search);
/*
* Returns the first key that is strictly greater than search
@@ -349,21 +363,23 @@ static inline struct bkey *bch_bset_search(struct btree_keys *b,
struct bset_sort_state {
mempool_t pool;
- unsigned page_order;
- unsigned crit_factor;
+ unsigned int page_order;
+ unsigned int crit_factor;
struct time_stats time;
};
-void bch_bset_sort_state_free(struct bset_sort_state *);
-int bch_bset_sort_state_init(struct bset_sort_state *, unsigned);
-void bch_btree_sort_lazy(struct btree_keys *, struct bset_sort_state *);
-void bch_btree_sort_into(struct btree_keys *, struct btree_keys *,
- struct bset_sort_state *);
-void bch_btree_sort_and_fix_extents(struct btree_keys *, struct btree_iter *,
- struct bset_sort_state *);
-void bch_btree_sort_partial(struct btree_keys *, unsigned,
- struct bset_sort_state *);
+void bch_bset_sort_state_free(struct bset_sort_state *state);
+int bch_bset_sort_state_init(struct bset_sort_state *state,
+ unsigned int page_order);
+void bch_btree_sort_lazy(struct btree_keys *b, struct bset_sort_state *state);
+void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
+ struct bset_sort_state *state);
+void bch_btree_sort_and_fix_extents(struct btree_keys *b,
+ struct btree_iter *iter,
+ struct bset_sort_state *state);
+void bch_btree_sort_partial(struct btree_keys *b, unsigned int start,
+ struct bset_sort_state *state);
static inline void bch_btree_sort(struct btree_keys *b,
struct bset_sort_state *state)
@@ -377,13 +393,13 @@ struct bset_stats {
size_t floats, failed;
};
-void bch_btree_keys_stats(struct btree_keys *, struct bset_stats *);
+void bch_btree_keys_stats(struct btree_keys *b, struct bset_stats *state);
/* Bkey utility code */
#define bset_bkey_last(i) bkey_idx((struct bkey *) (i)->d, (i)->keys)
-static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned idx)
+static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned int idx)
{
return bkey_idx(i->start, idx);
}
@@ -401,10 +417,10 @@ static __always_inline int64_t bkey_cmp(const struct bkey *l,
: (int64_t) KEY_OFFSET(l) - (int64_t) KEY_OFFSET(r);
}
-void bch_bkey_copy_single_ptr(struct bkey *, const struct bkey *,
- unsigned);
-bool __bch_cut_front(const struct bkey *, struct bkey *);
-bool __bch_cut_back(const struct bkey *, struct bkey *);
+void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
+ unsigned int i);
+bool __bch_cut_front(const struct bkey *where, struct bkey *k);
+bool __bch_cut_back(const struct bkey *where, struct bkey *k);
static inline bool bch_cut_front(const struct bkey *where, struct bkey *k)
{
@@ -522,18 +538,20 @@ static inline size_t bch_keylist_bytes(struct keylist *l)
return bch_keylist_nkeys(l) * sizeof(uint64_t);
}
-struct bkey *bch_keylist_pop(struct keylist *);
-void bch_keylist_pop_front(struct keylist *);
-int __bch_keylist_realloc(struct keylist *, unsigned);
+struct bkey *bch_keylist_pop(struct keylist *l);
+void bch_keylist_pop_front(struct keylist *l);
+int __bch_keylist_realloc(struct keylist *l, unsigned int u64s);
/* Debug stuff */
#ifdef CONFIG_BCACHE_DEBUG
-int __bch_count_data(struct btree_keys *);
-void __printf(2, 3) __bch_check_keys(struct btree_keys *, const char *, ...);
-void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
-void bch_dump_bucket(struct btree_keys *);
+int __bch_count_data(struct btree_keys *b);
+void __printf(2, 3) __bch_check_keys(struct btree_keys *b,
+ const char *fmt,
+ ...);
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set);
+void bch_dump_bucket(struct btree_keys *b);
#else
@@ -541,7 +559,7 @@ static inline int __bch_count_data(struct btree_keys *b) { return -1; }
static inline void __printf(2, 3)
__bch_check_keys(struct btree_keys *b, const char *fmt, ...) {}
static inline void bch_dump_bucket(struct btree_keys *b) {}
-void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set);
#endif
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index c19f7716df88..e7d4817681f2 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -183,7 +183,7 @@ static void bch_btree_init_next(struct btree *b)
void bkey_put(struct cache_set *c, struct bkey *k)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i))
@@ -287,6 +287,7 @@ err:
static void btree_node_read_endio(struct bio *bio)
{
struct closure *cl = bio->bi_private;
+
closure_put(cl);
}
@@ -435,7 +436,10 @@ static void do_btree_node_write(struct btree *b)
continue_at(cl, btree_node_write_done, NULL);
} else {
- /* No problem for multipage bvec since the bio is just allocated */
+ /*
+ * No problem for multipage bvec since the bio is
+ * just allocated
+ */
b->bio->bi_vcnt = 0;
bch_bio_map(b->bio, i);
@@ -479,7 +483,7 @@ void __bch_btree_node_write(struct btree *b, struct closure *parent)
void bch_btree_node_write(struct btree *b, struct closure *parent)
{
- unsigned nsets = b->keys.nsets;
+ unsigned int nsets = b->keys.nsets;
lockdep_assert_held(&b->lock);
@@ -581,7 +585,7 @@ static void mca_bucket_free(struct btree *b)
list_move(&b->list, &b->c->btree_cache_freeable);
}
-static unsigned btree_order(struct bkey *k)
+static unsigned int btree_order(struct bkey *k)
{
return ilog2(KEY_SIZE(k) / PAGE_SECTORS ?: 1);
}
@@ -589,7 +593,7 @@ static unsigned btree_order(struct bkey *k)
static void mca_data_alloc(struct btree *b, struct bkey *k, gfp_t gfp)
{
if (!bch_btree_keys_alloc(&b->keys,
- max_t(unsigned,
+ max_t(unsigned int,
ilog2(b->c->btree_pages),
btree_order(k)),
gfp)) {
@@ -604,6 +608,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
struct bkey *k, gfp_t gfp)
{
struct btree *b = kzalloc(sizeof(struct btree), gfp);
+
if (!b)
return NULL;
@@ -620,7 +625,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
return b;
}
-static int mca_reap(struct btree *b, unsigned min_order, bool flush)
+static int mca_reap(struct btree *b, unsigned int min_order, bool flush)
{
struct closure cl;
@@ -746,6 +751,7 @@ void bch_btree_cache_free(struct cache_set *c)
{
struct btree *b;
struct closure cl;
+
closure_init_stack(&cl);
if (c->shrink.list.next)
@@ -786,7 +792,7 @@ void bch_btree_cache_free(struct cache_set *c)
int bch_btree_cache_alloc(struct cache_set *c)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < mca_reserve(c); i++)
if (!mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL))
@@ -1124,6 +1130,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b,
struct btree_op *op)
{
struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
+
if (!IS_ERR_OR_NULL(n)) {
mutex_lock(&n->write_lock);
bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
@@ -1136,7 +1143,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b,
static void make_btree_freeing_key(struct btree *b, struct bkey *k)
{
- unsigned i;
+ unsigned int i;
mutex_lock(&b->c->bucket_lock);
@@ -1157,7 +1164,7 @@ static int btree_check_reserve(struct btree *b, struct btree_op *op)
{
struct cache_set *c = b->c;
struct cache *ca;
- unsigned i, reserve = (c->root->level - b->level) * 2 + 1;
+ unsigned int i, reserve = (c->root->level - b->level) * 2 + 1;
mutex_lock(&c->bucket_lock);
@@ -1181,7 +1188,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
struct bkey *k)
{
uint8_t stale = 0;
- unsigned i;
+ unsigned int i;
struct bucket *g;
/*
@@ -1219,7 +1226,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
SET_GC_MARK(g, GC_MARK_RECLAIMABLE);
/* guard against overflow */
- SET_GC_SECTORS_USED(g, min_t(unsigned,
+ SET_GC_SECTORS_USED(g, min_t(unsigned int,
GC_SECTORS_USED(g) + KEY_SIZE(k),
MAX_GC_SECTORS_USED));
@@ -1233,7 +1240,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i) &&
@@ -1259,7 +1266,7 @@ void bch_update_bucket_in_use(struct cache_set *c, struct gc_stat *stats)
static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
{
uint8_t stale = 0;
- unsigned keys = 0, good_keys = 0;
+ unsigned int keys = 0, good_keys = 0;
struct bkey *k;
struct btree_iter iter;
struct bset_tree *t;
@@ -1302,16 +1309,18 @@ static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
struct gc_merge_info {
struct btree *b;
- unsigned keys;
+ unsigned int keys;
};
-static int bch_btree_insert_node(struct btree *, struct btree_op *,
- struct keylist *, atomic_t *, struct bkey *);
+static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
+ struct keylist *insert_keys,
+ atomic_t *journal_ref,
+ struct bkey *replace_key);
static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
struct gc_stat *gc, struct gc_merge_info *r)
{
- unsigned i, nodes = 0, keys = 0, blocks;
+ unsigned int i, nodes = 0, keys = 0, blocks;
struct btree *new_nodes[GC_MERGE_NODES];
struct keylist keylist;
struct closure cl;
@@ -1511,11 +1520,11 @@ static int btree_gc_rewrite_node(struct btree *b, struct btree_op *op,
return -EINTR;
}
-static unsigned btree_gc_count_keys(struct btree *b)
+static unsigned int btree_gc_count_keys(struct btree *b)
{
struct bkey *k;
struct btree_iter iter;
- unsigned ret = 0;
+ unsigned int ret = 0;
for_each_key_filter(&b->keys, k, &iter, bch_ptr_bad)
ret += bkey_u64s(k);
@@ -1678,7 +1687,7 @@ static void btree_gc_start(struct cache_set *c)
{
struct cache *ca;
struct bucket *b;
- unsigned i;
+ unsigned int i;
if (!c->gc_mark_valid)
return;
@@ -1704,7 +1713,7 @@ static void bch_btree_gc_finish(struct cache_set *c)
{
struct bucket *b;
struct cache *ca;
- unsigned i;
+ unsigned int i;
mutex_lock(&c->bucket_lock);
@@ -1722,7 +1731,7 @@ static void bch_btree_gc_finish(struct cache_set *c)
struct bcache_device *d = c->devices[i];
struct cached_dev *dc;
struct keybuf_key *w, *n;
- unsigned j;
+ unsigned int j;
if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
continue;
@@ -1814,7 +1823,7 @@ static void bch_btree_gc(struct cache_set *c)
static bool gc_should_run(struct cache_set *c)
{
struct cache *ca;
- unsigned i;
+ unsigned int i;
for_each_cache(ca, c, i)
if (ca->invalidate_needs_gc)
@@ -1905,7 +1914,7 @@ void bch_initial_gc_finish(struct cache_set *c)
{
struct cache *ca;
struct bucket *b;
- unsigned i;
+ unsigned int i;
bch_btree_gc_finish(c);
@@ -1945,7 +1954,7 @@ void bch_initial_gc_finish(struct cache_set *c)
static bool btree_insert_key(struct btree *b, struct bkey *k,
struct bkey *replace_key)
{
- unsigned status;
+ unsigned int status;
BUG_ON(bkey_cmp(k, &b->key) > 0);
@@ -2044,7 +2053,7 @@ static int btree_split(struct btree *b, struct btree_op *op,
block_bytes(n1->c)) > (btree_blocks(b) * 4) / 5;
if (split) {
- unsigned keys = 0;
+ unsigned int keys = 0;
trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys);
@@ -2222,10 +2231,10 @@ int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
rw_lock(true, b, b->level);
if (b->key.ptr[0] != btree_ptr ||
- b->seq != seq + 1) {
+ b->seq != seq + 1) {
op->lock = b->level;
goto out;
- }
+ }
}
SET_KEY_PTRS(check_key, 1);
@@ -2300,7 +2309,7 @@ int bch_btree_insert(struct cache_set *c, struct keylist *keys,
void bch_btree_set_root(struct btree *b)
{
- unsigned i;
+ unsigned int i;
struct closure cl;
closure_init_stack(&cl);
@@ -2412,7 +2421,7 @@ static inline int keybuf_nonoverlapping_cmp(struct keybuf_key *l,
struct refill {
struct btree_op op;
- unsigned nr_found;
+ unsigned int nr_found;
struct keybuf *buf;
struct bkey *end;
keybuf_pred_fn *pred;
@@ -2488,6 +2497,7 @@ void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
if (!RB_EMPTY_ROOT(&buf->keys)) {
struct keybuf_key *w;
+
w = RB_FIRST(&buf->keys, struct keybuf_key, node);
buf->start = START_KEY(&w->key);
@@ -2519,6 +2529,7 @@ bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
{
bool ret = false;
struct keybuf_key *p, *w, s;
+
s.key = *start;
if (bkey_cmp(end, &buf->start) <= 0 ||
@@ -2545,6 +2556,7 @@ bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
struct keybuf_key *bch_keybuf_next(struct keybuf *buf)
{
struct keybuf_key *w;
+
spin_lock(&buf->lock);
w = RB_FIRST(&buf->keys, struct keybuf_key, node);
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 68e9d926134d..a68d6c55783b 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -184,7 +184,7 @@ static inline struct bset *btree_bset_last(struct btree *b)
return bset_tree_last(&b->keys)->data;
}
-static inline unsigned bset_block_offset(struct btree *b, struct bset *i)
+static inline unsigned int bset_block_offset(struct btree *b, struct bset *i)
{
return bset_sector_offset(&b->keys, i) >> b->c->block_bits;
}
@@ -213,7 +213,7 @@ struct btree_op {
/* Btree level at which we start taking write locks */
short lock;
- unsigned insert_collision:1;
+ unsigned int insert_collision:1;
};
static inline void bch_btree_op_init(struct btree_op *op, int write_lock_level)
@@ -238,26 +238,28 @@ static inline void rw_unlock(bool w, struct btree *b)
(w ? up_write : up_read)(&b->lock);
}
-void bch_btree_node_read_done(struct btree *);
-void __bch_btree_node_write(struct btree *, struct closure *);
-void bch_btree_node_write(struct btree *, struct closure *);
-
-void bch_btree_set_root(struct btree *);
-struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *,
- int, bool, struct btree *);
-struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *,
- struct bkey *, int, bool, struct btree *);
-
-int bch_btree_insert_check_key(struct btree *, struct btree_op *,
- struct bkey *);
-int bch_btree_insert(struct cache_set *, struct keylist *,
- atomic_t *, struct bkey *);
-
-int bch_gc_thread_start(struct cache_set *);
-void bch_initial_gc_finish(struct cache_set *);
-void bch_moving_gc(struct cache_set *);
-int bch_btree_check(struct cache_set *);
-void bch_initial_mark_key(struct cache_set *, int, struct bkey *);
+void bch_btree_node_read_done(struct btree *b);
+void __bch_btree_node_write(struct btree *b, struct closure *parent);
+void bch_btree_node_write(struct btree *b, struct closure *parent);
+
+void bch_btree_set_root(struct btree *b);
+struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
+ int level, bool wait,
+ struct btree *parent);
+struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
+ struct bkey *k, int level, bool write,
+ struct btree *parent);
+
+int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
+ struct bkey *check_key);
+int bch_btree_insert(struct cache_set *c, struct keylist *keys,
+ atomic_t *journal_ref, struct bkey *replace_key);
+
+int bch_gc_thread_start(struct cache_set *c);
+void bch_initial_gc_finish(struct cache_set *c);
+void bch_moving_gc(struct cache_set *c);
+int bch_btree_check(struct cache_set *c);
+void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k);
static inline void wake_up_gc(struct cache_set *c)
{
@@ -272,9 +274,9 @@ static inline void wake_up_gc(struct cache_set *c)
#define MAP_END_KEY 1
-typedef int (btree_map_nodes_fn)(struct btree_op *, struct btree *);
-int __bch_btree_map_nodes(struct btree_op *, struct cache_set *,
- struct bkey *, btree_map_nodes_fn *, int);
+typedef int (btree_map_nodes_fn)(struct btree_op *b_op, struct btree *b);
+int __bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
+ struct bkey *from, btree_map_nodes_fn *fn, int flags);
static inline int bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
struct bkey *from, btree_map_nodes_fn *fn)
@@ -290,21 +292,23 @@ static inline int bch_btree_map_leaf_nodes(struct btree_op *op,
return __bch_btree_map_nodes(op, c, from, fn, MAP_LEAF_NODES);
}
-typedef int (btree_map_keys_fn)(struct btree_op *, struct btree *,
- struct bkey *);
-int bch_btree_map_keys(struct btree_op *, struct cache_set *,
- struct bkey *, btree_map_keys_fn *, int);
-
-typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);
-
-void bch_keybuf_init(struct keybuf *);
-void bch_refill_keybuf(struct cache_set *, struct keybuf *,
- struct bkey *, keybuf_pred_fn *);
-bool bch_keybuf_check_overlapping(struct keybuf *, struct bkey *,
- struct bkey *);
-void bch_keybuf_del(struct keybuf *, struct keybuf_key *);
-struct keybuf_key *bch_keybuf_next(struct keybuf *);
-struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *, struct keybuf *,
- struct bkey *, keybuf_pred_fn *);
+typedef int (btree_map_keys_fn)(struct btree_op *op, struct btree *b,
+ struct bkey *k);
+int bch_btree_map_keys(struct btree_op *op, struct cache_set *c,
+ struct bkey *from, btree_map_keys_fn *fn, int flags);
+
+typedef bool (keybuf_pred_fn)(struct keybuf *buf, struct bkey *k);
+
+void bch_keybuf_init(struct keybuf *buf);
+void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
+ struct bkey *end, keybuf_pred_fn *pred);
+bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
+ struct bkey *end);
+void bch_keybuf_del(struct keybuf *buf, struct keybuf_key *w);
+struct keybuf_key *bch_keybuf_next(struct keybuf *buf);
+struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
+ struct keybuf *buf,
+ struct bkey *end,
+ keybuf_pred_fn *pred);
void bch_update_bucket_in_use(struct cache_set *c, struct gc_stat *stats);
#endif
diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
index 618253683d40..73f5319295bc 100644
--- a/drivers/md/bcache/closure.c
+++ b/drivers/md/bcache/closure.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Asynchronous refcounty things
*
@@ -162,12 +163,13 @@ static struct dentry *closure_debug;
static int debug_seq_show(struct seq_file *f, void *data)
{
struct closure *cl;
+
spin_lock_irq(&closure_list_lock);
list_for_each_entry(cl, &closure_list, all) {
int r = atomic_read(&cl->remaining);
- seq_printf(f, "%p: %pF -> %pf p %p r %i ",
+ seq_printf(f, "%p: %pS -> %pS p %p r %i ",
cl, (void *) cl->ip, cl->fn, cl->parent,
r & CLOSURE_REMAINING_MASK);
@@ -177,7 +179,7 @@ static int debug_seq_show(struct seq_file *f, void *data)
r & CLOSURE_RUNNING ? "R" : "");
if (r & CLOSURE_WAITING)
- seq_printf(f, " W %pF\n",
+ seq_printf(f, " W %pS\n",
(void *) cl->waiting_on);
seq_printf(f, "\n");
diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h
index 7c2c5bc7c88b..eca0d496b686 100644
--- a/drivers/md/bcache/closure.h
+++ b/drivers/md/bcache/closure.h
@@ -159,7 +159,7 @@ struct closure {
#define CLOSURE_MAGIC_DEAD 0xc054dead
#define CLOSURE_MAGIC_ALIVE 0xc054a11e
- unsigned magic;
+ unsigned int magic;
struct list_head all;
unsigned long ip;
unsigned long waiting_on;
@@ -289,10 +289,12 @@ static inline void closure_init_stack(struct closure *cl)
}
/**
- * closure_wake_up - wake up all closures on a wait list.
+ * closure_wake_up - wake up all closures on a wait list,
+ * with memory barrier
*/
static inline void closure_wake_up(struct closure_waitlist *list)
{
+ /* Memory barrier for the wait list */
smp_mb();
__closure_wake_up(list);
}
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 12034c07257b..06da66b2488a 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -67,34 +67,35 @@ void bch_btree_verify(struct btree *b)
if (inmemory->keys != sorted->keys ||
memcmp(inmemory->start,
sorted->start,
- (void *) bset_bkey_last(inmemory) - (void *) inmemory->start)) {
+ (void *) bset_bkey_last(inmemory) -
+ (void *) inmemory->start)) {
struct bset *i;
- unsigned j;
+ unsigned int j;
console_lock();
- printk(KERN_ERR "*** in memory:\n");
+ pr_err("*** in memory:\n");
bch_dump_bset(&b->keys, inmemory, 0);
- printk(KERN_ERR "*** read back in:\n");
+ pr_err("*** read back in:\n");
bch_dump_bset(&v->keys, sorted, 0);
for_each_written_bset(b, ondisk, i) {
- unsigned block = ((void *) i - (void *) ondisk) /
+ unsigned int block = ((void *) i - (void *) ondisk) /
block_bytes(b->c);
- printk(KERN_ERR "*** on disk block %u:\n", block);
+ pr_err("*** on disk block %u:\n", block);
bch_dump_bset(&b->keys, i, block);
}
- printk(KERN_ERR "*** block %zu not written\n",
+ pr_err("*** block %zu not written\n",
((void *) i - (void *) ondisk) / block_bytes(b->c));
for (j = 0; j < inmemory->keys; j++)
if (inmemory->d[j] != sorted->d[j])
break;
- printk(KERN_ERR "b->written %u\n", b->written);
+ pr_err("b->written %u\n", b->written);
console_unlock();
panic("verify failed at %u\n", j);
@@ -176,9 +177,9 @@ static ssize_t bch_dump_read(struct file *file, char __user *buf,
while (size) {
struct keybuf_key *w;
- unsigned bytes = min(i->bytes, size);
-
+ unsigned int bytes = min(i->bytes, size);
int err = copy_to_user(buf, i->buf, bytes);
+
if (err)
return err;
@@ -237,8 +238,8 @@ void bch_debug_init_cache_set(struct cache_set *c)
{
if (!IS_ERR_OR_NULL(bcache_debug)) {
char name[50];
- snprintf(name, 50, "bcache-%pU", c->sb.set_uuid);
+ snprintf(name, 50, "bcache-%pU", c->sb.set_uuid);
c->debug = debugfs_create_file(name, 0400, bcache_debug, c,
&cache_set_debug_ops);
}
diff --git a/drivers/md/bcache/debug.h b/drivers/md/bcache/debug.h
index acc48d3fa274..fb3d4dff4b26 100644
--- a/drivers/md/bcache/debug.h
+++ b/drivers/md/bcache/debug.h
@@ -8,8 +8,8 @@ struct cache_set;
#ifdef CONFIG_BCACHE_DEBUG
-void bch_btree_verify(struct btree *);
-void bch_data_verify(struct cached_dev *, struct bio *);
+void bch_btree_verify(struct btree *b);
+void bch_data_verify(struct cached_dev *dc, struct bio *bio);
#define expensive_debug_checks(c) ((c)->expensive_debug_checks)
#define key_merging_disabled(c) ((c)->key_merging_disabled)
@@ -27,7 +27,7 @@ static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {}
#endif
#ifdef CONFIG_DEBUG_FS
-void bch_debug_init_cache_set(struct cache_set *);
+void bch_debug_init_cache_set(struct cache_set *c);
#else
static inline void bch_debug_init_cache_set(struct cache_set *c) {}
#endif
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index 1d096742eb41..c809724e6571 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -46,7 +46,7 @@ static bool bch_key_sort_cmp(struct btree_iter_set l,
static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i)) {
@@ -67,7 +67,7 @@ static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
static const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
{
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i)) {
@@ -96,7 +96,7 @@ static const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
void bch_extent_to_text(char *buf, size_t size, const struct bkey *k)
{
- unsigned i = 0;
+ unsigned int i = 0;
char *out = buf, *end = buf + size;
#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
@@ -126,22 +126,22 @@ void bch_extent_to_text(char *buf, size_t size, const struct bkey *k)
static void bch_bkey_dump(struct btree_keys *keys, const struct bkey *k)
{
struct btree *b = container_of(keys, struct btree, keys);
- unsigned j;
+ unsigned int j;
char buf[80];
bch_extent_to_text(buf, sizeof(buf), k);
- printk(" %s", buf);
+ pr_err(" %s", buf);
for (j = 0; j < KEY_PTRS(k); j++) {
size_t n = PTR_BUCKET_NR(b->c, k, j);
- printk(" bucket %zu", n);
+ pr_err(" bucket %zu", n);
if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets)
- printk(" prio %i",
+ pr_err(" prio %i",
PTR_BUCKET(b->c, k, j)->prio);
}
- printk(" %s\n", bch_ptr_status(b->c, k));
+ pr_err(" %s\n", bch_ptr_status(b->c, k));
}
/* Btree ptrs */
@@ -166,12 +166,13 @@ bad:
static bool bch_btree_ptr_invalid(struct btree_keys *bk, const struct bkey *k)
{
struct btree *b = container_of(bk, struct btree, keys);
+
return __bch_btree_ptr_invalid(b->c, k);
}
static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k)
{
- unsigned i;
+ unsigned int i;
char buf[80];
struct bucket *g;
@@ -204,7 +205,7 @@ err:
static bool bch_btree_ptr_bad(struct btree_keys *bk, const struct bkey *k)
{
struct btree *b = container_of(bk, struct btree, keys);
- unsigned i;
+ unsigned int i;
if (!bkey_cmp(k, &ZERO_KEY) ||
!KEY_PTRS(k) ||
@@ -327,13 +328,14 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
struct cache_set *c = container_of(b, struct btree, keys)->c;
uint64_t old_offset;
- unsigned old_size, sectors_found = 0;
+ unsigned int old_size, sectors_found = 0;
BUG_ON(!KEY_OFFSET(insert));
BUG_ON(!KEY_SIZE(insert));
while (1) {
struct bkey *k = bch_btree_iter_next(iter);
+
if (!k)
break;
@@ -363,7 +365,7 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
* k might have been split since we inserted/found the
* key we're replacing
*/
- unsigned i;
+ unsigned int i;
uint64_t offset = KEY_START(k) -
KEY_START(replace_key);
@@ -498,11 +500,12 @@ bad:
static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
{
struct btree *b = container_of(bk, struct btree, keys);
+
return __bch_extent_invalid(b->c, k);
}
static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
- unsigned ptr)
+ unsigned int ptr)
{
struct bucket *g = PTR_BUCKET(b->c, k, ptr);
char buf[80];
@@ -534,7 +537,7 @@ err:
static bool bch_extent_bad(struct btree_keys *bk, const struct bkey *k)
{
struct btree *b = container_of(bk, struct btree, keys);
- unsigned i, stale;
+ unsigned int i, stale;
if (!KEY_PTRS(k) ||
bch_extent_invalid(bk, k))
@@ -574,10 +577,12 @@ static uint64_t merge_chksums(struct bkey *l, struct bkey *r)
~((uint64_t)1 << 63);
}
-static bool bch_extent_merge(struct btree_keys *bk, struct bkey *l, struct bkey *r)
+static bool bch_extent_merge(struct btree_keys *bk,
+ struct bkey *l,
+ struct bkey *r)
{
struct btree *b = container_of(bk, struct btree, keys);
- unsigned i;
+ unsigned int i;
if (key_merging_disabled(b->c))
return false;
diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h
index 0cd3575afa1d..4d667e05bb73 100644
--- a/drivers/md/bcache/extents.h
+++ b/drivers/md/bcache/extents.h
@@ -8,8 +8,8 @@ extern const struct btree_keys_ops bch_extent_keys_ops;
struct bkey;
struct cache_set;
-void bch_extent_to_text(char *, size_t, const struct bkey *);
-bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
-bool __bch_extent_invalid(struct cache_set *, const struct bkey *);
+void bch_extent_to_text(char *buf, size_t size, const struct bkey *k);
+bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k);
+bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k);
#endif /* _BCACHE_EXTENTS_H */
diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c
index 9612873afee2..c25097968319 100644
--- a/drivers/md/bcache/io.c
+++ b/drivers/md/bcache/io.c
@@ -17,6 +17,7 @@
void bch_bbio_free(struct bio *bio, struct cache_set *c)
{
struct bbio *b = container_of(bio, struct bbio, bio);
+
mempool_free(b, &c->bio_meta);
}
@@ -42,9 +43,10 @@ void __bch_submit_bbio(struct bio *bio, struct cache_set *c)
}
void bch_submit_bbio(struct bio *bio, struct cache_set *c,
- struct bkey *k, unsigned ptr)
+ struct bkey *k, unsigned int ptr)
{
struct bbio *b = container_of(bio, struct bbio, bio);
+
bch_bkey_copy_single_ptr(&b->key, k, ptr);
__bch_submit_bbio(bio, c);
}
@@ -52,7 +54,7 @@ void bch_submit_bbio(struct bio *bio, struct cache_set *c,
/* IO errors */
void bch_count_backing_io_errors(struct cached_dev *dc, struct bio *bio)
{
- unsigned errors;
+ unsigned int errors;
WARN_ONCE(!dc, "NULL pointer of struct cached_dev");
@@ -75,16 +77,16 @@ void bch_count_io_errors(struct cache *ca,
*/
if (ca->set->error_decay) {
- unsigned count = atomic_inc_return(&ca->io_count);
+ unsigned int count = atomic_inc_return(&ca->io_count);
while (count > ca->set->error_decay) {
- unsigned errors;
- unsigned old = count;
- unsigned new = count - ca->set->error_decay;
+ unsigned int errors;
+ unsigned int old = count;
+ unsigned int new = count - ca->set->error_decay;
/*
* First we subtract refresh from count; each time we
- * succesfully do so, we rescale the errors once:
+ * successfully do so, we rescale the errors once:
*/
count = atomic_cmpxchg(&ca->io_count, old, new);
@@ -104,7 +106,7 @@ void bch_count_io_errors(struct cache *ca,
}
if (error) {
- unsigned errors = atomic_add_return(1 << IO_ERROR_SHIFT,
+ unsigned int errors = atomic_add_return(1 << IO_ERROR_SHIFT,
&ca->io_errors);
errors >>= IO_ERROR_SHIFT;
@@ -126,18 +128,18 @@ void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
struct cache *ca = PTR_CACHE(c, &b->key, 0);
int is_read = (bio_data_dir(bio) == READ ? 1 : 0);
- unsigned threshold = op_is_write(bio_op(bio))
+ unsigned int threshold = op_is_write(bio_op(bio))
? c->congested_write_threshold_us
: c->congested_read_threshold_us;
if (threshold) {
- unsigned t = local_clock_us();
-
+ unsigned int t = local_clock_us();
int us = t - b->submit_time_us;
int congested = atomic_read(&c->congested);
if (us > (int) threshold) {
int ms = us / 1024;
+
c->congested_last_us = t;
ms = min(ms, CONGESTED_MAX + congested);
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 10748c626a1d..6116bbf870d8 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -28,11 +28,12 @@
static void journal_read_endio(struct bio *bio)
{
struct closure *cl = bio->bi_private;
+
closure_put(cl);
}
static int journal_read_bucket(struct cache *ca, struct list_head *list,
- unsigned bucket_index)
+ unsigned int bucket_index)
{
struct journal_device *ja = &ca->journal;
struct bio *bio = &ja->bio;
@@ -40,7 +41,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
struct journal_replay *i;
struct jset *j, *data = ca->set->journal.w[0].data;
struct closure cl;
- unsigned len, left, offset = 0;
+ unsigned int len, left, offset = 0;
int ret = 0;
sector_t bucket = bucket_to_sector(ca->set, ca->sb.d[bucket_index]);
@@ -50,7 +51,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
while (offset < ca->sb.bucket_size) {
reread: left = ca->sb.bucket_size - offset;
- len = min_t(unsigned, left, PAGE_SECTORS << JSET_BITS);
+ len = min_t(unsigned int, left, PAGE_SECTORS << JSET_BITS);
bio_reset(bio);
bio->bi_iter.bi_sector = bucket + offset;
@@ -154,12 +155,12 @@ int bch_journal_read(struct cache_set *c, struct list_head *list)
})
struct cache *ca;
- unsigned iter;
+ unsigned int iter;
for_each_cache(ca, c, iter) {
struct journal_device *ja = &ca->journal;
DECLARE_BITMAP(bitmap, SB_JOURNAL_BUCKETS);
- unsigned i, l, r, m;
+ unsigned int i, l, r, m;
uint64_t seq;
bitmap_zero(bitmap, SB_JOURNAL_BUCKETS);
@@ -192,7 +193,8 @@ int bch_journal_read(struct cache_set *c, struct list_head *list)
for (l = find_first_zero_bit(bitmap, ca->sb.njournal_buckets);
l < ca->sb.njournal_buckets;
- l = find_next_zero_bit(bitmap, ca->sb.njournal_buckets, l + 1))
+ l = find_next_zero_bit(bitmap, ca->sb.njournal_buckets,
+ l + 1))
if (read_bucket(l))
goto bsearch;
@@ -304,7 +306,7 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
k < bset_bkey_last(&i->j);
k = bkey_next(k))
if (!__bch_extent_invalid(c, k)) {
- unsigned j;
+ unsigned int j;
for (j = 0; j < KEY_PTRS(k); j++)
if (ptr_available(c, k, j))
@@ -492,7 +494,7 @@ static void journal_reclaim(struct cache_set *c)
struct bkey *k = &c->journal.key;
struct cache *ca;
uint64_t last_seq;
- unsigned iter, n = 0;
+ unsigned int iter, n = 0;
atomic_t p __maybe_unused;
atomic_long_inc(&c->reclaim);
@@ -526,7 +528,7 @@ static void journal_reclaim(struct cache_set *c)
for_each_cache(ca, c, iter) {
struct journal_device *ja = &ca->journal;
- unsigned next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
+ unsigned int next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
/* No space available on this device */
if (next == ja->discard_idx)
@@ -580,7 +582,7 @@ static void journal_write_endio(struct bio *bio)
closure_put(&w->c->journal.io);
}
-static void journal_write(struct closure *);
+static void journal_write(struct closure *cl);
static void journal_write_done(struct closure *cl)
{
@@ -609,11 +611,12 @@ static void journal_write_unlocked(struct closure *cl)
struct cache *ca;
struct journal_write *w = c->journal.cur;
struct bkey *k = &c->journal.key;
- unsigned i, sectors = set_blocks(w->data, block_bytes(c)) *
+ unsigned int i, sectors = set_blocks(w->data, block_bytes(c)) *
c->sb.block_size;
struct bio *bio;
struct bio_list list;
+
bio_list_init(&list);
if (!w->need_write) {
@@ -705,7 +708,7 @@ static void journal_try_write(struct cache_set *c)
}
static struct journal_write *journal_wait_for_write(struct cache_set *c,
- unsigned nkeys)
+ unsigned int nkeys)
__acquires(&c->journal.lock)
{
size_t sectors;
diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h
index b5788199188f..66f0facff84b 100644
--- a/drivers/md/bcache/journal.h
+++ b/drivers/md/bcache/journal.h
@@ -110,7 +110,7 @@ struct journal {
struct delayed_work work;
/* Number of blocks free in the bucket(s) we're currently writing to */
- unsigned blocks_free;
+ unsigned int blocks_free;
uint64_t seq;
DECLARE_FIFO(atomic_t, pin);
@@ -131,13 +131,13 @@ struct journal_device {
uint64_t seq[SB_JOURNAL_BUCKETS];
/* Journal bucket we're currently writing to */
- unsigned cur_idx;
+ unsigned int cur_idx;
/* Last journal bucket that still contains an open journal entry */
- unsigned last_idx;
+ unsigned int last_idx;
/* Next journal bucket to be discarded */
- unsigned discard_idx;
+ unsigned int discard_idx;
#define DISCARD_READY 0
#define DISCARD_IN_FLIGHT 1
@@ -167,14 +167,16 @@ struct cache_set;
struct btree_op;
struct keylist;
-atomic_t *bch_journal(struct cache_set *, struct keylist *, struct closure *);
-void bch_journal_next(struct journal *);
-void bch_journal_mark(struct cache_set *, struct list_head *);
-void bch_journal_meta(struct cache_set *, struct closure *);
-int bch_journal_read(struct cache_set *, struct list_head *);
-int bch_journal_replay(struct cache_set *, struct list_head *);
-
-void bch_journal_free(struct cache_set *);
-int bch_journal_alloc(struct cache_set *);
+atomic_t *bch_journal(struct cache_set *c,
+ struct keylist *keys,
+ struct closure *parent);
+void bch_journal_next(struct journal *j);
+void bch_journal_mark(struct cache_set *c, struct list_head *list);
+void bch_journal_meta(struct cache_set *c, struct closure *cl);
+int bch_journal_read(struct cache_set *c, struct list_head *list);
+int bch_journal_replay(struct cache_set *c, struct list_head *list);
+
+void bch_journal_free(struct cache_set *c);
+int bch_journal_alloc(struct cache_set *c);
#endif /* _BCACHE_JOURNAL_H */
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index a24c3a95b2c0..7891fb512736 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -23,7 +23,7 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
{
struct cache_set *c = container_of(buf, struct cache_set,
moving_gc_keys);
- unsigned i;
+ unsigned int i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i) &&
@@ -38,6 +38,7 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
static void moving_io_destructor(struct closure *cl)
{
struct moving_io *io = container_of(cl, struct moving_io, cl);
+
kfree(io);
}
@@ -186,9 +187,10 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
return GC_SECTORS_USED(l) < GC_SECTORS_USED(r);
}
-static unsigned bucket_heap_top(struct cache *ca)
+static unsigned int bucket_heap_top(struct cache *ca)
{
struct bucket *b;
+
return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
}
@@ -196,7 +198,7 @@ void bch_moving_gc(struct cache_set *c)
{
struct cache *ca;
struct bucket *b;
- unsigned i;
+ unsigned int i;
if (!c->copy_gc_enabled)
return;
@@ -204,9 +206,9 @@ void bch_moving_gc(struct cache_set *c)
mutex_lock(&c->bucket_lock);
for_each_cache(ca, c, i) {
- unsigned sectors_to_move = 0;
- unsigned reserve_sectors = ca->sb.bucket_size *
- fifo_used(&ca->free[RESERVE_MOVINGGC]);
+ unsigned int sectors_to_move = 0;
+ unsigned int reserve_sectors = ca->sb.bucket_size *
+ fifo_used(&ca->free[RESERVE_MOVINGGC]);
ca->heap.used = 0;
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 7dbe8b6316a0..51be355a3309 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -25,9 +25,9 @@
struct kmem_cache *bch_search_cache;
-static void bch_data_insert_start(struct closure *);
+static void bch_data_insert_start(struct closure *cl);
-static unsigned cache_mode(struct cached_dev *dc)
+static unsigned int cache_mode(struct cached_dev *dc)
{
return BDEV_CACHE_MODE(&dc->sb);
}
@@ -45,6 +45,7 @@ static void bio_csum(struct bio *bio, struct bkey *k)
bio_for_each_segment(bv, bio, iter) {
void *d = kmap(bv.bv_page) + bv.bv_offset;
+
csum = bch_crc64_update(csum, d, bv.bv_len);
kunmap(bv.bv_page);
}
@@ -98,7 +99,7 @@ static void bch_data_insert_keys(struct closure *cl)
closure_return(cl);
}
-static int bch_keylist_realloc(struct keylist *l, unsigned u64s,
+static int bch_keylist_realloc(struct keylist *l, unsigned int u64s,
struct cache_set *c)
{
size_t oldsize = bch_keylist_nkeys(l);
@@ -125,7 +126,7 @@ static void bch_data_invalidate(struct closure *cl)
bio_sectors(bio), (uint64_t) bio->bi_iter.bi_sector);
while (bio_sectors(bio)) {
- unsigned sectors = min(bio_sectors(bio),
+ unsigned int sectors = min(bio_sectors(bio),
1U << (KEY_SIZE_BITS - 1));
if (bch_keylist_realloc(&op->insert_keys, 2, op->c))
@@ -135,7 +136,9 @@ static void bch_data_invalidate(struct closure *cl)
bio->bi_iter.bi_size -= sectors << 9;
bch_keylist_add(&op->insert_keys,
- &KEY(op->inode, bio->bi_iter.bi_sector, sectors));
+ &KEY(op->inode,
+ bio->bi_iter.bi_sector,
+ sectors));
}
op->insert_data_done = true;
@@ -151,7 +154,7 @@ static void bch_data_insert_error(struct closure *cl)
/*
* Our data write just errored, which means we've got a bunch of keys to
- * insert that point to data that wasn't succesfully written.
+ * insert that point to data that wasn't successfully written.
*
* We don't have to insert those keys but we still have to invalidate
* that region of the cache - so, if we just strip off all the pointers
@@ -211,7 +214,7 @@ static void bch_data_insert_start(struct closure *cl)
bio->bi_opf &= ~(REQ_PREFLUSH|REQ_FUA);
do {
- unsigned i;
+ unsigned int i;
struct bkey *k;
struct bio_set *split = &op->c->bio_split;
@@ -328,7 +331,7 @@ void bch_data_insert(struct closure *cl)
/* Congested? */
-unsigned bch_get_congested(struct cache_set *c)
+unsigned int bch_get_congested(struct cache_set *c)
{
int i;
long rand;
@@ -372,8 +375,8 @@ static struct hlist_head *iohash(struct cached_dev *dc, uint64_t k)
static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
{
struct cache_set *c = dc->disk.c;
- unsigned mode = cache_mode(dc);
- unsigned sectors, congested = bch_get_congested(c);
+ unsigned int mode = cache_mode(dc);
+ unsigned int sectors, congested = bch_get_congested(c);
struct task_struct *task = current;
struct io *i;
@@ -469,11 +472,11 @@ struct search {
struct bio *cache_miss;
struct bcache_device *d;
- unsigned insert_bio_sectors;
- unsigned recoverable:1;
- unsigned write:1;
- unsigned read_dirty_data:1;
- unsigned cache_missed:1;
+ unsigned int insert_bio_sectors;
+ unsigned int recoverable:1;
+ unsigned int write:1;
+ unsigned int read_dirty_data:1;
+ unsigned int cache_missed:1;
unsigned long start_time;
@@ -514,20 +517,20 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
struct search *s = container_of(op, struct search, op);
struct bio *n, *bio = &s->bio.bio;
struct bkey *bio_key;
- unsigned ptr;
+ unsigned int ptr;
if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0)) <= 0)
return MAP_CONTINUE;
if (KEY_INODE(k) != s->iop.inode ||
KEY_START(k) > bio->bi_iter.bi_sector) {
- unsigned bio_sectors = bio_sectors(bio);
- unsigned sectors = KEY_INODE(k) == s->iop.inode
+ unsigned int bio_sectors = bio_sectors(bio);
+ unsigned int sectors = KEY_INODE(k) == s->iop.inode
? min_t(uint64_t, INT_MAX,
KEY_START(k) - bio->bi_iter.bi_sector)
: INT_MAX;
-
int ret = s->d->cache_miss(b, s, bio, sectors);
+
if (ret != MAP_CONTINUE)
return ret;
@@ -623,6 +626,7 @@ static void request_endio(struct bio *bio)
if (bio->bi_status) {
struct search *s = container_of(cl, struct search, cl);
+
s->iop.status = bio->bi_status;
/* Only cache read errors are recoverable */
s->recoverable = false;
@@ -813,7 +817,8 @@ static void cached_dev_read_done(struct closure *cl)
if (s->iop.bio) {
bio_reset(s->iop.bio);
- s->iop.bio->bi_iter.bi_sector = s->cache_miss->bi_iter.bi_sector;
+ s->iop.bio->bi_iter.bi_sector =
+ s->cache_miss->bi_iter.bi_sector;
bio_copy_dev(s->iop.bio, s->cache_miss);
s->iop.bio->bi_iter.bi_size = s->insert_bio_sectors << 9;
bch_bio_map(s->iop.bio, NULL);
@@ -856,10 +861,10 @@ static void cached_dev_read_done_bh(struct closure *cl)
}
static int cached_dev_cache_miss(struct btree *b, struct search *s,
- struct bio *bio, unsigned sectors)
+ struct bio *bio, unsigned int sectors)
{
int ret = MAP_CONTINUE;
- unsigned reada = 0;
+ unsigned int reada = 0;
struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
struct bio *miss, *cache_bio;
@@ -1212,6 +1217,7 @@ static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
return __blkdev_driver_ioctl(dc->bdev, mode, cmd, arg);
}
@@ -1226,7 +1232,7 @@ static int cached_dev_congested(void *data, int bits)
return 1;
if (cached_dev_get(dc)) {
- unsigned i;
+ unsigned int i;
struct cache *ca;
for_each_cache(ca, d->c, i) {
@@ -1253,9 +1259,9 @@ void bch_cached_dev_request_init(struct cached_dev *dc)
/* Flash backed devices */
static int flash_dev_cache_miss(struct btree *b, struct search *s,
- struct bio *bio, unsigned sectors)
+ struct bio *bio, unsigned int sectors)
{
- unsigned bytes = min(sectors, bio_sectors(bio)) << 9;
+ unsigned int bytes = min(sectors, bio_sectors(bio)) << 9;
swap(bio->bi_iter.bi_size, bytes);
zero_fill_bio(bio);
@@ -1338,7 +1344,7 @@ static int flash_dev_congested(void *data, int bits)
struct bcache_device *d = data;
struct request_queue *q;
struct cache *ca;
- unsigned i;
+ unsigned int i;
int ret = 0;
for_each_cache(ca, d->c, i) {
@@ -1361,8 +1367,7 @@ void bch_flash_dev_request_init(struct bcache_device *d)
void bch_request_exit(void)
{
- if (bch_search_cache)
- kmem_cache_destroy(bch_search_cache);
+ kmem_cache_destroy(bch_search_cache);
}
int __init bch_request_init(void)
diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
index dea0886b81c1..aa055cfeb099 100644
--- a/drivers/md/bcache/request.h
+++ b/drivers/md/bcache/request.h
@@ -8,7 +8,7 @@ struct data_insert_op {
struct bio *bio;
struct workqueue_struct *wq;
- unsigned inode;
+ unsigned int inode;
uint16_t write_point;
uint16_t write_prio;
blk_status_t status;
@@ -17,15 +17,15 @@ struct data_insert_op {
uint16_t flags;
struct {
- unsigned bypass:1;
- unsigned writeback:1;
- unsigned flush_journal:1;
- unsigned csum:1;
+ unsigned int bypass:1;
+ unsigned int writeback:1;
+ unsigned int flush_journal:1;
+ unsigned int csum:1;
- unsigned replace:1;
- unsigned replace_collision:1;
+ unsigned int replace:1;
+ unsigned int replace_collision:1;
- unsigned insert_data_done:1;
+ unsigned int insert_data_done:1;
};
};
@@ -33,7 +33,7 @@ struct data_insert_op {
BKEY_PADDED(replace_key);
};
-unsigned bch_get_congested(struct cache_set *);
+unsigned int bch_get_congested(struct cache_set *c);
void bch_data_insert(struct closure *cl);
void bch_cached_dev_request_init(struct cached_dev *dc);
diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c
index be119326297b..894410f3f829 100644
--- a/drivers/md/bcache/stats.c
+++ b/drivers/md/bcache/stats.c
@@ -33,11 +33,11 @@
* stored left shifted by 16, and scaled back in the sysfs show() function.
*/
-static const unsigned DAY_RESCALE = 288;
-static const unsigned HOUR_RESCALE = 12;
-static const unsigned FIVE_MINUTE_RESCALE = 1;
-static const unsigned accounting_delay = (HZ * 300) / 22;
-static const unsigned accounting_weight = 32;
+static const unsigned int DAY_RESCALE = 288;
+static const unsigned int HOUR_RESCALE = 12;
+static const unsigned int FIVE_MINUTE_RESCALE = 1;
+static const unsigned int accounting_delay = (HZ * 300) / 22;
+static const unsigned int accounting_weight = 32;
/* sysfs reading/writing */
@@ -152,7 +152,7 @@ static void scale_accounting(struct timer_list *t)
struct cache_accounting *acc = from_timer(acc, t, timer);
#define move_stat(name) do { \
- unsigned t = atomic_xchg(&acc->collector.name, 0); \
+ unsigned int t = atomic_xchg(&acc->collector.name, 0); \
t <<= 16; \
acc->five_minute.name += t; \
acc->hour.name += t; \
@@ -200,6 +200,7 @@ void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
bool hit, bool bypass)
{
struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
mark_cache_stats(&dc->accounting.collector, hit, bypass);
mark_cache_stats(&c->accounting.collector, hit, bypass);
}
@@ -207,6 +208,7 @@ void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d)
{
struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
atomic_inc(&dc->accounting.collector.cache_readaheads);
atomic_inc(&c->accounting.collector.cache_readaheads);
}
@@ -214,6 +216,7 @@ void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d)
void bch_mark_cache_miss_collision(struct cache_set *c, struct bcache_device *d)
{
struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
atomic_inc(&dc->accounting.collector.cache_miss_collisions);
atomic_inc(&c->accounting.collector.cache_miss_collisions);
}
diff --git a/drivers/md/bcache/stats.h b/drivers/md/bcache/stats.h
index 0b70f9de0c03..abfaabf7e7fc 100644
--- a/drivers/md/bcache/stats.h
+++ b/drivers/md/bcache/stats.h
@@ -23,7 +23,7 @@ struct cache_stats {
unsigned long cache_miss_collisions;
unsigned long sectors_bypassed;
- unsigned rescale;
+ unsigned int rescale;
};
struct cache_accounting {
@@ -53,10 +53,13 @@ void bch_cache_accounting_clear(struct cache_accounting *acc);
void bch_cache_accounting_destroy(struct cache_accounting *acc);
-void bch_mark_cache_accounting(struct cache_set *, struct bcache_device *,
- bool, bool);
-void bch_mark_cache_readahead(struct cache_set *, struct bcache_device *);
-void bch_mark_cache_miss_collision(struct cache_set *, struct bcache_device *);
-void bch_mark_sectors_bypassed(struct cache_set *, struct cached_dev *, int);
+void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
+ bool hit, bool bypass);
+void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d);
+void bch_mark_cache_miss_collision(struct cache_set *c,
+ struct bcache_device *d);
+void bch_mark_sectors_bypassed(struct cache_set *c,
+ struct cached_dev *dc,
+ int sectors);
#endif /* _BCACHE_STATS_H_ */
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 55a37641aa95..94c756c66bd7 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* bcache setup/teardown code, and some metadata io - read a superblock and
* figure out what to do with it.
@@ -61,7 +62,7 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
const char *err;
struct cache_sb *s;
struct buffer_head *bh = __bread(bdev, 1, SB_SIZE);
- unsigned i;
+ unsigned int i;
if (!bh)
return "IO error";
@@ -149,7 +150,8 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
goto err;
err = "Invalid superblock: device too small";
- if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets)
+ if (get_capacity(bdev->bd_disk) <
+ sb->bucket_size * sb->nbuckets)
goto err;
err = "Bad UUID";
@@ -202,7 +204,7 @@ static void write_bdev_super_endio(struct bio *bio)
static void __write_super(struct cache_sb *sb, struct bio *bio)
{
struct cache_sb *out = page_address(bio_first_page_all(bio));
- unsigned i;
+ unsigned int i;
bio->bi_iter.bi_sector = SB_SECTOR;
bio->bi_iter.bi_size = SB_SIZE;
@@ -282,7 +284,7 @@ void bcache_write_super(struct cache_set *c)
{
struct closure *cl = &c->sb_write;
struct cache *ca;
- unsigned i;
+ unsigned int i;
down(&c->sb_write_mutex);
closure_init(cl, &c->cl);
@@ -334,7 +336,7 @@ static void uuid_io(struct cache_set *c, int op, unsigned long op_flags,
{
struct closure *cl = &c->uuid_write;
struct uuid_entry *u;
- unsigned i;
+ unsigned int i;
char buf[80];
BUG_ON(!parent);
@@ -415,8 +417,8 @@ static int __uuid_write(struct cache_set *c)
{
BKEY_PADDED(key) k;
struct closure cl;
- closure_init_stack(&cl);
+ closure_init_stack(&cl);
lockdep_assert_held(&bch_register_lock);
if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, true))
@@ -456,6 +458,7 @@ static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid)
static struct uuid_entry *uuid_find_empty(struct cache_set *c)
{
static const char zero_uuid[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
return uuid_find(c, zero_uuid);
}
@@ -463,8 +466,8 @@ static struct uuid_entry *uuid_find_empty(struct cache_set *c)
* Bucket priorities/gens:
*
* For each bucket, we store on disk its
- * 8 bit gen
- * 16 bit priority
+ * 8 bit gen
+ * 16 bit priority
*
* See alloc.c for an explanation of the gen. The priority is used to implement
* lru (and in the future other) cache replacement policies; for most purposes
@@ -587,7 +590,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
struct prio_set *p = ca->disk_buckets;
struct bucket_disk *d = p->data + prios_per_bucket(ca), *end = d;
struct bucket *b;
- unsigned bucket_nr = 0;
+ unsigned int bucket_nr = 0;
for (b = ca->buckets;
b < ca->buckets + ca->sb.nbuckets;
@@ -599,7 +602,8 @@ static void prio_read(struct cache *ca, uint64_t bucket)
prio_io(ca, bucket, REQ_OP_READ, 0);
- if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
+ if (p->csum !=
+ bch_crc64(&p->magic, bucket_bytes(ca) - 8))
pr_warn("bad csum reading priorities");
if (p->magic != pset_magic(&ca->sb))
@@ -619,6 +623,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
static int open_dev(struct block_device *b, fmode_t mode)
{
struct bcache_device *d = b->bd_disk->private_data;
+
if (test_bit(BCACHE_DEV_CLOSING, &d->flags))
return -ENXIO;
@@ -629,6 +634,7 @@ static int open_dev(struct block_device *b, fmode_t mode)
static void release_dev(struct gendisk *b, fmode_t mode)
{
struct bcache_device *d = b->private_data;
+
closure_put(&d->cl);
}
@@ -662,7 +668,7 @@ static void bcache_device_unlink(struct bcache_device *d)
lockdep_assert_held(&bch_register_lock);
if (d->c && !test_and_set_bit(BCACHE_DEV_UNLINK_DONE, &d->flags)) {
- unsigned i;
+ unsigned int i;
struct cache *ca;
sysfs_remove_link(&d->c->kobj, d->name);
@@ -676,7 +682,7 @@ static void bcache_device_unlink(struct bcache_device *d)
static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
const char *name)
{
- unsigned i;
+ unsigned int i;
struct cache *ca;
for_each_cache(ca, d->c, i)
@@ -715,7 +721,7 @@ static void bcache_device_detach(struct bcache_device *d)
}
static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
- unsigned id)
+ unsigned int id)
{
d->id = id;
d->c = c;
@@ -762,7 +768,7 @@ static void bcache_device_free(struct bcache_device *d)
closure_debug_destroy(&d->cl);
}
-static int bcache_device_init(struct bcache_device *d, unsigned block_size,
+static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
sector_t sectors)
{
struct request_queue *q;
@@ -778,7 +784,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
if (!d->nr_stripes || d->nr_stripes > max_stripes) {
pr_err("nr_stripes too large or invalid: %u (start sector beyond end of disk?)",
- (unsigned)d->nr_stripes);
+ (unsigned int)d->nr_stripes);
return -ENOMEM;
}
@@ -919,6 +925,7 @@ void bch_cached_dev_run(struct cached_dev *dc)
if (!d->c &&
BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
struct closure cl;
+
closure_init_stack(&cl);
SET_BDEV_STATE(&dc->sb, BDEV_STATE_STALE);
@@ -928,8 +935,10 @@ void bch_cached_dev_run(struct cached_dev *dc)
add_disk(d->disk);
bd_link_disk_holder(dc->bdev, dc->disk.disk);
- /* won't show up in the uevent file, use udevadm monitor -e instead
- * only class / kset properties are persistent */
+ /*
+ * won't show up in the uevent file, use udevadm monitor -e instead
+ * only class / kset properties are persistent
+ */
kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
kfree(env[1]);
kfree(env[2]);
@@ -976,6 +985,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
{
struct cached_dev *dc = container_of(w, struct cached_dev, detach);
struct closure cl;
+
closure_init_stack(&cl);
BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
@@ -1097,12 +1107,14 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
}
}
- /* Deadlocks since we're called via sysfs...
- sysfs_remove_file(&dc->kobj, &sysfs_attach);
+ /*
+ * Deadlocks since we're called via sysfs...
+ * sysfs_remove_file(&dc->kobj, &sysfs_attach);
*/
if (bch_is_zero(u->uuid, 16)) {
struct closure cl;
+
closure_init_stack(&cl);
memcpy(u->uuid, dc->sb.uuid, 16);
@@ -1124,11 +1136,11 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
list_move(&dc->list, &c->cached_devs);
calc_cached_dev_sectors(c);
- smp_wmb();
/*
* dc->c must be set before dc->count != 0 - paired with the mb in
* cached_dev_get()
*/
+ smp_wmb();
refcount_set(&dc->count, 1);
/* Block writeback thread, but spawn it */
@@ -1212,7 +1224,7 @@ static void cached_dev_flush(struct closure *cl)
continue_at(cl, cached_dev_free, system_wq);
}
-static int cached_dev_init(struct cached_dev *dc, unsigned block_size)
+static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
{
int ret;
struct io *io;
@@ -1320,6 +1332,7 @@ void bch_flash_dev_release(struct kobject *kobj)
static void flash_dev_free(struct closure *cl)
{
struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+
mutex_lock(&bch_register_lock);
atomic_long_sub(bcache_dev_sectors_dirty(d),
&d->c->flash_dev_dirty_sectors);
@@ -1459,17 +1472,18 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
if (test_and_set_bit(CACHE_SET_IO_DISABLE, &c->flags))
pr_info("CACHE_SET_IO_DISABLE already set");
- /* XXX: we can be called from atomic context
- acquire_console_sem();
- */
+ /*
+ * XXX: we can be called from atomic context
+ * acquire_console_sem();
+ */
- printk(KERN_ERR "bcache: error on %pU: ", c->sb.set_uuid);
+ pr_err("bcache: error on %pU: ", c->sb.set_uuid);
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
- printk(", disabling caching\n");
+ pr_err(", disabling caching\n");
if (c->on_error == ON_ERROR_PANIC)
panic("panic forced after error\n");
@@ -1481,6 +1495,7 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
void bch_cache_set_release(struct kobject *kobj)
{
struct cache_set *c = container_of(kobj, struct cache_set, kobj);
+
kfree(c);
module_put(THIS_MODULE);
}
@@ -1489,7 +1504,7 @@ static void cache_set_free(struct closure *cl)
{
struct cache_set *c = container_of(cl, struct cache_set, cl);
struct cache *ca;
- unsigned i;
+ unsigned int i;
if (!IS_ERR_OR_NULL(c->debug))
debugfs_remove(c->debug);
@@ -1532,7 +1547,7 @@ static void cache_set_flush(struct closure *cl)
struct cache_set *c = container_of(cl, struct cache_set, caching);
struct cache *ca;
struct btree *b;
- unsigned i;
+ unsigned int i;
bch_cache_accounting_destroy(&c->accounting);
@@ -1671,6 +1686,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
{
int iter_size;
struct cache_set *c = kzalloc(sizeof(struct cache_set), GFP_KERNEL);
+
if (!c)
return NULL;
@@ -1731,8 +1747,8 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) ||
mempool_init_slab_pool(&c->search, 32, bch_search_cache) ||
mempool_init_kmalloc_pool(&c->bio_meta, 2,
- sizeof(struct bbio) + sizeof(struct bio_vec) *
- bucket_pages(c)) ||
+ sizeof(struct bbio) + sizeof(struct bio_vec) *
+ bucket_pages(c)) ||
mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
bioset_init(&c->bio_split, 4, offsetof(struct bbio, bio),
BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER) ||
@@ -1762,7 +1778,7 @@ static void run_cache_set(struct cache_set *c)
struct cached_dev *dc, *t;
struct cache *ca;
struct closure cl;
- unsigned i;
+ unsigned int i;
closure_init_stack(&cl);
@@ -1804,7 +1820,9 @@ static void run_cache_set(struct cache_set *c)
goto err;
err = "error reading btree root";
- c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL);
+ c->root = bch_btree_node_get(c, NULL, k,
+ j->btree_level,
+ true, NULL);
if (IS_ERR_OR_NULL(c->root))
goto err;
@@ -1853,7 +1871,7 @@ static void run_cache_set(struct cache_set *c)
pr_notice("invalidating existing data");
for_each_cache(ca, c, i) {
- unsigned j;
+ unsigned int j;
ca->sb.keys = clamp_t(int, ca->sb.nbuckets >> 7,
2, SB_JOURNAL_BUCKETS);
@@ -1998,7 +2016,7 @@ err:
void bch_cache_release(struct kobject *kobj)
{
struct cache *ca = container_of(kobj, struct cache, kobj);
- unsigned i;
+ unsigned int i;
if (ca->set) {
BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
@@ -2098,7 +2116,9 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
goto err;
}
- if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
+ if (kobject_add(&ca->kobj,
+ &part_to_dev(bdev->bd_part)->kobj,
+ "bcache")) {
err = "error calling kobject_add";
ret = -ENOMEM;
goto out;
@@ -2127,13 +2147,14 @@ err:
/* Global interfaces/init */
-static ssize_t register_bcache(struct kobject *, struct kobj_attribute *,
- const char *, size_t);
+static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
+ const char *buffer, size_t size);
kobj_attribute_write(register, register_bcache);
kobj_attribute_write(register_quiet, register_bcache);
-static bool bch_is_open_backing(struct block_device *bdev) {
+static bool bch_is_open_backing(struct block_device *bdev)
+{
struct cache_set *c, *tc;
struct cached_dev *dc, *t;
@@ -2147,10 +2168,11 @@ static bool bch_is_open_backing(struct block_device *bdev) {
return false;
}
-static bool bch_is_open_cache(struct block_device *bdev) {
+static bool bch_is_open_cache(struct block_device *bdev)
+{
struct cache_set *c, *tc;
struct cache *ca;
- unsigned i;
+ unsigned int i;
list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
for_each_cache(ca, c, i)
@@ -2159,7 +2181,8 @@ static bool bch_is_open_cache(struct block_device *bdev) {
return false;
}
-static bool bch_is_open(struct block_device *bdev) {
+static bool bch_is_open(struct block_device *bdev)
+{
return bch_is_open_cache(bdev) || bch_is_open_backing(bdev);
}
@@ -2216,6 +2239,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
err = "failed to register device";
if (SB_IS_BDEV(sb)) {
struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
+
if (!dc)
goto err_close;
@@ -2224,6 +2248,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
mutex_unlock(&bch_register_lock);
} else {
struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+
if (!ca)
goto err_close;
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 81d3520b0702..150cf4f4cf74 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -130,8 +130,10 @@ rw_attribute(btree_shrinker_disabled);
rw_attribute(copy_gc_enabled);
rw_attribute(size);
-static ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
- size_t selected)
+static ssize_t bch_snprint_string_list(char *buf,
+ size_t size,
+ const char * const list[],
+ size_t selected)
{
char *out = buf;
size_t i;
@@ -148,7 +150,7 @@ SHOW(__bch_cached_dev)
{
struct cached_dev *dc = container_of(kobj, struct cached_dev,
disk.kobj);
- const char *states[] = { "no cache", "clean", "dirty", "inconsistent" };
+ char const *states[] = { "no cache", "clean", "dirty", "inconsistent" };
int wb = dc->writeback_running;
#define var(stat) (dc->stat)
@@ -307,7 +309,7 @@ STORE(__cached_dev)
if (v < 0)
return v;
- if ((unsigned) v != BDEV_CACHE_MODE(&dc->sb)) {
+ if ((unsigned int) v != BDEV_CACHE_MODE(&dc->sb)) {
SET_BDEV_CACHE_MODE(&dc->sb, v);
bch_write_bdev_super(dc, NULL);
}
@@ -341,8 +343,9 @@ STORE(__cached_dev)
add_uevent_var(env, "DRIVER=bcache");
add_uevent_var(env, "CACHED_UUID=%pU", dc->sb.uuid),
add_uevent_var(env, "CACHED_LABEL=%s", buf);
- kobject_uevent_env(
- &disk_to_dev(dc->disk.disk)->kobj, KOBJ_CHANGE, env->envp);
+ kobject_uevent_env(&disk_to_dev(dc->disk.disk)->kobj,
+ KOBJ_CHANGE,
+ env->envp);
kfree(env);
}
@@ -459,6 +462,7 @@ STORE(__bch_flash_dev)
if (attr == &sysfs_size) {
uint64_t v;
+
strtoi_h_or_return(buf, v);
u->sectors = v >> 9;
@@ -533,9 +537,9 @@ static int bch_bset_print_stats(struct cache_set *c, char *buf)
op.stats.floats, op.stats.failed);
}
-static unsigned bch_root_usage(struct cache_set *c)
+static unsigned int bch_root_usage(struct cache_set *c)
{
- unsigned bytes = 0;
+ unsigned int bytes = 0;
struct bkey *k;
struct btree *b;
struct btree_iter iter;
@@ -570,9 +574,9 @@ static size_t bch_cache_size(struct cache_set *c)
return ret;
}
-static unsigned bch_cache_max_chain(struct cache_set *c)
+static unsigned int bch_cache_max_chain(struct cache_set *c)
{
- unsigned ret = 0;
+ unsigned int ret = 0;
struct hlist_head *h;
mutex_lock(&c->bucket_lock);
@@ -580,7 +584,7 @@ static unsigned bch_cache_max_chain(struct cache_set *c)
for (h = c->bucket_hash;
h < c->bucket_hash + (1 << BUCKET_HASH_BITS);
h++) {
- unsigned i = 0;
+ unsigned int i = 0;
struct hlist_node *p;
hlist_for_each(p, h)
@@ -593,13 +597,13 @@ static unsigned bch_cache_max_chain(struct cache_set *c)
return ret;
}
-static unsigned bch_btree_used(struct cache_set *c)
+static unsigned int bch_btree_used(struct cache_set *c)
{
return div64_u64(c->gc_stats.key_bytes * 100,
(c->gc_stats.nodes ?: 1) * btree_bytes(c));
}
-static unsigned bch_average_key_size(struct cache_set *c)
+static unsigned int bch_average_key_size(struct cache_set *c)
{
return c->gc_stats.nkeys
? div64_u64(c->gc_stats.data, c->gc_stats.nkeys)
@@ -703,6 +707,7 @@ STORE(__bch_cache_set)
if (attr == &sysfs_flash_vol_create) {
int r;
uint64_t v;
+
strtoi_h_or_return(buf, v);
r = bch_flash_dev_create(c, v);
@@ -736,6 +741,7 @@ STORE(__bch_cache_set)
if (attr == &sysfs_prune_cache) {
struct shrink_control sc;
+
sc.gfp_mask = GFP_KERNEL;
sc.nr_to_scan = strtoul_or_return(buf);
c->shrink.scan_objects(&c->shrink, &sc);
@@ -789,12 +795,14 @@ STORE_LOCKED(bch_cache_set)
SHOW(bch_cache_set_internal)
{
struct cache_set *c = container_of(kobj, struct cache_set, internal);
+
return bch_cache_set_show(&c->kobj, attr, buf);
}
STORE(bch_cache_set_internal)
{
struct cache_set *c = container_of(kobj, struct cache_set, internal);
+
return bch_cache_set_store(&c->kobj, attr, buf, size);
}
@@ -996,7 +1004,7 @@ STORE(__bch_cache)
if (v < 0)
return v;
- if ((unsigned) v != CACHE_REPLACEMENT(&ca->sb)) {
+ if ((unsigned int) v != CACHE_REPLACEMENT(&ca->sb)) {
mutex_lock(&ca->set->bucket_lock);
SET_CACHE_REPLACEMENT(&ca->sb, v);
mutex_unlock(&ca->set->bucket_lock);
diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h
index b54fe9602529..3fe82425859c 100644
--- a/drivers/md/bcache/sysfs.h
+++ b/drivers/md/bcache/sysfs.h
@@ -44,9 +44,9 @@ STORE(fn) \
static struct attribute sysfs_##_name = \
{ .name = #_name, .mode = _mode }
-#define write_attribute(n) __sysfs_attribute(n, S_IWUSR)
-#define read_attribute(n) __sysfs_attribute(n, S_IRUGO)
-#define rw_attribute(n) __sysfs_attribute(n, S_IRUGO|S_IWUSR)
+#define write_attribute(n) __sysfs_attribute(n, 0200)
+#define read_attribute(n) __sysfs_attribute(n, 0444)
+#define rw_attribute(n) __sysfs_attribute(n, 0644)
#define sysfs_printf(file, fmt, ...) \
do { \
diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c
index b15256bcf0e7..20eddeac1531 100644
--- a/drivers/md/bcache/util.c
+++ b/drivers/md/bcache/util.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* random utiility code, for bcache but in theory not specific to bcache
*
@@ -133,6 +134,7 @@ bool bch_is_zero(const char *p, size_t n)
int bch_parse_uuid(const char *s, char *uuid)
{
size_t i, j, x;
+
memset(uuid, 0, 16);
for (i = 0, j = 0;
@@ -279,134 +281,3 @@ int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
return 0;
}
-
-/*
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
- * use permitted, subject to terms of PostgreSQL license; see.)
-
- * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
- * usual sort of implementation. (See Ross Williams' excellent introduction
- * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
- * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
- * If we have no working 64-bit type, then fake it with two 32-bit registers.
- *
- * The present implementation is a normal (not "reflected", in Williams'
- * terms) 64-bit CRC, using initial all-ones register contents and a final
- * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
- * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
- *
- * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
- * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
- * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
- * x^7 + x^4 + x + 1
-*/
-
-static const uint64_t crc_table[256] = {
- 0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
- 0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
- 0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
- 0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
- 0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
- 0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
- 0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
- 0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
- 0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
- 0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
- 0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
- 0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
- 0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
- 0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
- 0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
- 0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
- 0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
- 0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
- 0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
- 0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
- 0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
- 0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
- 0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
- 0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
- 0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
- 0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
- 0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
- 0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
- 0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
- 0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
- 0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
- 0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
- 0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
- 0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
- 0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
- 0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
- 0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
- 0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
- 0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
- 0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
- 0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
- 0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
- 0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
- 0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
- 0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
- 0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
- 0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
- 0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
- 0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
- 0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
- 0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
- 0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
- 0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
- 0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
- 0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
- 0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
- 0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
- 0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
- 0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
- 0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
- 0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
- 0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
- 0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
- 0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
- 0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
- 0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
- 0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
- 0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
- 0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
- 0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
- 0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
- 0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
- 0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
- 0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
- 0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
- 0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
- 0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
- 0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
- 0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
- 0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
- 0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
- 0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
- 0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
- 0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
- 0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
- 0x9AFCE626CE85B507ULL,
-};
-
-uint64_t bch_crc64_update(uint64_t crc, const void *_data, size_t len)
-{
- const unsigned char *data = _data;
-
- while (len--) {
- int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
- crc = crc_table[i] ^ (crc << 8);
- }
-
- return crc;
-}
-
-uint64_t bch_crc64(const void *data, size_t len)
-{
- uint64_t crc = 0xffffffffffffffffULL;
-
- crc = bch_crc64_update(crc, data, len);
-
- return crc ^ 0xffffffffffffffffULL;
-}
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index f7b0133c9d2f..00aab6abcfe4 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -11,6 +11,7 @@
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
+#include <linux/crc64.h>
#include "closure.h"
@@ -288,10 +289,10 @@ do { \
#define ANYSINT_MAX(t) \
((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
-int bch_strtoint_h(const char *, int *);
-int bch_strtouint_h(const char *, unsigned int *);
-int bch_strtoll_h(const char *, long long *);
-int bch_strtoull_h(const char *, unsigned long long *);
+int bch_strtoint_h(const char *cp, int *res);
+int bch_strtouint_h(const char *cp, unsigned int *res);
+int bch_strtoll_h(const char *cp, long long *res);
+int bch_strtoull_h(const char *cp, unsigned long long *res);
static inline int bch_strtol_h(const char *cp, long *res)
{
@@ -347,7 +348,7 @@ static inline int bch_strtoul_h(const char *cp, long *res)
snprintf(buf, size, \
__builtin_types_compatible_p(typeof(var), int) \
? "%i\n" : \
- __builtin_types_compatible_p(typeof(var), unsigned) \
+ __builtin_types_compatible_p(typeof(var), unsigned int) \
? "%u\n" : \
__builtin_types_compatible_p(typeof(var), long) \
? "%li\n" : \
@@ -379,7 +380,7 @@ struct time_stats {
void bch_time_stats_update(struct time_stats *stats, uint64_t time);
-static inline unsigned local_clock_us(void)
+static inline unsigned int local_clock_us(void)
{
return local_clock() >> 10;
}
@@ -402,7 +403,8 @@ do { \
__print_time_stat(stats, name, \
average_duration, duration_units); \
sysfs_print(name ## _ ##max_duration ## _ ## duration_units, \
- div_u64((stats)->max_duration, NSEC_PER_ ## duration_units));\
+ div_u64((stats)->max_duration, \
+ NSEC_PER_ ## duration_units)); \
\
sysfs_print(name ## _last_ ## frequency_units, (stats)->last \
? div_s64(local_clock() - (stats)->last, \
@@ -542,10 +544,27 @@ dup: \
#define RB_PREV(ptr, member) \
container_of_or_null(rb_prev(&(ptr)->member), typeof(*ptr), member)
+static inline uint64_t bch_crc64(const void *p, size_t len)
+{
+ uint64_t crc = 0xffffffffffffffffULL;
+
+ crc = crc64_be(crc, p, len);
+ return crc ^ 0xffffffffffffffffULL;
+}
+
+static inline uint64_t bch_crc64_update(uint64_t crc,
+ const void *p,
+ size_t len)
+{
+ crc = crc64_be(crc, p, len);
+ return crc;
+}
+
/* Does linear interpolation between powers of two */
-static inline unsigned fract_exp_two(unsigned x, unsigned fract_bits)
+static inline unsigned int fract_exp_two(unsigned int x,
+ unsigned int fract_bits)
{
- unsigned fract = x & ~(~0 << fract_bits);
+ unsigned int fract = x & ~(~0 << fract_bits);
x >>= fract_bits;
x = 1 << x;
@@ -561,8 +580,4 @@ static inline sector_t bdev_sectors(struct block_device *bdev)
{
return bdev->bd_inode->i_size >> 9;
}
-
-uint64_t bch_crc64_update(uint64_t, const void *, size_t);
-uint64_t bch_crc64(const void *, size_t);
-
#endif /* _BCACHE_UTIL_H */
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 481d4cf38ac0..6be05bd7ca67 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -215,7 +215,8 @@ static void update_writeback_rate(struct work_struct *work)
smp_mb();
}
-static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
+static unsigned int writeback_delay(struct cached_dev *dc,
+ unsigned int sectors)
{
if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
!dc->writeback_percent)
@@ -249,6 +250,7 @@ static void dirty_init(struct keybuf_key *w)
static void dirty_io_destructor(struct closure *cl)
{
struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+
kfree(io);
}
@@ -263,7 +265,7 @@ static void write_dirty_finish(struct closure *cl)
/* This is kind of a dumb way of signalling errors. */
if (KEY_DIRTY(&w->key)) {
int ret;
- unsigned i;
+ unsigned int i;
struct keylist keys;
bch_keylist_init(&keys);
@@ -377,7 +379,7 @@ static void read_dirty_submit(struct closure *cl)
static void read_dirty(struct cached_dev *dc)
{
- unsigned delay = 0;
+ unsigned int delay = 0;
struct keybuf_key *next, *keys[MAX_WRITEBACKS_IN_PASS], *w;
size_t size;
int nk, i;
@@ -442,7 +444,8 @@ static void read_dirty(struct cached_dev *dc)
io = kzalloc(sizeof(struct dirty_io) +
sizeof(struct bio_vec) *
- DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+ DIV_ROUND_UP(KEY_SIZE(&w->key),
+ PAGE_SECTORS),
GFP_KERNEL);
if (!io)
goto err;
@@ -465,7 +468,8 @@ static void read_dirty(struct cached_dev *dc)
down(&dc->in_flight);
- /* We've acquired a semaphore for the maximum
+ /*
+ * We've acquired a semaphore for the maximum
* simultaneous number of writebacks; from here
* everything happens asynchronously.
*/
@@ -498,11 +502,11 @@ err:
/* Scan for dirty data */
-void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
+void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode,
uint64_t offset, int nr_sectors)
{
struct bcache_device *d = c->devices[inode];
- unsigned stripe_offset, stripe, sectors_dirty;
+ unsigned int stripe_offset, stripe, sectors_dirty;
if (!d)
return;
@@ -514,7 +518,7 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
stripe_offset = offset & (d->stripe_size - 1);
while (nr_sectors) {
- int s = min_t(unsigned, abs(nr_sectors),
+ int s = min_t(unsigned int, abs(nr_sectors),
d->stripe_size - stripe_offset);
if (nr_sectors < 0)
@@ -538,7 +542,9 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
static bool dirty_pred(struct keybuf *buf, struct bkey *k)
{
- struct cached_dev *dc = container_of(buf, struct cached_dev, writeback_keys);
+ struct cached_dev *dc = container_of(buf,
+ struct cached_dev,
+ writeback_keys);
BUG_ON(KEY_INODE(k) != dc->disk.id);
@@ -548,7 +554,7 @@ static bool dirty_pred(struct keybuf *buf, struct bkey *k)
static void refill_full_stripes(struct cached_dev *dc)
{
struct keybuf *buf = &dc->writeback_keys;
- unsigned start_stripe, stripe, next_stripe;
+ unsigned int start_stripe, stripe, next_stripe;
bool wrapped = false;
stripe = offset_to_stripe(&dc->disk, KEY_OFFSET(&buf->last_scanned));
@@ -688,7 +694,7 @@ static int bch_writeback_thread(void *arg)
read_dirty(dc);
if (searched_full_index) {
- unsigned delay = dc->writeback_delay * HZ;
+ unsigned int delay = dc->writeback_delay * HZ;
while (delay &&
!kthread_should_stop() &&
@@ -712,7 +718,7 @@ static int bch_writeback_thread(void *arg)
struct sectors_dirty_init {
struct btree_op op;
- unsigned inode;
+ unsigned int inode;
size_t count;
struct bkey start;
};
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index 3745d7004c47..d2b9fdbc8994 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -28,7 +28,7 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
return ret;
}
-static inline unsigned offset_to_stripe(struct bcache_device *d,
+static inline unsigned int offset_to_stripe(struct bcache_device *d,
uint64_t offset)
{
do_div(offset, d->stripe_size);
@@ -37,9 +37,9 @@ static inline unsigned offset_to_stripe(struct bcache_device *d,
static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
uint64_t offset,
- unsigned nr_sectors)
+ unsigned int nr_sectors)
{
- unsigned stripe = offset_to_stripe(&dc->disk, offset);
+ unsigned int stripe = offset_to_stripe(&dc->disk, offset);
while (1) {
if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
@@ -54,9 +54,9 @@ static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
}
static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
- unsigned cache_mode, bool would_skip)
+ unsigned int cache_mode, bool would_skip)
{
- unsigned in_use = dc->disk.c->gc_stats.in_use;
+ unsigned int in_use = dc->disk.c->gc_stats.in_use;
if (cache_mode != CACHE_MODE_WRITEBACK ||
test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
@@ -96,10 +96,11 @@ static inline void bch_writeback_add(struct cached_dev *dc)
}
}
-void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
+void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode,
+ uint64_t offset, int nr_sectors);
-void bch_sectors_dirty_init(struct bcache_device *);
-void bch_cached_dev_writeback_init(struct cached_dev *);
-int bch_cached_dev_writeback_start(struct cached_dev *);
+void bch_sectors_dirty_init(struct bcache_device *d);
+void bch_cached_dev_writeback_init(struct cached_dev *dc);
+int bch_cached_dev_writeback_start(struct cached_dev *dc);
#endif
diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c
index 16dffa06c913..dd2078b27a41 100644
--- a/drivers/media/cec/cec-notifier.c
+++ b/drivers/media/cec/cec-notifier.c
@@ -21,6 +21,7 @@ struct cec_notifier {
struct list_head head;
struct kref kref;
struct device *dev;
+ const char *conn;
struct cec_adapter *cec_adap;
void (*callback)(struct cec_adapter *adap, u16 pa);
@@ -30,13 +31,14 @@ struct cec_notifier {
static LIST_HEAD(cec_notifiers);
static DEFINE_MUTEX(cec_notifiers_lock);
-struct cec_notifier *cec_notifier_get(struct device *dev)
+struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
{
struct cec_notifier *n;
mutex_lock(&cec_notifiers_lock);
list_for_each_entry(n, &cec_notifiers, head) {
- if (n->dev == dev) {
+ if (n->dev == dev &&
+ (!conn || !strcmp(n->conn, conn))) {
kref_get(&n->kref);
mutex_unlock(&cec_notifiers_lock);
return n;
@@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
if (!n)
goto unlock;
n->dev = dev;
+ if (conn)
+ n->conn = kstrdup(conn, GFP_KERNEL);
n->phys_addr = CEC_PHYS_ADDR_INVALID;
mutex_init(&n->lock);
kref_init(&n->kref);
@@ -54,7 +58,7 @@ unlock:
mutex_unlock(&cec_notifiers_lock);
return n;
}
-EXPORT_SYMBOL_GPL(cec_notifier_get);
+EXPORT_SYMBOL_GPL(cec_notifier_get_conn);
static void cec_notifier_release(struct kref *kref)
{
@@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref)
container_of(kref, struct cec_notifier, kref);
list_del(&n->head);
+ kfree(n->conn);
kfree(n);
}
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
index f3acbb57d48c..35a93b251aab 100644
--- a/drivers/media/dvb-frontends/af9013.c
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -1311,10 +1311,10 @@ static int af9013_wregs(struct i2c_client *client, u8 cmd, u16 reg,
memcpy(&buf[3], val, len);
if (lock)
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = __i2c_transfer(client->adapter, msg, 1);
if (lock)
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (ret < 0) {
goto err;
} else if (ret != 1) {
@@ -1352,10 +1352,10 @@ static int af9013_rregs(struct i2c_client *client, u8 cmd, u16 reg,
buf[2] = cmd;
if (lock)
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = __i2c_transfer(client->adapter, msg, 2);
if (lock)
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
if (ret < 0) {
goto err;
} else if (ret != 2) {
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index f1886945a7bc..84ac3f73f8fe 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -213,7 +213,7 @@ static inline u32 log10times100(u32 value)
static int drxk_i2c_lock(struct drxk_state *state)
{
- i2c_lock_adapter(state->i2c);
+ i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
state->drxk_i2c_exclusive_lock = true;
return 0;
@@ -224,7 +224,7 @@ static void drxk_i2c_unlock(struct drxk_state *state)
if (!state->drxk_i2c_exclusive_lock)
return;
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
state->drxk_i2c_exclusive_lock = false;
}
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
index adc9046d5a90..c0659568471b 100644
--- a/drivers/media/dvb-frontends/rtl2830.c
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -24,9 +24,9 @@ static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
@@ -36,9 +36,9 @@ static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_update_bits(dev->regmap, reg, mask, val);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
@@ -48,9 +48,9 @@ static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
struct rtl2830_dev *dev = i2c_get_clientdata(client);
int ret;
- i2c_lock_adapter(client->adapter);
+ i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
- i2c_unlock_adapter(client->adapter);
+ i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
return ret;
}
diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c
index d402e4b722ca..e506f66657bb 100644
--- a/drivers/media/dvb-frontends/tda1004x.c
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -329,7 +329,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
tda1004x_write_byteI(state, dspCodeCounterReg, 0);
fw_msg.addr = state->config->demod_address;
- i2c_lock_adapter(state->i2c);
+ i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
buf[0] = dspCodeInReg;
while (pos != len) {
// work out how much to send this time
@@ -342,14 +342,14 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
fw_msg.len = tx_size + 1;
if (__i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
printk(KERN_ERR "tda1004x: Error during firmware upload\n");
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
return -EIO;
}
pos += tx_size;
dprintk("%s: fw_pos=0x%x\n", __func__, pos);
}
- i2c_unlock_adapter(state->i2c);
+ i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
/* give the DSP a chance to settle 03/10/05 Hac */
msleep(100);
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index b25c8d3c1c31..94c1fe0e9787 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -536,6 +536,17 @@ menuconfig CEC_PLATFORM_DRIVERS
if CEC_PLATFORM_DRIVERS
+config VIDEO_CROS_EC_CEC
+ tristate "ChromeOS EC CEC driver"
+ depends on MFD_CROS_EC
+ select CEC_CORE
+ select CEC_NOTIFIER
+ ---help---
+ If you say yes here you will get support for the
+ ChromeOS Embedded Controller's CEC.
+ The CEC bus is present in the HDMI connector and enables communication
+ between compatible devices.
+
config VIDEO_MESON_AO_CEC
tristate "Amlogic Meson AO CEC driver"
depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 08640ba87fc2..41322ab65802 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -94,3 +94,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += meson/
+
+obj-y += cros-ec-cec/
diff --git a/drivers/media/platform/cros-ec-cec/Makefile b/drivers/media/platform/cros-ec-cec/Makefile
new file mode 100644
index 000000000000..9ce97f93febe
--- /dev/null
+++ b/drivers/media/platform/cros-ec-cec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
new file mode 100644
index 000000000000..7bc4d8a9af28
--- /dev/null
+++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CEC driver for ChromeOS Embedded Controller
+ *
+ * Copyright (c) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/cec.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <media/cec.h>
+#include <media/cec-notifier.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+
+#define DRV_NAME "cros-ec-cec"
+
+/**
+ * struct cros_ec_cec - Driver data for EC CEC
+ *
+ * @cros_ec: Pointer to EC device
+ * @notifier: Notifier info for responding to EC events
+ * @adap: CEC adapter
+ * @notify: CEC notifier pointer
+ * @rx_msg: storage for a received message
+ */
+struct cros_ec_cec {
+ struct cros_ec_device *cros_ec;
+ struct notifier_block notifier;
+ struct cec_adapter *adap;
+ struct cec_notifier *notify;
+ struct cec_msg rx_msg;
+};
+
+static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
+{
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ uint8_t *cec_message = cros_ec->event_data.data.cec_message;
+ unsigned int len = cros_ec->event_size;
+
+ cros_ec_cec->rx_msg.len = len;
+ memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
+
+ cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
+}
+
+static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
+{
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ uint32_t events = cros_ec->event_data.data.cec_events;
+
+ if (events & EC_MKBP_CEC_SEND_OK)
+ cec_transmit_attempt_done(cros_ec_cec->adap,
+ CEC_TX_STATUS_OK);
+
+ /* FW takes care of all retries, tell core to avoid more retries */
+ if (events & EC_MKBP_CEC_SEND_FAILED)
+ cec_transmit_attempt_done(cros_ec_cec->adap,
+ CEC_TX_STATUS_MAX_RETRIES |
+ CEC_TX_STATUS_NACK);
+}
+
+static int cros_ec_cec_event(struct notifier_block *nb,
+ unsigned long queued_during_suspend,
+ void *_notify)
+{
+ struct cros_ec_cec *cros_ec_cec;
+ struct cros_ec_device *cros_ec;
+
+ cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier);
+ cros_ec = cros_ec_cec->cros_ec;
+
+ if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) {
+ handle_cec_event(cros_ec_cec);
+ return NOTIFY_OK;
+ }
+
+ if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) {
+ handle_cec_message(cros_ec_cec);
+ return NOTIFY_OK;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
+{
+ struct cros_ec_cec *cros_ec_cec = adap->priv;
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ struct {
+ struct cros_ec_command msg;
+ struct ec_params_cec_set data;
+ } __packed msg = {};
+ int ret;
+
+ msg.msg.command = EC_CMD_CEC_SET;
+ msg.msg.outsize = sizeof(msg.data);
+ msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS;
+ msg.data.val = logical_addr;
+
+ ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+ if (ret < 0) {
+ dev_err(cros_ec->dev,
+ "error setting CEC logical address on EC: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
+ u32 signal_free_time, struct cec_msg *cec_msg)
+{
+ struct cros_ec_cec *cros_ec_cec = adap->priv;
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ struct {
+ struct cros_ec_command msg;
+ struct ec_params_cec_write data;
+ } __packed msg = {};
+ int ret;
+
+ msg.msg.command = EC_CMD_CEC_WRITE_MSG;
+ msg.msg.outsize = cec_msg->len;
+ memcpy(msg.data.msg, cec_msg->msg, cec_msg->len);
+
+ ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+ if (ret < 0) {
+ dev_err(cros_ec->dev,
+ "error writing CEC msg on EC: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+ struct cros_ec_cec *cros_ec_cec = adap->priv;
+ struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+ struct {
+ struct cros_ec_command msg;
+ struct ec_params_cec_set data;
+ } __packed msg = {};
+ int ret;
+
+ msg.msg.command = EC_CMD_CEC_SET;
+ msg.msg.outsize = sizeof(msg.data);
+ msg.data.cmd = CEC_CMD_ENABLE;
+ msg.data.val = enable;
+
+ ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+ if (ret < 0) {
+ dev_err(cros_ec->dev,
+ "error %sabling CEC on EC: %d\n",
+ (enable ? "en" : "dis"), ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct cec_adap_ops cros_ec_cec_ops = {
+ .adap_enable = cros_ec_cec_adap_enable,
+ .adap_log_addr = cros_ec_cec_set_log_addr,
+ .adap_transmit = cros_ec_cec_transmit,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_cec_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(cros_ec_cec->cros_ec->irq);
+
+ return 0;
+}
+
+static int cros_ec_cec_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(cros_ec_cec->cros_ec->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
+ cros_ec_cec_suspend, cros_ec_cec_resume);
+
+#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI)
+
+/*
+ * The Firmware only handles a single CEC interface tied to a single HDMI
+ * connector we specify along with the DRM device name handling the HDMI output
+ */
+
+struct cec_dmi_match {
+ char *sys_vendor;
+ char *product_name;
+ char *devname;
+ char *conn;
+};
+
+static const struct cec_dmi_match cec_dmi_match_table[] = {
+ /* Google Fizz */
+ { "Google", "Fizz", "0000:00:02.0", "Port B" },
+};
+
+static int cros_ec_cec_get_notifier(struct device *dev,
+ struct cec_notifier **notify)
+{
+ int i;
+
+ for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) {
+ const struct cec_dmi_match *m = &cec_dmi_match_table[i];
+
+ if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
+ dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
+ struct device *d;
+
+ /* Find the device, bail out if not yet registered */
+ d = bus_find_device_by_name(&pci_bus_type, NULL,
+ m->devname);
+ if (!d)
+ return -EPROBE_DEFER;
+
+ *notify = cec_notifier_get_conn(d, m->conn);
+ return 0;
+ }
+ }
+
+ /* Hardware support must be added in the cec_dmi_match_table */
+ dev_warn(dev, "CEC notifier not configured for this hardware\n");
+
+ return -ENODEV;
+}
+
+#else
+
+static int cros_ec_cec_get_notifier(struct device *dev,
+ struct cec_notifier **notify)
+{
+ return -ENODEV;
+}
+
+#endif
+
+static int cros_ec_cec_probe(struct platform_device *pdev)
+{
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
+ struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+ struct cros_ec_cec *cros_ec_cec;
+ int ret;
+
+ cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
+ GFP_KERNEL);
+ if (!cros_ec_cec)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, cros_ec_cec);
+ cros_ec_cec->cros_ec = cros_ec;
+
+ ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify);
+ if (ret)
+ return ret;
+
+ ret = device_init_wakeup(&pdev->dev, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize wakeup\n");
+ return ret;
+ }
+
+ cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
+ DRV_NAME, CEC_CAP_DEFAULTS, 1);
+ if (IS_ERR(cros_ec_cec->adap))
+ return PTR_ERR(cros_ec_cec->adap);
+
+ /* Get CEC events from the EC. */
+ cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
+ ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
+ &cros_ec_cec->notifier);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register notifier\n");
+ cec_delete_adapter(cros_ec_cec->adap);
+ return ret;
+ }
+
+ ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
+ if (ret < 0) {
+ cec_delete_adapter(cros_ec_cec->adap);
+ return ret;
+ }
+
+ cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify);
+
+ return 0;
+}
+
+static int cros_ec_cec_remove(struct platform_device *pdev)
+{
+ struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = blocking_notifier_chain_unregister(
+ &cros_ec_cec->cros_ec->event_notifier,
+ &cros_ec_cec->notifier);
+
+ if (ret) {
+ dev_err(dev, "failed to unregister notifier\n");
+ return ret;
+ }
+
+ cec_unregister_adapter(cros_ec_cec->adap);
+
+ if (cros_ec_cec->notify)
+ cec_notifier_put(cros_ec_cec->notify);
+
+ return 0;
+}
+
+static struct platform_driver cros_ec_cec_driver = {
+ .probe = cros_ec_cec_probe,
+ .remove = cros_ec_cec_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .pm = &cros_ec_cec_pm_ops,
+ },
+};
+
+module_platform_driver(cros_ec_cec_driver);
+
+MODULE_DESCRIPTION("CEC driver for ChromeOS ECs");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c
index 7e81cd887c13..054b3b747dae 100644
--- a/drivers/media/tuners/tda18271-common.c
+++ b/drivers/media/tuners/tda18271-common.c
@@ -225,7 +225,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
*/
if (lock_i2c) {
tda18271_i2c_gate_ctrl(fe, 1);
- i2c_lock_adapter(priv->i2c_props.adap);
+ i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
}
while (len) {
if (max > len)
@@ -246,7 +246,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
len -= max;
}
if (lock_i2c) {
- i2c_unlock_adapter(priv->i2c_props.adap);
+ i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
tda18271_i2c_gate_ctrl(fe, 0);
}
@@ -300,7 +300,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
* as those could cause bad things
*/
tda18271_i2c_gate_ctrl(fe, 1);
- i2c_lock_adapter(priv->i2c_props.adap);
+ i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
/* initialize registers */
switch (priv->id) {
@@ -516,7 +516,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
/* synchronize */
__tda18271_write_regs(fe, R_EP1, 1, false);
- i2c_unlock_adapter(priv->i2c_props.adap);
+ i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
tda18271_i2c_gate_ctrl(fe, 0);
return 0;
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index bb93cc53554e..bd25faf6d13d 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -672,13 +672,6 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
- err = tegra_mc_reset_setup(mc);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to register reset controller: %d\n",
- err);
- return err;
- }
-
mc->irq = platform_get_irq(pdev, 0);
if (mc->irq < 0) {
dev_err(&pdev->dev, "interrupt not specified\n");
@@ -697,13 +690,16 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
+ err = tegra_mc_reset_setup(mc);
+ if (err < 0)
+ dev_err(&pdev->dev, "failed to register reset controller: %d\n",
+ err);
+
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
- if (IS_ERR(mc->smmu)) {
+ if (IS_ERR(mc->smmu))
dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
PTR_ERR(mc->smmu));
- return PTR_ERR(mc->smmu);
- }
}
return 0;
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
index 632651f4b6e8..2250d03ea17f 100644
--- a/drivers/memory/ti-emif-pm.c
+++ b/drivers/memory/ti-emif-pm.c
@@ -249,6 +249,34 @@ static const struct of_device_id ti_emif_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ti_emif_of_match);
+#ifdef CONFIG_PM_SLEEP
+static int ti_emif_resume(struct device *dev)
+{
+ unsigned long tmp =
+ __raw_readl((void *)emif_instance->ti_emif_sram_virt);
+
+ /*
+ * Check to see if what we are copying is already present in the
+ * first byte at the destination, only copy if it is not which
+ * indicates we have lost context and sram no longer contains
+ * the PM code
+ */
+ if (tmp != ti_emif_sram)
+ ti_emif_push_sram(dev, emif_instance);
+
+ return 0;
+}
+
+static int ti_emif_suspend(struct device *dev)
+{
+ /*
+ * The contents will be present in DDR hence no need to
+ * explicitly save
+ */
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
static int ti_emif_probe(struct platform_device *pdev)
{
int ret;
@@ -308,12 +336,17 @@ static int ti_emif_remove(struct platform_device *pdev)
return 0;
}
+static const struct dev_pm_ops ti_emif_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
+};
+
static struct platform_driver ti_emif_driver = {
.probe = ti_emif_probe,
.remove = ti_emif_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(ti_emif_of_match),
+ .pm = &ti_emif_pm_ops,
},
};
module_platform_driver(ti_emif_driver);
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
index 84e313107233..7b9052ea7413 100644
--- a/drivers/mfd/88pm860x-i2c.c
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -146,14 +146,14 @@ int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
unsigned char zero;
int ret;
- i2c_lock_adapter(i2c->adapter);
+ i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
read_device(i2c, 0xFA, 0, &zero);
read_device(i2c, 0xFB, 0, &zero);
read_device(i2c, 0xFF, 0, &zero);
ret = write_device(i2c, reg, 1, &data);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
- i2c_unlock_adapter(i2c->adapter);
+ i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
return ret;
}
EXPORT_SYMBOL(pm860x_page_reg_write);
@@ -164,14 +164,14 @@ int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
unsigned char zero = 0;
int ret;
- i2c_lock_adapter(i2c->adapter);
+ i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
read_device(i2c, 0xfa, 0, &zero);
read_device(i2c, 0xfb, 0, &zero);
read_device(i2c, 0xff, 0, &zero);
ret = read_device(i2c, reg, count, buf);
read_device(i2c, 0xFE, 0, &zero);
read_device(i2c, 0xFC, 0, &zero);
- i2c_unlock_adapter(i2c->adapter);
+ i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
return ret;
}
EXPORT_SYMBOL(pm860x_page_bulk_read);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b860eb5aa194..11841f4b7b2b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -202,26 +202,6 @@ config MFD_CROS_EC
You also need to enable the driver for the bus you are using. The
protocol for talking to the EC is defined by the bus driver.
-config MFD_CROS_EC_I2C
- tristate "ChromeOS Embedded Controller (I2C)"
- depends on MFD_CROS_EC && I2C
-
- help
- If you say Y here, you get support for talking to the ChromeOS
- EC through an I2C bus. This uses a simple byte-level protocol with
- a checksum. Failing accesses will be retried three times to
- improve reliability.
-
-config MFD_CROS_EC_SPI
- tristate "ChromeOS Embedded Controller (SPI)"
- depends on MFD_CROS_EC && SPI
-
- ---help---
- If you say Y here, you get support for talking to the ChromeOS EC
- through a SPI bus, using a byte-level protocol. Since the EC's
- response time cannot be guaranteed, we support ignoring
- 'pre-amble' bytes before the response actually starts.
-
config MFD_CROS_EC_CHARDEV
tristate "Chrome OS Embedded Controller userspace device interface"
depends on MFD_CROS_EC
@@ -232,6 +212,56 @@ config MFD_CROS_EC_CHARDEV
If you have a supported Chromebook, choose Y or M here.
The module will be called cros_ec_dev.
+config MFD_MADERA
+ tristate "Cirrus Logic Madera codecs"
+ select MFD_CORE
+ select REGMAP
+ select REGMAP_IRQ
+ select MADERA_IRQ
+ select PINCTRL
+ select PINCTRL_MADERA
+ help
+ Support for the Cirrus Logic Madera platform audio codecs
+
+config MFD_MADERA_I2C
+ tristate "Cirrus Logic Madera codecs with I2C"
+ depends on MFD_MADERA
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Support for the Cirrus Logic Madera platform audio SoC
+ core functionality controlled via I2C.
+
+config MFD_MADERA_SPI
+ tristate "Cirrus Logic Madera codecs with SPI"
+ depends on MFD_MADERA
+ depends on SPI_MASTER
+ select REGMAP_SPI
+ help
+ Support for the Cirrus Logic Madera platform audio SoC
+ core functionality controlled via SPI.
+
+config MFD_CS47L35
+ bool "Cirrus Logic CS47L35"
+ select PINCTRL_CS47L35
+ depends on MFD_MADERA
+ help
+ Support for Cirrus Logic CS47L35 Smart Codec
+
+config MFD_CS47L85
+ bool "Cirrus Logic CS47L85"
+ select PINCTRL_CS47L85
+ depends on MFD_MADERA
+ help
+ Support for Cirrus Logic CS47L85 Smart Codec
+
+config MFD_CS47L90
+ bool "Cirrus Logic CS47L90/91"
+ select PINCTRL_CS47L90
+ depends on MFD_MADERA
+ help
+ Support for Cirrus Logic CS47L90 and CS47L91 Smart Codecs
+
config MFD_ASIC3
bool "Compaq ASIC3"
depends on GPIOLIB && ARM
@@ -1787,6 +1817,19 @@ config MFD_STW481X
in various ST Microelectronics and ST-Ericsson embedded
Nomadik series.
+config MFD_ROHM_BD718XX
+ tristate "ROHM BD71837 Power Management IC"
+ depends on I2C=y
+ depends on OF
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ select MFD_CORE
+ help
+ Select this option to get support for the ROHM BD71837
+ Power Management ICs. BD71837 is designed to power processors like
+ NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
+ and emergency shut down as well as 32,768KHz clock output.
+
config MFD_STM32_LPTIMER
tristate "Support for STM32 Low-Power Timer"
depends on (ARCH_STM32 && OF) || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e9fd20dba18d..5856a9489cbd 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
-obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
-obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
@@ -72,6 +70,20 @@ wm8994-objs := wm8994-core.o wm8994-irq.o wm8994-regmap.o
obj-$(CONFIG_MFD_WM8994) += wm8994.o
obj-$(CONFIG_MFD_WM97xx) += wm97xx-core.o
+madera-objs := madera-core.o
+ifeq ($(CONFIG_MFD_CS47L35),y)
+madera-objs += cs47l35-tables.o
+endif
+ifeq ($(CONFIG_MFD_CS47L85),y)
+madera-objs += cs47l85-tables.o
+endif
+ifeq ($(CONFIG_MFD_CS47L90),y)
+madera-objs += cs47l90-tables.o
+endif
+obj-$(CONFIG_MFD_MADERA) += madera.o
+obj-$(CONFIG_MFD_MADERA_I2C) += madera-i2c.o
+obj-$(CONFIG_MFD_MADERA_SPI) += madera-spi.o
+
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_TPS6507X) += tps6507x.o
@@ -227,4 +239,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
+obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 83f1c5a516d9..5f1e37d23943 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/slab.h>
+#include <linux/ktime.h>
#include <linux/platform_device.h>
#include <linux/mfd/arizona/core.h>
@@ -236,22 +237,39 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
#define ARIZONA_REG_POLL_DELAY_US 7500
+static inline bool arizona_poll_reg_delay(ktime_t timeout)
+{
+ if (ktime_compare(ktime_get(), timeout) > 0)
+ return false;
+
+ usleep_range(ARIZONA_REG_POLL_DELAY_US / 2, ARIZONA_REG_POLL_DELAY_US);
+
+ return true;
+}
+
static int arizona_poll_reg(struct arizona *arizona,
int timeout_ms, unsigned int reg,
unsigned int mask, unsigned int target)
{
+ ktime_t timeout = ktime_add_us(ktime_get(), timeout_ms * USEC_PER_MSEC);
unsigned int val = 0;
int ret;
- ret = regmap_read_poll_timeout(arizona->regmap,
- reg, val, ((val & mask) == target),
- ARIZONA_REG_POLL_DELAY_US,
- timeout_ms * 1000);
- if (ret)
- dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n",
- reg, val);
+ do {
+ ret = regmap_read(arizona->regmap, reg, &val);
- return ret;
+ if ((val & mask) == target)
+ return 0;
+ } while (arizona_poll_reg_delay(timeout));
+
+ if (ret) {
+ dev_err(arizona->dev, "Failed polling reg 0x%x: %d\n",
+ reg, ret);
+ return ret;
+ }
+
+ dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n", reg, val);
+ return -ETIMEDOUT;
}
static int arizona_wait_for_boot(struct arizona *arizona)
diff --git a/drivers/mfd/as3722.c b/drivers/mfd/as3722.c
index f87342c211bc..4d069ed21ff6 100644
--- a/drivers/mfd/as3722.c
+++ b/drivers/mfd/as3722.c
@@ -349,6 +349,8 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c,
"ams,enable-internal-int-pullup");
as3722->en_intern_i2c_pullup = of_property_read_bool(np,
"ams,enable-internal-i2c-pullup");
+ as3722->en_ac_ok_pwr_on = of_property_read_bool(np,
+ "ams,enable-ac-ok-power-on");
as3722->irq_flags = irqd_get_trigger_type(irq_data);
dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags);
return 0;
@@ -360,6 +362,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
struct as3722 *as3722;
unsigned long irq_flags;
int ret;
+ u8 val = 0;
as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
if (!as3722)
@@ -398,6 +401,15 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
if (ret < 0)
return ret;
+ if (as3722->en_ac_ok_pwr_on)
+ val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;
+ ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,
+ AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);
+ if (ret < 0) {
+ dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);
+ return ret;
+ }
+
ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
ARRAY_SIZE(as3722_devs), NULL, 0,
regmap_irq_get_domain(as3722->irq_data));
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index d35a5fe6c950..a7b7c5423ea5 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
+ { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
@@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp202", 0 },
{ "axp209", 0 },
{ "axp221", 0 },
+ { "axp806", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 9a2ef3d9b8f8..0be511dd93d0 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
+static const struct resource axp806_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF"),
+};
+
static const struct resource axp809_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = {
{ .name = "axp20x-regulator" },
};
+static const struct mfd_cell axp806_self_working_cells[] = {
+ {
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp806_pek_resources),
+ .resources = axp806_pek_resources,
+ },
+ { .name = "axp20x-regulator" },
+};
+
static const struct mfd_cell axp806_cells[] = {
{
.id = 2,
@@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
case AXP806_ID:
- axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
- axp20x->cells = axp806_cells;
+ if (of_property_read_bool(axp20x->dev->of_node,
+ "x-powers,self-working-mode")) {
+ axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
+ axp20x->cells = axp806_self_working_cells;
+ } else {
+ axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
+ axp20x->cells = axp806_cells;
+ }
axp20x->regmap_cfg = &axp806_regmap_config;
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
break;
@@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
*/
if (axp20x->variant == AXP806_ID) {
if (of_property_read_bool(axp20x->dev->of_node,
- "x-powers,master-mode"))
+ "x-powers,master-mode") ||
+ of_property_read_bool(axp20x->dev->of_node,
+ "x-powers,self-working-mode"))
regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
else
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index 27af62ed480a..999dac752bcc 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -378,10 +378,18 @@ error:
kfree(msg);
}
+static const struct mfd_cell cros_ec_cec_cells[] = {
+ { .name = "cros-ec-cec" }
+};
+
static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc" }
};
+static const struct mfd_cell cros_usbpd_charger_cells[] = {
+ { .name = "cros-usbpd-charger" }
+};
+
static int ec_device_probe(struct platform_device *pdev)
{
int retval = -ENOMEM;
@@ -420,6 +428,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec);
+ /* Check whether this EC instance has CEC host command support */
+ if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
+ retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+ cros_ec_cec_cells,
+ ARRAY_SIZE(cros_ec_cec_cells),
+ NULL, 0, NULL);
+ if (retval)
+ dev_err(ec->dev,
+ "failed to add cros-ec-cec device: %d\n",
+ retval);
+ }
+
/* Check whether this EC instance has RTC host command support */
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
@@ -432,6 +452,18 @@ static int ec_device_probe(struct platform_device *pdev)
retval);
}
+ /* Check whether this EC instance has the PD charge manager */
+ if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) {
+ retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+ cros_usbpd_charger_cells,
+ ARRAY_SIZE(cros_usbpd_charger_cells),
+ NULL, 0, NULL);
+ if (retval)
+ dev_err(ec->dev,
+ "failed to add cros-usbpd-charger device: %d\n",
+ retval);
+ }
+
/* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1);
diff --git a/drivers/mfd/cs47l35-tables.c b/drivers/mfd/cs47l35-tables.c
new file mode 100644
index 000000000000..604c9dd14df5
--- /dev/null
+++ b/drivers/mfd/cs47l35-tables.c
@@ -0,0 +1,1609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L35 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l35_reva_16_patch[] = {
+ { 0x460, 0x0c40 },
+ { 0x461, 0xcd1a },
+ { 0x462, 0x0c40 },
+ { 0x463, 0xb53b },
+ { 0x464, 0x0c40 },
+ { 0x465, 0x7503 },
+ { 0x466, 0x0c40 },
+ { 0x467, 0x4a41 },
+ { 0x468, 0x0041 },
+ { 0x469, 0x3491 },
+ { 0x46a, 0x0841 },
+ { 0x46b, 0x1f50 },
+ { 0x46c, 0x0446 },
+ { 0x46d, 0x14ed },
+ { 0x46e, 0x0446 },
+ { 0x46f, 0x1455 },
+ { 0x470, 0x04c6 },
+ { 0x471, 0x1220 },
+ { 0x472, 0x04c6 },
+ { 0x473, 0x040f },
+ { 0x474, 0x04ce },
+ { 0x475, 0x0339 },
+ { 0x476, 0x05df },
+ { 0x477, 0x028f },
+ { 0x478, 0x05df },
+ { 0x479, 0x0209 },
+ { 0x47a, 0x05df },
+ { 0x47b, 0x00cf },
+ { 0x47c, 0x05df },
+ { 0x47d, 0x0001 },
+ { 0x47e, 0x07ff },
+};
+
+int cs47l35_patch(struct madera *madera)
+{
+ int ret;
+
+ ret = regmap_register_patch(madera->regmap, cs47l35_reva_16_patch,
+ ARRAY_SIZE(cs47l35_reva_16_patch));
+ if (ret < 0)
+ dev_err(madera->dev, "Error applying patch: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cs47l35_patch);
+
+static const struct reg_default cs47l35_reg_default[] = {
+ { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+ { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+ { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+ { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+ { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+ { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+ { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+ { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+ { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+ { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+ { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+ { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4*/
+ { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1*/
+ { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2*/
+ { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+ { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+ { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+ { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+ { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+ { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+ { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+ { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+ { 0x000000A0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+ { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+ { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+ { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+ { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+ { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+ { 0x00000120, 0x0305 }, /* R288 (0x120) - DSP Clock 1 */
+ { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+ { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+ { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+ { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+ { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+ { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+ { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+ { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+ { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+ { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+ { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+ { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+ { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+ { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+ { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+ { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+ { 0x0000017a, 0x0b06 }, /* R378 (0x17a) - FLL1 EFS2 */
+ { 0x0000017f, 0x0000 }, /* R383 (0x17f) - FLL1 Synchroniser 1 */
+ { 0x00000180, 0x0000 }, /* R384 (0x180) - FLL1 Synchroniser 2 */
+ { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 3 */
+ { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 4 */
+ { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 5 */
+ { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 6 */
+ { 0x00000185, 0x0001 }, /* R389 (0x185) - FLL1 Synchroniser 7 */
+ { 0x00000187, 0x0000 }, /* R391 (0x187) - FLL1 Spread Spectrum */
+ { 0x00000188, 0x000c }, /* R392 (0x188) - FLL1 GPIO Clock */
+ { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+ { 0x0000020b, 0x0400 }, /* R523 (0x20b) - HP Charge Pump 8 */
+ { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+ { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+ { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+ { 0x0000021c, 0x0022 }, /* R540 (0x21c) - Mic Bias Ctrl 5 */
+ { 0x0000021e, 0x0022 }, /* R542 (0x21e) - Mic Bias Ctrl 6 */
+ { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+ { 0x00000293, 0x0080 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+ { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+ { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect Control 1 */
+ { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect Control 2 */
+ { 0x000002a6, 0x3d3d }, /* R678 (0x2a6) - Mic Detect Level 1 */
+ { 0x000002a7, 0x3d3d }, /* R679 (0x2a7) - Mic Detect Level 2 */
+ { 0x000002a8, 0x333d }, /* R680 (0x2a8) - Mic Detect Level 3 */
+ { 0x000002a9, 0x202d }, /* R681 (0x2a9) - Mic Detect Level 4 */
+ { 0x000002c6, 0x0010 }, /* R710 (0x2c5) - Mic Clamp control */
+ { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+ { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+ { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+ { 0x00000308, 0x0000 }, /* R776 (0x308) - Input Rate */
+ { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+ { 0x0000030c, 0x0002 }, /* R780 (0x30c) - HPF Control */
+ { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+ { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+ { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+ { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+ { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+ { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+ { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+ { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+ { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+ { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+ { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+ { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+ { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+ { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+ { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+ { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+ { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+ { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+ { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+ { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+ { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+ { 0x00000428, 0x0000 }, /* R1064 (0x428) - Output Path Config 4L */
+ { 0x00000429, 0x0180 }, /* R1065 (0x429) - DAC Digital Volume 4L */
+ { 0x0000042b, 0x0040 }, /* R1067 (0x42b) - Noise Gate Select 4L */
+ { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+ { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+ { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+ { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+ { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+ { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+ { 0x00000440, 0x0003 }, /* R1088 (0x440) - DRE Enable */
+ { 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */
+ { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */
+ { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+ { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
+ { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
+ { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
+ { 0x000004a0, 0x3080 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+ { 0x000004a8, 0x7120 }, /* R1192 (0x4a8) - HP Test Ctrl 5 */
+ { 0x000004a9, 0x7120 }, /* R1193 (0x4a9) - HP Test Ctrl 6 */
+ { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+ { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+ { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+ { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+ { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+ { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+ { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+ { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+ { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+ { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+ { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+ { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+ { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+ { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+ { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+ { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+ { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+ { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+ { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+ { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+ { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+ { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+ { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+ { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+ { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+ { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+ { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+ { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+ { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+ { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+ { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+ { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+ { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+ { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+ { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+ { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+ { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+ { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+ { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+ { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+ { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+ { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+ { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+ { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+ { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+ { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+ { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+ { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+ { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+ { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+ { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+ { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+ { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+ { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+ { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+ { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+ { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+ { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+ { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+ { 0x000005f6, 0x0000 }, /* R1526 (0x5f6) - SLIMbus TX Channel Enable */
+ { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+ { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+ { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+ { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+ { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+ { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+ { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+ { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+ { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+ { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+ { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+ { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+ { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+ { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+ { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+ { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+ { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+ { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+ { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+ { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+ { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+ { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+ { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+ { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+ { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+ { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+ { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+ { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+ { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+ { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+ { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+ { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+ { 0x000006b0, 0x0000 }, /* R1712 (0x6b0) - OUT4LMIX Input 1 Source */
+ { 0x000006b1, 0x0080 }, /* R1713 (0x6b1) - OUT4LMIX Input 1 Volume */
+ { 0x000006b2, 0x0000 }, /* R1714 (0x6b2) - OUT4LMIX Input 2 Source */
+ { 0x000006b3, 0x0080 }, /* R1715 (0x6b3) - OUT4LMIX Input 2 Volume */
+ { 0x000006b4, 0x0000 }, /* R1716 (0x6b4) - OUT4LMIX Input 3 Source */
+ { 0x000006b5, 0x0080 }, /* R1717 (0x6b5) - OUT4LMIX Input 3 Volume */
+ { 0x000006b6, 0x0000 }, /* R1718 (0x6b6) - OUT4LMIX Input 4 Source */
+ { 0x000006b7, 0x0080 }, /* R1719 (0x6b7) - OUT4LMIX Input 4 Volume */
+ { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+ { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+ { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+ { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+ { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+ { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+ { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+ { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+ { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+ { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+ { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+ { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+ { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+ { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+ { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+ { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+ { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+ { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+ { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+ { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+ { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+ { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+ { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+ { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+ { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+ { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+ { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+ { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+ { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+ { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+ { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+ { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+ { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+ { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+ { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+ { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+ { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+ { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+ { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+ { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+ { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+ { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+ { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+ { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+ { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+ { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+ { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+ { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+ { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+ { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+ { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+ { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+ { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+ { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+ { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+ { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+ { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+ { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+ { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+ { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+ { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+ { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+ { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+ { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+ { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+ { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+ { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+ { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+ { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+ { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+ { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+ { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+ { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+ { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+ { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+ { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+ { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+ { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+ { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+ { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+ { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+ { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+ { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+ { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+ { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+ { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+ { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+ { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+ { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+ { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+ { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+ { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+ { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+ { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+ { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+ { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+ { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+ { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+ { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+ { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+ { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+ { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+ { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+ { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+ { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+ { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+ { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+ { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+ { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+ { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+ { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+ { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+ { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+ { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+ { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+ { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+ { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+ { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+ { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+ { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+ { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+ { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+ { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+ { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+ { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+ { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+ { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+ { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+ { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+ { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+ { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+ { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+ { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+ { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+ { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+ { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+ { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+ { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+ { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+ { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+ { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+ { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+ { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+ { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+ { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source*/
+ { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume*/
+ { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source*/
+ { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume*/
+ { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+ { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+ { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+ { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+ { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+ { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+ { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+ { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+ { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+ { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+ { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+ { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+ { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+ { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+ { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+ { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+ { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+ { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+ { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+ { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+ { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+ { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+ { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+ { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+ { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+ { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+ { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+ { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+ { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+ { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+ { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+ { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+ { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+ { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+ { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+ { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+ { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+ { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+ { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+ { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+ { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+ { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+ { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+ { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+ { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+ { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+ { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+ { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+ { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+ { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+ { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+ { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+ { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+ { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+ { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+ { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+ { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+ { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+ { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+ { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+ { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+ { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+ { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+ { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+ { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+ { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+ { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+ { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+ { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+ { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+ { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+ { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+ { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+ { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+ { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+ { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+ { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+ { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+ { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+ { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+ { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+ { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+ { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+ { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+ { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+ { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+ { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+ { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+ { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+ { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+ { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+ { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+ { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+ { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+ { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+ { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+ { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+ { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+ { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+ { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+ { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+ { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+ { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+ { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+ { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+ { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+ { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+ { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+ { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+ { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+ { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+ { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+ { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+ { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+ { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+ { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+ { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+ { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+ { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+ { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+ { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+ { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+ { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+ { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+ { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+ { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+ { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+ { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+ { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+ { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+ { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+ { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+ { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+ { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+ { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+ { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+ { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+ { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+ { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+ { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+ { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+ { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+ { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+ { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+ { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+ { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+ { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+ { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+ { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+ { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+ { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+ { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+ { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+ { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+ { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+ { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+ { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+ { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+ { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+ { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+ { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+ { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+ { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+ { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+ { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+ { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+ { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+ { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+ { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+ { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+ { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+ { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+ { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+ { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+ { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+ { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+ { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+ { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+ { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX Ctrl1 */
+ { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+ { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+ { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+ { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+ { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+ { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+ { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+ { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+ { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+ { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+ { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+ { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+ { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+ { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+ { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+ { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+ { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+ { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+ { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+ { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+ { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+ { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+ { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+ { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+ { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+ { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+ { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+ { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+ { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+ { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+ { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+ { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+ { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+ { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+ { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+ { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+ { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+ { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+ { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+ { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+ { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+ { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+ { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+ { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+ { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+ { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+ { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+ { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+ { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+ { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+ { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+ { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+ { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+ { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+ { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+ { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+ { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+ { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+ { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+ { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+ { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+ { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+ { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+ { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+ { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+ { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+ { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+ { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+ { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+ { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+ { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+ { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+ { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+ { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+ { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+ { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+ { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+ { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+ { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+ { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+ { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+ { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+ { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+ { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+ { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+ { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+ { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+ { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+ { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+ { 0x00000e88, 0x0018 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+ { 0x00000e89, 0x0933 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+ { 0x00000e8a, 0x0018 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+ { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+ { 0x00000e8c, 0x0000 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+ { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+ { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+ { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+ { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+ { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+ { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+ { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+ { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+ { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+ { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+ { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+ { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+ { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+ { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+ { 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
+ { 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
+ { 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+ { 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+ { 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+ { 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+ { 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+ { 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+ { 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+ { 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+ { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 4L 1 */
+ { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 4L 2 */
+ { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 4L 3 */
+ { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 4L 4 */
+ { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 5L 1 */
+ { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 5L 2 */
+ { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 5L 3 */
+ { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 5L 4 */
+ { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 5R 1 */
+ { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 5R 2 */
+ { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 5R 3 */
+ { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 5R 4 */
+ { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+ { 0x00001701, 0xf000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+ { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+ { 0x00001703, 0xf000 }, /* R5891 (0x1703) - GPIO2 Control 2 */
+ { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+ { 0x00001705, 0xf000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+ { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+ { 0x00001707, 0xf000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+ { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+ { 0x00001709, 0xf000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+ { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+ { 0x0000170b, 0xf000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+ { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+ { 0x0000170d, 0xf000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+ { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+ { 0x0000170f, 0xf000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+ { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+ { 0x00001711, 0xf000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+ { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+ { 0x00001713, 0xf000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+ { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+ { 0x00001715, 0xf000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+ { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+ { 0x00001717, 0xf000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+ { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+ { 0x00001719, 0xf000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+ { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+ { 0x0000171b, 0xf000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+ { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+ { 0x0000171d, 0xf000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+ { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+ { 0x0000171f, 0xf000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+ { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+ { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+ { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+ { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+ { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+ { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+ { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+ { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+ { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+ { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+ { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+ { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+ { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+ { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+ { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+ { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+ { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+ { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+ { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+ { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+ { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+ { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+ { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+ { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+ { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+ { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+ { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+ { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+ { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+ { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+ { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+ { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+ { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+ { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+ { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l35_is_adsp_memory(unsigned int reg)
+{
+ switch (reg) {
+ case 0x080000 ... 0x085ffe:
+ case 0x0a0000 ... 0x0a7ffe:
+ case 0x0c0000 ... 0x0c1ffe:
+ case 0x0e0000 ... 0x0e1ffe:
+ case 0x100000 ... 0x10effe:
+ case 0x120000 ... 0x12bffe:
+ case 0x136000 ... 0x137ffe:
+ case 0x140000 ... 0x14bffe:
+ case 0x160000 ... 0x161ffe:
+ case 0x180000 ... 0x18effe:
+ case 0x1a0000 ... 0x1b1ffe:
+ case 0x1b6000 ... 0x1b7ffe:
+ case 0x1c0000 ... 0x1cbffe:
+ case 0x1e0000 ... 0x1e1ffe:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l35_16bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_TONE_GENERATOR_1:
+ case MADERA_TONE_GENERATOR_2:
+ case MADERA_TONE_GENERATOR_3:
+ case MADERA_TONE_GENERATOR_4:
+ case MADERA_TONE_GENERATOR_5:
+ case MADERA_PWM_DRIVE_1:
+ case MADERA_PWM_DRIVE_2:
+ case MADERA_PWM_DRIVE_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+ case MADERA_HAPTICS_CONTROL_1:
+ case MADERA_HAPTICS_CONTROL_2:
+ case MADERA_HAPTICS_PHASE_1_INTENSITY:
+ case MADERA_HAPTICS_PHASE_1_DURATION:
+ case MADERA_HAPTICS_PHASE_2_INTENSITY:
+ case MADERA_HAPTICS_PHASE_2_DURATION:
+ case MADERA_HAPTICS_PHASE_3_INTENSITY:
+ case MADERA_HAPTICS_PHASE_3_DURATION:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_COMFORT_NOISE_GENERATOR:
+ case MADERA_CLOCK_32K_1:
+ case MADERA_SYSTEM_CLOCK_1:
+ case MADERA_SAMPLE_RATE_1:
+ case MADERA_SAMPLE_RATE_2:
+ case MADERA_SAMPLE_RATE_3:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_DSP_CLOCK_1:
+ case MADERA_DSP_CLOCK_2:
+ case MADERA_OUTPUT_SYSTEM_CLOCK:
+ case MADERA_OUTPUT_ASYNC_CLOCK:
+ case MADERA_RATE_ESTIMATOR_1:
+ case MADERA_RATE_ESTIMATOR_2:
+ case MADERA_RATE_ESTIMATOR_3:
+ case MADERA_RATE_ESTIMATOR_4:
+ case MADERA_RATE_ESTIMATOR_5:
+ case MADERA_FLL1_CONTROL_1:
+ case MADERA_FLL1_CONTROL_2:
+ case MADERA_FLL1_CONTROL_3:
+ case MADERA_FLL1_CONTROL_4:
+ case MADERA_FLL1_CONTROL_5:
+ case MADERA_FLL1_CONTROL_6:
+ case MADERA_FLL1_CONTROL_7:
+ case MADERA_FLL1_EFS_2:
+ case MADERA_FLL1_LOOP_FILTER_TEST_1:
+ case CS47L35_FLL1_SYNCHRONISER_1:
+ case CS47L35_FLL1_SYNCHRONISER_2:
+ case CS47L35_FLL1_SYNCHRONISER_3:
+ case CS47L35_FLL1_SYNCHRONISER_4:
+ case CS47L35_FLL1_SYNCHRONISER_5:
+ case CS47L35_FLL1_SYNCHRONISER_6:
+ case CS47L35_FLL1_SYNCHRONISER_7:
+ case CS47L35_FLL1_SPREAD_SPECTRUM:
+ case CS47L35_FLL1_GPIO_CLOCK:
+ case MADERA_MIC_CHARGE_PUMP_1:
+ case MADERA_HP_CHARGE_PUMP_8:
+ case MADERA_LDO2_CONTROL_1:
+ case MADERA_MIC_BIAS_CTRL_1:
+ case MADERA_MIC_BIAS_CTRL_2:
+ case MADERA_MIC_BIAS_CTRL_5:
+ case MADERA_MIC_BIAS_CTRL_6:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_DCS_HP1L_CONTROL:
+ case MADERA_DCS_HP1R_CONTROL:
+ case MADERA_EDRE_HP_STEREO_CONTROL:
+ case MADERA_ACCESSORY_DETECT_MODE_1:
+ case MADERA_HEADPHONE_DETECT_1:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_MICD_CLAMP_CONTROL:
+ case MADERA_MIC_DETECT_1_CONTROL_1:
+ case MADERA_MIC_DETECT_1_CONTROL_2:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_1:
+ case MADERA_MIC_DETECT_1_LEVEL_2:
+ case MADERA_MIC_DETECT_1_LEVEL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_4:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_GP_SWITCH_1:
+ case MADERA_JACK_DETECT_ANALOGUE:
+ case MADERA_INPUT_ENABLES:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_INPUT_RATE:
+ case MADERA_INPUT_VOLUME_RAMP:
+ case MADERA_HPF_CONTROL:
+ case MADERA_IN1L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1L:
+ case MADERA_DMIC1L_CONTROL:
+ case MADERA_IN1R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1R:
+ case MADERA_DMIC1R_CONTROL:
+ case MADERA_IN2L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2L:
+ case MADERA_DMIC2L_CONTROL:
+ case MADERA_IN2R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2R:
+ case MADERA_DMIC2R_CONTROL:
+ case MADERA_OUTPUT_ENABLES_1:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_OUTPUT_RATE_1:
+ case MADERA_OUTPUT_VOLUME_RAMP:
+ case MADERA_OUTPUT_PATH_CONFIG_1L:
+ case MADERA_DAC_DIGITAL_VOLUME_1L:
+ case MADERA_NOISE_GATE_SELECT_1L:
+ case MADERA_OUTPUT_PATH_CONFIG_1R:
+ case MADERA_DAC_DIGITAL_VOLUME_1R:
+ case MADERA_NOISE_GATE_SELECT_1R:
+ case MADERA_OUTPUT_PATH_CONFIG_4L:
+ case MADERA_DAC_DIGITAL_VOLUME_4L:
+ case MADERA_NOISE_GATE_SELECT_4L:
+ case MADERA_OUTPUT_PATH_CONFIG_5L:
+ case MADERA_DAC_DIGITAL_VOLUME_5L:
+ case MADERA_NOISE_GATE_SELECT_5L:
+ case MADERA_OUTPUT_PATH_CONFIG_5R:
+ case MADERA_DAC_DIGITAL_VOLUME_5R:
+ case MADERA_NOISE_GATE_SELECT_5R:
+ case MADERA_DRE_ENABLE:
+ case MADERA_EDRE_ENABLE:
+ case MADERA_EDRE_MANUAL:
+ case MADERA_DAC_AEC_CONTROL_1:
+ case MADERA_NOISE_GATE_CONTROL:
+ case MADERA_PDM_SPK1_CTRL_1:
+ case MADERA_PDM_SPK1_CTRL_2:
+ case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP_TEST_CTRL_5:
+ case MADERA_HP_TEST_CTRL_6:
+ case MADERA_AIF1_BCLK_CTRL:
+ case MADERA_AIF1_TX_PIN_CTRL:
+ case MADERA_AIF1_RX_PIN_CTRL:
+ case MADERA_AIF1_RATE_CTRL:
+ case MADERA_AIF1_FORMAT:
+ case MADERA_AIF1_RX_BCLK_RATE:
+ case MADERA_AIF1_FRAME_CTRL_1:
+ case MADERA_AIF1_FRAME_CTRL_2:
+ case MADERA_AIF1_FRAME_CTRL_3:
+ case MADERA_AIF1_FRAME_CTRL_4:
+ case MADERA_AIF1_FRAME_CTRL_5:
+ case MADERA_AIF1_FRAME_CTRL_6:
+ case MADERA_AIF1_FRAME_CTRL_7:
+ case MADERA_AIF1_FRAME_CTRL_8:
+ case MADERA_AIF1_FRAME_CTRL_11:
+ case MADERA_AIF1_FRAME_CTRL_12:
+ case MADERA_AIF1_FRAME_CTRL_13:
+ case MADERA_AIF1_FRAME_CTRL_14:
+ case MADERA_AIF1_FRAME_CTRL_15:
+ case MADERA_AIF1_FRAME_CTRL_16:
+ case MADERA_AIF1_TX_ENABLES:
+ case MADERA_AIF1_RX_ENABLES:
+ case MADERA_AIF2_BCLK_CTRL:
+ case MADERA_AIF2_TX_PIN_CTRL:
+ case MADERA_AIF2_RX_PIN_CTRL:
+ case MADERA_AIF2_RATE_CTRL:
+ case MADERA_AIF2_FORMAT:
+ case MADERA_AIF2_RX_BCLK_RATE:
+ case MADERA_AIF2_FRAME_CTRL_1:
+ case MADERA_AIF2_FRAME_CTRL_2:
+ case MADERA_AIF2_FRAME_CTRL_3:
+ case MADERA_AIF2_FRAME_CTRL_4:
+ case MADERA_AIF2_FRAME_CTRL_11:
+ case MADERA_AIF2_FRAME_CTRL_12:
+ case MADERA_AIF2_TX_ENABLES:
+ case MADERA_AIF2_RX_ENABLES:
+ case MADERA_AIF3_BCLK_CTRL:
+ case MADERA_AIF3_TX_PIN_CTRL:
+ case MADERA_AIF3_RX_PIN_CTRL:
+ case MADERA_AIF3_RATE_CTRL:
+ case MADERA_AIF3_FORMAT:
+ case MADERA_AIF3_RX_BCLK_RATE:
+ case MADERA_AIF3_FRAME_CTRL_1:
+ case MADERA_AIF3_FRAME_CTRL_2:
+ case MADERA_AIF3_FRAME_CTRL_3:
+ case MADERA_AIF3_FRAME_CTRL_4:
+ case MADERA_AIF3_FRAME_CTRL_11:
+ case MADERA_AIF3_FRAME_CTRL_12:
+ case MADERA_AIF3_TX_ENABLES:
+ case MADERA_AIF3_RX_ENABLES:
+ case MADERA_SPD1_TX_CONTROL:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+ case MADERA_SLIMBUS_RATES_1:
+ case MADERA_SLIMBUS_RATES_2:
+ case MADERA_SLIMBUS_RATES_3:
+ case MADERA_SLIMBUS_RATES_5:
+ case MADERA_SLIMBUS_RATES_6:
+ case MADERA_SLIMBUS_RATES_7:
+ case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_PWM1MIX_INPUT_1_SOURCE:
+ case MADERA_PWM1MIX_INPUT_1_VOLUME:
+ case MADERA_PWM1MIX_INPUT_2_SOURCE:
+ case MADERA_PWM1MIX_INPUT_2_VOLUME:
+ case MADERA_PWM1MIX_INPUT_3_SOURCE:
+ case MADERA_PWM1MIX_INPUT_3_VOLUME:
+ case MADERA_PWM1MIX_INPUT_4_SOURCE:
+ case MADERA_PWM1MIX_INPUT_4_VOLUME:
+ case MADERA_PWM2MIX_INPUT_1_SOURCE:
+ case MADERA_PWM2MIX_INPUT_1_VOLUME:
+ case MADERA_PWM2MIX_INPUT_2_SOURCE:
+ case MADERA_PWM2MIX_INPUT_2_VOLUME:
+ case MADERA_PWM2MIX_INPUT_3_SOURCE:
+ case MADERA_PWM2MIX_INPUT_3_VOLUME:
+ case MADERA_PWM2MIX_INPUT_4_SOURCE:
+ case MADERA_PWM2MIX_INPUT_4_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_1_SOURCE:
+ case MADERA_EQ1MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_2_SOURCE:
+ case MADERA_EQ1MIX_INPUT_2_VOLUME:
+ case MADERA_EQ1MIX_INPUT_3_SOURCE:
+ case MADERA_EQ1MIX_INPUT_3_VOLUME:
+ case MADERA_EQ1MIX_INPUT_4_SOURCE:
+ case MADERA_EQ1MIX_INPUT_4_VOLUME:
+ case MADERA_EQ2MIX_INPUT_1_SOURCE:
+ case MADERA_EQ2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ2MIX_INPUT_2_SOURCE:
+ case MADERA_EQ2MIX_INPUT_2_VOLUME:
+ case MADERA_EQ2MIX_INPUT_3_SOURCE:
+ case MADERA_EQ2MIX_INPUT_3_VOLUME:
+ case MADERA_EQ2MIX_INPUT_4_SOURCE:
+ case MADERA_EQ2MIX_INPUT_4_VOLUME:
+ case MADERA_EQ3MIX_INPUT_1_SOURCE:
+ case MADERA_EQ3MIX_INPUT_1_VOLUME:
+ case MADERA_EQ3MIX_INPUT_2_SOURCE:
+ case MADERA_EQ3MIX_INPUT_2_VOLUME:
+ case MADERA_EQ3MIX_INPUT_3_SOURCE:
+ case MADERA_EQ3MIX_INPUT_3_VOLUME:
+ case MADERA_EQ3MIX_INPUT_4_SOURCE:
+ case MADERA_EQ3MIX_INPUT_4_VOLUME:
+ case MADERA_EQ4MIX_INPUT_1_SOURCE:
+ case MADERA_EQ4MIX_INPUT_1_VOLUME:
+ case MADERA_EQ4MIX_INPUT_2_SOURCE:
+ case MADERA_EQ4MIX_INPUT_2_VOLUME:
+ case MADERA_EQ4MIX_INPUT_3_SOURCE:
+ case MADERA_EQ4MIX_INPUT_3_VOLUME:
+ case MADERA_EQ4MIX_INPUT_4_SOURCE:
+ case MADERA_EQ4MIX_INPUT_4_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+ case MADERA_FX_CTRL1:
+ case MADERA_FX_CTRL2:
+ case MADERA_EQ1_1 ... MADERA_EQ1_21:
+ case MADERA_EQ2_1 ... MADERA_EQ2_21:
+ case MADERA_EQ3_1 ... MADERA_EQ3_21:
+ case MADERA_EQ4_1 ... MADERA_EQ4_21:
+ case MADERA_DRC1_CTRL1:
+ case MADERA_DRC1_CTRL2:
+ case MADERA_DRC1_CTRL3:
+ case MADERA_DRC1_CTRL4:
+ case MADERA_DRC1_CTRL5:
+ case MADERA_DRC2_CTRL1:
+ case MADERA_DRC2_CTRL2:
+ case MADERA_DRC2_CTRL3:
+ case MADERA_DRC2_CTRL4:
+ case MADERA_DRC2_CTRL5:
+ case MADERA_HPLPF1_1:
+ case MADERA_HPLPF1_2:
+ case MADERA_HPLPF2_1:
+ case MADERA_HPLPF2_2:
+ case MADERA_HPLPF3_1:
+ case MADERA_HPLPF3_2:
+ case MADERA_HPLPF4_1:
+ case MADERA_HPLPF4_2:
+ case MADERA_ISRC_1_CTRL_1:
+ case MADERA_ISRC_1_CTRL_2:
+ case MADERA_ISRC_1_CTRL_3:
+ case MADERA_ISRC_2_CTRL_1:
+ case MADERA_ISRC_2_CTRL_2:
+ case MADERA_ISRC_2_CTRL_3:
+ case MADERA_DAC_COMP_1:
+ case MADERA_DAC_COMP_2:
+ case MADERA_FRF_COEFFICIENT_1L_1:
+ case MADERA_FRF_COEFFICIENT_1L_2:
+ case MADERA_FRF_COEFFICIENT_1L_3:
+ case MADERA_FRF_COEFFICIENT_1L_4:
+ case MADERA_FRF_COEFFICIENT_1R_1:
+ case MADERA_FRF_COEFFICIENT_1R_2:
+ case MADERA_FRF_COEFFICIENT_1R_3:
+ case MADERA_FRF_COEFFICIENT_1R_4:
+ case CS47L35_FRF_COEFFICIENT_4L_1:
+ case CS47L35_FRF_COEFFICIENT_4L_2:
+ case CS47L35_FRF_COEFFICIENT_4L_3:
+ case CS47L35_FRF_COEFFICIENT_4L_4:
+ case CS47L35_FRF_COEFFICIENT_5L_1:
+ case CS47L35_FRF_COEFFICIENT_5L_2:
+ case CS47L35_FRF_COEFFICIENT_5L_3:
+ case CS47L35_FRF_COEFFICIENT_5L_4:
+ case CS47L35_FRF_COEFFICIENT_5R_1:
+ case CS47L35_FRF_COEFFICIENT_5R_2:
+ case CS47L35_FRF_COEFFICIENT_5R_3:
+ case CS47L35_FRF_COEFFICIENT_5R_4:
+ case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO16_CTRL_2:
+ case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ case MADERA_INTERRUPT_DEBOUNCE_7:
+ case MADERA_IRQ1_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l35_16bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_DCS_HP1L_CONTROL:
+ case MADERA_DCS_HP1R_CONTROL:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_FX_CTRL2:
+ case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l35_32bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_252:
+ case CS47L35_OTP_HPDET_CAL_1 ... CS47L35_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+ return true;
+ default:
+ return cs47l35_is_adsp_memory(reg);
+ }
+}
+
+static bool cs47l35_32bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_252:
+ case CS47L35_OTP_HPDET_CAL_1 ... CS47L35_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+ return true;
+ default:
+ return cs47l35_is_adsp_memory(reg);
+ }
+}
+
+const struct regmap_config cs47l35_16bit_spi_regmap = {
+ .name = "cs47l35_16bit",
+ .reg_bits = 32,
+ .pad_bits = 16,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = 0x1b00,
+ .readable_reg = cs47l35_16bit_readable_register,
+ .volatile_reg = cs47l35_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l35_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l35_16bit_spi_regmap);
+
+const struct regmap_config cs47l35_16bit_i2c_regmap = {
+ .name = "cs47l35_16bit",
+ .reg_bits = 32,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = 0x1b00,
+ .readable_reg = cs47l35_16bit_readable_register,
+ .volatile_reg = cs47l35_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l35_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l35_16bit_i2c_regmap);
+
+const struct regmap_config cs47l35_32bit_spi_regmap = {
+ .name = "cs47l35_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .pad_bits = 16,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP3_SCRATCH_2,
+ .readable_reg = cs47l35_32bit_readable_register,
+ .volatile_reg = cs47l35_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l35_32bit_spi_regmap);
+
+const struct regmap_config cs47l35_32bit_i2c_regmap = {
+ .name = "cs47l35_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP3_SCRATCH_2,
+ .readable_reg = cs47l35_32bit_readable_register,
+ .volatile_reg = cs47l35_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l35_32bit_i2c_regmap);
diff --git a/drivers/mfd/cs47l85-tables.c b/drivers/mfd/cs47l85-tables.c
new file mode 100644
index 000000000000..43803145d8e5
--- /dev/null
+++ b/drivers/mfd/cs47l85-tables.c
@@ -0,0 +1,3009 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L85 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l85_reva_16_patch[] = {
+ { 0x80, 0x0003 },
+ { 0x213, 0x03E4 },
+ { 0x177, 0x0281 },
+ { 0x197, 0x0281 },
+ { 0x1B7, 0x0281 },
+ { 0x4B1, 0x010A },
+ { 0x4CF, 0x0933 },
+ { 0x36C, 0x011B },
+ { 0x4B8, 0x1120 },
+ { 0x4A0, 0x3280 },
+ { 0x4A1, 0x3200 },
+ { 0x4A2, 0x3200 },
+ { 0x441, 0xC050 },
+ { 0x4A4, 0x000B },
+ { 0x4A5, 0x000B },
+ { 0x4A6, 0x000B },
+ { 0x4E2, 0x1E1D },
+ { 0x4E3, 0x1E1D },
+ { 0x4E4, 0x1E1D },
+ { 0x293, 0x0080 },
+ { 0x17D, 0x0303 },
+ { 0x19D, 0x0303 },
+ { 0x27E, 0x0000 },
+ { 0x80, 0x0000 },
+ { 0x80, 0x0000 },
+ { 0x448, 0x003f },
+};
+
+static const struct reg_sequence cs47l85_revc_16_patch[] = {
+ { 0x27E, 0x0000 },
+ { 0x2C2, 0x0005 },
+ { 0x448, 0x003f },
+};
+
+static const struct reg_sequence cs47l85_reva_32_patch[] = {
+ { 0x3000, 0xC2253632 },
+ { 0x3002, 0xC2300001 },
+ { 0x3004, 0x8225100E },
+ { 0x3006, 0x22251803 },
+ { 0x3008, 0x82310B00 },
+ { 0x300A, 0xE231023B },
+ { 0x300C, 0x02313B01 },
+ { 0x300E, 0x62300000 },
+ { 0x3010, 0xE2314288 },
+ { 0x3012, 0x02310B00 },
+ { 0x3014, 0x02310B00 },
+ { 0x3016, 0x04050100 },
+ { 0x3018, 0x42310C02 },
+ { 0x301A, 0xE2310227 },
+ { 0x301C, 0x02313B01 },
+ { 0x301E, 0xE2314266 },
+ { 0x3020, 0xE2315294 },
+ { 0x3022, 0x02310B00 },
+ { 0x3024, 0x02310B00 },
+ { 0x3026, 0x02251100 },
+ { 0x3028, 0x02251401 },
+ { 0x302A, 0x02250200 },
+ { 0x302C, 0x02251001 },
+ { 0x302E, 0x02250200 },
+ { 0x3030, 0xE2310266 },
+ { 0x3032, 0x82314B15 },
+ { 0x3034, 0x82310B15 },
+ { 0x3036, 0xE2315294 },
+ { 0x3038, 0x02310B00 },
+ { 0x303A, 0x8225160D },
+ { 0x303C, 0x0225F501 },
+ { 0x303E, 0x8225061C },
+ { 0x3040, 0x02251000 },
+ { 0x3042, 0x04051101 },
+ { 0x3044, 0x02251800 },
+ { 0x3046, 0x42251203 },
+ { 0x3048, 0x02251101 },
+ { 0x304A, 0xC2251300 },
+ { 0x304C, 0x2225FB02 },
+ { 0x3050, 0xC2263632 },
+ { 0x3052, 0xC2300001 },
+ { 0x3054, 0x8226100E },
+ { 0x3056, 0x22261803 },
+ { 0x3058, 0x82310B02 },
+ { 0x305A, 0xE231023B },
+ { 0x305C, 0x02313B01 },
+ { 0x305E, 0x62300000 },
+ { 0x3060, 0xE2314288 },
+ { 0x3062, 0x02310B00 },
+ { 0x3064, 0x02310B00 },
+ { 0x3066, 0x04050000 },
+ { 0x3068, 0x42310C03 },
+ { 0x306A, 0xE2310227 },
+ { 0x306C, 0x02313B01 },
+ { 0x306E, 0xE2314266 },
+ { 0x3070, 0xE2315294 },
+ { 0x3072, 0x02310B00 },
+ { 0x3074, 0x02310B00 },
+ { 0x3076, 0x02261100 },
+ { 0x3078, 0x02261401 },
+ { 0x307A, 0x02260200 },
+ { 0x307C, 0x02261001 },
+ { 0x307E, 0x02260200 },
+ { 0x3080, 0xE2310266 },
+ { 0x3082, 0x82314B17 },
+ { 0x3084, 0x82310B17 },
+ { 0x3086, 0xE2315294 },
+ { 0x3088, 0x02310B00 },
+ { 0x308A, 0x8226160D },
+ { 0x308C, 0x0226F501 },
+ { 0x308E, 0x8226061C },
+ { 0x3090, 0x02261000 },
+ { 0x3092, 0x04051101 },
+ { 0x3094, 0x02261800 },
+ { 0x3096, 0x42261203 },
+ { 0x3098, 0x02261101 },
+ { 0x309A, 0xC2261300 },
+ { 0x309C, 0x2226FB02 },
+ { 0x309E, 0x0000F000 },
+ { 0x30A0, 0xC2273632 },
+ { 0x30A2, 0xC2400001 },
+ { 0x30A4, 0x8227100E },
+ { 0x30A6, 0x22271803 },
+ { 0x30A8, 0x82410B00 },
+ { 0x30AA, 0xE241023B },
+ { 0x30AC, 0x02413B01 },
+ { 0x30AE, 0x62400000 },
+ { 0x30B0, 0xE2414288 },
+ { 0x30B2, 0x02410B00 },
+ { 0x30B4, 0x02410B00 },
+ { 0x30B6, 0x04050300 },
+ { 0x30B8, 0x42410C02 },
+ { 0x30BA, 0xE2410227 },
+ { 0x30BC, 0x02413B01 },
+ { 0x30BE, 0xE2414266 },
+ { 0x30C0, 0xE2415294 },
+ { 0x30C2, 0x02410B00 },
+ { 0x30C4, 0x02410B00 },
+ { 0x30C6, 0x02271100 },
+ { 0x30C8, 0x02271401 },
+ { 0x30CA, 0x02270200 },
+ { 0x30CC, 0x02271001 },
+ { 0x30CE, 0x02270200 },
+ { 0x30D0, 0xE2410266 },
+ { 0x30D2, 0x82414B15 },
+ { 0x30D4, 0x82410B15 },
+ { 0x30D6, 0xE2415294 },
+ { 0x30D8, 0x02410B00 },
+ { 0x30DA, 0x8227160D },
+ { 0x30DC, 0x0227F501 },
+ { 0x30DE, 0x8227061C },
+ { 0x30E0, 0x02271000 },
+ { 0x30E2, 0x04051101 },
+ { 0x30E4, 0x02271800 },
+ { 0x30E6, 0x42271203 },
+ { 0x30E8, 0x02271101 },
+ { 0x30EA, 0xC2271300 },
+ { 0x30EC, 0x2227FB02 },
+ { 0x30F0, 0xC2283632 },
+ { 0x30F2, 0xC2400001 },
+ { 0x30F4, 0x8228100E },
+ { 0x30F6, 0x22281803 },
+ { 0x30F8, 0x82410B02 },
+ { 0x30FA, 0xE241023B },
+ { 0x30FC, 0x02413B01 },
+ { 0x30FE, 0x62400000 },
+ { 0x3100, 0xE2414288 },
+ { 0x3102, 0x02410B00 },
+ { 0x3104, 0x02410B00 },
+ { 0x3106, 0x04050200 },
+ { 0x3108, 0x42410C03 },
+ { 0x310A, 0xE2410227 },
+ { 0x310C, 0x02413B01 },
+ { 0x310E, 0xE2414266 },
+ { 0x3110, 0xE2415294 },
+ { 0x3112, 0x02410B00 },
+ { 0x3114, 0x02410B00 },
+ { 0x3116, 0x02281100 },
+ { 0x3118, 0x02281401 },
+ { 0x311A, 0x02280200 },
+ { 0x311C, 0x02281001 },
+ { 0x311E, 0x02280200 },
+ { 0x3120, 0xE2410266 },
+ { 0x3122, 0x82414B17 },
+ { 0x3124, 0x82410B17 },
+ { 0x3126, 0xE2415294 },
+ { 0x3128, 0x02410B00 },
+ { 0x312A, 0x8228160D },
+ { 0x312C, 0x0228F501 },
+ { 0x312E, 0x8228061C },
+ { 0x3130, 0x02281000 },
+ { 0x3132, 0x04051101 },
+ { 0x3134, 0x02281800 },
+ { 0x3136, 0x42281203 },
+ { 0x3138, 0x02281101 },
+ { 0x313A, 0xC2281300 },
+ { 0x313C, 0x2228FB02 },
+ { 0x3140, 0xC2293632 },
+ { 0x3142, 0xC2500001 },
+ { 0x3144, 0x8229100E },
+ { 0x3146, 0x22291803 },
+ { 0x3148, 0x82510B00 },
+ { 0x314A, 0xE251023B },
+ { 0x314C, 0x02513B01 },
+ { 0x314E, 0x62500000 },
+ { 0x3150, 0xE2514288 },
+ { 0x3152, 0x02510B00 },
+ { 0x3154, 0x02510B00 },
+ { 0x3156, 0x04050500 },
+ { 0x3158, 0x42510C02 },
+ { 0x315A, 0xE2510227 },
+ { 0x315C, 0x02513B01 },
+ { 0x315E, 0xE2514266 },
+ { 0x3160, 0xE2515294 },
+ { 0x3162, 0x02510B00 },
+ { 0x3164, 0x02510B00 },
+ { 0x3166, 0x02291100 },
+ { 0x3168, 0x02291401 },
+ { 0x316A, 0x02290200 },
+ { 0x316C, 0x02291001 },
+ { 0x316E, 0x02290200 },
+ { 0x3170, 0xE2510266 },
+ { 0x3172, 0x82514B15 },
+ { 0x3174, 0x82510B15 },
+ { 0x3176, 0xE2515294 },
+ { 0x3178, 0x02510B00 },
+ { 0x317A, 0x8229160D },
+ { 0x317C, 0x0229F501 },
+ { 0x317E, 0x8229061C },
+ { 0x3180, 0x02291000 },
+ { 0x3182, 0x04051101 },
+ { 0x3184, 0x02291800 },
+ { 0x3186, 0x42291203 },
+ { 0x3188, 0x02291101 },
+ { 0x318A, 0xC2291300 },
+ { 0x318C, 0x2229FB02 },
+ { 0x3190, 0xC22A3632 },
+ { 0x3192, 0xC2500001 },
+ { 0x3194, 0x822A100E },
+ { 0x3196, 0x222A1803 },
+ { 0x3198, 0x82510B02 },
+ { 0x319A, 0xE251023B },
+ { 0x319C, 0x02513B01 },
+ { 0x319E, 0x62500000 },
+ { 0x31A0, 0xE2514288 },
+ { 0x31A2, 0x02510B00 },
+ { 0x31A4, 0x02510B00 },
+ { 0x31A6, 0x04050400 },
+ { 0x31A8, 0x42510C03 },
+ { 0x31AA, 0xE2510227 },
+ { 0x31AC, 0x02513B01 },
+ { 0x31AE, 0xE2514266 },
+ { 0x31B0, 0xE2515294 },
+ { 0x31B2, 0x02510B00 },
+ { 0x31B4, 0x02510B00 },
+ { 0x31B6, 0x022A1100 },
+ { 0x31B8, 0x022A1401 },
+ { 0x31BA, 0x022A0200 },
+ { 0x31BC, 0x022A1001 },
+ { 0x31BE, 0x022A0200 },
+ { 0x31C0, 0xE2510266 },
+ { 0x31C2, 0x82514B17 },
+ { 0x31C4, 0x82510B17 },
+ { 0x31C6, 0xE2515294 },
+ { 0x31C8, 0x02510B00 },
+ { 0x31CA, 0x822A160D },
+ { 0x31CC, 0x022AF501 },
+ { 0x31CE, 0x822A061C },
+ { 0x31D0, 0x022A1000 },
+ { 0x31D2, 0x04051101 },
+ { 0x31D4, 0x022A1800 },
+ { 0x31D6, 0x422A1203 },
+ { 0x31D8, 0x022A1101 },
+ { 0x31DA, 0xC22A1300 },
+ { 0x31DC, 0x222AFB02 },
+};
+
+static const struct reg_sequence cs47l85_revc_32_patch[] = {
+ { 0x3380, 0xE4103066 },
+ { 0x3382, 0xE4103070 },
+ { 0x3384, 0xE4103078 },
+ { 0x3386, 0xE4103080 },
+ { 0x3388, 0xE410F080 },
+ { 0x338A, 0xE4143066 },
+ { 0x338C, 0xE4143070 },
+ { 0x338E, 0xE4143078 },
+ { 0x3390, 0xE4143080 },
+ { 0x3392, 0xE414F080 },
+ { 0x3394, 0xE4103078 },
+ { 0x3396, 0xE4103070 },
+ { 0x3398, 0xE4103066 },
+ { 0x339A, 0xE410F056 },
+ { 0x339C, 0xE4143078 },
+ { 0x339E, 0xE4143070 },
+ { 0x33A0, 0xE4143066 },
+ { 0x33A2, 0xE414F056 },
+};
+
+int cs47l85_patch(struct madera *madera)
+{
+ int ret = 0;
+ const struct reg_sequence *patch16;
+ const struct reg_sequence *patch32;
+ unsigned int num16, num32;
+
+ switch (madera->rev) {
+ case 0:
+ case 1:
+ patch16 = cs47l85_reva_16_patch;
+ num16 = ARRAY_SIZE(cs47l85_reva_16_patch);
+
+ patch32 = cs47l85_reva_32_patch;
+ num32 = ARRAY_SIZE(cs47l85_reva_32_patch);
+ break;
+ default:
+ patch16 = cs47l85_revc_16_patch;
+ num16 = ARRAY_SIZE(cs47l85_revc_16_patch);
+
+ patch32 = cs47l85_revc_32_patch;
+ num32 = ARRAY_SIZE(cs47l85_revc_32_patch);
+ break;
+ }
+
+ ret = regmap_register_patch(madera->regmap, patch16, num16);
+ if (ret < 0) {
+ dev_err(madera->dev,
+ "Error in applying 16-bit patch: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_register_patch(madera->regmap_32bit, patch32, num32);
+ if (ret < 0) {
+ dev_err(madera->dev,
+ "Error in applying 32-bit patch: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cs47l85_patch);
+
+static const struct reg_default cs47l85_reg_default[] = {
+ { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+ { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+ { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+ { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+ { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+ { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+ { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+ { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+ { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+ { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+ { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+ { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4 */
+ { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1*/
+ { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2*/
+ { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+ { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+ { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+ { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+ { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+ { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+ { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+ { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+ { 0x000000a0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+ { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+ { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+ { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+ { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+ { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+ { 0x00000112, 0x0305 }, /* R274 (0x112) - Async clock 1 */
+ { 0x00000113, 0x0011 }, /* R275 (0x113) - Async sample rate 1 */
+ { 0x00000114, 0x0011 }, /* R276 (0x114) - Async sample rate 2 */
+ { 0x00000120, 0x0305 }, /* R288 (0x120) - DSP Clock 1 */
+ { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+ { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+ { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+ { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+ { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+ { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+ { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+ { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+ { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+ { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+ { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+ { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+ { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+ { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+ { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+ { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+ { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
+ { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 2 */
+ { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 3 */
+ { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 4 */
+ { 0x00000185, 0x0000 }, /* R389 (0x185) - FLL1 Synchroniser 5 */
+ { 0x00000186, 0x0000 }, /* R390 (0x186) - FLL1 Synchroniser 6 */
+ { 0x00000187, 0x0001 }, /* R391 (0x187) - FLL1 Synchroniser 7 */
+ { 0x00000189, 0x0000 }, /* R393 (0x189) - FLL1 Spread Spectrum */
+ { 0x0000018a, 0x000c }, /* R394 (0x18a) - FLL1 GPIO Clock */
+ { 0x00000191, 0x0002 }, /* R401 (0x191) - FLL2 Control 1 */
+ { 0x00000192, 0x0008 }, /* R402 (0x192) - FLL2 Control 2 */
+ { 0x00000193, 0x0018 }, /* R403 (0x193) - FLL2 Control 3 */
+ { 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
+ { 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
+ { 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
+ { 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
+ { 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
+ { 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
+ { 0x000001a2, 0x0000 }, /* R418 (0x1a2) - FLL2 Synchroniser 2 */
+ { 0x000001a3, 0x0000 }, /* R419 (0x1a3) - FLL2 Synchroniser 3 */
+ { 0x000001a4, 0x0000 }, /* R420 (0x1a4) - FLL2 Synchroniser 4 */
+ { 0x000001a5, 0x0000 }, /* R421 (0x1a5) - FLL2 Synchroniser 5 */
+ { 0x000001a6, 0x0000 }, /* R422 (0x1a6) - FLL2 Synchroniser 6 */
+ { 0x000001a7, 0x0001 }, /* R423 (0x1a7) - FLL2 Synchroniser 7 */
+ { 0x000001a9, 0x0000 }, /* R425 (0x1a9) - FLL2 Spread Spectrum */
+ { 0x000001aa, 0x000c }, /* R426 (0x1aa) - FLL2 GPIO Clock */
+ { 0x000001b1, 0x0002 }, /* R433 (0x1b1) - FLL3 Control 1 */
+ { 0x000001b2, 0x0008 }, /* R434 (0x1b2) - FLL3 Control 2 */
+ { 0x000001b3, 0x0018 }, /* R435 (0x1b3) - FLL3 Control 3 */
+ { 0x000001b4, 0x007d }, /* R436 (0x1b4) - FLL3 Control 4 */
+ { 0x000001b5, 0x0000 }, /* R437 (0x1b5) - FLL3 Control 5 */
+ { 0x000001b6, 0x0000 }, /* R438 (0x1b6) - FLL3 Control 6 */
+ { 0x000001b7, 0x0281 }, /* R439 (0x1b7) - FLL3 Loop Filter Test 1 */
+ { 0x000001b9, 0x0000 }, /* R441 (0x1b9) - FLL3 Control 7 */
+ { 0x000001c1, 0x0000 }, /* R449 (0x1c1) - FLL3 Synchroniser 1 */
+ { 0x000001c2, 0x0000 }, /* R450 (0x1c2) - FLL3 Synchroniser 2 */
+ { 0x000001c3, 0x0000 }, /* R451 (0x1c3) - FLL3 Synchroniser 3 */
+ { 0x000001c4, 0x0000 }, /* R452 (0x1c4) - FLL3 Synchroniser 4 */
+ { 0x000001c5, 0x0000 }, /* R453 (0x1c5) - FLL3 Synchroniser 5 */
+ { 0x000001c6, 0x0000 }, /* R454 (0x1c6) - FLL3 Synchroniser 6 */
+ { 0x000001c7, 0x0001 }, /* R455 (0x1c7) - FLL3 Synchroniser 7 */
+ { 0x000001c9, 0x0000 }, /* R457 (0x1c9) - FLL3 Spread Spectrum */
+ { 0x000001ca, 0x000C }, /* R458 (0x1ca) - FLL3 GPIO Clock */
+ { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+ { 0x0000020b, 0x0400 }, /* R523 (0x20B) - HP Charge Pump 8 */
+ { 0x00000210, 0x0184 }, /* R528 (0x210) - LDO1 Control 1 */
+ { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+ { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+ { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+ { 0x0000021a, 0x00e6 }, /* R538 (0x21a) - Mic Bias Ctrl 3 */
+ { 0x0000021b, 0x00e6 }, /* R539 (0x21b) - Mic Bias Ctrl 4 */
+ { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+ { 0x00000293, 0x0000 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+ { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+ { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect Control 1 */
+ { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect Control 2 */
+ { 0x000002a6, 0x3737 }, /* R678 (0x2a6) - Mic Detect Level 1 */
+ { 0x000002a7, 0x2c37 }, /* R679 (0x2a7) - Mic Detect Level 2 */
+ { 0x000002a8, 0x1422 }, /* R680 (0x2a8) - Mic Detect Level 3 */
+ { 0x000002a9, 0x030a }, /* R681 (0x2a9) - Mic Detect Level 4 */
+ { 0x000002c6, 0x0010 }, /* R710 (0x2c6) - Mic Clamp control */
+ { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+ { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+ { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+ { 0x00000308, 0x0000 }, /* R776 (0x308) - Input Rate */
+ { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+ { 0x0000030c, 0x0002 }, /* R780 (0x30c) - HPF Control */
+ { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+ { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+ { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+ { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+ { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+ { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+ { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+ { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+ { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+ { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+ { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+ { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+ { 0x00000320, 0x0080 }, /* R800 (0x320) - IN3L Control */
+ { 0x00000321, 0x0180 }, /* R801 (0x321) - ADC Digital Volume 3L */
+ { 0x00000322, 0x0500 }, /* R802 (0x322) - DMIC3L Control */
+ { 0x00000324, 0x0080 }, /* R804 (0x324) - IN3R Control */
+ { 0x00000325, 0x0180 }, /* R805 (0x325) - ADC Digital Volume 3R */
+ { 0x00000326, 0x0000 }, /* R806 (0x326) - DMIC3R Control */
+ { 0x00000328, 0x0000 }, /* R808 (0x328) - IN4 Control */
+ { 0x00000329, 0x0180 }, /* R809 (0x329) - ADC Digital Volume 4L */
+ { 0x0000032a, 0x0500 }, /* R810 (0x32a) - DMIC4L Control */
+ { 0x0000032c, 0x0000 }, /* R812 (0x32c) - IN4R Control */
+ { 0x0000032d, 0x0180 }, /* R813 (0x32d) - ADC Digital Volume 4R */
+ { 0x0000032e, 0x0000 }, /* R814 (0x32e) - DMIC4R Control */
+ { 0x00000330, 0x0000 }, /* R816 (0x330) - IN5L Control */
+ { 0x00000331, 0x0180 }, /* R817 (0x331) - ADC Digital Volume 5L */
+ { 0x00000332, 0x0500 }, /* R818 (0x332) - DMIC5L Control */
+ { 0x00000334, 0x0000 }, /* R820 (0x334) - IN5R Control */
+ { 0x00000335, 0x0180 }, /* R821 (0x335) - ADC Digital Volume 5R */
+ { 0x00000336, 0x0000 }, /* R822 (0x336) - DMIC5R Control */
+ { 0x00000338, 0x0000 }, /* R824 (0x338) - IN6L Control */
+ { 0x00000339, 0x0180 }, /* R825 (0x339) - ADC Digital Volume 6L */
+ { 0x0000033a, 0x0500 }, /* R826 (0x33a) - DMIC6L Control */
+ { 0x0000033c, 0x0000 }, /* R828 (0x33c) - IN6R Control */
+ { 0x0000033d, 0x0180 }, /* R829 (0x33d) - ADC Digital Volume 6R */
+ { 0x0000033e, 0x0000 }, /* R830 (0x33e) - DMIC6R Control */
+ { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+ { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+ { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+ { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+ { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+ { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+ { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+ { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+ { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+ { 0x00000418, 0x0080 }, /* R1048 (0x418) - Output Path Config 2L */
+ { 0x00000419, 0x0180 }, /* R1049 (0x419) - DAC Digital Volume 2L */
+ { 0x0000041b, 0x0004 }, /* R1051 (0x41b) - Noise Gate Select 2L */
+ { 0x0000041c, 0x0080 }, /* R1052 (0x41c) - Output Path Config 2R */
+ { 0x0000041d, 0x0180 }, /* R1053 (0x41d) - DAC Digital Volume 2R */
+ { 0x0000041f, 0x0008 }, /* R1055 (0x41f) - Noise Gate Select 2R */
+ { 0x00000420, 0x0080 }, /* R1056 (0x420) - Output Path Config 3L */
+ { 0x00000421, 0x0180 }, /* R1057 (0x421) - DAC Digital Volume 3L */
+ { 0x00000423, 0x0010 }, /* R1059 (0x423) - Noise Gate Select 3L */
+ { 0x00000424, 0x0080 }, /* R1060 (0x424) - Output Path Config 3R */
+ { 0x00000425, 0x0180 }, /* R1061 (0x425) - DAC Digital Volume 3R */
+ { 0x00000427, 0x0020 }, /* R1063 (0x427) - Noise Gate Select 3R */
+ { 0x00000428, 0x0000 }, /* R1064 (0x428) - Output Path Config 4L */
+ { 0x00000429, 0x0180 }, /* R1065 (0x429) - DAC Digital Volume 4L */
+ { 0x0000042b, 0x0040 }, /* R1067 (0x42b) - Noise Gate Select 4L */
+ { 0x0000042c, 0x0000 }, /* R1068 (0x42c) - Output Path Config 4R */
+ { 0x0000042d, 0x0180 }, /* R1069 (0x42d) - DAC Digital Volume 4R */
+ { 0x0000042f, 0x0080 }, /* R1071 (0x42f) - Noise Gate Select 4R */
+ { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+ { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+ { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+ { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+ { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+ { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+ { 0x00000438, 0x0000 }, /* R1080 (0x438) - Output Path Config 6L */
+ { 0x00000439, 0x0180 }, /* R1081 (0x439) - DAC Digital Volume 6L */
+ { 0x0000043b, 0x0400 }, /* R1083 (0x43b) - Noise Gate Select 6L */
+ { 0x0000043c, 0x0000 }, /* R1084 (0x43c) - Output Path Config 6R */
+ { 0x0000043d, 0x0180 }, /* R1085 (0x43d) - DAC Digital Volume 6R */
+ { 0x0000043f, 0x0800 }, /* R1087 (0x43f) - Noise Gate Select 6R */
+ { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
+ { 0x00000448, 0x003f }, /* R1096 (0x448) - EDRE Enable */
+ { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - EDRE Manual */
+ { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+ { 0x00000451, 0x0000 }, /* R1105 (0x451) - DAC AEC Control 2 */
+ { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
+ { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
+ { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
+ { 0x00000492, 0x0069 }, /* R1170 (0x492) - PDM SPK2 CTRL 1 */
+ { 0x00000493, 0x0000 }, /* R1171 (0x493) - PDM SPK2 CTRL 2 */
+ { 0x000004a0, 0x3210 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+ { 0x000004a1, 0x3200 }, /* R1185 (0x4a1) - HP2 Short Circuit Ctrl */
+ { 0x000004a2, 0x3200 }, /* R1186 (0x4a2) - HP3 Short Circuit Ctrl */
+ { 0x000004a8, 0x7020 }, /* R1192 (0x4a8) - HP Test Ctrl 5 */
+ { 0x000004a9, 0x7020 }, /* R1193 (0x4a9) - HP Test Ctrl 6 */
+ { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+ { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+ { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+ { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+ { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+ { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+ { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+ { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+ { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+ { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+ { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+ { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+ { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+ { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+ { 0x0000050f, 0x0006 }, /* R1295 (0x50f) - AIF1 Frame Ctrl 9 */
+ { 0x00000510, 0x0007 }, /* R1296 (0x510) - AIF1 Frame Ctrl 10 */
+ { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+ { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+ { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+ { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+ { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+ { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+ { 0x00000517, 0x0006 }, /* R1303 (0x517) - AIF1 Frame Ctrl 17 */
+ { 0x00000518, 0x0007 }, /* R1304 (0x518) - AIF1 Frame Ctrl 18 */
+ { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+ { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+ { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+ { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+ { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+ { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+ { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+ { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+ { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+ { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+ { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+ { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+ { 0x0000054b, 0x0002 }, /* R1355 (0x54b) - AIF2 Frame Ctrl 5 */
+ { 0x0000054c, 0x0003 }, /* R1356 (0x54c) - AIF2 Frame Ctrl 6 */
+ { 0x0000054d, 0x0004 }, /* R1357 (0x54d) - AIF2 Frame Ctrl 7 */
+ { 0x0000054e, 0x0005 }, /* R1358 (0x54e) - AIF2 Frame Ctrl 8 */
+ { 0x0000054f, 0x0006 }, /* R1359 (0x54f) - AIF2 Frame Ctrl 9 */
+ { 0x00000550, 0x0007 }, /* R1360 (0x550) - AIF2 Frame Ctrl 10 */
+ { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+ { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+ { 0x00000553, 0x0002 }, /* R1363 (0x553) - AIF2 Frame Ctrl 13 */
+ { 0x00000554, 0x0003 }, /* R1364 (0x554) - AIF2 Frame Ctrl 14 */
+ { 0x00000555, 0x0004 }, /* R1365 (0x555) - AIF2 Frame Ctrl 15 */
+ { 0x00000556, 0x0005 }, /* R1366 (0x556) - AIF2 Frame Ctrl 16 */
+ { 0x00000557, 0x0006 }, /* R1367 (0x557) - AIF2 Frame Ctrl 17 */
+ { 0x00000558, 0x0007 }, /* R1368 (0x558) - AIF2 Frame Ctrl 18 */
+ { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+ { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+ { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+ { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+ { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+ { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+ { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+ { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+ { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+ { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+ { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+ { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+ { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+ { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+ { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+ { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+ { 0x000005a0, 0x000c }, /* R1440 (0x5a0) - AIF4 BCLK Ctrl */
+ { 0x000005a1, 0x0000 }, /* R1441 (0x5a1) - AIF4 Tx Pin Ctrl */
+ { 0x000005a2, 0x0000 }, /* R1442 (0x5a2) - AIF4 Rx Pin Ctrl */
+ { 0x000005a3, 0x0000 }, /* R1443 (0x5a3) - AIF4 Rate Ctrl */
+ { 0x000005a4, 0x0000 }, /* R1444 (0x5a4) - AIF4 Format */
+ { 0x000005a6, 0x0040 }, /* R1446 (0x5a6) - AIF4 Rx BCLK Rate */
+ { 0x000005a7, 0x1818 }, /* R1447 (0x5a7) - AIF4 Frame Ctrl 1 */
+ { 0x000005a8, 0x1818 }, /* R1448 (0x5a8) - AIF4 Frame Ctrl 2 */
+ { 0x000005a9, 0x0000 }, /* R1449 (0x5a9) - AIF4 Frame Ctrl 3 */
+ { 0x000005aa, 0x0001 }, /* R1450 (0x5aa) - AIF4 Frame Ctrl 4 */
+ { 0x000005b1, 0x0000 }, /* R1457 (0x5b1) - AIF4 Frame Ctrl 11 */
+ { 0x000005b2, 0x0001 }, /* R1458 (0x5b2) - AIF4 Frame Ctrl 12 */
+ { 0x000005b9, 0x0000 }, /* R1465 (0x5b9) - AIF4 Tx Enables */
+ { 0x000005ba, 0x0000 }, /* R1466 (0x5ba) - AIF4 Rx Enables */
+ { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+ { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+ { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+ { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+ { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+ { 0x000005e8, 0x0000 }, /* R1512 (0x5e8) - SLIMbus Rates 4 */
+ { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+ { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+ { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+ { 0x000005ec, 0x0000 }, /* R1516 (0x5ec) - SLIMbus Rates 8 */
+ { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+ { 0x000005f6, 0x0000 }, /* R1526 (0x5F6) - SLIMbus TX Channel Enable */
+ { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+ { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+ { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+ { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+ { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+ { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+ { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+ { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+ { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+ { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+ { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+ { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+ { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+ { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+ { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+ { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+ { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+ { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+ { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+ { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+ { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+ { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+ { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+ { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+ { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+ { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+ { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+ { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+ { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+ { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+ { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+ { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+ { 0x00000690, 0x0000 }, /* R1680 (0x690) - OUT2LMIX Input 1 Source */
+ { 0x00000691, 0x0080 }, /* R1681 (0x691) - OUT2LMIX Input 1 Volume */
+ { 0x00000692, 0x0000 }, /* R1682 (0x692) - OUT2LMIX Input 2 Source */
+ { 0x00000693, 0x0080 }, /* R1683 (0x693) - OUT2LMIX Input 2 Volume */
+ { 0x00000694, 0x0000 }, /* R1684 (0x694) - OUT2LMIX Input 3 Source */
+ { 0x00000695, 0x0080 }, /* R1685 (0x695) - OUT2LMIX Input 3 Volume */
+ { 0x00000696, 0x0000 }, /* R1686 (0x696) - OUT2LMIX Input 4 Source */
+ { 0x00000697, 0x0080 }, /* R1687 (0x697) - OUT2LMIX Input 4 Volume */
+ { 0x00000698, 0x0000 }, /* R1688 (0x698) - OUT2RMIX Input 1 Source */
+ { 0x00000699, 0x0080 }, /* R1689 (0x699) - OUT2RMIX Input 1 Volume */
+ { 0x0000069a, 0x0000 }, /* R1690 (0x69a) - OUT2RMIX Input 2 Source */
+ { 0x0000069b, 0x0080 }, /* R1691 (0x69b) - OUT2RMIX Input 2 Volume */
+ { 0x0000069c, 0x0000 }, /* R1692 (0x69c) - OUT2RMIX Input 3 Source */
+ { 0x0000069d, 0x0080 }, /* R1693 (0x69d) - OUT2RMIX Input 3 Volume */
+ { 0x0000069e, 0x0000 }, /* R1694 (0x69e) - OUT2RMIX Input 4 Source */
+ { 0x0000069f, 0x0080 }, /* R1695 (0x69f) - OUT2RMIX Input 4 Volume */
+ { 0x000006a0, 0x0000 }, /* R1696 (0x6a0) - OUT3LMIX Input 1 Source */
+ { 0x000006a1, 0x0080 }, /* R1697 (0x6a1) - OUT3LMIX Input 1 Volume */
+ { 0x000006a2, 0x0000 }, /* R1698 (0x6a2) - OUT3LMIX Input 2 Source */
+ { 0x000006a3, 0x0080 }, /* R1699 (0x6a3) - OUT3LMIX Input 2 Volume */
+ { 0x000006a4, 0x0000 }, /* R1700 (0x6a4) - OUT3LMIX Input 3 Source */
+ { 0x000006a5, 0x0080 }, /* R1701 (0x6a5) - OUT3LMIX Input 3 Volume */
+ { 0x000006a6, 0x0000 }, /* R1702 (0x6a6) - OUT3LMIX Input 4 Source */
+ { 0x000006a7, 0x0080 }, /* R1703 (0x6a7) - OUT3LMIX Input 4 Volume */
+ { 0x000006a8, 0x0000 }, /* R1704 (0x6a8) - OUT3RMIX Input 1 Source */
+ { 0x000006a9, 0x0080 }, /* R1705 (0x6a9) - OUT3RMIX Input 1 Volume */
+ { 0x000006aa, 0x0000 }, /* R1706 (0x6aa) - OUT3RMIX Input 2 Source */
+ { 0x000006ab, 0x0080 }, /* R1707 (0x6ab) - OUT3RMIX Input 2 Volume */
+ { 0x000006ac, 0x0000 }, /* R1708 (0x6ac) - OUT3RMIX Input 3 Source */
+ { 0x000006ad, 0x0080 }, /* R1709 (0x6ad) - OUT3RMIX Input 3 Volume */
+ { 0x000006ae, 0x0000 }, /* R1710 (0x6ae) - OUT3RMIX Input 4 Source */
+ { 0x000006af, 0x0080 }, /* R1711 (0x6af) - OUT3RMIX Input 4 Volume */
+ { 0x000006b0, 0x0000 }, /* R1712 (0x6b0) - OUT4LMIX Input 1 Source */
+ { 0x000006b1, 0x0080 }, /* R1713 (0x6b1) - OUT4LMIX Input 1 Volume */
+ { 0x000006b2, 0x0000 }, /* R1714 (0x6b2) - OUT4LMIX Input 2 Source */
+ { 0x000006b3, 0x0080 }, /* R1715 (0x6b3) - OUT4LMIX Input 2 Volume */
+ { 0x000006b4, 0x0000 }, /* R1716 (0x6b4) - OUT4LMIX Input 3 Source */
+ { 0x000006b5, 0x0080 }, /* R1717 (0x6b5) - OUT4LMIX Input 3 Volume */
+ { 0x000006b6, 0x0000 }, /* R1718 (0x6b6) - OUT4LMIX Input 4 Source */
+ { 0x000006b7, 0x0080 }, /* R1719 (0x6b7) - OUT4LMIX Input 4 Volume */
+ { 0x000006b8, 0x0000 }, /* R1720 (0x6b8) - OUT4RMIX Input 1 Source */
+ { 0x000006b9, 0x0080 }, /* R1721 (0x6b9) - OUT4RMIX Input 1 Volume */
+ { 0x000006ba, 0x0000 }, /* R1722 (0x6ba) - OUT4RMIX Input 2 Source */
+ { 0x000006bb, 0x0080 }, /* R1723 (0x6bb) - OUT4RMIX Input 2 Volume */
+ { 0x000006bc, 0x0000 }, /* R1724 (0x6bc) - OUT4RMIX Input 3 Source */
+ { 0x000006bd, 0x0080 }, /* R1725 (0x6bd) - OUT4RMIX Input 3 Volume */
+ { 0x000006be, 0x0000 }, /* R1726 (0x6be) - OUT4RMIX Input 4 Source */
+ { 0x000006bf, 0x0080 }, /* R1727 (0x6bf) - OUT4RMIX Input 4 Volume */
+ { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+ { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+ { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+ { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+ { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+ { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+ { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+ { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+ { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+ { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+ { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+ { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+ { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+ { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+ { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+ { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+ { 0x000006d0, 0x0000 }, /* R1744 (0x6d0) - OUT6LMIX Input 1 Source */
+ { 0x000006d1, 0x0080 }, /* R1745 (0x6d1) - OUT6LMIX Input 1 Volume */
+ { 0x000006d2, 0x0000 }, /* R1746 (0x6d2) - OUT6LMIX Input 2 Source */
+ { 0x000006d3, 0x0080 }, /* R1747 (0x6d3) - OUT6LMIX Input 2 Volume */
+ { 0x000006d4, 0x0000 }, /* R1748 (0x6d4) - OUT6LMIX Input 3 Source */
+ { 0x000006d5, 0x0080 }, /* R1749 (0x6d5) - OUT6LMIX Input 3 Volume */
+ { 0x000006d6, 0x0000 }, /* R1750 (0x6d6) - OUT6LMIX Input 4 Source */
+ { 0x000006d7, 0x0080 }, /* R1751 (0x6d7) - OUT6LMIX Input 4 Volume */
+ { 0x000006d8, 0x0000 }, /* R1752 (0x6d8) - OUT6RMIX Input 1 Source */
+ { 0x000006d9, 0x0080 }, /* R1753 (0x6d9) - OUT6RMIX Input 1 Volume */
+ { 0x000006da, 0x0000 }, /* R1754 (0x6da) - OUT6RMIX Input 2 Source */
+ { 0x000006db, 0x0080 }, /* R1755 (0x6db) - OUT6RMIX Input 2 Volume */
+ { 0x000006dc, 0x0000 }, /* R1756 (0x6dc) - OUT6RMIX Input 3 Source */
+ { 0x000006dd, 0x0080 }, /* R1757 (0x6dd) - OUT6RMIX Input 3 Volume */
+ { 0x000006de, 0x0000 }, /* R1758 (0x6de) - OUT6RMIX Input 4 Source */
+ { 0x000006df, 0x0080 }, /* R1759 (0x6df) - OUT6RMIX Input 4 Volume */
+ { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+ { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+ { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+ { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+ { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+ { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+ { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+ { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+ { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+ { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+ { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+ { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+ { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+ { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+ { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+ { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+ { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+ { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+ { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+ { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+ { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+ { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+ { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+ { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+ { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+ { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+ { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+ { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+ { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+ { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+ { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+ { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+ { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+ { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+ { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+ { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+ { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+ { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+ { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+ { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+ { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+ { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+ { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+ { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+ { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+ { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+ { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+ { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+ { 0x00000730, 0x0000 }, /* R1840 (0x730) - AIF1TX7MIX Input 1 Source */
+ { 0x00000731, 0x0080 }, /* R1841 (0x731) - AIF1TX7MIX Input 1 Volume */
+ { 0x00000732, 0x0000 }, /* R1842 (0x732) - AIF1TX7MIX Input 2 Source */
+ { 0x00000733, 0x0080 }, /* R1843 (0x733) - AIF1TX7MIX Input 2 Volume */
+ { 0x00000734, 0x0000 }, /* R1844 (0x734) - AIF1TX7MIX Input 3 Source */
+ { 0x00000735, 0x0080 }, /* R1845 (0x735) - AIF1TX7MIX Input 3 Volume */
+ { 0x00000736, 0x0000 }, /* R1846 (0x736) - AIF1TX7MIX Input 4 Source */
+ { 0x00000737, 0x0080 }, /* R1847 (0x737) - AIF1TX7MIX Input 4 Volume */
+ { 0x00000738, 0x0000 }, /* R1848 (0x738) - AIF1TX8MIX Input 1 Source */
+ { 0x00000739, 0x0080 }, /* R1849 (0x739) - AIF1TX8MIX Input 1 Volume */
+ { 0x0000073a, 0x0000 }, /* R1850 (0x73a) - AIF1TX8MIX Input 2 Source */
+ { 0x0000073b, 0x0080 }, /* R1851 (0x73b) - AIF1TX8MIX Input 2 Volume */
+ { 0x0000073c, 0x0000 }, /* R1852 (0x73c) - AIF1TX8MIX Input 3 Source */
+ { 0x0000073d, 0x0080 }, /* R1853 (0x73d) - AIF1TX8MIX Input 3 Volume */
+ { 0x0000073e, 0x0000 }, /* R1854 (0x73e) - AIF1TX8MIX Input 4 Source */
+ { 0x0000073f, 0x0080 }, /* R1855 (0x73f) - AIF1TX8MIX Input 4 Volume */
+ { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+ { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+ { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+ { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+ { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+ { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+ { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+ { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+ { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+ { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+ { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+ { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+ { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+ { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+ { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+ { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+ { 0x00000750, 0x0000 }, /* R1872 (0x750) - AIF2TX3MIX Input 1 Source */
+ { 0x00000751, 0x0080 }, /* R1873 (0x751) - AIF2TX3MIX Input 1 Volume */
+ { 0x00000752, 0x0000 }, /* R1874 (0x752) - AIF2TX3MIX Input 2 Source */
+ { 0x00000753, 0x0080 }, /* R1875 (0x753) - AIF2TX3MIX Input 2 Volume */
+ { 0x00000754, 0x0000 }, /* R1876 (0x754) - AIF2TX3MIX Input 3 Source */
+ { 0x00000755, 0x0080 }, /* R1877 (0x755) - AIF2TX3MIX Input 3 Volume */
+ { 0x00000756, 0x0000 }, /* R1878 (0x756) - AIF2TX3MIX Input 4 Source */
+ { 0x00000757, 0x0080 }, /* R1879 (0x757) - AIF2TX3MIX Input 4 Volume */
+ { 0x00000758, 0x0000 }, /* R1880 (0x758) - AIF2TX4MIX Input 1 Source */
+ { 0x00000759, 0x0080 }, /* R1881 (0x759) - AIF2TX4MIX Input 1 Volume */
+ { 0x0000075a, 0x0000 }, /* R1882 (0x75a) - AIF2TX4MIX Input 2 Source */
+ { 0x0000075b, 0x0080 }, /* R1883 (0x75b) - AIF2TX4MIX Input 2 Volume */
+ { 0x0000075c, 0x0000 }, /* R1884 (0x75c) - AIF2TX4MIX Input 3 Source */
+ { 0x0000075d, 0x0080 }, /* R1885 (0x75d) - AIF2TX4MIX Input 3 Volume */
+ { 0x0000075e, 0x0000 }, /* R1886 (0x75e) - AIF2TX4MIX Input 4 Source */
+ { 0x0000075f, 0x0080 }, /* R1887 (0x75f) - AIF2TX4MIX Input 4 Volume */
+ { 0x00000760, 0x0000 }, /* R1888 (0x760) - AIF2TX5MIX Input 1 Source */
+ { 0x00000761, 0x0080 }, /* R1889 (0x761) - AIF2TX5MIX Input 1 Volume */
+ { 0x00000762, 0x0000 }, /* R1890 (0x762) - AIF2TX5MIX Input 2 Source */
+ { 0x00000763, 0x0080 }, /* R1891 (0x763) - AIF2TX5MIX Input 2 Volume */
+ { 0x00000764, 0x0000 }, /* R1892 (0x764) - AIF2TX5MIX Input 3 Source */
+ { 0x00000765, 0x0080 }, /* R1893 (0x765) - AIF2TX5MIX Input 3 Volume */
+ { 0x00000766, 0x0000 }, /* R1894 (0x766) - AIF2TX5MIX Input 4 Source */
+ { 0x00000767, 0x0080 }, /* R1895 (0x767) - AIF2TX5MIX Input 4 Volume */
+ { 0x00000768, 0x0000 }, /* R1896 (0x768) - AIF2TX6MIX Input 1 Source */
+ { 0x00000769, 0x0080 }, /* R1897 (0x769) - AIF2TX6MIX Input 1 Volume */
+ { 0x0000076a, 0x0000 }, /* R1898 (0x76a) - AIF2TX6MIX Input 2 Source */
+ { 0x0000076b, 0x0080 }, /* R1899 (0x76b) - AIF2TX6MIX Input 2 Volume */
+ { 0x0000076c, 0x0000 }, /* R1900 (0x76c) - AIF2TX6MIX Input 3 Source */
+ { 0x0000076d, 0x0080 }, /* R1901 (0x76d) - AIF2TX6MIX Input 3 Volume */
+ { 0x0000076e, 0x0000 }, /* R1902 (0x76e) - AIF2TX6MIX Input 4 Source */
+ { 0x0000076f, 0x0080 }, /* R1903 (0x76f) - AIF2TX6MIX Input 4 Volume */
+ { 0x00000770, 0x0000 }, /* R1904 (0x770) - AIF2TX7MIX Input 1 Source */
+ { 0x00000771, 0x0080 }, /* R1905 (0x771) - AIF2TX7MIX Input 1 Volume */
+ { 0x00000772, 0x0000 }, /* R1906 (0x772) - AIF2TX7MIX Input 2 Source */
+ { 0x00000773, 0x0080 }, /* R1907 (0x773) - AIF2TX7MIX Input 2 Volume */
+ { 0x00000774, 0x0000 }, /* R1908 (0x774) - AIF2TX7MIX Input 3 Source */
+ { 0x00000775, 0x0080 }, /* R1909 (0x775) - AIF2TX7MIX Input 3 Volume */
+ { 0x00000776, 0x0000 }, /* R1910 (0x776) - AIF2TX7MIX Input 4 Source */
+ { 0x00000777, 0x0080 }, /* R1911 (0x777) - AIF2TX7MIX Input 4 Volume */
+ { 0x00000778, 0x0000 }, /* R1912 (0x778) - AIF2TX8MIX Input 1 Source */
+ { 0x00000779, 0x0080 }, /* R1913 (0x779) - AIF2TX8MIX Input 1 Volume */
+ { 0x0000077a, 0x0000 }, /* R1914 (0x77a) - AIF2TX8MIX Input 2 Source */
+ { 0x0000077b, 0x0080 }, /* R1915 (0x77b) - AIF2TX8MIX Input 2 Volume */
+ { 0x0000077c, 0x0000 }, /* R1916 (0x77c) - AIF2TX8MIX Input 3 Source */
+ { 0x0000077d, 0x0080 }, /* R1917 (0x77d) - AIF2TX8MIX Input 3 Volume */
+ { 0x0000077e, 0x0000 }, /* R1918 (0x77e) - AIF2TX8MIX Input 4 Source */
+ { 0x0000077f, 0x0080 }, /* R1919 (0x77f) - AIF2TX8MIX Input 4 Volume */
+ { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+ { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+ { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+ { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+ { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+ { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+ { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+ { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+ { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+ { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+ { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+ { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+ { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+ { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+ { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+ { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+ { 0x000007a0, 0x0000 }, /* R1952 (0x7a0) - AIF4TX1MIX Input 1 Source */
+ { 0x000007a1, 0x0080 }, /* R1953 (0x7a1) - AIF4TX1MIX Input 1 Volume */
+ { 0x000007a2, 0x0000 }, /* R1954 (0x7a2) - AIF4TX1MIX Input 2 Source */
+ { 0x000007a3, 0x0080 }, /* R1955 (0x7a3) - AIF4TX1MIX Input 2 Volume */
+ { 0x000007a4, 0x0000 }, /* R1956 (0x7a4) - AIF4TX1MIX Input 3 Source */
+ { 0x000007a5, 0x0080 }, /* R1957 (0x7a5) - AIF4TX1MIX Input 3 Volume */
+ { 0x000007a6, 0x0000 }, /* R1958 (0x7a6) - AIF4TX1MIX Input 4 Source */
+ { 0x000007a7, 0x0080 }, /* R1959 (0x7a7) - AIF4TX1MIX Input 4 Volume */
+ { 0x000007a8, 0x0000 }, /* R1960 (0x7a8) - AIF4TX2MIX Input 1 Source */
+ { 0x000007a9, 0x0080 }, /* R1961 (0x7a9) - AIF4TX2MIX Input 1 Volume */
+ { 0x000007aa, 0x0000 }, /* R1962 (0x7aa) - AIF4TX2MIX Input 2 Source */
+ { 0x000007ab, 0x0080 }, /* R1963 (0x7ab) - AIF4TX2MIX Input 2 Volume */
+ { 0x000007ac, 0x0000 }, /* R1964 (0x7ac) - AIF4TX2MIX Input 3 Source */
+ { 0x000007ad, 0x0080 }, /* R1965 (0x7ad) - AIF4TX2MIX Input 3 Volume */
+ { 0x000007ae, 0x0000 }, /* R1966 (0x7ae) - AIF4TX2MIX Input 4 Source */
+ { 0x000007af, 0x0080 }, /* R1967 (0x7af) - AIF4TX2MIX Input 4 Volume */
+ { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+ { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+ { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+ { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+ { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+ { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+ { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+ { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+ { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+ { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+ { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+ { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+ { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+ { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+ { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+ { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+ { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+ { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+ { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+ { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+ { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+ { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+ { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+ { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+ { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+ { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+ { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+ { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+ { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+ { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+ { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+ { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+ { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+ { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+ { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+ { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+ { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+ { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+ { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+ { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+ { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+ { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+ { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+ { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+ { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+ { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+ { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+ { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+ { 0x000007f0, 0x0000 }, /* R2032 (0x7f0) - SLIMTX7MIX Input 1 Source */
+ { 0x000007f1, 0x0080 }, /* R2033 (0x7f1) - SLIMTX7MIX Input 1 Volume */
+ { 0x000007f2, 0x0000 }, /* R2034 (0x7f2) - SLIMTX7MIX Input 2 Source */
+ { 0x000007f3, 0x0080 }, /* R2035 (0x7f3) - SLIMTX7MIX Input 2 Volume */
+ { 0x000007f4, 0x0000 }, /* R2036 (0x7f4) - SLIMTX7MIX Input 3 Source */
+ { 0x000007f5, 0x0080 }, /* R2037 (0x7f5) - SLIMTX7MIX Input 3 Volume */
+ { 0x000007f6, 0x0000 }, /* R2038 (0x7f6) - SLIMTX7MIX Input 4 Source */
+ { 0x000007f7, 0x0080 }, /* R2039 (0x7f7) - SLIMTX7MIX Input 4 Volume */
+ { 0x000007f8, 0x0000 }, /* R2040 (0x7f8) - SLIMTX8MIX Input 1 Source */
+ { 0x000007f9, 0x0080 }, /* R2041 (0x7f9) - SLIMTX8MIX Input 1 Volume */
+ { 0x000007fa, 0x0000 }, /* R2042 (0x7fa) - SLIMTX8MIX Input 2 Source */
+ { 0x000007fb, 0x0080 }, /* R2043 (0x7fb) - SLIMTX8MIX Input 2 Volume */
+ { 0x000007fc, 0x0000 }, /* R2044 (0x7fc) - SLIMTX8MIX Input 3 Source */
+ { 0x000007fd, 0x0080 }, /* R2045 (0x7fd) - SLIMTX8MIX Input 3 Volume */
+ { 0x000007fe, 0x0000 }, /* R2046 (0x7fe) - SLIMTX8MIX Input 4 Source */
+ { 0x000007ff, 0x0080 }, /* R2047 (0x7ff) - SLIMTX8MIX Input 4 Volume */
+ { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source */
+ { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume */
+ { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source */
+ { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume */
+ { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+ { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+ { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+ { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+ { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+ { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+ { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+ { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+ { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+ { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+ { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+ { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+ { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+ { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+ { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+ { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+ { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+ { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+ { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+ { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+ { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+ { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+ { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+ { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+ { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+ { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+ { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+ { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+ { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+ { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+ { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+ { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+ { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+ { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+ { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+ { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+ { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+ { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+ { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+ { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+ { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+ { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+ { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+ { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+ { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+ { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+ { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+ { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+ { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+ { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+ { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+ { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+ { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+ { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+ { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+ { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+ { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+ { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+ { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+ { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+ { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+ { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+ { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+ { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+ { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+ { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+ { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+ { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+ { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+ { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+ { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+ { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+ { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+ { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+ { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+ { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+ { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+ { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+ { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+ { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+ { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+ { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+ { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+ { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+ { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+ { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+ { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+ { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+ { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+ { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+ { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+ { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+ { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+ { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+ { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+ { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+ { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+ { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+ { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+ { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+ { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+ { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+ { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+ { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+ { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+ { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+ { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+ { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+ { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+ { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+ { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+ { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+ { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+ { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+ { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+ { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+ { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+ { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+ { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+ { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+ { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+ { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+ { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+ { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+ { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+ { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+ { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+ { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+ { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+ { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+ { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+ { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+ { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+ { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+ { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+ { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+ { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+ { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+ { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+ { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+ { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+ { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+ { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+ { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+ { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+ { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+ { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+ { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+ { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+ { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+ { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+ { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+ { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+ { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+ { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+ { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+ { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+ { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+ { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+ { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+ { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+ { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+ { 0x00000a00, 0x0000 }, /* R2560 (0xa00) - DSP4LMIX Input 1 Source */
+ { 0x00000a01, 0x0080 }, /* R2561 (0xa01) - DSP4LMIX Input 1 Volume */
+ { 0x00000a02, 0x0000 }, /* R2562 (0xa02) - DSP4LMIX Input 2 Source */
+ { 0x00000a03, 0x0080 }, /* R2563 (0xa03) - DSP4LMIX Input 2 Volume */
+ { 0x00000a04, 0x0000 }, /* R2564 (0xa04) - DSP4LMIX Input 3 Source */
+ { 0x00000a05, 0x0080 }, /* R2565 (0xa05) - DSP4LMIX Input 3 Volume */
+ { 0x00000a06, 0x0000 }, /* R2566 (0xa06) - DSP4LMIX Input 4 Source */
+ { 0x00000a07, 0x0080 }, /* R2567 (0xa07) - DSP4LMIX Input 4 Volume */
+ { 0x00000a08, 0x0000 }, /* R2568 (0xa08) - DSP4RMIX Input 1 Source */
+ { 0x00000a09, 0x0080 }, /* R2569 (0xa09) - DSP4RMIX Input 1 Volume */
+ { 0x00000a0a, 0x0000 }, /* R2570 (0xa0a) - DSP4RMIX Input 2 Source */
+ { 0x00000a0b, 0x0080 }, /* R2571 (0xa0b) - DSP4RMIX Input 2 Volume */
+ { 0x00000a0c, 0x0000 }, /* R2572 (0xa0c) - DSP4RMIX Input 3 Source */
+ { 0x00000a0d, 0x0080 }, /* R2573 (0xa0d) - DSP4RMIX Input 3 Volume */
+ { 0x00000a0e, 0x0000 }, /* R2574 (0xa0e) - DSP4RMIX Input 4 Source */
+ { 0x00000a0f, 0x0080 }, /* R2575 (0xa0f) - DSP4RMIX Input 4 Volume */
+ { 0x00000a10, 0x0000 }, /* R2576 (0xa10) - DSP4AUX1MIX Input 1 Source */
+ { 0x00000a18, 0x0000 }, /* R2584 (0xa18) - DSP4AUX2MIX Input 1 Source */
+ { 0x00000a20, 0x0000 }, /* R2592 (0xa20) - DSP4AUX3MIX Input 1 Source */
+ { 0x00000a28, 0x0000 }, /* R2600 (0xa28) - DSP4AUX4MIX Input 1 Source */
+ { 0x00000a30, 0x0000 }, /* R2608 (0xa30) - DSP4AUX5MIX Input 1 Source */
+ { 0x00000a38, 0x0000 }, /* R2616 (0xa38) - DSP4AUX6MIX Input 1 Source */
+ { 0x00000a40, 0x0000 }, /* R2624 (0xa40) - DSP5LMIX Input 1 Source */
+ { 0x00000a41, 0x0080 }, /* R2625 (0xa41) - DSP5LMIX Input 1 Volume */
+ { 0x00000a42, 0x0000 }, /* R2626 (0xa42) - DSP5LMIX Input 2 Source */
+ { 0x00000a43, 0x0080 }, /* R2627 (0xa43) - DSP5LMIX Input 2 Volume */
+ { 0x00000a44, 0x0000 }, /* R2628 (0xa44) - DSP5LMIX Input 3 Source */
+ { 0x00000a45, 0x0080 }, /* R2629 (0xa45) - DSP5LMIX Input 3 Volume */
+ { 0x00000a46, 0x0000 }, /* R2630 (0xa46) - DSP5LMIX Input 4 Source */
+ { 0x00000a47, 0x0080 }, /* R2631 (0xa47) - DSP5LMIX Input 4 Volume */
+ { 0x00000a48, 0x0000 }, /* R2632 (0xa48) - DSP5RMIX Input 1 Source */
+ { 0x00000a49, 0x0080 }, /* R2633 (0xa49) - DSP5RMIX Input 1 Volume */
+ { 0x00000a4a, 0x0000 }, /* R2634 (0xa4a) - DSP5RMIX Input 2 Source */
+ { 0x00000a4b, 0x0080 }, /* R2635 (0xa4b) - DSP5RMIX Input 2 Volume */
+ { 0x00000a4c, 0x0000 }, /* R2636 (0xa4c) - DSP5RMIX Input 3 Source */
+ { 0x00000a4d, 0x0080 }, /* R2637 (0xa4d) - DSP5RMIX Input 3 Volume */
+ { 0x00000a4e, 0x0000 }, /* R2638 (0xa4e) - DSP5RMIX Input 4 Source */
+ { 0x00000a4f, 0x0080 }, /* R2639 (0xa4f) - DSP5RMIX Input 4 Volume */
+ { 0x00000a50, 0x0000 }, /* R2640 (0xa50) - DSP5AUX1MIX Input 1 Source */
+ { 0x00000a58, 0x0000 }, /* R2658 (0xa58) - DSP5AUX2MIX Input 1 Source */
+ { 0x00000a60, 0x0000 }, /* R2656 (0xa60) - DSP5AUX3MIX Input 1 Source */
+ { 0x00000a68, 0x0000 }, /* R2664 (0xa68) - DSP5AUX4MIX Input 1 Source */
+ { 0x00000a70, 0x0000 }, /* R2672 (0xa70) - DSP5AUX5MIX Input 1 Source */
+ { 0x00000a78, 0x0000 }, /* R2680 (0xa78) - DSP5AUX6MIX Input 1 Source */
+ { 0x00000a80, 0x0000 }, /* R2688 (0xa80) - ASRC1_1LMIX Input 1 Source */
+ { 0x00000a88, 0x0000 }, /* R2696 (0xa88) - ASRC1_1RMIX Input 1 Source */
+ { 0x00000a90, 0x0000 }, /* R2704 (0xa90) - ASRC1_2LMIX Input 1 Source */
+ { 0x00000a98, 0x0000 }, /* R2712 (0xa98) - ASRC1_2RMIX Input 1 Source */
+ { 0x00000aa0, 0x0000 }, /* R2720 (0xaa0) - ASRC2_1LMIX Input 1 Source */
+ { 0x00000aa8, 0x0000 }, /* R2728 (0xaa8) - ASRC2_1RMIX Input 1 Source */
+ { 0x00000ab0, 0x0000 }, /* R2736 (0xab0) - ASRC2_2LMIX Input 1 Source */
+ { 0x00000ab8, 0x0000 }, /* R2744 (0xab8) - ASRC2_2RMIX Input 1 Source */
+ { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+ { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+ { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+ { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+ { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+ { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+ { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+ { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+ { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+ { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+ { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+ { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+ { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+ { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+ { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+ { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+ { 0x00000b80, 0x0000 }, /* R2944 (0xb80) - ISRC3DEC1MIX Input 1 Source*/
+ { 0x00000b88, 0x0000 }, /* R2952 (0xb88) - ISRC3DEC2MIX Input 1 Source*/
+ { 0x00000ba0, 0x0000 }, /* R2976 (0xb80) - ISRC3INT1MIX Input 1 Source*/
+ { 0x00000ba8, 0x0000 }, /* R2984 (0xb88) - ISRC3INT2MIX Input 1 Source*/
+ { 0x00000bc0, 0x0000 }, /* R3008 (0xbc0) - ISRC4DEC1MIX Input 1 Source */
+ { 0x00000bc8, 0x0000 }, /* R3016 (0xbc8) - ISRC4DEC2MIX Input 1 Source */
+ { 0x00000be0, 0x0000 }, /* R3040 (0xbe0) - ISRC4INT1MIX Input 1 Source */
+ { 0x00000be8, 0x0000 }, /* R3048 (0xbe8) - ISRC4INT2MIX Input 1 Source */
+ { 0x00000c00, 0x0000 }, /* R3072 (0xc00) - DSP6LMIX Input 1 Source */
+ { 0x00000c01, 0x0080 }, /* R3073 (0xc01) - DSP6LMIX Input 1 Volume */
+ { 0x00000c02, 0x0000 }, /* R3074 (0xc02) - DSP6LMIX Input 2 Source */
+ { 0x00000c03, 0x0080 }, /* R3075 (0xc03) - DSP6LMIX Input 2 Volume */
+ { 0x00000c04, 0x0000 }, /* R3076 (0xc04) - DSP6LMIX Input 3 Source */
+ { 0x00000c05, 0x0080 }, /* R3077 (0xc05) - DSP6LMIX Input 3 Volume */
+ { 0x00000c06, 0x0000 }, /* R3078 (0xc06) - DSP6LMIX Input 4 Source */
+ { 0x00000c07, 0x0080 }, /* R3079 (0xc07) - DSP6LMIX Input 4 Volume */
+ { 0x00000c08, 0x0000 }, /* R3080 (0xc08) - DSP6RMIX Input 1 Source */
+ { 0x00000c09, 0x0080 }, /* R3081 (0xc09) - DSP6RMIX Input 1 Volume */
+ { 0x00000c0a, 0x0000 }, /* R3082 (0xc0a) - DSP6RMIX Input 2 Source */
+ { 0x00000c0b, 0x0080 }, /* R3083 (0xc0b) - DSP6RMIX Input 2 Volume */
+ { 0x00000c0c, 0x0000 }, /* R3084 (0xc0c) - DSP6RMIX Input 3 Source */
+ { 0x00000c0d, 0x0080 }, /* R3085 (0xc0d) - DSP6RMIX Input 3 Volume */
+ { 0x00000c0e, 0x0000 }, /* R3086 (0xc0e) - DSP6RMIX Input 4 Source */
+ { 0x00000c0f, 0x0080 }, /* R3087 (0xc0f) - DSP6RMIX Input 4 Volume */
+ { 0x00000c10, 0x0000 }, /* R3088 (0xc10) - DSP6AUX1MIX Input 1 Source */
+ { 0x00000c18, 0x0000 }, /* R3088 (0xc18) - DSP6AUX2MIX Input 1 Source */
+ { 0x00000c20, 0x0000 }, /* R3088 (0xc20) - DSP6AUX3MIX Input 1 Source */
+ { 0x00000c28, 0x0000 }, /* R3088 (0xc28) - DSP6AUX4MIX Input 1 Source */
+ { 0x00000c30, 0x0000 }, /* R3088 (0xc30) - DSP6AUX5MIX Input 1 Source */
+ { 0x00000c38, 0x0000 }, /* R3088 (0xc38) - DSP6AUX6MIX Input 1 Source */
+ { 0x00000c40, 0x0000 }, /* R3136 (0xc40) - DSP7LMIX Input 1 Source */
+ { 0x00000c41, 0x0080 }, /* R3137 (0xc41) - DSP7LMIX Input 1 Volume */
+ { 0x00000c42, 0x0000 }, /* R3138 (0xc42) - DSP7LMIX Input 2 Source */
+ { 0x00000c43, 0x0080 }, /* R3139 (0xc43) - DSP7LMIX Input 2 Volume */
+ { 0x00000c44, 0x0000 }, /* R3140 (0xc44) - DSP7LMIX Input 3 Source */
+ { 0x00000c45, 0x0080 }, /* R3141 (0xc45) - DSP7lMIX Input 3 Volume */
+ { 0x00000c46, 0x0000 }, /* R3142 (0xc46) - DSP7lMIX Input 4 Source */
+ { 0x00000c47, 0x0080 }, /* R3143 (0xc47) - DSP7LMIX Input 4 Volume */
+ { 0x00000c48, 0x0000 }, /* R3144 (0xc48) - DSP7RMIX Input 1 Source */
+ { 0x00000c49, 0x0080 }, /* R3145 (0xc49) - DSP7RMIX Input 1 Volume */
+ { 0x00000c4a, 0x0000 }, /* R3146 (0xc4a) - DSP7RMIX Input 2 Source */
+ { 0x00000c4b, 0x0080 }, /* R3147 (0xc4b) - DSP7RMIX Input 2 Volume */
+ { 0x00000c4c, 0x0000 }, /* R3148 (0xc4c) - DSP7RMIX Input 3 Source */
+ { 0x00000c4d, 0x0080 }, /* R3159 (0xc4d) - DSP7RMIX Input 3 Volume */
+ { 0x00000c4e, 0x0000 }, /* R3150 (0xc4e) - DSP7RMIX Input 4 Source */
+ { 0x00000c4f, 0x0080 }, /* R3151 (0xc4f) - DSP7RMIX Input 4 Volume */
+ { 0x00000c50, 0x0000 }, /* R3152 (0xc50) - DSP7AUX1MIX Input 1 Source */
+ { 0x00000c58, 0x0000 }, /* R3160 (0xc58) - DSP7AUX2MIX Input 1 Source */
+ { 0x00000c60, 0x0000 }, /* R3168 (0xc60) - DSP7AUX3MIX Input 1 Source */
+ { 0x00000c68, 0x0000 }, /* R3176 (0xc68) - DSP7AUX4MIX Input 1 Source */
+ { 0x00000c70, 0x0000 }, /* R3184 (0xc70) - DSP7AUX5MIX Input 1 Source */
+ { 0x00000c78, 0x0000 }, /* R3192 (0xc78) - DSP7AUX6MIX Input 1 Source */
+ { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX Ctrl1 */
+ { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+ { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+ { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+ { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+ { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+ { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+ { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+ { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+ { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+ { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+ { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+ { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+ { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+ { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+ { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+ { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+ { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+ { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+ { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+ { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+ { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+ { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+ { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+ { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+ { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+ { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+ { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+ { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+ { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+ { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+ { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+ { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+ { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+ { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+ { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+ { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+ { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+ { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+ { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+ { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+ { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+ { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+ { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+ { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+ { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+ { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+ { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+ { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+ { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+ { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+ { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+ { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+ { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+ { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+ { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+ { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+ { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+ { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+ { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+ { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+ { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+ { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+ { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+ { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+ { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+ { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+ { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+ { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+ { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+ { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+ { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+ { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+ { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+ { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+ { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+ { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+ { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+ { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+ { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+ { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+ { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+ { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+ { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+ { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+ { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+ { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+ { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+ { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+ { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+ { 0x00000e88, 0x0933 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+ { 0x00000e89, 0x0018 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+ { 0x00000e8a, 0x0000 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+ { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+ { 0x00000e8c, 0x0040 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+ { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+ { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+ { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+ { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+ { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+ { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+ { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+ { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+ { 0x00000ed0, 0x0000 }, /* R3792 (0xed0) - ASRC2_ENABLE */
+ { 0x00000ed2, 0x0000 }, /* R3794 (0xed2) - ASRC2_RATE1 */
+ { 0x00000ed3, 0x4000 }, /* R3795 (0xed3) - ASRC2_RATE2 */
+ { 0x00000ee0, 0x0000 }, /* R3808 (0xee0) - ASRC1_ENABLE */
+ { 0x00000ee2, 0x0000 }, /* R3810 (0xee2) - ASRC1_RATE1 */
+ { 0x00000ee3, 0x4000 }, /* R3811 (0xee3) - ASRC1_RATE2 */
+ { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+ { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+ { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+ { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+ { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+ { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+ { 0x00000ef6, 0x0000 }, /* R3830 (0xef6) - ISRC 3 CTRL 1 */
+ { 0x00000ef7, 0x0001 }, /* R3831 (0xef7) - ISRC 3 CTRL 2 */
+ { 0x00000ef8, 0x0000 }, /* R3832 (0xef8) - ISRC 3 CTRL 3 */
+ { 0x00000ef9, 0x0000 }, /* R3833 (0xef9) - ISRC 4 CTRL 1 */
+ { 0x00000efa, 0x0001 }, /* R3834 (0xefa) - ISRC 4 CTRL 2 */
+ { 0x00000efb, 0x0000 }, /* R3835 (0xefb) - ISRC 4 CTRL 3 */
+ { 0x00000f01, 0x0000 }, /* R3841 (0xf01) - ANC_SRC */
+ { 0x00000f02, 0x0000 }, /* R3842 (0xf02) - DSP Status */
+ { 0x00000f08, 0x001c }, /* R3848 (0xf08) - ANC Coefficient */
+ { 0x00000f09, 0x0000 }, /* R3849 (0xf09) - ANC Coefficient */
+ { 0x00000f0a, 0x0000 }, /* R3850 (0xf0a) - ANC Coefficient */
+ { 0x00000f0b, 0x0000 }, /* R3851 (0xf0b) - ANC Coefficient */
+ { 0x00000f0c, 0x0000 }, /* R3852 (0xf0c) - ANC Coefficient */
+ { 0x00000f0d, 0x0000 }, /* R3853 (0xf0d) - ANC Coefficient */
+ { 0x00000f0e, 0x0000 }, /* R3854 (0xf0e) - ANC Coefficient */
+ { 0x00000f0f, 0x0000 }, /* R3855 (0xf0f) - ANC Coefficient */
+ { 0x00000f10, 0x0000 }, /* R3856 (0xf10) - ANC Coefficient */
+ { 0x00000f11, 0x0000 }, /* R3857 (0xf11) - ANC Coefficient */
+ { 0x00000f12, 0x0000 }, /* R3858 (0xf12) - ANC Coefficient */
+ { 0x00000f15, 0x0000 }, /* R3861 (0xf15) - FCL Filter Control */
+ { 0x00000f17, 0x0004 }, /* R3863 (0xf17) - FCL ADC Reformatter Control */
+ { 0x00000f18, 0x0004 }, /* R3864 (0xf18) - ANC Coefficient */
+ { 0x00000f19, 0x0002 }, /* R3865 (0xf19) - ANC Coefficient */
+ { 0x00000f1a, 0x0000 }, /* R3866 (0xf1a) - ANC Coefficient */
+ { 0x00000f1b, 0x0010 }, /* R3867 (0xf1b) - ANC Coefficient */
+ { 0x00000f1c, 0x0000 }, /* R3868 (0xf1c) - ANC Coefficient */
+ { 0x00000f1d, 0x0000 }, /* R3869 (0xf1d) - ANC Coefficient */
+ { 0x00000f1e, 0x0000 }, /* R3870 (0xf1e) - ANC Coefficient */
+ { 0x00000f1f, 0x0000 }, /* R3871 (0xf1f) - ANC Coefficient */
+ { 0x00000f20, 0x0000 }, /* R3872 (0xf20) - ANC Coefficient */
+ { 0x00000f21, 0x0000 }, /* R3873 (0xf21) - ANC Coefficient */
+ { 0x00000f22, 0x0000 }, /* R3874 (0xf22) - ANC Coefficient */
+ { 0x00000f23, 0x0000 }, /* R3875 (0xf23) - ANC Coefficient */
+ { 0x00000f24, 0x0000 }, /* R3876 (0xf24) - ANC Coefficient */
+ { 0x00000f25, 0x0000 }, /* R3877 (0xf25) - ANC Coefficient */
+ { 0x00000f26, 0x0000 }, /* R3878 (0xf26) - ANC Coefficient */
+ { 0x00000f27, 0x0000 }, /* R3879 (0xf27) - ANC Coefficient */
+ { 0x00000f28, 0x0000 }, /* R3880 (0xf28) - ANC Coefficient */
+ { 0x00000f29, 0x0000 }, /* R3881 (0xf29) - ANC Coefficient */
+ { 0x00000f2a, 0x0000 }, /* R3882 (0xf2a) - ANC Coefficient */
+ { 0x00000f2b, 0x0000 }, /* R3883 (0xf2b) - ANC Coefficient */
+ { 0x00000f2c, 0x0000 }, /* R3884 (0xf2c) - ANC Coefficient */
+ { 0x00000f2d, 0x0000 }, /* R3885 (0xf2d) - ANC Coefficient */
+ { 0x00000f2e, 0x0000 }, /* R3886 (0xf2e) - ANC Coefficient */
+ { 0x00000f2f, 0x0000 }, /* R3887 (0xf2f) - ANC Coefficient */
+ { 0x00000f30, 0x0000 }, /* R3888 (0xf30) - ANC Coefficient */
+ { 0x00000f31, 0x0000 }, /* R3889 (0xf31) - ANC Coefficient */
+ { 0x00000f32, 0x0000 }, /* R3890 (0xf32) - ANC Coefficient */
+ { 0x00000f33, 0x0000 }, /* R3891 (0xf33) - ANC Coefficient */
+ { 0x00000f34, 0x0000 }, /* R3892 (0xf34) - ANC Coefficient */
+ { 0x00000f35, 0x0000 }, /* R3893 (0xf35) - ANC Coefficient */
+ { 0x00000f36, 0x0000 }, /* R3894 (0xf36) - ANC Coefficient */
+ { 0x00000f37, 0x0000 }, /* R3895 (0xf37) - ANC Coefficient */
+ { 0x00000f38, 0x0000 }, /* R3896 (0xf38) - ANC Coefficient */
+ { 0x00000f39, 0x0000 }, /* R3897 (0xf39) - ANC Coefficient */
+ { 0x00000f3a, 0x0000 }, /* R3898 (0xf3a) - ANC Coefficient */
+ { 0x00000f3b, 0x0000 }, /* R3899 (0xf3b) - ANC Coefficient */
+ { 0x00000f3c, 0x0000 }, /* R3900 (0xf3c) - ANC Coefficient */
+ { 0x00000f3d, 0x0000 }, /* R3901 (0xf3d) - ANC Coefficient */
+ { 0x00000f3e, 0x0000 }, /* R3902 (0xf3e) - ANC Coefficient */
+ { 0x00000f3f, 0x0000 }, /* R3903 (0xf3f) - ANC Coefficient */
+ { 0x00000f40, 0x0000 }, /* R3904 (0xf40) - ANC Coefficient */
+ { 0x00000f41, 0x0000 }, /* R3905 (0xf41) - ANC Coefficient */
+ { 0x00000f42, 0x0000 }, /* R3906 (0xf42) - ANC Coefficient */
+ { 0x00000f43, 0x0000 }, /* R3907 (0xf43) - ANC Coefficient */
+ { 0x00000f44, 0x0000 }, /* R3908 (0xf44) - ANC Coefficient */
+ { 0x00000f45, 0x0000 }, /* R3909 (0xf45) - ANC Coefficient */
+ { 0x00000f46, 0x0000 }, /* R3910 (0xf46) - ANC Coefficient */
+ { 0x00000f47, 0x0000 }, /* R3911 (0xf47) - ANC Coefficient */
+ { 0x00000f48, 0x0000 }, /* R3912 (0xf48) - ANC Coefficient */
+ { 0x00000f49, 0x0000 }, /* R3913 (0xf49) - ANC Coefficient */
+ { 0x00000f4a, 0x0000 }, /* R3914 (0xf4a) - ANC Coefficient */
+ { 0x00000f4b, 0x0000 }, /* R3915 (0xf4b) - ANC Coefficient */
+ { 0x00000f4c, 0x0000 }, /* R3916 (0xf4c) - ANC Coefficient */
+ { 0x00000f4d, 0x0000 }, /* R3917 (0xf4d) - ANC Coefficient */
+ { 0x00000f4e, 0x0000 }, /* R3918 (0xf4e) - ANC Coefficient */
+ { 0x00000f4f, 0x0000 }, /* R3919 (0xf4f) - ANC Coefficient */
+ { 0x00000f50, 0x0000 }, /* R3920 (0xf50) - ANC Coefficient */
+ { 0x00000f51, 0x0000 }, /* R3921 (0xf51) - ANC Coefficient */
+ { 0x00000f52, 0x0000 }, /* R3922 (0xf52) - ANC Coefficient */
+ { 0x00000f53, 0x0000 }, /* R3923 (0xf53) - ANC Coefficient */
+ { 0x00000f54, 0x0000 }, /* R3924 (0xf54) - ANC Coefficient */
+ { 0x00000f55, 0x0000 }, /* R3925 (0xf55) - ANC Coefficient */
+ { 0x00000f56, 0x0000 }, /* R3926 (0xf56) - ANC Coefficient */
+ { 0x00000f57, 0x0000 }, /* R3927 (0xf57) - ANC Coefficient */
+ { 0x00000f58, 0x0000 }, /* R3928 (0xf58) - ANC Coefficient */
+ { 0x00000f59, 0x0000 }, /* R3929 (0xf59) - ANC Coefficient */
+ { 0x00000f5a, 0x0000 }, /* R3930 (0xf5a) - ANC Coefficient */
+ { 0x00000f5b, 0x0000 }, /* R3931 (0xf5b) - ANC Coefficient */
+ { 0x00000f5c, 0x0000 }, /* R3932 (0xf5c) - ANC Coefficient */
+ { 0x00000f5d, 0x0000 }, /* R3933 (0xf5d) - ANC Coefficient */
+ { 0x00000f5e, 0x0000 }, /* R3934 (0xf5e) - ANC Coefficient */
+ { 0x00000f5f, 0x0000 }, /* R3935 (0xf5f) - ANC Coefficient */
+ { 0x00000f60, 0x0000 }, /* R3936 (0xf60) - ANC Coefficient */
+ { 0x00000f61, 0x0000 }, /* R3937 (0xf61) - ANC Coefficient */
+ { 0x00000f62, 0x0000 }, /* R3938 (0xf62) - ANC Coefficient */
+ { 0x00000f63, 0x0000 }, /* R3939 (0xf63) - ANC Coefficient */
+ { 0x00000f64, 0x0000 }, /* R3940 (0xf64) - ANC Coefficient */
+ { 0x00000f65, 0x0000 }, /* R3941 (0xf65) - ANC Coefficient */
+ { 0x00000f66, 0x0000 }, /* R3942 (0xf66) - ANC Coefficient */
+ { 0x00000f67, 0x0000 }, /* R3943 (0xf67) - ANC Coefficient */
+ { 0x00000f68, 0x0000 }, /* R3944 (0xf68) - ANC Coefficient */
+ { 0x00000f69, 0x0000 }, /* R3945 (0xf69) - ANC Coefficient */
+ { 0x00000f71, 0x0000 }, /* R3953 (0xf71) - FCR Filter Control */
+ { 0x00000f73, 0x0004 }, /* R3955 (0xf73) - FCR ADC Reformatter Control */
+ { 0x00000f74, 0x0004 }, /* R3956 (0xf74) - ANC Coefficient */
+ { 0x00000f75, 0x0002 }, /* R3957 (0xf75) - ANC Coefficient */
+ { 0x00000f76, 0x0000 }, /* R3958 (0xf76) - ANC Coefficient */
+ { 0x00000f77, 0x0010 }, /* R3959 (0xf77) - ANC Coefficient */
+ { 0x00000f78, 0x0000 }, /* R3960 (0xf78) - ANC Coefficient */
+ { 0x00000f79, 0x0000 }, /* R3961 (0xf79) - ANC Coefficient */
+ { 0x00000f7a, 0x0000 }, /* R3962 (0xf7a) - ANC Coefficient */
+ { 0x00000f7b, 0x0000 }, /* R3963 (0xf7b) - ANC Coefficient */
+ { 0x00000f7c, 0x0000 }, /* R3964 (0xf7c) - ANC Coefficient */
+ { 0x00000f7d, 0x0000 }, /* R3965 (0xf7d) - ANC Coefficient */
+ { 0x00000f7e, 0x0000 }, /* R3966 (0xf7e) - ANC Coefficient */
+ { 0x00000f7f, 0x0000 }, /* R3967 (0xf7f) - ANC Coefficient */
+ { 0x00000f80, 0x0000 }, /* R3968 (0xf80) - ANC Coefficient */
+ { 0x00000f81, 0x0000 }, /* R3969 (0xf81) - ANC Coefficient */
+ { 0x00000f82, 0x0000 }, /* R3970 (0xf82) - ANC Coefficient */
+ { 0x00000f83, 0x0000 }, /* R3971 (0xf83) - ANC Coefficient */
+ { 0x00000f84, 0x0000 }, /* R3972 (0xf84) - ANC Coefficient */
+ { 0x00000f85, 0x0000 }, /* R3973 (0xf85) - ANC Coefficient */
+ { 0x00000f86, 0x0000 }, /* R3974 (0xf86) - ANC Coefficient */
+ { 0x00000f87, 0x0000 }, /* R3975 (0xf87) - ANC Coefficient */
+ { 0x00000f88, 0x0000 }, /* R3976 (0xf88) - ANC Coefficient */
+ { 0x00000f89, 0x0000 }, /* R3977 (0xf89) - ANC Coefficient */
+ { 0x00000f8a, 0x0000 }, /* R3978 (0xf8a) - ANC Coefficient */
+ { 0x00000f8b, 0x0000 }, /* R3979 (0xf8b) - ANC Coefficient */
+ { 0x00000f8c, 0x0000 }, /* R3980 (0xf8c) - ANC Coefficient */
+ { 0x00000f8d, 0x0000 }, /* R3981 (0xf8d) - ANC Coefficient */
+ { 0x00000f8e, 0x0000 }, /* R3982 (0xf8e) - ANC Coefficient */
+ { 0x00000f8f, 0x0000 }, /* R3983 (0xf8f) - ANC Coefficient */
+ { 0x00000f90, 0x0000 }, /* R3984 (0xf90) - ANC Coefficient */
+ { 0x00000f91, 0x0000 }, /* R3985 (0xf91) - ANC Coefficient */
+ { 0x00000f92, 0x0000 }, /* R3986 (0xf92) - ANC Coefficient */
+ { 0x00000f93, 0x0000 }, /* R3987 (0xf93) - ANC Coefficient */
+ { 0x00000f94, 0x0000 }, /* R3988 (0xf94) - ANC Coefficient */
+ { 0x00000f95, 0x0000 }, /* R3989 (0xf95) - ANC Coefficient */
+ { 0x00000f96, 0x0000 }, /* R3990 (0xf96) - ANC Coefficient */
+ { 0x00000f97, 0x0000 }, /* R3991 (0xf97) - ANC Coefficient */
+ { 0x00000f98, 0x0000 }, /* R3992 (0xf98) - ANC Coefficient */
+ { 0x00000f99, 0x0000 }, /* R3993 (0xf99) - ANC Coefficient */
+ { 0x00000f9a, 0x0000 }, /* R3994 (0xf9a) - ANC Coefficient */
+ { 0x00000f9b, 0x0000 }, /* R3995 (0xf9b) - ANC Coefficient */
+ { 0x00000f9c, 0x0000 }, /* R3996 (0xf9c) - ANC Coefficient */
+ { 0x00000f9d, 0x0000 }, /* R3997 (0xf9d) - ANC Coefficient */
+ { 0x00000f9e, 0x0000 }, /* R3998 (0xf9e) - ANC Coefficient */
+ { 0x00000f9f, 0x0000 }, /* R3999 (0xf9f) - ANC Coefficient */
+ { 0x00000fa0, 0x0000 }, /* R4000 (0xfa0) - ANC Coefficient */
+ { 0x00000fa1, 0x0000 }, /* R4001 (0xfa1) - ANC Coefficient */
+ { 0x00000fa2, 0x0000 }, /* R4002 (0xfa2) - ANC Coefficient */
+ { 0x00000fa3, 0x0000 }, /* R4003 (0xfa3) - ANC Coefficient */
+ { 0x00000fa4, 0x0000 }, /* R4004 (0xfa4) - ANC Coefficient */
+ { 0x00000fa5, 0x0000 }, /* R4005 (0xfa5) - ANC Coefficient */
+ { 0x00000fa6, 0x0000 }, /* R4006 (0xfa6) - ANC Coefficient */
+ { 0x00000fa7, 0x0000 }, /* R4007 (0xfa7) - ANC Coefficient */
+ { 0x00000fa8, 0x0000 }, /* R4008 (0xfa8) - ANC Coefficient */
+ { 0x00000fa9, 0x0000 }, /* R4009 (0xfa9) - ANC Coefficient */
+ { 0x00000faa, 0x0000 }, /* R4010 (0xfaa) - ANC Coefficient */
+ { 0x00000fab, 0x0000 }, /* R4011 (0xfab) - ANC Coefficient */
+ { 0x00000fac, 0x0000 }, /* R4012 (0xfac) - ANC Coefficient */
+ { 0x00000fad, 0x0000 }, /* R4013 (0xfad) - ANC Coefficient */
+ { 0x00000fae, 0x0000 }, /* R4014 (0xfae) - ANC Coefficient */
+ { 0x00000faf, 0x0000 }, /* R4015 (0xfaf) - ANC Coefficient */
+ { 0x00000fb0, 0x0000 }, /* R4016 (0xfb0) - ANC Coefficient */
+ { 0x00000fb1, 0x0000 }, /* R4017 (0xfb1) - ANC Coefficient */
+ { 0x00000fb2, 0x0000 }, /* R4018 (0xfb2) - ANC Coefficient */
+ { 0x00000fb3, 0x0000 }, /* R4019 (0xfb3) - ANC Coefficient */
+ { 0x00000fb4, 0x0000 }, /* R4020 (0xfb4) - ANC Coefficient */
+ { 0x00000fb5, 0x0000 }, /* R4021 (0xfb5) - ANC Coefficient */
+ { 0x00000fb6, 0x0000 }, /* R4022 (0xfb6) - ANC Coefficient */
+ { 0x00000fb7, 0x0000 }, /* R4023 (0xfb7) - ANC Coefficient */
+ { 0x00000fb8, 0x0000 }, /* R4024 (0xfb8) - ANC Coefficient */
+ { 0x00000fb9, 0x0000 }, /* R4025 (0xfb9) - ANC Coefficient */
+ { 0x00000fba, 0x0000 }, /* R4026 (0xfba) - ANC Coefficient */
+ { 0x00000fbb, 0x0000 }, /* R4027 (0xfbb) - ANC Coefficient */
+ { 0x00000fbc, 0x0000 }, /* R4028 (0xfbc) - ANC Coefficient */
+ { 0x00000fbd, 0x0000 }, /* R4029 (0xfbd) - ANC Coefficient */
+ { 0x00000fbe, 0x0000 }, /* R4030 (0xfbe) - ANC Coefficient */
+ { 0x00000fbf, 0x0000 }, /* R4031 (0xfbf) - ANC Coefficient */
+ { 0x00000fc0, 0x0000 }, /* R4032 (0xfc0) - ANC Coefficient */
+ { 0x00000fc1, 0x0000 }, /* R4033 (0xfc1) - ANC Coefficient */
+ { 0x00000fc2, 0x0000 }, /* R4034 (0xfc2) - ANC Coefficient */
+ { 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
+ { 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
+ { 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
+ { 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
+ { 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
+ { 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+ { 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+ { 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+ { 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+ { 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+ { 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+ { 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+ { 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+ { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
+ { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
+ { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
+ { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
+ { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
+ { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
+ { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
+ { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
+ { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
+ { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
+ { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
+ { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
+ { 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
+ { 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
+ { 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
+ { 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
+ { 0x000013e0, 0x0000 }, /* R5088 (0x13e0) - FRF Coefficient 4L 1 */
+ { 0x000013e1, 0x0000 }, /* R5089 (0x13e1) - FRF Coefficient 4L 2 */
+ { 0x000013e2, 0x0000 }, /* R5090 (0x13e2) - FRF Coefficient 4L 3 */
+ { 0x000013e3, 0x0000 }, /* R5091 (0x13e3) - FRF Coefficient 4L 4 */
+ { 0x000013f0, 0x0000 }, /* R5104 (0x13f0) - FRF Coefficient 4R 1 */
+ { 0x000013f1, 0x0000 }, /* R5105 (0x13f1) - FRF Coefficient 4R 2 */
+ { 0x000013f2, 0x0000 }, /* R5106 (0x13f2) - FRF Coefficient 4R 3 */
+ { 0x000013f3, 0x0000 }, /* R5107 (0x13f3) - FRF Coefficient 4R 4 */
+ { 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
+ { 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
+ { 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
+ { 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
+ { 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
+ { 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
+ { 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
+ { 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
+ { 0x00001420, 0x0000 }, /* R5152 (0x1420) - FRF Coefficient 6L 1 */
+ { 0x00001421, 0x0000 }, /* R5153 (0x1421) - FRF Coefficient 6L 2 */
+ { 0x00001422, 0x0000 }, /* R5154 (0x1422) - FRF Coefficient 6L 3 */
+ { 0x00001423, 0x0000 }, /* R5155 (0x1423) - FRF Coefficient 6L 4 */
+ { 0x00001430, 0x0000 }, /* R5168 (0x1430) - FRF Coefficient 6R 1 */
+ { 0x00001431, 0x0000 }, /* R5169 (0x1431) - FRF Coefficient 6R 2 */
+ { 0x00001432, 0x0000 }, /* R5170 (0x1432) - FRF Coefficient 6R 3 */
+ { 0x00001433, 0x0000 }, /* R5171 (0x1433) - FRF Coefficient 6R 4 */
+ { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+ { 0x00001701, 0xe000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+ { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+ { 0x00001703, 0xe000 }, /* R5891 (0x1703) - GPIO2 Control 2 */
+ { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+ { 0x00001705, 0xe000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+ { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+ { 0x00001707, 0xe000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+ { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+ { 0x00001709, 0xe000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+ { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+ { 0x0000170b, 0xe000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+ { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+ { 0x0000170d, 0xe000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+ { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+ { 0x0000170f, 0xe000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+ { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+ { 0x00001711, 0xe000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+ { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+ { 0x00001713, 0xe000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+ { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+ { 0x00001715, 0xe000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+ { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+ { 0x00001717, 0xe000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+ { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+ { 0x00001719, 0xE000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+ { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+ { 0x0000171b, 0xE000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+ { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+ { 0x0000171d, 0xE000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+ { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+ { 0x0000171f, 0xE000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+ { 0x00001720, 0x2001 }, /* R5920 (0x1720) - GPIO17 Control 1 */
+ { 0x00001721, 0xe000 }, /* R5921 (0x1721) - GPIO17 Control 2 */
+ { 0x00001722, 0x2001 }, /* R5922 (0x1722) - GPIO18 Control 1 */
+ { 0x00001723, 0xe000 }, /* R5923 (0x1723) - GPIO18 Control 2 */
+ { 0x00001724, 0x2001 }, /* R5924 (0x1724) - GPIO19 Control 1 */
+ { 0x00001725, 0xe000 }, /* R5925 (0x1725) - GPIO19 Control 2 */
+ { 0x00001726, 0x2001 }, /* R5926 (0x1726) - GPIO20 Control 1 */
+ { 0x00001727, 0xe000 }, /* R5927 (0x1727) - GPIO20 Control 2 */
+ { 0x00001728, 0x2001 }, /* R5928 (0x1728) - GPIO21 Control 1 */
+ { 0x00001729, 0xe000 }, /* R5929 (0x1729) - GPIO21 Control 2 */
+ { 0x0000172a, 0x2001 }, /* R5930 (0x172a) - GPIO22 Control 1 */
+ { 0x0000172b, 0xe000 }, /* R5931 (0x172b) - GPIO22 Control 2 */
+ { 0x0000172c, 0x2001 }, /* R5932 (0x172c) - GPIO23 Control 1 */
+ { 0x0000172d, 0xe000 }, /* R5933 (0x172d) - GPIO23 Control 2 */
+ { 0x0000172e, 0x2001 }, /* R5934 (0x172e) - GPIO24 Control 1 */
+ { 0x0000172f, 0xe000 }, /* R5935 (0x172f) - GPIO24 Control 2 */
+ { 0x00001730, 0x2001 }, /* R5936 (0x1730) - GPIO25 Control 1 */
+ { 0x00001731, 0xe000 }, /* R5937 (0x1731) - GPIO25 Control 2 */
+ { 0x00001732, 0x2001 }, /* R5938 (0x1732) - GPIO26 Control 1 */
+ { 0x00001733, 0xe000 }, /* R5939 (0x1733) - GPIO26 Control 2 */
+ { 0x00001734, 0x2001 }, /* R5940 (0x1734) - GPIO27 Control 1 */
+ { 0x00001735, 0xe000 }, /* R5941 (0x1735) - GPIO27 Control 2 */
+ { 0x00001736, 0x2001 }, /* R5942 (0x1736) - GPIO28 Control 1 */
+ { 0x00001737, 0xe000 }, /* R5943 (0x1737) - GPIO28 Control 2 */
+ { 0x00001738, 0x2001 }, /* R5944 (0x1738) - GPIO29 Control 1 */
+ { 0x00001739, 0xe000 }, /* R5945 (0x1739) - GPIO29 Control 2 */
+ { 0x0000173a, 0x2001 }, /* R5946 (0x173a) - GPIO30 Control 1 */
+ { 0x0000173b, 0xe000 }, /* R5947 (0x173b) - GPIO30 Control 2 */
+ { 0x0000173c, 0x2001 }, /* R5948 (0x173c) - GPIO31 Control 1 */
+ { 0x0000173d, 0xe000 }, /* R5949 (0x173d) - GPIO31 Control 2 */
+ { 0x0000173e, 0x2001 }, /* R5950 (0x173e) - GPIO32 Control 1 */
+ { 0x0000173f, 0xe000 }, /* R5951 (0x173f) - GPIO32 Control 2 */
+ { 0x00001740, 0x2001 }, /* R5952 (0x1740) - GPIO33 Control 1 */
+ { 0x00001741, 0xe000 }, /* R5953 (0x1741) - GPIO33 Control 2 */
+ { 0x00001742, 0x2001 }, /* R5954 (0x1742) - GPIO34 Control 1 */
+ { 0x00001743, 0xe000 }, /* R5955 (0x1743) - GPIO34 Control 2 */
+ { 0x00001744, 0x2001 }, /* R5956 (0x1744) - GPIO35 Control 1 */
+ { 0x00001745, 0xe000 }, /* R5957 (0x1745) - GPIO35 Control 2 */
+ { 0x00001746, 0x2001 }, /* R5958 (0x1746) - GPIO36 Control 1 */
+ { 0x00001747, 0xe000 }, /* R5959 (0x1747) - GPIO36 Control 2 */
+ { 0x00001748, 0x2001 }, /* R5960 (0x1748) - GPIO37 Control 1 */
+ { 0x00001749, 0xe000 }, /* R5961 (0x1749) - GPIO37 Control 2 */
+ { 0x0000174a, 0x2001 }, /* R5962 (0x174a) - GPIO38 Control 1 */
+ { 0x0000174b, 0xe000 }, /* R5963 (0x174b) - GPIO38 Control 2 */
+ { 0x0000174c, 0x2001 }, /* R5964 (0x174c) - GPIO39 Control 1 */
+ { 0x0000174d, 0xe000 }, /* R5965 (0x174d) - GPIO39 Control 2 */
+ { 0x0000174e, 0x2001 }, /* R5966 (0x174e) - GPIO40 Control 1 */
+ { 0x0000174f, 0xe000 }, /* R5967 (0x174f) - GPIO40 Control 2 */
+ { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+ { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+ { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+ { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+ { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+ { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+ { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+ { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+ { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+ { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+ { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+ { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+ { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+ { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+ { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+ { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+ { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+ { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+ { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+ { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+ { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+ { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+ { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+ { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+ { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+ { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+ { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+ { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+ { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+ { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+ { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+ { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+ { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+ { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+ { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l85_is_adsp_memory(unsigned int reg)
+{
+ switch (reg) {
+ case 0x080000 ... 0x085ffe:
+ case 0x0a0000 ... 0x0a7ffe:
+ case 0x0c0000 ... 0x0c1ffe:
+ case 0x0e0000 ... 0x0e1ffe:
+ case 0x100000 ... 0x10effe:
+ case 0x120000 ... 0x12bffe:
+ case 0x136000 ... 0x137ffe:
+ case 0x140000 ... 0x14bffe:
+ case 0x160000 ... 0x161ffe:
+ case 0x180000 ... 0x18effe:
+ case 0x1a0000 ... 0x1b1ffe:
+ case 0x1b6000 ... 0x1b7ffe:
+ case 0x1c0000 ... 0x1cbffe:
+ case 0x1e0000 ... 0x1e1ffe:
+ case 0x200000 ... 0x208ffe:
+ case 0x220000 ... 0x231ffe:
+ case 0x240000 ... 0x24bffe:
+ case 0x260000 ... 0x261ffe:
+ case 0x280000 ... 0x288ffe:
+ case 0x2a0000 ... 0x2a9ffe:
+ case 0x2c0000 ... 0x2c3ffe:
+ case 0x2e0000 ... 0x2e1ffe:
+ case 0x300000 ... 0x305ffe:
+ case 0x320000 ... 0x333ffe:
+ case 0x340000 ... 0x34bffe:
+ case 0x360000 ... 0x361ffe:
+ case 0x380000 ... 0x388ffe:
+ case 0x3a0000 ... 0x3a7ffe:
+ case 0x3c0000 ... 0x3c1ffe:
+ case 0x3e0000 ... 0x3e1ffe:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l85_16bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_TONE_GENERATOR_1:
+ case MADERA_TONE_GENERATOR_2:
+ case MADERA_TONE_GENERATOR_3:
+ case MADERA_TONE_GENERATOR_4:
+ case MADERA_TONE_GENERATOR_5:
+ case MADERA_PWM_DRIVE_1:
+ case MADERA_PWM_DRIVE_2:
+ case MADERA_PWM_DRIVE_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+ case MADERA_HAPTICS_CONTROL_1:
+ case MADERA_HAPTICS_CONTROL_2:
+ case MADERA_HAPTICS_PHASE_1_INTENSITY:
+ case MADERA_HAPTICS_PHASE_1_DURATION:
+ case MADERA_HAPTICS_PHASE_2_INTENSITY:
+ case MADERA_HAPTICS_PHASE_2_DURATION:
+ case MADERA_HAPTICS_PHASE_3_INTENSITY:
+ case MADERA_HAPTICS_PHASE_3_DURATION:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_COMFORT_NOISE_GENERATOR:
+ case MADERA_CLOCK_32K_1:
+ case MADERA_SYSTEM_CLOCK_1:
+ case MADERA_SAMPLE_RATE_1:
+ case MADERA_SAMPLE_RATE_2:
+ case MADERA_SAMPLE_RATE_3:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_ASYNC_CLOCK_1:
+ case MADERA_ASYNC_SAMPLE_RATE_1:
+ case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_2:
+ case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case MADERA_DSP_CLOCK_1:
+ case MADERA_DSP_CLOCK_2:
+ case MADERA_OUTPUT_SYSTEM_CLOCK:
+ case MADERA_OUTPUT_ASYNC_CLOCK:
+ case MADERA_RATE_ESTIMATOR_1:
+ case MADERA_RATE_ESTIMATOR_2:
+ case MADERA_RATE_ESTIMATOR_3:
+ case MADERA_RATE_ESTIMATOR_4:
+ case MADERA_RATE_ESTIMATOR_5:
+ case MADERA_FLL1_CONTROL_1:
+ case MADERA_FLL1_CONTROL_2:
+ case MADERA_FLL1_CONTROL_3:
+ case MADERA_FLL1_CONTROL_4:
+ case MADERA_FLL1_CONTROL_5:
+ case MADERA_FLL1_CONTROL_6:
+ case MADERA_FLL1_CONTROL_7:
+ case MADERA_FLL1_LOOP_FILTER_TEST_1:
+ case MADERA_FLL1_SYNCHRONISER_1:
+ case MADERA_FLL1_SYNCHRONISER_2:
+ case MADERA_FLL1_SYNCHRONISER_3:
+ case MADERA_FLL1_SYNCHRONISER_4:
+ case MADERA_FLL1_SYNCHRONISER_5:
+ case MADERA_FLL1_SYNCHRONISER_6:
+ case MADERA_FLL1_SYNCHRONISER_7:
+ case MADERA_FLL1_SPREAD_SPECTRUM:
+ case MADERA_FLL1_GPIO_CLOCK:
+ case MADERA_FLL2_CONTROL_1:
+ case MADERA_FLL2_CONTROL_2:
+ case MADERA_FLL2_CONTROL_3:
+ case MADERA_FLL2_CONTROL_4:
+ case MADERA_FLL2_CONTROL_5:
+ case MADERA_FLL2_CONTROL_6:
+ case MADERA_FLL2_CONTROL_7:
+ case MADERA_FLL2_LOOP_FILTER_TEST_1:
+ case MADERA_FLL2_SYNCHRONISER_1:
+ case MADERA_FLL2_SYNCHRONISER_2:
+ case MADERA_FLL2_SYNCHRONISER_3:
+ case MADERA_FLL2_SYNCHRONISER_4:
+ case MADERA_FLL2_SYNCHRONISER_5:
+ case MADERA_FLL2_SYNCHRONISER_6:
+ case MADERA_FLL2_SYNCHRONISER_7:
+ case MADERA_FLL2_SPREAD_SPECTRUM:
+ case MADERA_FLL2_GPIO_CLOCK:
+ case MADERA_FLL3_CONTROL_1:
+ case MADERA_FLL3_CONTROL_2:
+ case MADERA_FLL3_CONTROL_3:
+ case MADERA_FLL3_CONTROL_4:
+ case MADERA_FLL3_CONTROL_5:
+ case MADERA_FLL3_CONTROL_6:
+ case MADERA_FLL3_CONTROL_7:
+ case MADERA_FLL3_LOOP_FILTER_TEST_1:
+ case MADERA_FLL3_SYNCHRONISER_1:
+ case MADERA_FLL3_SYNCHRONISER_2:
+ case MADERA_FLL3_SYNCHRONISER_3:
+ case MADERA_FLL3_SYNCHRONISER_4:
+ case MADERA_FLL3_SYNCHRONISER_5:
+ case MADERA_FLL3_SYNCHRONISER_6:
+ case MADERA_FLL3_SYNCHRONISER_7:
+ case MADERA_FLL3_SPREAD_SPECTRUM:
+ case MADERA_FLL3_GPIO_CLOCK:
+ case MADERA_MIC_CHARGE_PUMP_1:
+ case MADERA_HP_CHARGE_PUMP_8:
+ case MADERA_LDO1_CONTROL_1:
+ case MADERA_LDO2_CONTROL_1:
+ case MADERA_MIC_BIAS_CTRL_1:
+ case MADERA_MIC_BIAS_CTRL_2:
+ case MADERA_MIC_BIAS_CTRL_3:
+ case MADERA_MIC_BIAS_CTRL_4:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_HP_CTRL_2L:
+ case MADERA_HP_CTRL_2R:
+ case MADERA_HP_CTRL_3L:
+ case MADERA_HP_CTRL_3R:
+ case MADERA_DCS_HP1L_CONTROL:
+ case MADERA_DCS_HP1R_CONTROL:
+ case MADERA_EDRE_HP_STEREO_CONTROL:
+ case MADERA_ACCESSORY_DETECT_MODE_1:
+ case MADERA_HEADPHONE_DETECT_1:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_MICD_CLAMP_CONTROL:
+ case MADERA_MIC_DETECT_1_CONTROL_1:
+ case MADERA_MIC_DETECT_1_CONTROL_2:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_1:
+ case MADERA_MIC_DETECT_1_LEVEL_2:
+ case MADERA_MIC_DETECT_1_LEVEL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_4:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_GP_SWITCH_1:
+ case MADERA_JACK_DETECT_ANALOGUE:
+ case MADERA_INPUT_ENABLES:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_INPUT_RATE:
+ case MADERA_INPUT_VOLUME_RAMP:
+ case MADERA_HPF_CONTROL:
+ case MADERA_IN1L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1L:
+ case MADERA_DMIC1L_CONTROL:
+ case MADERA_IN1R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1R:
+ case MADERA_DMIC1R_CONTROL:
+ case MADERA_IN2L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2L:
+ case MADERA_DMIC2L_CONTROL:
+ case MADERA_IN2R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2R:
+ case MADERA_DMIC2R_CONTROL:
+ case MADERA_IN3L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_3L:
+ case MADERA_DMIC3L_CONTROL:
+ case MADERA_IN3R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_3R:
+ case MADERA_DMIC3R_CONTROL:
+ case MADERA_IN4L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_4L:
+ case MADERA_DMIC4L_CONTROL:
+ case MADERA_IN4R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_4R:
+ case MADERA_DMIC4R_CONTROL:
+ case MADERA_IN5L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_5L:
+ case MADERA_DMIC5L_CONTROL:
+ case MADERA_IN5R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_5R:
+ case MADERA_DMIC5R_CONTROL:
+ case MADERA_IN6L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_6L:
+ case MADERA_DMIC6L_CONTROL:
+ case MADERA_IN6R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_6R:
+ case MADERA_DMIC6R_CONTROL:
+ case MADERA_OUTPUT_ENABLES_1:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_OUTPUT_RATE_1:
+ case MADERA_OUTPUT_VOLUME_RAMP:
+ case MADERA_OUTPUT_PATH_CONFIG_1L:
+ case MADERA_DAC_DIGITAL_VOLUME_1L:
+ case MADERA_NOISE_GATE_SELECT_1L:
+ case MADERA_OUTPUT_PATH_CONFIG_1R:
+ case MADERA_DAC_DIGITAL_VOLUME_1R:
+ case MADERA_NOISE_GATE_SELECT_1R:
+ case MADERA_OUTPUT_PATH_CONFIG_2L:
+ case MADERA_DAC_DIGITAL_VOLUME_2L:
+ case MADERA_NOISE_GATE_SELECT_2L:
+ case MADERA_OUTPUT_PATH_CONFIG_2R:
+ case MADERA_DAC_DIGITAL_VOLUME_2R:
+ case MADERA_NOISE_GATE_SELECT_2R:
+ case MADERA_OUTPUT_PATH_CONFIG_3L:
+ case MADERA_DAC_DIGITAL_VOLUME_3L:
+ case MADERA_NOISE_GATE_SELECT_3L:
+ case MADERA_OUTPUT_PATH_CONFIG_3R:
+ case MADERA_DAC_DIGITAL_VOLUME_3R:
+ case MADERA_NOISE_GATE_SELECT_3R:
+ case MADERA_OUTPUT_PATH_CONFIG_4L:
+ case MADERA_DAC_DIGITAL_VOLUME_4L:
+ case MADERA_NOISE_GATE_SELECT_4L:
+ case MADERA_OUTPUT_PATH_CONFIG_4R:
+ case MADERA_DAC_DIGITAL_VOLUME_4R:
+ case MADERA_NOISE_GATE_SELECT_4R:
+ case MADERA_OUTPUT_PATH_CONFIG_5L:
+ case MADERA_DAC_DIGITAL_VOLUME_5L:
+ case MADERA_NOISE_GATE_SELECT_5L:
+ case MADERA_OUTPUT_PATH_CONFIG_5R:
+ case MADERA_DAC_DIGITAL_VOLUME_5R:
+ case MADERA_NOISE_GATE_SELECT_5R:
+ case MADERA_OUTPUT_PATH_CONFIG_6L:
+ case MADERA_DAC_DIGITAL_VOLUME_6L:
+ case MADERA_NOISE_GATE_SELECT_6L:
+ case MADERA_OUTPUT_PATH_CONFIG_6R:
+ case MADERA_DAC_DIGITAL_VOLUME_6R:
+ case MADERA_NOISE_GATE_SELECT_6R:
+ case MADERA_DRE_ENABLE:
+ case MADERA_EDRE_ENABLE:
+ case MADERA_EDRE_MANUAL:
+ case MADERA_DAC_AEC_CONTROL_1:
+ case MADERA_DAC_AEC_CONTROL_2:
+ case MADERA_NOISE_GATE_CONTROL:
+ case MADERA_PDM_SPK1_CTRL_1:
+ case MADERA_PDM_SPK1_CTRL_2:
+ case MADERA_PDM_SPK2_CTRL_1:
+ case MADERA_PDM_SPK2_CTRL_2:
+ case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP2_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP3_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP_TEST_CTRL_5:
+ case MADERA_HP_TEST_CTRL_6:
+ case MADERA_AIF1_BCLK_CTRL:
+ case MADERA_AIF1_TX_PIN_CTRL:
+ case MADERA_AIF1_RX_PIN_CTRL:
+ case MADERA_AIF1_RATE_CTRL:
+ case MADERA_AIF1_FORMAT:
+ case MADERA_AIF1_RX_BCLK_RATE:
+ case MADERA_AIF1_FRAME_CTRL_1:
+ case MADERA_AIF1_FRAME_CTRL_2:
+ case MADERA_AIF1_FRAME_CTRL_3:
+ case MADERA_AIF1_FRAME_CTRL_4:
+ case MADERA_AIF1_FRAME_CTRL_5:
+ case MADERA_AIF1_FRAME_CTRL_6:
+ case MADERA_AIF1_FRAME_CTRL_7:
+ case MADERA_AIF1_FRAME_CTRL_8:
+ case MADERA_AIF1_FRAME_CTRL_9:
+ case MADERA_AIF1_FRAME_CTRL_10:
+ case MADERA_AIF1_FRAME_CTRL_11:
+ case MADERA_AIF1_FRAME_CTRL_12:
+ case MADERA_AIF1_FRAME_CTRL_13:
+ case MADERA_AIF1_FRAME_CTRL_14:
+ case MADERA_AIF1_FRAME_CTRL_15:
+ case MADERA_AIF1_FRAME_CTRL_16:
+ case MADERA_AIF1_FRAME_CTRL_17:
+ case MADERA_AIF1_FRAME_CTRL_18:
+ case MADERA_AIF1_TX_ENABLES:
+ case MADERA_AIF1_RX_ENABLES:
+ case MADERA_AIF2_BCLK_CTRL:
+ case MADERA_AIF2_TX_PIN_CTRL:
+ case MADERA_AIF2_RX_PIN_CTRL:
+ case MADERA_AIF2_RATE_CTRL:
+ case MADERA_AIF2_FORMAT:
+ case MADERA_AIF2_RX_BCLK_RATE:
+ case MADERA_AIF2_FRAME_CTRL_1:
+ case MADERA_AIF2_FRAME_CTRL_2:
+ case MADERA_AIF2_FRAME_CTRL_3:
+ case MADERA_AIF2_FRAME_CTRL_4:
+ case MADERA_AIF2_FRAME_CTRL_5:
+ case MADERA_AIF2_FRAME_CTRL_6:
+ case MADERA_AIF2_FRAME_CTRL_7:
+ case MADERA_AIF2_FRAME_CTRL_8:
+ case MADERA_AIF2_FRAME_CTRL_9:
+ case MADERA_AIF2_FRAME_CTRL_10:
+ case MADERA_AIF2_FRAME_CTRL_11:
+ case MADERA_AIF2_FRAME_CTRL_12:
+ case MADERA_AIF2_FRAME_CTRL_13:
+ case MADERA_AIF2_FRAME_CTRL_14:
+ case MADERA_AIF2_FRAME_CTRL_15:
+ case MADERA_AIF2_FRAME_CTRL_16:
+ case MADERA_AIF2_FRAME_CTRL_17:
+ case MADERA_AIF2_FRAME_CTRL_18:
+ case MADERA_AIF2_TX_ENABLES:
+ case MADERA_AIF2_RX_ENABLES:
+ case MADERA_AIF3_BCLK_CTRL:
+ case MADERA_AIF3_TX_PIN_CTRL:
+ case MADERA_AIF3_RX_PIN_CTRL:
+ case MADERA_AIF3_RATE_CTRL:
+ case MADERA_AIF3_FORMAT:
+ case MADERA_AIF3_RX_BCLK_RATE:
+ case MADERA_AIF3_FRAME_CTRL_1:
+ case MADERA_AIF3_FRAME_CTRL_2:
+ case MADERA_AIF3_FRAME_CTRL_3:
+ case MADERA_AIF3_FRAME_CTRL_4:
+ case MADERA_AIF3_FRAME_CTRL_11:
+ case MADERA_AIF3_FRAME_CTRL_12:
+ case MADERA_AIF3_TX_ENABLES:
+ case MADERA_AIF3_RX_ENABLES:
+ case MADERA_AIF4_BCLK_CTRL:
+ case MADERA_AIF4_TX_PIN_CTRL:
+ case MADERA_AIF4_RX_PIN_CTRL:
+ case MADERA_AIF4_RATE_CTRL:
+ case MADERA_AIF4_FORMAT:
+ case MADERA_AIF4_RX_BCLK_RATE:
+ case MADERA_AIF4_FRAME_CTRL_1:
+ case MADERA_AIF4_FRAME_CTRL_2:
+ case MADERA_AIF4_FRAME_CTRL_3:
+ case MADERA_AIF4_FRAME_CTRL_4:
+ case MADERA_AIF4_FRAME_CTRL_11:
+ case MADERA_AIF4_FRAME_CTRL_12:
+ case MADERA_AIF4_TX_ENABLES:
+ case MADERA_AIF4_RX_ENABLES:
+ case MADERA_SPD1_TX_CONTROL:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+ case MADERA_SLIMBUS_RATES_1:
+ case MADERA_SLIMBUS_RATES_2:
+ case MADERA_SLIMBUS_RATES_3:
+ case MADERA_SLIMBUS_RATES_4:
+ case MADERA_SLIMBUS_RATES_5:
+ case MADERA_SLIMBUS_RATES_6:
+ case MADERA_SLIMBUS_RATES_7:
+ case MADERA_SLIMBUS_RATES_8:
+ case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_PWM1MIX_INPUT_1_SOURCE:
+ case MADERA_PWM1MIX_INPUT_1_VOLUME:
+ case MADERA_PWM1MIX_INPUT_2_SOURCE:
+ case MADERA_PWM1MIX_INPUT_2_VOLUME:
+ case MADERA_PWM1MIX_INPUT_3_SOURCE:
+ case MADERA_PWM1MIX_INPUT_3_VOLUME:
+ case MADERA_PWM1MIX_INPUT_4_SOURCE:
+ case MADERA_PWM1MIX_INPUT_4_VOLUME:
+ case MADERA_PWM2MIX_INPUT_1_SOURCE:
+ case MADERA_PWM2MIX_INPUT_1_VOLUME:
+ case MADERA_PWM2MIX_INPUT_2_SOURCE:
+ case MADERA_PWM2MIX_INPUT_2_VOLUME:
+ case MADERA_PWM2MIX_INPUT_3_SOURCE:
+ case MADERA_PWM2MIX_INPUT_3_VOLUME:
+ case MADERA_PWM2MIX_INPUT_4_SOURCE:
+ case MADERA_PWM2MIX_INPUT_4_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT4LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT4LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT4RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT4RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT4RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT4RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT4RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT4RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT4RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT4RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT6LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT6LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT6LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT6LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT6LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT6LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT6LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT6LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT6RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT6RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT6RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT6RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT6RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT6RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT6RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT6RMIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_4_VOLUME:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_1_SOURCE:
+ case MADERA_EQ1MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_2_SOURCE:
+ case MADERA_EQ1MIX_INPUT_2_VOLUME:
+ case MADERA_EQ1MIX_INPUT_3_SOURCE:
+ case MADERA_EQ1MIX_INPUT_3_VOLUME:
+ case MADERA_EQ1MIX_INPUT_4_SOURCE:
+ case MADERA_EQ1MIX_INPUT_4_VOLUME:
+ case MADERA_EQ2MIX_INPUT_1_SOURCE:
+ case MADERA_EQ2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ2MIX_INPUT_2_SOURCE:
+ case MADERA_EQ2MIX_INPUT_2_VOLUME:
+ case MADERA_EQ2MIX_INPUT_3_SOURCE:
+ case MADERA_EQ2MIX_INPUT_3_VOLUME:
+ case MADERA_EQ2MIX_INPUT_4_SOURCE:
+ case MADERA_EQ2MIX_INPUT_4_VOLUME:
+ case MADERA_EQ3MIX_INPUT_1_SOURCE:
+ case MADERA_EQ3MIX_INPUT_1_VOLUME:
+ case MADERA_EQ3MIX_INPUT_2_SOURCE:
+ case MADERA_EQ3MIX_INPUT_2_VOLUME:
+ case MADERA_EQ3MIX_INPUT_3_SOURCE:
+ case MADERA_EQ3MIX_INPUT_3_VOLUME:
+ case MADERA_EQ3MIX_INPUT_4_SOURCE:
+ case MADERA_EQ3MIX_INPUT_4_VOLUME:
+ case MADERA_EQ4MIX_INPUT_1_SOURCE:
+ case MADERA_EQ4MIX_INPUT_1_VOLUME:
+ case MADERA_EQ4MIX_INPUT_2_SOURCE:
+ case MADERA_EQ4MIX_INPUT_2_VOLUME:
+ case MADERA_EQ4MIX_INPUT_3_SOURCE:
+ case MADERA_EQ4MIX_INPUT_3_VOLUME:
+ case MADERA_EQ4MIX_INPUT_4_SOURCE:
+ case MADERA_EQ4MIX_INPUT_4_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP4AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP5AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_1LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_1RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_2LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_2RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_1LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_1RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_2LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_2RMIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4INT2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP6AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP7AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_FX_CTRL1:
+ case MADERA_FX_CTRL2:
+ case MADERA_EQ1_1 ... MADERA_EQ1_21:
+ case MADERA_EQ2_1 ... MADERA_EQ2_21:
+ case MADERA_EQ3_1 ... MADERA_EQ3_21:
+ case MADERA_EQ4_1 ... MADERA_EQ4_21:
+ case MADERA_DRC1_CTRL1:
+ case MADERA_DRC1_CTRL2:
+ case MADERA_DRC1_CTRL3:
+ case MADERA_DRC1_CTRL4:
+ case MADERA_DRC1_CTRL5:
+ case MADERA_DRC2_CTRL1:
+ case MADERA_DRC2_CTRL2:
+ case MADERA_DRC2_CTRL3:
+ case MADERA_DRC2_CTRL4:
+ case MADERA_DRC2_CTRL5:
+ case MADERA_HPLPF1_1:
+ case MADERA_HPLPF1_2:
+ case MADERA_HPLPF2_1:
+ case MADERA_HPLPF2_2:
+ case MADERA_HPLPF3_1:
+ case MADERA_HPLPF3_2:
+ case MADERA_HPLPF4_1:
+ case MADERA_HPLPF4_2:
+ case MADERA_ASRC1_ENABLE:
+ case MADERA_ASRC1_STATUS:
+ case MADERA_ASRC1_RATE1:
+ case MADERA_ASRC1_RATE2:
+ case MADERA_ASRC2_ENABLE:
+ case MADERA_ASRC2_STATUS:
+ case MADERA_ASRC2_RATE1:
+ case MADERA_ASRC2_RATE2:
+ case MADERA_ISRC_1_CTRL_1:
+ case MADERA_ISRC_1_CTRL_2:
+ case MADERA_ISRC_1_CTRL_3:
+ case MADERA_ISRC_2_CTRL_1:
+ case MADERA_ISRC_2_CTRL_2:
+ case MADERA_ISRC_2_CTRL_3:
+ case MADERA_ISRC_3_CTRL_1:
+ case MADERA_ISRC_3_CTRL_2:
+ case MADERA_ISRC_3_CTRL_3:
+ case MADERA_ISRC_4_CTRL_1:
+ case MADERA_ISRC_4_CTRL_2:
+ case MADERA_ISRC_4_CTRL_3:
+ case MADERA_CLOCK_CONTROL:
+ case MADERA_ANC_SRC:
+ case MADERA_DSP_STATUS:
+ case MADERA_ANC_COEFF_START ... MADERA_ANC_COEFF_END:
+ case MADERA_FCL_FILTER_CONTROL:
+ case MADERA_FCL_ADC_REFORMATTER_CONTROL:
+ case MADERA_FCL_COEFF_START ... MADERA_FCL_COEFF_END:
+ case MADERA_FCR_FILTER_CONTROL:
+ case MADERA_FCR_ADC_REFORMATTER_CONTROL:
+ case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
+ case MADERA_DAC_COMP_1:
+ case MADERA_DAC_COMP_2:
+ case MADERA_FRF_COEFFICIENT_1L_1:
+ case MADERA_FRF_COEFFICIENT_1L_2:
+ case MADERA_FRF_COEFFICIENT_1L_3:
+ case MADERA_FRF_COEFFICIENT_1L_4:
+ case MADERA_FRF_COEFFICIENT_1R_1:
+ case MADERA_FRF_COEFFICIENT_1R_2:
+ case MADERA_FRF_COEFFICIENT_1R_3:
+ case MADERA_FRF_COEFFICIENT_1R_4:
+ case MADERA_FRF_COEFFICIENT_2L_1:
+ case MADERA_FRF_COEFFICIENT_2L_2:
+ case MADERA_FRF_COEFFICIENT_2L_3:
+ case MADERA_FRF_COEFFICIENT_2L_4:
+ case MADERA_FRF_COEFFICIENT_2R_1:
+ case MADERA_FRF_COEFFICIENT_2R_2:
+ case MADERA_FRF_COEFFICIENT_2R_3:
+ case MADERA_FRF_COEFFICIENT_2R_4:
+ case MADERA_FRF_COEFFICIENT_3L_1:
+ case MADERA_FRF_COEFFICIENT_3L_2:
+ case MADERA_FRF_COEFFICIENT_3L_3:
+ case MADERA_FRF_COEFFICIENT_3L_4:
+ case MADERA_FRF_COEFFICIENT_3R_1:
+ case MADERA_FRF_COEFFICIENT_3R_2:
+ case MADERA_FRF_COEFFICIENT_3R_3:
+ case MADERA_FRF_COEFFICIENT_3R_4:
+ case MADERA_FRF_COEFFICIENT_4L_1:
+ case MADERA_FRF_COEFFICIENT_4L_2:
+ case MADERA_FRF_COEFFICIENT_4L_3:
+ case MADERA_FRF_COEFFICIENT_4L_4:
+ case MADERA_FRF_COEFFICIENT_4R_1:
+ case MADERA_FRF_COEFFICIENT_4R_2:
+ case MADERA_FRF_COEFFICIENT_4R_3:
+ case MADERA_FRF_COEFFICIENT_4R_4:
+ case MADERA_FRF_COEFFICIENT_5L_1:
+ case MADERA_FRF_COEFFICIENT_5L_2:
+ case MADERA_FRF_COEFFICIENT_5L_3:
+ case MADERA_FRF_COEFFICIENT_5L_4:
+ case MADERA_FRF_COEFFICIENT_5R_1:
+ case MADERA_FRF_COEFFICIENT_5R_2:
+ case MADERA_FRF_COEFFICIENT_5R_3:
+ case MADERA_FRF_COEFFICIENT_5R_4:
+ case MADERA_FRF_COEFFICIENT_6L_1:
+ case MADERA_FRF_COEFFICIENT_6L_2:
+ case MADERA_FRF_COEFFICIENT_6L_3:
+ case MADERA_FRF_COEFFICIENT_6L_4:
+ case MADERA_FRF_COEFFICIENT_6R_1:
+ case MADERA_FRF_COEFFICIENT_6R_2:
+ case MADERA_FRF_COEFFICIENT_6R_3:
+ case MADERA_FRF_COEFFICIENT_6R_4:
+ case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO40_CTRL_2:
+ case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ case MADERA_INTERRUPT_DEBOUNCE_7:
+ case MADERA_IRQ1_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l85_16bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_HP_CTRL_2L:
+ case MADERA_HP_CTRL_2R:
+ case MADERA_HP_CTRL_3L:
+ case MADERA_HP_CTRL_3R:
+ case MADERA_DCS_HP1L_CONTROL:
+ case MADERA_DCS_HP1R_CONTROL:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_FX_CTRL2:
+ case MADERA_ASRC2_STATUS:
+ case MADERA_ASRC1_STATUS:
+ case MADERA_CLOCK_CONTROL:
+ case MADERA_IRQ1_STATUS_1 ...MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l85_32bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+ case CS47L85_OTP_HPDET_CAL_1 ... CS47L85_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+ case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_SCRATCH_2:
+ case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_SCRATCH_2:
+ case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_SCRATCH_2:
+ case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_SCRATCH_2:
+ return true;
+ default:
+ return cs47l85_is_adsp_memory(reg);
+ }
+}
+
+static bool cs47l85_32bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+ case CS47L85_OTP_HPDET_CAL_1 ... CS47L85_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+ case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_SCRATCH_2:
+ case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_SCRATCH_2:
+ case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_SCRATCH_2:
+ case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_SCRATCH_2:
+ return true;
+ default:
+ return cs47l85_is_adsp_memory(reg);
+ }
+}
+
+const struct regmap_config cs47l85_16bit_spi_regmap = {
+ .name = "cs47l85_16bit",
+ .reg_bits = 32,
+ .pad_bits = 16,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = 0x2fff,
+ .readable_reg = cs47l85_16bit_readable_register,
+ .volatile_reg = cs47l85_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l85_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l85_16bit_spi_regmap);
+
+const struct regmap_config cs47l85_16bit_i2c_regmap = {
+ .name = "cs47l85_16bit",
+ .reg_bits = 32,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = 0x2fff,
+ .readable_reg = cs47l85_16bit_readable_register,
+ .volatile_reg = cs47l85_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l85_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l85_16bit_i2c_regmap);
+
+const struct regmap_config cs47l85_32bit_spi_regmap = {
+ .name = "cs47l85_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .pad_bits = 16,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP7_SCRATCH_2,
+ .readable_reg = cs47l85_32bit_readable_register,
+ .volatile_reg = cs47l85_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l85_32bit_spi_regmap);
+
+const struct regmap_config cs47l85_32bit_i2c_regmap = {
+ .name = "cs47l85_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP7_SCRATCH_2,
+ .readable_reg = cs47l85_32bit_readable_register,
+ .volatile_reg = cs47l85_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l85_32bit_i2c_regmap);
diff --git a/drivers/mfd/cs47l90-tables.c b/drivers/mfd/cs47l90-tables.c
new file mode 100644
index 000000000000..77207d98f0cc
--- /dev/null
+++ b/drivers/mfd/cs47l90-tables.c
@@ -0,0 +1,2674 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L90 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l90_reva_16_patch[] = {
+ { 0x8A, 0x5555 },
+ { 0x8A, 0xAAAA },
+ { 0x4CF, 0x0700 },
+ { 0x171, 0x0003 },
+ { 0x101, 0x0444 },
+ { 0x159, 0x0002 },
+ { 0x120, 0x0444 },
+ { 0x1D1, 0x0004 },
+ { 0x1E0, 0xC084 },
+ { 0x159, 0x0000 },
+ { 0x120, 0x0404 },
+ { 0x101, 0x0404 },
+ { 0x171, 0x0002 },
+ { 0x17A, 0x2906 },
+ { 0x19A, 0x2906 },
+ { 0x441, 0xC750 },
+ { 0x340, 0x0001 },
+ { 0x112, 0x0405 },
+ { 0x124, 0x0C49 },
+ { 0x1300, 0x050E },
+ { 0x1302, 0x0101 },
+ { 0x1380, 0x0425 },
+ { 0x1381, 0xF6D8 },
+ { 0x1382, 0x0632 },
+ { 0x1383, 0xFEC8 },
+ { 0x1390, 0x042F },
+ { 0x1391, 0xF6CA },
+ { 0x1392, 0x0637 },
+ { 0x1393, 0xFEC8 },
+ { 0x281, 0x0000 },
+ { 0x282, 0x0000 },
+ { 0x4EA, 0x0100 },
+ { 0x8A, 0xCCCC },
+ { 0x8A, 0x3333 },
+};
+
+int cs47l90_patch(struct madera *madera)
+{
+ int ret;
+
+ ret = regmap_register_patch(madera->regmap,
+ cs47l90_reva_16_patch,
+ ARRAY_SIZE(cs47l90_reva_16_patch));
+ if (ret < 0) {
+ dev_err(madera->dev,
+ "Error in applying 16-bit patch: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cs47l90_patch);
+
+static const struct reg_default cs47l90_reg_default[] = {
+ { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+ { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+ { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+ { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+ { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+ { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+ { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+ { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+ { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+ { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+ { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+ { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4 */
+ { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1 */
+ { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2 */
+ { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+ { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+ { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+ { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+ { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+ { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+ { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+ { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+ { 0x000000a0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+ { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+ { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+ { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+ { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+ { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+ { 0x00000112, 0x0405 }, /* R274 (0x112) - Async clock 1 */
+ { 0x00000113, 0x0011 }, /* R275 (0x113) - Async sample rate 1 */
+ { 0x00000114, 0x0011 }, /* R276 (0x114) - Async sample rate 2 */
+ { 0x00000120, 0x0404 }, /* R288 (0x120) - DSP Clock 1 */
+ { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+ { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+ { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+ { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+ { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+ { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+ { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+ { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+ { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+ { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+ { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+ { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+ { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+ { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+ { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+ { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+ { 0x0000017a, 0x2906 }, /* R377 (0x17a) - FLL1 Efs 2 */
+ { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
+ { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 2 */
+ { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 3 */
+ { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 4 */
+ { 0x00000185, 0x0000 }, /* R389 (0x185) - FLL1 Synchroniser 5 */
+ { 0x00000186, 0x0000 }, /* R390 (0x186) - FLL1 Synchroniser 6 */
+ { 0x00000187, 0x0001 }, /* R391 (0x187) - FLL1 Synchroniser 7 */
+ { 0x00000189, 0x0000 }, /* R393 (0x189) - FLL1 Spread Spectrum */
+ { 0x0000018a, 0x0004 }, /* R394 (0x18a) - FLL1 GPIO Clock */
+ { 0x00000191, 0x0002 }, /* R401 (0x191) - FLL2 Control 1 */
+ { 0x00000192, 0x0008 }, /* R402 (0x192) - FLL2 Control 2 */
+ { 0x00000193, 0x0018 }, /* R403 (0x193) - FLL2 Control 3 */
+ { 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
+ { 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
+ { 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
+ { 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
+ { 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
+ { 0x0000019a, 0x2906 }, /* R410 (0x19a) - FLL2 Efs 2 */
+ { 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
+ { 0x000001a2, 0x0000 }, /* R418 (0x1a2) - FLL2 Synchroniser 2 */
+ { 0x000001a3, 0x0000 }, /* R419 (0x1a3) - FLL2 Synchroniser 3 */
+ { 0x000001a4, 0x0000 }, /* R420 (0x1a4) - FLL2 Synchroniser 4 */
+ { 0x000001a5, 0x0000 }, /* R421 (0x1a5) - FLL2 Synchroniser 5 */
+ { 0x000001a6, 0x0000 }, /* R422 (0x1a6) - FLL2 Synchroniser 6 */
+ { 0x000001a7, 0x0001 }, /* R423 (0x1a7) - FLL2 Synchroniser 7 */
+ { 0x000001a9, 0x0000 }, /* R425 (0x1a9) - FLL2 Spread Spectrum */
+ { 0x000001aa, 0x0004 }, /* R426 (0x1aa) - FLL2 GPIO Clock */
+ { 0x000001d1, 0x0004 }, /* R465 (0x1d1) - FLLAO_CONTROL_1 */
+ { 0x000001d2, 0x0004 }, /* R466 (0x1d2) - FLLAO_CONTROL_2 */
+ { 0x000001d3, 0x0000 }, /* R467 (0x1d3) - FLLAO_CONTROL_3 */
+ { 0x000001d4, 0x0000 }, /* R468 (0x1d4) - FLLAO_CONTROL_4 */
+ { 0x000001d5, 0x0001 }, /* R469 (0x1d5) - FLLAO_CONTROL_5 */
+ { 0x000001d6, 0x8004 }, /* R470 (0x1d6) - FLLAO_CONTROL_6 */
+ { 0x000001d8, 0x0000 }, /* R472 (0x1d8) - FLLAO_CONTROL_7 */
+ { 0x000001da, 0x0070 }, /* R474 (0x1da) - FLLAO_CONTROL_8 */
+ { 0x000001db, 0x0000 }, /* R475 (0x1db) - FLLAO_CONTROL_9 */
+ { 0x000001dc, 0x06da }, /* R476 (0x1dc) - FLLAO_CONTROL_10 */
+ { 0x000001dd, 0x0011 }, /* R477 (0x1dd) - FLLAO_CONTROL_11 */
+ { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+ { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+ { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+ { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+ { 0x0000021c, 0x2222 }, /* R540 (0x21c) - Mic Bias Ctrl 5 */
+ { 0x0000021e, 0x2222 }, /* R542 (0x21e) - Mic Bias Ctrl 6 */
+ { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+ { 0x00000293, 0x0080 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+ { 0x00000299, 0x0000 }, /* R665 (0x299) - Headphone Detect 0 */
+ { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+ { 0x000002a2, 0x0010 }, /* R674 (0x2a2) - Mic Detect 1 Control 0 */
+ { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect 1 Control 1 */
+ { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect 1 Control 2 */
+ { 0x000002a6, 0x3d3d }, /* R678 (0x2a6) - Mic Detect 1 Level 1 */
+ { 0x000002a7, 0x3d3d }, /* R679 (0x2a7) - Mic Detect 1 Level 2 */
+ { 0x000002a8, 0x333d }, /* R680 (0x2a8) - Mic Detect 1 Level 3 */
+ { 0x000002a9, 0x202d }, /* R681 (0x2a9) - Mic Detect 1 Level 4 */
+ { 0x000002b2, 0x0010 }, /* R690 (0x2b2) - Mic Detect 2 Control 0 */
+ { 0x000002b3, 0x1102 }, /* R691 (0x2b3) - Mic Detect 2 Control 1 */
+ { 0x000002b4, 0x009f }, /* R692 (0x2b4) - Mic Detect 2 Control 2 */
+ { 0x000002b6, 0x3d3d }, /* R694 (0x2b6) - Mic Detect 2 Level 1 */
+ { 0x000002b7, 0x3d3d }, /* R695 (0x2b7) - Mic Detect 2 Level 2 */
+ { 0x000002b8, 0x333d }, /* R696 (0x2b8) - Mic Detect 2 Level 3 */
+ { 0x000002b9, 0x202d }, /* R697 (0x2b9) - Mic Detect 2 Level 4 */
+ { 0x000002c6, 0x0010 }, /* R710 (0x2c6) - Mic Clamp control */
+ { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+ { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+ { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+ { 0x00000308, 0x0400 }, /* R776 (0x308) - Input Rate */
+ { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+ { 0x0000030c, 0x0002 }, /* R780 (0x30C) - HPF Control */
+ { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+ { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+ { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+ { 0x00000313, 0x0000 }, /* R787 (0x313) - IN1L Rate Control */
+ { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+ { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+ { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+ { 0x00000317, 0x0000 }, /* R791 (0x317) - IN1R Rate Control */
+ { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+ { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+ { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+ { 0x0000031b, 0x0000 }, /* R795 (0x31b) - IN2L Rate Control */
+ { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+ { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+ { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+ { 0x0000031f, 0x0000 }, /* R799 (0x31f) - IN2R Rate Control */
+ { 0x00000320, 0x0000 }, /* R800 (0x320) - IN3L Control */
+ { 0x00000321, 0x0180 }, /* R801 (0x321) - ADC Digital Volume 3L */
+ { 0x00000322, 0x0500 }, /* R802 (0x322) - DMIC3L Control */
+ { 0x00000323, 0x0000 }, /* R803 (0x323) - IN3L Rate Control */
+ { 0x00000324, 0x0000 }, /* R804 (0x324) - IN3R Control */
+ { 0x00000325, 0x0180 }, /* R805 (0x325) - ADC Digital Volume 3R */
+ { 0x00000326, 0x0000 }, /* R806 (0x326) - DMIC3R Control */
+ { 0x00000327, 0x0000 }, /* R807 (0x327) - IN3R Rate Control */
+ { 0x00000328, 0x0000 }, /* R808 (0x328) - IN4 Control */
+ { 0x00000329, 0x0180 }, /* R809 (0x329) - ADC Digital Volume 4L */
+ { 0x0000032a, 0x0500 }, /* R810 (0x32a) - DMIC4L Control */
+ { 0x0000032b, 0x0000 }, /* R811 (0x32b) - IN4L Rate Control */
+ { 0x0000032c, 0x0000 }, /* R812 (0x32c) - IN4R Control */
+ { 0x0000032d, 0x0180 }, /* R813 (0x32d) - ADC Digital Volume 4R */
+ { 0x0000032e, 0x0000 }, /* R814 (0x32e) - DMIC4R Control */
+ { 0x0000032f, 0x0000 }, /* R815 (0x32f) - IN4R Rate Control */
+ { 0x00000330, 0x0000 }, /* R816 (0x330) - IN5L Control */
+ { 0x00000331, 0x0180 }, /* R817 (0x331) - ADC Digital Volume 5L */
+ { 0x00000332, 0x0500 }, /* R818 (0x332) - DMIC5L Control */
+ { 0x00000333, 0x0000 }, /* R819 (0x333) - IN5L Rate Control */
+ { 0x00000334, 0x0000 }, /* R820 (0x334) - IN5R Control */
+ { 0x00000335, 0x0180 }, /* R821 (0x335) - ADC Digital Volume 5R */
+ { 0x00000336, 0x0000 }, /* R822 (0x336) - DMIC5R Control */
+ { 0x00000337, 0x0000 }, /* R823 (0x337) - IN5R Rate Control */
+ { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+ { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+ { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+ { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+ { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+ { 0x00000412, 0x0000 }, /* R1042 (0x412) - Output Path Config 1 */
+ { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+ { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+ { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+ { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+ { 0x00000418, 0x0080 }, /* R1048 (0x418) - Output Path Config 2L */
+ { 0x00000419, 0x0180 }, /* R1049 (0x419) - DAC Digital Volume 2L */
+ { 0x0000041a, 0x0002 }, /* R1050 (0x41a) - Output Path Config 2 */
+ { 0x0000041b, 0x0004 }, /* R1051 (0x41b) - Noise Gate Select 2L */
+ { 0x0000041c, 0x0080 }, /* R1052 (0x41c) - Output Path Config 2R */
+ { 0x0000041d, 0x0180 }, /* R1053 (0x41d) - DAC Digital Volume 2R */
+ { 0x0000041f, 0x0008 }, /* R1055 (0x41f) - Noise Gate Select 2R */
+ { 0x00000420, 0x0080 }, /* R1056 (0x420) - Output Path Config 3L */
+ { 0x00000421, 0x0180 }, /* R1057 (0x421) - DAC Digital Volume 3L */
+ { 0x00000423, 0x0010 }, /* R1059 (0x423) - Noise Gate Select 3L */
+ { 0x00000424, 0x0080 }, /* R1060 (0x424) - Output Path Config 3R */
+ { 0x00000425, 0x0180 }, /* R1061 (0x425) - DAC Digital Volume 3R */
+ { 0x00000427, 0x0020 }, /* R1063 (0x427) - Noise Gate Select 3R */
+ { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+ { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+ { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+ { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+ { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+ { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+ { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
+ { 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */
+ { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+ { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
+ { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
+ { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
+ { 0x000004a0, 0x3080 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+ { 0x000004a1, 0x3000 }, /* R1185 (0x4a1) - HP2 Short Circuit Ctrl */
+ { 0x000004a2, 0x3000 }, /* R1186 (0x4a2) - HP3 Short Circuit Ctrl */
+ { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+ { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+ { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+ { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+ { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+ { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+ { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+ { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+ { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+ { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+ { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+ { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+ { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+ { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+ { 0x0000050f, 0x0006 }, /* R1295 (0x50f) - AIF1 Frame Ctrl 9 */
+ { 0x00000510, 0x0007 }, /* R1296 (0x510) - AIF1 Frame Ctrl 10 */
+ { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+ { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+ { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+ { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+ { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+ { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+ { 0x00000517, 0x0006 }, /* R1303 (0x517) - AIF1 Frame Ctrl 17 */
+ { 0x00000518, 0x0007 }, /* R1304 (0x518) - AIF1 Frame Ctrl 18 */
+ { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+ { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+ { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+ { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+ { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+ { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+ { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+ { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+ { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+ { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+ { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+ { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+ { 0x0000054b, 0x0002 }, /* R1355 (0x54b) - AIF2 Frame Ctrl 5 */
+ { 0x0000054c, 0x0003 }, /* R1356 (0x54c) - AIF2 Frame Ctrl 6 */
+ { 0x0000054d, 0x0004 }, /* R1357 (0x54d) - AIF2 Frame Ctrl 7 */
+ { 0x0000054e, 0x0005 }, /* R1358 (0x54e) - AIF2 Frame Ctrl 8 */
+ { 0x0000054f, 0x0006 }, /* R1359 (0x54f) - AIF2 Frame Ctrl 9 */
+ { 0x00000550, 0x0007 }, /* R1360 (0x550) - AIF2 Frame Ctrl 10 */
+ { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+ { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+ { 0x00000553, 0x0002 }, /* R1363 (0x553) - AIF2 Frame Ctrl 13 */
+ { 0x00000554, 0x0003 }, /* R1364 (0x554) - AIF2 Frame Ctrl 14 */
+ { 0x00000555, 0x0004 }, /* R1365 (0x555) - AIF2 Frame Ctrl 15 */
+ { 0x00000556, 0x0005 }, /* R1366 (0x556) - AIF2 Frame Ctrl 16 */
+ { 0x00000557, 0x0006 }, /* R1367 (0x557) - AIF2 Frame Ctrl 17 */
+ { 0x00000558, 0x0007 }, /* R1368 (0x558) - AIF2 Frame Ctrl 18 */
+ { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+ { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+ { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+ { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+ { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+ { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+ { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+ { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+ { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+ { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+ { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+ { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+ { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+ { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+ { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+ { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+ { 0x000005a0, 0x000c }, /* R1440 (0x5a0) - AIF4 BCLK Ctrl */
+ { 0x000005a1, 0x0000 }, /* R1441 (0x5a1) - AIF4 Tx Pin Ctrl */
+ { 0x000005a2, 0x0000 }, /* R1442 (0x5a2) - AIF4 Rx Pin Ctrl */
+ { 0x000005a3, 0x0000 }, /* R1443 (0x5a3) - AIF4 Rate Ctrl */
+ { 0x000005a4, 0x0000 }, /* R1444 (0x5a4) - AIF4 Format */
+ { 0x000005a6, 0x0040 }, /* R1446 (0x5a6) - AIF4 Rx BCLK Rate */
+ { 0x000005a7, 0x1818 }, /* R1447 (0x5a7) - AIF4 Frame Ctrl 1 */
+ { 0x000005a8, 0x1818 }, /* R1448 (0x5a8) - AIF4 Frame Ctrl 2 */
+ { 0x000005a9, 0x0000 }, /* R1449 (0x5a9) - AIF4 Frame Ctrl 3 */
+ { 0x000005aa, 0x0001 }, /* R1450 (0x5aa) - AIF4 Frame Ctrl 4 */
+ { 0x000005b1, 0x0000 }, /* R1457 (0x5b1) - AIF4 Frame Ctrl 11 */
+ { 0x000005b2, 0x0001 }, /* R1458 (0x5b2) - AIF4 Frame Ctrl 12 */
+ { 0x000005b9, 0x0000 }, /* R1465 (0x5b9) - AIF4 Tx Enables */
+ { 0x000005ba, 0x0000 }, /* R1466 (0x5ba) - AIF4 Rx Enables */
+ { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+ { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+ { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+ { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+ { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+ { 0x000005e8, 0x0000 }, /* R1512 (0x5e8) - SLIMbus Rates 4 */
+ { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+ { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+ { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+ { 0x000005ec, 0x0000 }, /* R1516 (0x5ec) - SLIMbus Rates 8 */
+ { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+ { 0x000005f6, 0x0000 }, /* R1526 (0x5F6) - SLIMbus TX Channel Enable */
+ { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+ { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+ { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+ { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+ { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+ { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+ { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+ { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+ { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+ { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+ { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+ { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+ { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+ { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+ { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+ { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+ { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+ { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+ { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+ { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+ { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+ { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+ { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+ { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+ { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+ { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+ { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+ { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+ { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+ { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+ { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+ { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+ { 0x00000690, 0x0000 }, /* R1680 (0x690) - OUT2LMIX Input 1 Source */
+ { 0x00000691, 0x0080 }, /* R1681 (0x691) - OUT2LMIX Input 1 Volume */
+ { 0x00000692, 0x0000 }, /* R1682 (0x692) - OUT2LMIX Input 2 Source */
+ { 0x00000693, 0x0080 }, /* R1683 (0x693) - OUT2LMIX Input 2 Volume */
+ { 0x00000694, 0x0000 }, /* R1684 (0x694) - OUT2LMIX Input 3 Source */
+ { 0x00000695, 0x0080 }, /* R1685 (0x695) - OUT2LMIX Input 3 Volume */
+ { 0x00000696, 0x0000 }, /* R1686 (0x696) - OUT2LMIX Input 4 Source */
+ { 0x00000697, 0x0080 }, /* R1687 (0x697) - OUT2LMIX Input 4 Volume */
+ { 0x00000698, 0x0000 }, /* R1688 (0x698) - OUT2RMIX Input 1 Source */
+ { 0x00000699, 0x0080 }, /* R1689 (0x699) - OUT2RMIX Input 1 Volume */
+ { 0x0000069a, 0x0000 }, /* R1690 (0x69a) - OUT2RMIX Input 2 Source */
+ { 0x0000069b, 0x0080 }, /* R1691 (0x69b) - OUT2RMIX Input 2 Volume */
+ { 0x0000069c, 0x0000 }, /* R1692 (0x69c) - OUT2RMIX Input 3 Source */
+ { 0x0000069d, 0x0080 }, /* R1693 (0x69d) - OUT2RMIX Input 3 Volume */
+ { 0x0000069e, 0x0000 }, /* R1694 (0x69e) - OUT2RMIX Input 4 Source */
+ { 0x0000069f, 0x0080 }, /* R1695 (0x69f) - OUT2RMIX Input 4 Volume */
+ { 0x000006a0, 0x0000 }, /* R1696 (0x6a0) - OUT3LMIX Input 1 Source */
+ { 0x000006a1, 0x0080 }, /* R1697 (0x6a1) - OUT3LMIX Input 1 Volume */
+ { 0x000006a2, 0x0000 }, /* R1698 (0x6a2) - OUT3LMIX Input 2 Source */
+ { 0x000006a3, 0x0080 }, /* R1699 (0x6a3) - OUT3LMIX Input 2 Volume */
+ { 0x000006a4, 0x0000 }, /* R1700 (0x6a4) - OUT3LMIX Input 3 Source */
+ { 0x000006a5, 0x0080 }, /* R1701 (0x6a5) - OUT3LMIX Input 3 Volume */
+ { 0x000006a6, 0x0000 }, /* R1702 (0x6a6) - OUT3LMIX Input 4 Source */
+ { 0x000006a7, 0x0080 }, /* R1703 (0x6a7) - OUT3LMIX Input 4 Volume */
+ { 0x000006a8, 0x0000 }, /* R1704 (0x6a8) - OUT3RMIX Input 1 Source */
+ { 0x000006a9, 0x0080 }, /* R1705 (0x6a9) - OUT3RMIX Input 1 Volume */
+ { 0x000006aa, 0x0000 }, /* R1706 (0x6aa) - OUT3RMIX Input 2 Source */
+ { 0x000006ab, 0x0080 }, /* R1707 (0x6ab) - OUT3RMIX Input 2 Volume */
+ { 0x000006ac, 0x0000 }, /* R1708 (0x6ac) - OUT3RMIX Input 3 Source */
+ { 0x000006ad, 0x0080 }, /* R1709 (0x6ad) - OUT3RMIX Input 3 Volume */
+ { 0x000006ae, 0x0000 }, /* R1710 (0x6ae) - OUT3RMIX Input 4 Source */
+ { 0x000006af, 0x0080 }, /* R1711 (0x6af) - OUT3RMIX Input 4 Volume */
+ { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+ { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+ { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+ { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+ { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+ { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+ { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+ { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+ { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+ { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+ { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+ { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+ { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+ { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+ { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+ { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+ { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+ { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+ { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+ { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+ { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+ { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+ { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+ { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+ { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+ { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+ { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+ { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+ { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+ { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+ { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+ { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+ { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+ { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+ { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+ { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+ { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+ { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+ { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+ { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+ { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+ { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+ { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+ { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+ { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+ { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+ { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+ { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+ { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+ { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+ { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+ { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+ { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+ { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+ { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+ { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+ { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+ { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+ { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+ { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+ { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+ { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+ { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+ { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+ { 0x00000730, 0x0000 }, /* R1840 (0x730) - AIF1TX7MIX Input 1 Source */
+ { 0x00000731, 0x0080 }, /* R1841 (0x731) - AIF1TX7MIX Input 1 Volume */
+ { 0x00000732, 0x0000 }, /* R1842 (0x732) - AIF1TX7MIX Input 2 Source */
+ { 0x00000733, 0x0080 }, /* R1843 (0x733) - AIF1TX7MIX Input 2 Volume */
+ { 0x00000734, 0x0000 }, /* R1844 (0x734) - AIF1TX7MIX Input 3 Source */
+ { 0x00000735, 0x0080 }, /* R1845 (0x735) - AIF1TX7MIX Input 3 Volume */
+ { 0x00000736, 0x0000 }, /* R1846 (0x736) - AIF1TX7MIX Input 4 Source */
+ { 0x00000737, 0x0080 }, /* R1847 (0x737) - AIF1TX7MIX Input 4 Volume */
+ { 0x00000738, 0x0000 }, /* R1848 (0x738) - AIF1TX8MIX Input 1 Source */
+ { 0x00000739, 0x0080 }, /* R1849 (0x739) - AIF1TX8MIX Input 1 Volume */
+ { 0x0000073a, 0x0000 }, /* R1850 (0x73a) - AIF1TX8MIX Input 2 Source */
+ { 0x0000073b, 0x0080 }, /* R1851 (0x73b) - AIF1TX8MIX Input 2 Volume */
+ { 0x0000073c, 0x0000 }, /* R1852 (0x73c) - AIF1TX8MIX Input 3 Source */
+ { 0x0000073d, 0x0080 }, /* R1853 (0x73d) - AIF1TX8MIX Input 3 Volume */
+ { 0x0000073e, 0x0000 }, /* R1854 (0x73e) - AIF1TX8MIX Input 4 Source */
+ { 0x0000073f, 0x0080 }, /* R1855 (0x73f) - AIF1TX8MIX Input 4 Volume */
+ { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+ { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+ { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+ { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+ { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+ { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+ { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+ { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+ { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+ { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+ { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+ { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+ { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+ { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+ { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+ { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+ { 0x00000750, 0x0000 }, /* R1872 (0x750) - AIF2TX3MIX Input 1 Source */
+ { 0x00000751, 0x0080 }, /* R1873 (0x751) - AIF2TX3MIX Input 1 Volume */
+ { 0x00000752, 0x0000 }, /* R1874 (0x752) - AIF2TX3MIX Input 2 Source */
+ { 0x00000753, 0x0080 }, /* R1875 (0x753) - AIF2TX3MIX Input 2 Volume */
+ { 0x00000754, 0x0000 }, /* R1876 (0x754) - AIF2TX3MIX Input 3 Source */
+ { 0x00000755, 0x0080 }, /* R1877 (0x755) - AIF2TX3MIX Input 3 Volume */
+ { 0x00000756, 0x0000 }, /* R1878 (0x756) - AIF2TX3MIX Input 4 Source */
+ { 0x00000757, 0x0080 }, /* R1879 (0x757) - AIF2TX3MIX Input 4 Volume */
+ { 0x00000758, 0x0000 }, /* R1880 (0x758) - AIF2TX4MIX Input 1 Source */
+ { 0x00000759, 0x0080 }, /* R1881 (0x759) - AIF2TX4MIX Input 1 Volume */
+ { 0x0000075a, 0x0000 }, /* R1882 (0x75a) - AIF2TX4MIX Input 2 Source */
+ { 0x0000075b, 0x0080 }, /* R1883 (0x75b) - AIF2TX4MIX Input 2 Volume */
+ { 0x0000075c, 0x0000 }, /* R1884 (0x75c) - AIF2TX4MIX Input 3 Source */
+ { 0x0000075d, 0x0080 }, /* R1885 (0x75d) - AIF2TX4MIX Input 3 Volume */
+ { 0x0000075e, 0x0000 }, /* R1886 (0x75e) - AIF2TX4MIX Input 4 Source */
+ { 0x0000075f, 0x0080 }, /* R1887 (0x75f) - AIF2TX4MIX Input 4 Volume */
+ { 0x00000760, 0x0000 }, /* R1888 (0x760) - AIF2TX5MIX Input 1 Source */
+ { 0x00000761, 0x0080 }, /* R1889 (0x761) - AIF2TX5MIX Input 1 Volume */
+ { 0x00000762, 0x0000 }, /* R1890 (0x762) - AIF2TX5MIX Input 2 Source */
+ { 0x00000763, 0x0080 }, /* R1891 (0x763) - AIF2TX5MIX Input 2 Volume */
+ { 0x00000764, 0x0000 }, /* R1892 (0x764) - AIF2TX5MIX Input 3 Source */
+ { 0x00000765, 0x0080 }, /* R1893 (0x765) - AIF2TX5MIX Input 3 Volume */
+ { 0x00000766, 0x0000 }, /* R1894 (0x766) - AIF2TX5MIX Input 4 Source */
+ { 0x00000767, 0x0080 }, /* R1895 (0x767) - AIF2TX5MIX Input 4 Volume */
+ { 0x00000768, 0x0000 }, /* R1896 (0x768) - AIF2TX6MIX Input 1 Source */
+ { 0x00000769, 0x0080 }, /* R1897 (0x769) - AIF2TX6MIX Input 1 Volume */
+ { 0x0000076a, 0x0000 }, /* R1898 (0x76a) - AIF2TX6MIX Input 2 Source */
+ { 0x0000076b, 0x0080 }, /* R1899 (0x76b) - AIF2TX6MIX Input 2 Volume */
+ { 0x0000076c, 0x0000 }, /* R1900 (0x76c) - AIF2TX6MIX Input 3 Source */
+ { 0x0000076d, 0x0080 }, /* R1901 (0x76d) - AIF2TX6MIX Input 3 Volume */
+ { 0x0000076e, 0x0000 }, /* R1902 (0x76e) - AIF2TX6MIX Input 4 Source */
+ { 0x0000076f, 0x0080 }, /* R1903 (0x76f) - AIF2TX6MIX Input 4 Volume */
+ { 0x00000770, 0x0000 }, /* R1904 (0x770) - AIF2TX7MIX Input 1 Source */
+ { 0x00000771, 0x0080 }, /* R1905 (0x771) - AIF2TX7MIX Input 1 Volume */
+ { 0x00000772, 0x0000 }, /* R1906 (0x772) - AIF2TX7MIX Input 2 Source */
+ { 0x00000773, 0x0080 }, /* R1907 (0x773) - AIF2TX7MIX Input 2 Volume */
+ { 0x00000774, 0x0000 }, /* R1908 (0x774) - AIF2TX7MIX Input 3 Source */
+ { 0x00000775, 0x0080 }, /* R1909 (0x775) - AIF2TX7MIX Input 3 Volume */
+ { 0x00000776, 0x0000 }, /* R1910 (0x776) - AIF2TX7MIX Input 4 Source */
+ { 0x00000777, 0x0080 }, /* R1911 (0x777) - AIF2TX7MIX Input 4 Volume */
+ { 0x00000778, 0x0000 }, /* R1912 (0x778) - AIF2TX8MIX Input 1 Source */
+ { 0x00000779, 0x0080 }, /* R1913 (0x779) - AIF2TX8MIX Input 1 Volume */
+ { 0x0000077a, 0x0000 }, /* R1914 (0x77a) - AIF2TX8MIX Input 2 Source */
+ { 0x0000077b, 0x0080 }, /* R1915 (0x77b) - AIF2TX8MIX Input 2 Volume */
+ { 0x0000077c, 0x0000 }, /* R1916 (0x77c) - AIF2TX8MIX Input 3 Source */
+ { 0x0000077d, 0x0080 }, /* R1917 (0x77d) - AIF2TX8MIX Input 3 Volume */
+ { 0x0000077e, 0x0000 }, /* R1918 (0x77e) - AIF2TX8MIX Input 4 Source */
+ { 0x0000077f, 0x0080 }, /* R1919 (0x77f) - AIF2TX8MIX Input 4 Volume */
+ { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+ { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+ { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+ { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+ { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+ { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+ { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+ { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+ { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+ { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+ { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+ { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+ { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+ { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+ { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+ { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+ { 0x000007a0, 0x0000 }, /* R1952 (0x7a0) - AIF4TX1MIX Input 1 Source */
+ { 0x000007a1, 0x0080 }, /* R1953 (0x7a1) - AIF4TX1MIX Input 1 Volume */
+ { 0x000007a2, 0x0000 }, /* R1954 (0x7a2) - AIF4TX1MIX Input 2 Source */
+ { 0x000007a3, 0x0080 }, /* R1955 (0x7a3) - AIF4TX1MIX Input 2 Volume */
+ { 0x000007a4, 0x0000 }, /* R1956 (0x7a4) - AIF4TX1MIX Input 3 Source */
+ { 0x000007a5, 0x0080 }, /* R1957 (0x7a5) - AIF4TX1MIX Input 3 Volume */
+ { 0x000007a6, 0x0000 }, /* R1958 (0x7a6) - AIF4TX1MIX Input 4 Source */
+ { 0x000007a7, 0x0080 }, /* R1959 (0x7a7) - AIF4TX1MIX Input 4 Volume */
+ { 0x000007a8, 0x0000 }, /* R1960 (0x7a8) - AIF4TX2MIX Input 1 Source */
+ { 0x000007a9, 0x0080 }, /* R1961 (0x7a9) - AIF4TX2MIX Input 1 Volume */
+ { 0x000007aa, 0x0000 }, /* R1962 (0x7aa) - AIF4TX2MIX Input 2 Source */
+ { 0x000007ab, 0x0080 }, /* R1963 (0x7ab) - AIF4TX2MIX Input 2 Volume */
+ { 0x000007ac, 0x0000 }, /* R1964 (0x7ac) - AIF4TX2MIX Input 3 Source */
+ { 0x000007ad, 0x0080 }, /* R1965 (0x7ad) - AIF4TX2MIX Input 3 Volume */
+ { 0x000007ae, 0x0000 }, /* R1966 (0x7ae) - AIF4TX2MIX Input 4 Source */
+ { 0x000007af, 0x0080 }, /* R1967 (0x7af) - AIF4TX2MIX Input 4 Volume */
+ { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+ { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+ { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+ { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+ { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+ { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+ { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+ { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+ { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+ { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+ { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+ { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+ { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+ { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+ { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+ { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+ { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+ { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+ { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+ { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+ { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+ { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+ { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+ { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+ { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+ { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+ { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+ { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+ { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+ { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+ { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+ { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+ { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+ { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+ { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+ { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+ { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+ { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+ { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+ { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+ { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+ { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+ { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+ { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+ { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+ { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+ { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+ { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+ { 0x000007f0, 0x0000 }, /* R2032 (0x7f0) - SLIMTX7MIX Input 1 Source */
+ { 0x000007f1, 0x0080 }, /* R2033 (0x7f1) - SLIMTX7MIX Input 1 Volume */
+ { 0x000007f2, 0x0000 }, /* R2034 (0x7f2) - SLIMTX7MIX Input 2 Source */
+ { 0x000007f3, 0x0080 }, /* R2035 (0x7f3) - SLIMTX7MIX Input 2 Volume */
+ { 0x000007f4, 0x0000 }, /* R2036 (0x7f4) - SLIMTX7MIX Input 3 Source */
+ { 0x000007f5, 0x0080 }, /* R2037 (0x7f5) - SLIMTX7MIX Input 3 Volume */
+ { 0x000007f6, 0x0000 }, /* R2038 (0x7f6) - SLIMTX7MIX Input 4 Source */
+ { 0x000007f7, 0x0080 }, /* R2039 (0x7f7) - SLIMTX7MIX Input 4 Volume */
+ { 0x000007f8, 0x0000 }, /* R2040 (0x7f8) - SLIMTX8MIX Input 1 Source */
+ { 0x000007f9, 0x0080 }, /* R2041 (0x7f9) - SLIMTX8MIX Input 1 Volume */
+ { 0x000007fa, 0x0000 }, /* R2042 (0x7fa) - SLIMTX8MIX Input 2 Source */
+ { 0x000007fb, 0x0080 }, /* R2043 (0x7fb) - SLIMTX8MIX Input 2 Volume */
+ { 0x000007fc, 0x0000 }, /* R2044 (0x7fc) - SLIMTX8MIX Input 3 Source */
+ { 0x000007fd, 0x0080 }, /* R2045 (0x7fd) - SLIMTX8MIX Input 3 Volume */
+ { 0x000007fe, 0x0000 }, /* R2046 (0x7fe) - SLIMTX8MIX Input 4 Source */
+ { 0x000007ff, 0x0080 }, /* R2047 (0x7ff) - SLIMTX8MIX Input 4 Volume */
+ { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source */
+ { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume */
+ { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source */
+ { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume */
+ { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+ { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+ { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+ { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+ { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+ { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+ { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+ { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+ { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+ { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+ { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+ { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+ { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+ { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+ { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+ { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+ { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+ { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+ { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+ { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+ { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+ { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+ { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+ { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+ { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+ { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+ { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+ { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+ { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+ { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+ { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+ { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+ { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+ { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+ { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+ { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+ { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+ { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+ { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+ { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+ { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+ { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+ { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+ { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+ { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+ { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+ { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+ { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+ { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+ { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+ { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+ { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+ { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+ { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+ { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+ { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+ { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+ { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+ { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+ { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+ { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+ { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+ { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+ { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+ { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+ { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+ { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+ { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+ { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+ { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+ { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+ { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+ { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+ { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+ { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+ { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+ { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+ { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+ { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+ { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+ { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+ { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+ { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+ { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+ { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+ { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+ { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+ { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+ { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+ { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+ { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+ { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+ { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+ { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+ { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+ { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+ { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+ { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+ { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+ { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+ { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+ { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+ { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+ { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+ { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+ { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+ { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+ { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+ { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+ { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+ { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+ { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+ { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+ { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+ { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+ { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+ { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+ { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+ { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+ { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+ { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+ { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+ { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+ { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+ { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+ { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+ { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+ { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+ { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+ { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+ { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+ { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+ { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+ { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+ { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+ { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+ { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+ { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+ { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+ { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+ { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+ { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+ { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+ { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+ { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+ { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+ { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+ { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+ { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+ { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+ { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+ { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+ { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+ { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+ { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+ { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+ { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+ { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+ { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+ { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+ { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+ { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+ { 0x00000a00, 0x0000 }, /* R2560 (0xa00) - DSP4LMIX Input 1 Source */
+ { 0x00000a01, 0x0080 }, /* R2561 (0xa01) - DSP4LMIX Input 1 Volume */
+ { 0x00000a02, 0x0000 }, /* R2562 (0xa02) - DSP4LMIX Input 2 Source */
+ { 0x00000a03, 0x0080 }, /* R2563 (0xa03) - DSP4LMIX Input 2 Volume */
+ { 0x00000a04, 0x0000 }, /* R2564 (0xa04) - DSP4LMIX Input 3 Source */
+ { 0x00000a05, 0x0080 }, /* R2565 (0xa05) - DSP4LMIX Input 3 Volume */
+ { 0x00000a06, 0x0000 }, /* R2566 (0xa06) - DSP4LMIX Input 4 Source */
+ { 0x00000a07, 0x0080 }, /* R2567 (0xa07) - DSP4LMIX Input 4 Volume */
+ { 0x00000a08, 0x0000 }, /* R2568 (0xa08) - DSP4RMIX Input 1 Source */
+ { 0x00000a09, 0x0080 }, /* R2569 (0xa09) - DSP4RMIX Input 1 Volume */
+ { 0x00000a0a, 0x0000 }, /* R2570 (0xa0a) - DSP4RMIX Input 2 Source */
+ { 0x00000a0b, 0x0080 }, /* R2571 (0xa0b) - DSP4RMIX Input 2 Volume */
+ { 0x00000a0c, 0x0000 }, /* R2572 (0xa0c) - DSP4RMIX Input 3 Source */
+ { 0x00000a0d, 0x0080 }, /* R2573 (0xa0d) - DSP4RMIX Input 3 Volume */
+ { 0x00000a0e, 0x0000 }, /* R2574 (0xa0e) - DSP4RMIX Input 4 Source */
+ { 0x00000a0f, 0x0080 }, /* R2575 (0xa0f) - DSP4RMIX Input 4 Volume */
+ { 0x00000a10, 0x0000 }, /* R2576 (0xa10) - DSP4AUX1MIX Input 1 Source */
+ { 0x00000a18, 0x0000 }, /* R2584 (0xa18) - DSP4AUX2MIX Input 1 Source */
+ { 0x00000a20, 0x0000 }, /* R2592 (0xa20) - DSP4AUX3MIX Input 1 Source */
+ { 0x00000a28, 0x0000 }, /* R2600 (0xa28) - DSP4AUX4MIX Input 1 Source */
+ { 0x00000a30, 0x0000 }, /* R2608 (0xa30) - DSP4AUX5MIX Input 1 Source */
+ { 0x00000a38, 0x0000 }, /* R2616 (0xa38) - DSP4AUX6MIX Input 1 Source */
+ { 0x00000a40, 0x0000 }, /* R2624 (0xa40) - DSP5LMIX Input 1 Source */
+ { 0x00000a41, 0x0080 }, /* R2625 (0xa41) - DSP5LMIX Input 1 Volume */
+ { 0x00000a42, 0x0000 }, /* R2626 (0xa42) - DSP5LMIX Input 2 Source */
+ { 0x00000a43, 0x0080 }, /* R2627 (0xa43) - DSP5LMIX Input 2 Volume */
+ { 0x00000a44, 0x0000 }, /* R2628 (0xa44) - DSP5LMIX Input 3 Source */
+ { 0x00000a45, 0x0080 }, /* R2629 (0xa45) - DSP5LMIX Input 3 Volume */
+ { 0x00000a46, 0x0000 }, /* R2630 (0xa46) - DSP5LMIX Input 4 Source */
+ { 0x00000a47, 0x0080 }, /* R2631 (0xa47) - DSP5LMIX Input 4 Volume */
+ { 0x00000a48, 0x0000 }, /* R2632 (0xa48) - DSP5RMIX Input 1 Source */
+ { 0x00000a49, 0x0080 }, /* R2633 (0xa49) - DSP5RMIX Input 1 Volume */
+ { 0x00000a4a, 0x0000 }, /* R2634 (0xa4a) - DSP5RMIX Input 2 Source */
+ { 0x00000a4b, 0x0080 }, /* R2635 (0xa4b) - DSP5RMIX Input 2 Volume */
+ { 0x00000a4c, 0x0000 }, /* R2636 (0xa4c) - DSP5RMIX Input 3 Source */
+ { 0x00000a4d, 0x0080 }, /* R2637 (0xa4d) - DSP5RMIX Input 3 Volume */
+ { 0x00000a4e, 0x0000 }, /* R2638 (0xa4e) - DSP5RMIX Input 4 Source */
+ { 0x00000a4f, 0x0080 }, /* R2639 (0xa4f) - DSP5RMIX Input 4 Volume */
+ { 0x00000a50, 0x0000 }, /* R2640 (0xa50) - DSP5AUX1MIX Input 1 Source */
+ { 0x00000a58, 0x0000 }, /* R2658 (0xa58) - DSP5AUX2MIX Input 1 Source */
+ { 0x00000a60, 0x0000 }, /* R2656 (0xa60) - DSP5AUX3MIX Input 1 Source */
+ { 0x00000a68, 0x0000 }, /* R2664 (0xa68) - DSP5AUX4MIX Input 1 Source */
+ { 0x00000a70, 0x0000 }, /* R2672 (0xa70) - DSP5AUX5MIX Input 1 Source */
+ { 0x00000a78, 0x0000 }, /* R2680 (0xa78) - DSP5AUX6MIX Input 1 Source */
+ { 0x00000a80, 0x0000 }, /* R2688 (0xa80) - ASRC1_1LMIX Input 1 Source */
+ { 0x00000a88, 0x0000 }, /* R2696 (0xa88) - ASRC1_1RMIX Input 1 Source */
+ { 0x00000a90, 0x0000 }, /* R2704 (0xa90) - ASRC1_2LMIX Input 1 Source */
+ { 0x00000a98, 0x0000 }, /* R2712 (0xa98) - ASRC1_2RMIX Input 1 Source */
+ { 0x00000aa0, 0x0000 }, /* R2720 (0xaa0) - ASRC2_1LMIX Input 1 Source */
+ { 0x00000aa8, 0x0000 }, /* R2728 (0xaa8) - ASRC2_1RMIX Input 1 Source */
+ { 0x00000ab0, 0x0000 }, /* R2736 (0xab0) - ASRC2_2LMIX Input 1 Source */
+ { 0x00000ab8, 0x0000 }, /* R2744 (0xab8) - ASRC2_2RMIX Input 1 Source */
+ { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+ { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+ { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+ { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+ { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+ { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+ { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+ { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+ { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+ { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+ { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+ { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+ { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+ { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+ { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+ { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+ { 0x00000b80, 0x0000 }, /* R2944 (0xb80) - ISRC3DEC1MIX Input 1 Source*/
+ { 0x00000b88, 0x0000 }, /* R2952 (0xb88) - ISRC3DEC2MIX Input 1 Source*/
+ { 0x00000ba0, 0x0000 }, /* R2976 (0xb80) - ISRC3INT1MIX Input 1 Source*/
+ { 0x00000ba8, 0x0000 }, /* R2984 (0xb88) - ISRC3INT2MIX Input 1 Source*/
+ { 0x00000bc0, 0x0000 }, /* R3008 (0xbc0) - ISRC4DEC1MIX Input 1 Source */
+ { 0x00000bc8, 0x0000 }, /* R3016 (0xbc8) - ISRC4DEC2MIX Input 1 Source */
+ { 0x00000be0, 0x0000 }, /* R3040 (0xbe0) - ISRC4INT1MIX Input 1 Source */
+ { 0x00000be8, 0x0000 }, /* R3048 (0xbe8) - ISRC4INT2MIX Input 1 Source */
+ { 0x00000c00, 0x0000 }, /* R3072 (0xc00) - DSP6LMIX Input 1 Source */
+ { 0x00000c01, 0x0080 }, /* R3073 (0xc01) - DSP6LMIX Input 1 Volume */
+ { 0x00000c02, 0x0000 }, /* R3074 (0xc02) - DSP6LMIX Input 2 Source */
+ { 0x00000c03, 0x0080 }, /* R3075 (0xc03) - DSP6LMIX Input 2 Volume */
+ { 0x00000c04, 0x0000 }, /* R3076 (0xc04) - DSP6LMIX Input 3 Source */
+ { 0x00000c05, 0x0080 }, /* R3077 (0xc05) - DSP6LMIX Input 3 Volume */
+ { 0x00000c06, 0x0000 }, /* R3078 (0xc06) - DSP6LMIX Input 4 Source */
+ { 0x00000c07, 0x0080 }, /* R3079 (0xc07) - DSP6LMIX Input 4 Volume */
+ { 0x00000c08, 0x0000 }, /* R3080 (0xc08) - DSP6RMIX Input 1 Source */
+ { 0x00000c09, 0x0080 }, /* R3081 (0xc09) - DSP6RMIX Input 1 Volume */
+ { 0x00000c0a, 0x0000 }, /* R3082 (0xc0a) - DSP6RMIX Input 2 Source */
+ { 0x00000c0b, 0x0080 }, /* R3083 (0xc0b) - DSP6RMIX Input 2 Volume */
+ { 0x00000c0c, 0x0000 }, /* R3084 (0xc0c) - DSP6RMIX Input 3 Source */
+ { 0x00000c0d, 0x0080 }, /* R3085 (0xc0d) - DSP6RMIX Input 3 Volume */
+ { 0x00000c0e, 0x0000 }, /* R3086 (0xc0e) - DSP6RMIX Input 4 Source */
+ { 0x00000c0f, 0x0080 }, /* R3087 (0xc0f) - DSP6RMIX Input 4 Volume */
+ { 0x00000c10, 0x0000 }, /* R3088 (0xc10) - DSP6AUX1MIX Input 1 Source */
+ { 0x00000c18, 0x0000 }, /* R3088 (0xc18) - DSP6AUX2MIX Input 1 Source */
+ { 0x00000c20, 0x0000 }, /* R3088 (0xc20) - DSP6AUX3MIX Input 1 Source */
+ { 0x00000c28, 0x0000 }, /* R3088 (0xc28) - DSP6AUX4MIX Input 1 Source */
+ { 0x00000c30, 0x0000 }, /* R3088 (0xc30) - DSP6AUX5MIX Input 1 Source */
+ { 0x00000c38, 0x0000 }, /* R3088 (0xc38) - DSP6AUX6MIX Input 1 Source */
+ { 0x00000c40, 0x0000 }, /* R3136 (0xc40) - DSP7LMIX Input 1 Source */
+ { 0x00000c41, 0x0080 }, /* R3137 (0xc41) - DSP7LMIX Input 1 Volume */
+ { 0x00000c42, 0x0000 }, /* R3138 (0xc42) - DSP7LMIX Input 2 Source */
+ { 0x00000c43, 0x0080 }, /* R3139 (0xc43) - DSP7LMIX Input 2 Volume */
+ { 0x00000c44, 0x0000 }, /* R3140 (0xc44) - DSP7LMIX Input 3 Source */
+ { 0x00000c45, 0x0080 }, /* R3141 (0xc45) - DSP7lMIX Input 3 Volume */
+ { 0x00000c46, 0x0000 }, /* R3142 (0xc46) - DSP7lMIX Input 4 Source */
+ { 0x00000c47, 0x0080 }, /* R3143 (0xc47) - DSP7LMIX Input 4 Volume */
+ { 0x00000c48, 0x0000 }, /* R3144 (0xc48) - DSP7RMIX Input 1 Source */
+ { 0x00000c49, 0x0080 }, /* R3145 (0xc49) - DSP7RMIX Input 1 Volume */
+ { 0x00000c4a, 0x0000 }, /* R3146 (0xc4a) - DSP7RMIX Input 2 Source */
+ { 0x00000c4b, 0x0080 }, /* R3147 (0xc4b) - DSP7RMIX Input 2 Volume */
+ { 0x00000c4c, 0x0000 }, /* R3148 (0xc4c) - DSP7RMIX Input 3 Source */
+ { 0x00000c4d, 0x0080 }, /* R3159 (0xc4d) - DSP7RMIX Input 3 Volume */
+ { 0x00000c4e, 0x0000 }, /* R3150 (0xc4e) - DSP7RMIX Input 4 Source */
+ { 0x00000c4f, 0x0080 }, /* R3151 (0xc4f) - DSP7RMIX Input 4 Volume */
+ { 0x00000c50, 0x0000 }, /* R3152 (0xc50) - DSP7AUX1MIX Input 1 Source */
+ { 0x00000c58, 0x0000 }, /* R3160 (0xc58) - DSP7AUX2MIX Input 1 Source */
+ { 0x00000c60, 0x0000 }, /* R3168 (0xc60) - DSP7AUX3MIX Input 1 Source */
+ { 0x00000c68, 0x0000 }, /* R3176 (0xc68) - DSP7AUX4MIX Input 1 Source */
+ { 0x00000c70, 0x0000 }, /* R3184 (0xc70) - DSP7AUX5MIX Input 1 Source */
+ { 0x00000c78, 0x0000 }, /* R3192 (0xc78) - DSP7AUX6MIX Input 1 Source */
+ { 0x00000dc0, 0x0000 }, /* R3520 (0xdc0) - DFC1MIX Input 1 Source */
+ { 0x00000dc8, 0x0000 }, /* R3528 (0xdc8) - DFC2MIX Input 1 Source */
+ { 0x00000dd0, 0x0000 }, /* R3536 (0xdd0) - DFC3MIX Input 1 Source */
+ { 0x00000dd8, 0x0000 }, /* R3544 (0xdd8) - DFC4MIX Input 1 Source */
+ { 0x00000de0, 0x0000 }, /* R3552 (0xde0) - DFC5MIX Input 1 Source */
+ { 0x00000de8, 0x0000 }, /* R3560 (0xde8) - DFC6MIX Input 1 Source */
+ { 0x00000df0, 0x0000 }, /* R3568 (0xdf0) - DFC7MIX Input 1 Source */
+ { 0x00000df8, 0x0000 }, /* R3576 (0xdf8) - DFC8MIX Input 1 Source */
+ { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX_Ctrl1 */
+ { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+ { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+ { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+ { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+ { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+ { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+ { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+ { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+ { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+ { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+ { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+ { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+ { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+ { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+ { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+ { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+ { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+ { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+ { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+ { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+ { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+ { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+ { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+ { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+ { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+ { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+ { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+ { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+ { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+ { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+ { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+ { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+ { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+ { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+ { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+ { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+ { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+ { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+ { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+ { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+ { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+ { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+ { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+ { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+ { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+ { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+ { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+ { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+ { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+ { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+ { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+ { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+ { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+ { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+ { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+ { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+ { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+ { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+ { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+ { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+ { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+ { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+ { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+ { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+ { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+ { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+ { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+ { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+ { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+ { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+ { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+ { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+ { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+ { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+ { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+ { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+ { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+ { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+ { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+ { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+ { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+ { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+ { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+ { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+ { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+ { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+ { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+ { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+ { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+ { 0x00000e88, 0x0018 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+ { 0x00000e89, 0x0933 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+ { 0x00000e8a, 0x0018 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+ { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+ { 0x00000e8c, 0x0000 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+ { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+ { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+ { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+ { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+ { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+ { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+ { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+ { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+ { 0x00000ed0, 0x0000 }, /* R3792 (0xed0) - ASRC2_ENABLE */
+ { 0x00000ed2, 0x0000 }, /* R3794 (0xed2) - ASRC2_RATE1 */
+ { 0x00000ed3, 0x4000 }, /* R3795 (0xed3) - ASRC2_RATE2 */
+ { 0x00000ee0, 0x0000 }, /* R3808 (0xee0) - ASRC1_ENABLE */
+ { 0x00000ee2, 0x0000 }, /* R3810 (0xee2) - ASRC1_RATE1 */
+ { 0x00000ee3, 0x4000 }, /* R3811 (0xee3) - ASRC1_RATE2 */
+ { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+ { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+ { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+ { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+ { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+ { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+ { 0x00000ef6, 0x0000 }, /* R3830 (0xef6) - ISRC 3 CTRL 1 */
+ { 0x00000ef7, 0x0001 }, /* R3831 (0xef7) - ISRC 3 CTRL 2 */
+ { 0x00000ef8, 0x0000 }, /* R3832 (0xef8) - ISRC 3 CTRL 3 */
+ { 0x00000ef9, 0x0000 }, /* R3833 (0xef9) - ISRC 4 CTRL 1 */
+ { 0x00000efa, 0x0001 }, /* R3834 (0xefa) - ISRC 4 CTRL 2 */
+ { 0x00000efb, 0x0000 }, /* R3835 (0xefb) - ISRC 4 CTRL 3 */
+ { 0x00000f01, 0x0000 }, /* R3841 (0xf01) - ANC_SRC */
+ { 0x00000f02, 0x0000 }, /* R3842 (0xf02) - DSP Status */
+ { 0x00000f08, 0x001c }, /* R3848 (0xf08) - ANC Coefficient */
+ { 0x00000f09, 0x0000 }, /* R3849 (0xf09) - ANC Coefficient */
+ { 0x00000f0a, 0x0000 }, /* R3850 (0xf0a) - ANC Coefficient */
+ { 0x00000f0b, 0x0000 }, /* R3851 (0xf0b) - ANC Coefficient */
+ { 0x00000f0c, 0x0000 }, /* R3852 (0xf0c) - ANC Coefficient */
+ { 0x00000f0d, 0x0000 }, /* R3853 (0xf0d) - ANC Coefficient */
+ { 0x00000f0e, 0x0000 }, /* R3854 (0xf0e) - ANC Coefficient */
+ { 0x00000f0f, 0x0000 }, /* R3855 (0xf0f) - ANC Coefficient */
+ { 0x00000f10, 0x0000 }, /* R3856 (0xf10) - ANC Coefficient */
+ { 0x00000f11, 0x0000 }, /* R3857 (0xf11) - ANC Coefficient */
+ { 0x00000f12, 0x0000 }, /* R3858 (0xf12) - ANC Coefficient */
+ { 0x00000f15, 0x0000 }, /* R3861 (0xf15) - FCL Filter Control */
+ { 0x00000f17, 0x0004 }, /* R3863 (0xf17) - FCL ADC Reformatter Control */
+ { 0x00000f18, 0x0004 }, /* R3864 (0xf18) - ANC Coefficient */
+ { 0x00000f19, 0x0002 }, /* R3865 (0xf19) - ANC Coefficient */
+ { 0x00000f1a, 0x0000 }, /* R3866 (0xf1a) - ANC Coefficient */
+ { 0x00000f1b, 0x0010 }, /* R3867 (0xf1b) - ANC Coefficient */
+ { 0x00000f1c, 0x0000 }, /* R3868 (0xf1c) - ANC Coefficient */
+ { 0x00000f1d, 0x0000 }, /* R3869 (0xf1d) - ANC Coefficient */
+ { 0x00000f1e, 0x0000 }, /* R3870 (0xf1e) - ANC Coefficient */
+ { 0x00000f1f, 0x0000 }, /* R3871 (0xf1f) - ANC Coefficient */
+ { 0x00000f20, 0x0000 }, /* R3872 (0xf20) - ANC Coefficient */
+ { 0x00000f21, 0x0000 }, /* R3873 (0xf21) - ANC Coefficient */
+ { 0x00000f22, 0x0000 }, /* R3874 (0xf22) - ANC Coefficient */
+ { 0x00000f23, 0x0000 }, /* R3875 (0xf23) - ANC Coefficient */
+ { 0x00000f24, 0x0000 }, /* R3876 (0xf24) - ANC Coefficient */
+ { 0x00000f25, 0x0000 }, /* R3877 (0xf25) - ANC Coefficient */
+ { 0x00000f26, 0x0000 }, /* R3878 (0xf26) - ANC Coefficient */
+ { 0x00000f27, 0x0000 }, /* R3879 (0xf27) - ANC Coefficient */
+ { 0x00000f28, 0x0000 }, /* R3880 (0xf28) - ANC Coefficient */
+ { 0x00000f29, 0x0000 }, /* R3881 (0xf29) - ANC Coefficient */
+ { 0x00000f2a, 0x0000 }, /* R3882 (0xf2a) - ANC Coefficient */
+ { 0x00000f2b, 0x0000 }, /* R3883 (0xf2b) - ANC Coefficient */
+ { 0x00000f2c, 0x0000 }, /* R3884 (0xf2c) - ANC Coefficient */
+ { 0x00000f2d, 0x0000 }, /* R3885 (0xf2d) - ANC Coefficient */
+ { 0x00000f2e, 0x0000 }, /* R3886 (0xf2e) - ANC Coefficient */
+ { 0x00000f2f, 0x0000 }, /* R3887 (0xf2f) - ANC Coefficient */
+ { 0x00000f30, 0x0000 }, /* R3888 (0xf30) - ANC Coefficient */
+ { 0x00000f31, 0x0000 }, /* R3889 (0xf31) - ANC Coefficient */
+ { 0x00000f32, 0x0000 }, /* R3890 (0xf32) - ANC Coefficient */
+ { 0x00000f33, 0x0000 }, /* R3891 (0xf33) - ANC Coefficient */
+ { 0x00000f34, 0x0000 }, /* R3892 (0xf34) - ANC Coefficient */
+ { 0x00000f35, 0x0000 }, /* R3893 (0xf35) - ANC Coefficient */
+ { 0x00000f36, 0x0000 }, /* R3894 (0xf36) - ANC Coefficient */
+ { 0x00000f37, 0x0000 }, /* R3895 (0xf37) - ANC Coefficient */
+ { 0x00000f38, 0x0000 }, /* R3896 (0xf38) - ANC Coefficient */
+ { 0x00000f39, 0x0000 }, /* R3897 (0xf39) - ANC Coefficient */
+ { 0x00000f3a, 0x0000 }, /* R3898 (0xf3a) - ANC Coefficient */
+ { 0x00000f3b, 0x0000 }, /* R3899 (0xf3b) - ANC Coefficient */
+ { 0x00000f3c, 0x0000 }, /* R3900 (0xf3c) - ANC Coefficient */
+ { 0x00000f3d, 0x0000 }, /* R3901 (0xf3d) - ANC Coefficient */
+ { 0x00000f3e, 0x0000 }, /* R3902 (0xf3e) - ANC Coefficient */
+ { 0x00000f3f, 0x0000 }, /* R3903 (0xf3f) - ANC Coefficient */
+ { 0x00000f40, 0x0000 }, /* R3904 (0xf40) - ANC Coefficient */
+ { 0x00000f41, 0x0000 }, /* R3905 (0xf41) - ANC Coefficient */
+ { 0x00000f42, 0x0000 }, /* R3906 (0xf42) - ANC Coefficient */
+ { 0x00000f43, 0x0000 }, /* R3907 (0xf43) - ANC Coefficient */
+ { 0x00000f44, 0x0000 }, /* R3908 (0xf44) - ANC Coefficient */
+ { 0x00000f45, 0x0000 }, /* R3909 (0xf45) - ANC Coefficient */
+ { 0x00000f46, 0x0000 }, /* R3910 (0xf46) - ANC Coefficient */
+ { 0x00000f47, 0x0000 }, /* R3911 (0xf47) - ANC Coefficient */
+ { 0x00000f48, 0x0000 }, /* R3912 (0xf48) - ANC Coefficient */
+ { 0x00000f49, 0x0000 }, /* R3913 (0xf49) - ANC Coefficient */
+ { 0x00000f4a, 0x0000 }, /* R3914 (0xf4a) - ANC Coefficient */
+ { 0x00000f4b, 0x0000 }, /* R3915 (0xf4b) - ANC Coefficient */
+ { 0x00000f4c, 0x0000 }, /* R3916 (0xf4c) - ANC Coefficient */
+ { 0x00000f4d, 0x0000 }, /* R3917 (0xf4d) - ANC Coefficient */
+ { 0x00000f4e, 0x0000 }, /* R3918 (0xf4e) - ANC Coefficient */
+ { 0x00000f4f, 0x0000 }, /* R3919 (0xf4f) - ANC Coefficient */
+ { 0x00000f50, 0x0000 }, /* R3920 (0xf50) - ANC Coefficient */
+ { 0x00000f51, 0x0000 }, /* R3921 (0xf51) - ANC Coefficient */
+ { 0x00000f52, 0x0000 }, /* R3922 (0xf52) - ANC Coefficient */
+ { 0x00000f53, 0x0000 }, /* R3923 (0xf53) - ANC Coefficient */
+ { 0x00000f54, 0x0000 }, /* R3924 (0xf54) - ANC Coefficient */
+ { 0x00000f55, 0x0000 }, /* R3925 (0xf55) - ANC Coefficient */
+ { 0x00000f56, 0x0000 }, /* R3926 (0xf56) - ANC Coefficient */
+ { 0x00000f57, 0x0000 }, /* R3927 (0xf57) - ANC Coefficient */
+ { 0x00000f58, 0x0000 }, /* R3928 (0xf58) - ANC Coefficient */
+ { 0x00000f59, 0x0000 }, /* R3929 (0xf59) - ANC Coefficient */
+ { 0x00000f5a, 0x0000 }, /* R3930 (0xf5a) - ANC Coefficient */
+ { 0x00000f5b, 0x0000 }, /* R3931 (0xf5b) - ANC Coefficient */
+ { 0x00000f5c, 0x0000 }, /* R3932 (0xf5c) - ANC Coefficient */
+ { 0x00000f5d, 0x0000 }, /* R3933 (0xf5d) - ANC Coefficient */
+ { 0x00000f5e, 0x0000 }, /* R3934 (0xf5e) - ANC Coefficient */
+ { 0x00000f5f, 0x0000 }, /* R3935 (0xf5f) - ANC Coefficient */
+ { 0x00000f60, 0x0000 }, /* R3936 (0xf60) - ANC Coefficient */
+ { 0x00000f61, 0x0000 }, /* R3937 (0xf61) - ANC Coefficient */
+ { 0x00000f62, 0x0000 }, /* R3938 (0xf62) - ANC Coefficient */
+ { 0x00000f63, 0x0000 }, /* R3939 (0xf63) - ANC Coefficient */
+ { 0x00000f64, 0x0000 }, /* R3940 (0xf64) - ANC Coefficient */
+ { 0x00000f65, 0x0000 }, /* R3941 (0xf65) - ANC Coefficient */
+ { 0x00000f66, 0x0000 }, /* R3942 (0xf66) - ANC Coefficient */
+ { 0x00000f67, 0x0000 }, /* R3943 (0xf67) - ANC Coefficient */
+ { 0x00000f68, 0x0000 }, /* R3944 (0xf68) - ANC Coefficient */
+ { 0x00000f69, 0x0000 }, /* R3945 (0xf69) - ANC Coefficient */
+ { 0x00000f71, 0x0000 }, /* R3953 (0xf71) - FCR Filter Control */
+ { 0x00000f73, 0x0004 }, /* R3955 (0xf73) - FCR ADC Reformatter Control */
+ { 0x00000f74, 0x0004 }, /* R3956 (0xf74) - ANC Coefficient */
+ { 0x00000f75, 0x0002 }, /* R3957 (0xf75) - ANC Coefficient */
+ { 0x00000f76, 0x0000 }, /* R3958 (0xf76) - ANC Coefficient */
+ { 0x00000f77, 0x0010 }, /* R3959 (0xf77) - ANC Coefficient */
+ { 0x00000f78, 0x0000 }, /* R3960 (0xf78) - ANC Coefficient */
+ { 0x00000f79, 0x0000 }, /* R3961 (0xf79) - ANC Coefficient */
+ { 0x00000f7a, 0x0000 }, /* R3962 (0xf7a) - ANC Coefficient */
+ { 0x00000f7b, 0x0000 }, /* R3963 (0xf7b) - ANC Coefficient */
+ { 0x00000f7c, 0x0000 }, /* R3964 (0xf7c) - ANC Coefficient */
+ { 0x00000f7d, 0x0000 }, /* R3965 (0xf7d) - ANC Coefficient */
+ { 0x00000f7e, 0x0000 }, /* R3966 (0xf7e) - ANC Coefficient */
+ { 0x00000f7f, 0x0000 }, /* R3967 (0xf7f) - ANC Coefficient */
+ { 0x00000f80, 0x0000 }, /* R3968 (0xf80) - ANC Coefficient */
+ { 0x00000f81, 0x0000 }, /* R3969 (0xf81) - ANC Coefficient */
+ { 0x00000f82, 0x0000 }, /* R3970 (0xf82) - ANC Coefficient */
+ { 0x00000f83, 0x0000 }, /* R3971 (0xf83) - ANC Coefficient */
+ { 0x00000f84, 0x0000 }, /* R3972 (0xf84) - ANC Coefficient */
+ { 0x00000f85, 0x0000 }, /* R3973 (0xf85) - ANC Coefficient */
+ { 0x00000f86, 0x0000 }, /* R3974 (0xf86) - ANC Coefficient */
+ { 0x00000f87, 0x0000 }, /* R3975 (0xf87) - ANC Coefficient */
+ { 0x00000f88, 0x0000 }, /* R3976 (0xf88) - ANC Coefficient */
+ { 0x00000f89, 0x0000 }, /* R3977 (0xf89) - ANC Coefficient */
+ { 0x00000f8a, 0x0000 }, /* R3978 (0xf8a) - ANC Coefficient */
+ { 0x00000f8b, 0x0000 }, /* R3979 (0xf8b) - ANC Coefficient */
+ { 0x00000f8c, 0x0000 }, /* R3980 (0xf8c) - ANC Coefficient */
+ { 0x00000f8d, 0x0000 }, /* R3981 (0xf8d) - ANC Coefficient */
+ { 0x00000f8e, 0x0000 }, /* R3982 (0xf8e) - ANC Coefficient */
+ { 0x00000f8f, 0x0000 }, /* R3983 (0xf8f) - ANC Coefficient */
+ { 0x00000f90, 0x0000 }, /* R3984 (0xf90) - ANC Coefficient */
+ { 0x00000f91, 0x0000 }, /* R3985 (0xf91) - ANC Coefficient */
+ { 0x00000f92, 0x0000 }, /* R3986 (0xf92) - ANC Coefficient */
+ { 0x00000f93, 0x0000 }, /* R3987 (0xf93) - ANC Coefficient */
+ { 0x00000f94, 0x0000 }, /* R3988 (0xf94) - ANC Coefficient */
+ { 0x00000f95, 0x0000 }, /* R3989 (0xf95) - ANC Coefficient */
+ { 0x00000f96, 0x0000 }, /* R3990 (0xf96) - ANC Coefficient */
+ { 0x00000f97, 0x0000 }, /* R3991 (0xf97) - ANC Coefficient */
+ { 0x00000f98, 0x0000 }, /* R3992 (0xf98) - ANC Coefficient */
+ { 0x00000f99, 0x0000 }, /* R3993 (0xf99) - ANC Coefficient */
+ { 0x00000f9a, 0x0000 }, /* R3994 (0xf9a) - ANC Coefficient */
+ { 0x00000f9b, 0x0000 }, /* R3995 (0xf9b) - ANC Coefficient */
+ { 0x00000f9c, 0x0000 }, /* R3996 (0xf9c) - ANC Coefficient */
+ { 0x00000f9d, 0x0000 }, /* R3997 (0xf9d) - ANC Coefficient */
+ { 0x00000f9e, 0x0000 }, /* R3998 (0xf9e) - ANC Coefficient */
+ { 0x00000f9f, 0x0000 }, /* R3999 (0xf9f) - ANC Coefficient */
+ { 0x00000fa0, 0x0000 }, /* R4000 (0xfa0) - ANC Coefficient */
+ { 0x00000fa1, 0x0000 }, /* R4001 (0xfa1) - ANC Coefficient */
+ { 0x00000fa2, 0x0000 }, /* R4002 (0xfa2) - ANC Coefficient */
+ { 0x00000fa3, 0x0000 }, /* R4003 (0xfa3) - ANC Coefficient */
+ { 0x00000fa4, 0x0000 }, /* R4004 (0xfa4) - ANC Coefficient */
+ { 0x00000fa5, 0x0000 }, /* R4005 (0xfa5) - ANC Coefficient */
+ { 0x00000fa6, 0x0000 }, /* R4006 (0xfa6) - ANC Coefficient */
+ { 0x00000fa7, 0x0000 }, /* R4007 (0xfa7) - ANC Coefficient */
+ { 0x00000fa8, 0x0000 }, /* R4008 (0xfa8) - ANC Coefficient */
+ { 0x00000fa9, 0x0000 }, /* R4009 (0xfa9) - ANC Coefficient */
+ { 0x00000faa, 0x0000 }, /* R4010 (0xfaa) - ANC Coefficient */
+ { 0x00000fab, 0x0000 }, /* R4011 (0xfab) - ANC Coefficient */
+ { 0x00000fac, 0x0000 }, /* R4012 (0xfac) - ANC Coefficient */
+ { 0x00000fad, 0x0000 }, /* R4013 (0xfad) - ANC Coefficient */
+ { 0x00000fae, 0x0000 }, /* R4014 (0xfae) - ANC Coefficient */
+ { 0x00000faf, 0x0000 }, /* R4015 (0xfaf) - ANC Coefficient */
+ { 0x00000fb0, 0x0000 }, /* R4016 (0xfb0) - ANC Coefficient */
+ { 0x00000fb1, 0x0000 }, /* R4017 (0xfb1) - ANC Coefficient */
+ { 0x00000fb2, 0x0000 }, /* R4018 (0xfb2) - ANC Coefficient */
+ { 0x00000fb3, 0x0000 }, /* R4019 (0xfb3) - ANC Coefficient */
+ { 0x00000fb4, 0x0000 }, /* R4020 (0xfb4) - ANC Coefficient */
+ { 0x00000fb5, 0x0000 }, /* R4021 (0xfb5) - ANC Coefficient */
+ { 0x00000fb6, 0x0000 }, /* R4022 (0xfb6) - ANC Coefficient */
+ { 0x00000fb7, 0x0000 }, /* R4023 (0xfb7) - ANC Coefficient */
+ { 0x00000fb8, 0x0000 }, /* R4024 (0xfb8) - ANC Coefficient */
+ { 0x00000fb9, 0x0000 }, /* R4025 (0xfb9) - ANC Coefficient */
+ { 0x00000fba, 0x0000 }, /* R4026 (0xfba) - ANC Coefficient */
+ { 0x00000fbb, 0x0000 }, /* R4027 (0xfbb) - ANC Coefficient */
+ { 0x00000fbc, 0x0000 }, /* R4028 (0xfbc) - ANC Coefficient */
+ { 0x00000fbd, 0x0000 }, /* R4029 (0xfbd) - ANC Coefficient */
+ { 0x00000fbe, 0x0000 }, /* R4030 (0xfbe) - ANC Coefficient */
+ { 0x00000fbf, 0x0000 }, /* R4031 (0xfbf) - ANC Coefficient */
+ { 0x00000fc0, 0x0000 }, /* R4032 (0xfc0) - ANC Coefficient */
+ { 0x00000fc1, 0x0000 }, /* R4033 (0xfc1) - ANC Coefficient */
+ { 0x00000fc2, 0x0000 }, /* R4034 (0xfc2) - ANC Coefficient */
+ { 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
+ { 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
+ { 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
+ { 0x00001300, 0x050E }, /* R4864 (0x1300) - DAC Comp 1 */
+ { 0x00001302, 0x0101 }, /* R4866 (0x1302) - DAC Comp 2 */
+ { 0x00001380, 0x0425 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+ { 0x00001381, 0xF6D8 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+ { 0x00001382, 0x0632 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+ { 0x00001383, 0xFEC8 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+ { 0x00001390, 0x042F }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+ { 0x00001391, 0xF6CA }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+ { 0x00001392, 0x0637 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+ { 0x00001393, 0xFEC8 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+ { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
+ { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
+ { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
+ { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
+ { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
+ { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
+ { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
+ { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
+ { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
+ { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
+ { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
+ { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
+ { 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
+ { 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
+ { 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
+ { 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
+ { 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
+ { 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
+ { 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
+ { 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
+ { 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
+ { 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
+ { 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
+ { 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
+ { 0x00001480, 0x0000 }, /* R5248 (0x1480) - DFC1_CTRL */
+ { 0x00001482, 0x1f00 }, /* R5250 (0x1482) - DFC1_RX */
+ { 0x00001484, 0x1f00 }, /* R5252 (0x1486) - DFC1_TX */
+ { 0x00001486, 0x0000 }, /* R5254 (0x1486) - DFC2_CTRL */
+ { 0x00001488, 0x1f00 }, /* R5256 (0x1488) - DFC2_RX */
+ { 0x0000148a, 0x1f00 }, /* R5258 (0x148a) - DFC2_TX */
+ { 0x0000148c, 0x0000 }, /* R5260 (0x148c) - DFC3_CTRL */
+ { 0x0000148e, 0x1f00 }, /* R5262 (0x148e) - DFC3_RX */
+ { 0x00001490, 0x1f00 }, /* R5264 (0x1490) - DFC3_TX */
+ { 0x00001492, 0x0000 }, /* R5266 (0x1492) - DFC4_CTRL */
+ { 0x00001494, 0x1f00 }, /* R5268 (0x1494) - DFC4_RX */
+ { 0x00001496, 0x1f00 }, /* R5270 (0x1496) - DFC4_TX */
+ { 0x00001498, 0x0000 }, /* R5272 (0x1498) - DFC5_CTRL */
+ { 0x0000149a, 0x1f00 }, /* R5274 (0x149a) - DFC5_RX */
+ { 0x0000149c, 0x1f00 }, /* R5276 (0x149c) - DFC5_TX */
+ { 0x0000149e, 0x0000 }, /* R5278 (0x149e) - DFC6_CTRL */
+ { 0x000014a0, 0x1f00 }, /* R5280 (0x14a0) - DFC6_RX */
+ { 0x000014a2, 0x1f00 }, /* R5282 (0x14a2) - DFC6_TX */
+ { 0x000014a4, 0x0000 }, /* R5284 (0x14a4) - DFC7_CTRL */
+ { 0x000014a6, 0x1f00 }, /* R5286 (0x14a6) - DFC7_RX */
+ { 0x000014a8, 0x1f00 }, /* R5288 (0x14a8) - DFC7_TX */
+ { 0x000014aa, 0x0000 }, /* R5290 (0x14aa) - DFC8_CTRL */
+ { 0x000014ac, 0x1f00 }, /* R5292 (0x14ac) - DFC8_RX */
+ { 0x000014ae, 0x1f00 }, /* R5294 (0x14ae) - DFC8_TX */
+ { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+ { 0x00001701, 0xf000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+ { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+ { 0x00001703, 0xf000 }, /* R5891 (0x1702) - GPIO2 Control 2 */
+ { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+ { 0x00001705, 0xf000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+ { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+ { 0x00001707, 0xf000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+ { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+ { 0x00001709, 0xf000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+ { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+ { 0x0000170b, 0xf000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+ { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+ { 0x0000170d, 0xf000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+ { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+ { 0x0000170f, 0xf000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+ { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+ { 0x00001711, 0xf000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+ { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+ { 0x00001713, 0xf000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+ { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+ { 0x00001715, 0xf000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+ { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+ { 0x00001717, 0xf000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+ { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+ { 0x00001719, 0xf000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+ { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+ { 0x0000171b, 0xf000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+ { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+ { 0x0000171d, 0xf000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+ { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+ { 0x0000171f, 0xf000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+ { 0x00001720, 0x2001 }, /* R5920 (0x1720) - GPIO17 Control 1 */
+ { 0x00001721, 0xf000 }, /* R5921 (0x1721) - GPIO17 Control 2 */
+ { 0x00001722, 0x2001 }, /* R5922 (0x1722) - GPIO18 Control 1 */
+ { 0x00001723, 0xf000 }, /* R5923 (0x1723) - GPIO18 Control 2 */
+ { 0x00001724, 0x2001 }, /* R5924 (0x1724) - GPIO19 Control 1 */
+ { 0x00001725, 0xf000 }, /* R5925 (0x1725) - GPIO19 Control 2 */
+ { 0x00001726, 0x2001 }, /* R5926 (0x1726) - GPIO20 Control 1 */
+ { 0x00001727, 0xf000 }, /* R5927 (0x1727) - GPIO20 Control 2 */
+ { 0x00001728, 0x2001 }, /* R5928 (0x1728) - GPIO21 Control 1 */
+ { 0x00001729, 0xf000 }, /* R5929 (0x1729) - GPIO21 Control 2 */
+ { 0x0000172a, 0x2001 }, /* R5930 (0x172a) - GPIO22 Control 1 */
+ { 0x0000172b, 0xf000 }, /* R5931 (0x172b) - GPIO22 Control 2 */
+ { 0x0000172c, 0x2001 }, /* R5932 (0x172c) - GPIO23 Control 1 */
+ { 0x0000172d, 0xf000 }, /* R5933 (0x172d) - GPIO23 Control 2 */
+ { 0x0000172e, 0x2001 }, /* R5934 (0x172e) - GPIO24 Control 1 */
+ { 0x0000172f, 0xf000 }, /* R5935 (0x172f) - GPIO24 Control 2 */
+ { 0x00001730, 0x2001 }, /* R5936 (0x1730) - GPIO25 Control 1 */
+ { 0x00001731, 0xf000 }, /* R5937 (0x1731) - GPIO25 Control 2 */
+ { 0x00001732, 0x2001 }, /* R5938 (0x1732) - GPIO26 Control 1 */
+ { 0x00001733, 0xf000 }, /* R5939 (0x1733) - GPIO26 Control 2 */
+ { 0x00001734, 0x2001 }, /* R5940 (0x1734) - GPIO27 Control 1 */
+ { 0x00001735, 0xf000 }, /* R5941 (0x1735) - GPIO27 Control 2 */
+ { 0x00001736, 0x2001 }, /* R5942 (0x1736) - GPIO28 Control 1 */
+ { 0x00001737, 0xf000 }, /* R5943 (0x1737) - GPIO28 Control 2 */
+ { 0x00001738, 0x2001 }, /* R5944 (0x1738) - GPIO29 Control 1 */
+ { 0x00001739, 0xf000 }, /* R5945 (0x1739) - GPIO29 Control 2 */
+ { 0x0000173a, 0x2001 }, /* R5946 (0x173a) - GPIO30 Control 1 */
+ { 0x0000173b, 0xf000 }, /* R5947 (0x173b) - GPIO30 Control 2 */
+ { 0x0000173c, 0x2001 }, /* R5948 (0x173c) - GPIO31 Control 1 */
+ { 0x0000173d, 0xf000 }, /* R5949 (0x173d) - GPIO31 Control 2 */
+ { 0x0000173e, 0x2001 }, /* R5950 (0x173e) - GPIO32 Control 1 */
+ { 0x0000173f, 0xf000 }, /* R5951 (0x173f) - GPIO32 Control 2 */
+ { 0x00001740, 0x2001 }, /* R5952 (0x1740) - GPIO33 Control 1 */
+ { 0x00001741, 0xf000 }, /* R5953 (0x1741) - GPIO33 Control 2 */
+ { 0x00001742, 0x2001 }, /* R5954 (0x1742) - GPIO34 Control 1 */
+ { 0x00001743, 0xf000 }, /* R5955 (0x1743) - GPIO34 Control 2 */
+ { 0x00001744, 0x2001 }, /* R5956 (0x1744) - GPIO35 Control 1 */
+ { 0x00001745, 0xf000 }, /* R5957 (0x1745) - GPIO35 Control 2 */
+ { 0x00001746, 0x2001 }, /* R5958 (0x1746) - GPIO36 Control 1 */
+ { 0x00001747, 0xf000 }, /* R5959 (0x1747) - GPIO36 Control 2 */
+ { 0x00001748, 0x2001 }, /* R5960 (0x1748) - GPIO37 Control 1 */
+ { 0x00001749, 0xf000 }, /* R5961 (0x1749) - GPIO37 Control 2 */
+ { 0x0000174a, 0x2001 }, /* R5962 (0x174a) - GPIO38 Control 1 */
+ { 0x0000174b, 0xf000 }, /* R5963 (0x174b) - GPIO38 Control 2 */
+ { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+ { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+ { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+ { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+ { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+ { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+ { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+ { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+ { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+ { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+ { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+ { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+ { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+ { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+ { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+ { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+ { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+ { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+ { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+ { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+ { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+ { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+ { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+ { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+ { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+ { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+ { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+ { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+ { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+ { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+ { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+ { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+ { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+ { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+ { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l90_is_adsp_memory(unsigned int reg)
+{
+ switch (reg) {
+ case 0x080000 ... 0x088ffe:
+ case 0x0a0000 ... 0x0a9ffe:
+ case 0x0c0000 ... 0x0c3ffe:
+ case 0x0e0000 ... 0x0e1ffe:
+ case 0x100000 ... 0x10effe:
+ case 0x120000 ... 0x12bffe:
+ case 0x136000 ... 0x137ffe:
+ case 0x140000 ... 0x14bffe:
+ case 0x160000 ... 0x161ffe:
+ case 0x180000 ... 0x18effe:
+ case 0x1a0000 ... 0x1b1ffe:
+ case 0x1b6000 ... 0x1b7ffe:
+ case 0x1c0000 ... 0x1cbffe:
+ case 0x1e0000 ... 0x1e1ffe:
+ case 0x200000 ... 0x208ffe:
+ case 0x220000 ... 0x229ffe:
+ case 0x240000 ... 0x243ffe:
+ case 0x260000 ... 0x261ffe:
+ case 0x280000 ... 0x288ffe:
+ case 0x2a0000 ... 0x2a9ffe:
+ case 0x2c0000 ... 0x2c3ffe:
+ case 0x2e0000 ... 0x2e1ffe:
+ case 0x300000 ... 0x308ffe:
+ case 0x320000 ... 0x333ffe:
+ case 0x340000 ... 0x353ffe:
+ case 0x360000 ... 0x361ffe:
+ case 0x380000 ... 0x388ffe:
+ case 0x3a0000 ... 0x3b3ffe:
+ case 0x3c0000 ... 0x3d3ffe:
+ case 0x3e0000 ... 0x3e1ffe:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l90_16bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_TONE_GENERATOR_1:
+ case MADERA_TONE_GENERATOR_2:
+ case MADERA_TONE_GENERATOR_3:
+ case MADERA_TONE_GENERATOR_4:
+ case MADERA_TONE_GENERATOR_5:
+ case MADERA_PWM_DRIVE_1:
+ case MADERA_PWM_DRIVE_2:
+ case MADERA_PWM_DRIVE_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+ case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+ case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+ case MADERA_HAPTICS_CONTROL_1:
+ case MADERA_HAPTICS_CONTROL_2:
+ case MADERA_HAPTICS_PHASE_1_INTENSITY:
+ case MADERA_HAPTICS_PHASE_1_DURATION:
+ case MADERA_HAPTICS_PHASE_2_INTENSITY:
+ case MADERA_HAPTICS_PHASE_2_DURATION:
+ case MADERA_HAPTICS_PHASE_3_INTENSITY:
+ case MADERA_HAPTICS_PHASE_3_DURATION:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_COMFORT_NOISE_GENERATOR:
+ case MADERA_CLOCK_32K_1:
+ case MADERA_SYSTEM_CLOCK_1:
+ case MADERA_SAMPLE_RATE_1:
+ case MADERA_SAMPLE_RATE_2:
+ case MADERA_SAMPLE_RATE_3:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_ASYNC_CLOCK_1:
+ case MADERA_ASYNC_SAMPLE_RATE_1:
+ case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_2:
+ case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case MADERA_DSP_CLOCK_1:
+ case MADERA_DSP_CLOCK_2:
+ case MADERA_OUTPUT_SYSTEM_CLOCK:
+ case MADERA_OUTPUT_ASYNC_CLOCK:
+ case MADERA_RATE_ESTIMATOR_1:
+ case MADERA_RATE_ESTIMATOR_2:
+ case MADERA_RATE_ESTIMATOR_3:
+ case MADERA_RATE_ESTIMATOR_4:
+ case MADERA_RATE_ESTIMATOR_5:
+ case MADERA_FLL1_CONTROL_1:
+ case MADERA_FLL1_CONTROL_2:
+ case MADERA_FLL1_CONTROL_3:
+ case MADERA_FLL1_CONTROL_4:
+ case MADERA_FLL1_CONTROL_5:
+ case MADERA_FLL1_CONTROL_6:
+ case MADERA_FLL1_CONTROL_7:
+ case MADERA_FLL1_EFS_2:
+ case MADERA_FLL1_LOOP_FILTER_TEST_1:
+ case MADERA_FLL1_SYNCHRONISER_1:
+ case MADERA_FLL1_SYNCHRONISER_2:
+ case MADERA_FLL1_SYNCHRONISER_3:
+ case MADERA_FLL1_SYNCHRONISER_4:
+ case MADERA_FLL1_SYNCHRONISER_5:
+ case MADERA_FLL1_SYNCHRONISER_6:
+ case MADERA_FLL1_SYNCHRONISER_7:
+ case MADERA_FLL1_SPREAD_SPECTRUM:
+ case MADERA_FLL1_GPIO_CLOCK:
+ case MADERA_FLL2_CONTROL_1:
+ case MADERA_FLL2_CONTROL_2:
+ case MADERA_FLL2_CONTROL_3:
+ case MADERA_FLL2_CONTROL_4:
+ case MADERA_FLL2_CONTROL_5:
+ case MADERA_FLL2_CONTROL_6:
+ case MADERA_FLL2_CONTROL_7:
+ case MADERA_FLL2_EFS_2:
+ case MADERA_FLL2_LOOP_FILTER_TEST_1:
+ case MADERA_FLL2_SYNCHRONISER_1:
+ case MADERA_FLL2_SYNCHRONISER_2:
+ case MADERA_FLL2_SYNCHRONISER_3:
+ case MADERA_FLL2_SYNCHRONISER_4:
+ case MADERA_FLL2_SYNCHRONISER_5:
+ case MADERA_FLL2_SYNCHRONISER_6:
+ case MADERA_FLL2_SYNCHRONISER_7:
+ case MADERA_FLL2_SPREAD_SPECTRUM:
+ case MADERA_FLL2_GPIO_CLOCK:
+ case MADERA_FLLAO_CONTROL_1:
+ case MADERA_FLLAO_CONTROL_2:
+ case MADERA_FLLAO_CONTROL_3:
+ case MADERA_FLLAO_CONTROL_4:
+ case MADERA_FLLAO_CONTROL_5:
+ case MADERA_FLLAO_CONTROL_6:
+ case MADERA_FLLAO_CONTROL_7:
+ case MADERA_FLLAO_CONTROL_8:
+ case MADERA_FLLAO_CONTROL_9:
+ case MADERA_FLLAO_CONTROL_10:
+ case MADERA_FLLAO_CONTROL_11:
+ case MADERA_MIC_CHARGE_PUMP_1:
+ case MADERA_LDO2_CONTROL_1:
+ case MADERA_MIC_BIAS_CTRL_1:
+ case MADERA_MIC_BIAS_CTRL_2:
+ case MADERA_MIC_BIAS_CTRL_5:
+ case MADERA_MIC_BIAS_CTRL_6:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_HP_CTRL_2L:
+ case MADERA_HP_CTRL_2R:
+ case MADERA_HP_CTRL_3L:
+ case MADERA_HP_CTRL_3R:
+ case MADERA_EDRE_HP_STEREO_CONTROL:
+ case MADERA_ACCESSORY_DETECT_MODE_1:
+ case MADERA_HEADPHONE_DETECT_0:
+ case MADERA_HEADPHONE_DETECT_1:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_MICD_CLAMP_CONTROL:
+ case MADERA_MIC_DETECT_1_CONTROL_0:
+ case MADERA_MIC_DETECT_1_CONTROL_1:
+ case MADERA_MIC_DETECT_1_CONTROL_2:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_1:
+ case MADERA_MIC_DETECT_1_LEVEL_2:
+ case MADERA_MIC_DETECT_1_LEVEL_3:
+ case MADERA_MIC_DETECT_1_LEVEL_4:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_MIC_DETECT_2_CONTROL_0:
+ case MADERA_MIC_DETECT_2_CONTROL_1:
+ case MADERA_MIC_DETECT_2_CONTROL_2:
+ case MADERA_MIC_DETECT_2_CONTROL_3:
+ case MADERA_MIC_DETECT_2_LEVEL_1:
+ case MADERA_MIC_DETECT_2_LEVEL_2:
+ case MADERA_MIC_DETECT_2_LEVEL_3:
+ case MADERA_MIC_DETECT_2_LEVEL_4:
+ case MADERA_MIC_DETECT_2_CONTROL_4:
+ case MADERA_GP_SWITCH_1:
+ case MADERA_JACK_DETECT_ANALOGUE:
+ case MADERA_INPUT_ENABLES:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_INPUT_RATE:
+ case MADERA_INPUT_VOLUME_RAMP:
+ case MADERA_HPF_CONTROL:
+ case MADERA_IN1L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1L:
+ case MADERA_DMIC1L_CONTROL:
+ case MADERA_IN1L_RATE_CONTROL:
+ case MADERA_IN1R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_1R:
+ case MADERA_DMIC1R_CONTROL:
+ case MADERA_IN1R_RATE_CONTROL:
+ case MADERA_IN2L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2L:
+ case MADERA_DMIC2L_CONTROL:
+ case MADERA_IN2L_RATE_CONTROL:
+ case MADERA_IN2R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_2R:
+ case MADERA_DMIC2R_CONTROL:
+ case MADERA_IN2R_RATE_CONTROL:
+ case MADERA_IN3L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_3L:
+ case MADERA_DMIC3L_CONTROL:
+ case MADERA_IN3L_RATE_CONTROL:
+ case MADERA_IN3R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_3R:
+ case MADERA_DMIC3R_CONTROL:
+ case MADERA_IN3R_RATE_CONTROL:
+ case MADERA_IN4L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_4L:
+ case MADERA_DMIC4L_CONTROL:
+ case MADERA_IN4L_RATE_CONTROL:
+ case MADERA_IN4R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_4R:
+ case MADERA_DMIC4R_CONTROL:
+ case MADERA_IN4R_RATE_CONTROL:
+ case MADERA_IN5L_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_5L:
+ case MADERA_DMIC5L_CONTROL:
+ case MADERA_IN5L_RATE_CONTROL:
+ case MADERA_IN5R_CONTROL:
+ case MADERA_ADC_DIGITAL_VOLUME_5R:
+ case MADERA_DMIC5R_CONTROL:
+ case MADERA_IN5R_RATE_CONTROL:
+ case MADERA_OUTPUT_ENABLES_1:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_OUTPUT_RATE_1:
+ case MADERA_OUTPUT_VOLUME_RAMP:
+ case MADERA_OUTPUT_PATH_CONFIG_1L:
+ case MADERA_DAC_DIGITAL_VOLUME_1L:
+ case MADERA_OUTPUT_PATH_CONFIG_1:
+ case MADERA_NOISE_GATE_SELECT_1L:
+ case MADERA_OUTPUT_PATH_CONFIG_1R:
+ case MADERA_DAC_DIGITAL_VOLUME_1R:
+ case MADERA_NOISE_GATE_SELECT_1R:
+ case MADERA_OUTPUT_PATH_CONFIG_2L:
+ case MADERA_DAC_DIGITAL_VOLUME_2L:
+ case MADERA_OUTPUT_PATH_CONFIG_2:
+ case MADERA_NOISE_GATE_SELECT_2L:
+ case MADERA_OUTPUT_PATH_CONFIG_2R:
+ case MADERA_DAC_DIGITAL_VOLUME_2R:
+ case MADERA_NOISE_GATE_SELECT_2R:
+ case MADERA_OUTPUT_PATH_CONFIG_3L:
+ case MADERA_DAC_DIGITAL_VOLUME_3L:
+ case MADERA_NOISE_GATE_SELECT_3L:
+ case MADERA_OUTPUT_PATH_CONFIG_3R:
+ case MADERA_DAC_DIGITAL_VOLUME_3R:
+ case MADERA_NOISE_GATE_SELECT_3R:
+ case MADERA_OUTPUT_PATH_CONFIG_5L:
+ case MADERA_DAC_DIGITAL_VOLUME_5L:
+ case MADERA_NOISE_GATE_SELECT_5L:
+ case MADERA_OUTPUT_PATH_CONFIG_5R:
+ case MADERA_DAC_DIGITAL_VOLUME_5R:
+ case MADERA_NOISE_GATE_SELECT_5R:
+ case MADERA_DRE_ENABLE:
+ case MADERA_EDRE_ENABLE:
+ case MADERA_DAC_AEC_CONTROL_1:
+ case MADERA_NOISE_GATE_CONTROL:
+ case MADERA_PDM_SPK1_CTRL_1:
+ case MADERA_PDM_SPK1_CTRL_2:
+ case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP2_SHORT_CIRCUIT_CTRL:
+ case MADERA_HP3_SHORT_CIRCUIT_CTRL:
+ case MADERA_AIF1_BCLK_CTRL:
+ case MADERA_AIF1_TX_PIN_CTRL:
+ case MADERA_AIF1_RX_PIN_CTRL:
+ case MADERA_AIF1_RATE_CTRL:
+ case MADERA_AIF1_FORMAT:
+ case MADERA_AIF1_RX_BCLK_RATE:
+ case MADERA_AIF1_FRAME_CTRL_1:
+ case MADERA_AIF1_FRAME_CTRL_2:
+ case MADERA_AIF1_FRAME_CTRL_3:
+ case MADERA_AIF1_FRAME_CTRL_4:
+ case MADERA_AIF1_FRAME_CTRL_5:
+ case MADERA_AIF1_FRAME_CTRL_6:
+ case MADERA_AIF1_FRAME_CTRL_7:
+ case MADERA_AIF1_FRAME_CTRL_8:
+ case MADERA_AIF1_FRAME_CTRL_9:
+ case MADERA_AIF1_FRAME_CTRL_10:
+ case MADERA_AIF1_FRAME_CTRL_11:
+ case MADERA_AIF1_FRAME_CTRL_12:
+ case MADERA_AIF1_FRAME_CTRL_13:
+ case MADERA_AIF1_FRAME_CTRL_14:
+ case MADERA_AIF1_FRAME_CTRL_15:
+ case MADERA_AIF1_FRAME_CTRL_16:
+ case MADERA_AIF1_FRAME_CTRL_17:
+ case MADERA_AIF1_FRAME_CTRL_18:
+ case MADERA_AIF1_TX_ENABLES:
+ case MADERA_AIF1_RX_ENABLES:
+ case MADERA_AIF2_BCLK_CTRL:
+ case MADERA_AIF2_TX_PIN_CTRL:
+ case MADERA_AIF2_RX_PIN_CTRL:
+ case MADERA_AIF2_RATE_CTRL:
+ case MADERA_AIF2_FORMAT:
+ case MADERA_AIF2_RX_BCLK_RATE:
+ case MADERA_AIF2_FRAME_CTRL_1:
+ case MADERA_AIF2_FRAME_CTRL_2:
+ case MADERA_AIF2_FRAME_CTRL_3:
+ case MADERA_AIF2_FRAME_CTRL_4:
+ case MADERA_AIF2_FRAME_CTRL_5:
+ case MADERA_AIF2_FRAME_CTRL_6:
+ case MADERA_AIF2_FRAME_CTRL_7:
+ case MADERA_AIF2_FRAME_CTRL_8:
+ case MADERA_AIF2_FRAME_CTRL_9:
+ case MADERA_AIF2_FRAME_CTRL_10:
+ case MADERA_AIF2_FRAME_CTRL_11:
+ case MADERA_AIF2_FRAME_CTRL_12:
+ case MADERA_AIF2_FRAME_CTRL_13:
+ case MADERA_AIF2_FRAME_CTRL_14:
+ case MADERA_AIF2_FRAME_CTRL_15:
+ case MADERA_AIF2_FRAME_CTRL_16:
+ case MADERA_AIF2_FRAME_CTRL_17:
+ case MADERA_AIF2_FRAME_CTRL_18:
+ case MADERA_AIF2_TX_ENABLES:
+ case MADERA_AIF2_RX_ENABLES:
+ case MADERA_AIF3_BCLK_CTRL:
+ case MADERA_AIF3_TX_PIN_CTRL:
+ case MADERA_AIF3_RX_PIN_CTRL:
+ case MADERA_AIF3_RATE_CTRL:
+ case MADERA_AIF3_FORMAT:
+ case MADERA_AIF3_RX_BCLK_RATE:
+ case MADERA_AIF3_FRAME_CTRL_1:
+ case MADERA_AIF3_FRAME_CTRL_2:
+ case MADERA_AIF3_FRAME_CTRL_3:
+ case MADERA_AIF3_FRAME_CTRL_4:
+ case MADERA_AIF3_FRAME_CTRL_11:
+ case MADERA_AIF3_FRAME_CTRL_12:
+ case MADERA_AIF3_TX_ENABLES:
+ case MADERA_AIF3_RX_ENABLES:
+ case MADERA_AIF4_BCLK_CTRL:
+ case MADERA_AIF4_TX_PIN_CTRL:
+ case MADERA_AIF4_RX_PIN_CTRL:
+ case MADERA_AIF4_RATE_CTRL:
+ case MADERA_AIF4_FORMAT:
+ case MADERA_AIF4_RX_BCLK_RATE:
+ case MADERA_AIF4_FRAME_CTRL_1:
+ case MADERA_AIF4_FRAME_CTRL_2:
+ case MADERA_AIF4_FRAME_CTRL_3:
+ case MADERA_AIF4_FRAME_CTRL_4:
+ case MADERA_AIF4_FRAME_CTRL_11:
+ case MADERA_AIF4_FRAME_CTRL_12:
+ case MADERA_AIF4_TX_ENABLES:
+ case MADERA_AIF4_RX_ENABLES:
+ case MADERA_SPD1_TX_CONTROL:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+ case MADERA_SLIMBUS_RATES_1:
+ case MADERA_SLIMBUS_RATES_2:
+ case MADERA_SLIMBUS_RATES_3:
+ case MADERA_SLIMBUS_RATES_4:
+ case MADERA_SLIMBUS_RATES_5:
+ case MADERA_SLIMBUS_RATES_6:
+ case MADERA_SLIMBUS_RATES_7:
+ case MADERA_SLIMBUS_RATES_8:
+ case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_PWM1MIX_INPUT_1_SOURCE:
+ case MADERA_PWM1MIX_INPUT_1_VOLUME:
+ case MADERA_PWM1MIX_INPUT_2_SOURCE:
+ case MADERA_PWM1MIX_INPUT_2_VOLUME:
+ case MADERA_PWM1MIX_INPUT_3_SOURCE:
+ case MADERA_PWM1MIX_INPUT_3_VOLUME:
+ case MADERA_PWM1MIX_INPUT_4_SOURCE:
+ case MADERA_PWM1MIX_INPUT_4_VOLUME:
+ case MADERA_PWM2MIX_INPUT_1_SOURCE:
+ case MADERA_PWM2MIX_INPUT_1_VOLUME:
+ case MADERA_PWM2MIX_INPUT_2_SOURCE:
+ case MADERA_PWM2MIX_INPUT_2_VOLUME:
+ case MADERA_PWM2MIX_INPUT_3_SOURCE:
+ case MADERA_PWM2MIX_INPUT_3_VOLUME:
+ case MADERA_PWM2MIX_INPUT_4_SOURCE:
+ case MADERA_PWM2MIX_INPUT_4_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT2LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT2LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT2RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT2RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT3LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT3LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT3RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT3RMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+ case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+ case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX7MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX7MIX_INPUT_4_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_1_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_1_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_2_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_2_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_3_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_3_VOLUME:
+ case MADERA_AIF1TX8MIX_INPUT_4_SOURCE:
+ case MADERA_AIF1TX8MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX3MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX3MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX4MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX4MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX5MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX5MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX6MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX6MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX7MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX7MIX_INPUT_4_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_1_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_1_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_2_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_2_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_3_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_3_VOLUME:
+ case MADERA_AIF2TX8MIX_INPUT_4_SOURCE:
+ case MADERA_AIF2TX8MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_1_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_1_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_2_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_2_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_3_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_3_VOLUME:
+ case MADERA_AIF4TX1MIX_INPUT_4_SOURCE:
+ case MADERA_AIF4TX1MIX_INPUT_4_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_1_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_1_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_2_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_2_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_3_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_3_VOLUME:
+ case MADERA_AIF4TX2MIX_INPUT_4_SOURCE:
+ case MADERA_AIF4TX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX7MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX7MIX_INPUT_4_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_1_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_1_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_2_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_2_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_3_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_3_VOLUME:
+ case MADERA_SLIMTX8MIX_INPUT_4_SOURCE:
+ case MADERA_SLIMTX8MIX_INPUT_4_VOLUME:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+ case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_1_SOURCE:
+ case MADERA_EQ1MIX_INPUT_1_VOLUME:
+ case MADERA_EQ1MIX_INPUT_2_SOURCE:
+ case MADERA_EQ1MIX_INPUT_2_VOLUME:
+ case MADERA_EQ1MIX_INPUT_3_SOURCE:
+ case MADERA_EQ1MIX_INPUT_3_VOLUME:
+ case MADERA_EQ1MIX_INPUT_4_SOURCE:
+ case MADERA_EQ1MIX_INPUT_4_VOLUME:
+ case MADERA_EQ2MIX_INPUT_1_SOURCE:
+ case MADERA_EQ2MIX_INPUT_1_VOLUME:
+ case MADERA_EQ2MIX_INPUT_2_SOURCE:
+ case MADERA_EQ2MIX_INPUT_2_VOLUME:
+ case MADERA_EQ2MIX_INPUT_3_SOURCE:
+ case MADERA_EQ2MIX_INPUT_3_VOLUME:
+ case MADERA_EQ2MIX_INPUT_4_SOURCE:
+ case MADERA_EQ2MIX_INPUT_4_VOLUME:
+ case MADERA_EQ3MIX_INPUT_1_SOURCE:
+ case MADERA_EQ3MIX_INPUT_1_VOLUME:
+ case MADERA_EQ3MIX_INPUT_2_SOURCE:
+ case MADERA_EQ3MIX_INPUT_2_VOLUME:
+ case MADERA_EQ3MIX_INPUT_3_SOURCE:
+ case MADERA_EQ3MIX_INPUT_3_VOLUME:
+ case MADERA_EQ3MIX_INPUT_4_SOURCE:
+ case MADERA_EQ3MIX_INPUT_4_VOLUME:
+ case MADERA_EQ4MIX_INPUT_1_SOURCE:
+ case MADERA_EQ4MIX_INPUT_1_VOLUME:
+ case MADERA_EQ4MIX_INPUT_2_SOURCE:
+ case MADERA_EQ4MIX_INPUT_2_VOLUME:
+ case MADERA_EQ4MIX_INPUT_3_SOURCE:
+ case MADERA_EQ4MIX_INPUT_3_VOLUME:
+ case MADERA_EQ4MIX_INPUT_4_SOURCE:
+ case MADERA_EQ4MIX_INPUT_4_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+ case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+ case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+ case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+ case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP4LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP4LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP4RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP4RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP4AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP4AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP5LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP5LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP5RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP5RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP5AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP5AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_1LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_1RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_2LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC1_2RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_1LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_1RMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_2LMIX_INPUT_1_SOURCE:
+ case MADERA_ASRC2_2RMIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC3INT2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4INT1MIX_INPUT_1_SOURCE:
+ case MADERA_ISRC4INT2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP6LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP6LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP6RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP6RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP6AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP6AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_1_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_1_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_2_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_2_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_3_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_3_VOLUME:
+ case MADERA_DSP7LMIX_INPUT_4_SOURCE:
+ case MADERA_DSP7LMIX_INPUT_4_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_1_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_1_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_2_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_2_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_3_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_3_VOLUME:
+ case MADERA_DSP7RMIX_INPUT_4_SOURCE:
+ case MADERA_DSP7RMIX_INPUT_4_VOLUME:
+ case MADERA_DSP7AUX1MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX2MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX3MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX4MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX5MIX_INPUT_1_SOURCE:
+ case MADERA_DSP7AUX6MIX_INPUT_1_SOURCE:
+ case MADERA_DFC1MIX_INPUT_1_SOURCE:
+ case MADERA_DFC2MIX_INPUT_1_SOURCE:
+ case MADERA_DFC3MIX_INPUT_1_SOURCE:
+ case MADERA_DFC4MIX_INPUT_1_SOURCE:
+ case MADERA_DFC5MIX_INPUT_1_SOURCE:
+ case MADERA_DFC6MIX_INPUT_1_SOURCE:
+ case MADERA_DFC7MIX_INPUT_1_SOURCE:
+ case MADERA_DFC8MIX_INPUT_1_SOURCE:
+ case MADERA_FX_CTRL1:
+ case MADERA_FX_CTRL2:
+ case MADERA_EQ1_1 ... MADERA_EQ1_21:
+ case MADERA_EQ2_1 ... MADERA_EQ2_21:
+ case MADERA_EQ3_1 ... MADERA_EQ3_21:
+ case MADERA_EQ4_1 ... MADERA_EQ4_21:
+ case MADERA_DRC1_CTRL1:
+ case MADERA_DRC1_CTRL2:
+ case MADERA_DRC1_CTRL3:
+ case MADERA_DRC1_CTRL4:
+ case MADERA_DRC1_CTRL5:
+ case MADERA_DRC2_CTRL1:
+ case MADERA_DRC2_CTRL2:
+ case MADERA_DRC2_CTRL3:
+ case MADERA_DRC2_CTRL4:
+ case MADERA_DRC2_CTRL5:
+ case MADERA_HPLPF1_1:
+ case MADERA_HPLPF1_2:
+ case MADERA_HPLPF2_1:
+ case MADERA_HPLPF2_2:
+ case MADERA_HPLPF3_1:
+ case MADERA_HPLPF3_2:
+ case MADERA_HPLPF4_1:
+ case MADERA_HPLPF4_2:
+ case MADERA_ASRC1_ENABLE:
+ case MADERA_ASRC1_STATUS:
+ case MADERA_ASRC1_RATE1:
+ case MADERA_ASRC1_RATE2:
+ case MADERA_ASRC2_ENABLE:
+ case MADERA_ASRC2_STATUS:
+ case MADERA_ASRC2_RATE1:
+ case MADERA_ASRC2_RATE2:
+ case MADERA_ISRC_1_CTRL_1:
+ case MADERA_ISRC_1_CTRL_2:
+ case MADERA_ISRC_1_CTRL_3:
+ case MADERA_ISRC_2_CTRL_1:
+ case MADERA_ISRC_2_CTRL_2:
+ case MADERA_ISRC_2_CTRL_3:
+ case MADERA_ISRC_3_CTRL_1:
+ case MADERA_ISRC_3_CTRL_2:
+ case MADERA_ISRC_3_CTRL_3:
+ case MADERA_ISRC_4_CTRL_1:
+ case MADERA_ISRC_4_CTRL_2:
+ case MADERA_ISRC_4_CTRL_3:
+ case MADERA_CLOCK_CONTROL:
+ case MADERA_ANC_SRC:
+ case MADERA_DSP_STATUS:
+ case MADERA_ANC_COEFF_START ... MADERA_ANC_COEFF_END:
+ case MADERA_FCL_FILTER_CONTROL:
+ case MADERA_FCL_ADC_REFORMATTER_CONTROL:
+ case MADERA_FCL_COEFF_START ... MADERA_FCL_COEFF_END:
+ case MADERA_FCR_FILTER_CONTROL:
+ case MADERA_FCR_ADC_REFORMATTER_CONTROL:
+ case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
+ case MADERA_DAC_COMP_1:
+ case MADERA_DAC_COMP_2:
+ case MADERA_FRF_COEFFICIENT_1L_1:
+ case MADERA_FRF_COEFFICIENT_1L_2:
+ case MADERA_FRF_COEFFICIENT_1L_3:
+ case MADERA_FRF_COEFFICIENT_1L_4:
+ case MADERA_FRF_COEFFICIENT_1R_1:
+ case MADERA_FRF_COEFFICIENT_1R_2:
+ case MADERA_FRF_COEFFICIENT_1R_3:
+ case MADERA_FRF_COEFFICIENT_1R_4:
+ case MADERA_FRF_COEFFICIENT_2L_1:
+ case MADERA_FRF_COEFFICIENT_2L_2:
+ case MADERA_FRF_COEFFICIENT_2L_3:
+ case MADERA_FRF_COEFFICIENT_2L_4:
+ case MADERA_FRF_COEFFICIENT_2R_1:
+ case MADERA_FRF_COEFFICIENT_2R_2:
+ case MADERA_FRF_COEFFICIENT_2R_3:
+ case MADERA_FRF_COEFFICIENT_2R_4:
+ case MADERA_FRF_COEFFICIENT_3L_1:
+ case MADERA_FRF_COEFFICIENT_3L_2:
+ case MADERA_FRF_COEFFICIENT_3L_3:
+ case MADERA_FRF_COEFFICIENT_3L_4:
+ case MADERA_FRF_COEFFICIENT_3R_1:
+ case MADERA_FRF_COEFFICIENT_3R_2:
+ case MADERA_FRF_COEFFICIENT_3R_3:
+ case MADERA_FRF_COEFFICIENT_3R_4:
+ case MADERA_FRF_COEFFICIENT_5L_1:
+ case MADERA_FRF_COEFFICIENT_5L_2:
+ case MADERA_FRF_COEFFICIENT_5L_3:
+ case MADERA_FRF_COEFFICIENT_5L_4:
+ case MADERA_FRF_COEFFICIENT_5R_1:
+ case MADERA_FRF_COEFFICIENT_5R_2:
+ case MADERA_FRF_COEFFICIENT_5R_3:
+ case MADERA_FRF_COEFFICIENT_5R_4:
+ case MADERA_DFC1_CTRL:
+ case MADERA_DFC1_RX:
+ case MADERA_DFC1_TX:
+ case MADERA_DFC2_CTRL:
+ case MADERA_DFC2_RX:
+ case MADERA_DFC2_TX:
+ case MADERA_DFC3_CTRL:
+ case MADERA_DFC3_RX:
+ case MADERA_DFC3_TX:
+ case MADERA_DFC4_CTRL:
+ case MADERA_DFC4_RX:
+ case MADERA_DFC4_TX:
+ case MADERA_DFC5_CTRL:
+ case MADERA_DFC5_RX:
+ case MADERA_DFC5_TX:
+ case MADERA_DFC6_CTRL:
+ case MADERA_DFC6_RX:
+ case MADERA_DFC6_TX:
+ case MADERA_DFC7_CTRL:
+ case MADERA_DFC7_RX:
+ case MADERA_DFC7_TX:
+ case MADERA_DFC8_CTRL:
+ case MADERA_DFC8_RX:
+ case MADERA_DFC8_TX:
+ case MADERA_DFC_STATUS:
+ case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO38_CTRL_2:
+ case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ case MADERA_INTERRUPT_DEBOUNCE_7:
+ case MADERA_IRQ1_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l90_16bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_SOFTWARE_RESET:
+ case MADERA_HARDWARE_REVISION:
+ case MADERA_WRITE_SEQUENCER_CTRL_0:
+ case MADERA_WRITE_SEQUENCER_CTRL_1:
+ case MADERA_WRITE_SEQUENCER_CTRL_2:
+ case MADERA_HAPTICS_STATUS:
+ case MADERA_SAMPLE_RATE_1_STATUS:
+ case MADERA_SAMPLE_RATE_2_STATUS:
+ case MADERA_SAMPLE_RATE_3_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+ case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+ case MADERA_HP_CTRL_1L:
+ case MADERA_HP_CTRL_1R:
+ case MADERA_HP_CTRL_2L:
+ case MADERA_HP_CTRL_2R:
+ case MADERA_HP_CTRL_3L:
+ case MADERA_HP_CTRL_3R:
+ case MADERA_MIC_DETECT_1_CONTROL_3:
+ case MADERA_MIC_DETECT_1_CONTROL_4:
+ case MADERA_MIC_DETECT_2_CONTROL_3:
+ case MADERA_MIC_DETECT_2_CONTROL_4:
+ case MADERA_HEADPHONE_DETECT_2:
+ case MADERA_HEADPHONE_DETECT_3:
+ case MADERA_HEADPHONE_DETECT_5:
+ case MADERA_INPUT_ENABLES_STATUS:
+ case MADERA_OUTPUT_STATUS_1:
+ case MADERA_RAW_OUTPUT_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+ case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+ case MADERA_SLIMBUS_RX_PORT_STATUS:
+ case MADERA_SLIMBUS_TX_PORT_STATUS:
+ case MADERA_FX_CTRL2:
+ case MADERA_ASRC2_STATUS:
+ case MADERA_ASRC1_STATUS:
+ case MADERA_CLOCK_CONTROL:
+ case MADERA_DFC_STATUS:
+ case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+ case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs47l90_32bit_readable_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+ case MADERA_OTP_HPDET_CAL_1 ... MADERA_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ return true;
+ default:
+ return cs47l90_is_adsp_memory(reg);
+ }
+}
+
+static bool cs47l90_32bit_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+ case MADERA_OTP_HPDET_CAL_1 ... MADERA_OTP_HPDET_CAL_2:
+ case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+ return true;
+ default:
+ return cs47l90_is_adsp_memory(reg);
+ }
+}
+
+const struct regmap_config cs47l90_16bit_spi_regmap = {
+ .name = "cs47l90_16bit",
+ .reg_bits = 32,
+ .pad_bits = 16,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_INTERRUPT_RAW_STATUS_1,
+ .readable_reg = cs47l90_16bit_readable_register,
+ .volatile_reg = cs47l90_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l90_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l90_16bit_spi_regmap);
+
+const struct regmap_config cs47l90_16bit_i2c_regmap = {
+ .name = "cs47l90_16bit",
+ .reg_bits = 32,
+ .val_bits = 16,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_INTERRUPT_RAW_STATUS_1,
+ .readable_reg = cs47l90_16bit_readable_register,
+ .volatile_reg = cs47l90_16bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = cs47l90_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l90_16bit_i2c_regmap);
+
+const struct regmap_config cs47l90_32bit_spi_regmap = {
+ .name = "cs47l90_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .pad_bits = 16,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR,
+ .readable_reg = cs47l90_32bit_readable_register,
+ .volatile_reg = cs47l90_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l90_32bit_spi_regmap);
+
+const struct regmap_config cs47l90_32bit_i2c_regmap = {
+ .name = "cs47l90_32bit",
+ .reg_bits = 32,
+ .reg_stride = 2,
+ .val_bits = 32,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+
+ .max_register = MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR,
+ .readable_reg = cs47l90_32bit_readable_register,
+ .volatile_reg = cs47l90_32bit_volatile_register,
+
+ .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l90_32bit_i2c_regmap);
diff --git a/drivers/mfd/da9063-core.c b/drivers/mfd/da9063-core.c
index 6c2870d4e754..6e4ce49b4405 100644
--- a/drivers/mfd/da9063-core.c
+++ b/drivers/mfd/da9063-core.c
@@ -76,7 +76,7 @@ static struct resource da9063_hwmon_resources[] = {
};
-static const struct mfd_cell da9063_devs[] = {
+static const struct mfd_cell da9063_common_devs[] = {
{
.name = DA9063_DRVNAME_REGULATORS,
.num_resources = ARRAY_SIZE(da9063_regulators_resources),
@@ -101,14 +101,18 @@ static const struct mfd_cell da9063_devs[] = {
.of_compatible = "dlg,da9063-onkey",
},
{
+ .name = DA9063_DRVNAME_VIBRATION,
+ },
+};
+
+/* Only present on DA9063 , not on DA9063L */
+static const struct mfd_cell da9063_devs[] = {
+ {
.name = DA9063_DRVNAME_RTC,
.num_resources = ARRAY_SIZE(da9063_rtc_resources),
.resources = da9063_rtc_resources,
.of_compatible = "dlg,da9063-rtc",
},
- {
- .name = DA9063_DRVNAME_VIBRATION,
- },
};
static int da9063_clear_fault_log(struct da9063 *da9063)
@@ -192,7 +196,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
dev_err(da9063->dev, "Cannot read chip model id.\n");
return -EIO;
}
- if (model != PMIC_DA9063) {
+ if (model != PMIC_CHIP_ID_DA9063) {
dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
return -ENODEV;
}
@@ -215,7 +219,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
return -ENODEV;
}
- da9063->model = model;
da9063->variant_code = variant_code;
ret = da9063_irq_init(da9063);
@@ -226,19 +229,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
- ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
- ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
- NULL);
- if (ret)
- dev_err(da9063->dev, "Cannot add MFD cells\n");
+ ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
+ da9063_common_devs,
+ ARRAY_SIZE(da9063_common_devs),
+ NULL, da9063->irq_base, NULL);
+ if (ret) {
+ dev_err(da9063->dev, "Failed to add child devices\n");
+ return ret;
+ }
- return ret;
-}
+ if (da9063->type == PMIC_TYPE_DA9063) {
+ ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
+ da9063_devs, ARRAY_SIZE(da9063_devs),
+ NULL, da9063->irq_base, NULL);
+ if (ret) {
+ dev_err(da9063->dev, "Failed to add child devices\n");
+ return ret;
+ }
+ }
-void da9063_device_exit(struct da9063 *da9063)
-{
- mfd_remove_devices(da9063->dev);
- da9063_irq_exit(da9063);
+ return ret;
}
MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
diff --git a/drivers/mfd/da9063-i2c.c b/drivers/mfd/da9063-i2c.c
index 981805a2c521..50a24b1921d0 100644
--- a/drivers/mfd/da9063-i2c.c
+++ b/drivers/mfd/da9063-i2c.c
@@ -29,78 +29,33 @@
#include <linux/regulator/of_regulator.h>
static const struct regmap_range da9063_ad_readable_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_AD_REG_SECOND_D,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_ID_32_31,
- }, {
- .range_min = DA9063_REG_SEQ_A,
- .range_max = DA9063_REG_AUTO3_LOW,
- }, {
- .range_min = DA9063_REG_T_OFFSET,
- .range_max = DA9063_AD_REG_GP_ID_19,
- }, {
- .range_min = DA9063_REG_CHIP_ID,
- .range_max = DA9063_REG_CHIP_VARIANT,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
+ regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
};
static const struct regmap_range da9063_ad_writeable_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_PAGE_CON,
- }, {
- .range_min = DA9063_REG_FAULT_LOG,
- .range_max = DA9063_REG_VSYS_MON,
- }, {
- .range_min = DA9063_REG_COUNT_S,
- .range_max = DA9063_AD_REG_ALARM_Y,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_ID_32_31,
- }, {
- .range_min = DA9063_REG_SEQ_A,
- .range_max = DA9063_REG_AUTO3_LOW,
- }, {
- .range_min = DA9063_REG_CONFIG_I,
- .range_max = DA9063_AD_REG_MON_REG_4,
- }, {
- .range_min = DA9063_AD_REG_GP_ID_0,
- .range_max = DA9063_AD_REG_GP_ID_19,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+ regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+ regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4),
+ regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),
};
static const struct regmap_range da9063_ad_volatile_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_EVENT_D,
- }, {
- .range_min = DA9063_REG_CONTROL_A,
- .range_max = DA9063_REG_CONTROL_B,
- }, {
- .range_min = DA9063_REG_CONTROL_E,
- .range_max = DA9063_REG_CONTROL_F,
- }, {
- .range_min = DA9063_REG_BCORE2_CONT,
- .range_max = DA9063_REG_LDO11_CONT,
- }, {
- .range_min = DA9063_REG_DVC_1,
- .range_max = DA9063_REG_ADC_MAN,
- }, {
- .range_min = DA9063_REG_ADC_RES_L,
- .range_max = DA9063_AD_REG_SECOND_D,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_SEQ,
- }, {
- .range_min = DA9063_REG_EN_32K,
- .range_max = DA9063_REG_EN_32K,
- }, {
- .range_min = DA9063_AD_REG_MON_REG_5,
- .range_max = DA9063_AD_REG_MON_REG_6,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+ regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+ regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+ regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+ regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+ regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+ regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+ regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),
};
static const struct regmap_access_table da9063_ad_readable_table = {
@@ -119,78 +74,33 @@ static const struct regmap_access_table da9063_ad_volatile_table = {
};
static const struct regmap_range da9063_bb_readable_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_BB_REG_SECOND_D,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_ID_32_31,
- }, {
- .range_min = DA9063_REG_SEQ_A,
- .range_max = DA9063_REG_AUTO3_LOW,
- }, {
- .range_min = DA9063_REG_T_OFFSET,
- .range_max = DA9063_BB_REG_GP_ID_19,
- }, {
- .range_min = DA9063_REG_CHIP_ID,
- .range_max = DA9063_REG_CHIP_VARIANT,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
+ regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
};
static const struct regmap_range da9063_bb_writeable_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_PAGE_CON,
- }, {
- .range_min = DA9063_REG_FAULT_LOG,
- .range_max = DA9063_REG_VSYS_MON,
- }, {
- .range_min = DA9063_REG_COUNT_S,
- .range_max = DA9063_BB_REG_ALARM_Y,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_ID_32_31,
- }, {
- .range_min = DA9063_REG_SEQ_A,
- .range_max = DA9063_REG_AUTO3_LOW,
- }, {
- .range_min = DA9063_REG_CONFIG_I,
- .range_max = DA9063_BB_REG_MON_REG_4,
- }, {
- .range_min = DA9063_BB_REG_GP_ID_0,
- .range_max = DA9063_BB_REG_GP_ID_19,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+ regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+ regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
+ regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
};
static const struct regmap_range da9063_bb_volatile_ranges[] = {
- {
- .range_min = DA9063_REG_PAGE_CON,
- .range_max = DA9063_REG_EVENT_D,
- }, {
- .range_min = DA9063_REG_CONTROL_A,
- .range_max = DA9063_REG_CONTROL_B,
- }, {
- .range_min = DA9063_REG_CONTROL_E,
- .range_max = DA9063_REG_CONTROL_F,
- }, {
- .range_min = DA9063_REG_BCORE2_CONT,
- .range_max = DA9063_REG_LDO11_CONT,
- }, {
- .range_min = DA9063_REG_DVC_1,
- .range_max = DA9063_REG_ADC_MAN,
- }, {
- .range_min = DA9063_REG_ADC_RES_L,
- .range_max = DA9063_BB_REG_SECOND_D,
- }, {
- .range_min = DA9063_REG_SEQ,
- .range_max = DA9063_REG_SEQ,
- }, {
- .range_min = DA9063_REG_EN_32K,
- .range_max = DA9063_REG_EN_32K,
- }, {
- .range_min = DA9063_BB_REG_MON_REG_5,
- .range_max = DA9063_BB_REG_MON_REG_6,
- },
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+ regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+ regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+ regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+ regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+ regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+ regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+ regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
};
static const struct regmap_access_table da9063_bb_readable_table = {
@@ -208,6 +118,50 @@ static const struct regmap_access_table da9063_bb_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
};
+static const struct regmap_range da9063l_bb_readable_ranges[] = {
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
+ regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
+};
+
+static const struct regmap_range da9063l_bb_writeable_ranges[] = {
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+ regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+ regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+ regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
+ regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
+};
+
+static const struct regmap_range da9063l_bb_volatile_ranges[] = {
+ regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+ regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+ regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+ regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+ regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+ regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),
+ regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+ regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+ regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
+};
+
+static const struct regmap_access_table da9063l_bb_readable_table = {
+ .yes_ranges = da9063l_bb_readable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),
+};
+
+static const struct regmap_access_table da9063l_bb_writeable_table = {
+ .yes_ranges = da9063l_bb_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
+};
+
+static const struct regmap_access_table da9063l_bb_volatile_table = {
+ .yes_ranges = da9063l_bb_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(da9063l_bb_volatile_ranges),
+};
+
static const struct regmap_range_cfg da9063_range_cfg[] = {
{
.range_min = DA9063_REG_PAGE_CON,
@@ -232,11 +186,12 @@ static struct regmap_config da9063_regmap_config = {
static const struct of_device_id da9063_dt_ids[] = {
{ .compatible = "dlg,da9063", },
+ { .compatible = "dlg,da9063l", },
{ }
};
MODULE_DEVICE_TABLE(of, da9063_dt_ids);
static int da9063_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct da9063 *da9063;
int ret;
@@ -248,11 +203,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, da9063);
da9063->dev = &i2c->dev;
da9063->chip_irq = i2c->irq;
+ da9063->type = id->driver_data;
if (da9063->variant_code == PMIC_DA9063_AD) {
da9063_regmap_config.rd_table = &da9063_ad_readable_table;
da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
+ } else if (da9063->type == PMIC_TYPE_DA9063L) {
+ da9063_regmap_config.rd_table = &da9063l_bb_readable_table;
+ da9063_regmap_config.wr_table = &da9063l_bb_writeable_table;
+ da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table;
} else {
da9063_regmap_config.rd_table = &da9063_bb_readable_table;
da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
@@ -270,17 +230,9 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
return da9063_device_init(da9063, i2c->irq);
}
-static int da9063_i2c_remove(struct i2c_client *i2c)
-{
- struct da9063 *da9063 = i2c_get_clientdata(i2c);
-
- da9063_device_exit(da9063);
-
- return 0;
-}
-
static const struct i2c_device_id da9063_i2c_id[] = {
- {"da9063", PMIC_DA9063},
+ { "da9063", PMIC_TYPE_DA9063 },
+ { "da9063l", PMIC_TYPE_DA9063L },
{},
};
MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
@@ -291,7 +243,6 @@ static struct i2c_driver da9063_i2c_driver = {
.of_match_table = of_match_ptr(da9063_dt_ids),
},
.probe = da9063_i2c_probe,
- .remove = da9063_i2c_remove,
.id_table = da9063_i2c_id,
};
diff --git a/drivers/mfd/da9063-irq.c b/drivers/mfd/da9063-irq.c
index 207bbfe55449..ecc0c8ce6c58 100644
--- a/drivers/mfd/da9063-irq.c
+++ b/drivers/mfd/da9063-irq.c
@@ -28,132 +28,145 @@
static const struct regmap_irq da9063_irqs[] = {
/* DA9063 event A register */
- [DA9063_IRQ_ONKEY] = {
- .reg_offset = DA9063_REG_EVENT_A_OFFSET,
- .mask = DA9063_M_ONKEY,
- },
- [DA9063_IRQ_ALARM] = {
- .reg_offset = DA9063_REG_EVENT_A_OFFSET,
- .mask = DA9063_M_ALARM,
- },
- [DA9063_IRQ_TICK] = {
- .reg_offset = DA9063_REG_EVENT_A_OFFSET,
- .mask = DA9063_M_TICK,
- },
- [DA9063_IRQ_ADC_RDY] = {
- .reg_offset = DA9063_REG_EVENT_A_OFFSET,
- .mask = DA9063_M_ADC_RDY,
- },
- [DA9063_IRQ_SEQ_RDY] = {
- .reg_offset = DA9063_REG_EVENT_A_OFFSET,
- .mask = DA9063_M_SEQ_RDY,
- },
+ REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
+ REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
+ REGMAP_IRQ_REG(DA9063_IRQ_TICK,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
+ REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
+ REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
/* DA9063 event B register */
- [DA9063_IRQ_WAKE] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_WAKE,
- },
- [DA9063_IRQ_TEMP] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_TEMP,
- },
- [DA9063_IRQ_COMP_1V2] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_COMP_1V2,
- },
- [DA9063_IRQ_LDO_LIM] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_LDO_LIM,
- },
- [DA9063_IRQ_REG_UVOV] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_UVOV,
- },
- [DA9063_IRQ_DVC_RDY] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_DVC_RDY,
- },
- [DA9063_IRQ_VDD_MON] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_VDD_MON,
- },
- [DA9063_IRQ_WARN] = {
- .reg_offset = DA9063_REG_EVENT_B_OFFSET,
- .mask = DA9063_M_VDD_WARN,
- },
+ REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
+ REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
+ REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
+ REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
+ REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
+ REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
+ REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
+ REGMAP_IRQ_REG(DA9063_IRQ_WARN,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
/* DA9063 event C register */
- [DA9063_IRQ_GPI0] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI0,
- },
- [DA9063_IRQ_GPI1] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI1,
- },
- [DA9063_IRQ_GPI2] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI2,
- },
- [DA9063_IRQ_GPI3] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI3,
- },
- [DA9063_IRQ_GPI4] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI4,
- },
- [DA9063_IRQ_GPI5] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI5,
- },
- [DA9063_IRQ_GPI6] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI6,
- },
- [DA9063_IRQ_GPI7] = {
- .reg_offset = DA9063_REG_EVENT_C_OFFSET,
- .mask = DA9063_M_GPI7,
- },
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
/* DA9063 event D register */
- [DA9063_IRQ_GPI8] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI8,
- },
- [DA9063_IRQ_GPI9] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI9,
- },
- [DA9063_IRQ_GPI10] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI10,
- },
- [DA9063_IRQ_GPI11] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI11,
- },
- [DA9063_IRQ_GPI12] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI12,
- },
- [DA9063_IRQ_GPI13] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI13,
- },
- [DA9063_IRQ_GPI14] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI14,
- },
- [DA9063_IRQ_GPI15] = {
- .reg_offset = DA9063_REG_EVENT_D_OFFSET,
- .mask = DA9063_M_GPI15,
- },
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
};
static const struct regmap_irq_chip da9063_irq_chip = {
.name = "da9063-irq",
.irqs = da9063_irqs,
- .num_irqs = DA9063_NUM_IRQ,
+ .num_irqs = ARRAY_SIZE(da9063_irqs),
+ .num_regs = 4,
+ .status_base = DA9063_REG_EVENT_A,
+ .mask_base = DA9063_REG_IRQ_MASK_A,
+ .ack_base = DA9063_REG_EVENT_A,
+ .init_ack_masked = true,
+};
+
+static const struct regmap_irq da9063l_irqs[] = {
+ /* DA9063 event A register */
+ REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
+ REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
+ REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
+ DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
+ /* DA9063 event B register */
+ REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
+ REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
+ REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
+ REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
+ REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
+ REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
+ REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
+ REGMAP_IRQ_REG(DA9063_IRQ_WARN,
+ DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
+ /* DA9063 event C register */
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
+ DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
+ /* DA9063 event D register */
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
+ REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
+ DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
+};
+static const struct regmap_irq_chip da9063l_irq_chip = {
+ .name = "da9063l-irq",
+ .irqs = da9063l_irqs,
+ .num_irqs = ARRAY_SIZE(da9063l_irqs),
.num_regs = 4,
.status_base = DA9063_REG_EVENT_A,
.mask_base = DA9063_REG_IRQ_MASK_A,
@@ -163,6 +176,7 @@ static const struct regmap_irq_chip da9063_irq_chip = {
int da9063_irq_init(struct da9063 *da9063)
{
+ const struct regmap_irq_chip *irq_chip;
int ret;
if (!da9063->chip_irq) {
@@ -170,10 +184,15 @@ int da9063_irq_init(struct da9063 *da9063)
return -EINVAL;
}
- ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq,
+ if (da9063->type == PMIC_TYPE_DA9063)
+ irq_chip = &da9063_irq_chip;
+ else
+ irq_chip = &da9063l_irq_chip;
+
+ ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
+ da9063->chip_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
- da9063->irq_base, &da9063_irq_chip,
- &da9063->regmap_irq);
+ da9063->irq_base, irq_chip, &da9063->regmap_irq);
if (ret) {
dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
da9063->chip_irq, ret);
@@ -182,8 +201,3 @@ int da9063_irq_init(struct da9063 *da9063)
return 0;
}
-
-void da9063_irq_exit(struct da9063 *da9063)
-{
- regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
-}
diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
index 704e189ca162..90e789943466 100644
--- a/drivers/mfd/dln2.c
+++ b/drivers/mfd/dln2.c
@@ -194,6 +194,7 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
struct device *dev = &dln2->interface->dev;
struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
struct dln2_rx_context *rxc;
+ unsigned long flags;
bool valid_slot = false;
if (rx_slot >= DLN2_MAX_RX_SLOTS)
@@ -201,18 +202,13 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
rxc = &rxs->slots[rx_slot];
- /*
- * No need to disable interrupts as this lock is not taken in interrupt
- * context elsewhere in this driver. This function (or its callers) are
- * also not exported to other modules.
- */
- spin_lock(&rxs->lock);
+ spin_lock_irqsave(&rxs->lock, flags);
if (rxc->in_use && !rxc->urb) {
rxc->urb = urb;
complete(&rxc->done);
valid_slot = true;
}
- spin_unlock(&rxs->lock);
+ spin_unlock_irqrestore(&rxs->lock, flags);
out:
if (!valid_slot)
diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c
index c37ccbfd52f2..96c07fa1802a 100644
--- a/drivers/mfd/hi655x-pmic.c
+++ b/drivers/mfd/hi655x-pmic.c
@@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = {
.reg_bits = 32,
.reg_stride = HI655X_STRIDE,
.val_bits = 8,
- .max_register = HI655X_BUS_ADDR(0xFFF),
+ .max_register = HI655X_BUS_ADDR(0x400) - HI655X_STRIDE,
};
static struct resource pwrkey_resources[] = {
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index d9ae983095c5..0e5282fc1467 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -178,6 +178,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
+ /* ICL-LP */
+ { PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x34c5), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34c6), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34c7), (kernel_ulong_t)&spt_uart_info },
+ { PCI_VDEVICE(INTEL, 0x34e8), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34e9), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
/* APL */
{ PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 390b27cb2c2e..fb5a10b8317d 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -143,7 +143,7 @@ static struct platform_device *kempld_pdev;
static int kempld_create_platform_device(const struct dmi_system_id *id)
{
- struct kempld_platform_data *pdata = id->driver_data;
+ const struct kempld_platform_data *pdata = id->driver_data;
int ret;
kempld_pdev = platform_device_alloc("kempld", -1);
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
*/
void kempld_get_mutex(struct kempld_device_data *pld)
{
- struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+ const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
mutex_lock(&pld->lock);
pdata->get_hardware_mutex(pld);
@@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
*/
void kempld_release_mutex(struct kempld_device_data *pld)
{
- struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+ const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
pdata->release_hardware_mutex(pld);
mutex_unlock(&pld->lock);
@@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
static int kempld_get_info(struct kempld_device_data *pld)
{
int ret;
- struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+ const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
char major, minor;
ret = pdata->get_info(pld);
@@ -332,7 +332,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
*/
static int kempld_register_cells(struct kempld_device_data *pld)
{
- struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+ const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
return pdata->register_cells(pld);
}
@@ -444,7 +444,8 @@ static int kempld_detect_device(struct kempld_device_data *pld)
static int kempld_probe(struct platform_device *pdev)
{
- struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ const struct kempld_platform_data *pdata =
+ dev_get_platdata(&pdev->dev);
struct device *dev = &pdev->dev;
struct kempld_device_data *pld;
struct resource *ioport;
@@ -476,7 +477,7 @@ static int kempld_probe(struct platform_device *pdev)
static int kempld_remove(struct platform_device *pdev)
{
struct kempld_device_data *pld = platform_get_drvdata(pdev);
- struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+ const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c
new file mode 100644
index 000000000000..8cfea969b060
--- /dev/null
+++ b/drivers/mfd/madera-core.c
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core MFD support for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+#define CS47L35_SILICON_ID 0x6360
+#define CS47L85_SILICON_ID 0x6338
+#define CS47L90_SILICON_ID 0x6364
+
+#define MADERA_32KZ_MCLK2 1
+
+static const char * const madera_core_supplies[] = {
+ "AVDD",
+ "DBVDD1",
+};
+
+static const struct mfd_cell madera_ldo1_devs[] = {
+ { .name = "madera-ldo1" },
+};
+
+static const char * const cs47l35_supplies[] = {
+ "MICVDD",
+ "DBVDD2",
+ "CPVDD1",
+ "CPVDD2",
+ "SPKVDD",
+};
+
+static const struct mfd_cell cs47l35_devs[] = {
+ { .name = "madera-pinctrl", },
+ { .name = "madera-irq", },
+ { .name = "madera-micsupp", },
+ { .name = "madera-gpio", },
+ { .name = "madera-extcon", },
+ {
+ .name = "cs47l35-codec",
+ .parent_supplies = cs47l35_supplies,
+ .num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
+ },
+};
+
+static const char * const cs47l85_supplies[] = {
+ "MICVDD",
+ "DBVDD2",
+ "DBVDD3",
+ "DBVDD4",
+ "CPVDD1",
+ "CPVDD2",
+ "SPKVDDL",
+ "SPKVDDR",
+};
+
+static const struct mfd_cell cs47l85_devs[] = {
+ { .name = "madera-pinctrl", },
+ { .name = "madera-irq", },
+ { .name = "madera-micsupp" },
+ { .name = "madera-gpio", },
+ { .name = "madera-extcon", },
+ {
+ .name = "cs47l85-codec",
+ .parent_supplies = cs47l85_supplies,
+ .num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
+ },
+};
+
+static const char * const cs47l90_supplies[] = {
+ "MICVDD",
+ "DBVDD2",
+ "DBVDD3",
+ "DBVDD4",
+ "CPVDD1",
+ "CPVDD2",
+};
+
+static const struct mfd_cell cs47l90_devs[] = {
+ { .name = "madera-pinctrl", },
+ { .name = "madera-irq", },
+ { .name = "madera-micsupp", },
+ { .name = "madera-gpio", },
+ { .name = "madera-extcon", },
+ {
+ .name = "cs47l90-codec",
+ .parent_supplies = cs47l90_supplies,
+ .num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
+ },
+};
+
+/* Used by madera-i2c and madera-spi drivers */
+const char *madera_name_from_type(enum madera_type type)
+{
+ switch (type) {
+ case CS47L35:
+ return "CS47L35";
+ case CS47L85:
+ return "CS47L85";
+ case CS47L90:
+ return "CS47L90";
+ case CS47L91:
+ return "CS47L91";
+ case WM1840:
+ return "WM1840";
+ default:
+ return "Unknown";
+ }
+}
+EXPORT_SYMBOL_GPL(madera_name_from_type);
+
+#define MADERA_BOOT_POLL_MAX_INTERVAL_US 5000
+#define MADERA_BOOT_POLL_TIMEOUT_US 25000
+
+static int madera_wait_for_boot(struct madera *madera)
+{
+ unsigned int val;
+ int ret;
+
+ /*
+ * We can't use an interrupt as we need to runtime resume to do so,
+ * so we poll the status bit. This won't race with the interrupt
+ * handler because it will be blocked on runtime resume.
+ */
+ ret = regmap_read_poll_timeout(madera->regmap,
+ MADERA_IRQ1_RAW_STATUS_1,
+ val,
+ (val & MADERA_BOOT_DONE_STS1),
+ MADERA_BOOT_POLL_MAX_INTERVAL_US,
+ MADERA_BOOT_POLL_TIMEOUT_US);
+
+ if (ret)
+ dev_err(madera->dev, "Polling BOOT_DONE_STS failed: %d\n", ret);
+
+ /*
+ * BOOT_DONE defaults to unmasked on boot so we must ack it.
+ * Do this unconditionally to avoid interrupt storms.
+ */
+ regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
+ MADERA_BOOT_DONE_EINT1);
+
+ pm_runtime_mark_last_busy(madera->dev);
+
+ return ret;
+}
+
+static int madera_soft_reset(struct madera *madera)
+{
+ int ret;
+
+ ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
+ if (ret != 0) {
+ dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
+ return ret;
+ }
+
+ /* Allow time for internal clocks to startup after reset */
+ usleep_range(1000, 2000);
+
+ return 0;
+}
+
+static void madera_enable_hard_reset(struct madera *madera)
+{
+ if (!madera->pdata.reset)
+ return;
+
+ /*
+ * There are many existing out-of-tree users of these codecs that we
+ * can't break so preserve the expected behaviour of setting the line
+ * low to assert reset.
+ */
+ gpiod_set_raw_value_cansleep(madera->pdata.reset, 0);
+}
+
+static void madera_disable_hard_reset(struct madera *madera)
+{
+ if (!madera->pdata.reset)
+ return;
+
+ gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
+ usleep_range(1000, 2000);
+}
+
+static int __maybe_unused madera_runtime_resume(struct device *dev)
+{
+ struct madera *madera = dev_get_drvdata(dev);
+ int ret;
+
+ dev_dbg(dev, "Leaving sleep mode\n");
+
+ ret = regulator_enable(madera->dcvdd);
+ if (ret) {
+ dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(madera->regmap, false);
+ regcache_cache_only(madera->regmap_32bit, false);
+
+ ret = madera_wait_for_boot(madera);
+ if (ret)
+ goto err;
+
+ ret = regcache_sync(madera->regmap);
+ if (ret) {
+ dev_err(dev, "Failed to restore 16-bit register cache\n");
+ goto err;
+ }
+
+ ret = regcache_sync(madera->regmap_32bit);
+ if (ret) {
+ dev_err(dev, "Failed to restore 32-bit register cache\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regcache_cache_only(madera->regmap_32bit, true);
+ regcache_cache_only(madera->regmap, true);
+ regulator_disable(madera->dcvdd);
+
+ return ret;
+}
+
+static int __maybe_unused madera_runtime_suspend(struct device *dev)
+{
+ struct madera *madera = dev_get_drvdata(dev);
+
+ dev_dbg(madera->dev, "Entering sleep mode\n");
+
+ regcache_cache_only(madera->regmap, true);
+ regcache_mark_dirty(madera->regmap);
+ regcache_cache_only(madera->regmap_32bit, true);
+ regcache_mark_dirty(madera->regmap_32bit);
+
+ regulator_disable(madera->dcvdd);
+
+ return 0;
+}
+
+const struct dev_pm_ops madera_pm_ops = {
+ SET_RUNTIME_PM_OPS(madera_runtime_suspend,
+ madera_runtime_resume,
+ NULL)
+};
+EXPORT_SYMBOL_GPL(madera_pm_ops);
+
+const struct of_device_id madera_of_match[] = {
+ { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
+ { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
+ { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
+ { .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
+ { .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
+ {}
+};
+EXPORT_SYMBOL_GPL(madera_of_match);
+
+static int madera_get_reset_gpio(struct madera *madera)
+{
+ struct gpio_desc *reset;
+ int ret;
+
+ if (madera->pdata.reset)
+ return 0;
+
+ reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset)) {
+ ret = PTR_ERR(reset);
+ if (ret != -EPROBE_DEFER)
+ dev_err(madera->dev, "Failed to request /RESET: %d\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * A hard reset is needed for full reset of the chip. We allow running
+ * without hard reset only because it can be useful for early
+ * prototyping and some debugging, but we need to warn it's not ideal.
+ */
+ if (!reset)
+ dev_warn(madera->dev,
+ "Running without reset GPIO is not recommended\n");
+
+ madera->pdata.reset = reset;
+
+ return 0;
+}
+
+static void madera_set_micbias_info(struct madera *madera)
+{
+ /*
+ * num_childbias is an array because future codecs can have different
+ * childbiases for each micbias. Unspecified values default to 0.
+ */
+ switch (madera->type) {
+ case CS47L35:
+ madera->num_micbias = 2;
+ madera->num_childbias[0] = 2;
+ madera->num_childbias[1] = 2;
+ return;
+ case CS47L85:
+ case WM1840:
+ madera->num_micbias = 4;
+ /* no child biases */
+ return;
+ case CS47L90:
+ case CS47L91:
+ madera->num_micbias = 2;
+ madera->num_childbias[0] = 4;
+ madera->num_childbias[1] = 4;
+ return;
+ default:
+ return;
+ }
+}
+
+int madera_dev_init(struct madera *madera)
+{
+ struct device *dev = madera->dev;
+ unsigned int hwid;
+ int (*patch_fn)(struct madera *) = NULL;
+ const struct mfd_cell *mfd_devs;
+ int n_devs = 0;
+ int i, ret;
+
+ dev_set_drvdata(madera->dev, madera);
+ BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+ madera_set_micbias_info(madera);
+
+ /*
+ * We need writable hw config info that all children can share.
+ * Simplest to take one shared copy of pdata struct.
+ */
+ if (dev_get_platdata(madera->dev)) {
+ memcpy(&madera->pdata, dev_get_platdata(madera->dev),
+ sizeof(madera->pdata));
+ }
+
+ ret = madera_get_reset_gpio(madera);
+ if (ret)
+ return ret;
+
+ regcache_cache_only(madera->regmap, true);
+ regcache_cache_only(madera->regmap_32bit, true);
+
+ for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
+ madera->core_supplies[i].supply = madera_core_supplies[i];
+
+ madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
+
+ /*
+ * On some codecs DCVDD could be supplied by the internal LDO1.
+ * For those we must add the LDO1 driver before requesting DCVDD
+ * No devm_ because we need to control shutdown order of children.
+ */
+ switch (madera->type) {
+ case CS47L35:
+ case CS47L90:
+ case CS47L91:
+ break;
+ case CS47L85:
+ case WM1840:
+ ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
+ madera_ldo1_devs,
+ ARRAY_SIZE(madera_ldo1_devs),
+ NULL, 0, NULL);
+ if (ret) {
+ dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
+ return ret;
+ }
+ break;
+ default:
+ /* No point continuing if the type is unknown */
+ dev_err(madera->dev, "Unknown device type %d\n", madera->type);
+ return -ENODEV;
+ }
+
+ ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
+ madera->core_supplies);
+ if (ret) {
+ dev_err(dev, "Failed to request core supplies: %d\n", ret);
+ goto err_devs;
+ }
+
+ /*
+ * Don't use devres here. If the regulator is one of our children it
+ * will already have been removed before devres cleanup on this mfd
+ * driver tries to call put() on it. We need control of shutdown order.
+ */
+ madera->dcvdd = regulator_get(madera->dev, "DCVDD");
+ if (IS_ERR(madera->dcvdd)) {
+ ret = PTR_ERR(madera->dcvdd);
+ dev_err(dev, "Failed to request DCVDD: %d\n", ret);
+ goto err_devs;
+ }
+
+ ret = regulator_bulk_enable(madera->num_core_supplies,
+ madera->core_supplies);
+ if (ret) {
+ dev_err(dev, "Failed to enable core supplies: %d\n", ret);
+ goto err_dcvdd;
+ }
+
+ ret = regulator_enable(madera->dcvdd);
+ if (ret) {
+ dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
+ goto err_enable;
+ }
+
+ madera_disable_hard_reset(madera);
+
+ regcache_cache_only(madera->regmap, false);
+ regcache_cache_only(madera->regmap_32bit, false);
+
+ /*
+ * Now we can power up and verify that this is a chip we know about
+ * before we start doing any writes to its registers.
+ */
+ ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
+ if (ret) {
+ dev_err(dev, "Failed to read ID register: %d\n", ret);
+ goto err_reset;
+ }
+
+ switch (hwid) {
+ case CS47L35_SILICON_ID:
+ if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+ switch (madera->type) {
+ case CS47L35:
+ patch_fn = cs47l35_patch;
+ mfd_devs = cs47l35_devs;
+ n_devs = ARRAY_SIZE(cs47l35_devs);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case CS47L85_SILICON_ID:
+ if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+ switch (madera->type) {
+ case CS47L85:
+ case WM1840:
+ patch_fn = cs47l85_patch;
+ mfd_devs = cs47l85_devs;
+ n_devs = ARRAY_SIZE(cs47l85_devs);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case CS47L90_SILICON_ID:
+ if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+ switch (madera->type) {
+ case CS47L90:
+ case CS47L91:
+ patch_fn = cs47l90_patch;
+ mfd_devs = cs47l90_devs;
+ n_devs = ARRAY_SIZE(cs47l90_devs);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
+ ret = -EINVAL;
+ goto err_reset;
+ }
+
+ if (!n_devs) {
+ dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
+ madera->type_name);
+ ret = -ENODEV;
+ goto err_reset;
+ }
+
+ /*
+ * It looks like a device we support. If we don't have a hard reset
+ * we can now attempt a soft reset.
+ */
+ if (!madera->pdata.reset) {
+ ret = madera_soft_reset(madera);
+ if (ret)
+ goto err_reset;
+ }
+
+ ret = madera_wait_for_boot(madera);
+ if (ret) {
+ dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
+ goto err_reset;
+ }
+
+ ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
+ &madera->rev);
+ if (ret) {
+ dev_err(dev, "Failed to read revision register: %d\n", ret);
+ goto err_reset;
+ }
+ madera->rev &= MADERA_HW_REVISION_MASK;
+
+ dev_info(dev, "%s silicon revision %d\n", madera->type_name,
+ madera->rev);
+
+ /* Apply hardware patch */
+ if (patch_fn) {
+ ret = patch_fn(madera);
+ if (ret) {
+ dev_err(madera->dev, "Failed to apply patch %d\n", ret);
+ goto err_reset;
+ }
+ }
+
+ /* Init 32k clock sourced from MCLK2 */
+ ret = regmap_update_bits(madera->regmap,
+ MADERA_CLOCK_32K_1,
+ MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
+ MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
+ if (ret) {
+ dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
+ goto err_reset;
+ }
+
+ pm_runtime_set_active(madera->dev);
+ pm_runtime_enable(madera->dev);
+ pm_runtime_set_autosuspend_delay(madera->dev, 100);
+ pm_runtime_use_autosuspend(madera->dev);
+
+ /* No devm_ because we need to control shutdown order of children */
+ ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
+ mfd_devs, n_devs,
+ NULL, 0, NULL);
+ if (ret) {
+ dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
+ goto err_pm_runtime;
+ }
+
+ return 0;
+
+err_pm_runtime:
+ pm_runtime_disable(madera->dev);
+err_reset:
+ madera_enable_hard_reset(madera);
+ regulator_disable(madera->dcvdd);
+err_enable:
+ regulator_bulk_disable(madera->num_core_supplies,
+ madera->core_supplies);
+err_dcvdd:
+ regulator_put(madera->dcvdd);
+err_devs:
+ mfd_remove_devices(dev);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(madera_dev_init);
+
+int madera_dev_exit(struct madera *madera)
+{
+ /* Prevent any IRQs being serviced while we clean up */
+ disable_irq(madera->irq);
+
+ /*
+ * DCVDD could be supplied by a child node, we must disable it before
+ * removing the children, and prevent PM runtime from turning it back on
+ */
+ pm_runtime_disable(madera->dev);
+
+ regulator_disable(madera->dcvdd);
+ regulator_put(madera->dcvdd);
+
+ mfd_remove_devices(madera->dev);
+ madera_enable_hard_reset(madera);
+
+ regulator_bulk_disable(madera->num_core_supplies,
+ madera->core_supplies);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(madera_dev_exit);
+
+MODULE_DESCRIPTION("Madera core MFD driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c
new file mode 100644
index 000000000000..05ae94be01d8
--- /dev/null
+++ b/drivers/mfd/madera-i2c.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C bus interface to Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+
+#include "madera.h"
+
+static int madera_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct madera *madera;
+ const struct regmap_config *regmap_16bit_config = NULL;
+ const struct regmap_config *regmap_32bit_config = NULL;
+ const void *of_data;
+ unsigned long type;
+ const char *name;
+ int ret;
+
+ of_data = of_device_get_match_data(&i2c->dev);
+ if (of_data)
+ type = (unsigned long)of_data;
+ else
+ type = id->driver_data;
+
+ switch (type) {
+ case CS47L35:
+ if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+ regmap_16bit_config = &cs47l35_16bit_i2c_regmap;
+ regmap_32bit_config = &cs47l35_32bit_i2c_regmap;
+ }
+ break;
+ case CS47L85:
+ case WM1840:
+ if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+ regmap_16bit_config = &cs47l85_16bit_i2c_regmap;
+ regmap_32bit_config = &cs47l85_32bit_i2c_regmap;
+ }
+ break;
+ case CS47L90:
+ case CS47L91:
+ if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+ regmap_16bit_config = &cs47l90_16bit_i2c_regmap;
+ regmap_32bit_config = &cs47l90_32bit_i2c_regmap;
+ }
+ break;
+ default:
+ dev_err(&i2c->dev,
+ "Unknown Madera I2C device type %ld\n", type);
+ return -EINVAL;
+ }
+
+ name = madera_name_from_type(type);
+
+ if (!regmap_16bit_config) {
+ /* it's polite to say which codec isn't built into the kernel */
+ dev_err(&i2c->dev,
+ "Kernel does not include support for %s\n", name);
+ return -EINVAL;
+ }
+
+ madera = devm_kzalloc(&i2c->dev, sizeof(*madera), GFP_KERNEL);
+ if (!madera)
+ return -ENOMEM;
+
+
+ madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);
+ if (IS_ERR(madera->regmap)) {
+ ret = PTR_ERR(madera->regmap);
+ dev_err(&i2c->dev,
+ "Failed to allocate 16-bit register map: %d\n", ret);
+ return ret;
+ }
+
+ madera->regmap_32bit = devm_regmap_init_i2c(i2c, regmap_32bit_config);
+ if (IS_ERR(madera->regmap_32bit)) {
+ ret = PTR_ERR(madera->regmap_32bit);
+ dev_err(&i2c->dev,
+ "Failed to allocate 32-bit register map: %d\n", ret);
+ return ret;
+ }
+
+ madera->type = type;
+ madera->type_name = name;
+ madera->dev = &i2c->dev;
+ madera->irq = i2c->irq;
+
+ return madera_dev_init(madera);
+}
+
+static int madera_i2c_remove(struct i2c_client *i2c)
+{
+ struct madera *madera = dev_get_drvdata(&i2c->dev);
+
+ madera_dev_exit(madera);
+
+ return 0;
+}
+
+static const struct i2c_device_id madera_i2c_id[] = {
+ { "cs47l35", CS47L35 },
+ { "cs47l85", CS47L85 },
+ { "cs47l90", CS47L90 },
+ { "cs47l91", CS47L91 },
+ { "wm1840", WM1840 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, madera_i2c_id);
+
+static struct i2c_driver madera_i2c_driver = {
+ .driver = {
+ .name = "madera",
+ .pm = &madera_pm_ops,
+ .of_match_table = of_match_ptr(madera_of_match),
+ },
+ .probe = madera_i2c_probe,
+ .remove = madera_i2c_remove,
+ .id_table = madera_i2c_id,
+};
+
+module_i2c_driver(madera_i2c_driver);
+
+MODULE_DESCRIPTION("Madera I2C bus interface");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c
new file mode 100644
index 000000000000..4c398b278bba
--- /dev/null
+++ b/drivers/mfd/madera-spi.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI bus interface to Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mfd/madera/core.h>
+
+#include "madera.h"
+
+static int madera_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ struct madera *madera;
+ const struct regmap_config *regmap_16bit_config = NULL;
+ const struct regmap_config *regmap_32bit_config = NULL;
+ const void *of_data;
+ unsigned long type;
+ const char *name;
+ int ret;
+
+ of_data = of_device_get_match_data(&spi->dev);
+ if (of_data)
+ type = (unsigned long)of_data;
+ else
+ type = id->driver_data;
+
+ switch (type) {
+ case CS47L35:
+ if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+ regmap_16bit_config = &cs47l35_16bit_spi_regmap;
+ regmap_32bit_config = &cs47l35_32bit_spi_regmap;
+ }
+ break;
+ case CS47L85:
+ case WM1840:
+ if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+ regmap_16bit_config = &cs47l85_16bit_spi_regmap;
+ regmap_32bit_config = &cs47l85_32bit_spi_regmap;
+ }
+ break;
+ case CS47L90:
+ case CS47L91:
+ if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+ regmap_16bit_config = &cs47l90_16bit_spi_regmap;
+ regmap_32bit_config = &cs47l90_32bit_spi_regmap;
+ }
+ break;
+ default:
+ dev_err(&spi->dev,
+ "Unknown Madera SPI device type %ld\n", type);
+ return -EINVAL;
+ }
+
+ name = madera_name_from_type(type);
+
+ if (!regmap_16bit_config) {
+ /* it's polite to say which codec isn't built into the kernel */
+ dev_err(&spi->dev,
+ "Kernel does not include support for %s\n", name);
+ return -EINVAL;
+ }
+
+ madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
+ if (!madera)
+ return -ENOMEM;
+
+ madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
+ if (IS_ERR(madera->regmap)) {
+ ret = PTR_ERR(madera->regmap);
+ dev_err(&spi->dev,
+ "Failed to allocate 16-bit register map: %d\n", ret);
+ return ret;
+ }
+
+ madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
+ if (IS_ERR(madera->regmap_32bit)) {
+ ret = PTR_ERR(madera->regmap_32bit);
+ dev_err(&spi->dev,
+ "Failed to allocate 32-bit register map: %d\n", ret);
+ return ret;
+ }
+
+ madera->type = type;
+ madera->type_name = name;
+ madera->dev = &spi->dev;
+ madera->irq = spi->irq;
+
+ return madera_dev_init(madera);
+}
+
+static int madera_spi_remove(struct spi_device *spi)
+{
+ struct madera *madera = spi_get_drvdata(spi);
+
+ madera_dev_exit(madera);
+
+ return 0;
+}
+
+static const struct spi_device_id madera_spi_ids[] = {
+ { "cs47l35", CS47L35 },
+ { "cs47l85", CS47L85 },
+ { "cs47l90", CS47L90 },
+ { "cs47l91", CS47L91 },
+ { "wm1840", WM1840 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, madera_spi_ids);
+
+static struct spi_driver madera_spi_driver = {
+ .driver = {
+ .name = "madera",
+ .pm = &madera_pm_ops,
+ .of_match_table = of_match_ptr(madera_of_match),
+ },
+ .probe = madera_spi_probe,
+ .remove = madera_spi_remove,
+ .id_table = madera_spi_ids,
+};
+
+module_spi_driver(madera_spi_driver);
+
+MODULE_DESCRIPTION("Madera SPI bus interface");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera.h b/drivers/mfd/madera.h
new file mode 100644
index 000000000000..891b84efb9a7
--- /dev/null
+++ b/drivers/mfd/madera.h
@@ -0,0 +1,44 @@
+/*
+ * MFD internals for Cirrus Logic Madera codecs
+ *
+ * Copyright 2015-2018 Cirrus Logic
+ *
+ * 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.
+ */
+
+#ifndef MADERA_MFD_H
+#define MADERA_MFD_H
+
+#include <linux/of.h>
+#include <linux/pm.h>
+
+struct madera;
+
+extern const struct dev_pm_ops madera_pm_ops;
+extern const struct of_device_id madera_of_match[];
+
+int madera_dev_init(struct madera *madera);
+int madera_dev_exit(struct madera *madera);
+
+const char *madera_name_from_type(enum madera_type type);
+
+extern const struct regmap_config cs47l35_16bit_spi_regmap;
+extern const struct regmap_config cs47l35_32bit_spi_regmap;
+extern const struct regmap_config cs47l35_16bit_i2c_regmap;
+extern const struct regmap_config cs47l35_32bit_i2c_regmap;
+int cs47l35_patch(struct madera *madera);
+
+extern const struct regmap_config cs47l85_16bit_spi_regmap;
+extern const struct regmap_config cs47l85_32bit_spi_regmap;
+extern const struct regmap_config cs47l85_16bit_i2c_regmap;
+extern const struct regmap_config cs47l85_32bit_i2c_regmap;
+int cs47l85_patch(struct madera *madera);
+
+extern const struct regmap_config cs47l90_16bit_spi_regmap;
+extern const struct regmap_config cs47l90_32bit_spi_regmap;
+extern const struct regmap_config cs47l90_16bit_i2c_regmap;
+extern const struct regmap_config cs47l90_32bit_i2c_regmap;
+int cs47l90_patch(struct madera *madera);
+#endif
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 36dcd98977d6..2a8369657e38 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -63,16 +63,6 @@
#define RAVE_SP_TX_BUFFER_SIZE \
(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
-#define RAVE_SP_BOOT_SOURCE_GET 0
-#define RAVE_SP_BOOT_SOURCE_SET 1
-
-#define RAVE_SP_RDU2_BOARD_TYPE_RMB 0
-#define RAVE_SP_RDU2_BOARD_TYPE_DEB 1
-
-#define RAVE_SP_BOOT_SOURCE_SD 0
-#define RAVE_SP_BOOT_SOURCE_EMMC 1
-#define RAVE_SP_BOOT_SOURCE_NOR 2
-
/**
* enum rave_sp_deframer_state - Possible state for de-framer
*
@@ -127,14 +117,44 @@ struct rave_sp_checksum {
void (*subroutine)(const u8 *, size_t, u8 *);
};
+struct rave_sp_version {
+ u8 hardware;
+ __le16 major;
+ u8 minor;
+ u8 letter[2];
+} __packed;
+
+struct rave_sp_status {
+ struct rave_sp_version bootloader_version;
+ struct rave_sp_version firmware_version;
+ u16 rdu_eeprom_flag;
+ u16 dds_eeprom_flag;
+ u8 pic_flag;
+ u8 orientation;
+ u32 etc;
+ s16 temp[2];
+ u8 backlight_current[3];
+ u8 dip_switch;
+ u8 host_interrupt;
+ u16 voltage_28;
+ u8 i2c_device_status;
+ u8 power_status;
+ u8 general_status;
+ u8 deprecated1;
+ u8 power_led_status;
+ u8 deprecated2;
+ u8 periph_power_shutoff;
+} __packed;
+
/**
* struct rave_sp_variant_cmds - Variant specific command routines
*
* @translate: Generic to variant specific command mapping routine
- *
+ * @get_status: Variant specific implementation of CMD_GET_STATUS
*/
struct rave_sp_variant_cmds {
int (*translate)(enum rave_sp_command);
+ int (*get_status)(struct rave_sp *sp, struct rave_sp_status *);
};
/**
@@ -180,35 +200,6 @@ struct rave_sp {
const char *part_number_bootloader;
};
-struct rave_sp_version {
- u8 hardware;
- __le16 major;
- u8 minor;
- u8 letter[2];
-} __packed;
-
-struct rave_sp_status {
- struct rave_sp_version bootloader_version;
- struct rave_sp_version firmware_version;
- u16 rdu_eeprom_flag;
- u16 dds_eeprom_flag;
- u8 pic_flag;
- u8 orientation;
- u32 etc;
- s16 temp[2];
- u8 backlight_current[3];
- u8 dip_switch;
- u8 host_interrupt;
- u16 voltage_28;
- u8 i2c_device_status;
- u8 power_status;
- u8 general_status;
- u8 deprecated1;
- u8 power_led_status;
- u8 deprecated2;
- u8 periph_power_shutoff;
-} __packed;
-
static bool rave_sp_id_is_event(u8 code)
{
return (code & 0xF0) == RAVE_SP_EVNT_BASE;
@@ -641,10 +632,14 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
return 0x14;
case RAVE_SP_CMD_SW_WDT:
return 0x1C;
+ case RAVE_SP_CMD_PET_WDT:
+ return 0x1D;
case RAVE_SP_CMD_RESET:
return 0x1E;
case RAVE_SP_CMD_RESET_REASON:
return 0x1F;
+ case RAVE_SP_CMD_RMB_EEPROM:
+ return 0x20;
default:
return -EINVAL;
}
@@ -666,18 +661,44 @@ static const char *devm_rave_sp_version(struct device *dev,
version->letter[1]);
}
-static int rave_sp_get_status(struct rave_sp *sp)
+static int rave_sp_rdu1_get_status(struct rave_sp *sp,
+ struct rave_sp_status *status)
{
- struct device *dev = &sp->serdev->dev;
u8 cmd[] = {
[0] = RAVE_SP_CMD_STATUS,
[1] = 0
};
+
+ return rave_sp_exec(sp, cmd, sizeof(cmd), status, sizeof(*status));
+}
+
+static int rave_sp_emulated_get_status(struct rave_sp *sp,
+ struct rave_sp_status *status)
+{
+ u8 cmd[] = {
+ [0] = RAVE_SP_CMD_GET_FIRMWARE_VERSION,
+ [1] = 0,
+ };
+ int ret;
+
+ ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status->firmware_version,
+ sizeof(status->firmware_version));
+ if (ret)
+ return ret;
+
+ cmd[0] = RAVE_SP_CMD_GET_BOOTLOADER_VERSION;
+ return rave_sp_exec(sp, cmd, sizeof(cmd), &status->bootloader_version,
+ sizeof(status->bootloader_version));
+}
+
+static int rave_sp_get_status(struct rave_sp *sp)
+{
+ struct device *dev = &sp->serdev->dev;
struct rave_sp_status status;
const char *version;
int ret;
- ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
+ ret = sp->variant->cmd.get_status(sp, &status);
if (ret)
return ret;
@@ -707,9 +728,10 @@ static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
};
static const struct rave_sp_variant rave_sp_legacy = {
- .checksum = &rave_sp_checksum_8b2c,
+ .checksum = &rave_sp_checksum_ccitt,
.cmd = {
.translate = rave_sp_default_cmd_translate,
+ .get_status = rave_sp_emulated_get_status,
},
};
@@ -717,6 +739,7 @@ static const struct rave_sp_variant rave_sp_rdu1 = {
.checksum = &rave_sp_checksum_8b2c,
.cmd = {
.translate = rave_sp_rdu1_cmd_translate,
+ .get_status = rave_sp_rdu1_get_status,
},
};
@@ -724,6 +747,7 @@ static const struct rave_sp_variant rave_sp_rdu2 = {
.checksum = &rave_sp_checksum_ccitt,
.cmd = {
.translate = rave_sp_rdu2_cmd_translate,
+ .get_status = rave_sp_emulated_get_status,
},
};
@@ -776,6 +800,13 @@ static int rave_sp_probe(struct serdev_device *serdev)
return ret;
serdev_device_set_baudrate(serdev, baud);
+ serdev_device_set_flow_control(serdev, false);
+
+ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+ if (ret) {
+ dev_err(dev, "Failed to set parity\n");
+ return ret;
+ }
ret = rave_sp_get_status(sp);
if (ret) {
diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c
new file mode 100644
index 000000000000..75c8ec659547
--- /dev/null
+++ b/drivers/mfd/rohm-bd718x7.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Copyright (C) 2018 ROHM Semiconductors
+//
+// ROHM BD71837MWV PMIC driver
+//
+// Datasheet available from
+// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/rohm-bd718x7.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+/*
+ * gpio_keys.h requires definiton of bool. It is brought in
+ * by above includes. Keep this as last until gpio_keys.h gets fixed.
+ */
+#include <linux/gpio_keys.h>
+
+static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ };
+
+static struct gpio_keys_button button = {
+ .code = KEY_POWER,
+ .gpio = -1,
+ .type = EV_KEY,
+};
+
+static struct gpio_keys_platform_data bd718xx_powerkey_data = {
+ .buttons = &button,
+ .nbuttons = 1,
+ .name = "bd718xx-pwrkey",
+};
+
+static struct mfd_cell bd71837_mfd_cells[] = {
+ {
+ .name = "gpio-keys",
+ .platform_data = &bd718xx_powerkey_data,
+ .pdata_size = sizeof(bd718xx_powerkey_data),
+ },
+ { .name = "bd71837-clk", },
+ { .name = "bd71837-pmic", },
+};
+
+static const struct regmap_irq bd71837_irqs[] = {
+ REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK),
+ REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK),
+};
+
+static struct regmap_irq_chip bd71837_irq_chip = {
+ .name = "bd71837-irq",
+ .irqs = bd71837_irqs,
+ .num_irqs = ARRAY_SIZE(bd71837_irqs),
+ .num_regs = 1,
+ .irq_reg_stride = 1,
+ .status_base = BD71837_REG_IRQ,
+ .mask_base = BD71837_REG_MIRQ,
+ .ack_base = BD71837_REG_IRQ,
+ .init_ack_masked = true,
+ .mask_invert = false,
+};
+
+static const struct regmap_range pmic_status_range = {
+ .range_min = BD71837_REG_IRQ,
+ .range_max = BD71837_REG_POW_STATE,
+};
+
+static const struct regmap_access_table volatile_regs = {
+ .yes_ranges = &pmic_status_range,
+ .n_yes_ranges = 1,
+};
+
+static const struct regmap_config bd71837_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .volatile_table = &volatile_regs,
+ .max_register = BD71837_MAX_REGISTER - 1,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int bd71837_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct bd71837 *bd71837;
+ int ret, i;
+ unsigned int val;
+
+ bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
+
+ if (!bd71837)
+ return -ENOMEM;
+
+ bd71837->chip_irq = i2c->irq;
+
+ if (!bd71837->chip_irq) {
+ dev_err(&i2c->dev, "No IRQ configured\n");
+ return -EINVAL;
+ }
+
+ bd71837->dev = &i2c->dev;
+ dev_set_drvdata(&i2c->dev, bd71837);
+
+ bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
+ if (IS_ERR(bd71837->regmap)) {
+ dev_err(&i2c->dev, "regmap initialization failed\n");
+ return PTR_ERR(bd71837->regmap);
+ }
+
+ ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val);
+ if (ret) {
+ dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n");
+ return ret;
+ }
+ for (i = 0; i < ARRAY_SIZE(supported_revisions); i++)
+ if (supported_revisions[i] == val)
+ break;
+
+ if (i == ARRAY_SIZE(supported_revisions)) {
+ dev_err(&i2c->dev, "Unsupported chip revision\n");
+ return -ENODEV;
+ }
+
+ ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap,
+ bd71837->chip_irq, IRQF_ONESHOT, 0,
+ &bd71837_irq_chip, &bd71837->irq_data);
+ if (ret) {
+ dev_err(&i2c->dev, "Failed to add irq_chip\n");
+ return ret;
+ }
+
+ /* Configure short press to 10 milliseconds */
+ ret = regmap_update_bits(bd71837->regmap,
+ BD71837_REG_PWRONCONFIG0,
+ BD718XX_PWRBTN_PRESS_DURATION_MASK,
+ BD718XX_PWRBTN_SHORT_PRESS_10MS);
+ if (ret) {
+ dev_err(&i2c->dev,
+ "Failed to configure button short press timeout\n");
+ return ret;
+ }
+
+ /* Configure long press to 10 seconds */
+ ret = regmap_update_bits(bd71837->regmap,
+ BD71837_REG_PWRONCONFIG1,
+ BD718XX_PWRBTN_PRESS_DURATION_MASK,
+ BD718XX_PWRBTN_LONG_PRESS_10S);
+
+ if (ret) {
+ dev_err(&i2c->dev,
+ "Failed to configure button long press timeout\n");
+ return ret;
+ }
+
+ ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S);
+
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to get the IRQ\n");
+ return ret;
+ }
+
+ button.irq = ret;
+
+ ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
+ bd71837_mfd_cells,
+ ARRAY_SIZE(bd71837_mfd_cells), NULL, 0,
+ regmap_irq_get_domain(bd71837->irq_data));
+ if (ret)
+ dev_err(&i2c->dev, "Failed to create subdevices\n");
+
+ return ret;
+}
+
+static const struct of_device_id bd71837_of_match[] = {
+ { .compatible = "rohm,bd71837", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, bd71837_of_match);
+
+static struct i2c_driver bd71837_i2c_driver = {
+ .driver = {
+ .name = "rohm-bd718x7",
+ .of_match_table = bd71837_of_match,
+ },
+ .probe = bd71837_i2c_probe,
+};
+
+static int __init bd71837_i2c_init(void)
+{
+ return i2c_add_driver(&bd71837_i2c_driver);
+}
+
+/* Initialise early so consumer devices can complete system boot */
+subsys_initcall(bd71837_i2c_init);
+
+static void __exit bd71837_i2c_exit(void)
+{
+ i2c_del_driver(&bd71837_i2c_driver);
+}
+module_exit(bd71837_i2c_exit);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index ca6b80d08ffc..9613b4257302 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -146,6 +146,7 @@ static const struct of_device_id sec_dt_match[] = {
/* Sentinel */
},
};
+MODULE_DEVICE_TABLE(of, sec_dt_match);
#endif
static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 2a87b0d2f21f..a530972c5a7e 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -715,6 +715,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name,
smdev->pdev.name = name;
smdev->pdev.id = sm->pdev_id;
smdev->pdev.dev.parent = sm->dev;
+ smdev->pdev.dev.coherent_dma_mask = 0xffffffff;
if (res_count) {
smdev->pdev.resource = (struct resource *)(smdev+1);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 47012c0899cd..7a30546880a4 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -209,14 +209,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
* The TSC_ADC_SS controller design assumes the OCP clock is
* at least 6x faster than the ADC clock.
*/
- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+ clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get TSC fck\n");
err = PTR_ERR(clk);
goto err_disable_clk;
}
clock_rate = clk_get_rate(clk);
- clk_put(clk);
tscadc->clk_div = clock_rate / ADC_CLK;
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 5d5888ee2966..22bd6525e09c 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -302,6 +302,10 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
if (of_find_property(np, "wlf,ldoena-always-driven", NULL))
pdata->lineout2fb = true;
+ pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");
+
+ pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");
+
pdata->ldo[0].enable = of_get_named_gpio(np, "wlf,ldo1ena", 0);
if (pdata->ldo[0].enable < 0)
pdata->ldo[0].enable = 0;
@@ -513,14 +517,15 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
break;
default:
dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_enable;
}
ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
ret);
- return ret;
+ goto err_enable;
}
/* Explicitly put the device into reset in case regulators
@@ -531,7 +536,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
if (ret != 0) {
dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);
- return ret;
+ goto err_enable;
}
if (regmap_patch) {
@@ -540,7 +545,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
if (ret != 0) {
dev_err(wm8994->dev, "Failed to register patch: %d\n",
ret);
- goto err;
+ goto err_enable;
}
}
@@ -559,6 +564,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
if (pdata->spkmode_pu)
pulls |= WM8994_SPKMODE_PU;
+ if (pdata->csnaddr_pd)
+ pulls |= WM8994_CSNADDR_PD;
/* Disable unneeded pulls */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index f5cc517d1131..7e50e1d6f58c 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -478,6 +478,23 @@ static void at24_properties_to_pdata(struct device *dev,
if (device_property_present(dev, "no-read-rollover"))
chip->flags |= AT24_FLAG_NO_RDROL;
+ err = device_property_read_u32(dev, "address-width", &val);
+ if (!err) {
+ switch (val) {
+ case 8:
+ if (chip->flags & AT24_FLAG_ADDR16)
+ dev_warn(dev, "Override address width to be 8, while default is 16\n");
+ chip->flags &= ~AT24_FLAG_ADDR16;
+ break;
+ case 16:
+ chip->flags |= AT24_FLAG_ADDR16;
+ break;
+ default:
+ dev_warn(dev, "Bad \"address-width\" property: %u\n",
+ val);
+ }
+ }
+
err = device_property_read_u32(dev, "size", &val);
if (!err)
chip->byte_len = val;
diff --git a/drivers/misc/mic/scif/scif_dma.c b/drivers/misc/mic/scif/scif_dma.c
index 63d6246d6dff..6369aeaa7056 100644
--- a/drivers/misc/mic/scif/scif_dma.c
+++ b/drivers/misc/mic/scif/scif_dma.c
@@ -200,15 +200,18 @@ static void scif_mmu_notifier_release(struct mmu_notifier *mn,
schedule_work(&scif_info.misc_work);
}
-static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
unsigned long start,
- unsigned long end)
+ unsigned long end,
+ bool blockable)
{
struct scif_mmu_notif *mmn;
mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
scif_rma_destroy_tcw(mmn, start, end - start);
+
+ return 0;
}
static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
diff --git a/drivers/misc/sgi-gru/grutlbpurge.c b/drivers/misc/sgi-gru/grutlbpurge.c
index a3454eb56fbf..be28f05bfafa 100644
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -219,9 +219,10 @@ void gru_flush_all_tlb(struct gru_state *gru)
/*
* MMUOPS notifier callout functions
*/
-static void gru_invalidate_range_start(struct mmu_notifier *mn,
+static int gru_invalidate_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
- unsigned long start, unsigned long end)
+ unsigned long start, unsigned long end,
+ bool blockable)
{
struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct,
ms_notifier);
@@ -231,6 +232,8 @@ static void gru_invalidate_range_start(struct mmu_notifier *mn,
gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx, act %d\n", gms,
start, end, atomic_read(&gms->ms_range_active));
gru_flush_tlb_range(gms, start, end - start);
+
+ return 0;
}
static void gru_invalidate_range_end(struct mmu_notifier *mn,
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 05157442a980..b1b53f6c452f 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -74,7 +74,6 @@ static const char version[] =
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
-#include <linux/dma/pxa-dma.h>
#include <asm/io.h>
@@ -1795,7 +1794,6 @@ static int smc911x_probe(struct net_device *dev)
#ifdef SMC_USE_DMA
struct dma_slave_config config;
dma_cap_mask_t mask;
- struct pxad_param param;
#endif
DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__);
@@ -1971,15 +1969,8 @@ static int smc911x_probe(struct net_device *dev)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- param.prio = PXAD_PRIO_LOWEST;
- param.drcmr = -1UL;
-
- lp->rxdma =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev, "rx");
- lp->txdma =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev, "tx");
+ lp->rxdma = dma_request_channel(mask, NULL, NULL);
+ lp->txdma = dma_request_channel(mask, NULL, NULL);
lp->rxdma_active = 0;
lp->txdma_active = 0;
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 080428762858..b944828f9ea3 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2019,17 +2019,10 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
# endif
if (lp->cfg.flags & SMC91X_USE_DMA) {
dma_cap_mask_t mask;
- struct pxad_param param;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- param.prio = PXAD_PRIO_LOWEST;
- param.drcmr = -1UL;
-
- lp->dma_chan =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev,
- "data");
+ lp->dma_chan = dma_request_channel(mask, NULL, NULL);
}
#endif
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index b337ee97e0c0..a27352229fc2 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -301,7 +301,6 @@ struct smc_local {
* as RX which can overrun memory and lose packets.
*/
#include <linux/dma-mapping.h>
-#include <linux/dma/pxa-dma.h>
#ifdef SMC_insl
#undef SMC_insl
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2bbefe828670..ebd07ad82431 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -3217,7 +3217,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
goto out;
if (on) {
- __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
+ __f_setown(file, task_pid(current), PIDTYPE_TGID, 0);
tfile->flags |= TUN_FASYNC;
} else
tfile->flags &= ~TUN_FASYNC;
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 738e3546abb1..c2ab57705043 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -615,13 +615,11 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
/*
* In some cases (eg. Samsung 305V4A) leaving a bridge in suspend over
* system-wide suspend/resume confuses the platform firmware, so avoid
- * doing that, unless the bridge has a driver that should take care of
- * the PM handling. According to Section 16.1.6 of ACPI 6.2, endpoint
+ * doing that. According to Section 16.1.6 of ACPI 6.2, endpoint
* devices are expected to be in D3 before invoking the S3 entry path
* from the firmware, so they should not be affected by this issue.
*/
- if (pci_is_bridge(dev) && !dev->driver &&
- acpi_target_system_state() != ACPI_STATE_S0)
+ if (pci_is_bridge(dev) && acpi_target_system_state() != ACPI_STATE_S0)
return true;
if (!adev || !acpi_device_power_manageable(adev))
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 46f58a9771d7..ef7143a274e0 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -66,9 +66,15 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device ||
f->device == (u16) PCI_ANY_ID)) {
- calltime = fixup_debug_start(dev, f->hook);
- f->hook(dev);
- fixup_debug_report(dev, calltime, f->hook);
+ void (*hook)(struct pci_dev *dev);
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+ hook = offset_to_ptr(&f->hook_offset);
+#else
+ hook = f->hook;
+#endif
+ calltime = fixup_debug_start(dev, hook);
+ hook(dev);
+ fixup_debug_report(dev, calltime, hook);
}
}
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 8d4b7e999f02..e86752be1f19 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -361,6 +361,7 @@ source "drivers/pinctrl/vt8500/Kconfig"
source "drivers/pinctrl/mediatek/Kconfig"
source "drivers/pinctrl/zte/Kconfig"
source "drivers/pinctrl/meson/Kconfig"
+source "drivers/pinctrl/cirrus/Kconfig"
config PINCTRL_XWAY
bool
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index de40863e7297..46ef9bd52096 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -64,3 +64,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
obj-y += mediatek/
obj-$(CONFIG_PINCTRL_ZX) += zte/
+obj-y += cirrus/
diff --git a/drivers/pinctrl/cirrus/Kconfig b/drivers/pinctrl/cirrus/Kconfig
new file mode 100644
index 000000000000..27013e5949bc
--- /dev/null
+++ b/drivers/pinctrl/cirrus/Kconfig
@@ -0,0 +1,14 @@
+# This is all selected by the Madera MFD driver Kconfig options
+config PINCTRL_MADERA
+ tristate
+ select PINMUX
+ select GENERIC_PINCONF
+
+config PINCTRL_CS47L35
+ bool
+
+config PINCTRL_CS47L85
+ bool
+
+config PINCTRL_CS47L90
+ bool
diff --git a/drivers/pinctrl/cirrus/Makefile b/drivers/pinctrl/cirrus/Makefile
new file mode 100644
index 000000000000..6e4938cde9e3
--- /dev/null
+++ b/drivers/pinctrl/cirrus/Makefile
@@ -0,0 +1,13 @@
+# Cirrus Logic pinctrl drivers
+pinctrl-madera-objs := pinctrl-madera-core.o
+ifeq ($(CONFIG_PINCTRL_CS47L35),y)
+pinctrl-madera-objs += pinctrl-cs47l35.o
+endif
+ifeq ($(CONFIG_PINCTRL_CS47L85),y)
+pinctrl-madera-objs += pinctrl-cs47l85.o
+endif
+ifeq ($(CONFIG_PINCTRL_CS47L90),y)
+pinctrl-madera-objs += pinctrl-cs47l90.o
+endif
+
+obj-$(CONFIG_PINCTRL_MADERA) += pinctrl-madera.o
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l35.c b/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
new file mode 100644
index 000000000000..06b59160783d
--- /dev/null
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L35
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l35_aif3_pins[] = { 0, 1, 2, 3 };
+static const unsigned int cs47l35_spk_pins[] = { 4, 5 };
+static const unsigned int cs47l35_aif1_pins[] = { 7, 8, 9, 10 };
+static const unsigned int cs47l35_aif2_pins[] = { 11, 12, 13, 14 };
+static const unsigned int cs47l35_mif1_pins[] = { 6, 15 };
+
+static const struct madera_pin_groups cs47l35_pin_groups[] = {
+ { "aif1", cs47l35_aif1_pins, ARRAY_SIZE(cs47l35_aif1_pins) },
+ { "aif2", cs47l35_aif2_pins, ARRAY_SIZE(cs47l35_aif2_pins) },
+ { "aif3", cs47l35_aif3_pins, ARRAY_SIZE(cs47l35_aif3_pins) },
+ { "mif1", cs47l35_mif1_pins, ARRAY_SIZE(cs47l35_mif1_pins) },
+ { "pdmspk1", cs47l35_spk_pins, ARRAY_SIZE(cs47l35_spk_pins) },
+};
+
+const struct madera_pin_chip cs47l35_pin_chip = {
+ .n_pins = CS47L35_NUM_GPIOS,
+ .pin_groups = cs47l35_pin_groups,
+ .n_pin_groups = ARRAY_SIZE(cs47l35_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l85.c b/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
new file mode 100644
index 000000000000..0a322e2a0fde
--- /dev/null
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L85
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l85_mif1_pins[] = { 8, 9 };
+static const unsigned int cs47l85_mif2_pins[] = { 10, 11 };
+static const unsigned int cs47l85_mif3_pins[] = { 12, 13 };
+static const unsigned int cs47l85_aif1_pins[] = { 14, 15, 16, 17 };
+static const unsigned int cs47l85_aif2_pins[] = { 18, 19, 20, 21 };
+static const unsigned int cs47l85_aif3_pins[] = { 22, 23, 24, 25 };
+static const unsigned int cs47l85_aif4_pins[] = { 26, 27, 28, 29 };
+static const unsigned int cs47l85_dmic4_pins[] = { 30, 31 };
+static const unsigned int cs47l85_dmic5_pins[] = { 32, 33 };
+static const unsigned int cs47l85_dmic6_pins[] = { 34, 35 };
+static const unsigned int cs47l85_spk1_pins[] = { 36, 38 };
+static const unsigned int cs47l85_spk2_pins[] = { 37, 39 };
+
+static const struct madera_pin_groups cs47l85_pin_groups[] = {
+ { "aif1", cs47l85_aif1_pins, ARRAY_SIZE(cs47l85_aif1_pins) },
+ { "aif2", cs47l85_aif2_pins, ARRAY_SIZE(cs47l85_aif2_pins) },
+ { "aif3", cs47l85_aif3_pins, ARRAY_SIZE(cs47l85_aif3_pins) },
+ { "aif4", cs47l85_aif4_pins, ARRAY_SIZE(cs47l85_aif4_pins) },
+ { "mif1", cs47l85_mif1_pins, ARRAY_SIZE(cs47l85_mif1_pins) },
+ { "mif2", cs47l85_mif2_pins, ARRAY_SIZE(cs47l85_mif2_pins) },
+ { "mif3", cs47l85_mif3_pins, ARRAY_SIZE(cs47l85_mif3_pins) },
+ { "dmic4", cs47l85_dmic4_pins, ARRAY_SIZE(cs47l85_dmic4_pins) },
+ { "dmic5", cs47l85_dmic5_pins, ARRAY_SIZE(cs47l85_dmic5_pins) },
+ { "dmic6", cs47l85_dmic6_pins, ARRAY_SIZE(cs47l85_dmic6_pins) },
+ { "pdmspk1", cs47l85_spk1_pins, ARRAY_SIZE(cs47l85_spk1_pins) },
+ { "pdmspk2", cs47l85_spk2_pins, ARRAY_SIZE(cs47l85_spk2_pins) },
+};
+
+const struct madera_pin_chip cs47l85_pin_chip = {
+ .n_pins = CS47L85_NUM_GPIOS,
+ .pin_groups = cs47l85_pin_groups,
+ .n_pin_groups = ARRAY_SIZE(cs47l85_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l90.c b/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
new file mode 100644
index 000000000000..fc38f579f492
--- /dev/null
+++ b/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L90
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l90_mif1_pins[] = { 8, 9 };
+static const unsigned int cs47l90_mif2_pins[] = { 10, 11 };
+static const unsigned int cs47l90_mif3_pins[] = { 12, 13 };
+static const unsigned int cs47l90_aif1_pins[] = { 14, 15, 16, 17 };
+static const unsigned int cs47l90_aif2_pins[] = { 18, 19, 20, 21 };
+static const unsigned int cs47l90_aif3_pins[] = { 22, 23, 24, 25 };
+static const unsigned int cs47l90_aif4_pins[] = { 26, 27, 28, 29 };
+static const unsigned int cs47l90_dmic4_pins[] = { 30, 31 };
+static const unsigned int cs47l90_dmic5_pins[] = { 32, 33 };
+static const unsigned int cs47l90_dmic3_pins[] = { 34, 35 };
+static const unsigned int cs47l90_spk1_pins[] = { 36, 37 };
+
+static const struct madera_pin_groups cs47l90_pin_groups[] = {
+ { "aif1", cs47l90_aif1_pins, ARRAY_SIZE(cs47l90_aif1_pins) },
+ { "aif2", cs47l90_aif2_pins, ARRAY_SIZE(cs47l90_aif2_pins) },
+ { "aif3", cs47l90_aif3_pins, ARRAY_SIZE(cs47l90_aif3_pins) },
+ { "aif4", cs47l90_aif4_pins, ARRAY_SIZE(cs47l90_aif4_pins) },
+ { "mif1", cs47l90_mif1_pins, ARRAY_SIZE(cs47l90_mif1_pins) },
+ { "mif2", cs47l90_mif2_pins, ARRAY_SIZE(cs47l90_mif2_pins) },
+ { "mif3", cs47l90_mif3_pins, ARRAY_SIZE(cs47l90_mif3_pins) },
+ { "dmic3", cs47l90_dmic3_pins, ARRAY_SIZE(cs47l90_dmic3_pins) },
+ { "dmic4", cs47l90_dmic4_pins, ARRAY_SIZE(cs47l90_dmic4_pins) },
+ { "dmic5", cs47l90_dmic5_pins, ARRAY_SIZE(cs47l90_dmic5_pins) },
+ { "pdmspk1", cs47l90_spk1_pins, ARRAY_SIZE(cs47l90_spk1_pins) },
+};
+
+const struct madera_pin_chip cs47l90_pin_chip = {
+ .n_pins = CS47L90_NUM_GPIOS,
+ .pin_groups = cs47l90_pin_groups,
+ .n_pin_groups = ARRAY_SIZE(cs47l90_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera-core.c b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
new file mode 100644
index 000000000000..ece41fb2848f
--- /dev/null
+++ b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
@@ -0,0 +1,1076 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2016-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-madera.h"
+
+/*
+ * Use pin GPIO names for consistency
+ * NOTE: IDs are zero-indexed for coding convenience
+ */
+static const struct pinctrl_pin_desc madera_pins[] = {
+ PINCTRL_PIN(0, "gpio1"),
+ PINCTRL_PIN(1, "gpio2"),
+ PINCTRL_PIN(2, "gpio3"),
+ PINCTRL_PIN(3, "gpio4"),
+ PINCTRL_PIN(4, "gpio5"),
+ PINCTRL_PIN(5, "gpio6"),
+ PINCTRL_PIN(6, "gpio7"),
+ PINCTRL_PIN(7, "gpio8"),
+ PINCTRL_PIN(8, "gpio9"),
+ PINCTRL_PIN(9, "gpio10"),
+ PINCTRL_PIN(10, "gpio11"),
+ PINCTRL_PIN(11, "gpio12"),
+ PINCTRL_PIN(12, "gpio13"),
+ PINCTRL_PIN(13, "gpio14"),
+ PINCTRL_PIN(14, "gpio15"),
+ PINCTRL_PIN(15, "gpio16"),
+ PINCTRL_PIN(16, "gpio17"),
+ PINCTRL_PIN(17, "gpio18"),
+ PINCTRL_PIN(18, "gpio19"),
+ PINCTRL_PIN(19, "gpio20"),
+ PINCTRL_PIN(20, "gpio21"),
+ PINCTRL_PIN(21, "gpio22"),
+ PINCTRL_PIN(22, "gpio23"),
+ PINCTRL_PIN(23, "gpio24"),
+ PINCTRL_PIN(24, "gpio25"),
+ PINCTRL_PIN(25, "gpio26"),
+ PINCTRL_PIN(26, "gpio27"),
+ PINCTRL_PIN(27, "gpio28"),
+ PINCTRL_PIN(28, "gpio29"),
+ PINCTRL_PIN(29, "gpio30"),
+ PINCTRL_PIN(30, "gpio31"),
+ PINCTRL_PIN(31, "gpio32"),
+ PINCTRL_PIN(32, "gpio33"),
+ PINCTRL_PIN(33, "gpio34"),
+ PINCTRL_PIN(34, "gpio35"),
+ PINCTRL_PIN(35, "gpio36"),
+ PINCTRL_PIN(36, "gpio37"),
+ PINCTRL_PIN(37, "gpio38"),
+ PINCTRL_PIN(38, "gpio39"),
+ PINCTRL_PIN(39, "gpio40"),
+};
+
+/*
+ * All single-pin functions can be mapped to any GPIO, however pinmux applies
+ * functions to pin groups and only those groups declared as supporting that
+ * function. To make this work we must put each pin in its own dummy group so
+ * that the functions can be described as applying to all pins.
+ * Since these do not correspond to anything in the actual hardware - they are
+ * merely an adaptation to pinctrl's view of the world - we use the same name
+ * as the pin to avoid confusion when comparing with datasheet instructions
+ */
+static const char * const madera_pin_single_group_names[] = {
+ "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40",
+};
+
+/* set of pin numbers for single-pin groups, zero-indexed */
+static const unsigned int madera_pin_single_group_pins[] = {
+ 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39,
+};
+
+static const char * const madera_aif1_group_names[] = { "aif1" };
+static const char * const madera_aif2_group_names[] = { "aif2" };
+static const char * const madera_aif3_group_names[] = { "aif3" };
+static const char * const madera_aif4_group_names[] = { "aif4" };
+static const char * const madera_mif1_group_names[] = { "mif1" };
+static const char * const madera_mif2_group_names[] = { "mif2" };
+static const char * const madera_mif3_group_names[] = { "mif3" };
+static const char * const madera_dmic3_group_names[] = { "dmic3" };
+static const char * const madera_dmic4_group_names[] = { "dmic4" };
+static const char * const madera_dmic5_group_names[] = { "dmic5" };
+static const char * const madera_dmic6_group_names[] = { "dmic6" };
+static const char * const madera_spk1_group_names[] = { "pdmspk1" };
+static const char * const madera_spk2_group_names[] = { "pdmspk2" };
+
+/*
+ * alt-functions always apply to a single pin group, other functions always
+ * apply to all pins
+ */
+static const struct {
+ const char *name;
+ const char * const *group_names;
+ u32 func;
+} madera_mux_funcs[] = {
+ {
+ .name = "aif1",
+ .group_names = madera_aif1_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "aif2",
+ .group_names = madera_aif2_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "aif3",
+ .group_names = madera_aif3_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "aif4",
+ .group_names = madera_aif4_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "mif1",
+ .group_names = madera_mif1_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "mif2",
+ .group_names = madera_mif2_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "mif3",
+ .group_names = madera_mif3_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "dmic3",
+ .group_names = madera_dmic3_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "dmic4",
+ .group_names = madera_dmic4_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "dmic5",
+ .group_names = madera_dmic5_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "dmic6",
+ .group_names = madera_dmic6_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "pdmspk1",
+ .group_names = madera_spk1_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "pdmspk2",
+ .group_names = madera_spk2_group_names,
+ .func = 0x000
+ },
+ {
+ .name = "io",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x001
+ },
+ {
+ .name = "dsp-gpio",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x002
+ },
+ {
+ .name = "irq1",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x003
+ },
+ {
+ .name = "irq2",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x004
+ },
+ {
+ .name = "fll1-clk",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x010
+ },
+ {
+ .name = "fll2-clk",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x011
+ },
+ {
+ .name = "fll3-clk",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x012
+ },
+ {
+ .name = "fllao-clk",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x013
+ },
+ {
+ .name = "fll1-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x018
+ },
+ {
+ .name = "fll2-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x019
+ },
+ {
+ .name = "fll3-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x01a
+ },
+ {
+ .name = "fllao-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x01b
+ },
+ {
+ .name = "opclk",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x040
+ },
+ {
+ .name = "opclk-async",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x041
+ },
+ {
+ .name = "pwm1",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x048
+ },
+ {
+ .name = "pwm2",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x049
+ },
+ {
+ .name = "spdif",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x04c
+ },
+ {
+ .name = "asrc1-in1-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x088
+ },
+ {
+ .name = "asrc1-in2-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x089
+ },
+ {
+ .name = "asrc2-in1-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x08a
+ },
+ {
+ .name = "asrc2-in2-lock",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x08b
+ },
+ {
+ .name = "spkl-short-circuit",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x0b6
+ },
+ {
+ .name = "spkr-short-circuit",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x0b7
+ },
+ {
+ .name = "spk-shutdown",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x0e0
+ },
+ {
+ .name = "spk-overheat-shutdown",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x0e1
+ },
+ {
+ .name = "spk-overheat-warn",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x0e2
+ },
+ {
+ .name = "timer1-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x140
+ },
+ {
+ .name = "timer2-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x141
+ },
+ {
+ .name = "timer3-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x142
+ },
+ {
+ .name = "timer4-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x143
+ },
+ {
+ .name = "timer5-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x144
+ },
+ {
+ .name = "timer6-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x145
+ },
+ {
+ .name = "timer7-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x146
+ },
+ {
+ .name = "timer8-sts",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x147
+ },
+ {
+ .name = "log1-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x150
+ },
+ {
+ .name = "log2-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x151
+ },
+ {
+ .name = "log3-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x152
+ },
+ {
+ .name = "log4-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x153
+ },
+ {
+ .name = "log5-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x154
+ },
+ {
+ .name = "log6-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x155
+ },
+ {
+ .name = "log7-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x156
+ },
+ {
+ .name = "log8-fifo-ne",
+ .group_names = madera_pin_single_group_names,
+ .func = 0x157
+ },
+};
+
+static u16 madera_pin_make_drv_str(struct madera_pin_private *priv,
+ unsigned int milliamps)
+{
+ switch (milliamps) {
+ case 4:
+ return 0;
+ case 8:
+ return 2 << MADERA_GP1_DRV_STR_SHIFT;
+ default:
+ break;
+ }
+
+ dev_warn(priv->dev, "%u mA not a valid drive strength", milliamps);
+
+ return 0;
+}
+
+static unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv,
+ u16 regval)
+{
+ regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT;
+
+ switch (regval) {
+ case 0:
+ return 4;
+ case 2:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+static int madera_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+ /* Number of alt function groups plus number of single-pin groups */
+ return priv->chip->n_pin_groups + priv->chip->n_pins;
+}
+
+static const char *madera_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector < priv->chip->n_pin_groups)
+ return priv->chip->pin_groups[selector].name;
+
+ selector -= priv->chip->n_pin_groups;
+ return madera_pin_single_group_names[selector];
+}
+
+static int madera_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const unsigned int **pins,
+ unsigned int *num_pins)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+ if (selector < priv->chip->n_pin_groups) {
+ *pins = priv->chip->pin_groups[selector].pins;
+ *num_pins = priv->chip->pin_groups[selector].n_pins;
+ } else {
+ /* return the dummy group for a single pin */
+ selector -= priv->chip->n_pin_groups;
+ *pins = &madera_pin_single_group_pins[selector];
+ *num_pins = 1;
+ }
+ return 0;
+}
+
+static void madera_pin_dbg_show_fn(struct madera_pin_private *priv,
+ struct seq_file *s,
+ unsigned int pin, unsigned int fn)
+{
+ const struct madera_pin_chip *chip = priv->chip;
+ int i, g_pin;
+
+ if (fn != 0) {
+ for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) {
+ if (madera_mux_funcs[i].func == fn) {
+ seq_printf(s, " FN=%s",
+ madera_mux_funcs[i].name);
+ return;
+ }
+ }
+ return; /* ignore unknown function values */
+ }
+
+ /* alt function */
+ for (i = 0; i < chip->n_pin_groups; ++i) {
+ for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) {
+ if (chip->pin_groups[i].pins[g_pin] == pin) {
+ seq_printf(s, " FN=%s",
+ chip->pin_groups[i].name);
+ return;
+ }
+ }
+ }
+}
+
+static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned int pin)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int conf[2];
+ unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+ unsigned int fn;
+ int ret;
+
+ ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
+ if (ret)
+ return;
+
+ ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
+ if (ret)
+ return;
+
+ seq_printf(s, "%04x:%04x", conf[0], conf[1]);
+
+ fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT;
+ madera_pin_dbg_show_fn(priv, s, pin, fn);
+
+ /* State of direction bit is only relevant if function==1 */
+ if (fn == 1) {
+ if (conf[1] & MADERA_GP1_DIR_MASK)
+ seq_puts(s, " IN");
+ else
+ seq_puts(s, " OUT");
+ }
+
+ if (conf[1] & MADERA_GP1_PU_MASK)
+ seq_puts(s, " PU");
+
+ if (conf[1] & MADERA_GP1_PD_MASK)
+ seq_puts(s, " PD");
+
+ if (conf[0] & MADERA_GP1_DB_MASK)
+ seq_puts(s, " DB");
+
+ if (conf[0] & MADERA_GP1_OP_CFG_MASK)
+ seq_puts(s, " OD");
+ else
+ seq_puts(s, " CMOS");
+
+ seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));
+
+ if (conf[0] & MADERA_GP1_IP_CFG_MASK)
+ seq_puts(s, "SCHMITT");
+}
+
+
+static const struct pinctrl_ops madera_pin_group_ops = {
+ .get_groups_count = madera_get_groups_count,
+ .get_group_name = madera_get_group_name,
+ .get_group_pins = madera_get_group_pins,
+#if IS_ENABLED(CONFIG_OF)
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinctrl_utils_free_map,
+#endif
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+ .pin_dbg_show = madera_pin_dbg_show,
+#endif
+};
+
+static int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ return ARRAY_SIZE(madera_mux_funcs);
+}
+
+static const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned int selector)
+{
+ return madera_mux_funcs[selector].name;
+}
+
+static int madera_mux_get_groups(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ const char * const **groups,
+ unsigned int * const num_groups)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = madera_mux_funcs[selector].group_names;
+
+ if (madera_mux_funcs[selector].func == 0) {
+ /* alt func always maps to a single group */
+ *num_groups = 1;
+ } else {
+ /* other funcs map to all available gpio pins */
+ *num_groups = priv->chip->n_pins;
+ }
+
+ return 0;
+}
+
+static int madera_mux_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned int group)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ struct madera *madera = priv->madera;
+ const struct madera_pin_groups *pin_group = priv->chip->pin_groups;
+ unsigned int n_chip_groups = priv->chip->n_pin_groups;
+ const char *func_name = madera_mux_funcs[selector].name;
+ unsigned int reg;
+ int i, ret;
+
+ dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",
+ __func__, selector, func_name, group,
+ madera_get_group_name(pctldev, group));
+
+ if (madera_mux_funcs[selector].func == 0) {
+ /* alt func pin assignments are codec-specific */
+ for (i = 0; i < n_chip_groups; ++i) {
+ if (strcmp(func_name, pin_group->name) == 0)
+ break;
+
+ ++pin_group;
+ }
+
+ if (i == n_chip_groups)
+ return -EINVAL;
+
+ for (i = 0; i < pin_group->n_pins; ++i) {
+ reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]);
+
+ dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n",
+ __func__, reg);
+
+ ret = regmap_update_bits(madera->regmap, reg,
+ MADERA_GP1_FN_MASK, 0);
+ if (ret)
+ break;
+
+ }
+ } else {
+ /*
+ * for other funcs the group will be the gpio number and will
+ * be offset by the number of chip-specific functions at the
+ * start of the group list
+ */
+ group -= n_chip_groups;
+ reg = MADERA_GPIO1_CTRL_1 + (2 * group);
+
+ dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n",
+ __func__, reg, madera_mux_funcs[selector].func);
+
+ ret = regmap_update_bits(madera->regmap,
+ reg,
+ MADERA_GP1_FN_MASK,
+ madera_mux_funcs[selector].func);
+ }
+
+ if (ret)
+ dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+ return ret;
+}
+
+static int madera_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset,
+ bool input)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ struct madera *madera = priv->madera;
+ unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset);
+ unsigned int val;
+ int ret;
+
+ if (input)
+ val = MADERA_GP1_DIR;
+ else
+ val = 0;
+
+ ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_DIR_MASK, val);
+ if (ret)
+ dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+ return ret;
+}
+
+static int madera_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ struct madera *madera = priv->madera;
+ unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
+ int ret;
+
+ /* put the pin into GPIO mode */
+ ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
+ if (ret)
+ dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+ return ret;
+}
+
+static void madera_gpio_disable_free(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ struct madera *madera = priv->madera;
+ unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
+ int ret;
+
+ /* disable GPIO by setting to GPIO IN */
+ madera_gpio_set_direction(pctldev, range, offset, true);
+
+ ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
+ if (ret)
+ dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+}
+
+static const struct pinmux_ops madera_pin_mux_ops = {
+ .get_functions_count = madera_mux_get_funcs_count,
+ .get_function_name = madera_mux_get_func_name,
+ .get_function_groups = madera_mux_get_groups,
+ .set_mux = madera_mux_set_mux,
+ .gpio_request_enable = madera_gpio_request_enable,
+ .gpio_disable_free = madera_gpio_disable_free,
+ .gpio_set_direction = madera_gpio_set_direction,
+ .strict = true, /* GPIO and other functions are exclusive */
+};
+
+static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ unsigned int param = pinconf_to_config_param(*config);
+ unsigned int result = 0;
+ unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+ unsigned int conf[2];
+ int ret;
+
+ ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
+ if (!ret)
+ ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
+
+ if (ret) {
+ dev_err(priv->dev, "Failed to read GP%d conf (%d)\n",
+ pin + 1, ret);
+ return ret;
+ }
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD))
+ result = 1;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ if (!conf[1])
+ result = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ if (conf[1] == MADERA_GP1_PD_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ if (conf[1] == MADERA_GP1_PU_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ if (conf[0] & MADERA_GP1_OP_CFG_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ if (!(conf[0] & MADERA_GP1_OP_CFG_MASK))
+ result = 1;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ result = madera_pin_unmake_drv_str(priv, conf[1]);
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ if (conf[0] & MADERA_GP1_DB_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ if (conf[0] & MADERA_GP1_DIR_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT:
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (conf[0] & MADERA_GP1_IP_CFG_MASK)
+ result = 1;
+ break;
+ case PIN_CONFIG_OUTPUT:
+ if ((conf[1] & MADERA_GP1_DIR_MASK) &&
+ (conf[0] & MADERA_GP1_LVL_MASK))
+ result = 1;
+ break;
+ default:
+ break;
+ }
+
+ *config = pinconf_to_config_packed(param, result);
+
+ return 0;
+}
+
+static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ u16 conf[2] = {0, 0};
+ u16 mask[2] = {0, 0};
+ unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+ unsigned int val;
+ int ret;
+
+ while (num_configs) {
+ dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);
+
+ switch (pinconf_to_config_param(*configs)) {
+ case PIN_CONFIG_BIAS_BUS_HOLD:
+ mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;
+ break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ conf[1] |= MADERA_GP1_PD;
+ conf[1] &= ~MADERA_GP1_PU;
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+ conf[1] |= MADERA_GP1_PU;
+ conf[1] &= ~MADERA_GP1_PD;
+ break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ mask[0] |= MADERA_GP1_OP_CFG_MASK;
+ conf[0] |= MADERA_GP1_OP_CFG;
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ mask[0] |= MADERA_GP1_OP_CFG_MASK;
+ conf[0] &= ~MADERA_GP1_OP_CFG;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ val = pinconf_to_config_argument(*configs);
+ mask[1] |= MADERA_GP1_DRV_STR_MASK;
+ conf[1] &= ~MADERA_GP1_DRV_STR_MASK;
+ conf[1] |= madera_pin_make_drv_str(priv, val);
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ mask[0] |= MADERA_GP1_DB_MASK;
+
+ /*
+ * we can't configure debounce time per-pin so value
+ * is just a flag
+ */
+ val = pinconf_to_config_argument(*configs);
+ if (val)
+ conf[0] |= MADERA_GP1_DB;
+ else
+ conf[0] &= ~MADERA_GP1_DB;
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ val = pinconf_to_config_argument(*configs);
+ mask[1] |= MADERA_GP1_DIR_MASK;
+ if (val)
+ conf[1] |= MADERA_GP1_DIR;
+ else
+ conf[1] &= ~MADERA_GP1_DIR;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT:
+ val = pinconf_to_config_argument(*configs);
+ mask[0] |= MADERA_GP1_IP_CFG;
+ if (val)
+ conf[0] |= MADERA_GP1_IP_CFG;
+ else
+ conf[0] &= ~MADERA_GP1_IP_CFG;
+
+ mask[1] |= MADERA_GP1_DIR_MASK;
+ conf[1] |= MADERA_GP1_DIR;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ mask[0] |= MADERA_GP1_IP_CFG;
+ conf[0] |= MADERA_GP1_IP_CFG;
+ mask[1] |= MADERA_GP1_DIR_MASK;
+ conf[1] |= MADERA_GP1_DIR;
+ break;
+ case PIN_CONFIG_OUTPUT:
+ val = pinconf_to_config_argument(*configs);
+ mask[0] |= MADERA_GP1_LVL_MASK;
+ if (val)
+ conf[0] |= MADERA_GP1_LVL;
+ else
+ conf[0] &= ~MADERA_GP1_LVL;
+
+ mask[1] |= MADERA_GP1_DIR_MASK;
+ conf[1] &= ~MADERA_GP1_DIR;
+ break;
+ default:
+ break;
+ }
+
+ ++configs;
+ --num_configs;
+ }
+
+ dev_dbg(priv->dev,
+ "%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",
+ __func__, pin + 1, reg, conf[0], reg + 1, conf[1]);
+
+ ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);
+ if (ret)
+ goto err;
+
+ ++reg;
+ ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ dev_err(priv->dev,
+ "Failed to write GPIO%d conf (%d) reg 0x%x\n",
+ pin + 1, ret, reg);
+
+ return ret;
+}
+
+static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+ const struct madera_pin_groups *pin_group;
+ unsigned int n_groups = priv->chip->n_pin_groups;
+ int i, ret;
+
+ dev_dbg(priv->dev, "%s setting group %s\n", __func__,
+ madera_get_group_name(pctldev, selector));
+
+ if (selector >= n_groups) {
+ /* group is a single pin, convert to pin number and set */
+ return madera_pin_conf_set(pctldev,
+ selector - n_groups,
+ configs,
+ num_configs);
+ } else {
+ pin_group = &priv->chip->pin_groups[selector];
+
+ for (i = 0; i < pin_group->n_pins; ++i) {
+ ret = madera_pin_conf_set(pctldev,
+ pin_group->pins[i],
+ configs,
+ num_configs);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops madera_pin_conf_ops = {
+ .pin_config_get = madera_pin_conf_get,
+ .pin_config_set = madera_pin_conf_set,
+ .pin_config_group_set = madera_pin_conf_group_set,
+
+};
+
+static struct pinctrl_desc madera_pin_desc = {
+ .name = "madera-pinctrl",
+ .pins = madera_pins,
+ .pctlops = &madera_pin_group_ops,
+ .pmxops = &madera_pin_mux_ops,
+ .confops = &madera_pin_conf_ops,
+ .owner = THIS_MODULE,
+};
+
+static int madera_pin_probe(struct platform_device *pdev)
+{
+ struct madera *madera = dev_get_drvdata(pdev->dev.parent);
+ const struct madera_pdata *pdata = dev_get_platdata(madera->dev);
+ struct madera_pin_private *priv;
+ int ret;
+
+ BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) !=
+ ARRAY_SIZE(madera_pin_single_group_pins));
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = &pdev->dev;
+ priv->madera = madera;
+ pdev->dev.of_node = madera->dev->of_node;
+
+ switch (madera->type) {
+ case CS47L35:
+ if (IS_ENABLED(CONFIG_PINCTRL_CS47L35))
+ priv->chip = &cs47l35_pin_chip;
+ break;
+ case CS47L85:
+ case WM1840:
+ if (IS_ENABLED(CONFIG_PINCTRL_CS47L85))
+ priv->chip = &cs47l85_pin_chip;
+ break;
+ case CS47L90:
+ case CS47L91:
+ if (IS_ENABLED(CONFIG_PINCTRL_CS47L90))
+ priv->chip = &cs47l90_pin_chip;
+ break;
+ default:
+ break;
+ }
+
+ if (!priv->chip)
+ return -ENODEV;
+
+ madera_pin_desc.npins = priv->chip->n_pins;
+
+ ret = devm_pinctrl_register_and_init(&pdev->dev,
+ &madera_pin_desc,
+ priv,
+ &priv->pctl);
+ if (ret) {
+ dev_err(priv->dev, "Failed pinctrl register (%d)\n", ret);
+ return ret;
+ }
+
+ /* if the configuration is provided through pdata, apply it */
+ if (pdata) {
+ ret = pinctrl_register_mappings(pdata->gpio_configs,
+ pdata->n_gpio_configs);
+ if (ret) {
+ dev_err(priv->dev,
+ "Failed to register pdata mappings (%d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ ret = pinctrl_enable(priv->pctl);
+ if (ret) {
+ dev_err(priv->dev, "Failed to enable pinctrl (%d)\n", ret);
+ return ret;
+ }
+
+ dev_dbg(priv->dev, "pinctrl probed ok\n");
+
+ return 0;
+}
+
+static struct platform_driver madera_pin_driver = {
+ .probe = madera_pin_probe,
+ .driver = {
+ .name = "madera-pinctrl",
+ },
+};
+
+module_platform_driver(madera_pin_driver);
+
+MODULE_DESCRIPTION("Madera pinctrl driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera.h b/drivers/pinctrl/cirrus/pinctrl-madera.h
new file mode 100644
index 000000000000..8000f4f832a1
--- /dev/null
+++ b/drivers/pinctrl/cirrus/pinctrl-madera.h
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * 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.
+ */
+
+#ifndef PINCTRL_MADERA_H
+#define PINCTRL_MADERA_H
+
+struct madera_pin_groups {
+ const char *name;
+ const unsigned int *pins;
+ unsigned int n_pins;
+};
+
+struct madera_pin_chip {
+ unsigned int n_pins;
+
+ const struct madera_pin_groups *pin_groups;
+ unsigned int n_pin_groups;
+};
+
+struct madera_pin_private {
+ struct madera *madera;
+
+ const struct madera_pin_chip *chip; /* chip-specific groups */
+
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+};
+
+extern const struct madera_pin_chip cs47l35_pin_chip;
+extern const struct madera_pin_chip cs47l85_pin_chip;
+extern const struct madera_pin_chip cs47l90_pin_chip;
+
+#endif
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index cb0df9eb3e0f..16b1615958aa 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -52,6 +52,26 @@ config CHROMEOS_TBMC
config CROS_EC_CTL
tristate
+config CROS_EC_I2C
+ tristate "ChromeOS Embedded Controller (I2C)"
+ depends on MFD_CROS_EC && I2C
+
+ help
+ If you say Y here, you get support for talking to the ChromeOS
+ EC through an I2C bus. This uses a simple byte-level protocol with
+ a checksum. Failing accesses will be retried three times to
+ improve reliability.
+
+config CROS_EC_SPI
+ tristate "ChromeOS Embedded Controller (SPI)"
+ depends on MFD_CROS_EC && SPI
+
+ ---help---
+ If you say Y here, you get support for talking to the ChromeOS EC
+ through a SPI bus, using a byte-level protocol. Since the EC's
+ response time cannot be guaranteed, we support ignoring
+ 'pre-amble' bytes before the response actually starts.
+
config CROS_EC_LPC
tristate "ChromeOS Embedded Controller (LPC)"
depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index e44c37a63fa9..cd591bf872bb 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
cros_ec_ctl-objs := cros_ec_sysfs.o cros_ec_lightbar.o \
cros_ec_vbc.o cros_ec_debugfs.o
obj-$(CONFIG_CROS_EC_CTL) += cros_ec_ctl.o
+obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
+obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_reg.o
cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
diff --git a/drivers/platform/chrome/chromeos_tbmc.c b/drivers/platform/chrome/chromeos_tbmc.c
index b935df6a9694..1e81f8144c0d 100644
--- a/drivers/platform/chrome/chromeos_tbmc.c
+++ b/drivers/platform/chrome/chromeos_tbmc.c
@@ -1,8 +1,16 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
// Driver to detect Tablet Mode for ChromeOS convertible.
//
// Copyright (C) 2017 Google, Inc.
// Author: Gwendal Grignou <gwendal@chromium.org>
+//
+// On Chromebook using ACPI, this device listens for notification
+// from GOOG0006 and issue method TBMC to retrieve the status.
+//
+// GOOG0006 issues the notification when it receives EC_HOST_EVENT_MODE_CHANGE
+// from the EC.
+// Method TBMC reads EC_ACPI_MEM_DEVICE_ORIENTATION byte from the shared
+// memory region.
#include <linux/acpi.h>
#include <linux/input.h>
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c
index ef9b4763356f..ef9b4763356f 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/platform/chrome/cros_ec_i2c.c
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 8350ca2311c7..398393ab5df8 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -506,10 +506,31 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
}
EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
+static int get_next_event_xfer(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg,
+ int version, uint32_t size)
+{
+ int ret;
+
+ msg->version = version;
+ msg->command = EC_CMD_GET_NEXT_EVENT;
+ msg->insize = size;
+ msg->outsize = 0;
+
+ ret = cros_ec_cmd_xfer(ec_dev, msg);
+ if (ret > 0) {
+ ec_dev->event_size = ret - 1;
+ memcpy(&ec_dev->event_data, msg->data, ec_dev->event_size);
+ }
+
+ return ret;
+}
+
static int get_next_event(struct cros_ec_device *ec_dev)
{
u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
+ static int cmd_version = 1;
int ret;
if (ec_dev->suspended) {
@@ -517,18 +538,19 @@ static int get_next_event(struct cros_ec_device *ec_dev)
return -EHOSTDOWN;
}
- msg->version = 0;
- msg->command = EC_CMD_GET_NEXT_EVENT;
- msg->insize = sizeof(ec_dev->event_data);
- msg->outsize = 0;
+ if (cmd_version == 1) {
+ ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+ sizeof(struct ec_response_get_next_event_v1));
+ if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
+ return ret;
- ret = cros_ec_cmd_xfer(ec_dev, msg);
- if (ret > 0) {
- ec_dev->event_size = ret - 1;
- memcpy(&ec_dev->event_data, msg->data,
- sizeof(ec_dev->event_data));
+ /* Fallback to version 0 for future send attempts */
+ cmd_version = 0;
}
+ ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+ sizeof(struct ec_response_get_next_event));
+
return ret;
}
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c
index 2060d1483043..2060d1483043 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/platform/chrome/cros_ec_spi.c
diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig
index 591bccdeaff9..cd8a90846063 100644
--- a/drivers/platform/mellanox/Kconfig
+++ b/drivers/platform/mellanox/Kconfig
@@ -23,4 +23,15 @@ config MLXREG_HOTPLUG
This driver handles hot-plug events for the power suppliers, power
cables and fans on the wide range Mellanox IB and Ethernet systems.
+config MLXREG_IO
+ tristate "Mellanox platform register access driver support"
+ depends on REGMAP
+ depends on HWMON
+ help
+ This driver allows access to Mellanox programmable device register
+ space through sysfs interface. The sets of registers for sysfs access
+ are defined per system type bases and include the registers related
+ to system resets operation, system reset causes monitoring and some
+ kinds of mux selection.
+
endif # MELLANOX_PLATFORM
diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile
index 7c8385e497a8..57074d9c722c 100644
--- a/drivers/platform/mellanox/Makefile
+++ b/drivers/platform/mellanox/Makefile
@@ -4,3 +4,4 @@
# Mellanox Platform-Specific Drivers
#
obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o
+obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index ac97aa020db3..b6d44550d98c 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -50,9 +50,8 @@
#define MLXREG_HOTPLUG_MASK_OFF 2
#define MLXREG_HOTPLUG_AGGR_MASK_OFF 1
-/* ASIC health parameters. */
-#define MLXREG_HOTPLUG_HEALTH_MASK 0x02
-#define MLXREG_HOTPLUG_RST_CNTR 3
+/* ASIC good health mask. */
+#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x02
#define MLXREG_HOTPLUG_ATTRS_MAX 24
#define MLXREG_HOTPLUG_NOT_ASSERT 3
@@ -103,6 +102,9 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
{
struct mlxreg_core_hotplug_platform_data *pdata;
+ /* Notify user by sending hwmon uevent. */
+ kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
+
/*
* Return if adapter number is negative. It could be in case hotplug
* event is not associated with hotplug device.
@@ -134,8 +136,13 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
return 0;
}
-static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data)
+static void
+mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,
+ struct mlxreg_core_data *data)
{
+ /* Notify user by sending hwmon uevent. */
+ kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
+
if (data->hpdev.client) {
i2c_unregister_device(data->hpdev.client);
data->hpdev.client = NULL;
@@ -278,14 +285,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
data = item->data + bit;
if (regval & BIT(bit)) {
if (item->inversed)
- mlxreg_hotplug_device_destroy(data);
+ mlxreg_hotplug_device_destroy(priv, data);
else
mlxreg_hotplug_device_create(priv, data);
} else {
if (item->inversed)
mlxreg_hotplug_device_create(priv, data);
else
- mlxreg_hotplug_device_destroy(data);
+ mlxreg_hotplug_device_destroy(priv, data);
}
}
@@ -325,21 +332,40 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
goto out;
regval &= data->mask;
- item->cache = regval;
- if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
- if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
- !priv->after_probe) {
+
+ if (item->cache == regval)
+ goto ack_event;
+
+ /*
+ * ASIC health indication is provided through two bits. Bits
+ * value 0x2 indicates that ASIC reached the good health, value
+ * 0x0 indicates ASIC the bad health or dormant state and value
+ * 0x3 indicates the booting state. During ASIC reset it should
+ * pass the following states: dormant -> booting -> good.
+ */
+ if (regval == MLXREG_HOTPLUG_GOOD_HEALTH_MASK) {
+ if (!data->attached) {
+ /*
+ * ASIC is in steady state. Connect associated
+ * device, if configured.
+ */
mlxreg_hotplug_device_create(priv, data);
data->attached = true;
}
} else {
if (data->attached) {
- mlxreg_hotplug_device_destroy(data);
+ /*
+ * ASIC health is failed after ASIC has been
+ * in steady state. Disconnect associated
+ * device, if it has been connected.
+ */
+ mlxreg_hotplug_device_destroy(priv, data);
data->attached = false;
data->health_cntr = 0;
}
}
-
+ item->cache = regval;
+ack_event:
/* Acknowledge event. */
ret = regmap_write(priv->regmap, data->reg +
MLXREG_HOTPLUG_EVENT_OFF, 0);
@@ -551,7 +577,7 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
/* Remove all the attached devices in group. */
count = item->count;
for (j = 0; j < count; j++, data++)
- mlxreg_hotplug_device_destroy(data);
+ mlxreg_hotplug_device_destroy(priv, data);
}
}
@@ -616,10 +642,6 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
disable_irq(priv->irq);
spin_lock_init(&priv->lock);
INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
- /* Perform initial interrupts setup. */
- mlxreg_hotplug_set_irq(priv);
-
- priv->after_probe = true;
dev_set_drvdata(&pdev->dev, priv);
err = mlxreg_hotplug_attr_init(priv);
@@ -637,6 +659,10 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
return PTR_ERR(priv->hwmon);
}
+ /* Perform initial interrupts setup. */
+ mlxreg_hotplug_set_irq(priv);
+ priv->after_probe = true;
+
return 0;
}
diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c
new file mode 100644
index 000000000000..acfaf64ffde6
--- /dev/null
+++ b/drivers/platform/mellanox/mlxreg-io.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Mellanox register access driver
+ *
+ * Copyright (C) 2018 Mellanox Technologies
+ * Copyright (C) 2018 Vadim Pasternak <vadimp@mellanox.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/mlxreg.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Attribute parameters. */
+#define MLXREG_IO_ATT_SIZE 10
+#define MLXREG_IO_ATT_NUM 48
+
+/**
+ * struct mlxreg_io_priv_data - driver's private data:
+ *
+ * @pdev: platform device;
+ * @pdata: platform data;
+ * @hwmon: hwmon device;
+ * @mlxreg_io_attr: sysfs attributes array;
+ * @mlxreg_io_dev_attr: sysfs sensor device attribute array;
+ * @group: sysfs attribute group;
+ * @groups: list of sysfs attribute group for hwmon registration;
+ */
+struct mlxreg_io_priv_data {
+ struct platform_device *pdev;
+ struct mlxreg_core_platform_data *pdata;
+ struct device *hwmon;
+ struct attribute *mlxreg_io_attr[MLXREG_IO_ATT_NUM + 1];
+ struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
+ struct attribute_group group;
+ const struct attribute_group *groups[2];
+};
+
+static int
+mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
+ bool rw_flag, u32 *regval)
+{
+ int ret;
+
+ ret = regmap_read(regmap, data->reg, regval);
+ if (ret)
+ goto access_error;
+
+ /*
+ * There are three kinds of attributes: single bit, full register's
+ * bits and bit sequence. For the first kind field mask indicates which
+ * bits are not related and field bit is set zero. For the second kind
+ * field mask is set to zero and field bit is set with all bits one.
+ * No special handling for such kind of attributes - pass value as is.
+ * For the third kind, field mask indicates which bits are related and
+ * field bit is set to the first bit number (from 1 to 32) is the bit
+ * sequence.
+ */
+ if (!data->bit) {
+ /* Single bit. */
+ if (rw_flag) {
+ /* For show: expose effective bit value as 0 or 1. */
+ *regval = !!(*regval & ~data->mask);
+ } else {
+ /* For store: set effective bit value. */
+ *regval &= data->mask;
+ if (in_val)
+ *regval |= ~data->mask;
+ }
+ } else if (data->mask) {
+ /* Bit sequence. */
+ if (rw_flag) {
+ /* For show: mask and shift right. */
+ *regval = ror32(*regval & data->mask, (data->bit - 1));
+ } else {
+ /* For store: shift to the position and mask. */
+ in_val = rol32(in_val, data->bit - 1) & data->mask;
+ /* Clear relevant bits and set them to new value. */
+ *regval = (*regval & ~data->mask) | in_val;
+ }
+ }
+
+access_error:
+ return ret;
+}
+
+static ssize_t
+mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr(attr)->index;
+ struct mlxreg_core_data *data = priv->pdata->data + index;
+ u32 regval = 0;
+ int ret;
+
+ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, &regval);
+ if (ret)
+ goto access_error;
+
+ return sprintf(buf, "%u\n", regval);
+
+access_error:
+ return ret;
+}
+
+static ssize_t
+mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr(attr)->index;
+ struct mlxreg_core_data *data = priv->pdata->data + index;
+ u32 input_val, regval;
+ int ret;
+
+ if (len > MLXREG_IO_ATT_SIZE)
+ return -EINVAL;
+
+ /* Convert buffer to input value. */
+ ret = kstrtou32(buf, len, &input_val);
+ if (ret)
+ return ret;
+
+ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
+ &regval);
+ if (ret)
+ goto access_error;
+
+ ret = regmap_write(priv->pdata->regmap, data->reg, regval);
+ if (ret)
+ goto access_error;
+
+ return len;
+
+access_error:
+ dev_err(&priv->pdev->dev, "Bus access error\n");
+ return ret;
+}
+
+static struct device_attribute mlxreg_io_devattr_rw = {
+ .show = mlxreg_io_attr_show,
+ .store = mlxreg_io_attr_store,
+};
+
+static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv)
+{
+ int i;
+
+ priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
+ priv->pdata->counter,
+ sizeof(struct attribute *),
+ GFP_KERNEL);
+ if (!priv->group.attrs)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->pdata->counter; i++) {
+ priv->mlxreg_io_attr[i] =
+ &priv->mlxreg_io_dev_attr[i].dev_attr.attr;
+ memcpy(&priv->mlxreg_io_dev_attr[i].dev_attr,
+ &mlxreg_io_devattr_rw, sizeof(struct device_attribute));
+
+ /* Set attribute name as a label. */
+ priv->mlxreg_io_attr[i]->name =
+ devm_kasprintf(&priv->pdev->dev, GFP_KERNEL,
+ priv->pdata->data[i].label);
+
+ if (!priv->mlxreg_io_attr[i]->name) {
+ dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n",
+ i + 1);
+ return -ENOMEM;
+ }
+
+ priv->mlxreg_io_dev_attr[i].dev_attr.attr.mode =
+ priv->pdata->data[i].mode;
+ priv->mlxreg_io_dev_attr[i].dev_attr.attr.name =
+ priv->mlxreg_io_attr[i]->name;
+ priv->mlxreg_io_dev_attr[i].index = i;
+ sysfs_attr_init(&priv->mlxreg_io_dev_attr[i].dev_attr.attr);
+ }
+
+ priv->group.attrs = priv->mlxreg_io_attr;
+ priv->groups[0] = &priv->group;
+ priv->groups[1] = NULL;
+
+ return 0;
+}
+
+static int mlxreg_io_probe(struct platform_device *pdev)
+{
+ struct mlxreg_io_priv_data *priv;
+ int err;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->pdata = dev_get_platdata(&pdev->dev);
+ if (!priv->pdata) {
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
+ return -EINVAL;
+ }
+
+ priv->pdev = pdev;
+
+ err = mlxreg_io_attr_init(priv);
+ if (err) {
+ dev_err(&priv->pdev->dev, "Failed to allocate attributes: %d\n",
+ err);
+ return err;
+ }
+
+ priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
+ "mlxreg_io",
+ priv,
+ priv->groups);
+ if (IS_ERR(priv->hwmon)) {
+ dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
+ PTR_ERR(priv->hwmon));
+ return PTR_ERR(priv->hwmon);
+ }
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ return 0;
+}
+
+static struct platform_driver mlxreg_io_driver = {
+ .driver = {
+ .name = "mlxreg-io",
+ },
+ .probe = mlxreg_io_probe,
+};
+
+module_platform_driver(mlxreg_io_driver);
+
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox regmap I/O access driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mlxreg-io");
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 107d336453b2..0c1aa6c314f5 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1196,16 +1196,16 @@ config INTEL_TURBO_MAX_3
This driver is only required when the system is not using Hardware
P-States (HWP). In HWP mode, priority can be read from ACPI tables.
-config SILEAD_DMI
- bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+ bool "DMI based touchscreen configuration info"
depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
---help---
- Certain ACPI based tablets with Silead touchscreens do not have
- enough data in ACPI tables for the touchscreen driver to handle
- the touchscreen properly, as OEMs expected the data to be baked
- into the tablet model specific version of the driver shipped
- with the OS-image for the device. This option supplies the missing
- information. Enable this for x86 tablets with Silead touchscreens.
+ Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+ do not have enough data in ACPI tables for the touchscreen driver to
+ handle the touchscreen properly, as OEMs expect the data to be baked
+ into the tablet model specific version of the driver shipped with the
+ the OS-image for the device. This option supplies the missing info.
+ Enable this for x86 tablets with Silead or Chipone touchscreens.
config INTEL_CHTDC_TI_PWRBTN
tristate "Intel Cherry Trail Dollar Cove TI power button driver"
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 50dc8f280914..e6d1becf81ce 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
obj-$(CONFIG_INTEL_PMC_IPC) += intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI) += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o
obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o
obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
obj-$(CONFIG_INTEL_PUNIT_IPC) += intel_punit_ipc.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 8952173dd380..fcfeadd1301f 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -672,10 +672,7 @@ static void __init find_quirks(void)
static bool has_cap(u32 cap)
{
- if ((interface->capability & cap) != 0)
- return 1;
-
- return 0;
+ return interface->capability & cap;
}
/*
@@ -2216,7 +2213,7 @@ static int __init acer_wmi_init(void)
if (wmi_has_guid(AMW0_GUID1) &&
!dmi_check_system(amw0_whitelist) &&
quirks == &quirk_unknown) {
- pr_err("Unsupported machine has AMW0_GUID1, unable to load\n");
+ pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n");
return -ENODEV;
}
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 136ff2b4cce5..db2af09067db 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -496,6 +496,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
{ KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
{ KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */
+ { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */
{ KE_END, 0},
};
diff --git a/drivers/platform/x86/asus-wireless.c b/drivers/platform/x86/asus-wireless.c
index 6afd011de9e5..7458f7602d5e 100644
--- a/drivers/platform/x86/asus-wireless.c
+++ b/drivers/platform/x86/asus-wireless.c
@@ -52,13 +52,12 @@ static const struct acpi_device_id device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, device_ids);
-static u64 asus_wireless_method(acpi_handle handle, const char *method,
- int param)
+static acpi_status asus_wireless_method(acpi_handle handle, const char *method,
+ int param, u64 *ret)
{
struct acpi_object_list p;
union acpi_object obj;
acpi_status s;
- u64 ret;
acpi_handle_debug(handle, "Evaluating method %s, parameter %#x\n",
method, param);
@@ -67,24 +66,27 @@ static u64 asus_wireless_method(acpi_handle handle, const char *method,
p.count = 1;
p.pointer = &obj;
- s = acpi_evaluate_integer(handle, (acpi_string) method, &p, &ret);
+ s = acpi_evaluate_integer(handle, (acpi_string) method, &p, ret);
if (ACPI_FAILURE(s))
acpi_handle_err(handle,
"Failed to eval method %s, param %#x (%d)\n",
method, param, s);
- acpi_handle_debug(handle, "%s returned %#llx\n", method, ret);
- return ret;
+ else
+ acpi_handle_debug(handle, "%s returned %#llx\n", method, *ret);
+
+ return s;
}
static enum led_brightness led_state_get(struct led_classdev *led)
{
struct asus_wireless_data *data;
- int s;
+ acpi_status s;
+ u64 ret;
data = container_of(led, struct asus_wireless_data, led);
s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC",
- data->hswc_params->status);
- if (s == data->hswc_params->on)
+ data->hswc_params->status, &ret);
+ if (ACPI_SUCCESS(s) && ret == data->hswc_params->on)
return LED_FULL;
return LED_OFF;
}
@@ -92,10 +94,11 @@ static enum led_brightness led_state_get(struct led_classdev *led)
static void led_state_update(struct work_struct *work)
{
struct asus_wireless_data *data;
+ u64 ret;
data = container_of(work, struct asus_wireless_data, led_work);
asus_wireless_method(acpi_device_handle(data->adev), "HSWC",
- data->led_state);
+ data->led_state, &ret);
}
static void led_state_set(struct led_classdev *led, enum led_brightness value)
@@ -167,6 +170,7 @@ static int asus_wireless_add(struct acpi_device *adev)
data->led.brightness_get = led_state_get;
data->led.flags = LED_CORE_SUSPENDRESUME;
data->led.max_brightness = 1;
+ data->led.default_trigger = "rfkill-none";
err = devm_led_classdev_register(&adev->dev, &data->led);
if (err)
destroy_workqueue(data->wq);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index d67f32a29bb4..2d6e272315a8 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -67,6 +67,7 @@ MODULE_LICENSE("GPL");
#define NOTIFY_BRNDOWN_MAX 0x2e
#define NOTIFY_KBD_BRTUP 0xc4
#define NOTIFY_KBD_BRTDWN 0xc5
+#define NOTIFY_KBD_BRTTOGGLE 0xc7
/* WMI Methods */
#define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */
@@ -470,6 +471,7 @@ static void kbd_led_update(struct work_struct *work)
ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
+ led_classdev_notify_brightness_hw_changed(&asus->kbd_led, asus->kbd_led_wk);
}
static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
@@ -500,15 +502,16 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
return retval;
}
-static void kbd_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
{
struct asus_wmi *asus;
+ int max_level;
asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+ max_level = asus->kbd_led.max_brightness;
- if (value > asus->kbd_led.max_brightness)
- value = asus->kbd_led.max_brightness;
+ if (value > max_level)
+ value = max_level;
else if (value < 0)
value = 0;
@@ -516,6 +519,12 @@ static void kbd_led_set(struct led_classdev *led_cdev,
queue_work(asus->led_workqueue, &asus->kbd_led_work);
}
+static void kbd_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ do_kbd_led_set(led_cdev, value);
+}
+
static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
{
struct asus_wmi *asus;
@@ -666,6 +675,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
asus->kbd_led_wk = led_val;
asus->kbd_led.name = "asus::kbd_backlight";
+ asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
asus->kbd_led.brightness_set = kbd_led_set;
asus->kbd_led.brightness_get = kbd_led_get;
asus->kbd_led.max_brightness = 3;
@@ -1754,6 +1764,22 @@ static void asus_wmi_notify(u32 value, void *context)
}
}
+ if (code == NOTIFY_KBD_BRTUP) {
+ do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+ goto exit;
+ }
+ if (code == NOTIFY_KBD_BRTDWN) {
+ do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk - 1);
+ goto exit;
+ }
+ if (code == NOTIFY_KBD_BRTTOGGLE) {
+ if (asus->kbd_led_wk == asus->kbd_led.max_brightness)
+ do_kbd_led_set(&asus->kbd_led, 0);
+ else
+ do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+ goto exit;
+ }
+
if (is_display_toggle(code) &&
asus->driver->quirks->no_display_toggle)
goto exit;
diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c
index 9dc282ed5a9e..0537d44d45a6 100644
--- a/drivers/platform/x86/dell-smbios-base.c
+++ b/drivers/platform/x86/dell-smbios-base.c
@@ -212,6 +212,12 @@ int dell_smbios_call_filter(struct device *d,
if ((buffer->cmd_class == CLASS_TOKEN_READ ||
buffer->cmd_class == CLASS_TOKEN_WRITE) &&
buffer->cmd_select < 3) {
+ /* tokens enabled ? */
+ if (!da_tokens) {
+ dev_dbg(d, "no token support on this system\n");
+ return -EINVAL;
+ }
+
/* find the matching token ID */
for (i = 0; i < da_num_tokens; i++) {
if (da_tokens[i].location != buffer->input[0])
@@ -315,6 +321,9 @@ struct calling_interface_token *dell_smbios_find_token(int tokenid)
{
int i;
+ if (!da_tokens)
+ return NULL;
+
for (i = 0; i < da_num_tokens; i++) {
if (da_tokens[i].tokenID == tokenid)
return &da_tokens[i];
@@ -565,11 +574,6 @@ static int __init dell_smbios_init(void)
dmi_walk(find_tokens, NULL);
- if (!da_tokens) {
- pr_info("Unable to find dmi tokens\n");
- return -ENODEV;
- }
-
ret = platform_driver_register(&platform_driver);
if (ret)
goto fail_platform_driver;
@@ -583,13 +587,6 @@ static int __init dell_smbios_init(void)
if (ret)
goto fail_platform_device_add;
- /* duplicate tokens will cause problems building sysfs files */
- zero_duplicates(&platform_device->dev);
-
- ret = build_tokens_sysfs(platform_device);
- if (ret)
- goto fail_create_group;
-
/* register backends */
wmi = init_dell_smbios_wmi();
if (wmi)
@@ -600,7 +597,16 @@ static int __init dell_smbios_init(void)
if (wmi && smm) {
pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n",
wmi, smm);
- goto fail_sysfs;
+ goto fail_create_group;
+ }
+
+ if (da_tokens) {
+ /* duplicate tokens will cause problems building sysfs files */
+ zero_duplicates(&platform_device->dev);
+
+ ret = build_tokens_sysfs(platform_device);
+ if (ret)
+ goto fail_sysfs;
}
return 0;
@@ -628,7 +634,8 @@ static void __exit dell_smbios_exit(void)
exit_dell_smbios_smm();
mutex_lock(&smbios_mutex);
if (platform_device) {
- free_group(platform_device);
+ if (da_tokens)
+ free_group(platform_device);
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c
index e9e9da556318..97a90bebc360 100644
--- a/drivers/platform/x86/dell-smbios-smm.c
+++ b/drivers/platform/x86/dell-smbios-smm.c
@@ -24,7 +24,7 @@
static int da_command_address;
static int da_command_code;
static struct calling_interface_buffer *buffer;
-struct platform_device *platform_device;
+static struct platform_device *platform_device;
static DEFINE_MUTEX(smm_mutex);
static const struct dmi_system_id dell_device_table[] __initconst = {
@@ -82,7 +82,7 @@ static void find_cmd_address(const struct dmi_header *dm, void *dummy)
}
}
-int dell_smbios_smm_call(struct calling_interface_buffer *input)
+static int dell_smbios_smm_call(struct calling_interface_buffer *input)
{
struct smi_cmd command;
size_t size;
diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c
index fbefedb1c172..88afe5651d24 100644
--- a/drivers/platform/x86/dell-smbios-wmi.c
+++ b/drivers/platform/x86/dell-smbios-wmi.c
@@ -82,7 +82,7 @@ static int run_smbios_call(struct wmi_device *wdev)
return 0;
}
-int dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
+static int dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
{
struct wmi_smbios_priv *priv;
size_t difference;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 45b7cb01f410..d4f1259ff5a2 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1133,10 +1133,17 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
},
},
{
- .ident = "Lenovo Legion Y520-15IKBN",
+ .ident = "Lenovo Legion Y520-15IKB",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"),
+ },
+ },
+ {
+ .ident = "Lenovo Y520-15IKBM",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
},
},
{
@@ -1154,6 +1161,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
},
},
{
+ .ident = "Lenovo Y720-15IKBM",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBM"),
+ },
+ },
+ {
.ident = "Lenovo Yoga 2 11 / 13 / Pro",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index b5adba227783..6cf9b7fa5bf0 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -96,13 +96,140 @@ struct intel_hid_priv {
bool wakeup_mode;
};
-static int intel_hid_set_enable(struct device *device, bool enable)
+#define HID_EVENT_FILTER_UUID "eeec56b3-4442-408f-a792-4edd4d758054"
+
+enum intel_hid_dsm_fn_codes {
+ INTEL_HID_DSM_FN_INVALID,
+ INTEL_HID_DSM_BTNL_FN,
+ INTEL_HID_DSM_HDMM_FN,
+ INTEL_HID_DSM_HDSM_FN,
+ INTEL_HID_DSM_HDEM_FN,
+ INTEL_HID_DSM_BTNS_FN,
+ INTEL_HID_DSM_BTNE_FN,
+ INTEL_HID_DSM_HEBC_V1_FN,
+ INTEL_HID_DSM_VGBS_FN,
+ INTEL_HID_DSM_HEBC_V2_FN,
+ INTEL_HID_DSM_FN_MAX
+};
+
+static const char *intel_hid_dsm_fn_to_method[INTEL_HID_DSM_FN_MAX] = {
+ NULL,
+ "BTNL",
+ "HDMM",
+ "HDSM",
+ "HDEM",
+ "BTNS",
+ "BTNE",
+ "HEBC",
+ "VGBS",
+ "HEBC"
+};
+
+static unsigned long long intel_hid_dsm_fn_mask;
+static guid_t intel_dsm_guid;
+
+static bool intel_hid_execute_method(acpi_handle handle,
+ enum intel_hid_dsm_fn_codes fn_index,
+ unsigned long long arg)
{
+ union acpi_object *obj, argv4, req;
acpi_status status;
+ char *method_name;
- status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM",
- enable);
- if (ACPI_FAILURE(status)) {
+ if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
+ fn_index >= INTEL_HID_DSM_FN_MAX)
+ return false;
+
+ method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
+
+ if (!(intel_hid_dsm_fn_mask & fn_index))
+ goto skip_dsm_exec;
+
+ /* All methods expects a package with one integer element */
+ req.type = ACPI_TYPE_INTEGER;
+ req.integer.value = arg;
+
+ argv4.type = ACPI_TYPE_PACKAGE;
+ argv4.package.count = 1;
+ argv4.package.elements = &req;
+
+ obj = acpi_evaluate_dsm(handle, &intel_dsm_guid, 1, fn_index, &argv4);
+ if (obj) {
+ acpi_handle_debug(handle, "Exec DSM Fn code: %d[%s] success\n",
+ fn_index, method_name);
+ ACPI_FREE(obj);
+ return true;
+ }
+
+skip_dsm_exec:
+ status = acpi_execute_simple_method(handle, method_name, arg);
+ if (ACPI_SUCCESS(status))
+ return true;
+
+ return false;
+}
+
+static bool intel_hid_evaluate_method(acpi_handle handle,
+ enum intel_hid_dsm_fn_codes fn_index,
+ unsigned long long *result)
+{
+ union acpi_object *obj;
+ acpi_status status;
+ char *method_name;
+
+ if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
+ fn_index >= INTEL_HID_DSM_FN_MAX)
+ return false;
+
+ method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
+
+ if (!(intel_hid_dsm_fn_mask & fn_index))
+ goto skip_dsm_eval;
+
+ obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid,
+ 1, fn_index,
+ NULL, ACPI_TYPE_INTEGER);
+ if (obj) {
+ *result = obj->integer.value;
+ acpi_handle_debug(handle,
+ "Eval DSM Fn code: %d[%s] results: 0x%llx\n",
+ fn_index, method_name, *result);
+ ACPI_FREE(obj);
+ return true;
+ }
+
+skip_dsm_eval:
+ status = acpi_evaluate_integer(handle, method_name, NULL, result);
+ if (ACPI_SUCCESS(status))
+ return true;
+
+ return false;
+}
+
+static void intel_hid_init_dsm(acpi_handle handle)
+{
+ union acpi_object *obj;
+
+ guid_parse(HID_EVENT_FILTER_UUID, &intel_dsm_guid);
+
+ obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 1, 0, NULL,
+ ACPI_TYPE_BUFFER);
+ if (obj) {
+ intel_hid_dsm_fn_mask = *obj->buffer.pointer;
+ ACPI_FREE(obj);
+ }
+
+ acpi_handle_debug(handle, "intel_hid_dsm_fn_mask = %llx\n",
+ intel_hid_dsm_fn_mask);
+}
+
+static int intel_hid_set_enable(struct device *device, bool enable)
+{
+ acpi_handle handle = ACPI_HANDLE(device);
+
+ /* Enable|disable features - power button is always enabled */
+ if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN,
+ enable)) {
dev_warn(device, "failed to %sable hotkeys\n",
enable ? "en" : "dis");
return -EIO;
@@ -129,9 +256,8 @@ static void intel_button_array_enable(struct device *device, bool enable)
}
/* Enable|disable features - power button is always enabled */
- status = acpi_execute_simple_method(handle, "BTNE",
- enable ? button_cap : 1);
- if (ACPI_FAILURE(status))
+ if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN,
+ enable ? button_cap : 1))
dev_warn(device, "failed to set button capability\n");
}
@@ -217,7 +343,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
struct platform_device *device = context;
struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
unsigned long long ev_index;
- acpi_status status;
if (priv->wakeup_mode) {
/*
@@ -269,8 +394,8 @@ wakeup:
return;
}
- status = acpi_evaluate_integer(handle, "HDEM", NULL, &ev_index);
- if (ACPI_FAILURE(status)) {
+ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN,
+ &ev_index)) {
dev_warn(&device->dev, "failed to get event index\n");
return;
}
@@ -284,17 +409,24 @@ static bool button_array_present(struct platform_device *device)
{
acpi_handle handle = ACPI_HANDLE(&device->dev);
unsigned long long event_cap;
- acpi_status status;
- bool supported = false;
- status = acpi_evaluate_integer(handle, "HEBC", NULL, &event_cap);
- if (ACPI_SUCCESS(status) && (event_cap & 0x20000))
- supported = true;
+ if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN,
+ &event_cap)) {
+ /* Check presence of 5 button array or v2 power button */
+ if (event_cap & 0x60000)
+ return true;
+ }
+
+ if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN,
+ &event_cap)) {
+ if (event_cap & 0x20000)
+ return true;
+ }
if (dmi_check_system(button_array_table))
- supported = true;
+ return true;
- return supported;
+ return false;
}
static int intel_hid_probe(struct platform_device *device)
@@ -305,8 +437,9 @@ static int intel_hid_probe(struct platform_device *device)
acpi_status status;
int err;
- status = acpi_evaluate_integer(handle, "HDMM", NULL, &mode);
- if (ACPI_FAILURE(status)) {
+ intel_hid_init_dsm(handle);
+
+ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) {
dev_warn(&device->dev, "failed to read mode\n");
return -ENODEV;
}
@@ -352,13 +485,16 @@ static int intel_hid_probe(struct platform_device *device)
goto err_remove_notify;
if (priv->array) {
+ unsigned long long dummy;
+
intel_button_array_enable(&device->dev, true);
/* Call button load method to enable HID power button */
- status = acpi_evaluate_object(handle, "BTNL", NULL, NULL);
- if (ACPI_FAILURE(status))
+ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
+ &dummy)) {
dev_warn(&device->dev,
"failed to enable HID power button\n");
+ }
}
device_init_wakeup(&device->dev, true);
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
index c13780b8dabb..06cd7e818ed5 100644
--- a/drivers/platform/x86/intel-vbtn.c
+++ b/drivers/platform/x86/intel-vbtn.c
@@ -17,6 +17,7 @@
/* When NOT in tablet mode, VGBS returns with the flag 0x40 */
#define TABLET_MODE_FLAG 0x40
+#define DOCK_MODE_FLAG 0x80
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AceLan Kao");
@@ -38,6 +39,8 @@ static const struct key_entry intel_vbtn_keymap[] = {
{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
{ KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */
{ KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */
+ { KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
+ { KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
{ KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
{ KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
{ KE_END },
@@ -121,6 +124,8 @@ static void detect_tablet_mode(struct platform_device *device)
m = !(obj->integer.value & TABLET_MODE_FLAG);
input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
+ m = (obj->integer.value & DOCK_MODE_FLAG) ? 1 : 0;
+ input_report_switch(priv->input_dev, SW_DOCK, m);
out:
kfree(vgbs_output.pointer);
}
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index 014fc1634a3d..c5ece7ef08c6 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -858,10 +858,7 @@ static u16 read_mgtv(struct ips_driver *ips)
static u16 read_ptv(struct ips_driver *ips)
{
- u16 val, slope, offset;
-
- slope = (ips->pta_val & PTA_SLOPE_MASK) >> PTA_SLOPE_SHIFT;
- offset = ips->pta_val & PTA_OFFSET_MASK;
+ u16 val;
val = thm_readw(THM_PTV) & PTV_MASK;
diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c
index 43bbe74743d9..2d272a3e0176 100644
--- a/drivers/platform/x86/intel_pmc_core.c
+++ b/drivers/platform/x86/intel_pmc_core.c
@@ -196,9 +196,67 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
{}
};
+static const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
+ {"AUDIO_D3", BIT(0)},
+ {"OTG_D3", BIT(1)},
+ {"XHCI_D3", BIT(2)},
+ {"LPIO_D3", BIT(3)},
+ {"SDX_D3", BIT(4)},
+ {"SATA_D3", BIT(5)},
+ {"UFS0_D3", BIT(6)},
+ {"UFS1_D3", BIT(7)},
+ {"EMMC_D3", BIT(8)},
+ {}
+};
+
+static const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
+ {"SDIO_PLL_OFF", BIT(0)},
+ {"USB2_PLL_OFF", BIT(1)},
+ {"AUDIO_PLL_OFF", BIT(2)},
+ {"OC_PLL_OFF", BIT(3)},
+ {"MAIN_PLL_OFF", BIT(4)},
+ {"XOSC_OFF", BIT(5)},
+ {"LPC_CLKS_GATED", BIT(6)},
+ {"PCIE_CLKREQS_IDLE", BIT(7)},
+ {"AUDIO_ROSC_OFF", BIT(8)},
+ {"HPET_XOSC_CLK_REQ", BIT(9)},
+ {"PMC_ROSC_SLOW_CLK", BIT(10)},
+ {"AON2_ROSC_GATED", BIT(11)},
+ {"CLKACKS_DEASSERTED", BIT(12)},
+ {}
+};
+
+static const struct pmc_bit_map cnp_slps0_dbg2_map[] = {
+ {"MPHY_CORE_GATED", BIT(0)},
+ {"CSME_GATED", BIT(1)},
+ {"USB2_SUS_GATED", BIT(2)},
+ {"DYN_FLEX_IO_IDLE", BIT(3)},
+ {"GBE_NO_LINK", BIT(4)},
+ {"THERM_SEN_DISABLED", BIT(5)},
+ {"PCIE_LOW_POWER", BIT(6)},
+ {"ISH_VNNAON_REQ_ACT", BIT(7)},
+ {"ISH_VNN_REQ_ACT", BIT(8)},
+ {"CNV_VNNAON_REQ_ACT", BIT(9)},
+ {"CNV_VNN_REQ_ACT", BIT(10)},
+ {"NPK_VNNON_REQ_ACT", BIT(11)},
+ {"PMSYNC_STATE_IDLE", BIT(12)},
+ {"ALST_GT_THRES", BIT(13)},
+ {"PMC_ARC_PG_READY", BIT(14)},
+ {}
+};
+
+static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
+ cnp_slps0_dbg0_map,
+ cnp_slps0_dbg1_map,
+ cnp_slps0_dbg2_map,
+ NULL,
+};
+
static const struct pmc_reg_map cnp_reg_map = {
.pfear_sts = cnp_pfear_map,
.slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
+ .slps0_dbg_maps = cnp_slps0_dbg_maps,
+ .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
.ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
.regmap_length = CNP_PMC_MMIO_REG_LEN,
.ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
@@ -252,6 +310,8 @@ static int pmc_core_check_read_lock_bit(void)
}
#if IS_ENABLED(CONFIG_DEBUG_FS)
+static bool slps0_dbg_latch;
+
static void pmc_core_display_map(struct seq_file *s, int index,
u8 pf_reg, const struct pmc_bit_map *pf_map)
{
@@ -481,6 +541,57 @@ static const struct file_operations pmc_core_ltr_ignore_ops = {
.release = single_release,
};
+static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)
+{
+ const struct pmc_reg_map *map = pmcdev->map;
+ u32 fd;
+
+ mutex_lock(&pmcdev->lock);
+
+ if (!reset && !slps0_dbg_latch)
+ goto out_unlock;
+
+ fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset);
+ if (reset)
+ fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS;
+ else
+ fd |= CNP_PMC_LATCH_SLPS0_EVENTS;
+ pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd);
+
+ slps0_dbg_latch = 0;
+
+out_unlock:
+ mutex_unlock(&pmcdev->lock);
+}
+
+static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)
+{
+ struct pmc_dev *pmcdev = s->private;
+ const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps;
+ const struct pmc_bit_map *map;
+ int offset;
+ u32 data;
+
+ pmc_core_slps0_dbg_latch(pmcdev, false);
+ offset = pmcdev->map->slps0_dbg_offset;
+ while (*maps) {
+ map = *maps;
+ data = pmc_core_reg_read(pmcdev, offset);
+ offset += 4;
+ while (map->name) {
+ seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n",
+ map->name,
+ data & map->bit_mask ?
+ "Yes" : "No");
+ ++map;
+ }
+ ++maps;
+ }
+ pmc_core_slps0_dbg_latch(pmcdev, true);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg);
+
static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
{
debugfs_remove_recursive(pmcdev->dbgfs_dir);
@@ -514,6 +625,15 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
0444, dir, pmcdev,
&pmc_core_mphy_pg_ops);
+ if (pmcdev->map->slps0_dbg_maps) {
+ debugfs_create_file("slp_s0_debug_status", 0444,
+ dir, pmcdev,
+ &pmc_core_slps0_dbg_fops);
+
+ debugfs_create_bool("slp_s0_dbg_latch", 0644,
+ dir, &slps0_dbg_latch);
+ }
+
return 0;
}
#else
diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h
index 5fa5f97870aa..93a7e99e1f8b 100644
--- a/drivers/platform/x86/intel_pmc_core.h
+++ b/drivers/platform/x86/intel_pmc_core.h
@@ -127,12 +127,14 @@ enum ppfear_regs {
#define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET 0x193C
#define CNP_PMC_LTR_IGNORE_OFFSET 0x1B0C
#define CNP_PMC_PM_CFG_OFFSET 0x1818
+#define CNP_PMC_SLPS0_DBG_OFFSET 0x10B4
/* Cannonlake: PGD PFET Enable Ack Status Register(s) start */
#define CNP_PMC_HOST_PPFEAR0A 0x1D90
#define CNP_PMC_MMIO_REG_LEN 0x2000
#define CNP_PPFEAR_NUM_ENTRIES 8
#define CNP_PMC_READ_DISABLE_BIT 22
+#define CNP_PMC_LATCH_SLPS0_EVENTS BIT(31)
struct pmc_bit_map {
const char *name;
@@ -145,6 +147,7 @@ struct pmc_bit_map {
* @pfear_sts: Maps name of IP block to PPFEAR* bit
* @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit
* @pll_sts: Maps name of PLL to corresponding bit status
+ * @slps0_dbg_maps: Array of SLP_S0_DBG* registers containing debug info
* @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency
* @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit
* @regmap_length: Length of memory to map from PWRMBASE address to access
@@ -153,6 +156,7 @@ struct pmc_bit_map {
* PPFEAR
* @pm_cfg_offset: PWRMBASE offset to PM_CFG register
* @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE
+ * @slps0_dbg_offset: PWRMBASE offset to SLP_S0_DEBUG_REG*
*
* Each PCH has unique set of register offsets and bit indexes. This structure
* captures them to have a common implementation.
@@ -161,6 +165,7 @@ struct pmc_reg_map {
const struct pmc_bit_map *pfear_sts;
const struct pmc_bit_map *mphy_sts;
const struct pmc_bit_map *pll_sts;
+ const struct pmc_bit_map **slps0_dbg_maps;
const u32 slp_s0_offset;
const u32 ltr_ignore_offset;
const int regmap_length;
@@ -168,6 +173,7 @@ struct pmc_reg_map {
const int ppfear_buckets;
const u32 pm_cfg_offset;
const int pm_read_disable_bit;
+ const u32 slps0_dbg_offset;
};
/**
diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c
index f1afc0ebbc68..2efeab650345 100644
--- a/drivers/platform/x86/intel_punit_ipc.c
+++ b/drivers/platform/x86/intel_punit_ipc.c
@@ -18,6 +18,7 @@
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/platform_device.h>
#include <asm/intel_punit_ipc.h>
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index a0fd9aa6d932..d89936c93ba0 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -47,15 +47,26 @@
/* LPC bus IO offsets */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
+#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00
+#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
+#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
+#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30
+#define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31
+#define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32
+#define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET 0x33
+#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41
+#define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50
+#define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51
+#define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52
#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58
#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59
#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a
@@ -65,9 +76,23 @@
#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
+#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
+#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
+#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5
+#define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET 0xe6
+#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7
+#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8
+#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9
+#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea
+#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb
+#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec
+#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed
+#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee
+#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
+
#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
#define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
@@ -77,17 +102,20 @@
MLXPLAT_CPLD_LPC_PIO_OFFSET)
/* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
+#define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF 0x04
#define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08
#define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08
#define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40
-#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
+#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \
+ MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
+#define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01
#define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04
-#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0
-#define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04
+#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
#define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
+#define MLXPLAT_CPLD_ASIC_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
@@ -122,12 +150,16 @@
* @pdev_mux - array of mux platform devices
* @pdev_hotplug - hotplug platform devices
* @pdev_led - led platform devices
+ * @pdev_io_regs - register access platform devices
+ * @pdev_fan - FAN platform devices
*/
struct mlxplat_priv {
struct platform_device *pdev_i2c;
struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
struct platform_device *pdev_hotplug;
struct platform_device *pdev_led;
+ struct platform_device *pdev_io_regs;
+ struct platform_device *pdev_fan;
};
/* Regions for LPC I2C controller and LPC base register space */
@@ -288,6 +320,15 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
},
};
+static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = {
+ {
+ .label = "asic1",
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+ },
+};
+
static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
{
.data = mlxplat_mlxcpld_default_psu_items_data,
@@ -316,6 +357,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
.inversed = 1,
.health = false,
},
+ {
+ .data = mlxplat_mlxcpld_default_asic_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+ .inversed = 0,
+ .health = true,
+ },
};
static
@@ -324,6 +374,8 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
.cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
.mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
+ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
+ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
};
static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
@@ -352,6 +404,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
.inversed = 0,
.health = false,
},
+ {
+ .data = mlxplat_mlxcpld_default_asic_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+ .inversed = 0,
+ .health = true,
+ },
};
static
@@ -454,6 +515,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
.inversed = 1,
.health = false,
},
+ {
+ .data = mlxplat_mlxcpld_default_asic_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+ .inversed = 0,
+ .health = true,
+ },
};
static
@@ -492,6 +562,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
.inversed = 0,
.health = false,
},
+ {
+ .data = mlxplat_mlxcpld_default_asic_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+ .inversed = 0,
+ .health = true,
+ },
};
static
@@ -589,6 +668,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
.inversed = 1,
.health = false,
},
+ {
+ .data = mlxplat_mlxcpld_default_asic_items_data,
+ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+ .inversed = 0,
+ .health = true,
+ },
};
static
@@ -813,6 +901,278 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
};
+/* Platform register access default */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
+ {
+ .label = "cpld1_version",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld2_version",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_long_pb",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(0),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_short_pb",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(1),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_aux_pwr_or_ref",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(2),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_main_pwr_fail",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(3),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_sw_reset",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(4),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_fw_reset",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(5),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_hotswap_or_wd",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(6),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_asic_thermal",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(7),
+ .mode = 0444,
+ },
+ {
+ .label = "psu1_on",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(0),
+ .mode = 0200,
+ },
+ {
+ .label = "psu2_on",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(1),
+ .mode = 0200,
+ },
+ {
+ .label = "pwr_cycle",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(2),
+ .mode = 0200,
+ },
+ {
+ .label = "pwr_down",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(3),
+ .mode = 0200,
+ },
+ {
+ .label = "select_iio",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(6),
+ .mode = 0644,
+ },
+ {
+ .label = "asic_health",
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .bit = 1,
+ .mode = 0444,
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
+ .data = mlxplat_mlxcpld_default_regs_io_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
+};
+
+/* Platform register access MSN21xx, MSN201x, MSN274x systems families data */
+static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
+ {
+ .label = "cpld1_version",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "cpld2_version",
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
+ .bit = GENMASK(7, 0),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_long_pb",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(0),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_short_pb",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(1),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_aux_pwr_or_ref",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(2),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_sw_reset",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(3),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_main_pwr_fail",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(4),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_asic_thermal",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(5),
+ .mode = 0444,
+ },
+ {
+ .label = "reset_hotswap_or_halt",
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(6),
+ .mode = 0444,
+ },
+ {
+ .label = "psu1_on",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(0),
+ .mode = 0200,
+ },
+ {
+ .label = "psu2_on",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(1),
+ .mode = 0200,
+ },
+ {
+ .label = "pwr_cycle",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(2),
+ .mode = 0200,
+ },
+ {
+ .label = "pwr_down",
+ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+ .mask = GENMASK(7, 0) & ~BIT(3),
+ .mode = 0200,
+ },
+ {
+ .label = "asic_health",
+ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+ .mask = MLXPLAT_CPLD_ASIC_MASK,
+ .bit = 1,
+ .mode = 0444,
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = {
+ .data = mlxplat_mlxcpld_msn21xx_regs_io_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data),
+};
+
+/* Platform FAN default */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
+ {
+ .label = "pwm1",
+ .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET,
+ },
+ {
+ .label = "tacho1",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho2",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho3",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho4",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho5",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho6",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho7",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho8",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho9",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho10",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho11",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+ {
+ .label = "tacho12",
+ .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
+ .mask = GENMASK(7, 0),
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
+ .data = mlxplat_mlxcpld_default_fan_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
+};
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
{
@@ -822,14 +1182,22 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
return true;
}
return false;
@@ -838,15 +1206,25 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
@@ -856,6 +1234,20 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
return true;
}
return false;
@@ -864,15 +1256,23 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
@@ -882,11 +1282,31 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
return true;
}
return false;
}
+static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
+ { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
+ { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
+ { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
+};
+
struct mlxplat_mlxcpld_regmap_context {
void __iomem *base;
};
@@ -919,6 +1339,8 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
.writeable_reg = mlxplat_mlxcpld_writeable_reg,
.readable_reg = mlxplat_mlxcpld_readable_reg,
.volatile_reg = mlxplat_mlxcpld_volatile_reg,
+ .reg_defaults = mlxplat_mlxcpld_regmap_default,
+ .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default),
.reg_read = mlxplat_mlxcpld_reg_read,
.reg_write = mlxplat_mlxcpld_reg_write,
};
@@ -930,6 +1352,8 @@ static struct resource mlxplat_mlxcpld_resources[] = {
static struct platform_device *mlxplat_dev;
static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
static struct mlxreg_core_platform_data *mlxplat_led;
+static struct mlxreg_core_platform_data *mlxplat_regs_io;
+static struct mlxreg_core_platform_data *mlxplat_fan;
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{
@@ -944,6 +1368,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_led_data;
+ mlxplat_regs_io = &mlxplat_default_regs_io_data;
return 1;
};
@@ -961,6 +1386,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_msn21xx_led_data;
+ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
return 1;
};
@@ -978,6 +1404,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_led_data;
+ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
return 1;
};
@@ -995,6 +1422,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_default_ng_led_data;
+ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
return 1;
};
@@ -1012,6 +1440,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
mlxplat_led = &mlxplat_msn21xx_led_data;
+ mlxplat_fan = &mlxplat_default_fan_data;
return 1;
};
@@ -1163,7 +1592,7 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
static int __init mlxplat_init(void)
{
struct mlxplat_priv *priv;
- int i, nr, err;
+ int i, j, nr, err;
if (!dmi_check_system(mlxplat_dmi_table))
return -ENODEV;
@@ -1233,6 +1662,15 @@ static int __init mlxplat_init(void)
goto fail_platform_mux_register;
}
+ /* Set default registers. */
+ for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
+ err = regmap_write(mlxplat_hotplug->regmap,
+ mlxplat_mlxcpld_regmap_default[j].reg,
+ mlxplat_mlxcpld_regmap_default[j].def);
+ if (err)
+ goto fail_platform_mux_register;
+ }
+
/* Add LED driver. */
mlxplat_led->regmap = mlxplat_hotplug->regmap;
priv->pdev_led = platform_device_register_resndata(
@@ -1244,14 +1682,48 @@ static int __init mlxplat_init(void)
goto fail_platform_hotplug_register;
}
+ /* Add registers io access driver. */
+ if (mlxplat_regs_io) {
+ mlxplat_regs_io->regmap = mlxplat_hotplug->regmap;
+ priv->pdev_io_regs = platform_device_register_resndata(
+ &mlxplat_dev->dev, "mlxreg-io",
+ PLATFORM_DEVID_NONE, NULL, 0,
+ mlxplat_regs_io,
+ sizeof(*mlxplat_regs_io));
+ if (IS_ERR(priv->pdev_io_regs)) {
+ err = PTR_ERR(priv->pdev_io_regs);
+ goto fail_platform_led_register;
+ }
+ }
+
+ /* Add FAN driver. */
+ if (mlxplat_fan) {
+ mlxplat_fan->regmap = mlxplat_hotplug->regmap;
+ priv->pdev_fan = platform_device_register_resndata(
+ &mlxplat_dev->dev, "mlxreg-fan",
+ PLATFORM_DEVID_NONE, NULL, 0,
+ mlxplat_fan,
+ sizeof(*mlxplat_fan));
+ if (IS_ERR(priv->pdev_fan)) {
+ err = PTR_ERR(priv->pdev_fan);
+ goto fail_platform_io_regs_register;
+ }
+ }
+
/* Sync registers with hardware. */
regcache_mark_dirty(mlxplat_hotplug->regmap);
err = regcache_sync(mlxplat_hotplug->regmap);
if (err)
- goto fail_platform_led_register;
+ goto fail_platform_fan_register;
return 0;
+fail_platform_fan_register:
+ if (mlxplat_fan)
+ platform_device_unregister(priv->pdev_fan);
+fail_platform_io_regs_register:
+ if (mlxplat_regs_io)
+ platform_device_unregister(priv->pdev_io_regs);
fail_platform_led_register:
platform_device_unregister(priv->pdev_led);
fail_platform_hotplug_register:
@@ -1272,6 +1744,10 @@ static void __exit mlxplat_exit(void)
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
int i;
+ if (priv->pdev_fan)
+ platform_device_unregister(priv->pdev_fan);
+ if (priv->pdev_io_regs)
+ platform_device_unregister(priv->pdev_io_regs);
platform_device_unregister(priv->pdev_led);
platform_device_unregister(priv->pdev_hotplug);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cae9b0595692..fde08a997557 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -57,6 +57,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/delay.h>
@@ -335,6 +336,7 @@ static struct {
u32 second_fan:1;
u32 beep_needs_two_args:1;
u32 mixer_no_level_control:1;
+ u32 battery_force_primary:1;
u32 input_device_registered:1;
u32 platform_drv_registered:1;
u32 platform_drv_attrs_registered:1;
@@ -343,7 +345,6 @@ static struct {
u32 sensors_pdev_attrs_registered:1;
u32 hotkey_poll_active:1;
u32 has_adaptive_kbd:1;
- u32 battery:1;
} tp_features;
static struct {
@@ -358,9 +359,9 @@ struct thinkpad_id_data {
char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
char *ec_version_str; /* Something like 1ZHT51WW-1.04a */
- u16 bios_model; /* 1Y = 0x5931, 0 = unknown */
- u16 ec_model;
- u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */
+ u32 bios_model; /* 1Y = 0x3159, 0 = unknown */
+ u32 ec_model;
+ u16 bios_release; /* 1ZETK1WW = 0x4b31, 0 = unknown */
u16 ec_release;
char *model_str; /* ThinkPad T43 */
@@ -444,17 +445,20 @@ do { \
/*
* Quirk handling helpers
*
- * ThinkPad IDs and versions seen in the field so far
- * are two-characters from the set [0-9A-Z], i.e. base 36.
+ * ThinkPad IDs and versions seen in the field so far are
+ * two or three characters from the set [0-9A-Z], i.e. base 36.
*
* We use values well outside that range as specials.
*/
-#define TPACPI_MATCH_ANY 0xffffU
+#define TPACPI_MATCH_ANY 0xffffffffU
+#define TPACPI_MATCH_ANY_VERSION 0xffffU
#define TPACPI_MATCH_UNKNOWN 0U
-/* TPID('1', 'Y') == 0x5931 */
-#define TPID(__c1, __c2) (((__c2) << 8) | (__c1))
+/* TPID('1', 'Y') == 0x3159 */
+#define TPID(__c1, __c2) (((__c1) << 8) | (__c2))
+#define TPID3(__c1, __c2, __c3) (((__c1) << 16) | ((__c2) << 8) | (__c3))
+#define TPVER TPID
#define TPACPI_Q_IBM(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_IBM, \
@@ -468,6 +472,12 @@ do { \
.ec = TPACPI_MATCH_ANY, \
.quirks = (__quirk) }
+#define TPACPI_Q_LNV3(__id1, __id2, __id3, __quirk) \
+ { .vendor = PCI_VENDOR_ID_LENOVO, \
+ .bios = TPID3(__id1, __id2, __id3), \
+ .ec = TPACPI_MATCH_ANY, \
+ .quirks = (__quirk) }
+
#define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
{ .vendor = PCI_VENDOR_ID_LENOVO, \
.bios = TPACPI_MATCH_ANY, \
@@ -476,8 +486,8 @@ do { \
struct tpacpi_quirk {
unsigned int vendor;
- u16 bios;
- u16 ec;
+ u32 bios;
+ u32 ec;
unsigned long quirks;
};
@@ -1647,16 +1657,16 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
{ .vendor = (__v), \
.bios = TPID(__id1, __id2), \
.ec = TPACPI_MATCH_ANY, \
- .quirks = TPACPI_MATCH_ANY << 16 \
- | (__bv1) << 8 | (__bv2) }
+ .quirks = TPACPI_MATCH_ANY_VERSION << 16 \
+ | TPVER(__bv1, __bv2) }
#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \
__eid, __ev1, __ev2) \
{ .vendor = (__v), \
.bios = TPID(__bid1, __bid2), \
.ec = __eid, \
- .quirks = (__ev1) << 24 | (__ev2) << 16 \
- | (__bv1) << 8 | (__bv2) }
+ .quirks = TPVER(__ev1, __ev2) << 16 \
+ | TPVER(__bv1, __bv2) }
#define TPV_QI0(__id1, __id2, __bv1, __bv2) \
TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
@@ -1798,7 +1808,7 @@ static void __init tpacpi_check_outdated_fw(void)
/* note that unknown versions are set to 0x0000 and we use that */
if ((bios_version > thinkpad_id.bios_release) ||
(ec_version > thinkpad_id.ec_release &&
- ec_version != TPACPI_MATCH_ANY)) {
+ ec_version != TPACPI_MATCH_ANY_VERSION)) {
/*
* The changelogs would let us track down the exact
* reason, but it is just too much of a pain to track
@@ -1928,7 +1938,7 @@ enum { /* hot key scan codes (derived from ACPI DSDT) */
/* first new observed key (star, favorites) is 0x1311 */
TP_ACPI_HOTKEYSCAN_STAR = 69,
TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL2,
- TP_ACPI_HOTKEYSCAN_UNK25,
+ TP_ACPI_HOTKEYSCAN_CALCULATOR,
TP_ACPI_HOTKEYSCAN_BLUETOOTH,
TP_ACPI_HOTKEYSCAN_KEYBOARD,
@@ -3449,7 +3459,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
KEY_FAVORITES, /* Favorite app, 0x311 */
KEY_RESERVED, /* Clipping tool */
- KEY_RESERVED,
+ KEY_CALC, /* Calculator (above numpad, P52) */
KEY_BLUETOOTH, /* Bluetooth */
KEY_KEYBOARD /* Keyboard, 0x315 */
},
@@ -9365,7 +9375,9 @@ static int tpacpi_battery_probe(int battery)
{
int ret = 0;
- memset(&battery_info, 0, sizeof(struct tpacpi_battery_driver_data));
+ memset(&battery_info.batteries[battery], 0,
+ sizeof(battery_info.batteries[battery]));
+
/*
* 1) Get the current start threshold
* 2) Check for support
@@ -9420,7 +9432,8 @@ static int tpacpi_battery_probe(int battery)
static int tpacpi_battery_get_id(const char *battery_name)
{
- if (strcmp(battery_name, "BAT0") == 0)
+ if (strcmp(battery_name, "BAT0") == 0 ||
+ tp_features.battery_force_primary)
return BAT_PRIMARY;
if (strcmp(battery_name, "BAT1") == 0)
return BAT_SECONDARY;
@@ -9596,8 +9609,26 @@ static struct acpi_battery_hook battery_hook = {
/* Subdriver init/exit */
+static const struct tpacpi_quirk battery_quirk_table[] __initconst = {
+ /*
+ * Individual addressing is broken on models that expose the
+ * primary battery as BAT1.
+ */
+ TPACPI_Q_LNV('J', '7', true), /* B5400 */
+ TPACPI_Q_LNV('J', 'I', true), /* Thinkpad 11e */
+ TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
+ TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */
+ TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */
+};
+
static int __init tpacpi_battery_init(struct ibm_init_struct *ibm)
{
+ memset(&battery_info, 0, sizeof(battery_info));
+
+ tp_features.battery_force_primary = tpacpi_check_quirks(
+ battery_quirk_table,
+ ARRAY_SIZE(battery_quirk_table));
+
battery_hook_register(&battery_hook);
return 0;
}
@@ -9808,36 +9839,37 @@ err_out:
/* Probing */
-static bool __pure __init tpacpi_is_fw_digit(const char c)
+static char __init tpacpi_parse_fw_id(const char * const s,
+ u32 *model, u16 *release)
{
- return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
-}
+ int i;
+
+ if (!s || strlen(s) < 8)
+ goto invalid;
+
+ for (i = 0; i < 8; i++)
+ if (!((s[i] >= '0' && s[i] <= '9') ||
+ (s[i] >= 'A' && s[i] <= 'Z')))
+ goto invalid;
-static bool __pure __init tpacpi_is_valid_fw_id(const char * const s,
- const char t)
-{
/*
* Most models: xxyTkkWW (#.##c)
* Ancient 570/600 and -SL lacks (#.##c)
*/
- if (s && strlen(s) >= 8 &&
- tpacpi_is_fw_digit(s[0]) &&
- tpacpi_is_fw_digit(s[1]) &&
- s[2] == t &&
- (s[3] == 'T' || s[3] == 'N') &&
- tpacpi_is_fw_digit(s[4]) &&
- tpacpi_is_fw_digit(s[5]))
- return true;
+ if (s[3] == 'T' || s[3] == 'N') {
+ *model = TPID(s[0], s[1]);
+ *release = TPVER(s[4], s[5]);
+ return s[2];
/* New models: xxxyTkkW (#.##c); T550 and some others */
- return s && strlen(s) >= 8 &&
- tpacpi_is_fw_digit(s[0]) &&
- tpacpi_is_fw_digit(s[1]) &&
- tpacpi_is_fw_digit(s[2]) &&
- s[3] == t &&
- (s[4] == 'T' || s[4] == 'N') &&
- tpacpi_is_fw_digit(s[5]) &&
- tpacpi_is_fw_digit(s[6]);
+ } else if (s[4] == 'T' || s[4] == 'N') {
+ *model = TPID3(s[0], s[1], s[2]);
+ *release = TPVER(s[5], s[6]);
+ return s[3];
+ }
+
+invalid:
+ return '\0';
}
/* returns 0 - probe ok, or < 0 - probe error.
@@ -9849,6 +9881,7 @@ static int __must_check __init get_thinkpad_model_data(
const struct dmi_device *dev = NULL;
char ec_fw_string[18];
char const *s;
+ char t;
if (!tp)
return -EINVAL;
@@ -9868,15 +9901,11 @@ static int __must_check __init get_thinkpad_model_data(
return -ENOMEM;
/* Really ancient ThinkPad 240X will fail this, which is fine */
- if (!(tpacpi_is_valid_fw_id(tp->bios_version_str, 'E') ||
- tpacpi_is_valid_fw_id(tp->bios_version_str, 'C')))
+ t = tpacpi_parse_fw_id(tp->bios_version_str,
+ &tp->bios_model, &tp->bios_release);
+ if (t != 'E' && t != 'C')
return 0;
- tp->bios_model = tp->bios_version_str[0]
- | (tp->bios_version_str[1] << 8);
- tp->bios_release = (tp->bios_version_str[4] << 8)
- | tp->bios_version_str[5];
-
/*
* ThinkPad T23 or newer, A31 or newer, R50e or newer,
* X32 or newer, all Z series; Some models must have an
@@ -9895,12 +9924,9 @@ static int __must_check __init get_thinkpad_model_data(
if (!tp->ec_version_str)
return -ENOMEM;
- if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) {
- tp->ec_model = ec_fw_string[0]
- | (ec_fw_string[1] << 8);
- tp->ec_release = (ec_fw_string[4] << 8)
- | ec_fw_string[5];
- } else {
+ t = tpacpi_parse_fw_id(ec_fw_string,
+ &tp->ec_model, &tp->ec_release);
+ if (t != 'H') {
pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
ec_fw_string);
pr_notice("please report this to %s\n",
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index eef76bfa5d73..e366977bda41 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -34,6 +34,7 @@
#define TOSHIBA_ACPI_VERSION "0.24"
#define PROC_INTERFACE_VERSION 1
+#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -1682,7 +1683,7 @@ static const struct file_operations keys_proc_fops = {
.write = keys_proc_write,
};
-static int version_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused version_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION);
seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION);
@@ -1836,6 +1837,7 @@ static ssize_t kbd_backlight_mode_store(struct device *dev,
return ret;
toshiba->kbd_mode = mode;
+ toshiba_acpi->kbd_mode = mode;
/*
* Some laptop models with the second generation backlit
@@ -1852,7 +1854,7 @@ static ssize_t kbd_backlight_mode_store(struct device *dev,
* event via genetlink.
*/
if (toshiba->kbd_type == 2 &&
- !toshiba_acpi->kbd_event_generated)
+ !toshiba->kbd_event_generated)
schedule_work(&kbd_bl_work);
}
@@ -2413,16 +2415,21 @@ static const struct attribute_group toshiba_attr_group = {
static void toshiba_acpi_kbd_bl_work(struct work_struct *work)
{
- struct acpi_device *acpi_dev = toshiba_acpi->acpi_dev;
-
/* Update the sysfs entries */
- if (sysfs_update_group(&acpi_dev->dev.kobj,
+ if (sysfs_update_group(&toshiba_acpi->acpi_dev->dev.kobj,
&toshiba_attr_group))
pr_err("Unable to update sysfs entries\n");
+ /* Notify LED subsystem about keyboard backlight change */
+ if (toshiba_acpi->kbd_type == 2 &&
+ toshiba_acpi->kbd_mode != SCI_KBD_MODE_AUTO)
+ led_classdev_notify_brightness_hw_changed(&toshiba_acpi->kbd_led,
+ (toshiba_acpi->kbd_mode == SCI_KBD_MODE_ON) ?
+ LED_FULL : LED_OFF);
+
/* Emulate the keyboard backlight event */
- acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
- dev_name(&acpi_dev->dev),
+ acpi_bus_generate_netlink_event(toshiba_acpi->acpi_dev->pnp.device_class,
+ dev_name(&toshiba_acpi->acpi_dev->dev),
0x92, 0);
}
@@ -3119,9 +3126,12 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
/*
* Only register the LED if KBD illumination is supported
* and the keyboard backlight operation mode is set to FN-Z
+ * or we detect a second gen keyboard backlight
*/
- if (dev->kbd_illum_supported && dev->kbd_mode == SCI_KBD_MODE_FNZ) {
+ if (dev->kbd_illum_supported &&
+ (dev->kbd_mode == SCI_KBD_MODE_FNZ || dev->kbd_type == 2)) {
dev->kbd_led.name = "toshiba::kbd_backlight";
+ dev->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
dev->kbd_led.max_brightness = 1;
dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
@@ -3237,11 +3247,16 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
pr_info("SATA power event received %x\n", event);
break;
case 0x92: /* Keyboard backlight mode changed */
- toshiba_acpi->kbd_event_generated = true;
+ dev->kbd_event_generated = true;
/* Update sysfs entries */
if (sysfs_update_group(&acpi_dev->dev.kobj,
&toshiba_attr_group))
pr_err("Unable to update sysfs entries\n");
+ /* Notify LED subsystem about keyboard backlight change */
+ if (dev->kbd_type == 2 && dev->kbd_mode != SCI_KBD_MODE_AUTO)
+ led_classdev_notify_brightness_hw_changed(&dev->kbd_led,
+ (dev->kbd_mode == SCI_KBD_MODE_ON) ?
+ LED_FULL : LED_OFF);
break;
case 0x85: /* Unknown */
case 0x8d: /* Unknown */
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
index 853a7ce4601c..cb204f973491 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -1,5 +1,5 @@
/*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
*
* Copyright (c) 2017 Red Hat Inc.
*
@@ -20,95 +20,147 @@
#include <linux/property.h>
#include <linux/string.h>
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
const char *acpi_name;
const struct property_entry *properties;
};
-static const struct property_entry cube_iwork8_air_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+/* NOTE: Please keep all entries sorted alphabetically */
+
+static const struct property_entry chuwi_hi8_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
- PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
{ }
};
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data chuwi_hi8_data = {
+ .acpi_name = "MSSL0001:00",
+ .properties = chuwi_hi8_props,
+};
+
+static const struct property_entry chuwi_hi8_pro_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct ts_dmi_data chuwi_hi8_pro_data = {
.acpi_name = "MSSL1680:00",
- .properties = cube_iwork8_air_props,
+ .properties = chuwi_hi8_pro_props,
};
-static const struct property_entry jumper_ezpad_mini3_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+static const struct property_entry chuwi_vi8_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
- .acpi_name = "MSSL1680:00",
- .properties = jumper_ezpad_mini3_props,
+static const struct ts_dmi_data chuwi_vi8_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = chuwi_vi8_props,
};
-static const struct property_entry jumper_ezpad_6_pro_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
+static const struct property_entry chuwi_vi10_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 0),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 4),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1858),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-vi10.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data jumper_ezpad_6_pro_data = {
+static const struct ts_dmi_data chuwi_vi10_data = {
+ .acpi_name = "MSSL0002:00",
+ .properties = chuwi_vi10_props,
+};
+
+static const struct property_entry connect_tablet9_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 878),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ { }
+};
+
+static const struct ts_dmi_data connect_tablet9_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = connect_tablet9_props,
+};
+
+static const struct property_entry cube_iwork8_air_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ { }
+};
+
+static const struct ts_dmi_data cube_iwork8_air_data = {
.acpi_name = "MSSL1680:00",
- .properties = jumper_ezpad_6_pro_props,
+ .properties = cube_iwork8_air_props,
};
-static const struct property_entry dexp_ursus_7w_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
+static const struct property_entry cube_knote_i1101_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 20),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 22),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1961),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1513),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-cube-knote-i1101.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data dexp_ursus_7w_data = {
+static const struct ts_dmi_data cube_knote_i1101_data = {
.acpi_name = "MSSL1680:00",
- .properties = dexp_ursus_7w_props,
+ .properties = cube_knote_i1101_props,
};
-static const struct property_entry surftab_twin_10_1_st10432_8_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
- PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
- PROPERTY_ENTRY_STRING("firmware-name",
- "gsl3670-surftab-twin-10-1-st10432-8.fw"),
+static const struct property_entry dexp_ursus_7w_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data surftab_twin_10_1_st10432_8_data = {
+static const struct ts_dmi_data dexp_ursus_7w_data = {
.acpi_name = "MSSL1680:00",
- .properties = surftab_twin_10_1_st10432_8_props,
+ .properties = dexp_ursus_7w_props,
};
-static const struct property_entry surftab_wintron70_st70416_6_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
+static const struct property_entry digma_citi_e200_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
PROPERTY_ENTRY_STRING("firmware-name",
- "gsl1686-surftab-wintron70-st70416-6.fw"),
+ "gsl1686-digma_citi_e200.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
+static const struct ts_dmi_data digma_citi_e200_data = {
.acpi_name = "MSSL1680:00",
- .properties = surftab_wintron70_st70416_6_props,
+ .properties = digma_citi_e200_props,
};
static const struct property_entry gp_electronic_t701_props[] = {
@@ -121,162 +173,181 @@ static const struct property_entry gp_electronic_t701_props[] = {
{ }
};
-static const struct silead_ts_dmi_data gp_electronic_t701_data = {
+static const struct ts_dmi_data gp_electronic_t701_data = {
.acpi_name = "MSSL1680:00",
.properties = gp_electronic_t701_props,
};
-static const struct property_entry pipo_w2s_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
- PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+static const struct property_entry itworks_tw891_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name",
- "gsl1680-pipo-w2s.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
{ }
};
-static const struct silead_ts_dmi_data pipo_w2s_data = {
+static const struct ts_dmi_data itworks_tw891_data = {
.acpi_name = "MSSL1680:00",
- .properties = pipo_w2s_props,
+ .properties = itworks_tw891_props,
};
-static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
- PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
- PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name",
- "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
+static const struct property_entry jumper_ezpad_6_pro_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
+static const struct ts_dmi_data jumper_ezpad_6_pro_data = {
.acpi_name = "MSSL1680:00",
- .properties = pov_mobii_wintab_p800w_v20_props,
+ .properties = jumper_ezpad_6_pro_props,
};
-static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
+static const struct property_entry jumper_ezpad_mini3_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name",
- "gsl3692-pov-mobii-wintab-p800w.fw"),
- PROPERTY_ENTRY_BOOL("silead,home-button"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
{ }
};
-static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
+static const struct ts_dmi_data jumper_ezpad_mini3_data = {
.acpi_name = "MSSL1680:00",
- .properties = pov_mobii_wintab_p800w_v21_props,
+ .properties = jumper_ezpad_mini3_props,
};
-static const struct property_entry itworks_tw891_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+static const struct property_entry onda_obook_20_plus_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data itworks_tw891_data = {
+static const struct ts_dmi_data onda_obook_20_plus_data = {
.acpi_name = "MSSL1680:00",
- .properties = itworks_tw891_props,
+ .properties = onda_obook_20_plus_props,
};
-static const struct property_entry chuwi_hi8_pro_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+static const struct property_entry onda_v820w_32g_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl1680-onda-v820w-32g.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data chuwi_hi8_pro_data = {
+static const struct ts_dmi_data onda_v820w_32g_data = {
.acpi_name = "MSSL1680:00",
- .properties = chuwi_hi8_pro_props,
+ .properties = onda_v820w_32g_props,
};
-static const struct property_entry digma_citi_e200_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
- PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+static const struct property_entry onda_v891w_v1_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
PROPERTY_ENTRY_STRING("firmware-name",
- "gsl1686-digma_citi_e200.fw"),
+ "gsl3680-onda-v891w-v1.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data digma_citi_e200_data = {
+static const struct ts_dmi_data onda_v891w_v1_data = {
.acpi_name = "MSSL1680:00",
- .properties = digma_citi_e200_props,
+ .properties = onda_v891w_v1_props,
};
-static const struct property_entry onda_obook_20_plus_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
- PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+static const struct property_entry onda_v891w_v3_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 35),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1625),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1135),
PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
- PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl3676-onda-v891w-v3.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data onda_obook_20_plus_data = {
+static const struct ts_dmi_data onda_v891w_v3_data = {
.acpi_name = "MSSL1680:00",
- .properties = onda_obook_20_plus_props,
+ .properties = onda_v891w_v3_props,
};
-static const struct property_entry chuwi_hi8_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+static const struct property_entry pipo_w2s_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_BOOL("silead,home-button"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl1680-pipo-w2s.fw"),
{ }
};
-static const struct silead_ts_dmi_data chuwi_hi8_data = {
- .acpi_name = "MSSL0001:00",
- .properties = chuwi_hi8_props,
+static const struct ts_dmi_data pipo_w2s_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = pipo_w2s_props,
};
-static const struct property_entry chuwi_vi8_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data chuwi_vi8_data = {
- .acpi_name = "MSSL1680:00",
- .properties = chuwi_vi8_props,
+static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = pov_mobii_wintab_p800w_v20_props,
};
-static const struct property_entry trekstor_primebook_c13_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
+static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
PROPERTY_ENTRY_STRING("firmware-name",
- "gsl1680-trekstor-primebook-c13.fw"),
+ "gsl3692-pov-mobii-wintab-p800w.fw"),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = pov_mobii_wintab_p800w_v21_props,
+};
+
+static const struct property_entry teclast_x3_plus_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data trekstor_primebook_c13_data = {
+static const struct ts_dmi_data teclast_x3_plus_data = {
.acpi_name = "MSSL1680:00",
- .properties = trekstor_primebook_c13_props,
+ .properties = teclast_x3_plus_props,
};
static const struct property_entry teclast_x98plus2_props[] = {
@@ -290,156 +361,162 @@ static const struct property_entry teclast_x98plus2_props[] = {
{ }
};
-static const struct silead_ts_dmi_data teclast_x98plus2_data = {
+static const struct ts_dmi_data teclast_x98plus2_data = {
.acpi_name = "MSSL1680:00",
.properties = teclast_x98plus2_props,
};
-static const struct property_entry teclast_x3_plus_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
- PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"),
+static const struct property_entry trekstor_primebook_c13_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl1680-trekstor-primebook-c13.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data teclast_x3_plus_data = {
+static const struct ts_dmi_data trekstor_primebook_c13_data = {
.acpi_name = "MSSL1680:00",
- .properties = teclast_x3_plus_props,
+ .properties = trekstor_primebook_c13_props,
};
-static const struct property_entry onda_v891w_v1_props[] = {
- PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
- PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
- PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
- PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
+static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+ PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
PROPERTY_ENTRY_STRING("firmware-name",
- "gsl3680-onda-v891w-v1.fw"),
+ "gsl3670-surftab-twin-10-1-st10432-8.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ { }
+};
+
+static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = trekstor_surftab_twin_10_1_props,
+};
+
+static const struct property_entry trekstor_surftab_wintron70_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl1686-surftab-wintron70-st70416-6.fw"),
PROPERTY_ENTRY_U32("silead,max-fingers", 10),
PROPERTY_ENTRY_BOOL("silead,home-button"),
{ }
};
-static const struct silead_ts_dmi_data onda_v891w_v1_data = {
+static const struct ts_dmi_data trekstor_surftab_wintron70_data = {
.acpi_name = "MSSL1680:00",
- .properties = onda_v891w_v1_props,
+ .properties = trekstor_surftab_wintron70_props,
};
-static const struct dmi_system_id silead_ts_dmi_table[] = {
+/* NOTE: Please keep this table sorted alphabetically */
+static const struct dmi_system_id touchscreen_dmi_table[] = {
{
- /* CUBE iwork8 Air */
- .driver_data = (void *)&cube_iwork8_air_data,
+ /* Chuwi Hi8 */
+ .driver_data = (void *)&chuwi_hi8_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "cube"),
- DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
- DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
},
},
{
- /* Jumper EZpad mini3 */
- .driver_data = (void *)&jumper_ezpad_mini3_data,
+ /* Chuwi Hi8 (H1D_S806_206) */
+ .driver_data = (void *)&chuwi_hi8_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- /* jumperx.T87.KFBNEEA02 with the version-nr dropped */
- DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
},
},
{
- /* Jumper EZpad 6 Pro */
- .driver_data = (void *)&jumper_ezpad_6_pro_data,
+ /* Chuwi Hi8 Pro (CWI513) */
+ .driver_data = (void *)&chuwi_hi8_pro_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
- DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
- DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
- /* Above matches are too generic, add bios-date match */
- DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
},
},
{
- /* DEXP Ursus 7W */
- .driver_data = (void *)&dexp_ursus_7w_data,
+ /* Chuwi Vi8 (CWI506) */
+ .driver_data = (void *)&chuwi_vi8_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
+ DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
},
},
{
- /* TrekStor SurfTab twin 10.1 ST10432-8 */
- .driver_data = (void *)&surftab_twin_10_1_st10432_8_data,
+ /* Chuwi Vi10 (CWI505) */
+ .driver_data = (void *)&chuwi_vi10_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
- DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "S165"),
},
},
{
- /* Trekstor Surftab Wintron 7.0 ST70416-6 */
- .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+ /* Connect Tablet 9 */
+ .driver_data = (void *)&connect_tablet9_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
- /* Exact match, different versions need different fw */
- DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Connect"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),
},
},
{
- /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */
- .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+ /* CUBE iwork8 Air */
+ .driver_data = (void *)&cube_iwork8_air_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
- DMI_MATCH(DMI_PRODUCT_NAME,
- "SurfTab wintron 7.0 ST70416-6"),
- /* Exact match, different versions need different fw */
- DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
+ DMI_MATCH(DMI_SYS_VENDOR, "cube"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
+ DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
},
},
{
- /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
- .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+ /* Cube KNote i1101 */
+ .driver_data = (void *)&cube_knote_i1101_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"),
- DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"),
- /* Exact match, different versions need different fw */
- DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+ DMI_MATCH(DMI_BOARD_NAME, "L1W6_I1101"),
+ DMI_MATCH(DMI_SYS_VENDOR, "ALLDOCUBE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "i1101"),
},
},
{
- /* GP-electronic T701 */
- .driver_data = (void *)&gp_electronic_t701_data,
+ /* DEXP Ursus 7W */
+ .driver_data = (void *)&dexp_ursus_7w_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
- DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
},
},
{
- /* Pipo W2S */
- .driver_data = (void *)&pipo_w2s_data,
+ /* Digma Citi E200 */
+ .driver_data = (void *)&digma_citi_e200_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
- DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Digma"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"),
+ DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
},
},
{
- /* Point of View mobii wintab p800w (v2.0) */
- .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
+ /* GP-electronic T701 */
+ .driver_data = (void *)&gp_electronic_t701_data,
.matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
- DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
- /* Above matches are too generic, add bios-date match */
- DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
+ DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
},
},
{
- /* Point of View mobii wintab p800w (v2.1) */
- .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
+ /* I.T.Works TW701 (same hardware as the Trekstor ST70416-6) */
+ .driver_data = (void *)&trekstor_surftab_wintron70_data,
.matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
- DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
- /* Above matches are too generic, add bios-date match */
- DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
+ DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
},
},
{
@@ -451,20 +528,23 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
- /* Chuwi Hi8 Pro */
- .driver_data = (void *)&chuwi_hi8_pro_data,
+ /* Jumper EZpad 6 Pro */
+ .driver_data = (void *)&jumper_ezpad_6_pro_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
- DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+ DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
},
},
{
- /* Digma Citi E200 */
- .driver_data = (void *)&digma_citi_e200_data,
+ /* Jumper EZpad mini3 */
+ .driver_data = (void *)&jumper_ezpad_mini3_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Digma"),
- DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"),
- DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ /* jumperx.T87.KFBNEEA02 with the version-nr dropped */
+ DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
},
},
{
@@ -476,45 +556,71 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
- /* Chuwi Hi8 */
- .driver_data = (void *)&chuwi_hi8_data,
+ /* ONDA V820w DualOS */
+ .driver_data = (void *)&onda_v820w_32g_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
- DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V820w DualOS")
},
},
{
- /* Chuwi Hi8 (H1D_S806_206) */
- .driver_data = (void *)&chuwi_hi8_data,
+ /* ONDA V891w revision P891WBEBV1B00 aka v1 */
+ .driver_data = (void *)&onda_v891w_v1_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
- DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
+ DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
+ /* Exact match, different versions need different fw */
+ DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
},
},
{
- /* Chuwi Vi8 (CWI506) */
- .driver_data = (void *)&chuwi_vi8_data,
+ /* ONDA V891w Dual OS P891DCF2V1A01274 64GB */
+ .driver_data = (void *)&onda_v891w_v3_data,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
- DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ONDA Tablet"),
+ DMI_MATCH(DMI_BIOS_VERSION, "ONDA.D890HBBNR0A"),
},
},
{
- /* Trekstor Primebook C13 */
- .driver_data = (void *)&trekstor_primebook_c13_data,
+ /* Pipo W2S */
+ .driver_data = (void *)&pipo_w2s_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
+ DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
},
},
{
- /* Teclast X98 Plus II */
- .driver_data = (void *)&teclast_x98plus2_data,
+ /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
+ .driver_data = (void *)&trekstor_surftab_wintron70_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
- DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"),
+ /* Exact match, different versions need different fw */
+ DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"),
+ },
+ },
+ {
+ /* Point of View mobii wintab p800w (v2.0) */
+ .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
+ },
+ },
+ {
+ /* Point of View mobii wintab p800w (v2.1) */
+ .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
},
},
{
@@ -527,52 +633,77 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
- /* I.T.Works TW701 */
- .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+ /* Teclast X98 Plus II */
+ .driver_data = (void *)&teclast_x98plus2_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
- DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
- DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
+ DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
},
},
{
- /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
- .driver_data = (void *)&chuwi_vi8_data,
+ /* Trekstor Primebook C13 */
+ .driver_data = (void *)&trekstor_primebook_c13_data,
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
+ DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
},
},
{
- /* ONDA V891w revision P891WBEBV1B00 aka v1 */
- .driver_data = (void *)&onda_v891w_v1_data,
+ /* TrekStor SurfTab twin 10.1 ST10432-8 */
+ .driver_data = (void *)&trekstor_surftab_twin_10_1_data,
.matches = {
- DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
- DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
- DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
+ DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"),
+ },
+ },
+ {
+ /* Trekstor Surftab Wintron 7.0 ST70416-6 */
+ .driver_data = (void *)&trekstor_surftab_wintron70_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
/* Exact match, different versions need different fw */
- DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
+ DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
+ },
+ },
+ {
+ /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */
+ .driver_data = (void *)&trekstor_surftab_wintron70_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
+ DMI_MATCH(DMI_PRODUCT_NAME,
+ "SurfTab wintron 7.0 ST70416-6"),
+ /* Exact match, different versions need different fw */
+ DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
+ },
+ },
+ {
+ /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
+ .driver_data = (void *)&chuwi_vi8_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
{ },
};
-static const struct silead_ts_dmi_data *silead_ts_data;
+static const struct ts_dmi_data *ts_data;
-static void silead_ts_dmi_add_props(struct i2c_client *client)
+static void ts_dmi_add_props(struct i2c_client *client)
{
struct device *dev = &client->dev;
int error;
if (has_acpi_companion(dev) &&
- !strncmp(silead_ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
- error = device_add_properties(dev, silead_ts_data->properties);
+ !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
+ error = device_add_properties(dev, ts_data->properties);
if (error)
dev_err(dev, "failed to add properties: %d\n", error);
}
}
-static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
+static int ts_dmi_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
@@ -582,7 +713,7 @@ static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
case BUS_NOTIFY_ADD_DEVICE:
client = i2c_verify_client(dev);
if (client)
- silead_ts_dmi_add_props(client);
+ ts_dmi_add_props(client);
break;
default:
@@ -592,22 +723,22 @@ static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
return 0;
}
-static struct notifier_block silead_ts_dmi_notifier = {
- .notifier_call = silead_ts_dmi_notifier_call,
+static struct notifier_block ts_dmi_notifier = {
+ .notifier_call = ts_dmi_notifier_call,
};
-static int __init silead_ts_dmi_init(void)
+static int __init ts_dmi_init(void)
{
const struct dmi_system_id *dmi_id;
int error;
- dmi_id = dmi_first_match(silead_ts_dmi_table);
+ dmi_id = dmi_first_match(touchscreen_dmi_table);
if (!dmi_id)
return 0; /* Not an error */
- silead_ts_data = dmi_id->driver_data;
+ ts_data = dmi_id->driver_data;
- error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier);
+ error = bus_register_notifier(&i2c_bus_type, &ts_dmi_notifier);
if (error)
pr_err("%s: failed to register i2c bus notifier: %d\n",
__func__, error);
@@ -620,4 +751,4 @@ static int __init silead_ts_dmi_init(void)
* itself is ready (which happens at postcore initcall level), but before
* ACPI starts enumerating devices (at subsys initcall level).
*/
-arch_initcall(silead_ts_dmi_init);
+arch_initcall(ts_dmi_init);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 8e3d0146ff8c..04791ea5d97b 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -895,7 +895,6 @@ static int wmi_dev_probe(struct device *dev)
struct wmi_driver *wdriver =
container_of(dev->driver, struct wmi_driver, driver);
int ret = 0;
- int count;
char *buf;
if (ACPI_FAILURE(wmi_method_enable(wblock, 1)))
@@ -917,9 +916,8 @@ static int wmi_dev_probe(struct device *dev)
goto probe_failure;
}
- count = get_order(wblock->req_buf_size);
- wblock->handler_data = (void *)__get_free_pages(GFP_KERNEL,
- count);
+ wblock->handler_data = kmalloc(wblock->req_buf_size,
+ GFP_KERNEL);
if (!wblock->handler_data) {
ret = -ENOMEM;
goto probe_failure;
@@ -964,8 +962,7 @@ static int wmi_dev_remove(struct device *dev)
if (wdriver->filter_callback) {
misc_deregister(&wblock->char_dev);
kfree(wblock->char_dev.name);
- free_pages((unsigned long)wblock->handler_data,
- get_order(wblock->req_buf_size));
+ kfree(wblock->handler_data);
}
if (wdriver->remove)
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index df58fc878b3e..6533aa560aa1 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -104,6 +104,17 @@ config POWER_RESET_MSM
help
Power off and restart support for Qualcomm boards.
+config POWER_RESET_QCOM_PON
+ tristate "Qualcomm power-on driver"
+ depends on ARCH_QCOM
+ depends on MFD_SPMI_PMIC
+ select REBOOT_MODE
+ help
+ Power On support for Qualcomm boards.
+ If you have a Qualcomm platform and need support for
+ power-on and reboot reason, Say Y.
+ If unsure, Say N.
+
config POWER_RESET_OCELOT_RESET
bool "Microsemi Ocelot reset driver"
depends on MSCC_OCELOT || COMPILE_TEST
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 7778c7485cf1..0aebee954ac1 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
+obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
diff --git a/drivers/power/reset/gemini-poweroff.c b/drivers/power/reset/gemini-poweroff.c
index 2ac291af1265..90e35c07240a 100644
--- a/drivers/power/reset/gemini-poweroff.c
+++ b/drivers/power/reset/gemini-poweroff.c
@@ -130,7 +130,17 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
val |= GEMINI_CTRL_ENABLE;
writel(val, gpw->base + GEMINI_PWC_CTRLREG);
- /* Now that the state machine is active, clear the IRQ */
+ /* Clear the IRQ */
+ val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+ val |= GEMINI_CTRL_IRQ_CLR;
+ writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+ /* Wait for this to clear */
+ val = readl(gpw->base + GEMINI_PWC_STATREG);
+ while (val & 0x70U)
+ val = readl(gpw->base + GEMINI_PWC_STATREG);
+
+ /* Clear the IRQ again */
val = readl(gpw->base + GEMINI_PWC_CTRLREG);
val |= GEMINI_CTRL_IRQ_CLR;
writel(val, gpw->base + GEMINI_PWC_CTRLREG);
diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c
new file mode 100644
index 000000000000..0c4caaa7e88f
--- /dev/null
+++ b/drivers/power/reset/qcom-pon.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-18 Linaro Limited
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/reboot-mode.h>
+#include <linux/regmap.h>
+
+#define PON_SOFT_RB_SPARE 0x8f
+
+struct pm8916_pon {
+ struct device *dev;
+ struct regmap *regmap;
+ u32 baseaddr;
+ struct reboot_mode_driver reboot_mode;
+};
+
+static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot,
+ unsigned int magic)
+{
+ struct pm8916_pon *pon = container_of
+ (reboot, struct pm8916_pon, reboot_mode);
+ int ret;
+
+ ret = regmap_update_bits(pon->regmap,
+ pon->baseaddr + PON_SOFT_RB_SPARE,
+ 0xfc, magic << 2);
+ if (ret < 0)
+ dev_err(pon->dev, "update reboot mode bits failed\n");
+
+ return ret;
+}
+
+static int pm8916_pon_probe(struct platform_device *pdev)
+{
+ struct pm8916_pon *pon;
+ int error;
+
+ pon = devm_kzalloc(&pdev->dev, sizeof(*pon), GFP_KERNEL);
+ if (!pon)
+ return -ENOMEM;
+
+ pon->dev = &pdev->dev;
+
+ pon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!pon->regmap) {
+ dev_err(&pdev->dev, "failed to locate regmap\n");
+ return -ENODEV;
+ }
+
+ error = of_property_read_u32(pdev->dev.of_node, "reg",
+ &pon->baseaddr);
+ if (error)
+ return error;
+
+ pon->reboot_mode.dev = &pdev->dev;
+ pon->reboot_mode.write = pm8916_reboot_mode_write;
+ error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode);
+ if (error) {
+ dev_err(&pdev->dev, "can't register reboot mode\n");
+ return error;
+ }
+
+ platform_set_drvdata(pdev, pon);
+
+ return devm_of_platform_populate(&pdev->dev);
+}
+
+static const struct of_device_id pm8916_pon_id_table[] = {
+ { .compatible = "qcom,pm8916-pon" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pm8916_pon_id_table);
+
+static struct platform_driver pm8916_pon_driver = {
+ .probe = pm8916_pon_probe,
+ .driver = {
+ .name = "pm8916-pon",
+ .of_match_table = of_match_ptr(pm8916_pon_id_table),
+ },
+};
+module_platform_driver(pm8916_pon_driver);
+
+MODULE_DESCRIPTION("pm8916 Power On driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
index 102f95a09460..e9e749f87517 100644
--- a/drivers/power/reset/vexpress-poweroff.c
+++ b/drivers/power/reset/vexpress-poweroff.c
@@ -35,6 +35,7 @@ static void vexpress_reset_do(struct device *dev, const char *what)
}
static struct device *vexpress_power_off_device;
+static atomic_t vexpress_restart_nb_refcnt = ATOMIC_INIT(0);
static void vexpress_power_off(void)
{
@@ -99,10 +100,13 @@ static int _vexpress_register_restart_handler(struct device *dev)
int err;
vexpress_restart_device = dev;
- err = register_restart_handler(&vexpress_restart_nb);
- if (err) {
- dev_err(dev, "cannot register restart handler (err=%d)\n", err);
- return err;
+ if (atomic_inc_return(&vexpress_restart_nb_refcnt) == 1) {
+ err = register_restart_handler(&vexpress_restart_nb);
+ if (err) {
+ dev_err(dev, "cannot register restart handler (err=%d)\n", err);
+ atomic_dec(&vexpress_restart_nb_refcnt);
+ return err;
+ }
}
device_create_file(dev, &dev_attr_active);
diff --git a/drivers/power/reset/zx-reboot.c b/drivers/power/reset/zx-reboot.c
index c03e96e6a041..186901c96c01 100644
--- a/drivers/power/reset/zx-reboot.c
+++ b/drivers/power/reset/zx-reboot.c
@@ -51,6 +51,7 @@ static int zx_reboot_probe(struct platform_device *pdev)
np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
pcu_base = of_iomap(np, 0);
+ of_node_put(np);
if (!pcu_base) {
iounmap(base);
WARN(1, "failed to map pcu_base address");
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index 428b426842f4..ff6dab0bf0dd 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -75,6 +75,17 @@ config BATTERY_88PM860X
help
Say Y here to enable battery monitor for Marvell 88PM860x chip.
+config CHARGER_ADP5061
+ tristate "ADP5061 battery charger driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say Y here to enable support for the ADP5061 standalone battery
+ charger.
+
+ This driver can be built as a module. If so, the module will be
+ called adp5061.
+
config BATTERY_ACT8945A
tristate "Active-semi ACT8945A charger driver"
depends on MFD_ACT8945A || COMPILE_TEST
@@ -92,7 +103,7 @@ config BATTERY_CPCAP
config BATTERY_DS2760
tristate "DS2760 battery driver (HP iPAQ & others)"
- depends on W1 && W1_SLAVE_DS2760
+ depends on W1
help
Say Y here to enable support for batteries with ds2760 chip.
@@ -624,4 +635,14 @@ config CHARGER_RT9455
help
Say Y to enable support for Richtek RT9455 battery charger.
+config CHARGER_CROS_USBPD
+ tristate "ChromeOS EC based USBPD charger"
+ depends on MFD_CROS_EC
+ default n
+ help
+ Say Y here to enable ChromeOS EC based USBPD charger
+ driver. This driver gets various bits of information about
+ what is connected to USB PD ports from the EC and converts
+ that into power_supply properties.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index e83aa843bcc6..a26b402c45d9 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
obj-$(CONFIG_TEST_POWER) += test_power.o
obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
+obj-$(CONFIG_CHARGER_ADP5061) += adp5061.o
obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
obj-$(CONFIG_BATTERY_AXP20X) += axp20x_battery.o
obj-$(CONFIG_CHARGER_AXP20X) += axp20x_ac_power.o
@@ -83,3 +84,4 @@ obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index d9c6c7bedd85..02356f9b5f22 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -379,15 +379,13 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
*/
static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
{
- struct timespec64 ts64;
+ time64_t now = ktime_get_boottime_seconds();
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
- getnstimeofday64(&ts64);
-
do {
avg->sum += sample - avg->samples[avg->pos];
avg->samples[avg->pos] = sample;
- avg->time_stamps[avg->pos] = ts64.tv_sec;
+ avg->time_stamps[avg->pos] = now;
avg->pos++;
if (avg->pos == NBR_AVG_SAMPLES)
@@ -400,7 +398,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
* Check the time stamp for each sample. If too old,
* replace with latest sample
*/
- } while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
+ } while (now - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
avg->avg = avg->sum / avg->nbr_samples;
@@ -439,14 +437,14 @@ static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
{
int i;
- struct timespec64 ts64;
+ time64_t now;
struct ab8500_fg_avg_cap *avg = &di->avg_cap;
- getnstimeofday64(&ts64);
+ now = ktime_get_boottime_seconds();
for (i = 0; i < NBR_AVG_SAMPLES; i++) {
avg->samples[i] = sample;
- avg->time_stamps[i] = ts64.tv_sec;
+ avg->time_stamps[i] = now;
}
avg->pos = 0;
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
new file mode 100644
index 000000000000..939fd3d8fb1a
--- /dev/null
+++ b/drivers/power/supply/adp5061.c
@@ -0,0 +1,745 @@
+/*
+ * ADP5061 I2C Programmable Linear Battery Charger
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/mod_devicetable.h>
+#include <linux/power_supply.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+/* ADP5061 registers definition */
+#define ADP5061_ID 0x00
+#define ADP5061_REV 0x01
+#define ADP5061_VINX_SET 0x02
+#define ADP5061_TERM_SET 0x03
+#define ADP5061_CHG_CURR 0x04
+#define ADP5061_VOLTAGE_TH 0x05
+#define ADP5061_TIMER_SET 0x06
+#define ADP5061_FUNC_SET_1 0x07
+#define ADP5061_FUNC_SET_2 0x08
+#define ADP5061_INT_EN 0x09
+#define ADP5061_INT_ACT 0x0A
+#define ADP5061_CHG_STATUS_1 0x0B
+#define ADP5061_CHG_STATUS_2 0x0C
+#define ADP5061_FAULT 0x0D
+#define ADP5061_BATTERY_SHORT 0x10
+#define ADP5061_IEND 0x11
+
+/* ADP5061_VINX_SET */
+#define ADP5061_VINX_SET_ILIM_MSK GENMASK(3, 0)
+#define ADP5061_VINX_SET_ILIM_MODE(x) (((x) & 0x0F) << 0)
+
+/* ADP5061_TERM_SET */
+#define ADP5061_TERM_SET_VTRM_MSK GENMASK(7, 2)
+#define ADP5061_TERM_SET_VTRM_MODE(x) (((x) & 0x3F) << 2)
+#define ADP5061_TERM_SET_CHG_VLIM_MSK GENMASK(1, 0)
+#define ADP5061_TERM_SET_CHG_VLIM_MODE(x) (((x) & 0x03) << 0)
+
+/* ADP5061_CHG_CURR */
+#define ADP5061_CHG_CURR_ICHG_MSK GENMASK(6, 2)
+#define ADP5061_CHG_CURR_ICHG_MODE(x) (((x) & 0x1F) << 2)
+#define ADP5061_CHG_CURR_ITRK_DEAD_MSK GENMASK(1, 0)
+#define ADP5061_CHG_CURR_ITRK_DEAD_MODE(x) (((x) & 0x03) << 0)
+
+/* ADP5061_VOLTAGE_TH */
+#define ADP5061_VOLTAGE_TH_DIS_RCH_MSK BIT(7)
+#define ADP5061_VOLTAGE_TH_DIS_RCH_MODE(x) (((x) & 0x01) << 7)
+#define ADP5061_VOLTAGE_TH_VRCH_MSK GENMASK(6, 5)
+#define ADP5061_VOLTAGE_TH_VRCH_MODE(x) (((x) & 0x03) << 5)
+#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK GENMASK(4, 3)
+#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(x) (((x) & 0x03) << 3)
+#define ADP5061_VOLTAGE_TH_VWEAK_MSK GENMASK(2, 0)
+#define ADP5061_VOLTAGE_TH_VWEAK_MODE(x) (((x) & 0x07) << 0)
+
+/* ADP5061_CHG_STATUS_1 */
+#define ADP5061_CHG_STATUS_1_VIN_OV(x) (((x) >> 7) & 0x1)
+#define ADP5061_CHG_STATUS_1_VIN_OK(x) (((x) >> 6) & 0x1)
+#define ADP5061_CHG_STATUS_1_VIN_ILIM(x) (((x) >> 5) & 0x1)
+#define ADP5061_CHG_STATUS_1_THERM_LIM(x) (((x) >> 4) & 0x1)
+#define ADP5061_CHG_STATUS_1_CHDONE(x) (((x) >> 3) & 0x1)
+#define ADP5061_CHG_STATUS_1_CHG_STATUS(x) (((x) >> 0) & 0x7)
+
+/* ADP5061_CHG_STATUS_2 */
+#define ADP5061_CHG_STATUS_2_THR_STATUS(x) (((x) >> 5) & 0x7)
+#define ADP5061_CHG_STATUS_2_RCH_LIM_INFO(x) (((x) >> 3) & 0x1)
+#define ADP5061_CHG_STATUS_2_BAT_STATUS(x) (((x) >> 0) & 0x7)
+
+/* ADP5061_IEND */
+#define ADP5061_IEND_IEND_MSK GENMASK(7, 5)
+#define ADP5061_IEND_IEND_MODE(x) (((x) & 0x07) << 5)
+
+#define ADP5061_NO_BATTERY 0x01
+#define ADP5061_ICHG_MAX 1300 // mA
+
+enum adp5061_chg_status {
+ ADP5061_CHG_OFF,
+ ADP5061_CHG_TRICKLE,
+ ADP5061_CHG_FAST_CC,
+ ADP5061_CHG_FAST_CV,
+ ADP5061_CHG_COMPLETE,
+ ADP5061_CHG_LDO_MODE,
+ ADP5061_CHG_TIMER_EXP,
+ ADP5061_CHG_BAT_DET,
+};
+
+static const int adp5061_chg_type[4] = {
+ [ADP5061_CHG_OFF] = POWER_SUPPLY_CHARGE_TYPE_NONE,
+ [ADP5061_CHG_TRICKLE] = POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+ [ADP5061_CHG_FAST_CC] = POWER_SUPPLY_CHARGE_TYPE_FAST,
+ [ADP5061_CHG_FAST_CV] = POWER_SUPPLY_CHARGE_TYPE_FAST,
+};
+
+static const int adp5061_vweak_th[8] = {
+ 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400,
+};
+
+static const int adp5061_prechg_current[4] = {
+ 5, 10, 20, 80,
+};
+
+static const int adp5061_vmin[4] = {
+ 2000, 2500, 2600, 2900,
+};
+
+static const int adp5061_const_chg_vmax[4] = {
+ 3200, 3400, 3700, 3800,
+};
+
+static const int adp5061_const_ichg[24] = {
+ 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650,
+ 700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1200, 1300,
+};
+
+static const int adp5061_vmax[36] = {
+ 3800, 3820, 3840, 3860, 3880, 3900, 3920, 3940, 3960, 3980,
+ 4000, 4020, 4040, 4060, 4080, 4100, 4120, 4140, 4160, 4180,
+ 4200, 4220, 4240, 4260, 4280, 4300, 4320, 4340, 4360, 4380,
+ 4400, 4420, 4440, 4460, 4480, 4500,
+};
+
+static const int adp5061_in_current_lim[16] = {
+ 100, 150, 200, 250, 300, 400, 500, 600, 700,
+ 800, 900, 1000, 1200, 1500, 1800, 2100,
+};
+
+static const int adp5061_iend[8] = {
+ 12500, 32500, 52500, 72500, 92500, 117500, 142500, 170000,
+};
+
+struct adp5061_state {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct power_supply *psy;
+};
+
+static int adp5061_get_array_index(const int *array, u8 size, int val)
+{
+ int i;
+
+ for (i = 1; i < size; i++) {
+ if (val < array[i])
+ break;
+ }
+
+ return i-1;
+}
+
+static int adp5061_get_status(struct adp5061_state *st,
+ u8 *status1, u8 *status2)
+{
+ u8 buf[2];
+ int ret;
+
+ /* CHG_STATUS1 and CHG_STATUS2 are adjacent regs */
+ ret = regmap_bulk_read(st->regmap, ADP5061_CHG_STATUS_1,
+ &buf[0], 2);
+ if (ret < 0)
+ return ret;
+
+ *status1 = buf[0];
+ *status2 = buf[1];
+
+ return ret;
+}
+
+static int adp5061_get_input_current_limit(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int mode, ret;
+
+ ret = regmap_read(st->regmap, ADP5061_VINX_SET, &regval);
+ if (ret < 0)
+ return ret;
+
+ mode = ADP5061_VINX_SET_ILIM_MODE(regval);
+ val->intval = adp5061_in_current_lim[mode] * 1000;
+
+ return ret;
+}
+
+static int adp5061_set_input_current_limit(struct adp5061_state *st, int val)
+{
+ int index;
+
+ /* Convert from uA to mA */
+ val /= 1000;
+ index = adp5061_get_array_index(adp5061_in_current_lim,
+ ARRAY_SIZE(adp5061_in_current_lim),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_VINX_SET,
+ ADP5061_VINX_SET_ILIM_MSK,
+ ADP5061_VINX_SET_ILIM_MODE(index));
+}
+
+static int adp5061_set_min_voltage(struct adp5061_state *st, int val)
+{
+ int index;
+
+ /* Convert from uV to mV */
+ val /= 1000;
+ index = adp5061_get_array_index(adp5061_vmin,
+ ARRAY_SIZE(adp5061_vmin),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
+ ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK,
+ ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(index));
+}
+
+static int adp5061_get_min_voltage(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval = ((regval & ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK) >> 3);
+ val->intval = adp5061_vmin[regval] * 1000;
+
+ return ret;
+}
+
+static int adp5061_get_chg_volt_lim(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int mode, ret;
+
+ ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
+ if (ret < 0)
+ return ret;
+
+ mode = ADP5061_TERM_SET_CHG_VLIM_MODE(regval);
+ val->intval = adp5061_const_chg_vmax[mode] * 1000;
+
+ return ret;
+}
+
+static int adp5061_get_max_voltage(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval = ((regval & ADP5061_TERM_SET_VTRM_MSK) >> 2) - 0x0F;
+ if (regval >= ARRAY_SIZE(adp5061_vmax))
+ regval = ARRAY_SIZE(adp5061_vmax) - 1;
+
+ val->intval = adp5061_vmax[regval] * 1000;
+
+ return ret;
+}
+
+static int adp5061_set_max_voltage(struct adp5061_state *st, int val)
+{
+ int vmax_index;
+
+ /* Convert from uV to mV */
+ val /= 1000;
+ if (val > 4500)
+ val = 4500;
+
+ vmax_index = adp5061_get_array_index(adp5061_vmax,
+ ARRAY_SIZE(adp5061_vmax), val);
+ if (vmax_index < 0)
+ return vmax_index;
+
+ vmax_index += 0x0F;
+
+ return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
+ ADP5061_TERM_SET_VTRM_MSK,
+ ADP5061_TERM_SET_VTRM_MODE(vmax_index));
+}
+
+static int adp5061_set_const_chg_vmax(struct adp5061_state *st, int val)
+{
+ int index;
+
+ /* Convert from uV to mV */
+ val /= 1000;
+ index = adp5061_get_array_index(adp5061_const_chg_vmax,
+ ARRAY_SIZE(adp5061_const_chg_vmax),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
+ ADP5061_TERM_SET_CHG_VLIM_MSK,
+ ADP5061_TERM_SET_CHG_VLIM_MODE(index));
+}
+
+static int adp5061_set_const_chg_current(struct adp5061_state *st, int val)
+{
+
+ int index;
+
+ /* Convert from uA to mA */
+ val /= 1000;
+ if (val > ADP5061_ICHG_MAX)
+ val = ADP5061_ICHG_MAX;
+
+ index = adp5061_get_array_index(adp5061_const_ichg,
+ ARRAY_SIZE(adp5061_const_ichg),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
+ ADP5061_CHG_CURR_ICHG_MSK,
+ ADP5061_CHG_CURR_ICHG_MODE(index));
+}
+
+static int adp5061_get_const_chg_current(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval = ((regval & ADP5061_CHG_CURR_ICHG_MSK) >> 2);
+ if (regval >= ARRAY_SIZE(adp5061_const_ichg))
+ regval = ARRAY_SIZE(adp5061_const_ichg) - 1;
+
+ val->intval = adp5061_const_ichg[regval] * 1000;
+
+ return ret;
+}
+
+static int adp5061_get_prechg_current(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval &= ADP5061_CHG_CURR_ITRK_DEAD_MSK;
+ val->intval = adp5061_prechg_current[regval] * 1000;
+
+ return ret;
+}
+
+static int adp5061_set_prechg_current(struct adp5061_state *st, int val)
+{
+ int index;
+
+ /* Convert from uA to mA */
+ val /= 1000;
+ index = adp5061_get_array_index(adp5061_prechg_current,
+ ARRAY_SIZE(adp5061_prechg_current),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
+ ADP5061_CHG_CURR_ITRK_DEAD_MSK,
+ ADP5061_CHG_CURR_ITRK_DEAD_MODE(index));
+}
+
+static int adp5061_get_vweak_th(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval &= ADP5061_VOLTAGE_TH_VWEAK_MSK;
+ val->intval = adp5061_vweak_th[regval] * 1000;
+
+ return ret;
+}
+
+static int adp5061_set_vweak_th(struct adp5061_state *st, int val)
+{
+ int index;
+
+ /* Convert from uV to mV */
+ val /= 1000;
+ index = adp5061_get_array_index(adp5061_vweak_th,
+ ARRAY_SIZE(adp5061_vweak_th),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
+ ADP5061_VOLTAGE_TH_VWEAK_MSK,
+ ADP5061_VOLTAGE_TH_VWEAK_MODE(index));
+}
+
+static int adp5061_get_chg_type(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ u8 status1, status2;
+ int chg_type, ret;
+
+ ret = adp5061_get_status(st, &status1, &status2);
+ if (ret < 0)
+ return ret;
+
+ chg_type = adp5061_chg_type[ADP5061_CHG_STATUS_1_CHG_STATUS(status1)];
+ if (chg_type > ADP5061_CHG_FAST_CV)
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ else
+ val->intval = chg_type;
+
+ return ret;
+}
+
+static int adp5061_get_charger_status(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ u8 status1, status2;
+ int ret;
+
+ ret = adp5061_get_status(st, &status1, &status2);
+ if (ret < 0)
+ return ret;
+
+ switch (ADP5061_CHG_STATUS_1_CHG_STATUS(status1)) {
+ case ADP5061_CHG_OFF:
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case ADP5061_CHG_TRICKLE:
+ case ADP5061_CHG_FAST_CC:
+ case ADP5061_CHG_FAST_CV:
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case ADP5061_CHG_COMPLETE:
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case ADP5061_CHG_TIMER_EXP:
+ /* The battery must be discharging if there is a charge fault */
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+
+ return ret;
+}
+
+static int adp5061_get_battery_status(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ u8 status1, status2;
+ int ret;
+
+ ret = adp5061_get_status(st, &status1, &status2);
+ if (ret < 0)
+ return ret;
+
+ switch (ADP5061_CHG_STATUS_2_BAT_STATUS(status2)) {
+ case 0x0: /* Battery monitor off */
+ case 0x1: /* No battery */
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+ break;
+ case 0x2: /* VBAT < VTRK */
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ break;
+ case 0x3: /* VTRK < VBAT_SNS < VWEAK */
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ break;
+ case 0x4: /* VBAT_SNS > VWEAK */
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int adp5061_get_termination_current(struct adp5061_state *st,
+ union power_supply_propval *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(st->regmap, ADP5061_IEND, &regval);
+ if (ret < 0)
+ return ret;
+
+ regval = (regval & ADP5061_IEND_IEND_MSK) >> 5;
+ val->intval = adp5061_iend[regval];
+
+ return ret;
+}
+
+static int adp5061_set_termination_current(struct adp5061_state *st, int val)
+{
+ int index;
+
+ index = adp5061_get_array_index(adp5061_iend,
+ ARRAY_SIZE(adp5061_iend),
+ val);
+ if (index < 0)
+ return index;
+
+ return regmap_update_bits(st->regmap, ADP5061_IEND,
+ ADP5061_IEND_IEND_MSK,
+ ADP5061_IEND_IEND_MODE(index));
+}
+
+static int adp5061_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct adp5061_state *st = power_supply_get_drvdata(psy);
+ u8 status1, status2;
+ int mode, ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = adp5061_get_status(st, &status1, &status2);
+ if (ret < 0)
+ return ret;
+
+ mode = ADP5061_CHG_STATUS_2_BAT_STATUS(status2);
+ if (mode == ADP5061_NO_BATTERY)
+ val->intval = 0;
+ else
+ val->intval = 1;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ return adp5061_get_chg_type(st, val);
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ /* This property is used to indicate the input current
+ * limit into VINx (ILIM)
+ */
+ return adp5061_get_input_current_limit(st, val);
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ /* This property is used to indicate the termination
+ * voltage (VTRM)
+ */
+ return adp5061_get_max_voltage(st, val);
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ /*
+ * This property is used to indicate the trickle to fast
+ * charge threshold (VTRK_DEAD)
+ */
+ return adp5061_get_min_voltage(st, val);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ /* This property is used to indicate the charging
+ * voltage limit (CHG_VLIM)
+ */
+ return adp5061_get_chg_volt_lim(st, val);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ /*
+ * This property is used to indicate the value of the constant
+ * current charge (ICHG)
+ */
+ return adp5061_get_const_chg_current(st, val);
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ /*
+ * This property is used to indicate the value of the trickle
+ * and weak charge currents (ITRK_DEAD)
+ */
+ return adp5061_get_prechg_current(st, val);
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ /*
+ * This property is used to set the VWEAK threshold
+ * bellow this value, weak charge mode is entered
+ * above this value, fast chargerge mode is entered
+ */
+ return adp5061_get_vweak_th(st, val);
+ case POWER_SUPPLY_PROP_STATUS:
+ /*
+ * Indicate the charger status in relation to power
+ * supply status property
+ */
+ return adp5061_get_charger_status(st, val);
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ /*
+ * Indicate the battery status in relation to power
+ * supply capacity level property
+ */
+ return adp5061_get_battery_status(st, val);
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ /* Indicate the values of the termination current */
+ return adp5061_get_termination_current(st, val);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int adp5061_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct adp5061_state *st = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return adp5061_set_input_current_limit(st, val->intval);
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ return adp5061_set_max_voltage(st, val->intval);
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ return adp5061_set_min_voltage(st, val->intval);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ return adp5061_set_const_chg_vmax(st, val->intval);
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ return adp5061_set_const_chg_current(st, val->intval);
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ return adp5061_set_prechg_current(st, val->intval);
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ return adp5061_set_vweak_th(st, val->intval);
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ return adp5061_set_termination_current(st, val->intval);
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int adp5061_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static enum power_supply_property adp5061_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+};
+
+static const struct regmap_config adp5061_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static const struct power_supply_desc adp5061_desc = {
+ .name = "adp5061",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .get_property = adp5061_get_property,
+ .set_property = adp5061_set_property,
+ .property_is_writeable = adp5061_prop_writeable,
+ .properties = adp5061_props,
+ .num_properties = ARRAY_SIZE(adp5061_props),
+};
+
+static int adp5061_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct power_supply_config psy_cfg = {};
+ struct adp5061_state *st;
+
+ st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return -ENOMEM;
+
+ st->client = client;
+ st->regmap = devm_regmap_init_i2c(client,
+ &adp5061_regmap_config);
+ if (IS_ERR(st->regmap)) {
+ dev_err(&client->dev, "Failed to initialize register map\n");
+ return -EINVAL;
+ }
+
+ i2c_set_clientdata(client, st);
+ psy_cfg.drv_data = st;
+
+ st->psy = devm_power_supply_register(&client->dev,
+ &adp5061_desc,
+ &psy_cfg);
+
+ if (IS_ERR(st->psy)) {
+ dev_err(&client->dev, "Failed to register power supply\n");
+ return PTR_ERR(st->psy);
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id adp5061_id[] = {
+ { "adp5061", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adp5061_id);
+
+static struct i2c_driver adp5061_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ },
+ .probe = adp5061_probe,
+ .id_table = adp5061_id,
+};
+module_i2c_driver(adp5061_driver);
+
+MODULE_DESCRIPTION("Analog Devices adp5061 battery charger driver");
+MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 44f70dcea61e..42001df4bd13 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -222,6 +222,7 @@ static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
case 100000:
if (power->axp20x_id == AXP221_ID)
return -EINVAL;
+ /* fall through */
case 500000:
case 900000:
val = (900000 - intval) / 400000;
diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c
index 6e1bc14c3304..735658ee1c60 100644
--- a/drivers/power/supply/axp288_charger.c
+++ b/drivers/power/supply/axp288_charger.c
@@ -718,7 +718,7 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
}
/* Determine charge current limit */
- cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
+ cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
info->cc = cc;
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index d44ed8e17c47..f022e1b550df 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -26,7 +26,6 @@
* http://www.ti.com/product/bq27510-g1
* http://www.ti.com/product/bq27510-g2
* http://www.ti.com/product/bq27510-g3
- * http://www.ti.com/product/bq27520-g4
* http://www.ti.com/product/bq27520-g1
* http://www.ti.com/product/bq27520-g2
* http://www.ti.com/product/bq27520-g3
@@ -40,7 +39,9 @@
* http://www.ti.com/product/bq27545-g1
* http://www.ti.com/product/bq27421-g1
* http://www.ti.com/product/bq27425-g1
+ * http://www.ti.com/product/bq27426
* http://www.ti.com/product/bq27411-g1
+ * http://www.ti.com/product/bq27441-g1
* http://www.ti.com/product/bq27621-g1
*/
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
new file mode 100644
index 000000000000..688a16bacfbb
--- /dev/null
+++ b/drivers/power/supply/cros_usbpd-charger.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 - 2018 Google, Inc
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+
+#define CHARGER_DIR_NAME "CROS_USBPD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTH sizeof(CHARGER_DIR_NAME)
+#define CHARGER_CACHE_UPDATE_DELAY msecs_to_jiffies(500)
+#define CHARGER_MANUFACTURER_MODEL_LENGTH 32
+
+#define DRV_NAME "cros-usbpd-charger"
+
+struct port_data {
+ int port_number;
+ char name[CHARGER_DIR_NAME_LENGTH];
+ char manufacturer[CHARGER_MANUFACTURER_MODEL_LENGTH];
+ char model_name[CHARGER_MANUFACTURER_MODEL_LENGTH];
+ struct power_supply *psy;
+ struct power_supply_desc psy_desc;
+ int psy_usb_type;
+ int psy_online;
+ int psy_status;
+ int psy_current_max;
+ int psy_voltage_max_design;
+ int psy_voltage_now;
+ int psy_power_max;
+ struct charger_data *charger;
+ unsigned long last_update;
+};
+
+struct charger_data {
+ struct device *dev;
+ struct cros_ec_dev *ec_dev;
+ struct cros_ec_device *ec_device;
+ int num_charger_ports;
+ int num_registered_psy;
+ struct port_data *ports[EC_USB_PD_MAX_PORTS];
+ struct notifier_block notifier;
+};
+
+static enum power_supply_property cros_usbpd_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+ POWER_SUPPLY_PROP_USB_TYPE
+};
+
+static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
+ POWER_SUPPLY_USB_TYPE_UNKNOWN,
+ POWER_SUPPLY_USB_TYPE_SDP,
+ POWER_SUPPLY_USB_TYPE_DCP,
+ POWER_SUPPLY_USB_TYPE_CDP,
+ POWER_SUPPLY_USB_TYPE_C,
+ POWER_SUPPLY_USB_TYPE_PD,
+ POWER_SUPPLY_USB_TYPE_PD_DRP,
+ POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
+};
+
+static int cros_usbpd_charger_ec_command(struct charger_data *charger,
+ unsigned int version,
+ unsigned int command,
+ void *outdata,
+ unsigned int outsize,
+ void *indata,
+ unsigned int insize)
+{
+ struct cros_ec_dev *ec_dev = charger->ec_dev;
+ struct cros_ec_command *msg;
+ int ret;
+
+ msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ msg->version = version;
+ msg->command = ec_dev->cmd_offset + command;
+ msg->outsize = outsize;
+ msg->insize = insize;
+
+ if (outsize)
+ memcpy(msg->data, outdata, outsize);
+
+ ret = cros_ec_cmd_xfer_status(charger->ec_device, msg);
+ if (ret >= 0 && insize)
+ memcpy(indata, msg->data, insize);
+
+ kfree(msg);
+ return ret;
+}
+
+static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
+{
+ struct ec_response_usb_pd_ports resp;
+ int ret;
+
+ ret = cros_usbpd_charger_ec_command(charger, 0, EC_CMD_USB_PD_PORTS,
+ NULL, 0, &resp, sizeof(resp));
+ if (ret < 0) {
+ dev_err(charger->dev,
+ "Unable to get the number or ports (err:0x%x)\n", ret);
+ return ret;
+ }
+
+ return resp.num_ports;
+}
+
+static int cros_usbpd_charger_get_discovery_info(struct port_data *port)
+{
+ struct charger_data *charger = port->charger;
+ struct ec_params_usb_pd_discovery_entry resp;
+ struct ec_params_usb_pd_info_request req;
+ int ret;
+
+ req.port = port->port_number;
+
+ ret = cros_usbpd_charger_ec_command(charger, 0,
+ EC_CMD_USB_PD_DISCOVERY,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+ if (ret < 0) {
+ dev_err(charger->dev,
+ "Unable to query discovery info (err:0x%x)\n", ret);
+ return ret;
+ }
+
+ dev_dbg(charger->dev, "Port %d: VID = 0x%x, PID=0x%x, PTYPE=0x%x\n",
+ port->port_number, resp.vid, resp.pid, resp.ptype);
+
+ snprintf(port->manufacturer, sizeof(port->manufacturer), "%x",
+ resp.vid);
+ snprintf(port->model_name, sizeof(port->model_name), "%x", resp.pid);
+
+ return 0;
+}
+
+static int cros_usbpd_charger_get_power_info(struct port_data *port)
+{
+ struct charger_data *charger = port->charger;
+ struct ec_response_usb_pd_power_info resp;
+ struct ec_params_usb_pd_power_info req;
+ int last_psy_status, last_psy_usb_type;
+ struct device *dev = charger->dev;
+ int ret;
+
+ req.port = port->port_number;
+ ret = cros_usbpd_charger_ec_command(charger, 0,
+ EC_CMD_USB_PD_POWER_INFO,
+ &req, sizeof(req),
+ &resp, sizeof(resp));
+ if (ret < 0) {
+ dev_err(dev, "Unable to query PD power info (err:0x%x)\n", ret);
+ return ret;
+ }
+
+ last_psy_status = port->psy_status;
+ last_psy_usb_type = port->psy_usb_type;
+
+ switch (resp.role) {
+ case USB_PD_PORT_POWER_DISCONNECTED:
+ port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ port->psy_online = 0;
+ break;
+ case USB_PD_PORT_POWER_SOURCE:
+ port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ port->psy_online = 0;
+ break;
+ case USB_PD_PORT_POWER_SINK:
+ port->psy_status = POWER_SUPPLY_STATUS_CHARGING;
+ port->psy_online = 1;
+ break;
+ case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
+ port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ port->psy_online = 1;
+ break;
+ default:
+ dev_err(dev, "Unknown role %d\n", resp.role);
+ break;
+ }
+
+ port->psy_voltage_max_design = resp.meas.voltage_max;
+ port->psy_voltage_now = resp.meas.voltage_now;
+ port->psy_current_max = resp.meas.current_max;
+ port->psy_power_max = resp.max_power;
+
+ switch (resp.type) {
+ case USB_CHG_TYPE_BC12_SDP:
+ case USB_CHG_TYPE_VBUS:
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case USB_CHG_TYPE_NONE:
+ /*
+ * For dual-role devices when we are a source, the firmware
+ * reports the type as NONE. Report such chargers as type
+ * USB_PD_DRP.
+ */
+ if (resp.role == USB_PD_PORT_POWER_SOURCE && resp.dualrole)
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
+ else
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+ break;
+ case USB_CHG_TYPE_OTHER:
+ case USB_CHG_TYPE_PROPRIETARY:
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID;
+ break;
+ case USB_CHG_TYPE_C:
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_C;
+ break;
+ case USB_CHG_TYPE_BC12_DCP:
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP;
+ break;
+ case USB_CHG_TYPE_BC12_CDP:
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP;
+ break;
+ case USB_CHG_TYPE_PD:
+ if (resp.dualrole)
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
+ else
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD;
+ break;
+ case USB_CHG_TYPE_UNKNOWN:
+ /*
+ * While the EC is trying to determine the type of charger that
+ * has been plugged in, it will report the charger type as
+ * unknown. Additionally since the power capabilities are
+ * unknown, report the max current and voltage as zero.
+ */
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+ port->psy_voltage_max_design = 0;
+ port->psy_current_max = 0;
+ break;
+ default:
+ dev_err(dev, "Port %d: default case!\n", port->port_number);
+ port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+ }
+
+ port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+
+ dev_dbg(dev,
+ "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n",
+ port->port_number, resp.type, resp.meas.voltage_max,
+ resp.meas.voltage_now, resp.meas.current_max,
+ resp.meas.current_lim, resp.max_power);
+
+ /*
+ * If power supply type or status changed, explicitly call
+ * power_supply_changed. This results in udev event getting generated
+ * and allows user mode apps to react quicker instead of waiting for
+ * their next poll of power supply status.
+ */
+ if (last_psy_usb_type != port->psy_usb_type ||
+ last_psy_status != port->psy_status)
+ power_supply_changed(port->psy);
+
+ return 0;
+}
+
+static int cros_usbpd_charger_get_port_status(struct port_data *port,
+ bool ratelimit)
+{
+ int ret;
+
+ if (ratelimit &&
+ time_is_after_jiffies(port->last_update +
+ CHARGER_CACHE_UPDATE_DELAY))
+ return 0;
+
+ ret = cros_usbpd_charger_get_power_info(port);
+ if (ret < 0)
+ return ret;
+
+ ret = cros_usbpd_charger_get_discovery_info(port);
+ port->last_update = jiffies;
+
+ return ret;
+}
+
+static void cros_usbpd_charger_power_changed(struct power_supply *psy)
+{
+ struct port_data *port = power_supply_get_drvdata(psy);
+ struct charger_data *charger = port->charger;
+ int i;
+
+ for (i = 0; i < charger->num_registered_psy; i++)
+ cros_usbpd_charger_get_port_status(charger->ports[i], false);
+}
+
+static int cros_usbpd_charger_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct port_data *port = power_supply_get_drvdata(psy);
+ struct charger_data *charger = port->charger;
+ struct cros_ec_device *ec_device = charger->ec_device;
+ struct device *dev = charger->dev;
+ int ret;
+
+ /* Only refresh ec_port_status for dynamic properties */
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ /*
+ * If mkbp_event_supported, then we can be assured that
+ * the driver's state for the online property is consistent
+ * with the hardware. However, if we aren't event driven,
+ * the optimization before to skip an ec_port_status get
+ * and only returned cached values of the online property will
+ * cause a delay in detecting a cable attach until one of the
+ * other properties are read.
+ *
+ * Allow an ec_port_status refresh for online property check
+ * if we're not already online to check for plug events if
+ * not mkbp_event_supported.
+ */
+ if (ec_device->mkbp_event_supported || port->psy_online)
+ break;
+ /* fall through */
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = cros_usbpd_charger_get_port_status(port, true);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get port status (err:0x%x)\n",
+ ret);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = port->psy_online;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = port->psy_status;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = port->psy_current_max * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = port->psy_voltage_max_design * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = port->psy_voltage_now * 1000;
+ break;
+ case POWER_SUPPLY_PROP_USB_TYPE:
+ val->intval = port->psy_usb_type;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = port->model_name;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = port->manufacturer;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cros_usbpd_charger_ec_event(struct notifier_block *nb,
+ unsigned long queued_during_suspend,
+ void *_notify)
+{
+ struct cros_ec_device *ec_device;
+ struct charger_data *charger;
+ struct device *dev;
+ u32 host_event;
+
+ charger = container_of(nb, struct charger_data, notifier);
+ ec_device = charger->ec_device;
+ dev = charger->dev;
+
+ host_event = cros_ec_get_host_event(ec_device);
+ if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) {
+ cros_usbpd_charger_power_changed(charger->ports[0]->psy);
+ return NOTIFY_OK;
+ } else {
+ return NOTIFY_DONE;
+ }
+}
+
+static void cros_usbpd_charger_unregister_notifier(void *data)
+{
+ struct charger_data *charger = data;
+ struct cros_ec_device *ec_device = charger->ec_device;
+
+ blocking_notifier_chain_unregister(&ec_device->event_notifier,
+ &charger->notifier);
+}
+
+static int cros_usbpd_charger_probe(struct platform_device *pd)
+{
+ struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
+ struct cros_ec_device *ec_device = ec_dev->ec_dev;
+ struct power_supply_desc *psy_desc;
+ struct device *dev = &pd->dev;
+ struct charger_data *charger;
+ struct power_supply *psy;
+ struct port_data *port;
+ int ret = -EINVAL;
+ int i;
+
+ charger = devm_kzalloc(dev, sizeof(struct charger_data),
+ GFP_KERNEL);
+ if (!charger)
+ return -ENOMEM;
+
+ charger->dev = dev;
+ charger->ec_dev = ec_dev;
+ charger->ec_device = ec_device;
+
+ platform_set_drvdata(pd, charger);
+
+ charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger);
+ if (charger->num_charger_ports <= 0) {
+ /*
+ * This can happen on a system that doesn't support USB PD.
+ * Log a message, but no need to warn.
+ */
+ dev_info(dev, "No charging ports found\n");
+ ret = -ENODEV;
+ goto fail_nowarn;
+ }
+
+ for (i = 0; i < charger->num_charger_ports; i++) {
+ struct power_supply_config psy_cfg = {};
+
+ port = devm_kzalloc(dev, sizeof(struct port_data), GFP_KERNEL);
+ if (!port) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ port->charger = charger;
+ port->port_number = i;
+ sprintf(port->name, CHARGER_DIR_NAME, i);
+
+ psy_desc = &port->psy_desc;
+ psy_desc->name = port->name;
+ psy_desc->type = POWER_SUPPLY_TYPE_USB;
+ psy_desc->get_property = cros_usbpd_charger_get_prop;
+ psy_desc->external_power_changed =
+ cros_usbpd_charger_power_changed;
+ psy_desc->properties = cros_usbpd_charger_props;
+ psy_desc->num_properties =
+ ARRAY_SIZE(cros_usbpd_charger_props);
+ psy_desc->usb_types = cros_usbpd_charger_usb_types;
+ psy_desc->num_usb_types =
+ ARRAY_SIZE(cros_usbpd_charger_usb_types);
+ psy_cfg.drv_data = port;
+
+ psy = devm_power_supply_register_no_ws(dev, psy_desc,
+ &psy_cfg);
+ if (IS_ERR(psy)) {
+ dev_err(dev, "Failed to register power supply\n");
+ continue;
+ }
+ port->psy = psy;
+
+ charger->ports[charger->num_registered_psy++] = port;
+ }
+
+ if (!charger->num_registered_psy) {
+ ret = -ENODEV;
+ dev_err(dev, "No power supplies registered\n");
+ goto fail;
+ }
+
+ if (ec_device->mkbp_event_supported) {
+ /* Get PD events from the EC */
+ charger->notifier.notifier_call = cros_usbpd_charger_ec_event;
+ ret = blocking_notifier_chain_register(
+ &ec_device->event_notifier,
+ &charger->notifier);
+ if (ret < 0) {
+ dev_warn(dev, "failed to register notifier\n");
+ } else {
+ ret = devm_add_action_or_reset(dev,
+ cros_usbpd_charger_unregister_notifier,
+ charger);
+ if (ret < 0)
+ goto fail;
+ }
+ }
+
+ return 0;
+
+fail:
+ WARN(1, "%s: Failing probe (err:0x%x)\n", dev_name(dev), ret);
+
+fail_nowarn:
+ dev_info(dev, "Failing probe (err:0x%x)\n", ret);
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_usbpd_charger_resume(struct device *dev)
+{
+ struct charger_data *charger = dev_get_drvdata(dev);
+ int i;
+
+ if (!charger)
+ return 0;
+
+ for (i = 0; i < charger->num_registered_psy; i++) {
+ power_supply_changed(charger->ports[i]->psy);
+ charger->ports[i]->last_update =
+ jiffies - CHARGER_CACHE_UPDATE_DELAY;
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL,
+ cros_usbpd_charger_resume);
+
+static struct platform_driver cros_usbpd_charger_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .pm = &cros_usbpd_charger_pm_ops,
+ },
+ .probe = cros_usbpd_charger_probe
+};
+
+module_platform_driver(cros_usbpd_charger_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC USBPD charger");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/power/supply/ds2760_battery.c b/drivers/power/supply/ds2760_battery.c
index ae180dc929c9..11bed88a89fa 100644
--- a/drivers/power/supply/ds2760_battery.c
+++ b/drivers/power/supply/ds2760_battery.c
@@ -27,9 +27,64 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
-
+#include <linux/suspend.h>
#include <linux/w1.h>
-#include "../../w1/slaves/w1_ds2760.h"
+#include <linux/of.h>
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+static bool pmod_enabled;
+module_param(pmod_enabled, bool, 0644);
+MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
+
+static unsigned int rated_capacity;
+module_param(rated_capacity, uint, 0644);
+MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");
+
+static unsigned int current_accum;
+module_param(current_accum, uint, 0644);
+MODULE_PARM_DESC(current_accum, "current accumulator value");
+
+#define W1_FAMILY_DS2760 0x30
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP 0xAA
+#define W1_DS2760_READ_DATA 0x69
+#define W1_DS2760_WRITE_DATA 0x6C
+#define W1_DS2760_COPY_DATA 0x48
+#define W1_DS2760_RECALL_DATA 0xB8
+#define W1_DS2760_LOCK 0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE 0x40
+
+#define DS2760_PROTECTION_REG 0x00
+
+#define DS2760_STATUS_REG 0x01
+#define DS2760_STATUS_IE (1 << 2)
+#define DS2760_STATUS_SWEN (1 << 3)
+#define DS2760_STATUS_RNAOP (1 << 4)
+#define DS2760_STATUS_PMOD (1 << 5)
+
+#define DS2760_EEPROM_REG 0x07
+#define DS2760_SPECIAL_FEATURE_REG 0x08
+#define DS2760_VOLTAGE_MSB 0x0c
+#define DS2760_VOLTAGE_LSB 0x0d
+#define DS2760_CURRENT_MSB 0x0e
+#define DS2760_CURRENT_LSB 0x0f
+#define DS2760_CURRENT_ACCUM_MSB 0x10
+#define DS2760_CURRENT_ACCUM_LSB 0x11
+#define DS2760_TEMP_MSB 0x18
+#define DS2760_TEMP_LSB 0x19
+#define DS2760_EEPROM_BLOCK0 0x20
+#define DS2760_ACTIVE_FULL 0x20
+#define DS2760_EEPROM_BLOCK1 0x30
+#define DS2760_STATUS_WRITE_REG 0x31
+#define DS2760_RATED_CAPACITY 0x32
+#define DS2760_CURRENT_OFFSET_BIAS 0x33
+#define DS2760_ACTIVE_EMPTY 0x3b
struct ds2760_device_info {
struct device *dev;
@@ -55,28 +110,113 @@ struct ds2760_device_info {
int full_counter;
struct power_supply *bat;
struct power_supply_desc bat_desc;
- struct device *w1_dev;
struct workqueue_struct *monitor_wqueue;
struct delayed_work monitor_work;
struct delayed_work set_charged_work;
+ struct notifier_block pm_notifier;
};
-static unsigned int cache_time = 1000;
-module_param(cache_time, uint, 0644);
-MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+ int io)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-static bool pmod_enabled;
-module_param(pmod_enabled, bool, 0644);
-MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
+ if (!dev)
+ return 0;
-static unsigned int rated_capacity;
-module_param(rated_capacity, uint, 0644);
-MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");
+ mutex_lock(&sl->master->bus_mutex);
-static unsigned int current_accum;
-module_param(current_accum, uint, 0644);
-MODULE_PARM_DESC(current_accum, "current accumulator value");
+ if (addr > DS2760_DATA_SIZE || addr < 0) {
+ count = 0;
+ goto out;
+ }
+ if (addr + count > DS2760_DATA_SIZE)
+ count = DS2760_DATA_SIZE - addr;
+
+ if (!w1_reset_select_slave(sl)) {
+ if (!io) {
+ w1_write_8(sl->master, W1_DS2760_READ_DATA);
+ w1_write_8(sl->master, addr);
+ count = w1_read_block(sl->master, buf, count);
+ } else {
+ w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+ w1_write_8(sl->master, addr);
+ w1_write_block(sl->master, buf, count);
+ /* XXX w1_write_block returns void, not n_written */
+ }
+ }
+
+out:
+ mutex_unlock(&sl->master->bus_mutex);
+
+ return count;
+}
+
+static int w1_ds2760_read(struct device *dev,
+ char *buf, int addr,
+ size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+static int w1_ds2760_write(struct device *dev,
+ char *buf,
+ int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev)
+ return -EINVAL;
+
+ mutex_lock(&sl->master->bus_mutex);
+
+ if (w1_reset_select_slave(sl) == 0) {
+ w1_write_8(sl->master, cmd);
+ w1_write_8(sl->master, addr);
+ }
+
+ mutex_unlock(&sl->master->bus_mutex);
+ return 0;
+}
+
+static int w1_ds2760_store_eeprom(struct device *dev, int addr)
+{
+ return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA);
+}
+
+static int w1_ds2760_recall_eeprom(struct device *dev, int addr)
+{
+ return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
+}
+
+static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ return w1_ds2760_read(dev, buf, off, count);
+}
+
+static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
+
+static struct bin_attribute *w1_ds2760_bin_attrs[] = {
+ &bin_attr_w1_slave,
+ NULL,
+};
+
+static const struct attribute_group w1_ds2760_group = {
+ .bin_attrs = w1_ds2760_bin_attrs,
+};
+static const struct attribute_group *w1_ds2760_groups[] = {
+ &w1_ds2760_group,
+ NULL,
+};
/* Some batteries have their rated capacity stored a N * 10 mAh, while
* others use an index into this table. */
static int rated_capacities[] = {
@@ -138,10 +278,10 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
count = DS2760_TEMP_LSB - start + 1;
}
- ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+ ret = w1_ds2760_read(di->dev, di->raw + start, start, count);
if (ret != count) {
dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
- di->w1_dev);
+ di->dev);
return 1;
}
@@ -242,7 +382,7 @@ static void ds2760_battery_set_current_accum(struct ds2760_device_info *di,
acr[0] = acr_val >> 8;
acr[1] = acr_val & 0xff;
- if (w1_ds2760_write(di->w1_dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+ if (w1_ds2760_write(di->dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)
dev_warn(di->dev, "ACR write failed\n");
}
@@ -297,9 +437,9 @@ static void ds2760_battery_write_status(struct ds2760_device_info *di,
if (status == di->raw[DS2760_STATUS_REG])
return;
- w1_ds2760_write(di->w1_dev, &status, DS2760_STATUS_WRITE_REG, 1);
- w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
- w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_write(di->dev, &status, DS2760_STATUS_WRITE_REG, 1);
+ w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
}
static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
@@ -308,9 +448,9 @@ static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
if (rated_capacity == di->raw[DS2760_RATED_CAPACITY])
return;
- w1_ds2760_write(di->w1_dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);
- w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
- w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_write(di->dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);
+ w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
}
static void ds2760_battery_write_active_full(struct ds2760_device_info *di,
@@ -325,9 +465,9 @@ static void ds2760_battery_write_active_full(struct ds2760_device_info *di,
tmp[1] == di->raw[DS2760_ACTIVE_FULL + 1])
return;
- w1_ds2760_write(di->w1_dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));
- w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);
- w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);
+ w1_ds2760_write(di->dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));
+ w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK0);
+ w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK0);
/* Write to the di->raw[] buffer directly - the DS2760_ACTIVE_FULL
* values won't be read back by ds2760_battery_read_status() */
@@ -383,9 +523,9 @@ static void ds2760_battery_set_charged_work(struct work_struct *work)
dev_dbg(di->dev, "%s: bias = %d\n", __func__, bias);
- w1_ds2760_write(di->w1_dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
- w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
- w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_write(di->dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
+ w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+ w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
/* Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS
* value won't be read back by ds2760_battery_read_status() */
@@ -504,24 +644,55 @@ static enum power_supply_property ds2760_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
};
-static int ds2760_battery_probe(struct platform_device *pdev)
+static int ds2760_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event,
+ void *unused)
+{
+ struct ds2760_device_info *di =
+ container_of(notifier, struct ds2760_device_info, pm_notifier);
+
+ switch (pm_event) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ break;
+
+ case PM_POST_RESTORE:
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ power_supply_changed(di->bat);
+ mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+ break;
+
+ case PM_RESTORE_PREPARE:
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
{
struct power_supply_config psy_cfg = {};
- char status;
- int retval = 0;
struct ds2760_device_info *di;
+ struct device *dev = &sl->dev;
+ int retval = 0;
+ char name[32];
+ char status;
- di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+ di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
if (!di) {
retval = -ENOMEM;
goto di_alloc_failed;
}
- platform_set_drvdata(pdev, di);
+ snprintf(name, sizeof(name), "ds2760-battery.%d", dev->id);
- di->dev = &pdev->dev;
- di->w1_dev = pdev->dev.parent;
- di->bat_desc.name = dev_name(&pdev->dev);
+ di->dev = dev;
+ di->bat_desc.name = name;
di->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
di->bat_desc.properties = ds2760_battery_props;
di->bat_desc.num_properties = ARRAY_SIZE(ds2760_battery_props);
@@ -533,10 +704,30 @@ static int ds2760_battery_probe(struct platform_device *pdev)
di->bat_desc.external_power_changed =
ds2760_battery_external_power_changed;
- psy_cfg.drv_data = di;
+ psy_cfg.drv_data = di;
+
+ if (dev->of_node) {
+ u32 tmp;
+
+ psy_cfg.of_node = dev->of_node;
+
+ if (!of_property_read_bool(dev->of_node, "maxim,pmod-enabled"))
+ pmod_enabled = true;
+
+ if (!of_property_read_u32(dev->of_node,
+ "maxim,cache-time-ms", &tmp))
+ cache_time = tmp;
+
+ if (!of_property_read_u32(dev->of_node,
+ "rated-capacity-microamp-hours",
+ &tmp))
+ rated_capacity = tmp / 10; /* property is in mAh */
+ }
di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ sl->family_data = di;
+
/* enable sleep mode feature */
ds2760_battery_read_status(di);
status = di->raw[DS2760_STATUS_REG];
@@ -547,7 +738,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
ds2760_battery_write_status(di, status);
- /* set rated capacity from module param */
+ /* set rated capacity from module param or device tree */
if (rated_capacity)
ds2760_battery_write_rated_capacity(di, rated_capacity);
@@ -556,7 +747,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
if (current_accum)
ds2760_battery_set_current_accum(di, current_accum);
- di->bat = power_supply_register(&pdev->dev, &di->bat_desc, &psy_cfg);
+ di->bat = power_supply_register(dev, &di->bat_desc, &psy_cfg);
if (IS_ERR(di->bat)) {
dev_err(di->dev, "failed to register battery\n");
retval = PTR_ERR(di->bat);
@@ -566,14 +757,16 @@ static int ds2760_battery_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
INIT_DELAYED_WORK(&di->set_charged_work,
ds2760_battery_set_charged_work);
- di->monitor_wqueue = alloc_ordered_workqueue(dev_name(&pdev->dev),
- WQ_MEM_RECLAIM);
+ di->monitor_wqueue = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
if (!di->monitor_wqueue) {
retval = -ESRCH;
goto workqueue_failed;
}
queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+ di->pm_notifier.notifier_call = ds2760_pm_notifier;
+ register_pm_notifier(&di->pm_notifier);
+
goto success;
workqueue_failed:
@@ -584,65 +777,40 @@ success:
return retval;
}
-static int ds2760_battery_remove(struct platform_device *pdev)
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
{
- struct ds2760_device_info *di = platform_get_drvdata(pdev);
+ struct ds2760_device_info *di = sl->family_data;
+ unregister_pm_notifier(&di->pm_notifier);
cancel_delayed_work_sync(&di->monitor_work);
cancel_delayed_work_sync(&di->set_charged_work);
destroy_workqueue(di->monitor_wqueue);
power_supply_unregister(di->bat);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int ds2760_battery_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- struct ds2760_device_info *di = platform_get_drvdata(pdev);
-
- di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
-
- return 0;
-}
-
-static int ds2760_battery_resume(struct platform_device *pdev)
-{
- struct ds2760_device_info *di = platform_get_drvdata(pdev);
-
- di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
- power_supply_changed(di->bat);
-
- mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
-
- return 0;
}
-#else
-
-#define ds2760_battery_suspend NULL
-#define ds2760_battery_resume NULL
-
-#endif /* CONFIG_PM */
-
-MODULE_ALIAS("platform:ds2760-battery");
+#ifdef CONFIG_OF
+static const struct of_device_id w1_ds2760_of_ids[] = {
+ { .compatible = "maxim,ds2760" },
+ {}
+};
+#endif
-static struct platform_driver ds2760_battery_driver = {
- .driver = {
- .name = "ds2760-battery",
- },
- .probe = ds2760_battery_probe,
- .remove = ds2760_battery_remove,
- .suspend = ds2760_battery_suspend,
- .resume = ds2760_battery_resume,
+static struct w1_family_ops w1_ds2760_fops = {
+ .add_slave = w1_ds2760_add_slave,
+ .remove_slave = w1_ds2760_remove_slave,
+ .groups = w1_ds2760_groups,
};
-module_platform_driver(ds2760_battery_driver);
+static struct w1_family w1_ds2760_family = {
+ .fid = W1_FAMILY_DS2760,
+ .fops = &w1_ds2760_fops,
+ .of_match_table = of_match_ptr(w1_ds2760_of_ids),
+};
+module_w1_family(w1_ds2760_family);
-MODULE_LICENSE("GPL");
MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
"Matt Reimer <mreimer@vpop.net>, "
"Anton Vorontsov <cbou@mail.ru>");
-MODULE_DESCRIPTION("ds2760 battery driver");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760));
diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c
index 28dc056eaafa..bc462d1ec963 100644
--- a/drivers/power/supply/generic-adc-battery.c
+++ b/drivers/power/supply/generic-adc-battery.c
@@ -241,10 +241,10 @@ static int gab_probe(struct platform_device *pdev)
struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = {};
struct gab_platform_data *pdata = pdev->dev.platform_data;
- enum power_supply_property *properties;
int ret = 0;
int chan;
- int index = 0;
+ int index = ARRAY_SIZE(gab_props);
+ bool any = false;
adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
if (!adc_bat) {
@@ -278,8 +278,6 @@ static int gab_probe(struct platform_device *pdev)
}
memcpy(psy_desc->properties, gab_props, sizeof(gab_props));
- properties = (enum power_supply_property *)
- ((char *)psy_desc->properties + sizeof(gab_props));
/*
* getting channel from iio and copying the battery properties
@@ -293,15 +291,22 @@ static int gab_probe(struct platform_device *pdev)
adc_bat->channel[chan] = NULL;
} else {
/* copying properties for supported channels only */
- memcpy(properties + sizeof(*(psy_desc->properties)) * index,
- &gab_dyn_props[chan],
- sizeof(gab_dyn_props[chan]));
- index++;
+ int index2;
+
+ for (index2 = 0; index2 < index; index2++) {
+ if (psy_desc->properties[index2] ==
+ gab_dyn_props[chan])
+ break; /* already known */
+ }
+ if (index2 == index) /* really new */
+ psy_desc->properties[index++] =
+ gab_dyn_props[chan];
+ any = true;
}
}
/* none of the channels are supported so let's bail out */
- if (index == 0) {
+ if (!any) {
ret = -ENODEV;
goto second_mem_fail;
}
@@ -312,7 +317,7 @@ static int gab_probe(struct platform_device *pdev)
* as come channels may be not be supported by the device.So
* we need to take care of that.
*/
- psy_desc->num_properties = ARRAY_SIZE(gab_props) + index;
+ psy_desc->num_properties = index;
adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
if (IS_ERR(adc_bat->psy)) {
diff --git a/drivers/power/supply/lego_ev3_battery.c b/drivers/power/supply/lego_ev3_battery.c
index 7b993d669f7f..1ae3710909b7 100644
--- a/drivers/power/supply/lego_ev3_battery.c
+++ b/drivers/power/supply/lego_ev3_battery.c
@@ -39,7 +39,7 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
union power_supply_propval *val)
{
struct lego_ev3_battery *batt = power_supply_get_drvdata(psy);
- int val2;
+ int ret, val2;
switch (psp) {
case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -47,11 +47,18 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
/* battery voltage is iio channel * 2 + Vce of transistor */
- iio_read_channel_processed(batt->iio_v, &val->intval);
+ ret = iio_read_channel_processed(batt->iio_v, &val->intval);
+ if (ret)
+ return ret;
+
val->intval *= 2000;
- val->intval += 200000;
+ val->intval += 50000;
+
/* plus adjust for shunt resistor drop */
- iio_read_channel_processed(batt->iio_i, &val2);
+ ret = iio_read_channel_processed(batt->iio_i, &val2);
+ if (ret)
+ return ret;
+
val2 *= 1000;
val2 /= 15;
val->intval += val2;
@@ -64,7 +71,10 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
/* battery current is iio channel / 15 / 0.05 ohms */
- iio_read_channel_processed(batt->iio_i, &val->intval);
+ ret = iio_read_channel_processed(batt->iio_i, &val->intval);
+ if (ret)
+ return ret;
+
val->intval *= 20000;
val->intval /= 15;
break;
diff --git a/drivers/power/supply/max1721x_battery.c b/drivers/power/supply/max1721x_battery.c
index 9ee601a03d9b..9ca895b0dabb 100644
--- a/drivers/power/supply/max1721x_battery.c
+++ b/drivers/power/supply/max1721x_battery.c
@@ -372,7 +372,7 @@ static int devm_w1_max1721x_add_device(struct w1_slave *sl)
}
if (!info->rsense) {
- dev_warn(info->w1_dev, "RSenese not calibrated, set 10 mOhms!\n");
+ dev_warn(info->w1_dev, "RSense not calibrated, set 10 mOhms!\n");
info->rsense = 1000; /* in regs in 10^-5 */
}
dev_info(info->w1_dev, "RSense: %d mOhms.\n", info->rsense / 100);
diff --git a/drivers/power/supply/max77693_charger.c b/drivers/power/supply/max77693_charger.c
index 6c78884bad5e..749c7926e3c9 100644
--- a/drivers/power/supply/max77693_charger.c
+++ b/drivers/power/supply/max77693_charger.c
@@ -567,6 +567,7 @@ static int max77693_set_charge_input_threshold_volt(struct max77693_charger *chg
case 4800000:
case 4900000:
data = (uvolt - 4700000) / 100000;
+ break;
default:
dev_err(chg->dev, "Wrong value for charge input voltage regulation threshold\n");
return -EINVAL;
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index d21f478741c1..e85361878450 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/err.h>
@@ -140,8 +141,13 @@ static void power_supply_deferred_register_work(struct work_struct *work)
struct power_supply *psy = container_of(work, struct power_supply,
deferred_register_work.work);
- if (psy->dev.parent)
- mutex_lock(&psy->dev.parent->mutex);
+ if (psy->dev.parent) {
+ while (!mutex_trylock(&psy->dev.parent->mutex)) {
+ if (psy->removing)
+ return;
+ msleep(10);
+ }
+ }
power_supply_changed(psy);
@@ -1082,6 +1088,7 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws);
void power_supply_unregister(struct power_supply *psy)
{
WARN_ON(atomic_dec_return(&psy->use_cnt));
+ psy->removing = true;
cancel_work_sync(&psy->changed_work);
cancel_delayed_work_sync(&psy->deferred_register_work);
sysfs_remove_link(&psy->dev.kobj, "powers");
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
index 83d7b4115857..8ba6abf584de 100644
--- a/drivers/power/supply/sbs-battery.c
+++ b/drivers/power/supply/sbs-battery.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/power/sbs-battery.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
@@ -156,6 +157,9 @@ static enum power_supply_property sbs_properties[] = {
POWER_SUPPLY_PROP_MODEL_NAME
};
+/* Supports special manufacturer commands from TI BQ20Z75 IC. */
+#define SBS_FLAGS_TI_BQ20Z75 BIT(0)
+
struct sbs_info {
struct i2c_client *client;
struct power_supply *power_supply;
@@ -168,6 +172,7 @@ struct sbs_info {
u32 poll_retry_count;
struct delayed_work work;
struct mutex mode_lock;
+ u32 flags;
};
static char model_name[I2C_SMBUS_BLOCK_MAX + 1];
@@ -316,16 +321,40 @@ static int sbs_get_battery_presence_and_health(
struct i2c_client *client, enum power_supply_property psp,
union power_supply_propval *val)
{
+ int ret;
+
+ if (psp == POWER_SUPPLY_PROP_PRESENT) {
+ /* Dummy command; if it succeeds, battery is present. */
+ ret = sbs_read_word_data(client, sbs_data[REG_STATUS].addr);
+ if (ret < 0)
+ val->intval = 0; /* battery disconnected */
+ else
+ val->intval = 1; /* battery present */
+ } else { /* POWER_SUPPLY_PROP_HEALTH */
+ /* SBS spec doesn't have a general health command. */
+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static int sbs_get_ti_battery_presence_and_health(
+ struct i2c_client *client, enum power_supply_property psp,
+ union power_supply_propval *val)
+{
s32 ret;
/*
* Write to ManufacturerAccess with ManufacturerAccess command
- * and then read the status. Do not check for error on the write
- * since not all batteries implement write access to this command,
- * while others mandate it.
+ * and then read the status.
*/
- sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
- MANUFACTURER_ACCESS_STATUS);
+ ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
+ MANUFACTURER_ACCESS_STATUS);
+ if (ret < 0) {
+ if (psp == POWER_SUPPLY_PROP_PRESENT)
+ val->intval = 0; /* battery removed */
+ return ret;
+ }
ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
if (ret < 0) {
@@ -600,7 +629,12 @@ static int sbs_get_property(struct power_supply *psy,
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH:
- ret = sbs_get_battery_presence_and_health(client, psp, val);
+ if (client->flags & SBS_FLAGS_TI_BQ20Z75)
+ ret = sbs_get_ti_battery_presence_and_health(client,
+ psp, val);
+ else
+ ret = sbs_get_battery_presence_and_health(client, psp,
+ val);
if (psp == POWER_SUPPLY_PROP_PRESENT)
return 0;
break;
@@ -806,6 +840,7 @@ static int sbs_probe(struct i2c_client *client,
if (!chip)
return -ENOMEM;
+ chip->flags = (u32)(uintptr_t)of_device_get_match_data(&client->dev);
chip->client = client;
chip->enable_detection = false;
psy_cfg.of_node = client->dev.of_node;
@@ -911,16 +946,19 @@ static int sbs_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct sbs_info *chip = i2c_get_clientdata(client);
+ int ret;
if (chip->poll_time > 0)
cancel_delayed_work_sync(&chip->work);
- /*
- * Write to manufacturer access with sleep command.
- * Support is manufacturer dependend, so ignore errors.
- */
- sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
- MANUFACTURER_ACCESS_SLEEP);
+ if (chip->flags & SBS_FLAGS_TI_BQ20Z75) {
+ /* Write to manufacturer access with sleep command. */
+ ret = sbs_write_word_data(client,
+ sbs_data[REG_MANUFACTURER_DATA].addr,
+ MANUFACTURER_ACCESS_SLEEP);
+ if (chip->is_present && ret < 0)
+ return ret;
+ }
return 0;
}
@@ -941,7 +979,10 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
static const struct of_device_id sbs_dt_ids[] = {
{ .compatible = "sbs,sbs-battery" },
- { .compatible = "ti,bq20z75" },
+ {
+ .compatible = "ti,bq20z75",
+ .data = (void *)SBS_FLAGS_TI_BQ20Z75,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, sbs_dt_ids);
diff --git a/drivers/power/supply/tps65217_charger.c b/drivers/power/supply/tps65217_charger.c
index 1f5234098aaf..814c2b81fdfe 100644
--- a/drivers/power/supply/tps65217_charger.c
+++ b/drivers/power/supply/tps65217_charger.c
@@ -1,20 +1,8 @@
-/*
- * Battery charger driver for TI's tps65217
- *
- * Copyright (c) 2015, Collabora Ltd.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0
+// Battery charger driver for TI's tps65217
+//
+// Copyright (C) 2015 Collabora Ltd.
+// Author: Enric Balletbo i Serra <enric.balletbo@collabora.com>
/*
* Battery charger driver for TI's tps65217
diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c
index a2740cf57ad3..15c0ca15e2aa 100644
--- a/drivers/power/supply/wm8350_power.c
+++ b/drivers/power/supply/wm8350_power.c
@@ -230,7 +230,8 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
case WM8350_IRQ_EXT_USB_FB:
case WM8350_IRQ_EXT_WALL_FB:
wm8350_charger_config(wm8350, policy);
- case WM8350_IRQ_EXT_BAT_FB: /* Fall through */
+ /* Fall through */
+ case WM8350_IRQ_EXT_BAT_FB:
power_supply_changed(power->battery);
power_supply_changed(power->usb);
power_supply_changed(power->ac);
diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index a8cb8d2f2abb..cbe467ff1aba 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -1006,7 +1006,6 @@ out_free:
static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
{
struct mport_cdev_priv *priv;
- struct mport_dev *md;
struct rio_async_tx_wait w_param;
struct mport_dma_req *req;
dma_cookie_t cookie;
@@ -1016,7 +1015,6 @@ static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
int ret;
priv = (struct mport_cdev_priv *)filp->private_data;
- md = priv->md;
if (unlikely(copy_from_user(&w_param, arg, sizeof(w_param))))
return -EFAULT;
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 2df26f36c687..8cbcd2a3eb20 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -98,7 +98,7 @@ struct da9063_regulator_info {
struct da9063_dev_model {
const struct da9063_regulator_info *regulator_info;
unsigned n_regulators;
- unsigned dev_model;
+ enum da9063_type type;
};
/* Single regulator settings */
@@ -530,6 +530,32 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
DA9063_BMEM_ILIM_MASK),
},
{
+ DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
+ .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
+ .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
+ },
+ {
+ DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
+ .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
+ .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
+ },
+ {
+ DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
+ .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
+ .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
+ },
+ {
+ DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
+ .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
+ },
+ {
+ DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
+ .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
+ .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
+ },
+
+ /* The following LDOs are present only on DA9063, not on DA9063L */
+ {
DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
},
@@ -538,11 +564,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
},
{
- DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
- .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
- .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
- },
- {
DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
.suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
@@ -555,29 +576,11 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
},
- {
- DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
- .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
- },
- {
- DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
- .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
- },
- {
- DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
- },
+
{
DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
},
- {
- DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
- .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
- .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
- },
};
/* Link chip model with regulators info table */
@@ -585,7 +588,12 @@ static struct da9063_dev_model regulators_models[] = {
{
.regulator_info = da9063_regulator_info,
.n_regulators = ARRAY_SIZE(da9063_regulator_info),
- .dev_model = PMIC_DA9063,
+ .type = PMIC_TYPE_DA9063,
+ },
+ {
+ .regulator_info = da9063_regulator_info,
+ .n_regulators = ARRAY_SIZE(da9063_regulator_info) - 6,
+ .type = PMIC_TYPE_DA9063L,
},
{ }
};
@@ -641,28 +649,34 @@ static struct of_regulator_match da9063_matches[] = {
[DA9063_ID_BPERI] = { .name = "bperi", },
[DA9063_ID_BCORES_MERGED] = { .name = "bcores-merged" },
[DA9063_ID_BMEM_BIO_MERGED] = { .name = "bmem-bio-merged", },
+ [DA9063_ID_LDO3] = { .name = "ldo3", },
+ [DA9063_ID_LDO7] = { .name = "ldo7", },
+ [DA9063_ID_LDO8] = { .name = "ldo8", },
+ [DA9063_ID_LDO9] = { .name = "ldo9", },
+ [DA9063_ID_LDO11] = { .name = "ldo11", },
+ /* The following LDOs are present only on DA9063, not on DA9063L */
[DA9063_ID_LDO1] = { .name = "ldo1", },
[DA9063_ID_LDO2] = { .name = "ldo2", },
- [DA9063_ID_LDO3] = { .name = "ldo3", },
[DA9063_ID_LDO4] = { .name = "ldo4", },
[DA9063_ID_LDO5] = { .name = "ldo5", },
[DA9063_ID_LDO6] = { .name = "ldo6", },
- [DA9063_ID_LDO7] = { .name = "ldo7", },
- [DA9063_ID_LDO8] = { .name = "ldo8", },
- [DA9063_ID_LDO9] = { .name = "ldo9", },
[DA9063_ID_LDO10] = { .name = "ldo10", },
- [DA9063_ID_LDO11] = { .name = "ldo11", },
};
static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
struct platform_device *pdev,
struct of_regulator_match **da9063_reg_matches)
{
+ struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_regulators_pdata *pdata;
struct da9063_regulator_data *rdata;
struct device_node *node;
+ int da9063_matches_len = ARRAY_SIZE(da9063_matches);
int i, n, num;
+ if (da9063->type == PMIC_TYPE_DA9063L)
+ da9063_matches_len -= 6;
+
node = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!node) {
dev_err(&pdev->dev, "Regulators device node not found\n");
@@ -670,7 +684,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
}
num = of_regulator_match(&pdev->dev, node, da9063_matches,
- ARRAY_SIZE(da9063_matches));
+ da9063_matches_len);
of_node_put(node);
if (num < 0) {
dev_err(&pdev->dev, "Failed to match regulators\n");
@@ -689,7 +703,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
pdata->n_regulators = num;
n = 0;
- for (i = 0; i < ARRAY_SIZE(da9063_matches); i++) {
+ for (i = 0; i < da9063_matches_len; i++) {
if (!da9063_matches[i].init_data)
continue;
@@ -741,12 +755,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
/* Find regulators set for particular device model */
for (model = regulators_models; model->regulator_info; model++) {
- if (model->dev_model == da9063->model)
+ if (model->type == da9063->type)
break;
}
if (!model->regulator_info) {
dev_err(&pdev->dev, "Chip model not recognised (%u)\n",
- da9063->model);
+ da9063->type);
return -ENODEV;
}
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c0b292be1b72..a70262cb7e56 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -82,6 +82,15 @@ config RESET_PISTACHIO
help
This enables the reset driver for ImgTec Pistachio SoCs.
+config RESET_QCOM_AOSS
+ bool "Qcom AOSS Reset Driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ This enables the AOSS (always on subsystem) reset driver
+ for Qualcomm SDM845 SoCs. Say Y if you want to control
+ reset signals provided by AOSS for Modem, Venus, ADSP,
+ GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
+
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
@@ -138,6 +147,16 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block.
+config RESET_UNIPHIER_USB3
+ tristate "USB3 reset driver for UniPhier SoCs"
+ depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
+ default ARCH_UNIPHIER
+ select RESET_SIMPLE
+ help
+ Support for the USB3 core reset on UniPhier SoCs.
+ Say Y if you want to control reset signals provided by
+ USB3 glue layer.
+
config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST
default ARCH_ZYNQ
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index c1261dcfe9ad..0676b6b1976f 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -14,11 +14,13 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
new file mode 100644
index 000000000000..36db96750450
--- /dev/null
+++ b/drivers/reset/reset-qcom-aoss.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <dt-bindings/reset/qcom,sdm845-aoss.h>
+
+struct qcom_aoss_reset_map {
+ unsigned int reg;
+};
+
+struct qcom_aoss_desc {
+ const struct qcom_aoss_reset_map *resets;
+ size_t num_resets;
+};
+
+struct qcom_aoss_reset_data {
+ struct reset_controller_dev rcdev;
+ void __iomem *base;
+ const struct qcom_aoss_desc *desc;
+};
+
+static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
+ [AOSS_CC_MSS_RESTART] = {0x10000},
+ [AOSS_CC_CAMSS_RESTART] = {0x11000},
+ [AOSS_CC_VENUS_RESTART] = {0x12000},
+ [AOSS_CC_GPU_RESTART] = {0x13000},
+ [AOSS_CC_DISPSS_RESTART] = {0x14000},
+ [AOSS_CC_WCSS_RESTART] = {0x20000},
+ [AOSS_CC_LPASS_RESTART] = {0x30000},
+};
+
+static const struct qcom_aoss_desc sdm845_aoss_desc = {
+ .resets = sdm845_aoss_resets,
+ .num_resets = ARRAY_SIZE(sdm845_aoss_resets),
+};
+
+static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
+ struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
+}
+
+static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+ const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+ writel(1, data->base + map->reg);
+ /* Wait 6 32kHz sleep cycles for reset */
+ usleep_range(200, 300);
+ return 0;
+}
+
+static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+ const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+ writel(0, data->base + map->reg);
+ /* Wait 6 32kHz sleep cycles for reset */
+ usleep_range(200, 300);
+ return 0;
+}
+
+static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ qcom_aoss_control_assert(rcdev, idx);
+
+ return qcom_aoss_control_deassert(rcdev, idx);
+}
+
+static const struct reset_control_ops qcom_aoss_reset_ops = {
+ .reset = qcom_aoss_control_reset,
+ .assert = qcom_aoss_control_assert,
+ .deassert = qcom_aoss_control_deassert,
+};
+
+static int qcom_aoss_reset_probe(struct platform_device *pdev)
+{
+ struct qcom_aoss_reset_data *data;
+ struct device *dev = &pdev->dev;
+ const struct qcom_aoss_desc *desc;
+ struct resource *res;
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -EINVAL;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->desc = desc;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.ops = &qcom_aoss_reset_ops;
+ data->rcdev.nr_resets = desc->num_resets;
+ data->rcdev.of_node = dev->of_node;
+
+ return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static const struct of_device_id qcom_aoss_reset_of_match[] = {
+ { .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc },
+ {}
+};
+
+static struct platform_driver qcom_aoss_reset_driver = {
+ .probe = qcom_aoss_reset_probe,
+ .driver = {
+ .name = "qcom_aoss_reset",
+ .of_match_table = qcom_aoss_reset_of_match,
+ },
+};
+
+builtin_platform_driver(qcom_aoss_reset_driver);
+
+MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index f7ce8910a392..a91107fc9e27 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -87,6 +87,7 @@ const struct reset_control_ops reset_simple_ops = {
.deassert = reset_simple_deassert,
.status = reset_simple_status,
};
+EXPORT_SYMBOL_GPL(reset_simple_ops);
/**
* struct reset_simple_devdata - simple reset controller properties
diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-usb3.c
new file mode 100644
index 000000000000..ffa1b19b594d
--- /dev/null
+++ b/drivers/reset/reset-uniphier-usb3.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
+// Copyright 2018 Socionext Inc.
+// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "reset-simple.h"
+
+#define MAX_CLKS 2
+#define MAX_RSTS 2
+
+struct uniphier_usb3_reset_soc_data {
+ int nclks;
+ const char * const *clock_names;
+ int nrsts;
+ const char * const *reset_names;
+};
+
+struct uniphier_usb3_reset_priv {
+ struct clk_bulk_data clk[MAX_CLKS];
+ struct reset_control *rst[MAX_RSTS];
+ struct reset_simple_data rdata;
+ const struct uniphier_usb3_reset_soc_data *data;
+};
+
+static int uniphier_usb3_reset_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct uniphier_usb3_reset_priv *priv;
+ struct resource *res;
+ resource_size_t size;
+ const char *name;
+ int i, ret, nr;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->data = of_device_get_match_data(dev);
+ if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
+ priv->data->nrsts > MAX_RSTS))
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ size = resource_size(res);
+ priv->rdata.membase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->rdata.membase))
+ return PTR_ERR(priv->rdata.membase);
+
+ for (i = 0; i < priv->data->nclks; i++)
+ priv->clk[i].id = priv->data->clock_names[i];
+ ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < priv->data->nrsts; i++) {
+ name = priv->data->reset_names[i];
+ priv->rst[i] = devm_reset_control_get_shared(dev, name);
+ if (IS_ERR(priv->rst[i]))
+ return PTR_ERR(priv->rst[i]);
+ }
+
+ ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
+ if (ret)
+ return ret;
+
+ for (nr = 0; nr < priv->data->nrsts; nr++) {
+ ret = reset_control_deassert(priv->rst[nr]);
+ if (ret)
+ goto out_rst_assert;
+ }
+
+ spin_lock_init(&priv->rdata.lock);
+ priv->rdata.rcdev.owner = THIS_MODULE;
+ priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+ priv->rdata.rcdev.ops = &reset_simple_ops;
+ priv->rdata.rcdev.of_node = dev->of_node;
+ priv->rdata.active_low = true;
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
+ if (ret)
+ goto out_rst_assert;
+
+ return 0;
+
+out_rst_assert:
+ while (nr--)
+ reset_control_assert(priv->rst[nr]);
+
+ clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+ return ret;
+}
+
+static int uniphier_usb3_reset_remove(struct platform_device *pdev)
+{
+ struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < priv->data->nrsts; i++)
+ reset_control_assert(priv->rst[i]);
+
+ clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+ return 0;
+}
+
+static const char * const uniphier_pro4_clock_reset_names[] = {
+ "gio", "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
+ .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+ .clock_names = uniphier_pro4_clock_reset_names,
+ .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+ .reset_names = uniphier_pro4_clock_reset_names,
+};
+
+static const char * const uniphier_pxs2_clock_reset_names[] = {
+ "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
+ .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+ .clock_names = uniphier_pxs2_clock_reset_names,
+ .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+ .reset_names = uniphier_pxs2_clock_reset_names,
+};
+
+static const struct of_device_id uniphier_usb3_reset_match[] = {
+ {
+ .compatible = "socionext,uniphier-pro4-usb3-reset",
+ .data = &uniphier_pro4_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs2-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-ld20-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs3-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
+
+static struct platform_driver uniphier_usb3_reset_driver = {
+ .probe = uniphier_usb3_reset_probe,
+ .remove = uniphier_usb3_reset_remove,
+ .driver = {
+ .name = "uniphier-usb3-reset",
+ .of_match_table = uniphier_usb3_reset_match,
+ },
+};
+module_platform_driver(uniphier_usb3_reset_driver);
+
+MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
+MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index e9030ff1bf2f..5605745663ae 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -202,6 +202,12 @@ static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
UNIPHIER_RESETX((id), 0x114, 24 + (ch))
+#define UNIPHIER_PERI_RESET_SCSSI(id) \
+ UNIPHIER_RESETX((id), 0x110, 17)
+
+#define UNIPHIER_PERI_RESET_MCSSI(id) \
+ UNIPHIER_RESETX((id), 0x114, 14)
+
static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_UART(0, 0),
UNIPHIER_PERI_RESET_UART(1, 1),
@@ -212,6 +218,7 @@ static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_I2C(6, 2),
UNIPHIER_PERI_RESET_I2C(7, 3),
UNIPHIER_PERI_RESET_I2C(8, 4),
+ UNIPHIER_PERI_RESET_SCSSI(11),
UNIPHIER_RESET_END,
};
@@ -227,6 +234,8 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_FI2C(8, 4),
UNIPHIER_PERI_RESET_FI2C(9, 5),
UNIPHIER_PERI_RESET_FI2C(10, 6),
+ UNIPHIER_PERI_RESET_SCSSI(11),
+ UNIPHIER_PERI_RESET_MCSSI(12),
UNIPHIER_RESET_END,
};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index a2ba5db36145..7d7be60a2413 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -244,15 +244,6 @@ config RTC_DRV_DS1307
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
-config RTC_DRV_DS1307_HWMON
- bool "HWMON support for rtc-ds1307"
- depends on RTC_DRV_DS1307 && HWMON
- depends on !(RTC_DRV_DS1307=y && HWMON=m)
- default y
- help
- Say Y here if you want to expose temperature sensor data on
- rtc-ds1307 (only DS3231)
-
config RTC_DRV_DS1307_CENTURY
bool "Century bit support for rtc-ds1307"
depends on RTC_DRV_DS1307
@@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS
Unless you are debugging this driver, choose N.
-config RTC_DS1685_SYSFS_REGS
- bool "SysFS access to RTC register bits"
- depends on RTC_DRV_DS1685_FAMILY && SYSFS
- help
- Enable this to provide access to the RTC control register bits
- in /sys. Some of the bits are read-write, others are read-only.
-
- Keep in mind that reading Control C's bits automatically clears
- all pending IRQ flags - this can cause lost interrupts.
-
- If you know that you need access to these bits, choose Y, Else N.
-
config RTC_DRV_DS1742
tristate "Maxim/Dallas DS1742/1743"
depends on HAS_IOMEM
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index d37588f08055..0fca4d74c76b 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev)
return 0;
}
- getnstimeofday64(&old_system);
+ ktime_get_real_ts64(&old_system);
old_rtc.tv_sec = rtc_tm_to_time64(&tm);
@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
return 0;
/* snapshot the current rtc and system time at resume */
- getnstimeofday64(&new_system);
+ ktime_get_real_ts64(&new_system);
err = rtc_read_time(rtc, &tm);
if (err < 0) {
pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev));
@@ -172,7 +172,6 @@ static struct rtc_device *rtc_allocate_device(void)
mutex_init(&rtc->ops_lock);
spin_lock_init(&rtc->irq_lock);
- spin_lock_init(&rtc->irq_task_lock);
init_waitqueue_head(&rtc->irq_queue);
/* Init timerqueue */
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index bac1eeb3d312..3d577e259e91 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
spin_unlock_irqrestore(&rtc->irq_lock, flags);
- /* call the task func */
- spin_lock_irqsave(&rtc->irq_task_lock, flags);
- if (rtc->irq_task)
- rtc->irq_task->func(rtc->irq_task->private_data);
- spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
wake_up_interruptible(&rtc->irq_queue);
kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
}
@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc)
}
EXPORT_SYMBOL_GPL(rtc_class_close);
-int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
-{
- int retval = -EBUSY;
-
- if (task == NULL || task->func == NULL)
- return -EINVAL;
-
- /* Cannot register while the char dev is in use */
- if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
- return -EBUSY;
-
- spin_lock_irq(&rtc->irq_task_lock);
- if (rtc->irq_task == NULL) {
- rtc->irq_task = task;
- retval = 0;
- }
- spin_unlock_irq(&rtc->irq_task_lock);
-
- clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
-
- return retval;
-}
-EXPORT_SYMBOL_GPL(rtc_irq_register);
-
-void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
-{
- spin_lock_irq(&rtc->irq_task_lock);
- if (rtc->irq_task == task)
- rtc->irq_task = NULL;
- spin_unlock_irq(&rtc->irq_task_lock);
-}
-EXPORT_SYMBOL_GPL(rtc_irq_unregister);
-
static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
{
/*
@@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
* Context: any
*
* Note that rtc_irq_set_freq() should previously have been used to
- * specify the desired frequency of periodic IRQ task->func() callbacks.
+ * specify the desired frequency of periodic IRQ.
*/
-int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
+int rtc_irq_set_state(struct rtc_device *rtc, int enabled)
{
int err = 0;
- unsigned long flags;
-retry:
- spin_lock_irqsave(&rtc->irq_task_lock, flags);
- if (rtc->irq_task != NULL && task == NULL)
- err = -EBUSY;
- else if (rtc->irq_task != task)
- err = -EACCES;
- else {
- if (rtc_update_hrtimer(rtc, enabled) < 0) {
- spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
- cpu_relax();
- goto retry;
- }
- rtc->pie_enabled = enabled;
- }
- spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+ while (rtc_update_hrtimer(rtc, enabled) < 0)
+ cpu_relax();
+
+ rtc->pie_enabled = enabled;
trace_rtc_irq_set_state(enabled, err);
return err;
}
-EXPORT_SYMBOL_GPL(rtc_irq_set_state);
/**
* rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
* @rtc: the rtc device
* @task: currently registered with rtc_irq_register()
- * @freq: positive frequency with which task->func() will be called
+ * @freq: positive frequency
* Context: any
*
* Note that rtc_irq_set_state() is used to enable or disable the
* periodic IRQs.
*/
-int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
+int rtc_irq_set_freq(struct rtc_device *rtc, int freq)
{
int err = 0;
- unsigned long flags;
if (freq <= 0 || freq > RTC_MAX_FREQ)
return -EINVAL;
-retry:
- spin_lock_irqsave(&rtc->irq_task_lock, flags);
- if (rtc->irq_task != NULL && task == NULL)
- err = -EBUSY;
- else if (rtc->irq_task != task)
- err = -EACCES;
- else {
- rtc->irq_freq = freq;
- if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
- spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
- cpu_relax();
- goto retry;
- }
- }
- spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+ rtc->irq_freq = freq;
+ while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0)
+ cpu_relax();
trace_rtc_irq_set_freq(freq, err);
return err;
}
-EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
/**
* rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
@@ -979,8 +914,8 @@ again:
timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer);
timer->enabled = 0;
- if (timer->task.func)
- timer->task.func(timer->task.private_data);
+ if (timer->func)
+ timer->func(timer->private_data);
trace_rtc_timer_fired(timer);
/* Re-add/fwd periodic timers */
@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
{
timerqueue_init(&timer->node);
timer->enabled = 0;
- timer->task.func = f;
- timer->task.private_data = data;
+ timer->func = f;
+ timer->private_data = data;
}
/* rtc_timer_start - Sets an rtc_timer to fire in the future
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 1e4978c96ffd..bde53c8ccee2 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -30,6 +30,8 @@
#define RTC_IRQ_FREQ_1HZ BIT(2)
#define RTC_CCR 0x18
#define RTC_CCR_MODE BIT(15)
+#define RTC_CONF_TEST 0x1C
+#define RTC_NOMINAL_TIMING BIT(13)
#define RTC_TIME 0xC
#define RTC_ALARM1 0x10
@@ -75,6 +77,7 @@ struct armada38x_rtc {
void __iomem *regs_soc;
spinlock_t lock;
int irq;
+ bool initialized;
struct value_to_freq *val_to_freq;
struct armada38x_rtc_data *data;
};
@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
+{
+ u32 reg;
+
+ reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
+ /* If bits [7:0] are non-zero, assume RTC was uninitialized */
+ if (reg & 0xff) {
+ rtc_delayed_write(0, rtc, RTC_CONF_TEST);
+ msleep(500); /* Oscillator startup time */
+ rtc_delayed_write(0, rtc, RTC_TIME);
+ rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
+ RTC_STATUS);
+ rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
+ }
+ rtc->initialized = true;
+}
+
static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
if (ret)
goto out;
+ if (!rtc->initialized)
+ armada38x_rtc_reset(rtc);
+
spin_lock_irqsave(&rtc->lock, flags);
rtc_delayed_write(time, rtc, RTC_TIME);
spin_unlock_irqrestore(&rtc->lock, flags);
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index d768f6747961..113493b52149 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev)
} else if (p->r->flags & IORESOURCE_MEM) {
p->regs = devm_ioremap(&pdev->dev, p->r->start,
resource_size(p->r));
+ if (!p->regs){
+ err = -ENOMEM;
+ goto out;
+ }
p->read = bq4802_read_mem;
p->write = bq4802_write_mem;
} else {
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index 0abf98983e13..ccc17a2e293d 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#ifdef CONFIG_RTC_INTF_SYSFS
const struct attribute_group **rtc_get_dev_attribute_groups(void);
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
#else
static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
{
return NULL;
}
+
+static inline
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+ return 0;
+}
+
+static inline
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+ return 0;
+}
#endif
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index efa221e8bc22..43d962a9c210 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file,
return rtc_set_time(rtc, &tm);
case RTC_PIE_ON:
- err = rtc_irq_set_state(rtc, NULL, 1);
+ err = rtc_irq_set_state(rtc, 1);
break;
case RTC_PIE_OFF:
- err = rtc_irq_set_state(rtc, NULL, 0);
+ err = rtc_irq_set_state(rtc, 0);
break;
case RTC_AIE_ON:
@@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file,
return rtc_update_irq_enable(rtc, 0);
case RTC_IRQP_SET:
- err = rtc_irq_set_freq(rtc, NULL, arg);
+ err = rtc_irq_set_freq(rtc, arg);
break;
case RTC_IRQP_READ:
@@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
/* Keep ioctl until all drivers are converted */
rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
rtc_update_irq_enable(rtc, 0);
- rtc_irq_set_state(rtc, NULL, 0);
+ rtc_irq_set_state(rtc, 0);
clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
return 0;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index e9ec4160d7f6..4b2b4627daeb 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -44,6 +44,7 @@ enum ds_type {
ds_3231,
m41t0,
m41t00,
+ m41t11,
mcp794xx,
rx_8025,
rx_8130,
@@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = {
.irq_handler = rx8130_irq,
.rtc_ops = &rx8130_rtc_ops,
},
+ [m41t11] = {
+ /* this is battery backed SRAM */
+ .nvram_offset = 8,
+ .nvram_size = 56,
+ },
[mcp794xx] = {
.alarm = 1,
/* this is battery backed SRAM */
@@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = {
{ "ds3231", ds_3231 },
{ "m41t0", m41t0 },
{ "m41t00", m41t00 },
+ { "m41t11", m41t11 },
{ "mcp7940x", mcp794xx },
{ "mcp7941x", mcp794xx },
{ "pt7c4338", ds_1307 },
@@ -299,13 +306,17 @@ static const struct of_device_id ds1307_of_match[] = {
},
{
.compatible = "st,m41t0",
- .data = (void *)m41t00
+ .data = (void *)m41t0
},
{
.compatible = "st,m41t00",
.data = (void *)m41t00
},
{
+ .compatible = "st,m41t11",
+ .data = (void *)m41t11
+ },
+ {
.compatible = "microchip,mcp7940x",
.data = (void *)mcp794xx
},
@@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
{ .id = "DS3231", .driver_data = ds_3231 },
{ .id = "M41T0", .driver_data = m41t0 },
{ .id = "M41T00", .driver_data = m41t00 },
+ { .id = "M41T11", .driver_data = m41t11 },
{ .id = "MCP7940X", .driver_data = mcp794xx },
{ .id = "MCP7941X", .driver_data = mcp794xx },
{ .id = "PT7C4338", .driver_data = ds_1307 },
@@ -1030,7 +1042,7 @@ static u8 ds1307_trickle_init(struct ds1307 *ds1307,
/*----------------------------------------------------------------------*/
-#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+#if IS_REACHABLE(CONFIG_HWMON)
/*
* Temperature sensor support for ds3231 devices.
@@ -1576,6 +1588,7 @@ read_rtc:
case ds_1307:
case m41t0:
case m41t00:
+ case m41t11:
/* clock halted? turn it on, so clock can tick. */
if (tmp & DS1307_BIT_CH) {
regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
@@ -1641,6 +1654,7 @@ read_rtc:
case ds_1340:
case m41t0:
case m41t00:
+ case m41t11:
/*
* NOTE: ignores century bits; fix before deploying
* systems that will run through year 2100.
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 5c0db6c8134c..6f39f683a98c 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -1188,552 +1188,6 @@ ds1685_rtc_sysfs_misc_grp = {
.attrs = ds1685_rtc_sysfs_misc_attrs,
};
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_ctrl_regs {
- const char *name;
- const u8 reg;
- const u8 bit;
-};
-
-/*
- * Ctrl register bit lookup table.
- */
-static const struct ds1685_rtc_ctrl_regs
-ds1685_ctrl_regs_table[] = {
- { "uip", RTC_CTRL_A, RTC_CTRL_A_UIP },
- { "dv2", RTC_CTRL_A, RTC_CTRL_A_DV2 },
- { "dv1", RTC_CTRL_A, RTC_CTRL_A_DV1 },
- { "dv0", RTC_CTRL_A, RTC_CTRL_A_DV0 },
- { "rs3", RTC_CTRL_A, RTC_CTRL_A_RS3 },
- { "rs2", RTC_CTRL_A, RTC_CTRL_A_RS2 },
- { "rs1", RTC_CTRL_A, RTC_CTRL_A_RS1 },
- { "rs0", RTC_CTRL_A, RTC_CTRL_A_RS0 },
- { "set", RTC_CTRL_B, RTC_CTRL_B_SET },
- { "pie", RTC_CTRL_B, RTC_CTRL_B_PIE },
- { "aie", RTC_CTRL_B, RTC_CTRL_B_AIE },
- { "uie", RTC_CTRL_B, RTC_CTRL_B_UIE },
- { "sqwe", RTC_CTRL_B, RTC_CTRL_B_SQWE },
- { "dm", RTC_CTRL_B, RTC_CTRL_B_DM },
- { "2412", RTC_CTRL_B, RTC_CTRL_B_2412 },
- { "dse", RTC_CTRL_B, RTC_CTRL_B_DSE },
- { "irqf", RTC_CTRL_C, RTC_CTRL_C_IRQF },
- { "pf", RTC_CTRL_C, RTC_CTRL_C_PF },
- { "af", RTC_CTRL_C, RTC_CTRL_C_AF },
- { "uf", RTC_CTRL_C, RTC_CTRL_C_UF },
- { "vrt", RTC_CTRL_D, RTC_CTRL_D_VRT },
- { "vrt2", RTC_EXT_CTRL_4A, RTC_CTRL_4A_VRT2 },
- { "incr", RTC_EXT_CTRL_4A, RTC_CTRL_4A_INCR },
- { "pab", RTC_EXT_CTRL_4A, RTC_CTRL_4A_PAB },
- { "rf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_RF },
- { "wf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_WF },
- { "kf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_KF },
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
- { "bme", RTC_EXT_CTRL_4A, RTC_CTRL_4A_BME },
-#endif
- { "abe", RTC_EXT_CTRL_4B, RTC_CTRL_4B_ABE },
- { "e32k", RTC_EXT_CTRL_4B, RTC_CTRL_4B_E32K },
- { "cs", RTC_EXT_CTRL_4B, RTC_CTRL_4B_CS },
- { "rce", RTC_EXT_CTRL_4B, RTC_CTRL_4B_RCE },
- { "prs", RTC_EXT_CTRL_4B, RTC_CTRL_4B_PRS },
- { "rie", RTC_EXT_CTRL_4B, RTC_CTRL_4B_RIE },
- { "wie", RTC_EXT_CTRL_4B, RTC_CTRL_4B_WIE },
- { "kse", RTC_EXT_CTRL_4B, RTC_CTRL_4B_KSE },
- { NULL, 0, 0 },
-};
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_lookup - ctrl register bit lookup function.
- * @name: ctrl register bit to look up in ds1685_ctrl_regs_table.
- */
-static const struct ds1685_rtc_ctrl_regs*
-ds1685_rtc_sysfs_ctrl_regs_lookup(const char *name)
-{
- const struct ds1685_rtc_ctrl_regs *p = ds1685_ctrl_regs_table;
-
- for (; p->name != NULL; ++p)
- if (strcmp(p->name, name) == 0)
- return p;
-
- return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_show - reads a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u8 tmp;
- struct ds1685_priv *rtc = dev_get_drvdata(dev);
- const struct ds1685_rtc_ctrl_regs *reg_info =
- ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
- /* Make sure we actually matched something. */
- if (!reg_info)
- return -EINVAL;
-
- /* No spinlock during a read -- mutex is already held. */
- ds1685_rtc_switch_to_bank1(rtc);
- tmp = rtc->read(rtc, reg_info->reg) & reg_info->bit;
- ds1685_rtc_switch_to_bank0(rtc);
-
- return sprintf(buf, "%d\n", (tmp ? 1 : 0));
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_store - writes a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ds1685_priv *rtc = dev_get_drvdata(dev);
- u8 reg = 0, bit = 0, tmp;
- unsigned long flags;
- long int val = 0;
- const struct ds1685_rtc_ctrl_regs *reg_info =
- ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
- /* We only accept numbers. */
- if (kstrtol(buf, 10, &val) < 0)
- return -EINVAL;
-
- /* bits are binary, 0 or 1 only. */
- if ((val != 0) && (val != 1))
- return -ERANGE;
-
- /* Make sure we actually matched something. */
- if (!reg_info)
- return -EINVAL;
-
- reg = reg_info->reg;
- bit = reg_info->bit;
-
- /* Safe to spinlock during a write. */
- ds1685_rtc_begin_ctrl_access(rtc, &flags);
- tmp = rtc->read(rtc, reg);
- rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
- ds1685_rtc_end_ctrl_access(rtc, flags);
-
- return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RO - device_attribute for read-only register bit.
- * @bit: bit to read.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RO(bit) \
- static DEVICE_ATTR(bit, S_IRUGO, \
- ds1685_rtc_sysfs_ctrl_regs_show, NULL)
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RW - device_attribute for read-write register bit.
- * @bit: bit to read or write.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RW(bit) \
- static DEVICE_ATTR(bit, S_IRUGO | S_IWUSR, \
- ds1685_rtc_sysfs_ctrl_regs_show, \
- ds1685_rtc_sysfs_ctrl_regs_store)
-
-/*
- * Control Register A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(uip);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv1);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dv0);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs3);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs1);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs0);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrla_attrs[] = {
- &dev_attr_uip.attr,
- &dev_attr_dv2.attr,
- &dev_attr_dv1.attr,
- &dev_attr_dv0.attr,
- &dev_attr_rs3.attr,
- &dev_attr_rs2.attr,
- &dev_attr_rs1.attr,
- &dev_attr_rs0.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrla_grp = {
- .name = "ctrla",
- .attrs = ds1685_rtc_sysfs_ctrla_attrs,
-};
-
-
-/*
- * Control Register B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(set);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(aie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(uie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(sqwe);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dm);
-DS1685_RTC_SYSFS_CTRL_REG_RO(2412);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlb_attrs[] = {
- &dev_attr_set.attr,
- &dev_attr_pie.attr,
- &dev_attr_aie.attr,
- &dev_attr_uie.attr,
- &dev_attr_sqwe.attr,
- &dev_attr_dm.attr,
- &dev_attr_2412.attr,
- &dev_attr_dse.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlb_grp = {
- .name = "ctrlb",
- .attrs = ds1685_rtc_sysfs_ctrlb_attrs,
-};
-
-/*
- * Control Register C bits.
- *
- * Reading Control C clears these bits! Reading them individually can
- * possibly cause an interrupt to be missed. Use the /proc interface
- * to see all the bits in this register simultaneously.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(irqf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(pf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(af);
-DS1685_RTC_SYSFS_CTRL_REG_RO(uf);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlc_attrs[] = {
- &dev_attr_irqf.attr,
- &dev_attr_pf.attr,
- &dev_attr_af.attr,
- &dev_attr_uf.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlc_grp = {
- .name = "ctrlc",
- .attrs = ds1685_rtc_sysfs_ctrlc_attrs,
-};
-
-/*
- * Control Register D bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrld_attrs[] = {
- &dev_attr_vrt.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrld_grp = {
- .name = "ctrld",
- .attrs = ds1685_rtc_sysfs_ctrld_attrs,
-};
-
-/*
- * Control Register 4A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt2);
-DS1685_RTC_SYSFS_CTRL_REG_RO(incr);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pab);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kf);
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-DS1685_RTC_SYSFS_CTRL_REG_RO(bme);
-#endif
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4a_attrs[] = {
- &dev_attr_vrt2.attr,
- &dev_attr_incr.attr,
- &dev_attr_pab.attr,
- &dev_attr_rf.attr,
- &dev_attr_wf.attr,
- &dev_attr_kf.attr,
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
- &dev_attr_bme.attr,
-#endif
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4a_grp = {
- .name = "ctrl4a",
- .attrs = ds1685_rtc_sysfs_ctrl4a_attrs,
-};
-
-/*
- * Control Register 4B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RW(abe);
-DS1685_RTC_SYSFS_CTRL_REG_RW(e32k);
-DS1685_RTC_SYSFS_CTRL_REG_RO(cs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rce);
-DS1685_RTC_SYSFS_CTRL_REG_RW(prs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4b_attrs[] = {
- &dev_attr_abe.attr,
- &dev_attr_e32k.attr,
- &dev_attr_cs.attr,
- &dev_attr_rce.attr,
- &dev_attr_prs.attr,
- &dev_attr_rie.attr,
- &dev_attr_wie.attr,
- &dev_attr_kse.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4b_grp = {
- .name = "ctrl4b",
- .attrs = ds1685_rtc_sysfs_ctrl4b_attrs,
-};
-
-
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_time_regs {
- const char *name;
- const u8 reg;
- const u8 mask;
- const u8 min;
- const u8 max;
-};
-
-/*
- * Time/Date register lookup tables.
- */
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bcd_table[] = {
- { "seconds", RTC_SECS, RTC_SECS_BCD_MASK, 0, 59 },
- { "minutes", RTC_MINS, RTC_MINS_BCD_MASK, 0, 59 },
- { "hours", RTC_HRS, RTC_HRS_24_BCD_MASK, 0, 23 },
- { "wday", RTC_WDAY, RTC_WDAY_MASK, 1, 7 },
- { "mday", RTC_MDAY, RTC_MDAY_BCD_MASK, 1, 31 },
- { "month", RTC_MONTH, RTC_MONTH_BCD_MASK, 1, 12 },
- { "year", RTC_YEAR, RTC_YEAR_BCD_MASK, 0, 99 },
- { "century", RTC_CENTURY, RTC_CENTURY_MASK, 0, 99 },
- { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BCD_MASK, 0, 59 },
- { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BCD_MASK, 0, 59 },
- { "alarm_hours", RTC_HRS_ALARM, RTC_HRS_24_BCD_MASK, 0, 23 },
- { "alarm_mday", RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 1, 31 },
- { NULL, 0, 0, 0, 0 },
-};
-
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bin_table[] = {
- { "seconds", RTC_SECS, RTC_SECS_BIN_MASK, 0x00, 0x3b },
- { "minutes", RTC_MINS, RTC_MINS_BIN_MASK, 0x00, 0x3b },
- { "hours", RTC_HRS, RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
- { "wday", RTC_WDAY, RTC_WDAY_MASK, 0x01, 0x07 },
- { "mday", RTC_MDAY, RTC_MDAY_BIN_MASK, 0x01, 0x1f },
- { "month", RTC_MONTH, RTC_MONTH_BIN_MASK, 0x01, 0x0c },
- { "year", RTC_YEAR, RTC_YEAR_BIN_MASK, 0x00, 0x63 },
- { "century", RTC_CENTURY, RTC_CENTURY_MASK, 0x00, 0x63 },
- { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BIN_MASK, 0x00, 0x3b },
- { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BIN_MASK, 0x00, 0x3b },
- { "alarm_hours", RTC_HRS_ALARM, RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
- { "alarm_mday", RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 0x01, 0x1f },
- { NULL, 0, 0, 0x00, 0x00 },
-};
-
-/**
- * ds1685_rtc_sysfs_time_regs_bcd_lookup - time/date reg bit lookup function.
- * @name: register bit to look up in ds1685_time_regs_bcd_table.
- */
-static const struct ds1685_rtc_time_regs*
-ds1685_rtc_sysfs_time_regs_lookup(const char *name, bool bcd_mode)
-{
- const struct ds1685_rtc_time_regs *p;
-
- if (bcd_mode)
- p = ds1685_time_regs_bcd_table;
- else
- p = ds1685_time_regs_bin_table;
-
- for (; p->name != NULL; ++p)
- if (strcmp(p->name, name) == 0)
- return p;
-
- return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_show - reads a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u8 tmp;
- struct ds1685_priv *rtc = dev_get_drvdata(dev);
- const struct ds1685_rtc_time_regs *bcd_reg_info =
- ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
- const struct ds1685_rtc_time_regs *bin_reg_info =
- ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
- /* Make sure we actually matched something. */
- if (!bcd_reg_info || !bin_reg_info)
- return -EINVAL;
-
- /* bcd_reg_info->reg == bin_reg_info->reg. */
- ds1685_rtc_begin_data_access(rtc);
- tmp = rtc->read(rtc, bcd_reg_info->reg);
- ds1685_rtc_end_data_access(rtc);
-
- tmp = ds1685_rtc_bcd2bin(rtc, tmp, bcd_reg_info->mask,
- bin_reg_info->mask);
-
- return sprintf(buf, "%d\n", tmp);
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_store - writes a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- long int val = 0;
- struct ds1685_priv *rtc = dev_get_drvdata(dev);
- const struct ds1685_rtc_time_regs *bcd_reg_info =
- ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
- const struct ds1685_rtc_time_regs *bin_reg_info =
- ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
- /* We only accept numbers. */
- if (kstrtol(buf, 10, &val) < 0)
- return -EINVAL;
-
- /* Make sure we actually matched something. */
- if (!bcd_reg_info || !bin_reg_info)
- return -EINVAL;
-
- /* Check for a valid range. */
- if (rtc->bcd_mode) {
- if ((val < bcd_reg_info->min) || (val > bcd_reg_info->max))
- return -ERANGE;
- } else {
- if ((val < bin_reg_info->min) || (val > bin_reg_info->max))
- return -ERANGE;
- }
-
- val = ds1685_rtc_bin2bcd(rtc, val, bin_reg_info->mask,
- bcd_reg_info->mask);
-
- /* bcd_reg_info->reg == bin_reg_info->reg. */
- ds1685_rtc_begin_data_access(rtc);
- rtc->write(rtc, bcd_reg_info->reg, val);
- ds1685_rtc_end_data_access(rtc);
-
- return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_REG_RW - device_attribute for a read-write time register.
- * @reg: time/date register to read or write.
- */
-#define DS1685_RTC_SYSFS_TIME_REG_RW(reg) \
- static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, \
- ds1685_rtc_sysfs_time_regs_show, \
- ds1685_rtc_sysfs_time_regs_store)
-
-/*
- * Time/Date Register bits.
- */
-DS1685_RTC_SYSFS_TIME_REG_RW(seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(wday);
-DS1685_RTC_SYSFS_TIME_REG_RW(mday);
-DS1685_RTC_SYSFS_TIME_REG_RW(month);
-DS1685_RTC_SYSFS_TIME_REG_RW(year);
-DS1685_RTC_SYSFS_TIME_REG_RW(century);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_mday);
-
-static struct attribute*
-ds1685_rtc_sysfs_time_attrs[] = {
- &dev_attr_seconds.attr,
- &dev_attr_minutes.attr,
- &dev_attr_hours.attr,
- &dev_attr_wday.attr,
- &dev_attr_mday.attr,
- &dev_attr_month.attr,
- &dev_attr_year.attr,
- &dev_attr_century.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_time_grp = {
- .name = "datetime",
- .attrs = ds1685_rtc_sysfs_time_attrs,
-};
-
-static struct attribute*
-ds1685_rtc_sysfs_alarm_attrs[] = {
- &dev_attr_alarm_seconds.attr,
- &dev_attr_alarm_minutes.attr,
- &dev_attr_alarm_hours.attr,
- &dev_attr_alarm_mday.attr,
- NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_alarm_grp = {
- .name = "alarm",
- .attrs = ds1685_rtc_sysfs_alarm_attrs,
-};
-#endif /* CONFIG_RTC_DS1685_SYSFS_REGS */
-
-
/**
* ds1685_rtc_sysfs_register - register sysfs files.
* @dev: pointer to device structure.
@@ -1752,39 +1206,6 @@ ds1685_rtc_sysfs_register(struct device *dev)
if (ret)
return ret;
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
- if (ret)
- return ret;
-
- ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
- if (ret)
- return ret;
-#endif
return 0;
}
@@ -1798,17 +1219,6 @@ ds1685_rtc_sysfs_unregister(struct device *dev)
sysfs_remove_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr);
sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp);
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
- sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
-#endif
-
return 0;
}
#endif /* CONFIG_SYSFS */
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 1a2c38cc0178..ea18a8f4bce0 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -14,6 +14,8 @@
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
+#include "rtc-core.h"
+#include <linux/of_irq.h>
/* Register map */
/* rtc section */
@@ -33,13 +35,16 @@
#define ISL1208_REG_SR_ARST (1<<7) /* auto reset */
#define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */
#define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */
+#define ISL1208_REG_SR_EVT (1<<3) /* event */
#define ISL1208_REG_SR_ALM (1<<2) /* alarm */
#define ISL1208_REG_SR_BAT (1<<1) /* battery */
#define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */
#define ISL1208_REG_INT 0x08
#define ISL1208_REG_INT_ALME (1<<6) /* alarm enable */
#define ISL1208_REG_INT_IM (1<<7) /* interrupt/alarm mode */
-#define ISL1208_REG_09 0x09 /* reserved */
+#define ISL1219_REG_EV 0x09
+#define ISL1219_REG_EV_EVEN (1<<4) /* event detection enable */
+#define ISL1219_REG_EV_EVIENB (1<<7) /* event in pull-up disable */
#define ISL1208_REG_ATR 0x0a
#define ISL1208_REG_DTR 0x0b
@@ -57,8 +62,24 @@
#define ISL1208_REG_USR2 0x13
#define ISL1208_USR_SECTION_LEN 2
+/* event section */
+#define ISL1219_REG_SCT 0x14
+#define ISL1219_REG_MNT 0x15
+#define ISL1219_REG_HRT 0x16
+#define ISL1219_REG_DTT 0x17
+#define ISL1219_REG_MOT 0x18
+#define ISL1219_REG_YRT 0x19
+#define ISL1219_EVT_SECTION_LEN 6
+
static struct i2c_driver isl1208_driver;
+/* ISL1208 various variants */
+enum {
+ TYPE_ISL1208 = 0,
+ TYPE_ISL1218,
+ TYPE_ISL1219,
+};
+
/* block read */
static int
isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
@@ -80,8 +101,8 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
};
int ret;
- BUG_ON(reg > ISL1208_REG_USR2);
- BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+ WARN_ON(reg > ISL1219_REG_YRT);
+ WARN_ON(reg + len > ISL1219_REG_YRT + 1);
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret > 0)
@@ -104,8 +125,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
};
int ret;
- BUG_ON(reg > ISL1208_REG_USR2);
- BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+ WARN_ON(reg > ISL1219_REG_YRT);
+ WARN_ON(reg + len > ISL1219_REG_YRT + 1);
i2c_buf[0] = reg;
memcpy(&i2c_buf[1], &buf[0], len);
@@ -493,6 +514,73 @@ isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
}
+static ssize_t timestamp0_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = dev_get_drvdata(dev);
+ int sr;
+
+ sr = isl1208_i2c_get_sr(client);
+ if (sr < 0) {
+ dev_err(dev, "%s: reading SR failed\n", __func__);
+ return sr;
+ }
+
+ sr &= ~ISL1208_REG_SR_EVT;
+
+ sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+ if (sr < 0)
+ dev_err(dev, "%s: writing SR failed\n",
+ __func__);
+
+ return count;
+};
+
+static ssize_t timestamp0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = dev_get_drvdata(dev);
+ u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, };
+ struct rtc_time tm;
+ int sr;
+
+ sr = isl1208_i2c_get_sr(client);
+ if (sr < 0) {
+ dev_err(dev, "%s: reading SR failed\n", __func__);
+ return sr;
+ }
+
+ if (!(sr & ISL1208_REG_SR_EVT))
+ return 0;
+
+ sr = isl1208_i2c_read_regs(client, ISL1219_REG_SCT, regs,
+ ISL1219_EVT_SECTION_LEN);
+ if (sr < 0) {
+ dev_err(dev, "%s: reading event section failed\n",
+ __func__);
+ return 0;
+ }
+
+ /* MSB of each alarm register is an enable bit */
+ tm.tm_sec = bcd2bin(regs[ISL1219_REG_SCT - ISL1219_REG_SCT] & 0x7f);
+ tm.tm_min = bcd2bin(regs[ISL1219_REG_MNT - ISL1219_REG_SCT] & 0x7f);
+ tm.tm_hour = bcd2bin(regs[ISL1219_REG_HRT - ISL1219_REG_SCT] & 0x3f);
+ tm.tm_mday = bcd2bin(regs[ISL1219_REG_DTT - ISL1219_REG_SCT] & 0x3f);
+ tm.tm_mon =
+ bcd2bin(regs[ISL1219_REG_MOT - ISL1219_REG_SCT] & 0x1f) - 1;
+ tm.tm_year = bcd2bin(regs[ISL1219_REG_YRT - ISL1219_REG_SCT]) + 100;
+
+ sr = rtc_valid_tm(&tm);
+ if (sr)
+ return sr;
+
+ return sprintf(buf, "%llu\n",
+ (unsigned long long)rtc_tm_to_time64(&tm));
+};
+
+static DEVICE_ATTR_RW(timestamp0);
+
static irqreturn_t
isl1208_rtc_interrupt(int irq, void *data)
{
@@ -538,6 +626,13 @@ isl1208_rtc_interrupt(int irq, void *data)
return err;
}
+ if (sr & ISL1208_REG_SR_EVT) {
+ sysfs_notify(&rtc->dev.kobj, NULL,
+ dev_attr_timestamp0.attr.name);
+ dev_warn(&client->dev, "event detected");
+ handled = 1;
+ }
+
return handled ? IRQ_HANDLED : IRQ_NONE;
}
@@ -623,11 +718,39 @@ static const struct attribute_group isl1208_rtc_sysfs_files = {
.attrs = isl1208_rtc_attrs,
};
+static struct attribute *isl1219_rtc_attrs[] = {
+ &dev_attr_timestamp0.attr,
+ NULL
+};
+
+static const struct attribute_group isl1219_rtc_sysfs_files = {
+ .attrs = isl1219_rtc_attrs,
+};
+
+static int isl1208_setup_irq(struct i2c_client *client, int irq)
+{
+ int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
+ isl1208_rtc_interrupt,
+ IRQF_SHARED | IRQF_ONESHOT,
+ isl1208_driver.driver.name,
+ client);
+ if (!rc) {
+ device_init_wakeup(&client->dev, 1);
+ enable_irq_wake(irq);
+ } else {
+ dev_err(&client->dev,
+ "Unable to request irq %d, no alarm support\n",
+ irq);
+ }
+ return rc;
+}
+
static int
isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int rc = 0;
struct rtc_device *rtc;
+ int evdet_irq = -1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@@ -642,6 +765,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
rtc->ops = &isl1208_rtc_ops;
i2c_set_clientdata(client, rtc);
+ dev_set_drvdata(&rtc->dev, client);
rc = isl1208_i2c_get_sr(client);
if (rc < 0) {
@@ -653,26 +777,46 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_warn(&client->dev, "rtc power failure detected, "
"please set clock.\n");
+ if (id->driver_data == TYPE_ISL1219) {
+ struct device_node *np = client->dev.of_node;
+ u32 evienb;
+
+ rc = i2c_smbus_read_byte_data(client, ISL1219_REG_EV);
+ if (rc < 0) {
+ dev_err(&client->dev, "failed to read EV reg\n");
+ return rc;
+ }
+ rc |= ISL1219_REG_EV_EVEN;
+ if (!of_property_read_u32(np, "isil,ev-evienb", &evienb)) {
+ if (evienb)
+ rc |= ISL1219_REG_EV_EVIENB;
+ else
+ rc &= ~ISL1219_REG_EV_EVIENB;
+ }
+ rc = i2c_smbus_write_byte_data(client, ISL1219_REG_EV, rc);
+ if (rc < 0) {
+ dev_err(&client->dev, "could not enable tamper detection\n");
+ return rc;
+ }
+ rc = rtc_add_group(rtc, &isl1219_rtc_sysfs_files);
+ if (rc)
+ return rc;
+ evdet_irq = of_irq_get_byname(np, "evdet");
+ }
+
rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
if (rc)
return rc;
- if (client->irq > 0) {
- rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- isl1208_rtc_interrupt,
- IRQF_SHARED | IRQF_ONESHOT,
- isl1208_driver.driver.name,
- client);
- if (!rc) {
- device_init_wakeup(&client->dev, 1);
- enable_irq_wake(client->irq);
- } else {
- dev_err(&client->dev,
- "Unable to request irq %d, no alarm support\n",
- client->irq);
- client->irq = 0;
- }
- }
+ if (client->irq > 0)
+ rc = isl1208_setup_irq(client, client->irq);
+ if (rc)
+ return rc;
+
+ if (evdet_irq > 0 && evdet_irq != client->irq)
+ rc = isl1208_setup_irq(client, evdet_irq);
+ if (rc)
+ return rc;
return rtc_register_device(rtc);
}
@@ -686,8 +830,9 @@ isl1208_remove(struct i2c_client *client)
}
static const struct i2c_device_id isl1208_id[] = {
- { "isl1208", 0 },
- { "isl1218", 0 },
+ { "isl1208", TYPE_ISL1208 },
+ { "isl1218", TYPE_ISL1218 },
+ { "isl1219", TYPE_ISL1219 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
@@ -695,6 +840,7 @@ MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const struct of_device_id isl1208_of_match[] = {
{ .compatible = "isil,isl1208" },
{ .compatible = "isil,isl1218" },
+ { .compatible = "isil,isl1219" },
{ }
};
MODULE_DEVICE_TABLE(of, isl1208_of_match);
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 1053a406b3aa..ac9ca1042889 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -373,7 +373,6 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
struct m48t59_private *m48t59 = NULL;
struct resource *res;
int ret = -ENOMEM;
- char *name;
const struct rtc_class_ops *ops;
struct nvmem_config nvmem_cfg = {
.name = "m48t59-",
@@ -448,17 +447,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
}
switch (pdata->type) {
case M48T59RTC_TYPE_M48T59:
- name = "m48t59";
ops = &m48t59_rtc_ops;
pdata->offset = 0x1ff0;
break;
case M48T59RTC_TYPE_M48T02:
- name = "m48t02";
ops = &m48t02_rtc_ops;
pdata->offset = 0x7f0;
break;
case M48T59RTC_TYPE_M48T08:
- name = "m48t08";
ops = &m48t02_rtc_ops;
pdata->offset = 0x1ff0;
break;
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index cefde273fae6..8a60900d6b8b 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX77686 and MAX77802
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- * based on rtc-max8997.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX77686 and MAX77802
+//
+// Copyright (C) 2012 Samsung Electronics Co.Ltd
+//
+// based on rtc-max8997.c
#include <linux/i2c.h>
#include <linux/slab.h>
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index e8cee123e8aa..08c661a332ec 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8997
- *
- * Copyright (C) 2013 Samsung Electronics Co.Ltd
- *
- * based on rtc-max8998.c
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8997
+//
+// Copyright (C) 2013 Samsung Electronics Co.Ltd
+//
+// based on rtc-max8998.c
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/rtc/rtc-max8998.c b/drivers/rtc/rtc-max8998.c
index d8c0f9b3f87d..c873b4509b3c 100644
--- a/drivers/rtc/rtc-max8998.c
+++ b/drivers/rtc/rtc-max8998.c
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8998
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Minkyu Kang <mk7.kang@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8998
+//
+// Copyright (C) 2010 Samsung Electronics Co.Ltd
+// Author: Minkyu Kang <mk7.kang@samsung.com>
+// Author: Joonyoung Shim <jy0922.shim@samsung.com>
#include <linux/module.h>
#include <linux/i2c.h>
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 39086398833e..323ff55cc165 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -449,6 +449,7 @@ static void omap_rtc_power_off(void)
if (tm2bcd(&tm) < 0) {
dev_err(&rtc->rtc->dev, "power off failed\n");
+ rtc->type->lock(rtc);
return;
}
@@ -582,9 +583,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
u32 val;
u16 arg = 0;
- rtc->type->unlock(rtc);
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
- rtc->type->lock(rtc);
switch (param) {
case PIN_CONFIG_INPUT_ENABLE:
@@ -614,9 +613,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
u32 param_val;
int i;
- rtc->type->unlock(rtc);
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
- rtc->type->lock(rtc);
/* active low by default */
val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
@@ -861,13 +858,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
goto err;
}
- if (rtc->is_pmic_controller) {
- if (!pm_power_off) {
- omap_rtc_power_off_rtc = rtc;
- pm_power_off = omap_rtc_power_off;
- }
- }
-
/* Support ext_wakeup pinconf */
rtc_pinctrl_desc.name = dev_name(&pdev->dev);
@@ -880,12 +870,21 @@ static int omap_rtc_probe(struct platform_device *pdev)
ret = rtc_register_device(rtc->rtc);
if (ret)
- goto err;
+ goto err_deregister_pinctrl;
rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
+ if (rtc->is_pmic_controller) {
+ if (!pm_power_off) {
+ omap_rtc_power_off_rtc = rtc;
+ pm_power_off = omap_rtc_power_off;
+ }
+ }
+
return 0;
+err_deregister_pinctrl:
+ pinctrl_unregister(rtc->pctldev);
err:
clk_disable_unprepare(rtc->clk);
device_init_wakeup(&pdev->dev, false);
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index e83be1852c2f..9f99a0966550 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -36,6 +36,11 @@
#define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09)
+/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
+#define PCF2127_REG_RAM_addr_MSB 0x1a
+#define PCF2127_REG_RAM_wrt_cmd 0x1c
+#define PCF2127_REG_RAM_rd_cmd 0x1d
+
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
struct pcf2127 {
@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
.set_time = pcf2127_rtc_set_time,
};
+static int pcf2127_nvmem_read(void *priv, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct pcf2127 *pcf2127 = priv;
+ int ret;
+ unsigned char offsetbuf[] = { offset >> 8, offset };
+
+ ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+ offsetbuf, 2);
+ if (ret)
+ return ret;
+
+ ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
+ val, bytes);
+
+ return ret ?: bytes;
+}
+
+static int pcf2127_nvmem_write(void *priv, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct pcf2127 *pcf2127 = priv;
+ int ret;
+ unsigned char offsetbuf[] = { offset >> 8, offset };
+
+ ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+ offsetbuf, 2);
+ if (ret)
+ return ret;
+
+ ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
+ val, bytes);
+
+ return ret ?: bytes;
+}
+
static int pcf2127_probe(struct device *dev, struct regmap *regmap,
- const char *name)
+ const char *name, bool has_nvmem)
{
struct pcf2127 *pcf2127;
+ int ret = 0;
dev_dbg(dev, "%s\n", __func__);
@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
THIS_MODULE);
+ if (IS_ERR(pcf2127->rtc))
+ return PTR_ERR(pcf2127->rtc);
+
+ if (has_nvmem) {
+ struct nvmem_config nvmem_cfg = {
+ .priv = pcf2127,
+ .reg_read = pcf2127_nvmem_read,
+ .reg_write = pcf2127_nvmem_write,
+ .size = 512,
+ };
+
+ ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
+ }
- return PTR_ERR_OR_ZERO(pcf2127->rtc);
+ return ret;
}
#ifdef CONFIG_OF
@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
}
return pcf2127_probe(&client->dev, regmap,
- pcf2127_i2c_driver.driver.name);
+ pcf2127_i2c_driver.driver.name, id->driver_data);
}
static const struct i2c_device_id pcf2127_i2c_id[] = {
- { "pcf2127", 0 },
+ { "pcf2127", 1 },
{ "pcf2129", 0 },
{ }
};
@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
return PTR_ERR(regmap);
}
- return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+ return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
+ spi_get_device_id(spi)->driver_data);
}
static const struct spi_device_id pcf2127_spi_id[] = {
- { "pcf2127", 0 },
+ { "pcf2127", 1 },
{ "pcf2129", 0 },
{ }
};
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 49bcbb3d4a69..283c2335b01b 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -43,37 +43,38 @@ static struct i2c_driver pcf85063_driver;
static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
{
- s32 ret;
+ int rc;
+ u8 reg;
- ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
- if (ret < 0) {
+ rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
+ if (rc < 0) {
dev_err(&client->dev, "Failing to stop the clock\n");
return -EIO;
}
/* stop the clock */
- ret |= PCF85063_REG_CTRL1_STOP;
+ reg = rc | PCF85063_REG_CTRL1_STOP;
- ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
- if (ret < 0) {
+ rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
+ if (rc < 0) {
dev_err(&client->dev, "Failing to stop the clock\n");
return -EIO;
}
- *ctrl1 = ret;
+ *ctrl1 = reg;
return 0;
}
static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
{
- s32 ret;
+ int rc;
/* start the clock */
ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
- ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
- if (ret < 0) {
+ rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
+ if (rc < 0) {
dev_err(&client->dev, "Failing to start the clock\n");
return -EIO;
}
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 8428455432ca..6495f84f7428 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -1,19 +1,9 @@
-/*
- * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
- * http://www.samsung.com
- *
- * Copyright (C) 2013 Google, Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
+// http://www.samsung.com
+//
+// Copyright (C) 2013 Google, Inc
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index ed71d1113627..304d905cb23f 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -224,7 +224,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
info->rtc = rtc;
rtc->max_user_freq = RTC_FREQ;
- rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_interrupt().
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 776b70a14e03..51ba414798a8 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -143,8 +143,6 @@ static int __sh_rtc_alarm(struct sh_rtc *rtc)
static int __sh_rtc_periodic(struct sh_rtc *rtc)
{
- struct rtc_device *rtc_dev = rtc->rtc_dev;
- struct rtc_task *irq_task;
unsigned int tmp, pending;
tmp = readb(rtc->regbase + RCR2);
@@ -161,14 +159,7 @@ static int __sh_rtc_periodic(struct sh_rtc *rtc)
else {
if (rtc->periodic_freq & PF_HP)
rtc->periodic_freq |= PF_COUNT;
- if (rtc->periodic_freq & PF_KOU) {
- spin_lock(&rtc_dev->irq_task_lock);
- irq_task = rtc_dev->irq_task;
- if (irq_task)
- irq_task->func(irq_task->private_data);
- spin_unlock(&rtc_dev->irq_task_lock);
- } else
- rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
}
return pending;
@@ -224,81 +215,6 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
return IRQ_RETVAL(ret);
}
-static int sh_rtc_irq_set_state(struct device *dev, int enable)
-{
- struct sh_rtc *rtc = dev_get_drvdata(dev);
- unsigned int tmp;
-
- spin_lock_irq(&rtc->lock);
-
- tmp = readb(rtc->regbase + RCR2);
-
- if (enable) {
- rtc->periodic_freq |= PF_KOU;
- tmp &= ~RCR2_PEF; /* Clear PES bit */
- tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */
- } else {
- rtc->periodic_freq &= ~PF_KOU;
- tmp &= ~(RCR2_PESMASK | RCR2_PEF);
- }
-
- writeb(tmp, rtc->regbase + RCR2);
-
- spin_unlock_irq(&rtc->lock);
-
- return 0;
-}
-
-static int sh_rtc_irq_set_freq(struct device *dev, int freq)
-{
- struct sh_rtc *rtc = dev_get_drvdata(dev);
- int tmp, ret = 0;
-
- spin_lock_irq(&rtc->lock);
- tmp = rtc->periodic_freq & PF_MASK;
-
- switch (freq) {
- case 0:
- rtc->periodic_freq = 0x00;
- break;
- case 1:
- rtc->periodic_freq = 0x60;
- break;
- case 2:
- rtc->periodic_freq = 0x50;
- break;
- case 4:
- rtc->periodic_freq = 0x40;
- break;
- case 8:
- rtc->periodic_freq = 0x30 | PF_HP;
- break;
- case 16:
- rtc->periodic_freq = 0x30;
- break;
- case 32:
- rtc->periodic_freq = 0x20 | PF_HP;
- break;
- case 64:
- rtc->periodic_freq = 0x20;
- break;
- case 128:
- rtc->periodic_freq = 0x10 | PF_HP;
- break;
- case 256:
- rtc->periodic_freq = 0x10;
- break;
- default:
- ret = -ENOTSUPP;
- }
-
- if (ret == 0)
- rtc->periodic_freq |= tmp;
-
- spin_unlock_irq(&rtc->lock);
- return ret;
-}
-
static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -675,8 +591,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
/* everything disabled by default */
- sh_rtc_irq_set_freq(&pdev->dev, 0);
- sh_rtc_irq_set_state(&pdev->dev, 0);
sh_rtc_setaie(&pdev->dev, 0);
sh_rtc_setcie(&pdev->dev, 0);
@@ -708,8 +622,6 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
{
struct sh_rtc *rtc = platform_get_drvdata(pdev);
- sh_rtc_irq_set_state(&pdev->dev, 0);
-
sh_rtc_setaie(&pdev->dev, 0);
sh_rtc_setcie(&pdev->dev, 0);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index 8a75cc3af6e7..b2483a749ac4 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -40,49 +40,83 @@ struct snvs_rtc_data {
struct clk *clk;
};
+/* Read 64 bit timer register, which could be in inconsistent state */
+static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
+{
+ u32 msb, lsb;
+
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
+ return (u64)msb << 32 | lsb;
+}
+
+/* Read the secure real time counter, taking care to deal with the cases of the
+ * counter updating while being read.
+ */
static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
{
u64 read1, read2;
- u32 val;
+ unsigned int timeout = 100;
+ /* As expected, the registers might update between the read of the LSB
+ * reg and the MSB reg. It's also possible that one register might be
+ * in partially modified state as well.
+ */
+ read1 = rtc_read_lpsrt(data);
do {
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
- read1 = val;
- read1 <<= 32;
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
- read1 |= val;
-
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
- read2 = val;
- read2 <<= 32;
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
- read2 |= val;
- } while (read1 != read2);
+ read2 = read1;
+ read1 = rtc_read_lpsrt(data);
+ } while (read1 != read2 && --timeout);
+ if (!timeout)
+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
/* Convert 47-bit counter to 32-bit raw second count */
return (u32) (read1 >> CNTR_TO_SECS_SH);
}
-static void rtc_write_sync_lp(struct snvs_rtc_data *data)
+/* Just read the lsb from the counter, dealing with inconsistent state */
+static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
+{
+ u32 count1, count2;
+ unsigned int timeout = 100;
+
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+ do {
+ count2 = count1;
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+ } while (count1 != count2 && --timeout);
+ if (!timeout) {
+ dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+ return -ETIMEDOUT;
+ }
+
+ *lsb = count1;
+ return 0;
+}
+
+static int rtc_write_sync_lp(struct snvs_rtc_data *data)
{
- u32 count1, count2, count3;
- int i;
-
- /* Wait for 3 CKIL cycles */
- for (i = 0; i < 3; i++) {
- do {
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
- } while (count1 != count2);
-
- /* Now wait until counter value changes */
- do {
- do {
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
- regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
- } while (count2 != count3);
- } while (count3 == count1);
+ u32 count1, count2;
+ u32 elapsed;
+ unsigned int timeout = 1000;
+ int ret;
+
+ ret = rtc_read_lp_counter_lsb(data, &count1);
+ if (ret)
+ return ret;
+
+ /* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
+ do {
+ ret = rtc_read_lp_counter_lsb(data, &count2);
+ if (ret)
+ return ret;
+ elapsed = count2 - count1; /* wrap around _is_ handled! */
+ } while (elapsed < 3 && --timeout);
+ if (!timeout) {
+ dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
+ return -ETIMEDOUT;
}
+ return 0;
}
static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
@@ -166,9 +200,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
- rtc_write_sync_lp(data);
-
- return 0;
+ return rtc_write_sync_lp(data);
}
static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -176,11 +208,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct snvs_rtc_data *data = dev_get_drvdata(dev);
struct rtc_time *alrm_tm = &alrm->time;
unsigned long time;
+ int ret;
rtc_tm_to_time(alrm_tm, &time);
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
- rtc_write_sync_lp(data);
+ ret = rtc_write_sync_lp(data);
+ if (ret)
+ return ret;
regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
/* Clear alarm interrupt status bit */
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index d578e40d5a50..b76318fd5bb0 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -288,10 +288,22 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc_data);
- err = stmp_reset_block(rtc_data->io);
- if (err) {
- dev_err(&pdev->dev, "stmp_reset_block failed: %d\n", err);
- return err;
+ /*
+ * Resetting the rtc stops the watchdog timer that is potentially
+ * running. So (assuming it is running on purpose) don't reset if the
+ * watchdog is enabled.
+ */
+ if (readl(rtc_data->io + STMP3XXX_RTC_CTRL) &
+ STMP3XXX_RTC_CTRL_WATCHDOGEN) {
+ dev_info(&pdev->dev,
+ "Watchdog is running, skip resetting rtc\n");
+ } else {
+ err = stmp_reset_block(rtc_data->io);
+ if (err) {
+ dev_err(&pdev->dev, "stmp_reset_block failed: %d\n",
+ err);
+ return err;
+ }
}
/*
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 454da38c6012..f1ff30ade534 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
{
return rtc_attr_groups;
}
+
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+ size_t old_cnt = 0, add_cnt = 0, new_cnt;
+ const struct attribute_group **groups, **old;
+
+ if (rtc->registered)
+ return -EINVAL;
+ if (!grps)
+ return -EINVAL;
+
+ groups = rtc->dev.groups;
+ if (groups)
+ for (; *groups; groups++)
+ old_cnt++;
+
+ for (groups = grps; *groups; groups++)
+ add_cnt++;
+
+ new_cnt = old_cnt + add_cnt + 1;
+ groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
+ if (IS_ERR_OR_NULL(groups))
+ return PTR_ERR(groups);
+ memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
+ memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
+ groups[old_cnt + add_cnt] = NULL;
+
+ old = rtc->dev.groups;
+ rtc->dev.groups = groups;
+ if (old && old != rtc_attr_groups)
+ devm_kfree(&rtc->dev, old);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtc_add_groups);
+
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+ const struct attribute_group *groups[] = { grp, NULL };
+
+ return rtc_add_groups(rtc, groups);
+}
+EXPORT_SYMBOL(rtc_add_group);
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 8469256edc2a..ade6a82709be 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -22,7 +22,7 @@ struct rtc_test_data {
bool alarm_en;
};
-struct platform_device *pdev[MAX_RTC_TEST];
+static struct platform_device *pdev[MAX_RTC_TEST];
static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
index dcf8c8065508..a5577dd5eb08 100644
--- a/drivers/soc/bcm/brcmstb/pm/pm-arm.c
+++ b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
@@ -628,10 +628,26 @@ static const struct of_device_id ddr_shimphy_dt_ids[] = {
static const struct of_device_id brcmstb_memc_of_match[] = {
{
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
+ .data = &ddr_seq,
+ },
+ {
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
.data = &ddr_seq_b22,
},
{
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
+ .data = &ddr_seq_b22,
+ },
+ {
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
+ .data = &ddr_seq_b22,
+ },
+ {
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
+ .data = &ddr_seq_b22,
+ },
+ {
.compatible = "brcm,brcmstb-memc-ddr",
.data = &ddr_seq,
},
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 7a9fb9baa66d..8f80e8bbf29e 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -1,7 +1,9 @@
#
-# Freescale SOC drivers
+# NXP/Freescale QorIQ series SOC drivers
#
+menu "NXP/Freescale QorIQ SoC drivers"
+
source "drivers/soc/fsl/qbman/Kconfig"
source "drivers/soc/fsl/qe/Kconfig"
@@ -16,3 +18,14 @@ config FSL_GUTS
Initially only reading SVR and registering soc device are supported.
Other guts accesses, such as reading RCW, should eventually be moved
into this driver as well.
+
+config FSL_MC_DPIO
+ tristate "QorIQ DPAA2 DPIO driver"
+ depends on FSL_MC_BUS
+ help
+ Driver for the DPAA2 DPIO object. A DPIO provides queue and
+ buffer management facilities for software to interact with
+ other DPAA2 objects. This driver does not expose the DPIO
+ objects individually, but groups them under a service layer
+ API.
+endmenu
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 44b3bebef24a..803ef1bfb5ff 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA) += qbman/
obj-$(CONFIG_QUICC_ENGINE) += qe/
obj-$(CONFIG_CPM) += qe/
obj-$(CONFIG_FSL_GUTS) += guts.o
+obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/staging/fsl-mc/bus/dpio/Makefile b/drivers/soc/fsl/dpio/Makefile
index b9ff24c76582..b9ff24c76582 100644
--- a/drivers/staging/fsl-mc/bus/dpio/Makefile
+++ b/drivers/soc/fsl/dpio/Makefile
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h
index ab8f82ee7ee5..ab8f82ee7ee5 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h
+++ b/drivers/soc/fsl/dpio/dpio-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c
index 11a90a90d827..b60b77bfaffa 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
+++ b/drivers/soc/fsl/dpio/dpio-driver.c
@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
#include "qbman-portal.h"
#include "dpio.h"
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index 14ed2beb7432..9b17f72349ed 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -6,7 +6,7 @@
*/
#include <linux/types.h>
#include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c
index ff37c80e11a0..ff37c80e11a0 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio.c
+++ b/drivers/soc/fsl/dpio/dpio.c
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.h b/drivers/soc/fsl/dpio/dpio.h
index 49194c8e45f1..49194c8e45f1 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio.h
+++ b/drivers/soc/fsl/dpio/dpio.h
diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c
index 116fafb28640..cf1d448ea468 100644
--- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
+++ b/drivers/soc/fsl/dpio/qbman-portal.c
@@ -8,7 +8,7 @@
#include <asm/cacheflush.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include "../../include/dpaa2-global.h"
+#include <soc/fsl/dpaa2-global.h>
#include "qbman-portal.h"
diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h b/drivers/soc/fsl/dpio/qbman-portal.h
index 69db3c818742..89d1dd9969b6 100644
--- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
+++ b/drivers/soc/fsl/dpio/qbman-portal.h
@@ -7,7 +7,7 @@
#ifndef __FSL_QBMAN_PORTAL_H
#define __FSL_QBMAN_PORTAL_H
-#include "../../include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
struct dpaa2_dq;
struct qbman_swp;
diff --git a/drivers/soc/fsl/qbman/Kconfig b/drivers/soc/fsl/qbman/Kconfig
index fb4e6bf0a0c4..d570cb5fd381 100644
--- a/drivers/soc/fsl/qbman/Kconfig
+++ b/drivers/soc/fsl/qbman/Kconfig
@@ -1,5 +1,5 @@
menuconfig FSL_DPAA
- bool "Freescale DPAA 1.x support"
+ bool "QorIQ DPAA1 framework support"
depends on (FSL_SOC_BOOKE || ARCH_LAYERSCAPE)
select GENERIC_ALLOCATOR
help
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index 73a2e08b47ef..fabba17e9d65 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -3,7 +3,7 @@
#
config QUICC_ENGINE
- bool "Freescale QUICC Engine (QE) Support"
+ bool "QUICC Engine (QE) framework support"
depends on FSL_SOC && PPC32
select GENERIC_ALLOCATOR
select CRC32
diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c
index 3b27075c21a7..819bed0f5667 100644
--- a/drivers/soc/fsl/qe/gpio.c
+++ b/drivers/soc/fsl/qe/gpio.c
@@ -83,6 +83,33 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&qe_gc->lock, flags);
}
+static void qe_gpio_set_multiple(struct gpio_chip *gc,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ for (i = 0; i < gc->ngpio; i++) {
+ if (*mask == 0)
+ break;
+ if (__test_and_clear_bit(i, mask)) {
+ if (test_bit(i, bits))
+ qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i));
+ else
+ qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i));
+ }
+ }
+
+ out_be32(&regs->cpdata, qe_gc->cpdata);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+
static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@@ -298,6 +325,7 @@ static int __init qe_add_gpiochips(void)
gc->direction_output = qe_gpio_dir_out;
gc->get = qe_gpio_get;
gc->set = qe_gpio_set;
+ gc->set_multiple = qe_gpio_set_multiple;
ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc);
if (ret)
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index 546960a18d60..b3da635970ea 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -54,7 +54,6 @@ struct imx_pm_domain {
unsigned int reg_offs;
signed char cntr_pdn_bit;
unsigned int ipg_rate_mhz;
- unsigned int flags;
};
static inline struct imx_pm_domain *
@@ -69,9 +68,6 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
int iso, iso2sw;
u32 val;
- if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
- return -EBUSY;
-
/* Read ISO and ISO2SW power down delays */
regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
iso = val & 0x3f;
@@ -295,26 +291,31 @@ static struct imx_pm_domain imx_gpc_domains[] = {
struct imx_gpc_dt_data {
int num_domains;
bool err009619_present;
+ bool err006287_present;
};
static const struct imx_gpc_dt_data imx6q_dt_data = {
.num_domains = 2,
.err009619_present = false,
+ .err006287_present = false,
};
static const struct imx_gpc_dt_data imx6qp_dt_data = {
.num_domains = 2,
.err009619_present = true,
+ .err006287_present = false,
};
static const struct imx_gpc_dt_data imx6sl_dt_data = {
.num_domains = 3,
.err009619_present = false,
+ .err006287_present = true,
};
static const struct imx_gpc_dt_data imx6sx_dt_data = {
.num_domains = 4,
.err009619_present = false,
+ .err006287_present = false,
};
static const struct of_device_id imx_gpc_dt_ids[] = {
@@ -434,8 +435,13 @@ static int imx_gpc_probe(struct platform_device *pdev)
/* Disable PU power down in normal operation if ERR009619 is present */
if (of_id_data->err009619_present)
- imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
- PGC_DOMAIN_FLAG_NO_PD;
+ imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
+ GENPD_FLAG_ALWAYS_ON;
+
+ /* Keep DISP always on if ERR006287 is present */
+ if (of_id_data->err006287_present)
+ imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
+ GENPD_FLAG_ALWAYS_ON;
if (!pgc_node) {
ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 2afae64061d8..4e931fdf4d09 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -146,6 +146,21 @@ static const u32 mt6397_regs[] = {
[PWRAP_DEW_CIPHER_SWRST] = 0xbc24,
};
+static const u32 mt6351_regs[] = {
+ [PWRAP_DEW_DIO_EN] = 0x02F2,
+ [PWRAP_DEW_READ_TEST] = 0x02F4,
+ [PWRAP_DEW_WRITE_TEST] = 0x02F6,
+ [PWRAP_DEW_CRC_EN] = 0x02FA,
+ [PWRAP_DEW_CRC_VAL] = 0x02FC,
+ [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300,
+ [PWRAP_DEW_CIPHER_IV_SEL] = 0x0302,
+ [PWRAP_DEW_CIPHER_EN] = 0x0304,
+ [PWRAP_DEW_CIPHER_RDY] = 0x0306,
+ [PWRAP_DEW_CIPHER_MODE] = 0x0308,
+ [PWRAP_DEW_CIPHER_SWRST] = 0x030A,
+ [PWRAP_DEW_RDDMY_NO] = 0x030C,
+};
+
enum pwrap_regs {
PWRAP_MUX_SEL,
PWRAP_WRAP_EN,
@@ -366,6 +381,39 @@ static int mt2701_regs[] = {
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
};
+static int mt6797_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_SIDLY] = 0xC,
+ [PWRAP_RDDMY] = 0x10,
+ [PWRAP_CSHEXT_WRITE] = 0x18,
+ [PWRAP_CSHEXT_READ] = 0x1C,
+ [PWRAP_CSLEXT_START] = 0x20,
+ [PWRAP_CSLEXT_END] = 0x24,
+ [PWRAP_STAUPD_PRD] = 0x28,
+ [PWRAP_HARB_HPRIO] = 0x50,
+ [PWRAP_HIPRIO_ARB_EN] = 0x54,
+ [PWRAP_MAN_EN] = 0x60,
+ [PWRAP_MAN_CMD] = 0x64,
+ [PWRAP_WACS0_EN] = 0x70,
+ [PWRAP_WACS1_EN] = 0x84,
+ [PWRAP_WACS2_EN] = 0x98,
+ [PWRAP_INIT_DONE2] = 0x9C,
+ [PWRAP_WACS2_CMD] = 0xA0,
+ [PWRAP_WACS2_RDATA] = 0xA4,
+ [PWRAP_WACS2_VLDCLR] = 0xA8,
+ [PWRAP_INT_EN] = 0xC0,
+ [PWRAP_INT_FLG_RAW] = 0xC4,
+ [PWRAP_INT_FLG] = 0xC8,
+ [PWRAP_INT_CLR] = 0xCC,
+ [PWRAP_TIMER_EN] = 0xF4,
+ [PWRAP_WDT_UNIT] = 0xFC,
+ [PWRAP_WDT_SRC_EN] = 0x100,
+ [PWRAP_DCM_EN] = 0x1CC,
+ [PWRAP_DCM_DBC_PRD] = 0x1D4,
+};
+
static int mt7622_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
@@ -635,12 +683,14 @@ static int mt8135_regs[] = {
enum pmic_type {
PMIC_MT6323,
+ PMIC_MT6351,
PMIC_MT6380,
PMIC_MT6397,
};
enum pwrap_type {
PWRAP_MT2701,
+ PWRAP_MT6797,
PWRAP_MT7622,
PWRAP_MT8135,
PWRAP_MT8173,
@@ -1067,6 +1117,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
break;
case PWRAP_MT2701:
+ case PWRAP_MT6797:
case PWRAP_MT8173:
pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
break;
@@ -1080,8 +1131,6 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1);
switch (wrp->slave->type) {
case PMIC_MT6397:
@@ -1091,6 +1140,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
0x1);
break;
case PMIC_MT6323:
+ case PMIC_MT6351:
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN],
0x1);
break;
@@ -1367,6 +1417,15 @@ static const struct pwrap_slv_type pmic_mt6397 = {
.pwrap_write = pwrap_write16,
};
+static const struct pwrap_slv_type pmic_mt6351 = {
+ .dew_regs = mt6351_regs,
+ .type = PMIC_MT6351,
+ .regmap = &pwrap_regmap_config16,
+ .caps = 0,
+ .pwrap_read = pwrap_read16,
+ .pwrap_write = pwrap_write16,
+};
+
static const struct of_device_id of_slave_match_tbl[] = {
{
.compatible = "mediatek,mt6323",
@@ -1381,6 +1440,9 @@ static const struct of_device_id of_slave_match_tbl[] = {
.compatible = "mediatek,mt6397",
.data = &pmic_mt6397,
}, {
+ .compatible = "mediatek,mt6351",
+ .data = &pmic_mt6351,
+ }, {
/* sentinel */
}
};
@@ -1398,6 +1460,18 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
.init_soc_specific = pwrap_mt2701_init_soc_specific,
};
+static const struct pmic_wrapper_type pwrap_mt6797 = {
+ .regs = mt6797_regs,
+ .type = PWRAP_MT6797,
+ .arb_en_all = 0x01fff,
+ .int_en_all = 0xffffffc6,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .has_bridge = 0,
+ .init_reg_clock = pwrap_common_init_reg_clock,
+ .init_soc_specific = NULL,
+};
+
static const struct pmic_wrapper_type pwrap_mt7622 = {
.regs = mt7622_regs,
.type = PWRAP_MT7622,
@@ -1439,6 +1513,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
.compatible = "mediatek,mt2701-pwrap",
.data = &pwrap_mt2701,
}, {
+ .compatible = "mediatek,mt6797-pwrap",
+ .data = &pwrap_mt6797,
+ }, {
.compatible = "mediatek,mt7622-pwrap",
.data = &pwrap_mt7622,
}, {
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 7dc0f20d7907..c37b0803c1b6 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
+ifdef CONFIG_SMP
+obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o
+endif
# Family
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
diff --git a/drivers/soc/renesas/r9a06g032-smp.c b/drivers/soc/renesas/r9a06g032-smp.c
new file mode 100644
index 000000000000..a1926e8d73f2
--- /dev/null
+++ b/drivers/soc/renesas/r9a06g032-smp.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R9A06G032 Second CA7 enabler.
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ * Derived from actions,s500-smp
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+/*
+ * The second CPU is parked in ROM at boot time. It requires waking it after
+ * writing an address into the BOOTADDR register of sysctrl.
+ *
+ * So the default value of the "cpu-release-addr" corresponds to BOOTADDR...
+ *
+ * *However* the BOOTADDR register is not available when the kernel
+ * starts in NONSEC mode.
+ *
+ * So for NONSEC mode, the bootloader re-parks the second CPU into a pen
+ * in SRAM, and changes the "cpu-release-addr" of linux's DT to a SRAM address,
+ * which is not restricted.
+ */
+
+static void __iomem *cpu_bootaddr;
+
+static DEFINE_SPINLOCK(cpu_lock);
+
+static int
+r9a06g032_smp_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ if (!cpu_bootaddr)
+ return -ENODEV;
+
+ spin_lock(&cpu_lock);
+
+ writel(__pa_symbol(secondary_startup), cpu_bootaddr);
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ spin_unlock(&cpu_lock);
+
+ return 0;
+}
+
+static void __init r9a06g032_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *dn;
+ int ret = -EINVAL, dns;
+ u32 bootaddr;
+
+ dn = of_get_cpu_node(1, NULL);
+ if (!dn) {
+ pr_err("CPU#1: missing device tree node\n");
+ return;
+ }
+ /*
+ * Determine the address from which the CPU is polling.
+ * The bootloader *does* change this property.
+ * Note: The property can be either 64 or 32 bits, so handle both cases
+ */
+ if (of_find_property(dn, "cpu-release-addr", &dns)) {
+ if (dns == sizeof(u64)) {
+ u64 temp;
+
+ ret = of_property_read_u64(dn,
+ "cpu-release-addr", &temp);
+ bootaddr = temp;
+ } else {
+ ret = of_property_read_u32(dn,
+ "cpu-release-addr",
+ &bootaddr);
+ }
+ }
+ of_node_put(dn);
+ if (ret) {
+ pr_err("CPU#1: invalid cpu-release-addr property\n");
+ return;
+ }
+ pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
+
+ cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr));
+}
+
+static const struct smp_operations r9a06g032_smp_ops __initconst = {
+ .smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
+ .smp_boot_secondary = r9a06g032_smp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(r9a06g032_smp,
+ "renesas,r9a06g032-smp", &r9a06g032_smp_ops);
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 50d03d8b4f9a..029188e8be6e 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -58,6 +58,12 @@
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
+struct rcar_sysc_ch {
+ u16 chan_offs;
+ u8 chan_bit;
+ u8 isr_bit;
+};
+
static void __iomem *rcar_sysc_base;
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
@@ -143,12 +149,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
return ret;
}
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
{
return rcar_sysc_power(sysc_ch, false);
}
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
{
return rcar_sysc_power(sysc_ch, true);
}
@@ -315,6 +321,8 @@ struct rcar_pm_domains {
struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
};
+static struct genpd_onecell_data *rcar_sysc_onecell_data;
+
static int __init rcar_sysc_pd_init(void)
{
const struct rcar_sysc_info *info;
@@ -326,9 +334,6 @@ static int __init rcar_sysc_pd_init(void)
unsigned int i;
int error;
- if (rcar_sysc_base)
- return 0;
-
np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
if (!np)
return -ENODEV;
@@ -361,6 +366,7 @@ static int __init rcar_sysc_pd_init(void)
domains->onecell_data.domains = domains->domains;
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
+ rcar_sysc_onecell_data = &domains->onecell_data;
for (i = 0, syscier = 0; i < info->num_areas; i++)
syscier |= BIT(info->areas[i].isr_bit);
@@ -448,27 +454,39 @@ void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
}
}
-void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
+#ifdef CONFIG_ARCH_R8A7779
+static int rcar_sysc_power_cpu(unsigned int idx, bool on)
{
- u32 syscimr;
+ struct generic_pm_domain *genpd;
+ struct rcar_sysc_pd *pd;
+ unsigned int i;
- if (!rcar_sysc_pd_init())
- return;
+ if (!rcar_sysc_onecell_data)
+ return -ENODEV;
- rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+ for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
+ genpd = rcar_sysc_onecell_data->domains[i];
+ if (!genpd)
+ continue;
- /*
- * Mask all interrupt sources to prevent the CPU from receiving them.
- * Make sure not to clear reserved bits that were set before.
- */
- syscimr = ioread32(rcar_sysc_base + SYSCIMR);
- syscimr |= syscier;
- pr_debug("%s: syscimr = 0x%08x\n", __func__, syscimr);
- iowrite32(syscimr, rcar_sysc_base + SYSCIMR);
+ pd = to_rcar_pd(genpd);
+ if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
+ continue;
- /*
- * SYSC needs all interrupt sources enabled to control power.
- */
- pr_debug("%s: syscier = 0x%08x\n", __func__, syscier);
- iowrite32(syscier, rcar_sysc_base + SYSCIER);
+ return on ? rcar_sysc_power_up(&pd->ch)
+ : rcar_sysc_power_down(&pd->ch);
+ }
+
+ return -ENOENT;
+}
+
+int rcar_sysc_power_down_cpu(unsigned int cpu)
+{
+ return rcar_sysc_power_cpu(cpu, false);
+}
+
+int rcar_sysc_power_up_cpu(unsigned int cpu)
+{
+ return rcar_sysc_power_cpu(cpu, true);
}
+#endif /* CONFIG_ARCH_R8A7779 */
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 882be5ed7e84..b4b0f3480bd3 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/soc/sunxi/sunxi_sram.h>
@@ -63,6 +64,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
SUNXI_SRAM_MAP(1, 1, "emac")),
};
+static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
+ .data = SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
+ SUNXI_SRAM_MAP(0, 0, "cpu"),
+ SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
+};
+
static struct sunxi_sram_desc sun4i_a10_sram_d = {
.data = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
SUNXI_SRAM_MAP(0, 0, "cpu"),
@@ -81,6 +88,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
.data = &sun4i_a10_sram_a3_a4.data,
},
{
+ .compatible = "allwinner,sun4i-a10-sram-c1",
+ .data = &sun4i_a10_sram_c1.data,
+ },
+ {
.compatible = "allwinner,sun4i-a10-sram-d",
.data = &sun4i_a10_sram_d.data,
},
@@ -281,13 +292,51 @@ int sunxi_sram_release(struct device *dev)
}
EXPORT_SYMBOL(sunxi_sram_release);
+struct sunxi_sramc_variant {
+ bool has_emac_clock;
+};
+
+static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
+ /* Nothing special */
+};
+
+static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
+ .has_emac_clock = true,
+};
+
+#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
+static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
+ return true;
+ return false;
+}
+
+static struct regmap_config sunxi_sram_emac_clock_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ /* last defined register */
+ .max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
+ /* other devices have no business accessing other registers */
+ .readable_reg = sunxi_sram_regmap_accessible_reg,
+ .writeable_reg = sunxi_sram_regmap_accessible_reg,
+};
+
static int sunxi_sram_probe(struct platform_device *pdev)
{
struct resource *res;
struct dentry *d;
+ struct regmap *emac_clock;
+ const struct sunxi_sramc_variant *variant;
sram_dev = &pdev->dev;
+ variant = of_device_get_match_data(&pdev->dev);
+ if (!variant)
+ return -EINVAL;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
@@ -300,12 +349,46 @@ static int sunxi_sram_probe(struct platform_device *pdev)
if (!d)
return -ENOMEM;
+ if (variant->has_emac_clock) {
+ emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
+ &sunxi_sram_emac_clock_regmap);
+
+ if (IS_ERR(emac_clock))
+ return PTR_ERR(emac_clock);
+ }
+
return 0;
}
static const struct of_device_id sunxi_sram_dt_match[] = {
- { .compatible = "allwinner,sun4i-a10-sram-controller" },
- { .compatible = "allwinner,sun50i-a64-sram-controller" },
+ {
+ .compatible = "allwinner,sun4i-a10-sram-controller",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun4i-a10-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun5i-a13-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun8i-a23-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun8i-h3-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a64-sram-controller",
+ .data = &sun50i_a64_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a64-system-control",
+ .data = &sun50i_a64_sramc_variant,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 92770d84a288..be4570baad96 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -1,3 +1,17 @@
+# 64-bit ARM SoCs from TI
+if ARM64
+
+if ARCH_K3
+
+config ARCH_K3_AM6_SOC
+ bool "K3 AM6 SoC"
+ help
+ Enable support for TI's AM6 SoC Family support
+
+endif
+
+endif
+
#
# TI SOC drivers
#
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 652739c7f718..d0dab323651f 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -41,6 +41,8 @@ static struct am33xx_pm_sram_addr *pm_sram;
static struct device *pm33xx_dev;
static struct wkup_m3_ipc *m3_ipc;
+static unsigned long suspend_wfi_flags;
+
static u32 sram_suspend_address(unsigned long addr)
{
return ((unsigned long)am33xx_do_wfi_sram +
@@ -53,7 +55,7 @@ static int am33xx_pm_suspend(suspend_state_t suspend_state)
int i, ret = 0;
ret = pm_ops->soc_suspend((unsigned long)suspend_state,
- am33xx_do_wfi_sram);
+ am33xx_do_wfi_sram, suspend_wfi_flags);
if (ret) {
dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
@@ -227,6 +229,7 @@ static int am33xx_push_sram_idle(void)
ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
ro_sram_data.amx3_pm_sram_data_phys =
gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
+ ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
/* Save physical address to calculate resume offset during pm init */
am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
@@ -310,6 +313,17 @@ static int am33xx_pm_probe(struct platform_device *pdev)
suspend_set_ops(&am33xx_pm_ops);
#endif /* CONFIG_SUSPEND */
+ /*
+ * For a system suspend we must flush the caches, we want
+ * the DDR in self-refresh, we want to save the context
+ * of the EMIF, and we want the wkup_m3 to handle low-power
+ * transition.
+ */
+ suspend_wfi_flags |= WFI_FLAG_FLUSH_CACHE;
+ suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
+ suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
+ suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
+
ret = pm_ops->init();
if (ret) {
dev_err(dev, "Unable to call core pm init!\n");
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index 369aef5e7228..f5cb8c0af09f 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -46,6 +46,7 @@
#define M3_BASELINE_VERSION 0x191
#define M3_STATUS_RESP_MASK (0xffff << 16)
#define M3_FW_VERSION_MASK 0xffff
+#define M3_WAKE_SRC_MASK 0xff
#define M3_STATE_UNKNOWN 0
#define M3_STATE_RESET 1
@@ -55,6 +56,23 @@
static struct wkup_m3_ipc *m3_ipc_state;
+static const struct wkup_m3_wakeup_src wakeups[] = {
+ {.irq_nr = 35, .src = "USB0_PHY"},
+ {.irq_nr = 36, .src = "USB1_PHY"},
+ {.irq_nr = 40, .src = "I2C0"},
+ {.irq_nr = 41, .src = "RTC Timer"},
+ {.irq_nr = 42, .src = "RTC Alarm"},
+ {.irq_nr = 43, .src = "Timer0"},
+ {.irq_nr = 44, .src = "Timer1"},
+ {.irq_nr = 45, .src = "UART"},
+ {.irq_nr = 46, .src = "GPIO0"},
+ {.irq_nr = 48, .src = "MPU_WAKE"},
+ {.irq_nr = 49, .src = "WDT0"},
+ {.irq_nr = 50, .src = "WDT1"},
+ {.irq_nr = 51, .src = "ADC_TSC"},
+ {.irq_nr = 0, .src = "Unknown"},
+};
+
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
{
writel(AM33XX_M3_TXEV_ACK,
@@ -329,12 +347,45 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
return 0;
}
+/**
+ * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
+ * @m3_ipc: Pointer to wkup_m3_ipc context
+ */
+static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
+{
+ unsigned int wakeup_src_idx;
+ int j, val;
+
+ val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
+
+ wakeup_src_idx = val & M3_WAKE_SRC_MASK;
+
+ for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
+ if (wakeups[j].irq_nr == wakeup_src_idx)
+ return wakeups[j].src;
+ }
+ return wakeups[j].src;
+}
+
+/**
+ * wkup_m3_set_rtc_only - Set the rtc_only flag
+ * @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
+ * wakeup src value
+ */
+static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
+{
+ if (m3_ipc_state)
+ m3_ipc_state->is_rtc_only = true;
+}
+
static struct wkup_m3_ipc_ops ipc_ops = {
.set_mem_type = wkup_m3_set_mem_type,
.set_resume_address = wkup_m3_set_resume_address,
.prepare_low_power = wkup_m3_prepare_low_power,
.finish_low_power = wkup_m3_finish_low_power,
.request_pm_status = wkup_m3_request_pm_status,
+ .request_wake_src = wkup_m3_request_wake_src,
+ .set_rtc_only = wkup_m3_set_rtc_only,
};
/**
@@ -484,6 +535,30 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
+{
+ /*
+ * Nothing needs to be done on suspend even with rtc_only flag set
+ */
+ return 0;
+}
+
+static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
+{
+ if (m3_ipc_state->is_rtc_only) {
+ rproc_shutdown(m3_ipc_state->rproc);
+ rproc_boot(m3_ipc_state->rproc);
+ }
+
+ m3_ipc_state->is_rtc_only = false;
+
+ return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
+};
+
static const struct of_device_id wkup_m3_ipc_of_match[] = {
{ .compatible = "ti,am3352-wkup-m3-ipc", },
{ .compatible = "ti,am4372-wkup-m3-ipc", },
@@ -497,6 +572,7 @@ static struct platform_driver wkup_m3_ipc_driver = {
.driver = {
.name = "wkup_m3_ipc",
.of_match_table = wkup_m3_ipc_of_match,
+ .pm = &wkup_m3_ipc_pm_ops,
},
};
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 396fb3d56398..1abf76be2aa8 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -90,8 +90,6 @@ source "drivers/staging/clocking-wizard/Kconfig"
source "drivers/staging/fbtft/Kconfig"
-source "drivers/staging/fsl-mc/Kconfig"
-
source "drivers/staging/fsl-dpaa2/Kconfig"
source "drivers/staging/wilc1000/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ad7b4ca412ef..ab0cbe8815b1 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
obj-$(CONFIG_UNISYSSPAR) += unisys/
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
obj-$(CONFIG_FB_TFT) += fbtft/
-obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_FSL_DPAA2) += fsl-dpaa2/
obj-$(CONFIG_WILC1000) += wilc1000/
obj-$(CONFIG_MOST) += most/
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
index e2dac44eccbe..9329fcad95ac 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -426,7 +426,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
dpaa2_fd_set_format(fd, dpaa2_fd_sg);
dpaa2_fd_set_addr(fd, addr);
dpaa2_fd_set_len(fd, skb->len);
- dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
enable_tx_tstamp(fd, sgt_buf);
@@ -479,7 +479,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
dpaa2_fd_set_len(fd, skb->len);
dpaa2_fd_set_format(fd, dpaa2_fd_single);
- dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
enable_tx_tstamp(fd, buffer_start);
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
index 506466778b2c..d54cb0b99d08 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -10,8 +10,8 @@
#include <linux/if_vlan.h>
#include <linux/fsl/mc.h>
-#include "../../fsl-mc/include/dpaa2-io.h"
-#include "../../fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-io.h>
+#include <soc/fsl/dpaa2-fd.h>
#include "dpni.h"
#include "dpni-cmd.h"
@@ -97,21 +97,13 @@ struct dpaa2_eth_swa {
#define DPAA2_FD_FRC_FAICFDV 0x0400
/* Error bits in FD CTRL */
-#define DPAA2_FD_CTRL_UFD 0x00000004
-#define DPAA2_FD_CTRL_SBE 0x00000008
-#define DPAA2_FD_CTRL_FSE 0x00000020
-#define DPAA2_FD_CTRL_FAERR 0x00000040
-
-#define DPAA2_FD_RX_ERR_MASK (DPAA2_FD_CTRL_SBE | \
- DPAA2_FD_CTRL_FAERR)
-#define DPAA2_FD_TX_ERR_MASK (DPAA2_FD_CTRL_UFD | \
- DPAA2_FD_CTRL_SBE | \
- DPAA2_FD_CTRL_FSE | \
- DPAA2_FD_CTRL_FAERR)
+#define DPAA2_FD_RX_ERR_MASK (FD_CTRL_SBE | FD_CTRL_FAERR)
+#define DPAA2_FD_TX_ERR_MASK (FD_CTRL_UFD | \
+ FD_CTRL_SBE | \
+ FD_CTRL_FSE | \
+ FD_CTRL_FAERR)
/* Annotation bits in FD CTRL */
-#define DPAA2_FD_CTRL_PTA 0x00800000
-#define DPAA2_FD_CTRL_PTV1 0x00400000
#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128B */
/* Frame annotation status */
diff --git a/drivers/staging/fsl-mc/Kconfig b/drivers/staging/fsl-mc/Kconfig
deleted file mode 100644
index 3002229bec1b..000000000000
--- a/drivers/staging/fsl-mc/Kconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-source "drivers/staging/fsl-mc/bus/Kconfig"
diff --git a/drivers/staging/fsl-mc/Makefile b/drivers/staging/fsl-mc/Makefile
deleted file mode 100644
index 14683889dabd..000000000000
--- a/drivers/staging/fsl-mc/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Freescale Management Complex (MC) bus drivers
-obj-$(CONFIG_FSL_MC_BUS) += bus/
diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
deleted file mode 100644
index 342453035269..000000000000
--- a/drivers/staging/fsl-mc/bus/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# DPAA2 fsl-mc bus
-#
-# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
-#
-
-config FSL_MC_DPIO
- tristate "QorIQ DPAA2 DPIO driver"
- depends on FSL_MC_BUS
- help
- Driver for the DPAA2 DPIO object. A DPIO provides queue and
- buffer management facilities for software to interact with
- other DPAA2 objects. This driver does not expose the DPIO
- objects individually, but groups them under a service layer
- API.
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
deleted file mode 100644
index 21d8ebc8ce21..000000000000
--- a/drivers/staging/fsl-mc/bus/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Freescale Management Complex (MC) bus drivers
-#
-# Copyright (C) 2014 Freescale Semiconductor, Inc.
-#
-
-# MC DPIO driver
-obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
deleted file mode 100644
index 72ba9da3d179..000000000000
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Copyright 2016 NXP
-
-Introduction
-------------
-
-A DPAA2 DPIO (Data Path I/O) is a hardware object that provides
-interfaces to enqueue and dequeue frames to/from network interfaces
-and other accelerators. A DPIO also provides hardware buffer
-pool management for network interfaces.
-
-This document provides an overview the Linux DPIO driver, its
-subcomponents, and its APIs.
-
-See Documentation/networking/dpaa2/overview.rst for a general overview of DPAA2
-and the general DPAA2 driver architecture in Linux.
-
-Driver Overview
----------------
-
-The DPIO driver is bound to DPIO objects discovered on the fsl-mc bus and
-provides services that:
- A) allow other drivers, such as the Ethernet driver, to enqueue and dequeue
- frames for their respective objects
- B) allow drivers to register callbacks for data availability notifications
- when data becomes available on a queue or channel
- C) allow drivers to manage hardware buffer pools
-
-The Linux DPIO driver consists of 3 primary components--
- DPIO object driver-- fsl-mc driver that manages the DPIO object
- DPIO service-- provides APIs to other Linux drivers for services
- QBman portal interface-- sends portal commands, gets responses
-
- fsl-mc other
- bus drivers
- | |
- +---+----+ +------+-----+
- |DPIO obj| |DPIO service|
- | driver |---| (DPIO) |
- +--------+ +------+-----+
- |
- +------+-----+
- | QBman |
- | portal i/f |
- +------------+
- |
- hardware
-
-The diagram below shows how the DPIO driver components fit with the other
-DPAA2 Linux driver components:
- +------------+
- | OS Network |
- | Stack |
- +------------+ +------------+
- | Allocator |. . . . . . . | Ethernet |
- |(DPMCP,DPBP)| | (DPNI) |
- +-.----------+ +---+---+----+
- . . ^ |
- . . <data avail, | |<enqueue,
- . . tx confirm> | | dequeue>
- +-------------+ . | |
- | DPRC driver | . +--------+ +------------+
- | (DPRC) | . . |DPIO obj| |DPIO service|
- +----------+--+ | driver |-| (DPIO) |
- | +--------+ +------+-----+
- |<dev add/remove> +------|-----+
- | | QBman |
- +----+--------------+ | portal i/f |
- | MC-bus driver | +------------+
- | | |
- | /soc/fsl-mc | |
- +-------------------+ |
- |
- =========================================|=========|========================
- +-+--DPIO---|-----------+
- | | |
- | QBman Portal |
- +-----------------------+
-
- ============================================================================
-
-
-DPIO Object Driver (dpio-driver.c)
-----------------------------------
-
- The dpio-driver component registers with the fsl-mc bus to handle objects of
- type "dpio". The implementation of probe() handles basic initialization
- of the DPIO including mapping of the DPIO regions (the QBman SW portal)
- and initializing interrupts and registering irq handlers. The dpio-driver
- registers the probed DPIO with dpio-service.
-
-DPIO service (dpio-service.c, dpaa2-io.h)
-------------------------------------------
-
- The dpio service component provides queuing, notification, and buffers
- management services to DPAA2 drivers, such as the Ethernet driver. A system
- will typically allocate 1 DPIO object per CPU to allow queuing operations
- to happen simultaneously across all CPUs.
-
- Notification handling
- dpaa2_io_service_register()
- dpaa2_io_service_deregister()
- dpaa2_io_service_rearm()
-
- Queuing
- dpaa2_io_service_pull_fq()
- dpaa2_io_service_pull_channel()
- dpaa2_io_service_enqueue_fq()
- dpaa2_io_service_enqueue_qd()
- dpaa2_io_store_create()
- dpaa2_io_store_destroy()
- dpaa2_io_store_next()
-
- Buffer pool management
- dpaa2_io_service_release()
- dpaa2_io_service_acquire()
-
-QBman portal interface (qbman-portal.c)
----------------------------------------
-
- The qbman-portal component provides APIs to do the low level hardware
- bit twiddling for operations such as:
- -initializing Qman software portals
- -building and sending portal commands
- -portal interrupt configuration and processing
-
- The qbman-portal APIs are not public to other drivers, and are
- only used by dpio-service.
-
-Other (dpaa2-fd.h, dpaa2-global.h)
-----------------------------------
-
- Frame descriptor and scatter-gather definitions and the APIs used to
- manipulate them are defined in dpaa2-fd.h.
-
- Dequeue result struct and parsing APIs are defined in dpaa2-global.h.
diff --git a/drivers/staging/fsl-mc/include/dpaa2-fd.h b/drivers/staging/fsl-mc/include/dpaa2-fd.h
deleted file mode 100644
index b55b89ba4eda..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-fd.h
+++ /dev/null
@@ -1,426 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright 2016 NXP
- *
- */
-#ifndef __FSL_DPAA2_FD_H
-#define __FSL_DPAA2_FD_H
-
-#include <linux/kernel.h>
-
-/**
- * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2
- *
- * Frame Descriptors (FDs) are used to describe frame data in the DPAA2.
- * Frames can be enqueued and dequeued to Frame Queues (FQs) which are consumed
- * by the various DPAA accelerators (WRIOP, SEC, PME, DCE)
- *
- * There are three types of frames: single, scatter gather, and frame lists.
- *
- * The set of APIs in this file must be used to create, manipulate and
- * query Frame Descriptors.
- */
-
-/**
- * struct dpaa2_fd - Struct describing FDs
- * @words: for easier/faster copying the whole FD structure
- * @addr: address in the FD
- * @len: length in the FD
- * @bpid: buffer pool ID
- * @format_offset: format, offset, and short-length fields
- * @frc: frame context
- * @ctrl: control bits...including dd, sc, va, err, etc
- * @flc: flow context address
- *
- * This structure represents the basic Frame Descriptor used in the system.
- */
-struct dpaa2_fd {
- union {
- u32 words[8];
- struct dpaa2_fd_simple {
- __le64 addr;
- __le32 len;
- __le16 bpid;
- __le16 format_offset;
- __le32 frc;
- __le32 ctrl;
- __le64 flc;
- } simple;
- };
-};
-
-#define FD_SHORT_LEN_FLAG_MASK 0x1
-#define FD_SHORT_LEN_FLAG_SHIFT 14
-#define FD_SHORT_LEN_MASK 0x3FFFF
-#define FD_OFFSET_MASK 0x0FFF
-#define FD_FORMAT_MASK 0x3
-#define FD_FORMAT_SHIFT 12
-#define FD_BPID_MASK 0x3FFF
-#define SG_SHORT_LEN_FLAG_MASK 0x1
-#define SG_SHORT_LEN_FLAG_SHIFT 14
-#define SG_SHORT_LEN_MASK 0x1FFFF
-#define SG_OFFSET_MASK 0x0FFF
-#define SG_FORMAT_MASK 0x3
-#define SG_FORMAT_SHIFT 12
-#define SG_BPID_MASK 0x3FFF
-#define SG_FINAL_FLAG_MASK 0x1
-#define SG_FINAL_FLAG_SHIFT 15
-
-enum dpaa2_fd_format {
- dpaa2_fd_single = 0,
- dpaa2_fd_list,
- dpaa2_fd_sg
-};
-
-/**
- * dpaa2_fd_get_addr() - get the addr field of frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the address in the frame descriptor.
- */
-static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd)
-{
- return (dma_addr_t)le64_to_cpu(fd->simple.addr);
-}
-
-/**
- * dpaa2_fd_set_addr() - Set the addr field of frame descriptor
- * @fd: the given frame descriptor
- * @addr: the address needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t addr)
-{
- fd->simple.addr = cpu_to_le64(addr);
-}
-
-/**
- * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the frame context field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd)
-{
- return le32_to_cpu(fd->simple.frc);
-}
-
-/**
- * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor
- * @fd: the given frame descriptor
- * @frc: the frame context needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc)
-{
- fd->simple.frc = cpu_to_le32(frc);
-}
-
-/**
- * dpaa2_fd_get_ctrl() - Get the control bits in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the control bits field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_ctrl(const struct dpaa2_fd *fd)
-{
- return le32_to_cpu(fd->simple.ctrl);
-}
-
-/**
- * dpaa2_fd_set_ctrl() - Set the control bits in the frame descriptor
- * @fd: the given frame descriptor
- * @ctrl: the control bits to be set in the frame descriptor
- */
-static inline void dpaa2_fd_set_ctrl(struct dpaa2_fd *fd, u32 ctrl)
-{
- fd->simple.ctrl = cpu_to_le32(ctrl);
-}
-
-/**
- * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the flow context in the frame descriptor.
- */
-static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd)
-{
- return (dma_addr_t)le64_to_cpu(fd->simple.flc);
-}
-
-/**
- * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor
- * @fd: the given frame descriptor
- * @flc_addr: the flow context needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t flc_addr)
-{
- fd->simple.flc = cpu_to_le64(flc_addr);
-}
-
-static inline bool dpaa2_fd_short_len(const struct dpaa2_fd *fd)
-{
- return !!((le16_to_cpu(fd->simple.format_offset) >>
- FD_SHORT_LEN_FLAG_SHIFT) & FD_SHORT_LEN_FLAG_MASK);
-}
-
-/**
- * dpaa2_fd_get_len() - Get the length in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the length field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd)
-{
- if (dpaa2_fd_short_len(fd))
- return le32_to_cpu(fd->simple.len) & FD_SHORT_LEN_MASK;
-
- return le32_to_cpu(fd->simple.len);
-}
-
-/**
- * dpaa2_fd_set_len() - Set the length field of frame descriptor
- * @fd: the given frame descriptor
- * @len: the length needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len)
-{
- fd->simple.len = cpu_to_le32(len);
-}
-
-/**
- * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the offset.
- */
-static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd)
-{
- return le16_to_cpu(fd->simple.format_offset) & FD_OFFSET_MASK;
-}
-
-/**
- * dpaa2_fd_set_offset() - Set the offset field of frame descriptor
- * @fd: the given frame descriptor
- * @offset: the offset needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset)
-{
- fd->simple.format_offset &= cpu_to_le16(~FD_OFFSET_MASK);
- fd->simple.format_offset |= cpu_to_le16(offset);
-}
-
-/**
- * dpaa2_fd_get_format() - Get the format field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the format.
- */
-static inline enum dpaa2_fd_format dpaa2_fd_get_format(
- const struct dpaa2_fd *fd)
-{
- return (enum dpaa2_fd_format)((le16_to_cpu(fd->simple.format_offset)
- >> FD_FORMAT_SHIFT) & FD_FORMAT_MASK);
-}
-
-/**
- * dpaa2_fd_set_format() - Set the format field of frame descriptor
- * @fd: the given frame descriptor
- * @format: the format needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd,
- enum dpaa2_fd_format format)
-{
- fd->simple.format_offset &=
- cpu_to_le16(~(FD_FORMAT_MASK << FD_FORMAT_SHIFT));
- fd->simple.format_offset |= cpu_to_le16(format << FD_FORMAT_SHIFT);
-}
-
-/**
- * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the buffer pool id.
- */
-static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd)
-{
- return le16_to_cpu(fd->simple.bpid) & FD_BPID_MASK;
-}
-
-/**
- * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
- * @fd: the given frame descriptor
- * @bpid: buffer pool id to be set
- */
-static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
-{
- fd->simple.bpid &= cpu_to_le16(~(FD_BPID_MASK));
- fd->simple.bpid |= cpu_to_le16(bpid);
-}
-
-/**
- * struct dpaa2_sg_entry - the scatter-gathering structure
- * @addr: address of the sg entry
- * @len: length in this sg entry
- * @bpid: buffer pool id
- * @format_offset: format and offset fields
- */
-struct dpaa2_sg_entry {
- __le64 addr;
- __le32 len;
- __le16 bpid;
- __le16 format_offset;
-};
-
-enum dpaa2_sg_format {
- dpaa2_sg_single = 0,
- dpaa2_sg_frame_data,
- dpaa2_sg_sgt_ext
-};
-
-/* Accessors for SG entry fields */
-
-/**
- * dpaa2_sg_get_addr() - Get the address from SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the address.
- */
-static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg)
-{
- return (dma_addr_t)le64_to_cpu(sg->addr);
-}
-
-/**
- * dpaa2_sg_set_addr() - Set the address in SG entry
- * @sg: the given scatter-gathering object
- * @addr: the address to be set
- */
-static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg, dma_addr_t addr)
-{
- sg->addr = cpu_to_le64(addr);
-}
-
-static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg)
-{
- return !!((le16_to_cpu(sg->format_offset) >> SG_SHORT_LEN_FLAG_SHIFT)
- & SG_SHORT_LEN_FLAG_MASK);
-}
-
-/**
- * dpaa2_sg_get_len() - Get the length in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the length.
- */
-static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
-{
- if (dpaa2_sg_short_len(sg))
- return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
-
- return le32_to_cpu(sg->len);
-}
-
-/**
- * dpaa2_sg_set_len() - Set the length in SG entry
- * @sg: the given scatter-gathering object
- * @len: the length to be set
- */
-static inline void dpaa2_sg_set_len(struct dpaa2_sg_entry *sg, u32 len)
-{
- sg->len = cpu_to_le32(len);
-}
-
-/**
- * dpaa2_sg_get_offset() - Get the offset in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the offset.
- */
-static inline u16 dpaa2_sg_get_offset(const struct dpaa2_sg_entry *sg)
-{
- return le16_to_cpu(sg->format_offset) & SG_OFFSET_MASK;
-}
-
-/**
- * dpaa2_sg_set_offset() - Set the offset in SG entry
- * @sg: the given scatter-gathering object
- * @offset: the offset to be set
- */
-static inline void dpaa2_sg_set_offset(struct dpaa2_sg_entry *sg,
- u16 offset)
-{
- sg->format_offset &= cpu_to_le16(~SG_OFFSET_MASK);
- sg->format_offset |= cpu_to_le16(offset);
-}
-
-/**
- * dpaa2_sg_get_format() - Get the SG format in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the format.
- */
-static inline enum dpaa2_sg_format
- dpaa2_sg_get_format(const struct dpaa2_sg_entry *sg)
-{
- return (enum dpaa2_sg_format)((le16_to_cpu(sg->format_offset)
- >> SG_FORMAT_SHIFT) & SG_FORMAT_MASK);
-}
-
-/**
- * dpaa2_sg_set_format() - Set the SG format in SG entry
- * @sg: the given scatter-gathering object
- * @format: the format to be set
- */
-static inline void dpaa2_sg_set_format(struct dpaa2_sg_entry *sg,
- enum dpaa2_sg_format format)
-{
- sg->format_offset &= cpu_to_le16(~(SG_FORMAT_MASK << SG_FORMAT_SHIFT));
- sg->format_offset |= cpu_to_le16(format << SG_FORMAT_SHIFT);
-}
-
-/**
- * dpaa2_sg_get_bpid() - Get the buffer pool id in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the bpid.
- */
-static inline u16 dpaa2_sg_get_bpid(const struct dpaa2_sg_entry *sg)
-{
- return le16_to_cpu(sg->bpid) & SG_BPID_MASK;
-}
-
-/**
- * dpaa2_sg_set_bpid() - Set the buffer pool id in SG entry
- * @sg: the given scatter-gathering object
- * @bpid: the bpid to be set
- */
-static inline void dpaa2_sg_set_bpid(struct dpaa2_sg_entry *sg, u16 bpid)
-{
- sg->bpid &= cpu_to_le16(~(SG_BPID_MASK));
- sg->bpid |= cpu_to_le16(bpid);
-}
-
-/**
- * dpaa2_sg_is_final() - Check final bit in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return bool.
- */
-static inline bool dpaa2_sg_is_final(const struct dpaa2_sg_entry *sg)
-{
- return !!(le16_to_cpu(sg->format_offset) >> SG_FINAL_FLAG_SHIFT);
-}
-
-/**
- * dpaa2_sg_set_final() - Set the final bit in SG entry
- * @sg: the given scatter-gathering object
- * @final: the final boolean to be set
- */
-static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final)
-{
- sg->format_offset &= cpu_to_le16((~(SG_FINAL_FLAG_MASK
- << SG_FINAL_FLAG_SHIFT)) & 0xFFFF);
- sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT);
-}
-
-#endif /* __FSL_DPAA2_FD_H */
diff --git a/drivers/staging/fsl-mc/include/dpaa2-global.h b/drivers/staging/fsl-mc/include/dpaa2-global.h
deleted file mode 100644
index 9bc0713346a8..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-global.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright 2016 NXP
- *
- */
-#ifndef __FSL_DPAA2_GLOBAL_H
-#define __FSL_DPAA2_GLOBAL_H
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include "dpaa2-fd.h"
-
-struct dpaa2_dq {
- union {
- struct common {
- u8 verb;
- u8 reserved[63];
- } common;
- struct dq {
- u8 verb;
- u8 stat;
- __le16 seqnum;
- __le16 oprid;
- u8 reserved;
- u8 tok;
- __le32 fqid;
- u32 reserved2;
- __le32 fq_byte_cnt;
- __le32 fq_frm_cnt;
- __le64 fqd_ctx;
- u8 fd[32];
- } dq;
- struct scn {
- u8 verb;
- u8 stat;
- u8 state;
- u8 reserved;
- __le32 rid_tok;
- __le64 ctx;
- } scn;
- };
-};
-
-/* Parsing frame dequeue results */
-/* FQ empty */
-#define DPAA2_DQ_STAT_FQEMPTY 0x80
-/* FQ held active */
-#define DPAA2_DQ_STAT_HELDACTIVE 0x40
-/* FQ force eligible */
-#define DPAA2_DQ_STAT_FORCEELIGIBLE 0x20
-/* valid frame */
-#define DPAA2_DQ_STAT_VALIDFRAME 0x10
-/* FQ ODP enable */
-#define DPAA2_DQ_STAT_ODPVALID 0x04
-/* volatile dequeue */
-#define DPAA2_DQ_STAT_VOLATILE 0x02
-/* volatile dequeue command is expired */
-#define DPAA2_DQ_STAT_EXPIRED 0x01
-
-#define DQ_FQID_MASK 0x00FFFFFF
-#define DQ_FRAME_COUNT_MASK 0x00FFFFFF
-
-/**
- * dpaa2_dq_flags() - Get the stat field of dequeue response
- * @dq: the dequeue result.
- */
-static inline u32 dpaa2_dq_flags(const struct dpaa2_dq *dq)
-{
- return dq->dq.stat;
-}
-
-/**
- * dpaa2_dq_is_pull() - Check whether the dq response is from a pull
- * command.
- * @dq: the dequeue result
- *
- * Return 1 for volatile(pull) dequeue, 0 for static dequeue.
- */
-static inline int dpaa2_dq_is_pull(const struct dpaa2_dq *dq)
-{
- return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_VOLATILE);
-}
-
-/**
- * dpaa2_dq_is_pull_complete() - Check whether the pull command is completed.
- * @dq: the dequeue result
- *
- * Return boolean.
- */
-static inline bool dpaa2_dq_is_pull_complete(const struct dpaa2_dq *dq)
-{
- return !!(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_EXPIRED);
-}
-
-/**
- * dpaa2_dq_seqnum() - Get the seqnum field in dequeue response
- * @dq: the dequeue result
- *
- * seqnum is valid only if VALIDFRAME flag is TRUE
- *
- * Return seqnum.
- */
-static inline u16 dpaa2_dq_seqnum(const struct dpaa2_dq *dq)
-{
- return le16_to_cpu(dq->dq.seqnum);
-}
-
-/**
- * dpaa2_dq_odpid() - Get the odpid field in dequeue response
- * @dq: the dequeue result
- *
- * odpid is valid only if ODPVALID flag is TRUE.
- *
- * Return odpid.
- */
-static inline u16 dpaa2_dq_odpid(const struct dpaa2_dq *dq)
-{
- return le16_to_cpu(dq->dq.oprid);
-}
-
-/**
- * dpaa2_dq_fqid() - Get the fqid in dequeue response
- * @dq: the dequeue result
- *
- * Return fqid.
- */
-static inline u32 dpaa2_dq_fqid(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fqid) & DQ_FQID_MASK;
-}
-
-/**
- * dpaa2_dq_byte_count() - Get the byte count in dequeue response
- * @dq: the dequeue result
- *
- * Return the byte count remaining in the FQ.
- */
-static inline u32 dpaa2_dq_byte_count(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fq_byte_cnt);
-}
-
-/**
- * dpaa2_dq_frame_count() - Get the frame count in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame count remaining in the FQ.
- */
-static inline u32 dpaa2_dq_frame_count(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fq_frm_cnt) & DQ_FRAME_COUNT_MASK;
-}
-
-/**
- * dpaa2_dq_fd_ctx() - Get the frame queue context in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame queue context.
- */
-static inline u64 dpaa2_dq_fqd_ctx(const struct dpaa2_dq *dq)
-{
- return le64_to_cpu(dq->dq.fqd_ctx);
-}
-
-/**
- * dpaa2_dq_fd() - Get the frame descriptor in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame descriptor.
- */
-static inline const struct dpaa2_fd *dpaa2_dq_fd(const struct dpaa2_dq *dq)
-{
- return (const struct dpaa2_fd *)&dq->dq.fd[0];
-}
-
-#endif /* __FSL_DPAA2_GLOBAL_H */
diff --git a/drivers/staging/fsl-mc/include/dpaa2-io.h b/drivers/staging/fsl-mc/include/dpaa2-io.h
deleted file mode 100644
index ab51e40d11db..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-io.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright NXP
- *
- */
-#ifndef __FSL_DPAA2_IO_H
-#define __FSL_DPAA2_IO_H
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include <linux/irqreturn.h>
-
-#include "dpaa2-fd.h"
-#include "dpaa2-global.h"
-
-struct dpaa2_io;
-struct dpaa2_io_store;
-struct device;
-
-/**
- * DOC: DPIO Service
- *
- * The DPIO service provides APIs for users to interact with the datapath
- * by enqueueing and dequeing frame descriptors.
- *
- * The following set of APIs can be used to enqueue and dequeue frames
- * as well as producing notification callbacks when data is available
- * for dequeue.
- */
-
-#define DPAA2_IO_ANY_CPU -1
-
-/**
- * struct dpaa2_io_desc - The DPIO descriptor
- * @receives_notifications: Use notificaton mode. Non-zero if the DPIO
- * has a channel.
- * @has_8prio: Set to non-zero for channel with 8 priority WQs. Ignored
- * unless receives_notification is TRUE.
- * @cpu: The cpu index that at least interrupt handlers will
- * execute on.
- * @stash_affinity: The stash affinity for this portal favour 'cpu'
- * @regs_cena: The cache enabled regs.
- * @regs_cinh: The cache inhibited regs
- * @dpio_id: The dpio index
- * @qman_version: The qman version
- *
- * Describes the attributes and features of the DPIO object.
- */
-struct dpaa2_io_desc {
- int receives_notifications;
- int has_8prio;
- int cpu;
- void *regs_cena;
- void __iomem *regs_cinh;
- int dpio_id;
- u32 qman_version;
-};
-
-struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc);
-
-void dpaa2_io_down(struct dpaa2_io *d);
-
-irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj);
-
-struct dpaa2_io *dpaa2_io_service_select(int cpu);
-
-/**
- * struct dpaa2_io_notification_ctx - The DPIO notification context structure
- * @cb: The callback to be invoked when the notification arrives
- * @is_cdan: Zero for FQDAN, non-zero for CDAN
- * @id: FQID or channel ID, needed for rearm
- * @desired_cpu: The cpu on which the notifications will show up. Use
- * DPAA2_IO_ANY_CPU if don't care
- * @dpio_id: The dpio index
- * @qman64: The 64-bit context value shows up in the FQDAN/CDAN.
- * @node: The list node
- * @dpio_private: The dpio object internal to dpio_service
- *
- * Used when a FQDAN/CDAN registration is made by drivers.
- */
-struct dpaa2_io_notification_ctx {
- void (*cb)(struct dpaa2_io_notification_ctx *ctx);
- int is_cdan;
- u32 id;
- int desired_cpu;
- int dpio_id;
- u64 qman64;
- struct list_head node;
- void *dpio_private;
-};
-
-int dpaa2_io_service_register(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-void dpaa2_io_service_deregister(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-int dpaa2_io_service_rearm(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-
-int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
- struct dpaa2_io_store *s);
-
-int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
- u16 qdbin, const struct dpaa2_fd *fd);
-int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
- const u64 *buffers, unsigned int num_buffers);
-int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid,
- u64 *buffers, unsigned int num_buffers);
-
-struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
- struct device *dev);
-void dpaa2_io_store_destroy(struct dpaa2_io_store *s);
-struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last);
-
-#endif /* __FSL_DPAA2_IO_H */
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 0126de898036..3c59e19029be 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -5,3 +5,11 @@ config OPTEE
help
This implements the OP-TEE Trusted Execution Environment (TEE)
driver.
+
+config OPTEE_SHM_NUM_PRIV_PAGES
+ int "Private Shared Memory Pages"
+ default 1
+ depends on OPTEE
+ help
+ This sets the number of private shared memory pages to be
+ used by OP-TEE TEE driver.
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index e5fd5ed217da..e1aafe842d66 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -32,7 +32,7 @@
#define DRIVER_NAME "optee"
-#define OPTEE_SHM_NUM_PRIV_PAGES 1
+#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
/**
* optee_from_msg_param() - convert from OPTEE_MSG parameters to
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index 41aea12e2bcc..b45c73dd37a5 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -48,7 +48,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
goto bad;
- getnstimeofday64(&ts);
+ ktime_get_real_ts64(&ts);
arg->params[0].u.value.a = ts.tv_sec;
arg->params[0].u.value.b = ts.tv_nsec;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 6364890575ec..06ed20dd01ba 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -348,7 +348,7 @@ static void send_sig_all(int sig)
if (is_global_init(p))
continue;
- do_send_sig_info(sig, SEND_SIG_FORCED, p, true);
+ do_send_sig_info(sig, SEND_SIG_FORCED, p, PIDTYPE_MAX);
}
read_unlock(&tasklist_lock);
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 11c2df904ac9..32bc3e3fe4d3 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2113,7 +2113,7 @@ static int __tty_fasync(int fd, struct file *filp, int on)
type = PIDTYPE_PGID;
} else {
pid = task_pid(current);
- type = PIDTYPE_PID;
+ type = PIDTYPE_TGID;
}
get_pid(pid);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d9145a8f35d2..8e3bab1e0c1f 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -161,16 +161,10 @@ static int exynos_ehci_probe(struct platform_device *pdev)
}
exynos_ehci = to_exynos_ehci(hcd);
- if (of_device_is_compatible(pdev->dev.of_node,
- "samsung,exynos5440-ehci"))
- goto skip_phy;
-
err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
if (err)
goto fail_clk;
-skip_phy:
-
exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ehci->clk)) {
@@ -304,7 +298,6 @@ static const struct dev_pm_ops exynos_ehci_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id exynos_ehci_match[] = {
{ .compatible = "samsung,exynos4210-ehci" },
- { .compatible = "samsung,exynos5440-ehci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ehci_match);
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index a39fae41bc70..c0c4dcca6f3c 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -130,15 +130,10 @@ static int exynos_ohci_probe(struct platform_device *pdev)
exynos_ohci = to_exynos_ohci(hcd);
- if (of_device_is_compatible(pdev->dev.of_node,
- "samsung,exynos5440-ohci"))
- goto skip_phy;
-
err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
if (err)
goto fail_clk;
-skip_phy:
exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ohci->clk)) {
@@ -270,7 +265,6 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id exynos_ohci_match[] = {
{ .compatible = "samsung,exynos4210-ohci" },
- { .compatible = "samsung,exynos5440-ohci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ohci_match);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 16119bde9750..f1dc41cf19e3 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -690,6 +690,7 @@ static int adp8860_probe(struct i2c_client *client,
switch (ADP8860_MANID(reg_val)) {
case ADP8863_MANUFID:
data->gdwn_dis = !!pdata->gdwn_dis;
+ /* fall through */
case ADP8860_MANUFID:
data->en_ambl_sens = !!pdata->en_ambl_sens;
break;
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 44ac5bde4e9d..bdfcc0a71db1 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -143,11 +143,116 @@ static const struct backlight_ops pwm_backlight_ops = {
};
#ifdef CONFIG_OF
+#define PWM_LUMINANCE_SCALE 10000 /* luminance scale */
+
+/* An integer based power function */
+static u64 int_pow(u64 base, int exp)
+{
+ u64 result = 1;
+
+ while (exp) {
+ if (exp & 1)
+ result *= base;
+ exp >>= 1;
+ base *= base;
+ }
+
+ return result;
+}
+
+/*
+ * CIE lightness to PWM conversion.
+ *
+ * The CIE 1931 lightness formula is what actually describes how we perceive
+ * light:
+ * Y = (L* / 902.3) if L* ≤ 0.08856
+ * Y = ((L* + 16) / 116)^3 if L* > 0.08856
+ *
+ * Where Y is the luminance, the amount of light coming out of the screen, and
+ * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
+ * perceives the screen to be, and is a number between 0 and 100.
+ *
+ * The following function does the fixed point maths needed to implement the
+ * above formula.
+ */
+static u64 cie1931(unsigned int lightness, unsigned int scale)
+{
+ u64 retval;
+
+ lightness *= 100;
+ if (lightness <= (8 * scale)) {
+ retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
+ } else {
+ retval = int_pow((lightness + (16 * scale)) / 116, 3);
+ retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
+ }
+
+ return retval;
+}
+
+/*
+ * Create a default correction table for PWM values to create linear brightness
+ * for LED based backlights using the CIE1931 algorithm.
+ */
+static
+int pwm_backlight_brightness_default(struct device *dev,
+ struct platform_pwm_backlight_data *data,
+ unsigned int period)
+{
+ unsigned int counter = 0;
+ unsigned int i, n;
+ u64 retval;
+
+ /*
+ * Count the number of bits needed to represent the period number. The
+ * number of bits is used to calculate the number of levels used for the
+ * brightness-levels table, the purpose of this calculation is have a
+ * pre-computed table with enough levels to get linear brightness
+ * perception. The period is divided by the number of bits so for a
+ * 8-bit PWM we have 255 / 8 = 32 brightness levels or for a 16-bit PWM
+ * we have 65535 / 16 = 4096 brightness levels.
+ *
+ * Note that this method is based on empirical testing on different
+ * devices with PWM of 8 and 16 bits of resolution.
+ */
+ n = period;
+ while (n) {
+ counter += n % 2;
+ n >>= 1;
+ }
+
+ data->max_brightness = DIV_ROUND_UP(period, counter);
+ data->levels = devm_kcalloc(dev, data->max_brightness,
+ sizeof(*data->levels), GFP_KERNEL);
+ if (!data->levels)
+ return -ENOMEM;
+
+ /* Fill the table using the cie1931 algorithm */
+ for (i = 0; i < data->max_brightness; i++) {
+ retval = cie1931((i * PWM_LUMINANCE_SCALE) /
+ data->max_brightness, PWM_LUMINANCE_SCALE) *
+ period;
+ retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
+ if (retval > UINT_MAX)
+ return -EINVAL;
+ data->levels[i] = (unsigned int)retval;
+ }
+
+ data->dft_brightness = data->max_brightness / 2;
+ data->max_brightness--;
+
+ return 0;
+}
+
static int pwm_backlight_parse_dt(struct device *dev,
struct platform_pwm_backlight_data *data)
{
struct device_node *node = dev->of_node;
+ unsigned int num_levels = 0;
+ unsigned int levels_count;
+ unsigned int num_steps = 0;
struct property *prop;
+ unsigned int *table;
int length;
u32 value;
int ret;
@@ -157,16 +262,20 @@ static int pwm_backlight_parse_dt(struct device *dev,
memset(data, 0, sizeof(*data));
- /* determine the number of brightness levels */
+ /*
+ * Determine the number of brightness levels, if this property is not
+ * set a default table of brightness levels will be used.
+ */
prop = of_find_property(node, "brightness-levels", &length);
if (!prop)
- return -EINVAL;
+ return 0;
data->max_brightness = length / sizeof(u32);
/* read brightness levels from DT property */
if (data->max_brightness > 0) {
size_t size = sizeof(*data->levels) * data->max_brightness;
+ unsigned int i, j, n = 0;
data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
if (!data->levels)
@@ -184,6 +293,84 @@ static int pwm_backlight_parse_dt(struct device *dev,
return ret;
data->dft_brightness = value;
+
+ /*
+ * This property is optional, if is set enables linear
+ * interpolation between each of the values of brightness levels
+ * and creates a new pre-computed table.
+ */
+ of_property_read_u32(node, "num-interpolated-steps",
+ &num_steps);
+
+ /*
+ * Make sure that there is at least two entries in the
+ * brightness-levels table, otherwise we can't interpolate
+ * between two points.
+ */
+ if (num_steps) {
+ if (data->max_brightness < 2) {
+ dev_err(dev, "can't interpolate\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Recalculate the number of brightness levels, now
+ * taking in consideration the number of interpolated
+ * steps between two levels.
+ */
+ for (i = 0; i < data->max_brightness - 1; i++) {
+ if ((data->levels[i + 1] - data->levels[i]) /
+ num_steps)
+ num_levels += num_steps;
+ else
+ num_levels++;
+ }
+ num_levels++;
+ dev_dbg(dev, "new number of brightness levels: %d\n",
+ num_levels);
+
+ /*
+ * Create a new table of brightness levels with all the
+ * interpolated steps.
+ */
+ size = sizeof(*table) * num_levels;
+ table = devm_kzalloc(dev, size, GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ /* Fill the interpolated table. */
+ levels_count = 0;
+ for (i = 0; i < data->max_brightness - 1; i++) {
+ value = data->levels[i];
+ n = (data->levels[i + 1] - value) / num_steps;
+ if (n > 0) {
+ for (j = 0; j < num_steps; j++) {
+ table[levels_count] = value;
+ value += n;
+ levels_count++;
+ }
+ } else {
+ table[levels_count] = data->levels[i];
+ levels_count++;
+ }
+ }
+ table[levels_count] = data->levels[i];
+
+ /*
+ * As we use interpolation lets remove current
+ * brightness levels table and replace for the
+ * new interpolated table.
+ */
+ devm_kfree(dev, data->levels);
+ data->levels = table;
+
+ /*
+ * Reassign max_brightness value to the new total number
+ * of brightness levels.
+ */
+ data->max_brightness = num_levels;
+ }
+
data->max_brightness--;
}
@@ -211,6 +398,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
{
return -ENODEV;
}
+
+static
+int pwm_backlight_brightness_default(struct device *dev,
+ struct platform_pwm_backlight_data *data,
+ unsigned int period)
+{
+ return -ENODEV;
+}
#endif
static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
@@ -251,7 +446,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
struct backlight_device *bl;
struct device_node *node = pdev->dev.of_node;
struct pwm_bl_data *pb;
+ struct pwm_state state;
struct pwm_args pargs;
+ unsigned int i;
int ret;
if (!data) {
@@ -276,17 +473,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
goto err_alloc;
}
- if (data->levels) {
- unsigned int i;
-
- for (i = 0; i <= data->max_brightness; i++)
- if (data->levels[i] > pb->scale)
- pb->scale = data->levels[i];
-
- pb->levels = data->levels;
- } else
- pb->scale = data->max_brightness;
-
pb->notify = data->notify;
pb->notify_after = data->notify_after;
pb->check_fb = data->check_fb;
@@ -353,6 +539,26 @@ static int pwm_backlight_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "got pwm for backlight\n");
+ if (!data->levels) {
+ /* Get the PWM period (in nanoseconds) */
+ pwm_get_state(pb->pwm, &state);
+
+ ret = pwm_backlight_brightness_default(&pdev->dev, data,
+ state.period);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "failed to setup default brightness table\n");
+ goto err_alloc;
+ }
+ }
+
+ for (i = 0; i <= data->max_brightness; i++) {
+ if (data->levels[i] > pb->scale)
+ pb->scale = data->levels[i];
+
+ pb->levels = data->levels;
+ }
+
/*
* FIXME: pwm_apply_args() should be removed when switching to
* the atomic PWM API.
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 7931231d8e80..e22fdeddada1 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -100,18 +100,6 @@ config W1_SLAVE_DS2438
Say Y here if you want to use a 1-wire
DS2438 Smart Battery Monitor device support
-config W1_SLAVE_DS2760
- tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
- help
- If you enable this you will have the DS2760 battery monitor
- chip support.
-
- The battery monitor chip is used in many batteries/devices
- as the one who is responsible for charging/discharging/monitoring
- Li+ batteries.
-
- If you are unsure, say N.
-
config W1_SLAVE_DS2780
tristate "Dallas 2780 battery monitor chip"
help
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index d5f4f4d5b9e5..eab29f151413 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o
obj-$(CONFIG_W1_SLAVE_DS2805) += w1_ds2805.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
obj-$(CONFIG_W1_SLAVE_DS2438) += w1_ds2438.o
-obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o
obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o
obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
deleted file mode 100644
index 26168abfb8b8..000000000000
--- a/drivers/w1/slaves/w1_ds2760.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 1-Wire implementation for the ds2760 chip
- *
- * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/idr.h>
-#include <linux/gfp.h>
-
-#include <linux/w1.h>
-
-#include "w1_ds2760.h"
-
-#define W1_FAMILY_DS2760 0x30
-
-static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
- int io)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- if (!dev)
- return 0;
-
- mutex_lock(&sl->master->bus_mutex);
-
- if (addr > DS2760_DATA_SIZE || addr < 0) {
- count = 0;
- goto out;
- }
- if (addr + count > DS2760_DATA_SIZE)
- count = DS2760_DATA_SIZE - addr;
-
- if (!w1_reset_select_slave(sl)) {
- if (!io) {
- w1_write_8(sl->master, W1_DS2760_READ_DATA);
- w1_write_8(sl->master, addr);
- count = w1_read_block(sl->master, buf, count);
- } else {
- w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
- w1_write_8(sl->master, addr);
- w1_write_block(sl->master, buf, count);
- /* XXX w1_write_block returns void, not n_written */
- }
- }
-
-out:
- mutex_unlock(&sl->master->bus_mutex);
-
- return count;
-}
-
-int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
-{
- return w1_ds2760_io(dev, buf, addr, count, 0);
-}
-EXPORT_SYMBOL(w1_ds2760_read);
-
-int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
-{
- return w1_ds2760_io(dev, buf, addr, count, 1);
-}
-EXPORT_SYMBOL(w1_ds2760_write);
-
-static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
- if (!dev)
- return -EINVAL;
-
- mutex_lock(&sl->master->bus_mutex);
-
- if (w1_reset_select_slave(sl) == 0) {
- w1_write_8(sl->master, cmd);
- w1_write_8(sl->master, addr);
- }
-
- mutex_unlock(&sl->master->bus_mutex);
- return 0;
-}
-
-int w1_ds2760_store_eeprom(struct device *dev, int addr)
-{
- return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA);
-}
-EXPORT_SYMBOL(w1_ds2760_store_eeprom);
-
-int w1_ds2760_recall_eeprom(struct device *dev, int addr)
-{
- return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
-}
-EXPORT_SYMBOL(w1_ds2760_recall_eeprom);
-
-static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
- loff_t off, size_t count)
-{
- struct device *dev = container_of(kobj, struct device, kobj);
- return w1_ds2760_read(dev, buf, off, count);
-}
-
-static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
-
-static struct bin_attribute *w1_ds2760_bin_attrs[] = {
- &bin_attr_w1_slave,
- NULL,
-};
-
-static const struct attribute_group w1_ds2760_group = {
- .bin_attrs = w1_ds2760_bin_attrs,
-};
-
-static const struct attribute_group *w1_ds2760_groups[] = {
- &w1_ds2760_group,
- NULL,
-};
-
-static int w1_ds2760_add_slave(struct w1_slave *sl)
-{
- int ret;
- struct platform_device *pdev;
-
- pdev = platform_device_alloc("ds2760-battery", PLATFORM_DEVID_AUTO);
- if (!pdev)
- return -ENOMEM;
- pdev->dev.parent = &sl->dev;
-
- ret = platform_device_add(pdev);
- if (ret)
- goto pdev_add_failed;
-
- dev_set_drvdata(&sl->dev, pdev);
-
- return 0;
-
-pdev_add_failed:
- platform_device_put(pdev);
-
- return ret;
-}
-
-static void w1_ds2760_remove_slave(struct w1_slave *sl)
-{
- struct platform_device *pdev = dev_get_drvdata(&sl->dev);
-
- platform_device_unregister(pdev);
-}
-
-static struct w1_family_ops w1_ds2760_fops = {
- .add_slave = w1_ds2760_add_slave,
- .remove_slave = w1_ds2760_remove_slave,
- .groups = w1_ds2760_groups,
-};
-
-static struct w1_family w1_ds2760_family = {
- .fid = W1_FAMILY_DS2760,
- .fops = &w1_ds2760_fops,
-};
-module_w1_family(w1_ds2760_family);
-
-MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
-MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760));
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
deleted file mode 100644
index 24168c94eeae..000000000000
--- a/drivers/w1/slaves/w1_ds2760.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 1-Wire implementation for the ds2760 chip
- *
- * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- */
-
-#ifndef __w1_ds2760_h__
-#define __w1_ds2760_h__
-
-/* Known commands to the DS2760 chip */
-#define W1_DS2760_SWAP 0xAA
-#define W1_DS2760_READ_DATA 0x69
-#define W1_DS2760_WRITE_DATA 0x6C
-#define W1_DS2760_COPY_DATA 0x48
-#define W1_DS2760_RECALL_DATA 0xB8
-#define W1_DS2760_LOCK 0x6A
-
-/* Number of valid register addresses */
-#define DS2760_DATA_SIZE 0x40
-
-#define DS2760_PROTECTION_REG 0x00
-
-#define DS2760_STATUS_REG 0x01
-#define DS2760_STATUS_IE (1 << 2)
-#define DS2760_STATUS_SWEN (1 << 3)
-#define DS2760_STATUS_RNAOP (1 << 4)
-#define DS2760_STATUS_PMOD (1 << 5)
-
-#define DS2760_EEPROM_REG 0x07
-#define DS2760_SPECIAL_FEATURE_REG 0x08
-#define DS2760_VOLTAGE_MSB 0x0c
-#define DS2760_VOLTAGE_LSB 0x0d
-#define DS2760_CURRENT_MSB 0x0e
-#define DS2760_CURRENT_LSB 0x0f
-#define DS2760_CURRENT_ACCUM_MSB 0x10
-#define DS2760_CURRENT_ACCUM_LSB 0x11
-#define DS2760_TEMP_MSB 0x18
-#define DS2760_TEMP_LSB 0x19
-#define DS2760_EEPROM_BLOCK0 0x20
-#define DS2760_ACTIVE_FULL 0x20
-#define DS2760_EEPROM_BLOCK1 0x30
-#define DS2760_STATUS_WRITE_REG 0x31
-#define DS2760_RATED_CAPACITY 0x32
-#define DS2760_CURRENT_OFFSET_BIAS 0x33
-#define DS2760_ACTIVE_EMPTY 0x3b
-
-extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
- size_t count);
-extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
- size_t count);
-extern int w1_ds2760_store_eeprom(struct device *dev, int addr);
-extern int w1_ds2760_recall_eeprom(struct device *dev, int addr);
-
-#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index caef0e0fd817..890c038c25f8 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -26,6 +26,7 @@
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/hwmon.h>
+#include <linux/of.h>
#include <linux/atomic.h>
@@ -686,6 +687,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
sl->dev.bus = &w1_bus_type;
sl->dev.release = &w1_slave_release;
sl->dev.groups = w1_slave_groups;
+ sl->dev.of_node = of_find_matching_node(sl->master->dev.of_node,
+ sl->family->of_match_table);
dev_set_name(&sl->dev, "%02x-%012llx",
(unsigned int) sl->reg_num.family,
diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c
index 2f3b049ea301..e268add43010 100644
--- a/drivers/watchdog/kempld_wdt.c
+++ b/drivers/watchdog/kempld_wdt.c
@@ -146,12 +146,7 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
u32 remainder;
u8 stage_cfg;
-#if GCC_VERSION < 40400
- /* work around a bug compiling do_div() */
- prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]);
-#else
prescaler = kempld_prescaler[PRESCALER_21];
-#endif
if (!stage)
return -EINVAL;
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index c866a62f766d..57390c7666e5 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -479,18 +479,25 @@ static const struct vm_operations_struct gntdev_vmops = {
/* ------------------------------------------------------------------ */
+static bool in_range(struct gntdev_grant_map *map,
+ unsigned long start, unsigned long end)
+{
+ if (!map->vma)
+ return false;
+ if (map->vma->vm_start >= end)
+ return false;
+ if (map->vma->vm_end <= start)
+ return false;
+
+ return true;
+}
+
static void unmap_if_in_range(struct gntdev_grant_map *map,
unsigned long start, unsigned long end)
{
unsigned long mstart, mend;
int err;
- if (!map->vma)
- return;
- if (map->vma->vm_start >= end)
- return;
- if (map->vma->vm_end <= start)
- return;
mstart = max(start, map->vma->vm_start);
mend = min(end, map->vma->vm_end);
pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
@@ -503,21 +510,40 @@ static void unmap_if_in_range(struct gntdev_grant_map *map,
WARN_ON(err);
}
-static void mn_invl_range_start(struct mmu_notifier *mn,
+static int mn_invl_range_start(struct mmu_notifier *mn,
struct mm_struct *mm,
- unsigned long start, unsigned long end)
+ unsigned long start, unsigned long end,
+ bool blockable)
{
struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
struct gntdev_grant_map *map;
+ int ret = 0;
+
+ /* TODO do we really need a mutex here? */
+ if (blockable)
+ mutex_lock(&priv->lock);
+ else if (!mutex_trylock(&priv->lock))
+ return -EAGAIN;
- mutex_lock(&priv->lock);
list_for_each_entry(map, &priv->maps, next) {
+ if (in_range(map, start, end)) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
unmap_if_in_range(map, start, end);
}
list_for_each_entry(map, &priv->freeable_maps, next) {
+ if (in_range(map, start, end)) {
+ ret = -EAGAIN;
+ goto out_unlock;
+ }
unmap_if_in_range(map, start, end);
}
+
+out_unlock:
mutex_unlock(&priv->lock);
+
+ return ret;
}
static void mn_release(struct mmu_notifier *mn,