summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt6
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt39
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-exynos5.txt11
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt2
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-rcar.txt3
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt26
-rw-r--r--Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt70
-rw-r--r--Documentation/devicetree/bindings/media/i2c/adv7604.txt70
-rw-r--r--Documentation/devicetree/bindings/media/renesas,vsp1.txt43
-rw-r--r--Documentation/devicetree/bindings/mfd/sun6i-prcm.txt59
-rw-r--r--Documentation/devicetree/bindings/mfd/ti-keystone-devctrl.txt19
-rw-r--r--Documentation/devicetree/bindings/mfd/twl6040.txt2
-rw-r--r--arch/arm/boot/dts/sun4i-a10.dtsi6
-rw-r--r--arch/arm/boot/dts/sun5i-a10s.dtsi6
-rw-r--r--arch/arm/boot/dts/sun5i-a13.dtsi6
-rw-r--r--arch/arm/boot/dts/sun7i-a20.dtsi10
-rw-r--r--drivers/gpio/gpio-stmpe.c18
-rw-r--r--drivers/i2c/busses/Kconfig18
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c82
-rw-r--r--drivers/i2c/busses/i2c-bcm2835.c4
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c44
-rw-r--r--drivers/i2c/busses/i2c-cros-ec-tunnel.c318
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c22
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c13
-rw-r--r--drivers/i2c/busses/i2c-diolan-u2c.c1
-rw-r--r--drivers/i2c/busses/i2c-efm32.c4
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c4
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c71
-rw-r--r--drivers/i2c/busses/i2c-gpio.c25
-rw-r--r--drivers/i2c/busses/i2c-imx.c169
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c14
-rw-r--r--drivers/i2c/busses/i2c-nuc900.c709
-rw-r--r--drivers/i2c/busses/i2c-ocores.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c4
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/i2c-rcar.c259
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c8
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c225
-rw-r--r--drivers/i2c/busses/i2c-simtec.c4
-rw-r--r--drivers/i2c/busses/i2c-sirf.c1
-rw-r--r--drivers/i2c/busses/i2c-st.c2
-rw-r--r--drivers/i2c/busses/i2c-stu300.c4
-rw-r--r--drivers/i2c/busses/i2c-tegra.c4
-rw-r--r--drivers/i2c/busses/i2c-wmt.c6
-rw-r--r--drivers/i2c/busses/scx200_acb.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c24
-rw-r--r--drivers/iommu/Kconfig26
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/amd_iommu.c8
-rw-r--r--drivers/iommu/amd_iommu_v2.c184
-rw-r--r--drivers/iommu/arm-smmu.c4
-rw-r--r--drivers/iommu/exynos-iommu.c1033
-rw-r--r--drivers/iommu/fsl_pamu.c3
-rw-r--r--drivers/iommu/ipmmu-vmsa.c1255
-rw-r--r--drivers/iommu/msm_iommu_dev.c38
-rw-r--r--drivers/iommu/omap-iommu.c31
-rw-r--r--drivers/iommu/omap-iopgtable.h3
-rw-r--r--drivers/iommu/shmobile-ipmmu.c20
-rw-r--r--drivers/media/i2c/adv7604.c1464
-rw-r--r--drivers/media/platform/vsp1/Makefile2
-rw-r--r--drivers/media/platform/vsp1/vsp1.h3
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c395
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.h39
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c101
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c57
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.h24
-rw-r--r--drivers/media/platform/vsp1/vsp1_hsit.c7
-rw-r--r--drivers/media/platform/vsp1/vsp1_lif.c1
-rw-r--r--drivers/media/platform/vsp1/vsp1_lut.c1
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h98
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c7
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.h4
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c1
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c4
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c26
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.h1
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c13
-rw-r--r--drivers/memstick/host/Kconfig10
-rw-r--r--drivers/memstick/host/Makefile1
-rw-r--r--drivers/memstick/host/rtsx_usb_ms.c839
-rw-r--r--drivers/mfd/Kconfig31
-rw-r--r--drivers/mfd/Makefile3
-rw-r--r--drivers/mfd/abx500-core.c16
-rw-r--r--drivers/mfd/arizona-core.c1
-rw-r--r--drivers/mfd/arizona-irq.c2
-rw-r--r--drivers/mfd/as3711.c2
-rw-r--r--drivers/mfd/axp20x.c258
-rw-r--r--drivers/mfd/bcm590xx.c9
-rw-r--r--drivers/mfd/cros_ec.c10
-rw-r--r--drivers/mfd/cros_ec_spi.c67
-rw-r--r--drivers/mfd/db8500-prcmu.c5
-rw-r--r--drivers/mfd/ipaq-micro.c482
-rw-r--r--drivers/mfd/kempld-core.c129
-rw-r--r--drivers/mfd/lp3943.c2
-rw-r--r--drivers/mfd/lpc_ich.c1
-rw-r--r--drivers/mfd/max14577.c40
-rw-r--r--drivers/mfd/max77686.c2
-rw-r--r--drivers/mfd/max77693.c2
-rw-r--r--drivers/mfd/max8907.c2
-rw-r--r--drivers/mfd/max8997.c2
-rw-r--r--drivers/mfd/max8998.c2
-rw-r--r--drivers/mfd/mc13xxx-core.c26
-rw-r--r--drivers/mfd/menelaus.c23
-rw-r--r--drivers/mfd/mfd-core.c11
-rw-r--r--drivers/mfd/omap-usb-host.c2
-rw-r--r--drivers/mfd/pm8921-core.c123
-rw-r--r--drivers/mfd/rdc321x-southbridge.c2
-rw-r--r--drivers/mfd/rtsx_usb.c16
-rw-r--r--drivers/mfd/sec-core.c88
-rw-r--r--drivers/mfd/sec-irq.c2
-rw-r--r--drivers/mfd/sm501.c2
-rw-r--r--drivers/mfd/stmpe-i2c.c30
-rw-r--r--drivers/mfd/stmpe.c33
-rw-r--r--drivers/mfd/stmpe.h2
-rw-r--r--drivers/mfd/sun6i-prcm.c134
-rw-r--r--drivers/mfd/syscon.c6
-rw-r--r--drivers/mfd/tps6507x.c2
-rw-r--r--drivers/mfd/tps65218.c1
-rw-r--r--drivers/mfd/tps6586x.c2
-rw-r--r--drivers/mfd/tps65910.c2
-rw-r--r--drivers/mfd/twl6040.c42
-rw-r--r--drivers/mfd/wm5102-tables.c4
-rw-r--r--drivers/mfd/wm5110-tables.c14
-rw-r--r--drivers/mfd/wm8400-core.c2
-rw-r--r--drivers/mfd/wm8997-tables.c14
-rw-r--r--drivers/mmc/host/Kconfig7
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/rtsx_usb_sdmmc.c1455
-rw-r--r--drivers/rtc/rtc-s5m.c75
-rw-r--r--drivers/sh/intc/Kconfig2
-rw-r--r--drivers/sh/pm_runtime.c40
-rw-r--r--include/linux/mfd/abx500.h1
-rw-r--r--include/linux/mfd/arizona/registers.h14
-rw-r--r--include/linux/mfd/axp20x.h180
-rw-r--r--include/linux/mfd/cros_ec.h4
-rw-r--r--include/linux/mfd/cros_ec_commands.h1128
-rw-r--r--include/linux/mfd/ipaq-micro.h148
-rw-r--r--include/linux/mfd/kempld.h4
-rw-r--r--include/linux/mfd/mc13xxx.h22
-rw-r--r--include/linux/mfd/palmas.h2166
-rw-r--r--include/linux/mfd/pm8xxx/core.h81
-rw-r--r--include/linux/mfd/rdc321x.h2
-rw-r--r--include/linux/mfd/samsung/core.h35
-rw-r--r--include/linux/mfd/stmpe.h19
-rw-r--r--include/linux/mfd/syscon.h2
-rw-r--r--include/linux/mfd/tps65218.h1
-rw-r--r--include/linux/mfd/twl6040.h3
-rw-r--r--include/linux/platform_data/ipmmu-vmsa.h24
-rw-r--r--include/media/adv7604.h122
-rw-r--r--include/media/v4l2-subdev.h4
154 files changed, 11162 insertions, 4184 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
index 1ac8ea8ade1d..bfeabb843941 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
@@ -8,6 +8,12 @@ the standard I2C multi-master rules. Using GPIOs is generally useful in
the case where there is a device on the bus that has errata and/or bugs
that makes standard multimaster mode not feasible.
+Note that this scheme works well enough but has some downsides:
+* It is nonstandard (not using standard I2C multimaster)
+* Having two masters on a bus in general makes it relatively hard to debug
+ problems (hard to tell if i2c issues were caused by one master, another, or
+ some device on the bus).
+
Algorithm:
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt b/Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt
new file mode 100644
index 000000000000..898f030eba62
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-cros-ec-tunnel.txt
@@ -0,0 +1,39 @@
+I2C bus that tunnels through the ChromeOS EC (cros-ec)
+======================================================
+On some ChromeOS board designs we've got a connection to the EC (embedded
+controller) but no direct connection to some devices on the other side of
+the EC (like a battery and PMIC). To get access to those devices we need
+to tunnel our i2c commands through the EC.
+
+The node for this device should be under a cros-ec node like google,cros-ec-spi
+or google,cros-ec-i2c.
+
+
+Required properties:
+- compatible: google,cros-ec-i2c-tunnel
+- google,remote-bus: The EC bus we'd like to talk to.
+
+Optional child nodes:
+- One node per I2C device connected to the tunnelled I2C bus.
+
+
+Example:
+ cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+
+ ...
+
+ i2c-tunnel {
+ compatible = "google,cros-ec-i2c-tunnel";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ google,remote-bus = <0>;
+
+ battery: sbs-battery@b {
+ compatible = "sbs,sbs-battery";
+ reg = <0xb>;
+ sbs,poll-retry-count = <1>;
+ };
+ };
+ }
diff --git a/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
index 056732cfdcee..d4745e31f5c6 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-exynos5.txt
@@ -5,7 +5,14 @@ at various speeds ranging from 100khz to 3.4Mhz.
Required properties:
- compatible: value should be.
- -> "samsung,exynos5-hsi2c", for i2c compatible with exynos5 hsi2c.
+ -> "samsung,exynos5-hsi2c", (DEPRECATED)
+ for i2c compatible with HSI2C available
+ on Exynos5250 and Exynos5420 SoCs.
+ -> "samsung,exynos5250-hsi2c", for i2c compatible with HSI2C available
+ on Exynos5250 and Exynos5420 SoCs.
+ -> "samsung,exynos5260-hsi2c", for i2c compatible with HSI2C available
+ on Exynos5260 SoCs.
+
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu.
@@ -26,7 +33,7 @@ Optional properties:
Example:
hsi2c@12ca0000 {
- compatible = "samsung,exynos5-hsi2c";
+ compatible = "samsung,exynos5250-hsi2c";
reg = <0x12ca0000 0x100>;
interrupts = <56>;
clock-frequency = <100000>;
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
index befd4fb4764f..5c30026921ae 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
@@ -5,7 +5,7 @@ Required properties :
- reg : Offset and length of the register set for the device
- compatible : Should be either:
- - "allwinner,sun4i-i2c"
+ - "allwinner,sun4i-a10-i2c"
- "allwinner,sun6i-a31-i2c"
- "marvell,mv64xxx-i2c"
- "marvell,mv78230-i2c"
diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
index dd8b2dd1edeb..16b3e07aa98f 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
@@ -7,6 +7,9 @@ Required properties:
"renesas,i2c-r8a7779"
"renesas,i2c-r8a7790"
"renesas,i2c-r8a7791"
+ "renesas,i2c-r8a7792"
+ "renesas,i2c-r8a7793"
+ "renesas,i2c-r8a7794"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt specifier.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt b/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
new file mode 100644
index 000000000000..d2153ce36fa8
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
@@ -0,0 +1,26 @@
+Device tree configuration for Renesas IIC (sh_mobile) driver
+
+Required properties:
+- compatible : "renesas,iic-<soctype>". "renesas,rmobile-iic" as fallback
+- reg : address start and address range size of device
+- interrupts : interrupt of device
+- clocks : clock for device
+- #address-cells : should be <1>
+- #size-cells : should be <0>
+
+Optional properties:
+- clock-frequency : frequency of bus clock in Hz. Default 100kHz if unset.
+
+Pinctrl properties might be needed, too. See there.
+
+Example:
+
+ iic0: i2c@e6500000 {
+ compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+ reg = <0 0xe6500000 0 0x425>;
+ interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
new file mode 100644
index 000000000000..6fa4c737af23
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
@@ -0,0 +1,70 @@
+Samsung Exynos IOMMU H/W, System MMU (System Memory Management Unit)
+
+Samsung's Exynos architecture contains System MMUs that enables scattered
+physical memory chunks visible as a contiguous region to DMA-capable peripheral
+devices like MFC, FIMC, FIMD, GScaler, FIMC-IS and so forth.
+
+System MMU is an IOMMU and supports identical translation table format to
+ARMv7 translation tables with minimum set of page properties including access
+permissions, shareability and security protection. In addition, System MMU has
+another capabilities like L2 TLB or block-fetch buffers to minimize translation
+latency.
+
+System MMUs are in many to one relation with peripheral devices, i.e. single
+peripheral device might have multiple System MMUs (usually one for each bus
+master), but one System MMU can handle transactions from only one peripheral
+device. The relation between a System MMU and the peripheral device needs to be
+defined in device node of the peripheral device.
+
+MFC in all Exynos SoCs and FIMD, M2M Scalers and G2D in Exynos5420 has 2 System
+MMUs.
+* MFC has one System MMU on its left and right bus.
+* FIMD in Exynos5420 has one System MMU for window 0 and 4, the other system MMU
+ for window 1, 2 and 3.
+* M2M Scalers and G2D in Exynos5420 has one System MMU on the read channel and
+ the other System MMU on the write channel.
+The drivers must consider how to handle those System MMUs. One of the idea is
+to implement child devices or sub-devices which are the client devices of the
+System MMU.
+
+Note:
+The current DT binding for the Exynos System MMU is incomplete.
+The following properties can be removed or changed, if found incompatible with
+the "Generic IOMMU Binding" support for attaching devices to the IOMMU.
+
+Required properties:
+- compatible: Should be "samsung,exynos-sysmmu"
+- reg: A tuple of base address and size of System MMU registers.
+- interrupt-parent: The phandle of the interrupt controller of System MMU
+- interrupts: An interrupt specifier for interrupt signal of System MMU,
+ according to the format defined by a particular interrupt
+ controller.
+- clock-names: Should be "sysmmu" if the System MMU is needed to gate its clock.
+ Optional "master" if the clock to the System MMU is gated by
+ another gate clock other than "sysmmu".
+ Exynos4 SoCs, there needs no "master" clock.
+ Exynos5 SoCs, some System MMUs must have "master" clocks.
+- clocks: Required if the System MMU is needed to gate its clock.
+- samsung,power-domain: Required if the System MMU is needed to gate its power.
+ Please refer to the following document:
+ Documentation/devicetree/bindings/arm/exynos/power_domain.txt
+
+Examples:
+ gsc_0: gsc@13e00000 {
+ compatible = "samsung,exynos5-gsc";
+ reg = <0x13e00000 0x1000>;
+ interrupts = <0 85 0>;
+ samsung,power-domain = <&pd_gsc>;
+ clocks = <&clock CLK_GSCL0>;
+ clock-names = "gscl";
+ };
+
+ sysmmu_gsc0: sysmmu@13E80000 {
+ compatible = "samsung,exynos-sysmmu";
+ reg = <0x13E80000 0x1000>;
+ interrupt-parent = <&combiner>;
+ interrupts = <2 0>;
+ clock-names = "sysmmu", "master";
+ clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
+ samsung,power-domain = <&pd_gsc>;
+ };
diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
new file mode 100644
index 000000000000..c27cede3bd68
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt
@@ -0,0 +1,70 @@
+* Analog Devices ADV7604/11 video decoder with HDMI receiver
+
+The ADV7604 and ADV7611 are multiformat video decoders with an integrated HDMI
+receiver. The ADV7604 has four multiplexed HDMI inputs and one analog input,
+and the ADV7611 has one HDMI input and no analog input.
+
+These device tree bindings support the ADV7611 only at the moment.
+
+Required Properties:
+
+ - compatible: Must contain one of the following
+ - "adi,adv7611" for the ADV7611
+
+ - reg: I2C slave address
+
+ - hpd-gpios: References to the GPIOs that control the HDMI hot-plug
+ detection pins, one per HDMI input. The active flag indicates the GPIO
+ level that enables hot-plug detection.
+
+The device node must contain one 'port' child node per device input and output
+port, in accordance with the video interface bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
+are numbered as follows.
+
+ Port ADV7611
+------------------------------------------------------------
+ HDMI 0
+ Digital output 1
+
+The digital output port node must contain at least one endpoint.
+
+Optional Properties:
+
+ - reset-gpios: Reference to the GPIO connected to the device's reset pin.
+
+Optional Endpoint Properties:
+
+ The following three properties are defined in video-interfaces.txt and are
+ valid for source endpoints only.
+
+ - hsync-active: Horizontal synchronization polarity. Defaults to active low.
+ - vsync-active: Vertical synchronization polarity. Defaults to active low.
+ - pclk-sample: Pixel clock polarity. Defaults to output on the falling edge.
+
+ If none of hsync-active, vsync-active and pclk-sample is specified the
+ endpoint will use embedded BT.656 synchronization.
+
+
+Example:
+
+ hdmi_receiver@4c {
+ compatible = "adi,adv7611";
+ reg = <0x4c>;
+
+ reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
+ hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ hdmi_in: endpoint {
+ remote-endpoint = <&ccdc_in>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
new file mode 100644
index 000000000000..87fe08abf36d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
@@ -0,0 +1,43 @@
+* Renesas VSP1 Video Processing Engine
+
+The VSP1 is a video processing engine that supports up-/down-scaling, alpha
+blending, color space conversion and various other image processing features.
+It can be found in the Renesas R-Car second generation SoCs.
+
+Required properties:
+
+ - compatible: Must contain "renesas,vsp1"
+
+ - reg: Base address and length of the registers block for the VSP1.
+ - interrupts: VSP1 interrupt specifier.
+ - clocks: A phandle + clock-specifier pair for the VSP1 functional clock.
+
+ - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP1.
+ - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1.
+ - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP1.
+
+
+Optional properties:
+
+ - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is
+ available.
+ - renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is
+ available.
+ - renesas,has-sru: Boolean, indicates that the Super Resolution Unit (SRU)
+ module is available.
+
+
+Example: R8A7790 (R-Car H2) VSP1-S node
+
+ vsp1@fe928000 {
+ compatible = "renesas,vsp1";
+ reg = <0 0xfe928000 0 0x8000>;
+ interrupts = <0 267 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>;
+
+ renesas,has-lut;
+ renesas,has-sru;
+ renesas,#rpf = <5>;
+ renesas,#uds = <3>;
+ renesas,#wpf = <4>;
+ };
diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
new file mode 100644
index 000000000000..1f5a31fef907
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
@@ -0,0 +1,59 @@
+* Allwinner PRCM (Power/Reset/Clock Management) Multi-Functional Device
+
+PRCM is an MFD device exposing several Power Management related devices
+(like clks and reset controllers).
+
+Required properties:
+ - compatible: "allwinner,sun6i-a31-prcm"
+ - reg: The PRCM registers range
+
+The prcm node may contain several subdevices definitions:
+ - see Documentation/devicetree/clk/sunxi.txt for clock devices
+ - see Documentation/devicetree/reset/allwinner,sunxi-clock-reset.txt for reset
+ controller devices
+
+
+Example:
+
+ prcm: prcm@01f01400 {
+ compatible = "allwinner,sun6i-a31-prcm";
+ reg = <0x01f01400 0x200>;
+
+ /* Put subdevices here */
+ ar100: ar100_clk {
+ compatible = "allwinner,sun6i-a31-ar100-clk";
+ #clock-cells = <0>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>;
+ };
+
+ ahb0: ahb0_clk {
+ compatible = "fixed-factor-clock";
+ #clock-cells = <0>;
+ clock-div = <1>;
+ clock-mult = <1>;
+ clocks = <&ar100_div>;
+ clock-output-names = "ahb0";
+ };
+
+ apb0: apb0_clk {
+ compatible = "allwinner,sun6i-a31-apb0-clk";
+ #clock-cells = <0>;
+ clocks = <&ahb0>;
+ clock-output-names = "apb0";
+ };
+
+ apb0_gates: apb0_gates_clk {
+ compatible = "allwinner,sun6i-a31-apb0-gates-clk";
+ #clock-cells = <1>;
+ clocks = <&apb0>;
+ clock-output-names = "apb0_pio", "apb0_ir",
+ "apb0_timer01", "apb0_p2wi",
+ "apb0_uart", "apb0_1wire",
+ "apb0_i2c";
+ };
+
+ apb0_rst: apb0_rst {
+ compatible = "allwinner,sun6i-a31-clock-reset";
+ #reset-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mfd/ti-keystone-devctrl.txt b/Documentation/devicetree/bindings/mfd/ti-keystone-devctrl.txt
new file mode 100644
index 000000000000..20963c76b4bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti-keystone-devctrl.txt
@@ -0,0 +1,19 @@
+* Device tree bindings for Texas Instruments keystone device state control
+
+The Keystone II devices have a set of registers that are used to control
+the status of its peripherals. This node is intended to allow access to
+this functionality.
+
+Required properties:
+
+- compatible: "ti,keystone-devctrl", "syscon"
+
+- reg: contains offset/length value for device state control
+ registers space.
+
+Example:
+
+devctrl: device-state-control@0x02620000 {
+ compatible = "ti,keystone-devctrl", "syscon";
+ reg = <0x02620000 0x1000>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
index 0f5dd709d752..a41157b5d930 100644
--- a/Documentation/devicetree/bindings/mfd/twl6040.txt
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -19,6 +19,8 @@ Required properties:
Optional properties, nodes:
- enable-active-high: To power on the twl6040 during boot.
+- clocks: phandle to the clk32k clock provider
+- clock-names: Must be "clk32k"
Vibra functionality
Required properties:
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index c7b794ed337d..d96e179490ce 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -713,7 +713,7 @@
};
i2c0: i2c@01c2ac00 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun4i-a10-i2c";
reg = <0x01c2ac00 0x400>;
interrupts = <7>;
clocks = <&apb1_gates 0>;
@@ -724,7 +724,7 @@
};
i2c1: i2c@01c2b000 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun4i-a10-i2c";
reg = <0x01c2b000 0x400>;
interrupts = <8>;
clocks = <&apb1_gates 1>;
@@ -735,7 +735,7 @@
};
i2c2: i2c@01c2b400 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun4i-a10-i2c";
reg = <0x01c2b400 0x400>;
interrupts = <9>;
clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index aa1dd59dc34a..b64f705d9008 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -560,7 +560,7 @@
i2c0: i2c@01c2ac00 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2ac00 0x400>;
interrupts = <7>;
clocks = <&apb1_gates 0>;
@@ -571,7 +571,7 @@
i2c1: i2c@01c2b000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b000 0x400>;
interrupts = <8>;
clocks = <&apb1_gates 1>;
@@ -582,7 +582,7 @@
i2c2: i2c@01c2b400 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a10s-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b400 0x400>;
interrupts = <9>;
clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c9fdb7b3ecd9..3b2a94c40f6e 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -486,7 +486,7 @@
};
i2c0: i2c@01c2ac00 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2ac00 0x400>;
interrupts = <7>;
clocks = <&apb1_gates 0>;
@@ -497,7 +497,7 @@
};
i2c1: i2c@01c2b000 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b000 0x400>;
interrupts = <8>;
clocks = <&apb1_gates 1>;
@@ -508,7 +508,7 @@
};
i2c2: i2c@01c2b400 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun5i-a13-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b400 0x400>;
interrupts = <9>;
clocks = <&apb1_gates 2>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 385933bac114..01e94664232a 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -863,7 +863,7 @@
};
i2c0: i2c@01c2ac00 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2ac00 0x400>;
interrupts = <0 7 4>;
clocks = <&apb1_gates 0>;
@@ -874,7 +874,7 @@
};
i2c1: i2c@01c2b000 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b000 0x400>;
interrupts = <0 8 4>;
clocks = <&apb1_gates 1>;
@@ -885,7 +885,7 @@
};
i2c2: i2c@01c2b400 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b400 0x400>;
interrupts = <0 9 4>;
clocks = <&apb1_gates 2>;
@@ -896,7 +896,7 @@
};
i2c3: i2c@01c2b800 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2b800 0x400>;
interrupts = <0 88 4>;
clocks = <&apb1_gates 3>;
@@ -907,7 +907,7 @@
};
i2c4: i2c@01c2c000 {
- compatible = "allwinner,sun4i-i2c";
+ compatible = "allwinner,sun7i-a20-i2c", "allwinner,sun4i-a10-i2c";
reg = <0x01c2c000 0x400>;
interrupts = <0 89 4>;
clocks = <&apb1_gates 15>;
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index 2776a09bee58..628b58494294 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -23,7 +23,8 @@
enum { REG_RE, REG_FE, REG_IE };
#define CACHE_NR_REGS 3
-#define CACHE_NR_BANKS (STMPE_NR_GPIOS / 8)
+/* No variant has more than 24 GPIOs */
+#define CACHE_NR_BANKS (24 / 8)
struct stmpe_gpio {
struct gpio_chip chip;
@@ -31,8 +32,6 @@ struct stmpe_gpio {
struct device *dev;
struct mutex irq_lock;
struct irq_domain *domain;
-
- int irq_base;
unsigned norequest_mask;
/* Caches of interrupt control registers for bus_lock */
@@ -311,13 +310,8 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
struct device_node *np)
{
- int base = 0;
-
- if (!np)
- base = stmpe_gpio->irq_base;
-
stmpe_gpio->domain = irq_domain_add_simple(np,
- stmpe_gpio->chip.ngpio, base,
+ stmpe_gpio->chip.ngpio, 0,
&stmpe_gpio_irq_simple_ops, stmpe_gpio);
if (!stmpe_gpio->domain) {
dev_err(stmpe_gpio->dev, "failed to create irqdomain\n");
@@ -354,7 +348,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
#ifdef CONFIG_OF
stmpe_gpio->chip.of_node = np;
#endif
- stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
+ stmpe_gpio->chip.base = -1;
if (pdata)
stmpe_gpio->norequest_mask = pdata->norequest_mask;
@@ -362,9 +356,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
of_property_read_u32(np, "st,norequest-mask",
&stmpe_gpio->norequest_mask);
- if (irq >= 0)
- stmpe_gpio->irq_base = stmpe->irq_base + STMPE_INT_GPIO(0);
- else
+ if (irq < 0)
dev_info(&pdev->dev,
"device configured in no-irq mode; "
"irqs are not available\n");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index c94db1c5e353..620d1004a1e7 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -449,7 +449,7 @@ config I2C_EFM32
config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
- depends on PCI
+ depends on PCI && (X86_32 || COMPILE_TEST)
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -570,13 +570,6 @@ config I2C_NOMADIK
I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
as well as the STA2X11 PCIe I/O HUB.
-config I2C_NUC900
- tristate "NUC900 I2C Driver"
- depends on ARCH_W90X900
- help
- Say Y here to include support for I2C controller in the
- Winbond/Nuvoton NUC900 based System-on-Chip devices.
-
config I2C_OCORES
tristate "OpenCores I2C Controller"
help
@@ -993,6 +986,15 @@ config I2C_SIBYTE
help
Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+config I2C_CROS_EC_TUNNEL
+ tristate "ChromeOS EC tunnel I2C bus"
+ depends on MFD_CROS_EC
+ help
+ If you say yes here you get an I2C bus that will tunnel i2c commands
+ through to the other side of the ChromeOS EC to the i2c bus
+ connected there. This will work whatever the interface used to
+ talk to the EC (SPI, I2C or LPC).
+
config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
depends on SCx200_GPIO
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 18d18ff9db93..298692cc6000 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -55,7 +55,6 @@ obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
-obj-$(CONFIG_I2C_NUC900) += i2c-nuc900.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
@@ -95,6 +94,7 @@ obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o
# Other I2C/SMBus bus drivers
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o
+obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 98a1c97739ba..15517d78d5ff 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -63,7 +63,7 @@
static struct pci_driver ali1563_pci_driver;
static unsigned short ali1563_smba;
-static int ali1563_transaction(struct i2c_adapter * a, int size)
+static int ali1563_transaction(struct i2c_adapter *a, int size)
{
u32 data;
int timeout;
@@ -78,7 +78,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) {
dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
- outb_p(data | HST_STS_BAD,SMB_HST_STS);
+ outb_p(data | HST_STS_BAD, SMB_HST_STS);
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD)
return -EBUSY;
@@ -102,10 +102,10 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
if (!timeout) {
dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
/* Issue 'kill' to host controller */
- outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
+ outb_p(HST_CNTL2_KILL, SMB_HST_CNTL2);
data = inb_p(SMB_HST_STS);
status = -ETIMEDOUT;
- }
+ }
/* device error - no response, ignore the autodetection case */
if (data & HST_STS_DEVERR) {
@@ -117,18 +117,18 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
if (data & HST_STS_BUSERR) {
dev_err(&a->dev, "Bus collision!\n");
/* Issue timeout, hoping it helps */
- outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
+ outb_p(HST_CNTL1_TIMEOUT, SMB_HST_CNTL1);
}
if (data & HST_STS_FAIL) {
dev_err(&a->dev, "Cleaning fail after KILL!\n");
- outb_p(0x0,SMB_HST_CNTL2);
+ outb_p(0x0, SMB_HST_CNTL2);
}
return status;
}
-static int ali1563_block_start(struct i2c_adapter * a)
+static int ali1563_block_start(struct i2c_adapter *a)
{
u32 data;
int timeout;
@@ -142,8 +142,8 @@ static int ali1563_block_start(struct i2c_adapter * a)
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) {
- dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
- outb_p(data | HST_STS_BAD,SMB_HST_STS);
+ dev_warn(&a->dev, "ali1563: Trying to reset busy device\n");
+ outb_p(data | HST_STS_BAD, SMB_HST_STS);
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD)
return -EBUSY;
@@ -184,13 +184,14 @@ static int ali1563_block_start(struct i2c_adapter * a)
return status;
}
-static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
+static int ali1563_block(struct i2c_adapter *a,
+ union i2c_smbus_data *data, u8 rw)
{
int i, len;
int error = 0;
/* Do we need this? */
- outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
+ outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1);
if (rw == I2C_SMBUS_WRITE) {
len = data->block[0];
@@ -198,8 +199,8 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
len = 1;
else if (len > 32)
len = 32;
- outb_p(len,SMB_HST_DAT0);
- outb_p(data->block[1],SMB_BLK_DAT);
+ outb_p(len, SMB_HST_DAT0);
+ outb_p(data->block[1], SMB_BLK_DAT);
} else
len = 32;
@@ -208,10 +209,12 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
for (i = 0; i < len; i++) {
if (rw == I2C_SMBUS_WRITE) {
outb_p(data->block[i + 1], SMB_BLK_DAT);
- if ((error = ali1563_block_start(a)))
+ error = ali1563_block_start(a);
+ if (error)
break;
} else {
- if ((error = ali1563_block_start(a)))
+ error = ali1563_block_start(a);
+ if (error)
break;
if (i == 0) {
len = inb_p(SMB_HST_DAT0);
@@ -224,25 +227,26 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8
}
}
/* Do we need this? */
- outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
+ outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1);
return error;
}
-static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
+static s32 ali1563_access(struct i2c_adapter *a, u16 addr,
unsigned short flags, char rw, u8 cmd,
- int size, union i2c_smbus_data * data)
+ int size, union i2c_smbus_data *data)
{
int error = 0;
int timeout;
u32 reg;
for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) {
- if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY))
+ reg = inb_p(SMB_HST_STS);
+ if (!(reg & HST_STS_BUSY))
break;
}
if (!timeout)
- dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg);
- outb_p(0xff,SMB_HST_STS);
+ dev_warn(&a->dev, "SMBus not idle. HST_STS = %02x\n", reg);
+ outb_p(0xff, SMB_HST_STS);
/* Map the size to what the chip understands */
switch (size) {
@@ -268,13 +272,14 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
}
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
- outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
+ outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) |
+ (size << 3), SMB_HST_CNTL2);
/* Write the command register */
- switch(size) {
+ switch (size) {
case HST_CNTL2_BYTE:
- if (rw== I2C_SMBUS_WRITE)
+ if (rw == I2C_SMBUS_WRITE)
/* Beware it uses DAT0 register and not CMD! */
outb_p(cmd, SMB_HST_DAT0);
break;
@@ -292,11 +297,12 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
break;
case HST_CNTL2_BLOCK:
outb_p(cmd, SMB_HST_CMD);
- error = ali1563_block(a,data,rw);
+ error = ali1563_block(a, data, rw);
goto Done;
}
- if ((error = ali1563_transaction(a, size)))
+ error = ali1563_transaction(a, size);
+ if (error)
goto Done;
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
@@ -317,7 +323,7 @@ Done:
return error;
}
-static u32 ali1563_func(struct i2c_adapter * a)
+static u32 ali1563_func(struct i2c_adapter *a)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
@@ -329,13 +335,13 @@ static int ali1563_setup(struct pci_dev *dev)
{
u16 ctrl;
- pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
+ pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
/* SMB I/O Base in high 12 bits and must be aligned with the
* size of the I/O space. */
ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1);
if (!ali1563_smba) {
- dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
+ dev_warn(&dev->dev, "ali1563_smba Uninitialized\n");
goto Err;
}
@@ -350,8 +356,8 @@ static int ali1563_setup(struct pci_dev *dev)
ctrl | ALI1563_SMB_IOEN);
pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
if (!(ctrl & ALI1563_SMB_IOEN)) {
- dev_err(&dev->dev, "I/O space still not enabled, "
- "giving up\n");
+ dev_err(&dev->dev,
+ "I/O space still not enabled, giving up\n");
goto Err;
}
}
@@ -375,7 +381,7 @@ Err:
static void ali1563_shutdown(struct pci_dev *dev)
{
- release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
+ release_region(ali1563_smba, ALI1563_SMB_IOSIZE);
}
static const struct i2c_algorithm ali1563_algorithm = {
@@ -394,12 +400,14 @@ static int ali1563_probe(struct pci_dev *dev,
{
int error;
- if ((error = ali1563_setup(dev)))
+ error = ali1563_setup(dev);
+ if (error)
goto exit;
ali1563_adapter.dev.parent = &dev->dev;
snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
"SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
- if ((error = i2c_add_adapter(&ali1563_adapter)))
+ error = i2c_add_adapter(&ali1563_adapter);
+ if (error)
goto exit_shutdown;
return 0;
@@ -421,12 +429,12 @@ static const struct pci_device_id ali1563_id_table[] = {
{},
};
-MODULE_DEVICE_TABLE (pci, ali1563_id_table);
+MODULE_DEVICE_TABLE(pci, ali1563_id_table);
static struct pci_driver ali1563_pci_driver = {
- .name = "ali1563_smbus",
+ .name = "ali1563_smbus",
.id_table = ali1563_id_table,
- .probe = ali1563_probe,
+ .probe = ali1563_probe,
.remove = ali1563_remove,
};
diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
index c60719577fc3..214ff9700efe 100644
--- a/drivers/i2c/busses/i2c-bcm2835.c
+++ b/drivers/i2c/busses/i2c-bcm2835.c
@@ -225,10 +225,8 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
struct i2c_adapter *adap;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
- if (!i2c_dev) {
- dev_err(&pdev->dev, "Cannot allocate i2c_dev\n");
+ if (!i2c_dev)
return -ENOMEM;
- }
platform_set_drvdata(pdev, i2c_dev);
i2c_dev->dev = &pdev->dev;
init_completion(&i2c_dev->completion);
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index e6d5162b6379..3e271e7558d3 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -620,35 +620,27 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
int rc;
unsigned int clkhilow;
- iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
+ iface = devm_kzalloc(&pdev->dev, sizeof(struct bfin_twi_iface),
+ GFP_KERNEL);
if (!iface) {
dev_err(&pdev->dev, "Cannot allocate memory\n");
- rc = -ENOMEM;
- goto out_error_nomem;
+ return -ENOMEM;
}
spin_lock_init(&(iface->lock));
/* Find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
- rc = -ENOENT;
- goto out_error_get_res;
- }
-
- iface->regs_base = ioremap(res->start, resource_size(res));
- if (iface->regs_base == NULL) {
+ iface->regs_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(iface->regs_base)) {
dev_err(&pdev->dev, "Cannot map IO\n");
- rc = -ENXIO;
- goto out_error_ioremap;
+ return PTR_ERR(iface->regs_base);
}
iface->irq = platform_get_irq(pdev, 0);
if (iface->irq < 0) {
dev_err(&pdev->dev, "No IRQ specified\n");
- rc = -ENOENT;
- goto out_error_no_irq;
+ return -ENOENT;
}
p_adap = &iface->adap;
@@ -666,15 +658,15 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
"i2c-bfin-twi");
if (rc) {
dev_err(&pdev->dev, "Can't setup pin mux!\n");
- goto out_error_pin_mux;
+ return -EBUSY;
}
- rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
+ rc = devm_request_irq(&pdev->dev, iface->irq, bfin_twi_interrupt_entry,
0, pdev->name, iface);
if (rc) {
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
rc = -ENODEV;
- goto out_error_req_irq;
+ goto out_error;
}
/* Set TWI internal clock as 10MHz */
@@ -695,7 +687,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
rc = i2c_add_numbered_adapter(p_adap);
if (rc < 0) {
dev_err(&pdev->dev, "Can't add i2c adapter!\n");
- goto out_error_add_adapter;
+ goto out_error;
}
platform_set_drvdata(pdev, iface);
@@ -705,17 +697,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
return 0;
-out_error_add_adapter:
- free_irq(iface->irq, iface);
-out_error_req_irq:
-out_error_no_irq:
+out_error:
peripheral_free_list(dev_get_platdata(&pdev->dev));
-out_error_pin_mux:
- iounmap(iface->regs_base);
-out_error_ioremap:
-out_error_get_res:
- kfree(iface);
-out_error_nomem:
return rc;
}
@@ -724,10 +707,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
i2c_del_adapter(&(iface->adap));
- free_irq(iface->irq, iface);
peripheral_free_list(dev_get_platdata(&pdev->dev));
- iounmap(iface->regs_base);
- kfree(iface);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
new file mode 100644
index 000000000000..8e7a71487bb1
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c
@@ -0,0 +1,318 @@
+/*
+ * 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.
+ *
+ * Expose an I2C passthrough to the ChromeOS EC.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/**
+ * struct ec_i2c_device - Driver data for I2C tunnel
+ *
+ * @dev: Device node
+ * @adap: I2C adapter
+ * @ec: Pointer to EC device
+ * @remote_bus: The EC bus number we tunnel to on the other side.
+ * @request_buf: Buffer for transmitting data; we expect most transfers to fit.
+ * @response_buf: Buffer for receiving data; we expect most transfers to fit.
+ */
+
+struct ec_i2c_device {
+ struct device *dev;
+ struct i2c_adapter adap;
+ struct cros_ec_device *ec;
+
+ u16 remote_bus;
+
+ u8 request_buf[256];
+ u8 response_buf[256];
+};
+
+/**
+ * ec_i2c_count_message - Count bytes needed for ec_i2c_construct_message
+ *
+ * @i2c_msgs: The i2c messages to read
+ * @num: The number of i2c messages.
+ *
+ * Returns the number of bytes the messages will take up.
+ */
+static int ec_i2c_count_message(const struct i2c_msg i2c_msgs[], int num)
+{
+ int i;
+ int size;
+
+ size = sizeof(struct ec_params_i2c_passthru);
+ size += num * sizeof(struct ec_params_i2c_passthru_msg);
+ for (i = 0; i < num; i++)
+ if (!(i2c_msgs[i].flags & I2C_M_RD))
+ size += i2c_msgs[i].len;
+
+ return size;
+}
+
+/**
+ * ec_i2c_construct_message - construct a message to go to the EC
+ *
+ * This function effectively stuffs the standard i2c_msg format of Linux into
+ * a format that the EC understands.
+ *
+ * @buf: The buffer to fill. We assume that the buffer is big enough.
+ * @i2c_msgs: The i2c messages to read.
+ * @num: The number of i2c messages.
+ * @bus_num: The remote bus number we want to talk to.
+ *
+ * Returns 0 or a negative error number.
+ */
+static int ec_i2c_construct_message(u8 *buf, const struct i2c_msg i2c_msgs[],
+ int num, u16 bus_num)
+{
+ struct ec_params_i2c_passthru *params;
+ u8 *out_data;
+ int i;
+
+ out_data = buf + sizeof(struct ec_params_i2c_passthru) +
+ num * sizeof(struct ec_params_i2c_passthru_msg);
+
+ params = (struct ec_params_i2c_passthru *)buf;
+ params->port = bus_num;
+ params->num_msgs = num;
+ for (i = 0; i < num; i++) {
+ const struct i2c_msg *i2c_msg = &i2c_msgs[i];
+ struct ec_params_i2c_passthru_msg *msg = &params->msg[i];
+
+ msg->len = i2c_msg->len;
+ msg->addr_flags = i2c_msg->addr;
+
+ if (i2c_msg->flags & I2C_M_TEN)
+ msg->addr_flags |= EC_I2C_FLAG_10BIT;
+
+ if (i2c_msg->flags & I2C_M_RD) {
+ msg->addr_flags |= EC_I2C_FLAG_READ;
+ } else {
+ memcpy(out_data, i2c_msg->buf, msg->len);
+ out_data += msg->len;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ec_i2c_count_response - Count bytes needed for ec_i2c_parse_response
+ *
+ * @i2c_msgs: The i2c messages to to fill up.
+ * @num: The number of i2c messages expected.
+ *
+ * Returns the number of response bytes expeced.
+ */
+static int ec_i2c_count_response(struct i2c_msg i2c_msgs[], int num)
+{
+ int size;
+ int i;
+
+ size = sizeof(struct ec_response_i2c_passthru);
+ for (i = 0; i < num; i++)
+ if (i2c_msgs[i].flags & I2C_M_RD)
+ size += i2c_msgs[i].len;
+
+ return size;
+}
+
+/**
+ * ec_i2c_parse_response - Parse a response from the EC
+ *
+ * We'll take the EC's response and copy it back into msgs.
+ *
+ * @buf: The buffer to parse.
+ * @i2c_msgs: The i2c messages to to fill up.
+ * @num: The number of i2c messages; will be modified to include the actual
+ * number received.
+ *
+ * Returns 0 or a negative error number.
+ */
+static int ec_i2c_parse_response(const u8 *buf, struct i2c_msg i2c_msgs[],
+ int *num)
+{
+ const struct ec_response_i2c_passthru *resp;
+ const u8 *in_data;
+ int i;
+
+ in_data = buf + sizeof(struct ec_response_i2c_passthru);
+
+ resp = (const struct ec_response_i2c_passthru *)buf;
+ if (resp->i2c_status & EC_I2C_STATUS_TIMEOUT)
+ return -ETIMEDOUT;
+ else if (resp->i2c_status & EC_I2C_STATUS_ERROR)
+ return -EREMOTEIO;
+
+ /* Other side could send us back fewer messages, but not more */
+ if (resp->num_msgs > *num)
+ return -EPROTO;
+ *num = resp->num_msgs;
+
+ for (i = 0; i < *num; i++) {
+ struct i2c_msg *i2c_msg = &i2c_msgs[i];
+
+ if (i2c_msgs[i].flags & I2C_M_RD) {
+ memcpy(i2c_msg->buf, in_data, i2c_msg->len);
+ in_data += i2c_msg->len;
+ }
+ }
+
+ return 0;
+}
+
+static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
+ int num)
+{
+ struct ec_i2c_device *bus = adap->algo_data;
+ struct device *dev = bus->dev;
+ const u16 bus_num = bus->remote_bus;
+ int request_len;
+ int response_len;
+ u8 *request = NULL;
+ u8 *response = NULL;
+ int result;
+
+ request_len = ec_i2c_count_message(i2c_msgs, num);
+ if (request_len < 0) {
+ dev_warn(dev, "Error constructing message %d\n", request_len);
+ result = request_len;
+ goto exit;
+ }
+ response_len = ec_i2c_count_response(i2c_msgs, num);
+ if (response_len < 0) {
+ /* Unexpected; no errors should come when NULL response */
+ dev_warn(dev, "Error preparing response %d\n", response_len);
+ result = response_len;
+ goto exit;
+ }
+
+ if (request_len <= ARRAY_SIZE(bus->request_buf)) {
+ request = bus->request_buf;
+ } else {
+ request = kzalloc(request_len, GFP_KERNEL);
+ if (request == NULL) {
+ result = -ENOMEM;
+ goto exit;
+ }
+ }
+ if (response_len <= ARRAY_SIZE(bus->response_buf)) {
+ response = bus->response_buf;
+ } else {
+ response = kzalloc(response_len, GFP_KERNEL);
+ if (response == NULL) {
+ result = -ENOMEM;
+ goto exit;
+ }
+ }
+
+ ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
+ result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU,
+ request, request_len,
+ response, response_len);
+ if (result)
+ goto exit;
+
+ result = ec_i2c_parse_response(response, i2c_msgs, &num);
+ if (result < 0)
+ goto exit;
+
+ /* Indicate success by saying how many messages were sent */
+ result = num;
+exit:
+ if (request != bus->request_buf)
+ kfree(request);
+ if (response != bus->response_buf)
+ kfree(response);
+
+ return result;
+}
+
+static u32 ec_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm ec_i2c_algorithm = {
+ .master_xfer = ec_i2c_xfer,
+ .functionality = ec_i2c_functionality,
+};
+
+static int ec_i2c_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct ec_i2c_device *bus = NULL;
+ u32 remote_bus;
+ int err;
+
+ if (!ec->command_sendrecv) {
+ dev_err(dev, "Missing sendrecv\n");
+ return -EINVAL;
+ }
+
+ bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
+ if (bus == NULL)
+ return -ENOMEM;
+
+ err = of_property_read_u32(np, "google,remote-bus", &remote_bus);
+ if (err) {
+ dev_err(dev, "Couldn't read remote-bus property\n");
+ return err;
+ }
+ bus->remote_bus = remote_bus;
+
+ bus->ec = ec;
+ bus->dev = dev;
+
+ bus->adap.owner = THIS_MODULE;
+ strlcpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name));
+ bus->adap.algo = &ec_i2c_algorithm;
+ bus->adap.algo_data = bus;
+ bus->adap.dev.parent = &pdev->dev;
+ bus->adap.dev.of_node = np;
+
+ err = i2c_add_adapter(&bus->adap);
+ if (err) {
+ dev_err(dev, "cannot register i2c adapter\n");
+ return err;
+ }
+ platform_set_drvdata(pdev, bus);
+
+ return err;
+}
+
+static int ec_i2c_remove(struct platform_device *dev)
+{
+ struct ec_i2c_device *bus = platform_get_drvdata(dev);
+
+ i2c_del_adapter(&bus->adap);
+
+ return 0;
+}
+
+static struct platform_driver ec_i2c_tunnel_driver = {
+ .probe = ec_i2c_probe,
+ .remove = ec_i2c_remove,
+ .driver = {
+ .name = "cros-ec-i2c-tunnel",
+ },
+};
+
+module_platform_driver(ec_i2c_tunnel_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("EC I2C tunnel driver");
+MODULE_ALIAS("platform:cros-ec-i2c-tunnel");
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 85056c22d21e..3356f7ab9f79 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -56,6 +56,7 @@ enum dw_pci_ctl_id_t {
medfield_5,
baytrail,
+ haswell,
};
struct dw_scl_sda_cfg {
@@ -95,6 +96,15 @@ static struct dw_scl_sda_cfg byt_config = {
.sda_hold = 0x6,
};
+/* Haswell HCNT/LCNT/SDA hold time */
+static struct dw_scl_sda_cfg hsw_config = {
+ .ss_hcnt = 0x01b0,
+ .fs_hcnt = 0x48,
+ .ss_lcnt = 0x01fb,
+ .fs_lcnt = 0xa0,
+ .sda_hold = 0x9,
+};
+
static struct dw_pci_controller dw_pci_controllers[] = {
[moorestown_0] = {
.bus_num = 0,
@@ -168,6 +178,15 @@ static struct dw_pci_controller dw_pci_controllers[] = {
.functionality = I2C_FUNC_10BIT_ADDR,
.scl_sda_cfg = &byt_config,
},
+ [haswell] = {
+ .bus_num = -1,
+ .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
+ .tx_fifo_depth = 32,
+ .rx_fifo_depth = 32,
+ .clk_khz = 100000,
+ .functionality = I2C_FUNC_10BIT_ADDR,
+ .scl_sda_cfg = &hsw_config,
+ },
};
static struct i2c_algorithm i2c_dw_algo = {
.master_xfer = i2c_dw_xfer,
@@ -328,6 +347,9 @@ static const struct pci_device_id i2_designware_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0F45), baytrail },
{ PCI_VDEVICE(INTEL, 0x0F46), baytrail },
{ PCI_VDEVICE(INTEL, 0x0F47), baytrail },
+ /* Haswell */
+ { PCI_VDEVICE(INTEL, 0x9c61), haswell },
+ { PCI_VDEVICE(INTEL, 0x9c62), haswell },
{ 0,}
};
MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 9c7802614342..402ec3970fed 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -247,12 +247,13 @@ static const struct of_device_id dw_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int dw_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
+ i2c_dw_disable(i_dev);
clk_disable_unprepare(i_dev->clk);
return 0;
@@ -268,13 +269,11 @@ static int dw_i2c_resume(struct device *dev)
return 0;
}
-
-static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
-#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops)
-#else
-#define DW_I2C_DEV_PM_OPS NULL
#endif
+static UNIVERSAL_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend,
+ dw_i2c_resume, NULL);
+
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c_designware");
@@ -286,7 +285,7 @@ static struct platform_driver dw_i2c_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(dw_i2c_of_match),
.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
- .pm = DW_I2C_DEV_PM_OPS,
+ .pm = &dw_i2c_dev_pm_ops,
},
};
diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c
index 721f7ebf9a3b..b19a310bf9b3 100644
--- a/drivers/i2c/busses/i2c-diolan-u2c.c
+++ b/drivers/i2c/busses/i2c-diolan-u2c.c
@@ -455,7 +455,6 @@ static int diolan_u2c_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
- dev_err(&interface->dev, "no memory for device state\n");
ret = -ENOMEM;
goto error;
}
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
index 777ed409a24a..f7eccd682de9 100644
--- a/drivers/i2c/busses/i2c-efm32.c
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -320,10 +320,8 @@ static int efm32_i2c_probe(struct platform_device *pdev)
return -EINVAL;
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata) {
- dev_dbg(&pdev->dev, "failed to allocate private data\n");
+ if (!ddata)
return -ENOMEM;
- }
platform_set_drvdata(pdev, ddata);
init_completion(&ddata->done);
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index ff775ac29e49..a44ea13d1434 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -751,10 +751,8 @@ static int pch_i2c_probe(struct pci_dev *pdev,
pch_pci_dbg(pdev, "Entered.\n");
adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL);
- if (adap_info == NULL) {
- pch_pci_err(pdev, "Memory allocation FAILED\n");
+ if (adap_info == NULL)
return -ENOMEM;
- }
ret = pci_enable_device(pdev);
if (ret) {
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 00af0a0a3361..63d229202854 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -76,12 +76,6 @@
#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4)
#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16)
-/* As per user manual FIFO max depth is 64bytes */
-#define HSI2C_FIFO_MAX 0x40
-/* default trigger levels for Tx and Rx FIFOs */
-#define HSI2C_DEF_TXFIFO_LVL (HSI2C_FIFO_MAX - 0x30)
-#define HSI2C_DEF_RXFIFO_LVL (HSI2C_FIFO_MAX - 0x10)
-
/* I2C_TRAILING_CTL Register bits */
#define HSI2C_TRAILING_COUNT (0xf)
@@ -183,14 +177,54 @@ struct exynos5_i2c {
* 2. Fast speed upto 1Mbps
*/
int speed_mode;
+
+ /* Version of HS-I2C Hardware */
+ struct exynos_hsi2c_variant *variant;
+};
+
+/**
+ * struct exynos_hsi2c_variant - platform specific HSI2C driver data
+ * @fifo_depth: the fifo depth supported by the HSI2C module
+ *
+ * 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;
+};
+
+static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
+ .fifo_depth = 64,
+};
+
+static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
+ .fifo_depth = 16,
};
static const struct of_device_id exynos5_i2c_match[] = {
- { .compatible = "samsung,exynos5-hsi2c" },
- {},
+ {
+ .compatible = "samsung,exynos5-hsi2c",
+ .data = &exynos5250_hsi2c_data
+ }, {
+ .compatible = "samsung,exynos5250-hsi2c",
+ .data = &exynos5250_hsi2c_data
+ }, {
+ .compatible = "samsung,exynos5260-hsi2c",
+ .data = &exynos5260_hsi2c_data
+ }, {},
};
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
+static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant
+ (struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+
+ match = of_match_node(exynos5_i2c_match, pdev->dev.of_node);
+ return (struct exynos_hsi2c_variant *)match->data;
+}
+
static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
{
writel(readl(i2c->regs + HSI2C_INT_STATUS),
@@ -415,7 +449,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS);
fifo_level = HSI2C_TX_FIFO_LVL(fifo_status);
- len = HSI2C_FIFO_MAX - fifo_level;
+ len = i2c->variant->fifo_depth - fifo_level;
if (len > (i2c->msg->len - i2c->msg_ptr))
len = i2c->msg->len - i2c->msg_ptr;
@@ -483,6 +517,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
u32 i2c_auto_conf = 0;
u32 fifo_ctl;
unsigned long flags;
+ unsigned short trig_lvl;
i2c_ctl = readl(i2c->regs + HSI2C_CTL);
i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON);
@@ -493,13 +528,19 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
i2c_auto_conf = HSI2C_READ_WRITE;
- fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(HSI2C_DEF_TXFIFO_LVL);
+ trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
+ (i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
+ fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(trig_lvl);
+
int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN |
HSI2C_INT_TRAILING_EN);
} else {
i2c_ctl |= HSI2C_TXCHON;
- fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(HSI2C_DEF_RXFIFO_LVL);
+ trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
+ (i2c->variant->fifo_depth * 1 / 4) : i2c->msg->len;
+ fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(trig_lvl);
+
int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN;
}
@@ -621,10 +662,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
int ret;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL);
- if (!i2c) {
- dev_err(&pdev->dev, "no memory for state\n");
+ if (!i2c)
return -ENOMEM;
- }
if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
i2c->speed_mode = HSI2C_FAST_SPD;
@@ -691,7 +730,9 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
if (ret)
goto err_clk;
- exynos5_i2c_init(i2c);
+ i2c->variant = exynos5_i2c_get_variant(pdev);
+
+ exynos5_i2c_reset(i2c);
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 02d2d4abb9dd..71a45b210a24 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -147,24 +147,22 @@ static int i2c_gpio_probe(struct platform_device *pdev)
scl_pin = pdata->scl_pin;
}
- ret = gpio_request(sda_pin, "sda");
+ ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
if (ret) {
if (ret == -EINVAL)
ret = -EPROBE_DEFER; /* Try again later */
- goto err_request_sda;
+ return ret;
}
- ret = gpio_request(scl_pin, "scl");
+ ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
if (ret) {
if (ret == -EINVAL)
ret = -EPROBE_DEFER; /* Try again later */
- goto err_request_scl;
+ return ret;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- ret = -ENOMEM;
- goto err_add_bus;
- }
+ if (!priv)
+ return -ENOMEM;
adap = &priv->adap;
bit_data = &priv->bit_data;
pdata = &priv->pdata;
@@ -225,7 +223,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap);
if (ret)
- goto err_add_bus;
+ return ret;
platform_set_drvdata(pdev, priv);
@@ -235,13 +233,6 @@ static int i2c_gpio_probe(struct platform_device *pdev)
? ", no clock stretching" : "");
return 0;
-
-err_add_bus:
- gpio_free(scl_pin);
-err_request_scl:
- gpio_free(sda_pin);
-err_request_sda:
- return ret;
}
static int i2c_gpio_remove(struct platform_device *pdev)
@@ -255,8 +246,6 @@ static int i2c_gpio_remove(struct platform_device *pdev)
pdata = &priv->pdata;
i2c_del_adapter(adap);
- gpio_free(pdata->scl_pin);
- gpio_free(pdata->sda_pin);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index db895fb22e65..aa8bc146718b 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -183,6 +183,8 @@ struct imx_i2c_struct {
unsigned int disable_delay;
int stopped;
unsigned int ifdr; /* IMX_I2C_IFDR */
+ unsigned int cur_clk;
+ unsigned int bitrate;
const struct imx_i2c_hwdata *hwdata;
};
@@ -305,6 +307,48 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
return 0;
}
+static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
+{
+ struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
+ unsigned int i2c_clk_rate;
+ unsigned int div;
+ int i;
+
+ /* Divider value calculation */
+ i2c_clk_rate = clk_get_rate(i2c_imx->clk);
+ if (i2c_imx->cur_clk == i2c_clk_rate)
+ return;
+ else
+ i2c_imx->cur_clk = i2c_clk_rate;
+
+ div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate;
+ if (div < i2c_clk_div[0].div)
+ i = 0;
+ else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
+ i = i2c_imx->hwdata->ndivs - 1;
+ else
+ for (i = 0; i2c_clk_div[i].div < div; i++);
+
+ /* Store divider value */
+ i2c_imx->ifdr = i2c_clk_div[i].val;
+
+ /*
+ * There dummy delay is calculated.
+ * It should be about one I2C clock period long.
+ * This delay is used in I2C bus disable function
+ * to fix chip hardware bug.
+ */
+ i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
+ + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
+
+#ifdef CONFIG_I2C_DEBUG_BUS
+ dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n",
+ i2c_clk_rate, div);
+ dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n",
+ i2c_clk_div[i].val, i2c_clk_div[i].div);
+#endif
+}
+
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
@@ -312,6 +356,8 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ i2c_imx_set_clk(i2c_imx);
+
result = clk_prepare_enable(i2c_imx->clk);
if (result)
return result;
@@ -367,45 +413,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
clk_disable_unprepare(i2c_imx->clk);
}
-static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
- unsigned int rate)
-{
- struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
- unsigned int i2c_clk_rate;
- unsigned int div;
- int i;
-
- /* Divider value calculation */
- i2c_clk_rate = clk_get_rate(i2c_imx->clk);
- div = (i2c_clk_rate + rate - 1) / rate;
- if (div < i2c_clk_div[0].div)
- i = 0;
- else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
- i = i2c_imx->hwdata->ndivs - 1;
- else
- for (i = 0; i2c_clk_div[i].div < div; i++);
-
- /* Store divider value */
- i2c_imx->ifdr = i2c_clk_div[i].val;
-
- /*
- * There dummy delay is calculated.
- * It should be about one I2C clock period long.
- * This delay is used in I2C bus disable function
- * to fix chip hardware bug.
- */
- i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
- + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
-
- /* dev_dbg() can't be used, because adapter is not yet registered */
-#ifdef CONFIG_I2C_DEBUG_BUS
- dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
- __func__, i2c_clk_rate, div);
- dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
- __func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
-#endif
-}
-
static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
{
struct imx_i2c_struct *i2c_imx = dev_id;
@@ -458,10 +465,11 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
return 0;
}
-static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
+static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg)
{
int i, result;
unsigned int temp;
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
dev_dbg(&i2c_imx->adapter.dev,
"<%s> write slave address: addr=0x%x\n",
@@ -481,7 +489,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
/* setup bus to read data */
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
temp &= ~I2CR_MTX;
- if (msgs->len - 1)
+
+ /*
+ * Reset the I2CR_TXAK flag initially for SMBus block read since the
+ * length is unknown
+ */
+ if ((msgs->len - 1) || block_data)
temp &= ~I2CR_TXAK;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
@@ -490,19 +503,49 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
/* read data */
for (i = 0; i < msgs->len; i++) {
+ u8 len = 0;
result = i2c_imx_trx_complete(i2c_imx);
if (result)
return result;
- if (i == (msgs->len - 1)) {
- /* It must generate STOP before read I2DR to prevent
- controller from generating another clock cycle */
+ /*
+ * First byte is the length of remaining packet
+ * in the SMBus block data read. Add it to
+ * msgs->len.
+ */
+ if ((!i) && block_data) {
+ len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+ if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
+ return -EPROTO;
dev_dbg(&i2c_imx->adapter.dev,
- "<%s> clear MSTA\n", __func__);
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- 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;
+ "<%s> read length: 0x%X\n",
+ __func__, len);
+ msgs->len += len;
+ }
+ if (i == (msgs->len - 1)) {
+ if (is_lastmsg) {
+ /*
+ * It must generate STOP before read I2DR to prevent
+ * controller from generating another clock cycle
+ */
+ dev_dbg(&i2c_imx->adapter.dev,
+ "<%s> clear MSTA\n", __func__);
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ 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:
+ * read -> repeat MSTA -> read/write
+ * The controller must set MTX before read the last byte in
+ * the first read operation, otherwise the first read cost
+ * one extra clock cycle.
+ */
+ temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+ temp |= I2CR_MTX;
+ writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ }
} else if (i == (msgs->len - 2)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> set TXAK\n", __func__);
@@ -510,7 +553,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
temp |= I2CR_TXAK;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
}
- msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
+ if ((!i) && block_data)
+ msgs->buf[0] = len;
+ else
+ msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
dev_dbg(&i2c_imx->adapter.dev,
"<%s> read byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
@@ -523,6 +569,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
{
unsigned int i, temp;
int result;
+ bool is_lastmsg = false;
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
@@ -534,6 +581,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
/* read/write data */
for (i = 0; i < num; i++) {
+ if (i == num - 1)
+ is_lastmsg = true;
+
if (i) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> repeated start\n", __func__);
@@ -564,7 +614,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
(temp & I2SR_RXAK ? 1 : 0));
#endif
if (msgs[i].flags & I2C_M_RD)
- result = i2c_imx_read(i2c_imx, &msgs[i]);
+ result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg);
else
result = i2c_imx_write(i2c_imx, &msgs[i]);
if (result)
@@ -583,7 +633,8 @@ fail0:
static u32 i2c_imx_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
+ | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
}
static struct i2c_algorithm i2c_imx_algo = {
@@ -600,7 +651,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
void __iomem *base;
int irq, ret;
- u32 bitrate;
dev_dbg(&pdev->dev, "<%s>\n", __func__);
@@ -617,10 +667,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct),
GFP_KERNEL);
- if (!i2c_imx) {
- dev_err(&pdev->dev, "can't allocate interface\n");
+ if (!i2c_imx)
return -ENOMEM;
- }
if (of_id)
i2c_imx->hwdata = of_id->data;
@@ -664,12 +712,11 @@ static int i2c_imx_probe(struct platform_device *pdev)
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
/* Set up clock divider */
- bitrate = IMX_I2C_BIT_RATE;
+ i2c_imx->bitrate = IMX_I2C_BIT_RATE;
ret = of_property_read_u32(pdev->dev.of_node,
- "clock-frequency", &bitrate);
+ "clock-frequency", &i2c_imx->bitrate);
if (ret < 0 && pdata && pdata->bitrate)
- bitrate = pdata->bitrate;
- i2c_imx_set_clk(i2c_imx, bitrate);
+ i2c_imx->bitrate = pdata->bitrate;
/* Set up chip registers to defaults */
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f5391633b53a..6a32aa095f83 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -115,7 +115,7 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c)
for (k = 9; k; k--) {
writeccr(i2c, 0);
writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
- udelay(delay_val);
+ readb(i2c->base + MPC_I2C_DR);
writeccr(i2c, CCR_MEN);
udelay(delay_val << 1);
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 540ea692bf79..9f4b775e2e39 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -681,7 +681,7 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = {
*****************************************************************************
*/
static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
- { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i},
+ { .compatible = "allwinner,sun4i-a10-i2c", .data = &mv64xxx_i2c_regs_sun4i},
{ .compatible = "allwinner,sun6i-a31-i2c", .data = &mv64xxx_i2c_regs_sun4i},
{ .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
{ .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx},
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 32c85e9ecdae..0e55d85fd4ed 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -879,19 +879,19 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
#ifdef CONFIG_PM_SLEEP
static int nmk_i2c_suspend_late(struct device *dev)
{
- pinctrl_pm_select_sleep_state(dev);
+ int ret;
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+
+ pinctrl_pm_select_sleep_state(dev);
return 0;
}
static int nmk_i2c_resume_early(struct device *dev)
{
- /* First go to the default state */
- pinctrl_pm_select_default_state(dev);
- /* Then let's idle the pins until the next transfer happens */
- pinctrl_pm_select_idle_state(dev);
-
- return 0;
+ return pm_runtime_force_resume(dev);
}
#endif
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
deleted file mode 100644
index 36394d737faf..000000000000
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * linux/drivers/i2c/busses/i2c-nuc900.c
- *
- * Copyright (c) 2010 Nuvoton technology corporation.
- *
- * This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>.
- * Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;version 2 of the License.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-
-#include <mach/mfp.h>
-#include <linux/platform_data/i2c-nuc900.h>
-
-/* nuc900 i2c registers offset */
-
-#define CSR 0x00
-#define DIVIDER 0x04
-#define CMDR 0x08
-#define SWR 0x0C
-#define RXR 0x10
-#define TXR 0x14
-
-/* nuc900 i2c CSR register bits */
-
-#define IRQEN 0x003
-#define I2CBUSY 0x400
-#define I2CSTART 0x018
-#define IRQFLAG 0x004
-#define ARBIT_LOST 0x200
-#define SLAVE_ACK 0x800
-
-/* nuc900 i2c CMDR register bits */
-
-#define I2C_CMD_START 0x10
-#define I2C_CMD_STOP 0x08
-#define I2C_CMD_READ 0x04
-#define I2C_CMD_WRITE 0x02
-#define I2C_CMD_NACK 0x01
-
-/* i2c controller state */
-
-enum nuc900_i2c_state {
- STATE_IDLE,
- STATE_START,
- STATE_READ,
- STATE_WRITE,
- STATE_STOP
-};
-
-/* i2c controller private data */
-
-struct nuc900_i2c {
- spinlock_t lock;
- wait_queue_head_t wait;
-
- struct i2c_msg *msg;
- unsigned int msg_num;
- unsigned int msg_idx;
- unsigned int msg_ptr;
- unsigned int irq;
-
- enum nuc900_i2c_state state;
-
- void __iomem *regs;
- struct clk *clk;
- struct device *dev;
- struct resource *ioarea;
- struct i2c_adapter adap;
-};
-
-/* nuc900_i2c_master_complete
- *
- * complete the message and wake up the caller, using the given return code,
- * or zero to mean ok.
-*/
-
-static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret)
-{
- dev_dbg(i2c->dev, "master_complete %d\n", ret);
-
- i2c->msg_ptr = 0;
- i2c->msg = NULL;
- i2c->msg_idx++;
- i2c->msg_num = 0;
- if (ret)
- i2c->msg_idx = ret;
-
- wake_up(&i2c->wait);
-}
-
-/* irq enable/disable functions */
-
-static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c)
-{
- unsigned long tmp;
-
- tmp = readl(i2c->regs + CSR);
- writel(tmp & ~IRQEN, i2c->regs + CSR);
-}
-
-static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c)
-{
- unsigned long tmp;
-
- tmp = readl(i2c->regs + CSR);
- writel(tmp | IRQEN, i2c->regs + CSR);
-}
-
-
-/* nuc900_i2c_message_start
- *
- * put the start of a message onto the bus
-*/
-
-static void nuc900_i2c_message_start(struct nuc900_i2c *i2c,
- struct i2c_msg *msg)
-{
- unsigned int addr = (msg->addr & 0x7f) << 1;
-
- if (msg->flags & I2C_M_RD)
- addr |= 0x1;
- writel(addr & 0xff, i2c->regs + TXR);
- writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR);
-}
-
-static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret)
-{
-
- dev_dbg(i2c->dev, "STOP\n");
-
- /* stop the transfer */
- i2c->state = STATE_STOP;
- writel(I2C_CMD_STOP, i2c->regs + CMDR);
-
- nuc900_i2c_master_complete(i2c, ret);
- nuc900_i2c_disable_irq(i2c);
-}
-
-/* helper functions to determine the current state in the set of
- * messages we are sending
-*/
-
-/* is_lastmsg()
- *
- * returns TRUE if the current message is the last in the set
-*/
-
-static inline int is_lastmsg(struct nuc900_i2c *i2c)
-{
- return i2c->msg_idx >= (i2c->msg_num - 1);
-}
-
-/* is_msglast
- *
- * returns TRUE if we this is the last byte in the current message
-*/
-
-static inline int is_msglast(struct nuc900_i2c *i2c)
-{
- return i2c->msg_ptr == i2c->msg->len-1;
-}
-
-/* is_msgend
- *
- * returns TRUE if we reached the end of the current message
-*/
-
-static inline int is_msgend(struct nuc900_i2c *i2c)
-{
- return i2c->msg_ptr >= i2c->msg->len;
-}
-
-/* i2c_nuc900_irq_nextbyte
- *
- * process an interrupt and work out what to do
- */
-
-static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c,
- unsigned long iicstat)
-{
- unsigned char byte;
-
- switch (i2c->state) {
-
- case STATE_IDLE:
- dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
- break;
-
- case STATE_STOP:
- dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
- nuc900_i2c_disable_irq(i2c);
- break;
-
- case STATE_START:
- /* last thing we did was send a start condition on the
- * bus, or started a new i2c message
- */
-
- if (iicstat & SLAVE_ACK &&
- !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
- /* ack was not received... */
-
- dev_dbg(i2c->dev, "ack was not received\n");
- nuc900_i2c_stop(i2c, -ENXIO);
- break;
- }
-
- if (i2c->msg->flags & I2C_M_RD)
- i2c->state = STATE_READ;
- else
- i2c->state = STATE_WRITE;
-
- /* terminate the transfer if there is nothing to do
- * as this is used by the i2c probe to find devices.
- */
-
- if (is_lastmsg(i2c) && i2c->msg->len == 0) {
- nuc900_i2c_stop(i2c, 0);
- break;
- }
-
- if (i2c->state == STATE_READ)
- goto prepare_read;
-
- /* fall through to the write state, as we will need to
- * send a byte as well
- */
-
- case STATE_WRITE:
- /* we are writing data to the device... check for the
- * end of the message, and if so, work out what to do
- */
-
- if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
- if (iicstat & SLAVE_ACK) {
- dev_dbg(i2c->dev, "WRITE: No Ack\n");
-
- nuc900_i2c_stop(i2c, -ECONNREFUSED);
- break;
- }
- }
-
-retry_write:
-
- if (!is_msgend(i2c)) {
- byte = i2c->msg->buf[i2c->msg_ptr++];
- writeb(byte, i2c->regs + TXR);
- writel(I2C_CMD_WRITE, i2c->regs + CMDR);
-
- } else if (!is_lastmsg(i2c)) {
- /* we need to go to the next i2c message */
-
- dev_dbg(i2c->dev, "WRITE: Next Message\n");
-
- i2c->msg_ptr = 0;
- i2c->msg_idx++;
- i2c->msg++;
-
- /* check to see if we need to do another message */
- if (i2c->msg->flags & I2C_M_NOSTART) {
-
- if (i2c->msg->flags & I2C_M_RD) {
- /* cannot do this, the controller
- * forces us to send a new START
- * when we change direction
- */
-
- nuc900_i2c_stop(i2c, -EINVAL);
- }
-
- goto retry_write;
- } else {
- /* send the new start */
- nuc900_i2c_message_start(i2c, i2c->msg);
- i2c->state = STATE_START;
- }
-
- } else {
- /* send stop */
-
- nuc900_i2c_stop(i2c, 0);
- }
- break;
-
- case STATE_READ:
- /* we have a byte of data in the data register, do
- * something with it, and then work out whether we are
- * going to do any more read/write
- */
-
- byte = readb(i2c->regs + RXR);
- i2c->msg->buf[i2c->msg_ptr++] = byte;
-
-prepare_read:
- if (is_msglast(i2c)) {
- /* last byte of buffer */
-
- if (is_lastmsg(i2c))
- writel(I2C_CMD_READ | I2C_CMD_NACK,
- i2c->regs + CMDR);
-
- } else if (is_msgend(i2c)) {
- /* ok, we've read the entire buffer, see if there
- * is anything else we need to do
- */
-
- if (is_lastmsg(i2c)) {
- /* last message, send stop and complete */
- dev_dbg(i2c->dev, "READ: Send Stop\n");
-
- nuc900_i2c_stop(i2c, 0);
- } else {
- /* go to the next transfer */
- dev_dbg(i2c->dev, "READ: Next Transfer\n");
-
- i2c->msg_ptr = 0;
- i2c->msg_idx++;
- i2c->msg++;
-
- writel(I2C_CMD_READ, i2c->regs + CMDR);
- }
-
- } else {
- writel(I2C_CMD_READ, i2c->regs + CMDR);
- }
-
- break;
- }
-}
-
-/* nuc900_i2c_irq
- *
- * top level IRQ servicing routine
-*/
-
-static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id)
-{
- struct nuc900_i2c *i2c = dev_id;
- unsigned long status;
-
- status = readl(i2c->regs + CSR);
- writel(status | IRQFLAG, i2c->regs + CSR);
-
- if (status & ARBIT_LOST) {
- /* deal with arbitration loss */
- dev_err(i2c->dev, "deal with arbitration loss\n");
- goto out;
- }
-
- if (i2c->state == STATE_IDLE) {
- dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
- goto out;
- }
-
- /* pretty much this leaves us with the fact that we've
- * transmitted or received whatever byte we last sent
- */
-
- i2c_nuc900_irq_nextbyte(i2c, status);
-
- out:
- return IRQ_HANDLED;
-}
-
-
-/* nuc900_i2c_set_master
- *
- * get the i2c bus for a master transaction
-*/
-
-static int nuc900_i2c_set_master(struct nuc900_i2c *i2c)
-{
- int timeout = 400;
-
- while (timeout-- > 0) {
- if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) &&
- ((readl(i2c->regs + CSR) & I2CBUSY) == 0)) {
- return 0;
- }
-
- msleep(1);
- }
-
- return -ETIMEDOUT;
-}
-
-/* nuc900_i2c_doxfer
- *
- * this starts an i2c transfer
-*/
-
-static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c,
- struct i2c_msg *msgs, int num)
-{
- unsigned long iicstat, timeout;
- int spins = 20;
- int ret;
-
- ret = nuc900_i2c_set_master(i2c);
- if (ret != 0) {
- dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
- ret = -EAGAIN;
- goto out;
- }
-
- spin_lock_irq(&i2c->lock);
-
- i2c->msg = msgs;
- i2c->msg_num = num;
- i2c->msg_ptr = 0;
- i2c->msg_idx = 0;
- i2c->state = STATE_START;
-
- nuc900_i2c_message_start(i2c, msgs);
- spin_unlock_irq(&i2c->lock);
-
- timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
-
- ret = i2c->msg_idx;
-
- /* having these next two as dev_err() makes life very
- * noisy when doing an i2cdetect
- */
-
- if (timeout == 0)
- dev_dbg(i2c->dev, "timeout\n");
- else if (ret != num)
- dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
-
- /* ensure the stop has been through the bus */
-
- dev_dbg(i2c->dev, "waiting for bus idle\n");
-
- /* first, try busy waiting briefly */
- do {
- iicstat = readl(i2c->regs + CSR);
- } while ((iicstat & I2CBUSY) && --spins);
-
- /* if that timed out sleep */
- if (!spins) {
- msleep(1);
- iicstat = readl(i2c->regs + CSR);
- }
-
- if (iicstat & I2CBUSY)
- dev_warn(i2c->dev, "timeout waiting for bus idle\n");
-
- out:
- return ret;
-}
-
-/* nuc900_i2c_xfer
- *
- * first port of call from the i2c bus code when an message needs
- * transferring across the i2c bus.
-*/
-
-static int nuc900_i2c_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data;
- int retry;
- int ret;
-
- nuc900_i2c_enable_irq(i2c);
-
- for (retry = 0; retry < adap->retries; retry++) {
-
- ret = nuc900_i2c_doxfer(i2c, msgs, num);
-
- if (ret != -EAGAIN)
- return ret;
-
- dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry);
-
- udelay(100);
- }
-
- return -EREMOTEIO;
-}
-
-/* declare our i2c functionality */
-static u32 nuc900_i2c_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
- I2C_FUNC_PROTOCOL_MANGLING;
-}
-
-/* i2c bus registration info */
-
-static const struct i2c_algorithm nuc900_i2c_algorithm = {
- .master_xfer = nuc900_i2c_xfer,
- .functionality = nuc900_i2c_func,
-};
-
-/* nuc900_i2c_probe
- *
- * called by the bus driver when a suitable device is found
-*/
-
-static int nuc900_i2c_probe(struct platform_device *pdev)
-{
- struct nuc900_i2c *i2c;
- struct nuc900_platform_i2c *pdata;
- struct resource *res;
- int ret;
-
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data\n");
- return -EINVAL;
- }
-
- i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL);
- if (!i2c) {
- dev_err(&pdev->dev, "no memory for state\n");
- return -ENOMEM;
- }
-
- strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name));
- i2c->adap.owner = THIS_MODULE;
- i2c->adap.algo = &nuc900_i2c_algorithm;
- i2c->adap.retries = 2;
- i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
-
- spin_lock_init(&i2c->lock);
- init_waitqueue_head(&i2c->wait);
-
- /* find the clock and enable it */
-
- i2c->dev = &pdev->dev;
- i2c->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(i2c->clk)) {
- dev_err(&pdev->dev, "cannot get clock\n");
- ret = -ENOENT;
- goto err_noclk;
- }
-
- dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
-
- clk_enable(i2c->clk);
-
- /* map the registers */
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "cannot find IO resource\n");
- ret = -ENOENT;
- goto err_clk;
- }
-
- i2c->ioarea = request_mem_region(res->start, resource_size(res),
- pdev->name);
-
- if (i2c->ioarea == NULL) {
- dev_err(&pdev->dev, "cannot request IO\n");
- ret = -ENXIO;
- goto err_clk;
- }
-
- i2c->regs = ioremap(res->start, resource_size(res));
-
- if (i2c->regs == NULL) {
- dev_err(&pdev->dev, "cannot map IO\n");
- ret = -ENXIO;
- goto err_ioarea;
- }
-
- dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
- i2c->regs, i2c->ioarea, res);
-
- /* setup info block for the i2c core */
-
- i2c->adap.algo_data = i2c;
- i2c->adap.dev.parent = &pdev->dev;
-
- mfp_set_groupg(&pdev->dev, NULL);
-
- clk_get_rate(i2c->clk);
-
- ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1;
- writel(ret & 0xffff, i2c->regs + DIVIDER);
-
- /* find the IRQ for this unit (note, this relies on the init call to
- * ensure no current IRQs pending
- */
-
- i2c->irq = ret = platform_get_irq(pdev, 0);
- if (ret <= 0) {
- dev_err(&pdev->dev, "cannot find IRQ\n");
- goto err_iomap;
- }
-
- ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED,
- dev_name(&pdev->dev), i2c);
-
- if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
- goto err_iomap;
- }
-
- /* Note, previous versions of the driver used i2c_add_adapter()
- * to add the bus at any number. We now pass the bus number via
- * the platform data, so if unset it will now default to always
- * being bus 0.
- */
-
- i2c->adap.nr = pdata->bus_num;
-
- ret = i2c_add_numbered_adapter(&i2c->adap);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to add bus to i2c core\n");
- goto err_irq;
- }
-
- platform_set_drvdata(pdev, i2c);
-
- dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n",
- dev_name(&i2c->adap.dev));
- return 0;
-
- err_irq:
- free_irq(i2c->irq, i2c);
-
- err_iomap:
- iounmap(i2c->regs);
-
- err_ioarea:
- release_resource(i2c->ioarea);
- kfree(i2c->ioarea);
-
- err_clk:
- clk_disable(i2c->clk);
- clk_put(i2c->clk);
-
- err_noclk:
- kfree(i2c);
- return ret;
-}
-
-/* nuc900_i2c_remove
- *
- * called when device is removed from the bus
-*/
-
-static int nuc900_i2c_remove(struct platform_device *pdev)
-{
- struct nuc900_i2c *i2c = platform_get_drvdata(pdev);
-
- i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq, i2c);
-
- clk_disable(i2c->clk);
- clk_put(i2c->clk);
-
- iounmap(i2c->regs);
-
- release_resource(i2c->ioarea);
- kfree(i2c->ioarea);
- kfree(i2c);
-
- return 0;
-}
-
-static struct platform_driver nuc900_i2c_driver = {
- .probe = nuc900_i2c_probe,
- .remove = nuc900_i2c_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "nuc900-i2c0",
- },
-};
-
-static int __init i2c_adap_nuc900_init(void)
-{
- return platform_driver_register(&nuc900_i2c_driver);
-}
-
-static void __exit i2c_adap_nuc900_exit(void)
-{
- platform_driver_unregister(&nuc900_i2c_driver);
-}
-subsys_initcall(i2c_adap_nuc900_init);
-module_exit(i2c_adap_nuc900_exit);
-
-MODULE_DESCRIPTION("NUC900 I2C Bus driver");
-MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-i2c0");
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 1f6369f14fb6..0e10cc6182f0 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -250,7 +250,7 @@ static struct i2c_adapter ocores_adapter = {
.algo = &ocores_algorithm,
};
-static struct of_device_id ocores_i2c_match[] = {
+static const struct of_device_id ocores_i2c_match[] = {
{
.compatible = "opencores,i2c-ocores",
.data = (void *)TYPE_OCORES,
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 85f8eac9ba18..b182793a4051 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1114,10 +1114,8 @@ omap_i2c_probe(struct platform_device *pdev)
}
dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL);
- if (!dev) {
- dev_err(&pdev->dev, "Menory allocation failed\n");
+ if (!dev)
return -ENOMEM;
- }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index bbe6dfbc5c05..be671f7a0e06 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1084,7 +1084,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
.functionality = i2c_pxa_functionality,
};
-static struct of_device_id i2c_pxa_dt_ids[] = {
+static const struct of_device_id i2c_pxa_dt_ids[] = {
{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX },
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 06d47aafbb79..899405923678 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -1,7 +1,9 @@
/*
- * drivers/i2c/busses/i2c-rcar.c
+ * Driver for the Renesas RCar I2C unit
*
- * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
+ *
+ * Copyright (C) 2012-14 Renesas Solutions Corp.
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This file is based on the drivers/i2c/busses/i2c-sh7760.c
@@ -12,16 +14,12 @@
*
* 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
+ * the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/clk.h>
#include <linux/delay.h>
@@ -36,7 +34,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
/* register offsets */
#define ICSCR 0x00 /* slave ctrl */
@@ -60,7 +57,7 @@
#define FSB (1 << 1) /* force stop bit */
#define ESG (1 << 0) /* en startbit gen */
-/* ICMSR */
+/* ICMSR (also for ICMIE) */
#define MNR (1 << 6) /* nack received */
#define MAL (1 << 5) /* arbitration lost */
#define MST (1 << 4) /* sent a stop */
@@ -69,32 +66,18 @@
#define MDR (1 << 1)
#define MAT (1 << 0) /* slave addr xfer done */
-/* ICMIE */
-#define MNRE (1 << 6) /* nack irq en */
-#define MALE (1 << 5) /* arblos irq en */
-#define MSTE (1 << 4) /* stop irq en */
-#define MDEE (1 << 3)
-#define MDTE (1 << 2)
-#define MDRE (1 << 1)
-#define MATE (1 << 0) /* address sent irq en */
+#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
+#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
+#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
-enum {
- RCAR_BUS_PHASE_ADDR,
- RCAR_BUS_PHASE_DATA,
- RCAR_BUS_PHASE_STOP,
-};
+#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
+#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
+#define RCAR_IRQ_STOP (MST)
-enum {
- RCAR_IRQ_CLOSE,
- RCAR_IRQ_OPEN_FOR_SEND,
- RCAR_IRQ_OPEN_FOR_RECV,
- RCAR_IRQ_OPEN_FOR_STOP,
-};
+#define RCAR_IRQ_ACK_SEND (~(MAT | MDE))
+#define RCAR_IRQ_ACK_RECV (~(MAT | MDR))
-/*
- * flags
- */
#define ID_LAST_MSG (1 << 0)
#define ID_IOERROR (1 << 1)
#define ID_DONE (1 << 2)
@@ -112,14 +95,12 @@ struct rcar_i2c_priv {
struct i2c_msg *msg;
struct clk *clk;
- spinlock_t lock;
wait_queue_head_t wait;
int pos;
- int irq;
u32 icccr;
u32 flags;
- enum rcar_i2c_type devtype;
+ enum rcar_i2c_type devtype;
};
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -130,9 +111,7 @@ struct rcar_i2c_priv {
#define LOOP_TIMEOUT 1024
-/*
- * basic functions
- */
+
static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val)
{
writel(val, priv->io + reg);
@@ -161,36 +140,6 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
rcar_i2c_write(priv, ICMAR, 0);
}
-static void rcar_i2c_irq_mask(struct rcar_i2c_priv *priv, int open)
-{
- u32 val = MNRE | MALE | MSTE | MATE; /* default */
-
- switch (open) {
- case RCAR_IRQ_OPEN_FOR_SEND:
- val |= MDEE; /* default + send */
- break;
- case RCAR_IRQ_OPEN_FOR_RECV:
- val |= MDRE; /* default + read */
- break;
- case RCAR_IRQ_OPEN_FOR_STOP:
- val = MSTE; /* stop irq only */
- break;
- case RCAR_IRQ_CLOSE:
- default:
- val = 0; /* all close */
- break;
- }
- rcar_i2c_write(priv, ICMIER, val);
-}
-
-static void rcar_i2c_set_addr(struct rcar_i2c_priv *priv, u32 recv)
-{
- rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | recv);
-}
-
-/*
- * bus control functions
- */
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
{
int i;
@@ -205,24 +154,6 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
return -EBUSY;
}
-static void rcar_i2c_bus_phase(struct rcar_i2c_priv *priv, int phase)
-{
- switch (phase) {
- case RCAR_BUS_PHASE_ADDR:
- rcar_i2c_write(priv, ICMCR, MDBS | MIE | ESG);
- break;
- case RCAR_BUS_PHASE_DATA:
- rcar_i2c_write(priv, ICMCR, MDBS | MIE);
- break;
- case RCAR_BUS_PHASE_STOP:
- rcar_i2c_write(priv, ICMCR, MDBS | MIE | FSB);
- break;
- }
-}
-
-/*
- * clock function
- */
static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv,
u32 bus_speed,
struct device *dev)
@@ -312,60 +243,18 @@ scgd_find:
return 0;
}
-static void rcar_i2c_clock_start(struct rcar_i2c_priv *priv)
-{
- rcar_i2c_write(priv, ICCCR, priv->icccr);
-}
-
-/*
- * status functions
- */
-static u32 rcar_i2c_status_get(struct rcar_i2c_priv *priv)
-{
- return rcar_i2c_read(priv, ICMSR);
-}
-
-#define rcar_i2c_status_clear(priv) rcar_i2c_status_bit_clear(priv, 0xffffffff)
-static void rcar_i2c_status_bit_clear(struct rcar_i2c_priv *priv, u32 bit)
-{
- rcar_i2c_write(priv, ICMSR, ~bit);
-}
-
-/*
- * recv/send functions
- */
-static int rcar_i2c_recv(struct rcar_i2c_priv *priv)
-{
- rcar_i2c_set_addr(priv, 1);
- rcar_i2c_status_clear(priv);
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
- rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_RECV);
-
- return 0;
-}
-
-static int rcar_i2c_send(struct rcar_i2c_priv *priv)
+static int rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
{
- int ret;
+ int read = !!rcar_i2c_is_recv(priv);
- /*
- * It should check bus status when send case
- */
- ret = rcar_i2c_bus_barrier(priv);
- if (ret < 0)
- return ret;
-
- rcar_i2c_set_addr(priv, 0);
- rcar_i2c_status_clear(priv);
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR);
- rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_SEND);
+ rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
+ rcar_i2c_write(priv, ICMSR, 0);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+ rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
return 0;
}
-#define rcar_i2c_send_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDE))
-#define rcar_i2c_recv_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDR))
-
/*
* interrupt functions
*/
@@ -386,7 +275,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
* goto data phase.
*/
if (msr & MAT)
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
if (priv->pos < msg->len) {
/*
@@ -414,7 +303,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
* prepare stop condition here.
* ID_DONE will be set on STOP irq.
*/
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
else
/*
* If current msg is _NOT_ last msg,
@@ -425,7 +314,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
return ID_DONE;
}
- rcar_i2c_send_restart(priv);
+ rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND);
return 0;
}
@@ -462,11 +351,11 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
* otherwise, go to DATA phase.
*/
if (priv->pos + 1 >= msg->len)
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
else
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
- rcar_i2c_recv_restart(priv);
+ rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV);
return 0;
}
@@ -474,53 +363,31 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
{
struct rcar_i2c_priv *priv = ptr;
- struct device *dev = rcar_i2c_priv_to_dev(priv);
u32 msr;
- /*-------------- spin lock -----------------*/
- spin_lock(&priv->lock);
-
- msr = rcar_i2c_status_get(priv);
+ msr = rcar_i2c_read(priv, ICMSR);
- /*
- * Arbitration lost
- */
+ /* Arbitration lost */
if (msr & MAL) {
- /*
- * CAUTION
- *
- * When arbitration lost, device become _slave_ mode.
- */
- dev_dbg(dev, "Arbitration Lost\n");
rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
goto out;
}
- /*
- * Stop
- */
+ /* Stop */
if (msr & MST) {
- dev_dbg(dev, "Stop\n");
rcar_i2c_flags_set(priv, ID_DONE);
goto out;
}
- /*
- * Nack
- */
+ /* Nack */
if (msr & MNR) {
- dev_dbg(dev, "Nack\n");
-
/* go to stop phase */
- rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
- rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP);
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+ rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP);
rcar_i2c_flags_set(priv, ID_NACK);
goto out;
}
- /*
- * recv/send
- */
if (rcar_i2c_is_recv(priv))
rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
else
@@ -528,14 +395,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
out:
if (rcar_i2c_flags_has(priv, ID_DONE)) {
- rcar_i2c_irq_mask(priv, RCAR_IRQ_CLOSE);
- rcar_i2c_status_clear(priv);
+ rcar_i2c_write(priv, ICMIER, 0);
+ rcar_i2c_write(priv, ICMSR, 0);
wake_up(&priv->wait);
}
- spin_unlock(&priv->lock);
- /*-------------- spin unlock -----------------*/
-
return IRQ_HANDLED;
}
@@ -545,21 +409,18 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
{
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv);
- unsigned long flags;
int i, ret, timeout;
pm_runtime_get_sync(dev);
- /*-------------- spin lock -----------------*/
- spin_lock_irqsave(&priv->lock, flags);
-
rcar_i2c_init(priv);
- rcar_i2c_clock_start(priv);
+ /* start clock */
+ rcar_i2c_write(priv, ICCCR, priv->icccr);
- spin_unlock_irqrestore(&priv->lock, flags);
- /*-------------- spin unlock -----------------*/
+ ret = rcar_i2c_bus_barrier(priv);
+ if (ret < 0)
+ goto out;
- ret = -EINVAL;
for (i = 0; i < num; i++) {
/* This HW can't send STOP after address phase */
if (msgs[i].len == 0) {
@@ -567,9 +428,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
break;
}
- /*-------------- spin lock -----------------*/
- spin_lock_irqsave(&priv->lock, flags);
-
/* init each data */
priv->msg = &msgs[i];
priv->pos = 0;
@@ -577,21 +435,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
if (priv->msg == &msgs[num - 1])
rcar_i2c_flags_set(priv, ID_LAST_MSG);
- /* start send/recv */
- if (rcar_i2c_is_recv(priv))
- ret = rcar_i2c_recv(priv);
- else
- ret = rcar_i2c_send(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- /*-------------- spin unlock -----------------*/
+ ret = rcar_i2c_prepare_msg(priv);
if (ret < 0)
break;
- /*
- * wait result
- */
timeout = wait_event_timeout(priv->wait,
rcar_i2c_flags_has(priv, ID_DONE),
5 * HZ);
@@ -600,9 +448,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
break;
}
- /*
- * error handling
- */
if (rcar_i2c_flags_has(priv, ID_NACK)) {
ret = -ENXIO;
break;
@@ -620,7 +465,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
ret = i + 1; /* The number of transfer */
}
-
+out:
pm_runtime_put(dev);
if (ret < 0 && ret != -ENXIO)
@@ -646,6 +491,9 @@ static const struct of_device_id rcar_i2c_dt_ids[] = {
{ .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
{ .compatible = "renesas,i2c-r8a7790", .data = (void *)I2C_RCAR_GEN2 },
{ .compatible = "renesas,i2c-r8a7791", .data = (void *)I2C_RCAR_GEN2 },
+ { .compatible = "renesas,i2c-r8a7792", .data = (void *)I2C_RCAR_GEN2 },
+ { .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 },
+ { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
{},
};
MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
@@ -658,13 +506,11 @@ static int rcar_i2c_probe(struct platform_device *pdev)
struct resource *res;
struct device *dev = &pdev->dev;
u32 bus_speed;
- int ret;
+ int irq, ret;
priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL);
- if (!priv) {
- dev_err(dev, "no mem for private data\n");
+ if (!priv)
return -ENOMEM;
- }
priv->clk = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
@@ -692,9 +538,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
if (IS_ERR(priv->io))
return PTR_ERR(priv->io);
- priv->irq = platform_get_irq(pdev, 0);
+ irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait);
- spin_lock_init(&priv->lock);
adap = &priv->adap;
adap->nr = pdev->id;
@@ -706,10 +551,10 @@ static int rcar_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, priv);
strlcpy(adap->name, pdev->name, sizeof(adap->name));
- ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0,
+ ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0,
dev_name(dev), priv);
if (ret < 0) {
- dev_err(dev, "cannot get irq %d\n", priv->irq);
+ dev_err(dev, "cannot get irq %d\n", irq);
return ret;
}
@@ -759,6 +604,6 @@ static struct platform_driver rcar_i2c_driver = {
module_platform_driver(rcar_i2c_driver);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index 9e1f8bacfb39..af3b3d032a9f 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -404,7 +404,7 @@ static int riic_i2c_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id riic_i2c_dt_ids[] = {
+static const struct of_device_id riic_i2c_dt_ids[] = {
{ .compatible = "renesas,riic-rz" },
{ /* Sentinel */ },
};
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index bb3a9964f7e0..e828a1dba0e5 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1114,16 +1114,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
}
i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL);
- if (!i2c) {
- dev_err(&pdev->dev, "no memory for state\n");
+ if (!i2c)
return -ENOMEM;
- }
i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!i2c->pdata) {
- dev_err(&pdev->dev, "no memory for platform data\n");
+ if (!i2c->pdata)
return -ENOMEM;
- }
i2c->quirks = s3c24xx_get_device_quirks(pdev);
if (pdata)
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 1d79585ba4b3..8b5e79cb4468 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -32,6 +32,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <linux/i2c/i2c-sh_mobile.h>
/* Transmit operation: */
@@ -139,6 +140,10 @@ struct sh_mobile_i2c_data {
bool send_stop;
};
+struct sh_mobile_dt_config {
+ int clks_per_count;
+};
+
#define IIC_FLAG_HAS_ICIC67 (1 << 0)
#define STANDARD_MODE 100000
@@ -194,7 +199,7 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
}
-static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
+static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf)
{
/*
* Conditional expression:
@@ -206,10 +211,10 @@ static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int off
* account the fall time of SCL signal (tf). Default tf value
* should be 0.3 us, for safety.
*/
- return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset;
+ return (((count_khz * (tLOW + tf)) + 5000) / 10000);
}
-static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset)
+static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf)
{
/*
* Conditional expression:
@@ -225,52 +230,58 @@ static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int of
* to take into account the fall time of SDA signal (tf) at START
* condition, in order to meet both tHIGH and tHD;STA specs.
*/
- return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
+ return (((count_khz * (tHIGH + tf)) + 5000) / 10000);
}
-static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
+static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
{
unsigned long i2c_clk_khz;
u32 tHIGH, tLOW, tf;
- int offset;
+ uint16_t max_val;
/* Get clock rate after clock is enabled */
clk_prepare_enable(pd->clk);
i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
+ clk_disable_unprepare(pd->clk);
i2c_clk_khz /= pd->clks_per_count;
if (pd->bus_speed == STANDARD_MODE) {
tLOW = 47; /* tLOW = 4.7 us */
tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */
tf = 3; /* tf = 0.3 us */
- offset = 0; /* No offset */
} else if (pd->bus_speed == FAST_MODE) {
tLOW = 13; /* tLOW = 1.3 us */
tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */
tf = 3; /* tf = 0.3 us */
- offset = 0; /* No offset */
} else {
dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
pd->bus_speed);
- goto out;
+ return -EINVAL;
+ }
+
+ pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf);
+ pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf);
+
+ max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff;
+ if (pd->iccl > max_val || pd->icch > max_val) {
+ dev_err(pd->dev, "timing values out of range: L/H=0x%x/0x%x\n",
+ pd->iccl, pd->icch);
+ return -EINVAL;
}
- pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset);
/* one more bit of ICCL in ICIC */
- if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+ if (pd->iccl & 0x100)
pd->icic |= ICIC_ICCLB8;
else
pd->icic &= ~ICIC_ICCLB8;
- pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset);
/* one more bit of ICCH in ICIC */
- if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
+ if (pd->icch & 0x100)
pd->icic |= ICIC_ICCHB8;
else
pd->icic &= ~ICIC_ICCHB8;
-out:
- clk_disable_unprepare(pd->clk);
+ return 0;
}
static void activate_ch(struct sh_mobile_i2c_data *pd)
@@ -316,7 +327,7 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
switch (op) {
case OP_START: /* issue start and trigger DTE interrupt */
- iic_wr(pd, ICCR, 0x94);
+ iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY);
break;
case OP_TX_FIRST: /* disable DTE interrupt and write data */
iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
@@ -327,10 +338,11 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
break;
case OP_TX_STOP: /* write data and issue a stop afterwards */
iic_wr(pd, ICDR, data);
- iic_wr(pd, ICCR, pd->send_stop ? 0x90 : 0x94);
+ iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS
+ : ICCR_ICE | ICCR_TRS | ICCR_BBSY);
break;
case OP_TX_TO_RX: /* select read mode */
- iic_wr(pd, ICCR, 0x81);
+ iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP);
break;
case OP_RX: /* just read data */
ret = iic_rd(pd, ICDR);
@@ -338,13 +350,13 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
case OP_RX_STOP: /* enable DTE interrupt, issue stop */
iic_wr(pd, ICIC,
ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
- iic_wr(pd, ICCR, 0xc0);
+ iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
break;
case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
iic_wr(pd, ICIC,
ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
ret = iic_rd(pd, ICDR);
- iic_wr(pd, ICCR, 0xc0);
+ iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
break;
}
@@ -479,7 +491,7 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
{
if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
dev_err(pd->dev, "Unsupported zero length i2c read\n");
- return -EIO;
+ return -EOPNOTSUPP;
}
if (do_init) {
@@ -514,17 +526,12 @@ static int poll_dte(struct sh_mobile_i2c_data *pd)
break;
if (val & ICSR_TACK)
- return -EIO;
+ return -ENXIO;
udelay(10);
}
- if (!i) {
- dev_warn(pd->dev, "Timeout polling for DTE!\n");
- return -ETIMEDOUT;
- }
-
- return 0;
+ return i ? 0 : -ETIMEDOUT;
}
static int poll_busy(struct sh_mobile_i2c_data *pd)
@@ -542,20 +549,18 @@ static int poll_busy(struct sh_mobile_i2c_data *pd)
*/
if (!(val & ICSR_BUSY)) {
/* handle missing acknowledge and arbitration lost */
- if ((val | pd->sr) & (ICSR_TACK | ICSR_AL))
- return -EIO;
+ val |= pd->sr;
+ if (val & ICSR_TACK)
+ return -ENXIO;
+ if (val & ICSR_AL)
+ return -EAGAIN;
break;
}
udelay(10);
}
- if (!i) {
- dev_err(pd->dev, "Polling timed out\n");
- return -ETIMEDOUT;
- }
-
- return 0;
+ return i ? 0 : -ETIMEDOUT;
}
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
@@ -617,42 +622,44 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = {
.master_xfer = sh_mobile_i2c_xfer,
};
-static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
+static const struct sh_mobile_dt_config default_dt_config = {
+ .clks_per_count = 1,
+};
+
+static const struct sh_mobile_dt_config rcar_gen2_dt_config = {
+ .clks_per_count = 2,
+};
+
+static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
+ { .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
+ { .compatible = "renesas,iic-r8a7790", .data = &rcar_gen2_dt_config },
+ { .compatible = "renesas,iic-r8a7791", .data = &rcar_gen2_dt_config },
+ { .compatible = "renesas,iic-r8a7792", .data = &rcar_gen2_dt_config },
+ { .compatible = "renesas,iic-r8a7793", .data = &rcar_gen2_dt_config },
+ { .compatible = "renesas,iic-r8a7794", .data = &rcar_gen2_dt_config },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
+
+static int sh_mobile_i2c_hook_irqs(struct platform_device *dev)
{
struct resource *res;
- int ret = -ENXIO;
- int n, k = 0;
+ resource_size_t n;
+ int k = 0, ret;
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
- for (n = res->start; hook && n <= res->end; n++) {
- if (request_irq(n, sh_mobile_i2c_isr, 0,
- dev_name(&dev->dev), dev)) {
- for (n--; n >= res->start; n--)
- free_irq(n, dev);
-
- goto rollback;
+ for (n = res->start; n <= res->end; n++) {
+ ret = devm_request_irq(&dev->dev, n, sh_mobile_i2c_isr,
+ 0, dev_name(&dev->dev), dev);
+ if (ret) {
+ dev_err(&dev->dev, "cannot request IRQ %pa\n", &n);
+ return ret;
}
}
k++;
}
- if (hook)
- return k > 0 ? 0 : -ENOENT;
-
- ret = 0;
-
- rollback:
- k--;
-
- while (k >= 0) {
- res = platform_get_resource(dev, IORESOURCE_IRQ, k);
- for (n = res->start; n <= res->end; n++)
- free_irq(n, dev);
-
- k--;
- }
-
- return ret;
+ return k > 0 ? 0 : -ENOENT;
}
static int sh_mobile_i2c_probe(struct platform_device *dev)
@@ -661,62 +668,64 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
struct sh_mobile_i2c_data *pd;
struct i2c_adapter *adap;
struct resource *res;
- int size;
int ret;
+ u32 bus_speed;
- pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
- if (pd == NULL) {
- dev_err(&dev->dev, "cannot allocate private data\n");
+ pd = devm_kzalloc(&dev->dev, sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
+ if (!pd)
return -ENOMEM;
- }
- pd->clk = clk_get(&dev->dev, NULL);
+ pd->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(pd->clk)) {
dev_err(&dev->dev, "cannot get clock\n");
- ret = PTR_ERR(pd->clk);
- goto err;
+ return PTR_ERR(pd->clk);
}
- ret = sh_mobile_i2c_hook_irqs(dev, 1);
- if (ret) {
- dev_err(&dev->dev, "cannot request IRQ\n");
- goto err_clk;
- }
+ ret = sh_mobile_i2c_hook_irqs(dev);
+ if (ret)
+ return ret;
pd->dev = &dev->dev;
platform_set_drvdata(dev, pd);
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&dev->dev, "cannot find IO resource\n");
- ret = -ENOENT;
- goto err_irq;
- }
-
- size = resource_size(res);
- pd->reg = ioremap(res->start, size);
- if (pd->reg == NULL) {
- dev_err(&dev->dev, "cannot map IO\n");
- ret = -ENXIO;
- goto err_irq;
- }
+ pd->reg = devm_ioremap_resource(&dev->dev, res);
+ if (IS_ERR(pd->reg))
+ return PTR_ERR(pd->reg);
/* Use platform data bus speed or STANDARD_MODE */
- pd->bus_speed = STANDARD_MODE;
- if (pdata && pdata->bus_speed)
- pd->bus_speed = pdata->bus_speed;
+ ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed);
+ pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
+
pd->clks_per_count = 1;
- if (pdata && pdata->clks_per_count)
- pd->clks_per_count = pdata->clks_per_count;
+
+ if (dev->dev.of_node) {
+ const struct of_device_id *match;
+
+ match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev);
+ if (match) {
+ const struct sh_mobile_dt_config *config;
+
+ config = match->data;
+ pd->clks_per_count = config->clks_per_count;
+ }
+ } else {
+ if (pdata && pdata->bus_speed)
+ pd->bus_speed = pdata->bus_speed;
+ if (pdata && pdata->clks_per_count)
+ pd->clks_per_count = pdata->clks_per_count;
+ }
/* The IIC blocks on SH-Mobile ARM processors
* come with two new bits in ICIC.
*/
- if (size > 0x17)
+ if (resource_size(res) > 0x17)
pd->flags |= IIC_FLAG_HAS_ICIC67;
- sh_mobile_i2c_init(pd);
+ ret = sh_mobile_i2c_init(pd);
+ if (ret)
+ return ret;
/* Enable Runtime PM for this device.
*
@@ -750,24 +759,14 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(&dev->dev, "cannot add numbered adapter\n");
- goto err_all;
+ return ret;
}
dev_info(&dev->dev,
- "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
+ "I2C adapter %d with bus speed %lu Hz (L/H=0x%x/0x%x)\n",
adap->nr, pd->bus_speed, pd->iccl, pd->icch);
return 0;
-
- err_all:
- iounmap(pd->reg);
- err_irq:
- sh_mobile_i2c_hook_irqs(dev, 0);
- err_clk:
- clk_put(pd->clk);
- err:
- kfree(pd);
- return ret;
}
static int sh_mobile_i2c_remove(struct platform_device *dev)
@@ -775,11 +774,7 @@ static int sh_mobile_i2c_remove(struct platform_device *dev)
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
i2c_del_adapter(&pd->adap);
- iounmap(pd->reg);
- sh_mobile_i2c_hook_irqs(dev, 0);
- clk_put(pd->clk);
pm_runtime_disable(&dev->dev);
- kfree(pd);
return 0;
}
@@ -800,12 +795,6 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
.runtime_resume = sh_mobile_i2c_runtime_nop,
};
-static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
- { .compatible = "renesas,rmobile-iic", },
- {},
-};
-MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
-
static struct platform_driver sh_mobile_i2c_driver = {
.driver = {
.name = "i2c-sh_mobile",
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c
index 294c80f21d65..964e5c6f84ab 100644
--- a/drivers/i2c/busses/i2c-simtec.c
+++ b/drivers/i2c/busses/i2c-simtec.c
@@ -77,10 +77,8 @@ static int simtec_i2c_probe(struct platform_device *dev)
int ret;
pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
- if (pd == NULL) {
- dev_err(&dev->dev, "cannot allocate private data\n");
+ if (pd == NULL)
return -ENOMEM;
- }
platform_set_drvdata(dev, pd);
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 8e3be7ed0586..a3216defc1d3 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -307,7 +307,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL);
if (!siic) {
- dev_err(&pdev->dev, "Can't allocate driver data\n");
err = -ENOMEM;
goto out;
}
diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c
index 872016196ef3..95b947670386 100644
--- a/drivers/i2c/busses/i2c-st.c
+++ b/drivers/i2c/busses/i2c-st.c
@@ -847,7 +847,7 @@ static int st_i2c_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id st_i2c_match[] = {
+static const struct of_device_id st_i2c_match[] = {
{ .compatible = "st,comms-ssc-i2c", },
{ .compatible = "st,comms-ssc4-i2c", },
{},
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 29b1fb778943..fefb1c19ec1d 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -868,10 +868,8 @@ static int stu300_probe(struct platform_device *pdev)
int ret = 0;
dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL);
- if (!dev) {
- dev_err(&pdev->dev, "could not allocate device struct\n");
+ if (!dev)
return -ENOMEM;
- }
bus_nr = pdev->id;
dev->clk = devm_clk_get(&pdev->dev, NULL);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 00f04cb5b4eb..f1bb2fc06791 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -732,10 +732,8 @@ static int tegra_i2c_probe(struct platform_device *pdev)
}
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
- if (!i2c_dev) {
- dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev");
+ if (!i2c_dev)
return -ENOMEM;
- }
i2c_dev->base = base;
i2c_dev->div_clk = div_clk;
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
index 2c8a3e4f9008..f80a38c2072c 100644
--- a/drivers/i2c/busses/i2c-wmt.c
+++ b/drivers/i2c/busses/i2c-wmt.c
@@ -379,10 +379,8 @@ static int wmt_i2c_probe(struct platform_device *pdev)
u32 clk_rate;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
- if (!i2c_dev) {
- dev_err(&pdev->dev, "device memory allocation failed\n");
+ if (!i2c_dev)
return -ENOMEM;
- }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
@@ -454,7 +452,7 @@ static int wmt_i2c_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id wmt_i2c_dt_ids[] = {
+static const struct of_device_id wmt_i2c_dt_ids[] = {
{ .compatible = "wm,wm8505-i2c" },
{ /* Sentinel */ },
};
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index cb66f9586f76..ff3f5747e43b 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -431,10 +431,8 @@ static struct scx200_acb_iface *scx200_create_iface(const char *text,
struct i2c_adapter *adapter;
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
- if (!iface) {
- pr_err("can't allocate memory\n");
+ if (!iface)
return NULL;
- }
adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface);
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 550bd36aa5d6..9bd4212782ab 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -36,12 +36,11 @@
*/
#include <linux/device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/i2c/pca954x.h>
#include <linux/module.h>
-#include <linux/of_gpio.h>
#include <linux/slab.h>
#define PCA954X_MAX_NCHANS 8
@@ -186,7 +185,7 @@ 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 *np = client->dev.of_node;
+ struct gpio_desc *gpio;
int num, force, class;
struct pca954x *data;
int ret;
@@ -200,21 +199,10 @@ static int pca954x_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
- if (IS_ENABLED(CONFIG_OF) && np) {
- enum of_gpio_flags flags;
- int gpio;
-
- /* Get the mux out of reset if a reset GPIO is specified. */
- gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags);
- if (gpio_is_valid(gpio)) {
- ret = devm_gpio_request_one(&client->dev, gpio,
- flags & OF_GPIO_ACTIVE_LOW ?
- GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
- "pca954x reset");
- if (ret < 0)
- return ret;
- }
- }
+ /* Get the mux out of reset if a reset GPIO is specified. */
+ gpio = devm_gpiod_get(&client->dev, "reset");
+ if (!IS_ERR(gpio))
+ gpiod_direction_output(gpio, 0);
/* Write the mux register at addr to verify
* that the mux is in fact present. This also
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index df56e4c74a7e..d260605e6d5f 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -178,13 +178,13 @@ config TEGRA_IOMMU_SMMU
config EXYNOS_IOMMU
bool "Exynos IOMMU Support"
- depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU
+ depends on ARCH_EXYNOS
select IOMMU_API
help
- Support for the IOMMU(System MMU) of Samsung Exynos application
- processor family. This enables H/W multimedia accellerators to see
- non-linear physical memory chunks as a linear memory in their
- address spaces
+ Support for the IOMMU (System MMU) of Samsung Exynos application
+ processor family. This enables H/W multimedia accelerators to see
+ non-linear physical memory chunks as linear memory in their
+ address space.
If unsure, say N here.
@@ -193,9 +193,9 @@ config EXYNOS_IOMMU_DEBUG
depends on EXYNOS_IOMMU
help
Select this to see the detailed log message that shows what
- happens in the IOMMU driver
+ happens in the IOMMU driver.
- Say N unless you need kernel log message for IOMMU debugging
+ Say N unless you need kernel log message for IOMMU debugging.
config SHMOBILE_IPMMU
bool
@@ -272,6 +272,18 @@ config SHMOBILE_IOMMU_L1SIZE
default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB
default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB
+config IPMMU_VMSA
+ bool "Renesas VMSA-compatible IPMMU"
+ depends on ARM_LPAE
+ depends on ARCH_SHMOBILE || COMPILE_TEST
+ select IOMMU_API
+ select ARM_DMA_USE_IOMMU
+ help
+ Support for the Renesas VMSA-compatible IPMMU Renesas found in the
+ R-Mobile APE6 and R-Car H2/M2 SoCs.
+
+ If unsure, say N.
+
config SPAPR_TCE_IOMMU
bool "sPAPR TCE IOMMU Support"
depends on PPC_POWERNV || PPC_PSERIES
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 5d58bf16e9e3..8893bad048e0 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
+obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 57068e8035b5..4aec6a29e316 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3499,8 +3499,6 @@ int __init amd_iommu_init_passthrough(void)
{
struct iommu_dev_data *dev_data;
struct pci_dev *dev = NULL;
- struct amd_iommu *iommu;
- u16 devid;
int ret;
ret = alloc_passthrough_domain();
@@ -3514,12 +3512,6 @@ int __init amd_iommu_init_passthrough(void)
dev_data = get_dev_data(&dev->dev);
dev_data->passthrough = true;
- devid = get_device_id(&dev->dev);
-
- iommu = amd_iommu_rlookup_table[devid];
- if (!iommu)
- continue;
-
attach_device(&dev->dev, pt_domain);
}
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 203b2e6a91cf..d4daa05efe60 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -45,6 +45,8 @@ struct pri_queue {
struct pasid_state {
struct list_head list; /* For global state-list */
atomic_t count; /* Reference count */
+ atomic_t mmu_notifier_count; /* Counting nested mmu_notifier
+ calls */
struct task_struct *task; /* Task bound to this PASID */
struct mm_struct *mm; /* mm_struct for the faults */
struct mmu_notifier mn; /* mmu_otifier handle */
@@ -56,6 +58,8 @@ struct pasid_state {
};
struct device_state {
+ struct list_head list;
+ u16 devid;
atomic_t count;
struct pci_dev *pdev;
struct pasid_state **states;
@@ -81,13 +85,9 @@ struct fault {
u16 flags;
};
-static struct device_state **state_table;
+static LIST_HEAD(state_list);
static spinlock_t state_lock;
-/* List and lock for all pasid_states */
-static LIST_HEAD(pasid_state_list);
-static DEFINE_SPINLOCK(ps_lock);
-
static struct workqueue_struct *iommu_wq;
/*
@@ -99,7 +99,6 @@ static u64 *empty_page_table;
static void free_pasid_states(struct device_state *dev_state);
static void unbind_pasid(struct device_state *dev_state, int pasid);
-static int task_exit(struct notifier_block *nb, unsigned long e, void *data);
static u16 device_id(struct pci_dev *pdev)
{
@@ -111,13 +110,25 @@ static u16 device_id(struct pci_dev *pdev)
return devid;
}
+static struct device_state *__get_device_state(u16 devid)
+{
+ struct device_state *dev_state;
+
+ list_for_each_entry(dev_state, &state_list, list) {
+ if (dev_state->devid == devid)
+ return dev_state;
+ }
+
+ return NULL;
+}
+
static struct device_state *get_device_state(u16 devid)
{
struct device_state *dev_state;
unsigned long flags;
spin_lock_irqsave(&state_lock, flags);
- dev_state = state_table[devid];
+ dev_state = __get_device_state(devid);
if (dev_state != NULL)
atomic_inc(&dev_state->count);
spin_unlock_irqrestore(&state_lock, flags);
@@ -158,29 +169,6 @@ static void put_device_state_wait(struct device_state *dev_state)
free_device_state(dev_state);
}
-static struct notifier_block profile_nb = {
- .notifier_call = task_exit,
-};
-
-static void link_pasid_state(struct pasid_state *pasid_state)
-{
- spin_lock(&ps_lock);
- list_add_tail(&pasid_state->list, &pasid_state_list);
- spin_unlock(&ps_lock);
-}
-
-static void __unlink_pasid_state(struct pasid_state *pasid_state)
-{
- list_del(&pasid_state->list);
-}
-
-static void unlink_pasid_state(struct pasid_state *pasid_state)
-{
- spin_lock(&ps_lock);
- __unlink_pasid_state(pasid_state);
- spin_unlock(&ps_lock);
-}
-
/* Must be called under dev_state->lock */
static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state,
int pasid, bool alloc)
@@ -337,7 +325,6 @@ static void unbind_pasid(struct device_state *dev_state, int pasid)
if (pasid_state == NULL)
return;
- unlink_pasid_state(pasid_state);
__unbind_pasid(pasid_state);
put_pasid_state_wait(pasid_state); /* Reference taken in this function */
}
@@ -379,7 +366,12 @@ static void free_pasid_states(struct device_state *dev_state)
continue;
put_pasid_state(pasid_state);
- unbind_pasid(dev_state, i);
+
+ /*
+ * This will call the mn_release function and
+ * unbind the PASID
+ */
+ mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
}
if (dev_state->pasid_levels == 2)
@@ -443,8 +435,11 @@ static void mn_invalidate_range_start(struct mmu_notifier *mn,
pasid_state = mn_to_state(mn);
dev_state = pasid_state->device_state;
- amd_iommu_domain_set_gcr3(dev_state->domain, pasid_state->pasid,
- __pa(empty_page_table));
+ if (atomic_add_return(1, &pasid_state->mmu_notifier_count) == 1) {
+ amd_iommu_domain_set_gcr3(dev_state->domain,
+ pasid_state->pasid,
+ __pa(empty_page_table));
+ }
}
static void mn_invalidate_range_end(struct mmu_notifier *mn,
@@ -457,11 +452,31 @@ static void mn_invalidate_range_end(struct mmu_notifier *mn,
pasid_state = mn_to_state(mn);
dev_state = pasid_state->device_state;
- amd_iommu_domain_set_gcr3(dev_state->domain, pasid_state->pasid,
- __pa(pasid_state->mm->pgd));
+ if (atomic_dec_and_test(&pasid_state->mmu_notifier_count)) {
+ amd_iommu_domain_set_gcr3(dev_state->domain,
+ pasid_state->pasid,
+ __pa(pasid_state->mm->pgd));
+ }
+}
+
+static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm)
+{
+ struct pasid_state *pasid_state;
+ struct device_state *dev_state;
+
+ might_sleep();
+
+ pasid_state = mn_to_state(mn);
+ dev_state = pasid_state->device_state;
+
+ if (pasid_state->device_state->inv_ctx_cb)
+ dev_state->inv_ctx_cb(dev_state->pdev, pasid_state->pasid);
+
+ unbind_pasid(dev_state, pasid_state->pasid);
}
static struct mmu_notifier_ops iommu_mn = {
+ .release = mn_release,
.clear_flush_young = mn_clear_flush_young,
.change_pte = mn_change_pte,
.invalidate_page = mn_invalidate_page,
@@ -606,53 +621,6 @@ static struct notifier_block ppr_nb = {
.notifier_call = ppr_notifier,
};
-static int task_exit(struct notifier_block *nb, unsigned long e, void *data)
-{
- struct pasid_state *pasid_state;
- struct task_struct *task;
-
- task = data;
-
- /*
- * Using this notifier is a hack - but there is no other choice
- * at the moment. What I really want is a sleeping notifier that
- * is called when an MM goes down. But such a notifier doesn't
- * exist yet. The notifier needs to sleep because it has to make
- * sure that the device does not use the PASID and the address
- * space anymore before it is destroyed. This includes waiting
- * for pending PRI requests to pass the workqueue. The
- * MMU-Notifiers would be a good fit, but they use RCU and so
- * they are not allowed to sleep. Lets see how we can solve this
- * in a more intelligent way in the future.
- */
-again:
- spin_lock(&ps_lock);
- list_for_each_entry(pasid_state, &pasid_state_list, list) {
- struct device_state *dev_state;
- int pasid;
-
- if (pasid_state->task != task)
- continue;
-
- /* Drop Lock and unbind */
- spin_unlock(&ps_lock);
-
- dev_state = pasid_state->device_state;
- pasid = pasid_state->pasid;
-
- if (pasid_state->device_state->inv_ctx_cb)
- dev_state->inv_ctx_cb(dev_state->pdev, pasid);
-
- unbind_pasid(dev_state, pasid);
-
- /* Task may be in the list multiple times */
- goto again;
- }
- spin_unlock(&ps_lock);
-
- return NOTIFY_OK;
-}
-
int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
struct task_struct *task)
{
@@ -682,6 +650,7 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
goto out;
atomic_set(&pasid_state->count, 1);
+ atomic_set(&pasid_state->mmu_notifier_count, 0);
init_waitqueue_head(&pasid_state->wq);
spin_lock_init(&pasid_state->lock);
@@ -705,8 +674,6 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid,
if (ret)
goto out_clear_state;
- link_pasid_state(pasid_state);
-
return 0;
out_clear_state:
@@ -727,6 +694,7 @@ EXPORT_SYMBOL(amd_iommu_bind_pasid);
void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid)
{
+ struct pasid_state *pasid_state;
struct device_state *dev_state;
u16 devid;
@@ -743,7 +711,17 @@ void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid)
if (pasid < 0 || pasid >= dev_state->max_pasids)
goto out;
- unbind_pasid(dev_state, pasid);
+ pasid_state = get_pasid_state(dev_state, pasid);
+ if (pasid_state == NULL)
+ goto out;
+ /*
+ * Drop reference taken here. We are safe because we still hold
+ * the reference taken in the amd_iommu_bind_pasid function.
+ */
+ put_pasid_state(pasid_state);
+
+ /* This will call the mn_release function and unbind the PASID */
+ mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm);
out:
put_device_state(dev_state);
@@ -773,7 +751,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
spin_lock_init(&dev_state->lock);
init_waitqueue_head(&dev_state->wq);
- dev_state->pdev = pdev;
+ dev_state->pdev = pdev;
+ dev_state->devid = devid;
tmp = pasids;
for (dev_state->pasid_levels = 0; (tmp - 1) & ~0x1ff; tmp >>= 9)
@@ -803,13 +782,13 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
spin_lock_irqsave(&state_lock, flags);
- if (state_table[devid] != NULL) {
+ if (__get_device_state(devid) != NULL) {
spin_unlock_irqrestore(&state_lock, flags);
ret = -EBUSY;
goto out_free_domain;
}
- state_table[devid] = dev_state;
+ list_add_tail(&dev_state->list, &state_list);
spin_unlock_irqrestore(&state_lock, flags);
@@ -841,13 +820,13 @@ void amd_iommu_free_device(struct pci_dev *pdev)
spin_lock_irqsave(&state_lock, flags);
- dev_state = state_table[devid];
+ dev_state = __get_device_state(devid);
if (dev_state == NULL) {
spin_unlock_irqrestore(&state_lock, flags);
return;
}
- state_table[devid] = NULL;
+ list_del(&dev_state->list);
spin_unlock_irqrestore(&state_lock, flags);
@@ -874,7 +853,7 @@ int amd_iommu_set_invalid_ppr_cb(struct pci_dev *pdev,
spin_lock_irqsave(&state_lock, flags);
ret = -EINVAL;
- dev_state = state_table[devid];
+ dev_state = __get_device_state(devid);
if (dev_state == NULL)
goto out_unlock;
@@ -905,7 +884,7 @@ int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev,
spin_lock_irqsave(&state_lock, flags);
ret = -EINVAL;
- dev_state = state_table[devid];
+ dev_state = __get_device_state(devid);
if (dev_state == NULL)
goto out_unlock;
@@ -922,7 +901,6 @@ EXPORT_SYMBOL(amd_iommu_set_invalidate_ctx_cb);
static int __init amd_iommu_v2_init(void)
{
- size_t state_table_size;
int ret;
pr_info("AMD IOMMUv2 driver by Joerg Roedel <joerg.roedel@amd.com>\n");
@@ -938,16 +916,10 @@ static int __init amd_iommu_v2_init(void)
spin_lock_init(&state_lock);
- state_table_size = MAX_DEVICES * sizeof(struct device_state *);
- state_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
- get_order(state_table_size));
- if (state_table == NULL)
- return -ENOMEM;
-
ret = -ENOMEM;
iommu_wq = create_workqueue("amd_iommu_v2");
if (iommu_wq == NULL)
- goto out_free;
+ goto out;
ret = -ENOMEM;
empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL);
@@ -955,29 +927,24 @@ static int __init amd_iommu_v2_init(void)
goto out_destroy_wq;
amd_iommu_register_ppr_notifier(&ppr_nb);
- profile_event_register(PROFILE_TASK_EXIT, &profile_nb);
return 0;
out_destroy_wq:
destroy_workqueue(iommu_wq);
-out_free:
- free_pages((unsigned long)state_table, get_order(state_table_size));
-
+out:
return ret;
}
static void __exit amd_iommu_v2_exit(void)
{
struct device_state *dev_state;
- size_t state_table_size;
int i;
if (!amd_iommu_v2_supported())
return;
- profile_event_unregister(PROFILE_TASK_EXIT, &profile_nb);
amd_iommu_unregister_ppr_notifier(&ppr_nb);
flush_workqueue(iommu_wq);
@@ -1000,9 +967,6 @@ static void __exit amd_iommu_v2_exit(void)
destroy_workqueue(iommu_wq);
- state_table_size = MAX_DEVICES * sizeof(struct device_state *);
- free_pages((unsigned long)state_table, get_order(state_table_size));
-
free_page((unsigned long)empty_page_table);
}
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 647c3c7fd742..1599354e974d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1167,7 +1167,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
for (i = 0; i < master->num_streamids; ++i) {
u32 idx, s2cr;
idx = master->smrs ? master->smrs[i].idx : master->streamids[i];
- s2cr = (S2CR_TYPE_TRANS << S2CR_TYPE_SHIFT) |
+ s2cr = S2CR_TYPE_TRANS |
(smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT);
writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
}
@@ -1804,7 +1804,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
* allocation (PTRS_PER_PGD).
*/
#ifdef CONFIG_64BIT
- smmu->s1_output_size = min(39UL, size);
+ smmu->s1_output_size = min((unsigned long)VA_BITS, size);
#else
smmu->s1_output_size = min(32UL, size);
#endif
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 685f9263cfee..99054d2c040d 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -29,7 +29,8 @@
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
-#include <mach/sysmmu.h>
+typedef u32 sysmmu_iova_t;
+typedef u32 sysmmu_pte_t;
/* We does not consider super section mapping (16MB) */
#define SECT_ORDER 20
@@ -44,28 +45,44 @@
#define LPAGE_MASK (~(LPAGE_SIZE - 1))
#define SPAGE_MASK (~(SPAGE_SIZE - 1))
-#define lv1ent_fault(sent) (((*(sent) & 3) == 0) || ((*(sent) & 3) == 3))
-#define lv1ent_page(sent) ((*(sent) & 3) == 1)
+#define lv1ent_fault(sent) ((*(sent) == ZERO_LV2LINK) || \
+ ((*(sent) & 3) == 0) || ((*(sent) & 3) == 3))
+#define lv1ent_zero(sent) (*(sent) == ZERO_LV2LINK)
+#define lv1ent_page_zero(sent) ((*(sent) & 3) == 1)
+#define lv1ent_page(sent) ((*(sent) != ZERO_LV2LINK) && \
+ ((*(sent) & 3) == 1))
#define lv1ent_section(sent) ((*(sent) & 3) == 2)
#define lv2ent_fault(pent) ((*(pent) & 3) == 0)
#define lv2ent_small(pent) ((*(pent) & 2) == 2)
#define lv2ent_large(pent) ((*(pent) & 3) == 1)
+static u32 sysmmu_page_offset(sysmmu_iova_t iova, u32 size)
+{
+ return iova & (size - 1);
+}
+
#define section_phys(sent) (*(sent) & SECT_MASK)
-#define section_offs(iova) ((iova) & 0xFFFFF)
+#define section_offs(iova) sysmmu_page_offset((iova), SECT_SIZE)
#define lpage_phys(pent) (*(pent) & LPAGE_MASK)
-#define lpage_offs(iova) ((iova) & 0xFFFF)
+#define lpage_offs(iova) sysmmu_page_offset((iova), LPAGE_SIZE)
#define spage_phys(pent) (*(pent) & SPAGE_MASK)
-#define spage_offs(iova) ((iova) & 0xFFF)
-
-#define lv1ent_offset(iova) ((iova) >> SECT_ORDER)
-#define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER)
+#define spage_offs(iova) sysmmu_page_offset((iova), SPAGE_SIZE)
#define NUM_LV1ENTRIES 4096
-#define NUM_LV2ENTRIES 256
+#define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE)
+
+static u32 lv1ent_offset(sysmmu_iova_t iova)
+{
+ return iova >> SECT_ORDER;
+}
+
+static u32 lv2ent_offset(sysmmu_iova_t iova)
+{
+ return (iova >> SPAGE_ORDER) & (NUM_LV2ENTRIES - 1);
+}
-#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(long))
+#define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t))
#define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
@@ -80,6 +97,13 @@
#define CTRL_BLOCK 0x7
#define CTRL_DISABLE 0x0
+#define CFG_LRU 0x1
+#define CFG_QOS(n) ((n & 0xF) << 7)
+#define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */
+#define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */
+#define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */
+#define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */
+
#define REG_MMU_CTRL 0x000
#define REG_MMU_CFG 0x004
#define REG_MMU_STATUS 0x008
@@ -96,19 +120,32 @@
#define REG_MMU_VERSION 0x034
+#define MMU_MAJ_VER(val) ((val) >> 7)
+#define MMU_MIN_VER(val) ((val) & 0x7F)
+#define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */
+
+#define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F))
+
#define REG_PB0_SADDR 0x04C
#define REG_PB0_EADDR 0x050
#define REG_PB1_SADDR 0x054
#define REG_PB1_EADDR 0x058
-static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
+#define has_sysmmu(dev) (dev->archdata.iommu != NULL)
+
+static struct kmem_cache *lv2table_kmem_cache;
+static sysmmu_pte_t *zero_lv2_table;
+#define ZERO_LV2LINK mk_lv1ent_page(virt_to_phys(zero_lv2_table))
+
+static sysmmu_pte_t *section_entry(sysmmu_pte_t *pgtable, sysmmu_iova_t iova)
{
return pgtable + lv1ent_offset(iova);
}
-static unsigned long *page_entry(unsigned long *sent, unsigned long iova)
+static sysmmu_pte_t *page_entry(sysmmu_pte_t *sent, sysmmu_iova_t iova)
{
- return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova);
+ return (sysmmu_pte_t *)phys_to_virt(
+ lv2table_base(sent)) + lv2ent_offset(iova);
}
enum exynos_sysmmu_inttype {
@@ -124,16 +161,6 @@ enum exynos_sysmmu_inttype {
SYSMMU_FAULTS_NUM
};
-/*
- * @itype: type of fault.
- * @pgtable_base: the physical address of page table base. This is 0 if @itype
- * is SYSMMU_BUSERROR.
- * @fault_addr: the device (virtual) address that the System MMU tried to
- * translated. This is 0 if @itype is SYSMMU_BUSERROR.
- */
-typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype,
- unsigned long pgtable_base, unsigned long fault_addr);
-
static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
REG_PAGE_FAULT_ADDR,
REG_AR_FAULT_ADDR,
@@ -157,27 +184,34 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
"UNKNOWN FAULT"
};
+/* attached to dev.archdata.iommu of the master device */
+struct exynos_iommu_owner {
+ struct list_head client; /* entry of exynos_iommu_domain.clients */
+ struct device *dev;
+ struct device *sysmmu;
+ struct iommu_domain *domain;
+ void *vmm_data; /* IO virtual memory manager's data */
+ spinlock_t lock; /* Lock to preserve consistency of System MMU */
+};
+
struct exynos_iommu_domain {
struct list_head clients; /* list of sysmmu_drvdata.node */
- unsigned long *pgtable; /* lv1 page table, 16KB */
+ sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */
short *lv2entcnt; /* free lv2 entry counter for each section */
spinlock_t lock; /* lock for this structure */
spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
};
struct sysmmu_drvdata {
- struct list_head node; /* entry of exynos_iommu_domain.clients */
struct device *sysmmu; /* System MMU's device descriptor */
- struct device *dev; /* Owner of system MMU */
- char *dbgname;
- int nsfrs;
- void __iomem **sfrbases;
- struct clk *clk[2];
+ struct device *master; /* Owner of system MMU */
+ void __iomem *sfrbase;
+ struct clk *clk;
+ struct clk *clk_master;
int activations;
- rwlock_t lock;
+ spinlock_t lock;
struct iommu_domain *domain;
- sysmmu_fault_handler_t fault_handler;
- unsigned long pgtable;
+ phys_addr_t pgtable;
};
static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -204,6 +238,11 @@ static void sysmmu_unblock(void __iomem *sfrbase)
__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
}
+static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
+{
+ return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
+}
+
static bool sysmmu_block(void __iomem *sfrbase)
{
int i = 120;
@@ -226,429 +265,428 @@ static void __sysmmu_tlb_invalidate(void __iomem *sfrbase)
}
static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase,
- unsigned long iova)
+ sysmmu_iova_t iova, unsigned int num_inv)
{
- __raw_writel((iova & SPAGE_MASK) | 1, sfrbase + REG_MMU_FLUSH_ENTRY);
+ unsigned int i;
+
+ for (i = 0; i < num_inv; i++) {
+ __raw_writel((iova & SPAGE_MASK) | 1,
+ sfrbase + REG_MMU_FLUSH_ENTRY);
+ iova += SPAGE_SIZE;
+ }
}
static void __sysmmu_set_ptbase(void __iomem *sfrbase,
- unsigned long pgd)
+ phys_addr_t pgd)
{
- __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */
__raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR);
__sysmmu_tlb_invalidate(sfrbase);
}
-static void __sysmmu_set_prefbuf(void __iomem *sfrbase, unsigned long base,
- unsigned long size, int idx)
+static void show_fault_information(const char *name,
+ enum exynos_sysmmu_inttype itype,
+ phys_addr_t pgtable_base, sysmmu_iova_t fault_addr)
{
- __raw_writel(base, sfrbase + REG_PB0_SADDR + idx * 8);
- __raw_writel(size - 1 + base, sfrbase + REG_PB0_EADDR + idx * 8);
-}
-
-static void __set_fault_handler(struct sysmmu_drvdata *data,
- sysmmu_fault_handler_t handler)
-{
- unsigned long flags;
-
- write_lock_irqsave(&data->lock, flags);
- data->fault_handler = handler;
- write_unlock_irqrestore(&data->lock, flags);
-}
-
-void exynos_sysmmu_set_fault_handler(struct device *dev,
- sysmmu_fault_handler_t handler)
-{
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
-
- __set_fault_handler(data, handler);
-}
-
-static int default_fault_handler(enum exynos_sysmmu_inttype itype,
- unsigned long pgtable_base, unsigned long fault_addr)
-{
- unsigned long *ent;
+ sysmmu_pte_t *ent;
if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
itype = SYSMMU_FAULT_UNKNOWN;
- pr_err("%s occurred at 0x%lx(Page table base: 0x%lx)\n",
- sysmmu_fault_name[itype], fault_addr, pgtable_base);
+ pr_err("%s occurred at %#x by %s(Page table base: %pa)\n",
+ sysmmu_fault_name[itype], fault_addr, name, &pgtable_base);
- ent = section_entry(__va(pgtable_base), fault_addr);
- pr_err("\tLv1 entry: 0x%lx\n", *ent);
+ ent = section_entry(phys_to_virt(pgtable_base), fault_addr);
+ pr_err("\tLv1 entry: %#x\n", *ent);
if (lv1ent_page(ent)) {
ent = page_entry(ent, fault_addr);
- pr_err("\t Lv2 entry: 0x%lx\n", *ent);
+ pr_err("\t Lv2 entry: %#x\n", *ent);
}
-
- pr_err("Generating Kernel OOPS... because it is unrecoverable.\n");
-
- BUG();
-
- return 0;
}
static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
{
/* SYSMMU is in blocked when interrupt occurred. */
struct sysmmu_drvdata *data = dev_id;
- struct resource *irqres;
- struct platform_device *pdev;
enum exynos_sysmmu_inttype itype;
- unsigned long addr = -1;
-
- int i, ret = -ENOSYS;
-
- read_lock(&data->lock);
+ sysmmu_iova_t addr = -1;
+ int ret = -ENOSYS;
WARN_ON(!is_sysmmu_active(data));
- pdev = to_platform_device(data->sysmmu);
- for (i = 0; i < (pdev->num_resources / 2); i++) {
- irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i);
- if (irqres && ((int)irqres->start == irq))
- break;
- }
+ spin_lock(&data->lock);
+
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
- if (i == pdev->num_resources) {
+ itype = (enum exynos_sysmmu_inttype)
+ __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS));
+ if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN))))
itype = SYSMMU_FAULT_UNKNOWN;
+ else
+ addr = __raw_readl(data->sfrbase + fault_reg_offset[itype]);
+
+ if (itype == SYSMMU_FAULT_UNKNOWN) {
+ pr_err("%s: Fault is not occurred by System MMU '%s'!\n",
+ __func__, dev_name(data->sysmmu));
+ pr_err("%s: Please check if IRQ is correctly configured.\n",
+ __func__);
+ BUG();
} else {
- itype = (enum exynos_sysmmu_inttype)
- __ffs(__raw_readl(data->sfrbases[i] + REG_INT_STATUS));
- if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN))))
- itype = SYSMMU_FAULT_UNKNOWN;
- else
- addr = __raw_readl(
- data->sfrbases[i] + fault_reg_offset[itype]);
+ unsigned int base =
+ __raw_readl(data->sfrbase + REG_PT_BASE_ADDR);
+ show_fault_information(dev_name(data->sysmmu),
+ itype, base, addr);
+ if (data->domain)
+ ret = report_iommu_fault(data->domain,
+ data->master, addr, itype);
}
- if (data->domain)
- ret = report_iommu_fault(data->domain, data->dev,
- addr, itype);
+ /* fault is not recovered by fault handler */
+ BUG_ON(ret != 0);
- if ((ret == -ENOSYS) && data->fault_handler) {
- unsigned long base = data->pgtable;
- if (itype != SYSMMU_FAULT_UNKNOWN)
- base = __raw_readl(
- data->sfrbases[i] + REG_PT_BASE_ADDR);
- ret = data->fault_handler(itype, base, addr);
- }
+ __raw_writel(1 << itype, data->sfrbase + REG_INT_CLEAR);
- if (!ret && (itype != SYSMMU_FAULT_UNKNOWN))
- __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR);
- else
- dev_dbg(data->sysmmu, "(%s) %s is not handled.\n",
- data->dbgname, sysmmu_fault_name[itype]);
+ sysmmu_unblock(data->sfrbase);
- if (itype != SYSMMU_FAULT_UNKNOWN)
- sysmmu_unblock(data->sfrbases[i]);
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
- read_unlock(&data->lock);
+ spin_unlock(&data->lock);
return IRQ_HANDLED;
}
-static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data)
+static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
{
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
+
+ __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
+ __raw_writel(0, data->sfrbase + REG_MMU_CFG);
+
+ clk_disable(data->clk);
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
+}
+
+static bool __sysmmu_disable(struct sysmmu_drvdata *data)
+{
+ bool disabled;
unsigned long flags;
- bool disabled = false;
- int i;
- write_lock_irqsave(&data->lock, flags);
+ spin_lock_irqsave(&data->lock, flags);
- if (!set_sysmmu_inactive(data))
- goto finish;
+ disabled = set_sysmmu_inactive(data);
- for (i = 0; i < data->nsfrs; i++)
- __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL);
+ if (disabled) {
+ data->pgtable = 0;
+ data->domain = NULL;
- if (data->clk[1])
- clk_disable(data->clk[1]);
- if (data->clk[0])
- clk_disable(data->clk[0]);
+ __sysmmu_disable_nocount(data);
- disabled = true;
- data->pgtable = 0;
- data->domain = NULL;
-finish:
- write_unlock_irqrestore(&data->lock, flags);
+ dev_dbg(data->sysmmu, "Disabled\n");
+ } else {
+ dev_dbg(data->sysmmu, "%d times left to disable\n",
+ data->activations);
+ }
- if (disabled)
- dev_dbg(data->sysmmu, "(%s) Disabled\n", data->dbgname);
- else
- dev_dbg(data->sysmmu, "(%s) %d times left to be disabled\n",
- data->dbgname, data->activations);
+ spin_unlock_irqrestore(&data->lock, flags);
return disabled;
}
-/* __exynos_sysmmu_enable: Enables System MMU
- *
- * returns -error if an error occurred and System MMU is not enabled,
- * 0 if the System MMU has been just enabled and 1 if System MMU was already
- * enabled before.
- */
-static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data,
- unsigned long pgtable, struct iommu_domain *domain)
+static void __sysmmu_init_config(struct sysmmu_drvdata *data)
{
- int i, ret = 0;
- unsigned long flags;
+ unsigned int cfg = CFG_LRU | CFG_QOS(15);
+ unsigned int ver;
+
+ ver = __raw_sysmmu_version(data);
+ if (MMU_MAJ_VER(ver) == 3) {
+ if (MMU_MIN_VER(ver) >= 2) {
+ cfg |= CFG_FLPDCACHE;
+ if (MMU_MIN_VER(ver) == 3) {
+ cfg |= CFG_ACGEN;
+ cfg &= ~CFG_LRU;
+ } else {
+ cfg |= CFG_SYSSEL;
+ }
+ }
+ }
- write_lock_irqsave(&data->lock, flags);
+ __raw_writel(cfg, data->sfrbase + REG_MMU_CFG);
+}
- if (!set_sysmmu_active(data)) {
- if (WARN_ON(pgtable != data->pgtable)) {
- ret = -EBUSY;
- set_sysmmu_inactive(data);
- } else {
- ret = 1;
- }
+static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
+{
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
+ clk_enable(data->clk);
- dev_dbg(data->sysmmu, "(%s) Already enabled\n", data->dbgname);
- goto finish;
- }
+ __raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
- if (data->clk[0])
- clk_enable(data->clk[0]);
- if (data->clk[1])
- clk_enable(data->clk[1]);
+ __sysmmu_init_config(data);
- data->pgtable = pgtable;
+ __sysmmu_set_ptbase(data->sfrbase, data->pgtable);
- for (i = 0; i < data->nsfrs; i++) {
- __sysmmu_set_ptbase(data->sfrbases[i], pgtable);
+ __raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
- if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) {
- /* System MMU version is 3.x */
- __raw_writel((1 << 12) | (2 << 28),
- data->sfrbases[i] + REG_MMU_CFG);
- __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 0);
- __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 1);
- }
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
+}
+
+static int __sysmmu_enable(struct sysmmu_drvdata *data,
+ phys_addr_t pgtable, struct iommu_domain *domain)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&data->lock, flags);
+ if (set_sysmmu_active(data)) {
+ data->pgtable = pgtable;
+ data->domain = domain;
+
+ __sysmmu_enable_nocount(data);
+
+ dev_dbg(data->sysmmu, "Enabled\n");
+ } else {
+ ret = (pgtable == data->pgtable) ? 1 : -EBUSY;
- __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL);
+ dev_dbg(data->sysmmu, "already enabled\n");
}
- data->domain = domain;
+ if (WARN_ON(ret < 0))
+ set_sysmmu_inactive(data); /* decrement count */
- dev_dbg(data->sysmmu, "(%s) Enabled\n", data->dbgname);
-finish:
- write_unlock_irqrestore(&data->lock, flags);
+ spin_unlock_irqrestore(&data->lock, flags);
return ret;
}
-int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable)
+/* __exynos_sysmmu_enable: Enables System MMU
+ *
+ * returns -error if an error occurred and System MMU is not enabled,
+ * 0 if the System MMU has been just enabled and 1 if System MMU was already
+ * enabled before.
+ */
+static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
+ struct iommu_domain *domain)
{
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
- int ret;
+ int ret = 0;
+ unsigned long flags;
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ struct sysmmu_drvdata *data;
- BUG_ON(!memblock_is_memory(pgtable));
+ BUG_ON(!has_sysmmu(dev));
- ret = pm_runtime_get_sync(data->sysmmu);
- if (ret < 0) {
- dev_dbg(data->sysmmu, "(%s) Failed to enable\n", data->dbgname);
- return ret;
- }
+ spin_lock_irqsave(&owner->lock, flags);
- ret = __exynos_sysmmu_enable(data, pgtable, NULL);
- if (WARN_ON(ret < 0)) {
- pm_runtime_put(data->sysmmu);
- dev_err(data->sysmmu,
- "(%s) Already enabled with page table %#lx\n",
- data->dbgname, data->pgtable);
- } else {
- data->dev = dev;
- }
+ data = dev_get_drvdata(owner->sysmmu);
+
+ ret = __sysmmu_enable(data, pgtable, domain);
+ if (ret >= 0)
+ data->master = dev;
+
+ spin_unlock_irqrestore(&owner->lock, flags);
return ret;
}
+int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable)
+{
+ BUG_ON(!memblock_is_memory(pgtable));
+
+ return __exynos_sysmmu_enable(dev, pgtable, NULL);
+}
+
static bool exynos_sysmmu_disable(struct device *dev)
{
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
- bool disabled;
+ unsigned long flags;
+ bool disabled = true;
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ struct sysmmu_drvdata *data;
+
+ BUG_ON(!has_sysmmu(dev));
+
+ spin_lock_irqsave(&owner->lock, flags);
+
+ data = dev_get_drvdata(owner->sysmmu);
+
+ disabled = __sysmmu_disable(data);
+ if (disabled)
+ data->master = NULL;
- disabled = __exynos_sysmmu_disable(data);
- pm_runtime_put(data->sysmmu);
+ spin_unlock_irqrestore(&owner->lock, flags);
return disabled;
}
-static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova)
+static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
+ sysmmu_iova_t iova)
+{
+ if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3))
+ __raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
+}
+
+static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
+ sysmmu_iova_t iova)
{
unsigned long flags;
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ struct sysmmu_drvdata *data = dev_get_drvdata(owner->sysmmu);
+
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
- read_lock_irqsave(&data->lock, flags);
+ spin_lock_irqsave(&data->lock, flags);
+ if (is_sysmmu_active(data))
+ __sysmmu_tlb_invalidate_flpdcache(data, iova);
+ spin_unlock_irqrestore(&data->lock, flags);
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
+}
+
+static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
+ size_t size)
+{
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
+ unsigned long flags;
+ struct sysmmu_drvdata *data;
+
+ data = dev_get_drvdata(owner->sysmmu);
+
+ spin_lock_irqsave(&data->lock, flags);
if (is_sysmmu_active(data)) {
- int i;
- for (i = 0; i < data->nsfrs; i++) {
- if (sysmmu_block(data->sfrbases[i])) {
- __sysmmu_tlb_invalidate_entry(
- data->sfrbases[i], iova);
- sysmmu_unblock(data->sfrbases[i]);
- }
+ unsigned int num_inv = 1;
+
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
+
+ /*
+ * L2TLB invalidation required
+ * 4KB page: 1 invalidation
+ * 64KB page: 16 invalidation
+ * 1MB page: 64 invalidation
+ * because it is set-associative TLB
+ * with 8-way and 64 sets.
+ * 1MB page can be cached in one of all sets.
+ * 64KB page can be one of 16 consecutive sets.
+ */
+ if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2)
+ num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
+
+ if (sysmmu_block(data->sfrbase)) {
+ __sysmmu_tlb_invalidate_entry(
+ data->sfrbase, iova, num_inv);
+ sysmmu_unblock(data->sfrbase);
}
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
} else {
- dev_dbg(data->sysmmu,
- "(%s) Disabled. Skipping invalidating TLB.\n",
- data->dbgname);
+ dev_dbg(dev, "disabled. Skipping TLB invalidation @ %#x\n",
+ iova);
}
-
- read_unlock_irqrestore(&data->lock, flags);
+ spin_unlock_irqrestore(&data->lock, flags);
}
void exynos_sysmmu_tlb_invalidate(struct device *dev)
{
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
unsigned long flags;
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ struct sysmmu_drvdata *data;
- read_lock_irqsave(&data->lock, flags);
+ data = dev_get_drvdata(owner->sysmmu);
+ spin_lock_irqsave(&data->lock, flags);
if (is_sysmmu_active(data)) {
- int i;
- for (i = 0; i < data->nsfrs; i++) {
- if (sysmmu_block(data->sfrbases[i])) {
- __sysmmu_tlb_invalidate(data->sfrbases[i]);
- sysmmu_unblock(data->sfrbases[i]);
- }
+ if (!IS_ERR(data->clk_master))
+ clk_enable(data->clk_master);
+ if (sysmmu_block(data->sfrbase)) {
+ __sysmmu_tlb_invalidate(data->sfrbase);
+ sysmmu_unblock(data->sfrbase);
}
+ if (!IS_ERR(data->clk_master))
+ clk_disable(data->clk_master);
} else {
- dev_dbg(data->sysmmu,
- "(%s) Disabled. Skipping invalidating TLB.\n",
- data->dbgname);
+ dev_dbg(dev, "disabled. Skipping TLB invalidation\n");
}
-
- read_unlock_irqrestore(&data->lock, flags);
+ spin_unlock_irqrestore(&data->lock, flags);
}
-static int exynos_sysmmu_probe(struct platform_device *pdev)
+static int __init exynos_sysmmu_probe(struct platform_device *pdev)
{
- int i, ret;
- struct device *dev;
+ int irq, ret;
+ struct device *dev = &pdev->dev;
struct sysmmu_drvdata *data;
+ struct resource *res;
- dev = &pdev->dev;
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- dev_dbg(dev, "Not enough memory\n");
- ret = -ENOMEM;
- goto err_alloc;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->sfrbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->sfrbase))
+ return PTR_ERR(data->sfrbase);
- dev_set_drvdata(dev, data);
- data->nsfrs = pdev->num_resources / 2;
- data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs,
- GFP_KERNEL);
- if (data->sfrbases == NULL) {
- dev_dbg(dev, "Not enough memory\n");
- ret = -ENOMEM;
- goto err_init;
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
+ dev_err(dev, "Unable to find IRQ resource\n");
+ return irq;
}
- for (i = 0; i < data->nsfrs; i++) {
- struct resource *res;
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res) {
- dev_dbg(dev, "Unable to find IOMEM region\n");
- ret = -ENOENT;
- goto err_res;
- }
-
- data->sfrbases[i] = ioremap(res->start, resource_size(res));
- if (!data->sfrbases[i]) {
- dev_dbg(dev, "Unable to map IOMEM @ PA:%#x\n",
- res->start);
- ret = -ENOENT;
- goto err_res;
- }
+ ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0,
+ dev_name(dev), data);
+ if (ret) {
+ dev_err(dev, "Unabled to register handler of irq %d\n", irq);
+ return ret;
}
- for (i = 0; i < data->nsfrs; i++) {
- ret = platform_get_irq(pdev, i);
- if (ret <= 0) {
- dev_dbg(dev, "Unable to find IRQ resource\n");
- goto err_irq;
- }
-
- ret = request_irq(ret, exynos_sysmmu_irq, 0,
- dev_name(dev), data);
+ data->clk = devm_clk_get(dev, "sysmmu");
+ if (IS_ERR(data->clk)) {
+ dev_err(dev, "Failed to get clock!\n");
+ return PTR_ERR(data->clk);
+ } else {
+ ret = clk_prepare(data->clk);
if (ret) {
- dev_dbg(dev, "Unabled to register interrupt handler\n");
- goto err_irq;
+ dev_err(dev, "Failed to prepare clk\n");
+ return ret;
}
}
- if (dev_get_platdata(dev)) {
- char *deli, *beg;
- struct sysmmu_platform_data *platdata = dev_get_platdata(dev);
-
- beg = platdata->clockname;
-
- for (deli = beg; (*deli != '\0') && (*deli != ','); deli++)
- /* NOTHING */;
-
- if (*deli == '\0')
- deli = NULL;
- else
- *deli = '\0';
-
- data->clk[0] = clk_get(dev, beg);
- if (IS_ERR(data->clk[0])) {
- data->clk[0] = NULL;
- dev_dbg(dev, "No clock descriptor registered\n");
- }
-
- if (data->clk[0] && deli) {
- *deli = ',';
- data->clk[1] = clk_get(dev, deli + 1);
- if (IS_ERR(data->clk[1]))
- data->clk[1] = NULL;
+ data->clk_master = devm_clk_get(dev, "master");
+ if (!IS_ERR(data->clk_master)) {
+ ret = clk_prepare(data->clk_master);
+ if (ret) {
+ clk_unprepare(data->clk);
+ dev_err(dev, "Failed to prepare master's clk\n");
+ return ret;
}
-
- data->dbgname = platdata->dbgname;
}
data->sysmmu = dev;
- rwlock_init(&data->lock);
- INIT_LIST_HEAD(&data->node);
+ spin_lock_init(&data->lock);
- __set_fault_handler(data, &default_fault_handler);
+ platform_set_drvdata(pdev, data);
- if (dev->parent)
- pm_runtime_enable(dev);
+ pm_runtime_enable(dev);
- dev_dbg(dev, "(%s) Initialized\n", data->dbgname);
return 0;
-err_irq:
- while (i-- > 0) {
- int irq;
-
- irq = platform_get_irq(pdev, i);
- free_irq(irq, data);
- }
-err_res:
- while (data->nsfrs-- > 0)
- iounmap(data->sfrbases[data->nsfrs]);
- kfree(data->sfrbases);
-err_init:
- kfree(data);
-err_alloc:
- dev_err(dev, "Failed to initialize\n");
- return ret;
}
-static struct platform_driver exynos_sysmmu_driver = {
- .probe = exynos_sysmmu_probe,
- .driver = {
+static const struct of_device_id sysmmu_of_match[] __initconst = {
+ { .compatible = "samsung,exynos-sysmmu", },
+ { },
+};
+
+static struct platform_driver exynos_sysmmu_driver __refdata = {
+ .probe = exynos_sysmmu_probe,
+ .driver = {
.owner = THIS_MODULE,
.name = "exynos-sysmmu",
+ .of_match_table = sysmmu_of_match,
}
};
@@ -662,21 +700,32 @@ static inline void pgtable_flush(void *vastart, void *vaend)
static int exynos_iommu_domain_init(struct iommu_domain *domain)
{
struct exynos_iommu_domain *priv;
+ int i;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- priv->pgtable = (unsigned long *)__get_free_pages(
- GFP_KERNEL | __GFP_ZERO, 2);
+ priv->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
if (!priv->pgtable)
goto err_pgtable;
- priv->lv2entcnt = (short *)__get_free_pages(
- GFP_KERNEL | __GFP_ZERO, 1);
+ priv->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
if (!priv->lv2entcnt)
goto err_counter;
+ /* w/a of System MMU v3.3 to prevent caching 1MiB mapping */
+ for (i = 0; i < NUM_LV1ENTRIES; i += 8) {
+ priv->pgtable[i + 0] = ZERO_LV2LINK;
+ priv->pgtable[i + 1] = ZERO_LV2LINK;
+ priv->pgtable[i + 2] = ZERO_LV2LINK;
+ priv->pgtable[i + 3] = ZERO_LV2LINK;
+ priv->pgtable[i + 4] = ZERO_LV2LINK;
+ priv->pgtable[i + 5] = ZERO_LV2LINK;
+ priv->pgtable[i + 6] = ZERO_LV2LINK;
+ priv->pgtable[i + 7] = ZERO_LV2LINK;
+ }
+
pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
spin_lock_init(&priv->lock);
@@ -700,7 +749,7 @@ err_pgtable:
static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
{
struct exynos_iommu_domain *priv = domain->priv;
- struct sysmmu_drvdata *data;
+ struct exynos_iommu_owner *owner;
unsigned long flags;
int i;
@@ -708,16 +757,20 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(data, &priv->clients, node) {
- while (!exynos_sysmmu_disable(data->dev))
+ list_for_each_entry(owner, &priv->clients, client) {
+ while (!exynos_sysmmu_disable(owner->dev))
; /* until System MMU is actually disabled */
}
+ while (!list_empty(&priv->clients))
+ list_del_init(priv->clients.next);
+
spin_unlock_irqrestore(&priv->lock, flags);
for (i = 0; i < NUM_LV1ENTRIES; i++)
if (lv1ent_page(priv->pgtable + i))
- kfree(__va(lv2table_base(priv->pgtable + i)));
+ kmem_cache_free(lv2table_kmem_cache,
+ phys_to_virt(lv2table_base(priv->pgtable + i)));
free_pages((unsigned long)priv->pgtable, 2);
free_pages((unsigned long)priv->lv2entcnt, 1);
@@ -728,114 +781,134 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
static int exynos_iommu_attach_device(struct iommu_domain *domain,
struct device *dev)
{
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ struct exynos_iommu_owner *owner = dev->archdata.iommu;
struct exynos_iommu_domain *priv = domain->priv;
+ phys_addr_t pagetable = virt_to_phys(priv->pgtable);
unsigned long flags;
int ret;
- ret = pm_runtime_get_sync(data->sysmmu);
- if (ret < 0)
- return ret;
-
- ret = 0;
-
spin_lock_irqsave(&priv->lock, flags);
- ret = __exynos_sysmmu_enable(data, __pa(priv->pgtable), domain);
-
+ ret = __exynos_sysmmu_enable(dev, pagetable, domain);
if (ret == 0) {
- /* 'data->node' must not be appeared in priv->clients */
- BUG_ON(!list_empty(&data->node));
- data->dev = dev;
- list_add_tail(&data->node, &priv->clients);
+ list_add_tail(&owner->client, &priv->clients);
+ owner->domain = domain;
}
spin_unlock_irqrestore(&priv->lock, flags);
if (ret < 0) {
- dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n",
- __func__, __pa(priv->pgtable));
- pm_runtime_put(data->sysmmu);
- } else if (ret > 0) {
- dev_dbg(dev, "%s: IOMMU with pgtable 0x%lx already attached\n",
- __func__, __pa(priv->pgtable));
- } else {
- dev_dbg(dev, "%s: Attached new IOMMU with pgtable 0x%lx\n",
- __func__, __pa(priv->pgtable));
+ dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
+ __func__, &pagetable);
+ return ret;
}
+ dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa %s\n",
+ __func__, &pagetable, (ret == 0) ? "" : ", again");
+
return ret;
}
static void exynos_iommu_detach_device(struct iommu_domain *domain,
struct device *dev)
{
- struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu);
+ struct exynos_iommu_owner *owner;
struct exynos_iommu_domain *priv = domain->priv;
- struct list_head *pos;
+ phys_addr_t pagetable = virt_to_phys(priv->pgtable);
unsigned long flags;
- bool found = false;
spin_lock_irqsave(&priv->lock, flags);
- list_for_each(pos, &priv->clients) {
- if (list_entry(pos, struct sysmmu_drvdata, node) == data) {
- found = true;
+ list_for_each_entry(owner, &priv->clients, client) {
+ if (owner == dev->archdata.iommu) {
+ if (exynos_sysmmu_disable(dev)) {
+ list_del_init(&owner->client);
+ owner->domain = NULL;
+ }
break;
}
}
- if (!found)
- goto finish;
-
- if (__exynos_sysmmu_disable(data)) {
- dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n",
- __func__, __pa(priv->pgtable));
- list_del_init(&data->node);
-
- } else {
- dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed",
- __func__, __pa(priv->pgtable));
- }
-
-finish:
spin_unlock_irqrestore(&priv->lock, flags);
- if (found)
- pm_runtime_put(data->sysmmu);
+ if (owner == dev->archdata.iommu)
+ dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
+ __func__, &pagetable);
+ else
+ dev_err(dev, "%s: No IOMMU is attached\n", __func__);
}
-static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova,
- short *pgcounter)
+static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
+ sysmmu_pte_t *sent, sysmmu_iova_t iova, short *pgcounter)
{
+ if (lv1ent_section(sent)) {
+ WARN(1, "Trying mapping on %#08x mapped with 1MiB page", iova);
+ return ERR_PTR(-EADDRINUSE);
+ }
+
if (lv1ent_fault(sent)) {
- unsigned long *pent;
+ sysmmu_pte_t *pent;
+ bool need_flush_flpd_cache = lv1ent_zero(sent);
- pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC);
- BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1));
+ pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC);
+ BUG_ON((unsigned int)pent & (LV2TABLE_SIZE - 1));
if (!pent)
- return NULL;
+ return ERR_PTR(-ENOMEM);
- *sent = mk_lv1ent_page(__pa(pent));
+ *sent = mk_lv1ent_page(virt_to_phys(pent));
*pgcounter = NUM_LV2ENTRIES;
pgtable_flush(pent, pent + NUM_LV2ENTRIES);
pgtable_flush(sent, sent + 1);
+
+ /*
+ * If pretched SLPD is a fault SLPD in zero_l2_table, FLPD cache
+ * may caches the address of zero_l2_table. This function
+ * replaces the zero_l2_table with new L2 page table to write
+ * valid mappings.
+ * Accessing the valid area may cause page fault since FLPD
+ * cache may still caches zero_l2_table for the valid area
+ * instead of new L2 page table that have the mapping
+ * information of the valid area
+ * Thus any replacement of zero_l2_table with other valid L2
+ * page table must involve FLPD cache invalidation for System
+ * MMU v3.3.
+ * FLPD cache invalidation is performed with TLB invalidation
+ * by VPN without blocking. It is safe to invalidate TLB without
+ * blocking because the target address of TLB invalidation is
+ * not currently mapped.
+ */
+ if (need_flush_flpd_cache) {
+ struct exynos_iommu_owner *owner;
+
+ spin_lock(&priv->lock);
+ list_for_each_entry(owner, &priv->clients, client)
+ sysmmu_tlb_invalidate_flpdcache(
+ owner->dev, iova);
+ spin_unlock(&priv->lock);
+ }
}
return page_entry(sent, iova);
}
-static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt)
+static int lv1set_section(struct exynos_iommu_domain *priv,
+ sysmmu_pte_t *sent, sysmmu_iova_t iova,
+ phys_addr_t paddr, short *pgcnt)
{
- if (lv1ent_section(sent))
+ if (lv1ent_section(sent)) {
+ WARN(1, "Trying mapping on 1MiB@%#08x that is mapped",
+ iova);
return -EADDRINUSE;
+ }
if (lv1ent_page(sent)) {
- if (*pgcnt != NUM_LV2ENTRIES)
+ if (*pgcnt != NUM_LV2ENTRIES) {
+ WARN(1, "Trying mapping on 1MiB@%#08x that is mapped",
+ iova);
return -EADDRINUSE;
+ }
- kfree(page_entry(sent, 0));
-
+ kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0));
*pgcnt = 0;
}
@@ -843,14 +916,26 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt)
pgtable_flush(sent, sent + 1);
+ spin_lock(&priv->lock);
+ if (lv1ent_page_zero(sent)) {
+ struct exynos_iommu_owner *owner;
+ /*
+ * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
+ * entry by speculative prefetch of SLPD which has no mapping.
+ */
+ list_for_each_entry(owner, &priv->clients, client)
+ sysmmu_tlb_invalidate_flpdcache(owner->dev, iova);
+ }
+ spin_unlock(&priv->lock);
+
return 0;
}
-static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size,
+static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size,
short *pgcnt)
{
if (size == SPAGE_SIZE) {
- if (!lv2ent_fault(pent))
+ if (WARN_ON(!lv2ent_fault(pent)))
return -EADDRINUSE;
*pent = mk_lv2ent_spage(paddr);
@@ -858,9 +943,11 @@ static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size,
*pgcnt -= 1;
} else { /* size == LPAGE_SIZE */
int i;
+
for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) {
- if (!lv2ent_fault(pent)) {
- memset(pent, 0, sizeof(*pent) * i);
+ if (WARN_ON(!lv2ent_fault(pent))) {
+ if (i > 0)
+ memset(pent - i, 0, sizeof(*pent) * i);
return -EADDRINUSE;
}
@@ -873,11 +960,38 @@ static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size,
return 0;
}
-static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova,
+/*
+ * *CAUTION* to the I/O virtual memory managers that support exynos-iommu:
+ *
+ * System MMU v3.x have an advanced logic to improve address translation
+ * performance with caching more page table entries by a page table walk.
+ * However, the logic has a bug that caching fault page table entries and System
+ * MMU reports page fault if the cached fault entry is hit even though the fault
+ * entry is updated to a valid entry after the entry is cached.
+ * To prevent caching fault page table entries which may be updated to valid
+ * entries later, the virtual memory manager should care about the w/a about the
+ * problem. The followings describe w/a.
+ *
+ * Any two consecutive I/O virtual address regions must have a hole of 128KiB
+ * in maximum to prevent misbehavior of System MMU 3.x. (w/a of h/w bug)
+ *
+ * Precisely, any start address of I/O virtual region must be aligned by
+ * the following sizes for System MMU v3.1 and v3.2.
+ * System MMU v3.1: 128KiB
+ * System MMU v3.2: 256KiB
+ *
+ * Because System MMU v3.3 caches page table entries more aggressively, it needs
+ * more w/a.
+ * - Any two consecutive I/O virtual regions must be have a hole of larger size
+ * than or equal size to 128KiB.
+ * - Start address of an I/O virtual region must be aligned by 128KiB.
+ */
+static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
phys_addr_t paddr, size_t size, int prot)
{
struct exynos_iommu_domain *priv = domain->priv;
- unsigned long *entry;
+ sysmmu_pte_t *entry;
+ sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
unsigned long flags;
int ret = -ENOMEM;
@@ -888,38 +1002,52 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova,
entry = section_entry(priv->pgtable, iova);
if (size == SECT_SIZE) {
- ret = lv1set_section(entry, paddr,
+ ret = lv1set_section(priv, entry, iova, paddr,
&priv->lv2entcnt[lv1ent_offset(iova)]);
} else {
- unsigned long *pent;
+ sysmmu_pte_t *pent;
- pent = alloc_lv2entry(entry, iova,
+ pent = alloc_lv2entry(priv, entry, iova,
&priv->lv2entcnt[lv1ent_offset(iova)]);
- if (!pent)
- ret = -ENOMEM;
+ if (IS_ERR(pent))
+ ret = PTR_ERR(pent);
else
ret = lv2set_page(pent, paddr, size,
&priv->lv2entcnt[lv1ent_offset(iova)]);
}
- if (ret) {
- pr_debug("%s: Failed to map iova 0x%lx/0x%x bytes\n",
- __func__, iova, size);
- }
+ if (ret)
+ pr_err("%s: Failed(%d) to map %#zx bytes @ %#x\n",
+ __func__, ret, size, iova);
spin_unlock_irqrestore(&priv->pgtablelock, flags);
return ret;
}
+static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
+ sysmmu_iova_t iova, size_t size)
+{
+ struct exynos_iommu_owner *owner;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ list_for_each_entry(owner, &priv->clients, client)
+ sysmmu_tlb_invalidate_entry(owner->dev, iova, size);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
static size_t exynos_iommu_unmap(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+ unsigned long l_iova, size_t size)
{
struct exynos_iommu_domain *priv = domain->priv;
- struct sysmmu_drvdata *data;
+ sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
+ sysmmu_pte_t *ent;
+ size_t err_pgsize;
unsigned long flags;
- unsigned long *ent;
BUG_ON(priv->pgtable == NULL);
@@ -928,9 +1056,12 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
ent = section_entry(priv->pgtable, iova);
if (lv1ent_section(ent)) {
- BUG_ON(size < SECT_SIZE);
+ if (WARN_ON(size < SECT_SIZE)) {
+ err_pgsize = SECT_SIZE;
+ goto err;
+ }
- *ent = 0;
+ *ent = ZERO_LV2LINK; /* w/a for h/w bug in Sysmem MMU v3.3 */
pgtable_flush(ent, ent + 1);
size = SECT_SIZE;
goto done;
@@ -954,34 +1085,42 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
if (lv2ent_small(ent)) {
*ent = 0;
size = SPAGE_SIZE;
+ pgtable_flush(ent, ent + 1);
priv->lv2entcnt[lv1ent_offset(iova)] += 1;
goto done;
}
/* lv1ent_large(ent) == true here */
- BUG_ON(size < LPAGE_SIZE);
+ if (WARN_ON(size < LPAGE_SIZE)) {
+ err_pgsize = LPAGE_SIZE;
+ goto err;
+ }
memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE);
+ pgtable_flush(ent, ent + SPAGES_PER_LPAGE);
size = LPAGE_SIZE;
priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
done:
spin_unlock_irqrestore(&priv->pgtablelock, flags);
- spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry(data, &priv->clients, node)
- sysmmu_tlb_invalidate_entry(data->dev, iova);
- spin_unlock_irqrestore(&priv->lock, flags);
-
+ exynos_iommu_tlb_invalidate_entry(priv, iova, size);
return size;
+err:
+ spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+ pr_err("%s: Failed: size(%#zx) @ %#x is smaller than page size %#zx\n",
+ __func__, size, iova, err_pgsize);
+
+ return 0;
}
static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{
struct exynos_iommu_domain *priv = domain->priv;
- unsigned long *entry;
+ sysmmu_pte_t *entry;
unsigned long flags;
phys_addr_t phys = 0;
@@ -1005,6 +1144,32 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
return phys;
}
+static int exynos_iommu_add_device(struct device *dev)
+{
+ struct iommu_group *group;
+ int ret;
+
+ group = iommu_group_get(dev);
+
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group)) {
+ dev_err(dev, "Failed to allocate IOMMU group\n");
+ return PTR_ERR(group);
+ }
+ }
+
+ ret = iommu_group_add_device(group, dev);
+ iommu_group_put(group);
+
+ return ret;
+}
+
+static void exynos_iommu_remove_device(struct device *dev)
+{
+ iommu_group_remove_device(dev);
+}
+
static struct iommu_ops exynos_iommu_ops = {
.domain_init = exynos_iommu_domain_init,
.domain_destroy = exynos_iommu_domain_destroy,
@@ -1013,6 +1178,8 @@ static struct iommu_ops exynos_iommu_ops = {
.map = exynos_iommu_map,
.unmap = exynos_iommu_unmap,
.iova_to_phys = exynos_iommu_iova_to_phys,
+ .add_device = exynos_iommu_add_device,
+ .remove_device = exynos_iommu_remove_device,
.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
};
@@ -1020,11 +1187,41 @@ static int __init exynos_iommu_init(void)
{
int ret;
+ lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
+ LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
+ if (!lv2table_kmem_cache) {
+ pr_err("%s: Failed to create kmem cache\n", __func__);
+ return -ENOMEM;
+ }
+
ret = platform_driver_register(&exynos_sysmmu_driver);
+ if (ret) {
+ pr_err("%s: Failed to register driver\n", __func__);
+ goto err_reg_driver;
+ }
- if (ret == 0)
- bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
+ zero_lv2_table = kmem_cache_zalloc(lv2table_kmem_cache, GFP_KERNEL);
+ if (zero_lv2_table == NULL) {
+ pr_err("%s: Failed to allocate zero level2 page table\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_zero_lv2;
+ }
+ ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
+ if (ret) {
+ pr_err("%s: Failed to register exynos-iommu driver.\n",
+ __func__);
+ goto err_set_iommu;
+ }
+
+ return 0;
+err_set_iommu:
+ kmem_cache_free(lv2table_kmem_cache, zero_lv2_table);
+err_zero_lv2:
+ platform_driver_unregister(&exynos_sysmmu_driver);
+err_reg_driver:
+ kmem_cache_destroy(lv2table_kmem_cache);
return ret;
}
subsys_initcall(exynos_iommu_init);
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index cba0498eb011..b99dd88e31b9 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -592,8 +592,7 @@ found_cpu_node:
/* advance to next node in cache hierarchy */
node = of_find_node_by_phandle(*prop);
if (!node) {
- pr_debug("Invalid node for cache hierarchy %s\n",
- node->full_name);
+ pr_debug("Invalid node for cache hierarchy\n");
return ~(u32)0;
}
}
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
new file mode 100644
index 000000000000..53cde086e83b
--- /dev/null
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -0,0 +1,1255 @@
+/*
+ * IPMMU VMSA
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/platform_data/ipmmu-vmsa.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+#include <asm/dma-iommu.h>
+#include <asm/pgalloc.h>
+
+struct ipmmu_vmsa_device {
+ struct device *dev;
+ void __iomem *base;
+ struct list_head list;
+
+ const struct ipmmu_vmsa_platform_data *pdata;
+ unsigned int num_utlbs;
+
+ struct dma_iommu_mapping *mapping;
+};
+
+struct ipmmu_vmsa_domain {
+ struct ipmmu_vmsa_device *mmu;
+ struct iommu_domain *io_domain;
+
+ unsigned int context_id;
+ spinlock_t lock; /* Protects mappings */
+ pgd_t *pgd;
+};
+
+struct ipmmu_vmsa_archdata {
+ struct ipmmu_vmsa_device *mmu;
+ unsigned int utlb;
+};
+
+static DEFINE_SPINLOCK(ipmmu_devices_lock);
+static LIST_HEAD(ipmmu_devices);
+
+#define TLB_LOOP_TIMEOUT 100 /* 100us */
+
+/* -----------------------------------------------------------------------------
+ * Registers Definition
+ */
+
+#define IM_CTX_SIZE 0x40
+
+#define IMCTR 0x0000
+#define IMCTR_TRE (1 << 17)
+#define IMCTR_AFE (1 << 16)
+#define IMCTR_RTSEL_MASK (3 << 4)
+#define IMCTR_RTSEL_SHIFT 4
+#define IMCTR_TREN (1 << 3)
+#define IMCTR_INTEN (1 << 2)
+#define IMCTR_FLUSH (1 << 1)
+#define IMCTR_MMUEN (1 << 0)
+
+#define IMCAAR 0x0004
+
+#define IMTTBCR 0x0008
+#define IMTTBCR_EAE (1 << 31)
+#define IMTTBCR_PMB (1 << 30)
+#define IMTTBCR_SH1_NON_SHAREABLE (0 << 28)
+#define IMTTBCR_SH1_OUTER_SHAREABLE (2 << 28)
+#define IMTTBCR_SH1_INNER_SHAREABLE (3 << 28)
+#define IMTTBCR_SH1_MASK (3 << 28)
+#define IMTTBCR_ORGN1_NC (0 << 26)
+#define IMTTBCR_ORGN1_WB_WA (1 << 26)
+#define IMTTBCR_ORGN1_WT (2 << 26)
+#define IMTTBCR_ORGN1_WB (3 << 26)
+#define IMTTBCR_ORGN1_MASK (3 << 26)
+#define IMTTBCR_IRGN1_NC (0 << 24)
+#define IMTTBCR_IRGN1_WB_WA (1 << 24)
+#define IMTTBCR_IRGN1_WT (2 << 24)
+#define IMTTBCR_IRGN1_WB (3 << 24)
+#define IMTTBCR_IRGN1_MASK (3 << 24)
+#define IMTTBCR_TSZ1_MASK (7 << 16)
+#define IMTTBCR_TSZ1_SHIFT 16
+#define IMTTBCR_SH0_NON_SHAREABLE (0 << 12)
+#define IMTTBCR_SH0_OUTER_SHAREABLE (2 << 12)
+#define IMTTBCR_SH0_INNER_SHAREABLE (3 << 12)
+#define IMTTBCR_SH0_MASK (3 << 12)
+#define IMTTBCR_ORGN0_NC (0 << 10)
+#define IMTTBCR_ORGN0_WB_WA (1 << 10)
+#define IMTTBCR_ORGN0_WT (2 << 10)
+#define IMTTBCR_ORGN0_WB (3 << 10)
+#define IMTTBCR_ORGN0_MASK (3 << 10)
+#define IMTTBCR_IRGN0_NC (0 << 8)
+#define IMTTBCR_IRGN0_WB_WA (1 << 8)
+#define IMTTBCR_IRGN0_WT (2 << 8)
+#define IMTTBCR_IRGN0_WB (3 << 8)
+#define IMTTBCR_IRGN0_MASK (3 << 8)
+#define IMTTBCR_SL0_LVL_2 (0 << 4)
+#define IMTTBCR_SL0_LVL_1 (1 << 4)
+#define IMTTBCR_TSZ0_MASK (7 << 0)
+#define IMTTBCR_TSZ0_SHIFT O
+
+#define IMBUSCR 0x000c
+#define IMBUSCR_DVM (1 << 2)
+#define IMBUSCR_BUSSEL_SYS (0 << 0)
+#define IMBUSCR_BUSSEL_CCI (1 << 0)
+#define IMBUSCR_BUSSEL_IMCAAR (2 << 0)
+#define IMBUSCR_BUSSEL_CCI_IMCAAR (3 << 0)
+#define IMBUSCR_BUSSEL_MASK (3 << 0)
+
+#define IMTTLBR0 0x0010
+#define IMTTUBR0 0x0014
+#define IMTTLBR1 0x0018
+#define IMTTUBR1 0x001c
+
+#define IMSTR 0x0020
+#define IMSTR_ERRLVL_MASK (3 << 12)
+#define IMSTR_ERRLVL_SHIFT 12
+#define IMSTR_ERRCODE_TLB_FORMAT (1 << 8)
+#define IMSTR_ERRCODE_ACCESS_PERM (4 << 8)
+#define IMSTR_ERRCODE_SECURE_ACCESS (5 << 8)
+#define IMSTR_ERRCODE_MASK (7 << 8)
+#define IMSTR_MHIT (1 << 4)
+#define IMSTR_ABORT (1 << 2)
+#define IMSTR_PF (1 << 1)
+#define IMSTR_TF (1 << 0)
+
+#define IMMAIR0 0x0028
+#define IMMAIR1 0x002c
+#define IMMAIR_ATTR_MASK 0xff
+#define IMMAIR_ATTR_DEVICE 0x04
+#define IMMAIR_ATTR_NC 0x44
+#define IMMAIR_ATTR_WBRWA 0xff
+#define IMMAIR_ATTR_SHIFT(n) ((n) << 3)
+#define IMMAIR_ATTR_IDX_NC 0
+#define IMMAIR_ATTR_IDX_WBRWA 1
+#define IMMAIR_ATTR_IDX_DEV 2
+
+#define IMEAR 0x0030
+
+#define IMPCTR 0x0200
+#define IMPSTR 0x0208
+#define IMPEAR 0x020c
+#define IMPMBA(n) (0x0280 + ((n) * 4))
+#define IMPMBD(n) (0x02c0 + ((n) * 4))
+
+#define IMUCTR(n) (0x0300 + ((n) * 16))
+#define IMUCTR_FIXADDEN (1 << 31)
+#define IMUCTR_FIXADD_MASK (0xff << 16)
+#define IMUCTR_FIXADD_SHIFT 16
+#define IMUCTR_TTSEL_MMU(n) ((n) << 4)
+#define IMUCTR_TTSEL_PMB (8 << 4)
+#define IMUCTR_TTSEL_MASK (15 << 4)
+#define IMUCTR_FLUSH (1 << 1)
+#define IMUCTR_MMUEN (1 << 0)
+
+#define IMUASID(n) (0x0308 + ((n) * 16))
+#define IMUASID_ASID8_MASK (0xff << 8)
+#define IMUASID_ASID8_SHIFT 8
+#define IMUASID_ASID0_MASK (0xff << 0)
+#define IMUASID_ASID0_SHIFT 0
+
+/* -----------------------------------------------------------------------------
+ * Page Table Bits
+ */
+
+/*
+ * VMSA states in section B3.6.3 "Control of Secure or Non-secure memory access,
+ * Long-descriptor format" that the NStable bit being set in a table descriptor
+ * will result in the NStable and NS bits of all child entries being ignored and
+ * considered as being set. The IPMMU seems not to comply with this, as it
+ * generates a secure access page fault if any of the NStable and NS bits isn't
+ * set when running in non-secure mode.
+ */
+#ifndef PMD_NSTABLE
+#define PMD_NSTABLE (_AT(pmdval_t, 1) << 63)
+#endif
+
+#define ARM_VMSA_PTE_XN (((pteval_t)3) << 53)
+#define ARM_VMSA_PTE_CONT (((pteval_t)1) << 52)
+#define ARM_VMSA_PTE_AF (((pteval_t)1) << 10)
+#define ARM_VMSA_PTE_SH_NS (((pteval_t)0) << 8)
+#define ARM_VMSA_PTE_SH_OS (((pteval_t)2) << 8)
+#define ARM_VMSA_PTE_SH_IS (((pteval_t)3) << 8)
+#define ARM_VMSA_PTE_SH_MASK (((pteval_t)3) << 8)
+#define ARM_VMSA_PTE_NS (((pteval_t)1) << 5)
+#define ARM_VMSA_PTE_PAGE (((pteval_t)3) << 0)
+
+/* Stage-1 PTE */
+#define ARM_VMSA_PTE_nG (((pteval_t)1) << 11)
+#define ARM_VMSA_PTE_AP_UNPRIV (((pteval_t)1) << 6)
+#define ARM_VMSA_PTE_AP_RDONLY (((pteval_t)2) << 6)
+#define ARM_VMSA_PTE_AP_MASK (((pteval_t)3) << 6)
+#define ARM_VMSA_PTE_ATTRINDX_MASK (((pteval_t)3) << 2)
+#define ARM_VMSA_PTE_ATTRINDX_SHIFT 2
+
+#define ARM_VMSA_PTE_ATTRS_MASK \
+ (ARM_VMSA_PTE_XN | ARM_VMSA_PTE_CONT | ARM_VMSA_PTE_nG | \
+ ARM_VMSA_PTE_AF | ARM_VMSA_PTE_SH_MASK | ARM_VMSA_PTE_AP_MASK | \
+ ARM_VMSA_PTE_NS | ARM_VMSA_PTE_ATTRINDX_MASK)
+
+#define ARM_VMSA_PTE_CONT_ENTRIES 16
+#define ARM_VMSA_PTE_CONT_SIZE (PAGE_SIZE * ARM_VMSA_PTE_CONT_ENTRIES)
+
+#define IPMMU_PTRS_PER_PTE 512
+#define IPMMU_PTRS_PER_PMD 512
+#define IPMMU_PTRS_PER_PGD 4
+
+/* -----------------------------------------------------------------------------
+ * Read/Write Access
+ */
+
+static u32 ipmmu_read(struct ipmmu_vmsa_device *mmu, unsigned int offset)
+{
+ return ioread32(mmu->base + offset);
+}
+
+static void ipmmu_write(struct ipmmu_vmsa_device *mmu, unsigned int offset,
+ u32 data)
+{
+ iowrite32(data, mmu->base + offset);
+}
+
+static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+{
+ return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+}
+
+static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
+ u32 data)
+{
+ ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
+/* -----------------------------------------------------------------------------
+ * TLB and microTLB Management
+ */
+
+/* Wait for any pending TLB invalidations to complete */
+static void ipmmu_tlb_sync(struct ipmmu_vmsa_domain *domain)
+{
+ unsigned int count = 0;
+
+ while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+ cpu_relax();
+ if (++count == TLB_LOOP_TIMEOUT) {
+ dev_err_ratelimited(domain->mmu->dev,
+ "TLB sync timed out -- MMU may be deadlocked\n");
+ return;
+ }
+ udelay(1);
+ }
+}
+
+static void ipmmu_tlb_invalidate(struct ipmmu_vmsa_domain *domain)
+{
+ u32 reg;
+
+ reg = ipmmu_ctx_read(domain, IMCTR);
+ reg |= IMCTR_FLUSH;
+ ipmmu_ctx_write(domain, IMCTR, reg);
+
+ ipmmu_tlb_sync(domain);
+}
+
+/*
+ * Enable MMU translation for the microTLB.
+ */
+static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain *domain,
+ unsigned int utlb)
+{
+ struct ipmmu_vmsa_device *mmu = domain->mmu;
+
+ /*
+ * TODO: Reference-count the microTLB as several bus masters can be
+ * connected to the same microTLB.
+ */
+
+ /* TODO: What should we set the ASID to ? */
+ ipmmu_write(mmu, IMUASID(utlb), 0);
+ /* TODO: Do we need to flush the microTLB ? */
+ ipmmu_write(mmu, IMUCTR(utlb),
+ IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
+ IMUCTR_MMUEN);
+}
+
+/*
+ * Disable MMU translation for the microTLB.
+ */
+static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain *domain,
+ unsigned int utlb)
+{
+ struct ipmmu_vmsa_device *mmu = domain->mmu;
+
+ ipmmu_write(mmu, IMUCTR(utlb), 0);
+}
+
+static void ipmmu_flush_pgtable(struct ipmmu_vmsa_device *mmu, void *addr,
+ size_t size)
+{
+ unsigned long offset = (unsigned long)addr & ~PAGE_MASK;
+
+ /*
+ * TODO: Add support for coherent walk through CCI with DVM and remove
+ * cache handling.
+ */
+ dma_map_page(mmu->dev, virt_to_page(addr), offset, size, DMA_TO_DEVICE);
+}
+
+/* -----------------------------------------------------------------------------
+ * Domain/Context Management
+ */
+
+static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
+{
+ phys_addr_t ttbr;
+ u32 reg;
+
+ /*
+ * TODO: When adding support for multiple contexts, find an unused
+ * context.
+ */
+ domain->context_id = 0;
+
+ /* TTBR0 */
+ ipmmu_flush_pgtable(domain->mmu, domain->pgd,
+ IPMMU_PTRS_PER_PGD * sizeof(*domain->pgd));
+ ttbr = __pa(domain->pgd);
+ ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
+ ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+
+ /*
+ * TTBCR
+ * We use long descriptors with inner-shareable WBWA tables and allocate
+ * the whole 32-bit VA space to TTBR0.
+ */
+ ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
+ IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+ IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+
+ /*
+ * MAIR0
+ * We need three attributes only, non-cacheable, write-back read/write
+ * allocate and device memory.
+ */
+ reg = (IMMAIR_ATTR_NC << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_NC))
+ | (IMMAIR_ATTR_WBRWA << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_WBRWA))
+ | (IMMAIR_ATTR_DEVICE << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_DEV));
+ ipmmu_ctx_write(domain, IMMAIR0, reg);
+
+ /* IMBUSCR */
+ ipmmu_ctx_write(domain, IMBUSCR,
+ ipmmu_ctx_read(domain, IMBUSCR) &
+ ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+
+ /*
+ * IMSTR
+ * Clear all interrupt flags.
+ */
+ ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+
+ /*
+ * IMCTR
+ * Enable the MMU and interrupt generation. The long-descriptor
+ * translation table format doesn't use TEX remapping. Don't enable AF
+ * software management as we have no use for it. Flush the TLB as
+ * required when modifying the context registers.
+ */
+ ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+
+ return 0;
+}
+
+static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
+{
+ /*
+ * Disable the context. Flush the TLB as required when modifying the
+ * context registers.
+ *
+ * TODO: Is TLB flush really needed ?
+ */
+ ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
+ ipmmu_tlb_sync(domain);
+}
+
+/* -----------------------------------------------------------------------------
+ * Fault Handling
+ */
+
+static irqreturn_t ipmmu_domain_irq(struct ipmmu_vmsa_domain *domain)
+{
+ const u32 err_mask = IMSTR_MHIT | IMSTR_ABORT | IMSTR_PF | IMSTR_TF;
+ struct ipmmu_vmsa_device *mmu = domain->mmu;
+ u32 status;
+ u32 iova;
+
+ status = ipmmu_ctx_read(domain, IMSTR);
+ if (!(status & err_mask))
+ return IRQ_NONE;
+
+ iova = ipmmu_ctx_read(domain, IMEAR);
+
+ /*
+ * Clear the error status flags. Unlike traditional interrupt flag
+ * registers that must be cleared by writing 1, this status register
+ * seems to require 0. The error address register must be read before,
+ * otherwise its value will be 0.
+ */
+ ipmmu_ctx_write(domain, IMSTR, 0);
+
+ /* Log fatal errors. */
+ if (status & IMSTR_MHIT)
+ dev_err_ratelimited(mmu->dev, "Multiple TLB hits @0x%08x\n",
+ iova);
+ if (status & IMSTR_ABORT)
+ dev_err_ratelimited(mmu->dev, "Page Table Walk Abort @0x%08x\n",
+ iova);
+
+ if (!(status & (IMSTR_PF | IMSTR_TF)))
+ return IRQ_NONE;
+
+ /*
+ * Try to handle page faults and translation faults.
+ *
+ * TODO: We need to look up the faulty device based on the I/O VA. Use
+ * the IOMMU device for now.
+ */
+ if (!report_iommu_fault(domain->io_domain, mmu->dev, iova, 0))
+ return IRQ_HANDLED;
+
+ dev_err_ratelimited(mmu->dev,
+ "Unhandled fault: status 0x%08x iova 0x%08x\n",
+ status, iova);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ipmmu_irq(int irq, void *dev)
+{
+ struct ipmmu_vmsa_device *mmu = dev;
+ struct iommu_domain *io_domain;
+ struct ipmmu_vmsa_domain *domain;
+
+ if (!mmu->mapping)
+ return IRQ_NONE;
+
+ io_domain = mmu->mapping->domain;
+ domain = io_domain->priv;
+
+ return ipmmu_domain_irq(domain);
+}
+
+/* -----------------------------------------------------------------------------
+ * Page Table Management
+ */
+
+#define pud_pgtable(pud) pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK))
+
+static void ipmmu_free_ptes(pmd_t *pmd)
+{
+ pgtable_t table = pmd_pgtable(*pmd);
+ __free_page(table);
+}
+
+static void ipmmu_free_pmds(pud_t *pud)
+{
+ pmd_t *pmd = pmd_offset(pud, 0);
+ pgtable_t table;
+ unsigned int i;
+
+ for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) {
+ if (!pmd_table(*pmd))
+ continue;
+
+ ipmmu_free_ptes(pmd);
+ pmd++;
+ }
+
+ table = pud_pgtable(*pud);
+ __free_page(table);
+}
+
+static void ipmmu_free_pgtables(struct ipmmu_vmsa_domain *domain)
+{
+ pgd_t *pgd, *pgd_base = domain->pgd;
+ unsigned int i;
+
+ /*
+ * Recursively free the page tables for this domain. We don't care about
+ * speculative TLB filling, because the TLB will be nuked next time this
+ * context bank is re-allocated and no devices currently map to these
+ * tables.
+ */
+ pgd = pgd_base;
+ for (i = 0; i < IPMMU_PTRS_PER_PGD; ++i) {
+ if (pgd_none(*pgd))
+ continue;
+ ipmmu_free_pmds((pud_t *)pgd);
+ pgd++;
+ }
+
+ kfree(pgd_base);
+}
+
+/*
+ * We can't use the (pgd|pud|pmd|pte)_populate or the set_(pgd|pud|pmd|pte)
+ * functions as they would flush the CPU TLB.
+ */
+
+static pte_t *ipmmu_alloc_pte(struct ipmmu_vmsa_device *mmu, pmd_t *pmd,
+ unsigned long iova)
+{
+ pte_t *pte;
+
+ if (!pmd_none(*pmd))
+ return pte_offset_kernel(pmd, iova);
+
+ pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
+ if (!pte)
+ return NULL;
+
+ ipmmu_flush_pgtable(mmu, pte, PAGE_SIZE);
+ *pmd = __pmd(__pa(pte) | PMD_NSTABLE | PMD_TYPE_TABLE);
+ ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd));
+
+ return pte + pte_index(iova);
+}
+
+static pmd_t *ipmmu_alloc_pmd(struct ipmmu_vmsa_device *mmu, pgd_t *pgd,
+ unsigned long iova)
+{
+ pud_t *pud = (pud_t *)pgd;
+ pmd_t *pmd;
+
+ if (!pud_none(*pud))
+ return pmd_offset(pud, iova);
+
+ pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
+ if (!pmd)
+ return NULL;
+
+ ipmmu_flush_pgtable(mmu, pmd, PAGE_SIZE);
+ *pud = __pud(__pa(pmd) | PMD_NSTABLE | PMD_TYPE_TABLE);
+ ipmmu_flush_pgtable(mmu, pud, sizeof(*pud));
+
+ return pmd + pmd_index(iova);
+}
+
+static u64 ipmmu_page_prot(unsigned int prot, u64 type)
+{
+ u64 pgprot = ARM_VMSA_PTE_XN | ARM_VMSA_PTE_nG | ARM_VMSA_PTE_AF
+ | ARM_VMSA_PTE_SH_IS | ARM_VMSA_PTE_AP_UNPRIV
+ | ARM_VMSA_PTE_NS | type;
+
+ if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
+ pgprot |= ARM_VMSA_PTE_AP_RDONLY;
+
+ if (prot & IOMMU_CACHE)
+ pgprot |= IMMAIR_ATTR_IDX_WBRWA << ARM_VMSA_PTE_ATTRINDX_SHIFT;
+
+ if (prot & IOMMU_EXEC)
+ pgprot &= ~ARM_VMSA_PTE_XN;
+ else if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
+ /* If no access create a faulting entry to avoid TLB fills. */
+ pgprot &= ~ARM_VMSA_PTE_PAGE;
+
+ return pgprot;
+}
+
+static int ipmmu_alloc_init_pte(struct ipmmu_vmsa_device *mmu, pmd_t *pmd,
+ unsigned long iova, unsigned long pfn,
+ size_t size, int prot)
+{
+ pteval_t pteval = ipmmu_page_prot(prot, ARM_VMSA_PTE_PAGE);
+ unsigned int num_ptes = 1;
+ pte_t *pte, *start;
+ unsigned int i;
+
+ pte = ipmmu_alloc_pte(mmu, pmd, iova);
+ if (!pte)
+ return -ENOMEM;
+
+ start = pte;
+
+ /*
+ * Install the page table entries. We can be called both for a single
+ * page or for a block of 16 physically contiguous pages. In the latter
+ * case set the PTE contiguous hint.
+ */
+ if (size == SZ_64K) {
+ pteval |= ARM_VMSA_PTE_CONT;
+ num_ptes = ARM_VMSA_PTE_CONT_ENTRIES;
+ }
+
+ for (i = num_ptes; i; --i)
+ *pte++ = pfn_pte(pfn++, __pgprot(pteval));
+
+ ipmmu_flush_pgtable(mmu, start, sizeof(*pte) * num_ptes);
+
+ return 0;
+}
+
+static int ipmmu_alloc_init_pmd(struct ipmmu_vmsa_device *mmu, pmd_t *pmd,
+ unsigned long iova, unsigned long pfn,
+ int prot)
+{
+ pmdval_t pmdval = ipmmu_page_prot(prot, PMD_TYPE_SECT);
+
+ *pmd = pfn_pmd(pfn, __pgprot(pmdval));
+ ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd));
+
+ return 0;
+}
+
+static int ipmmu_create_mapping(struct ipmmu_vmsa_domain *domain,
+ unsigned long iova, phys_addr_t paddr,
+ size_t size, int prot)
+{
+ struct ipmmu_vmsa_device *mmu = domain->mmu;
+ pgd_t *pgd = domain->pgd;
+ unsigned long flags;
+ unsigned long pfn;
+ pmd_t *pmd;
+ int ret;
+
+ if (!pgd)
+ return -EINVAL;
+
+ if (size & ~PAGE_MASK)
+ return -EINVAL;
+
+ if (paddr & ~((1ULL << 40) - 1))
+ return -ERANGE;
+
+ pfn = __phys_to_pfn(paddr);
+ pgd += pgd_index(iova);
+
+ /* Update the page tables. */
+ spin_lock_irqsave(&domain->lock, flags);
+
+ pmd = ipmmu_alloc_pmd(mmu, pgd, iova);
+ if (!pmd) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ switch (size) {
+ case SZ_2M:
+ ret = ipmmu_alloc_init_pmd(mmu, pmd, iova, pfn, prot);
+ break;
+ case SZ_64K:
+ case SZ_4K:
+ ret = ipmmu_alloc_init_pte(mmu, pmd, iova, pfn, size, prot);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+done:
+ spin_unlock_irqrestore(&domain->lock, flags);
+
+ if (!ret)
+ ipmmu_tlb_invalidate(domain);
+
+ return ret;
+}
+
+static void ipmmu_clear_pud(struct ipmmu_vmsa_device *mmu, pud_t *pud)
+{
+ /* Free the page table. */
+ pgtable_t table = pud_pgtable(*pud);
+ __free_page(table);
+
+ /* Clear the PUD. */
+ *pud = __pud(0);
+ ipmmu_flush_pgtable(mmu, pud, sizeof(*pud));
+}
+
+static void ipmmu_clear_pmd(struct ipmmu_vmsa_device *mmu, pud_t *pud,
+ pmd_t *pmd)
+{
+ unsigned int i;
+
+ /* Free the page table. */
+ if (pmd_table(*pmd)) {
+ pgtable_t table = pmd_pgtable(*pmd);
+ __free_page(table);
+ }
+
+ /* Clear the PMD. */
+ *pmd = __pmd(0);
+ ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd));
+
+ /* Check whether the PUD is still needed. */
+ pmd = pmd_offset(pud, 0);
+ for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) {
+ if (!pmd_none(pmd[i]))
+ return;
+ }
+
+ /* Clear the parent PUD. */
+ ipmmu_clear_pud(mmu, pud);
+}
+
+static void ipmmu_clear_pte(struct ipmmu_vmsa_device *mmu, pud_t *pud,
+ pmd_t *pmd, pte_t *pte, unsigned int num_ptes)
+{
+ unsigned int i;
+
+ /* Clear the PTE. */
+ for (i = num_ptes; i; --i)
+ pte[i-1] = __pte(0);
+
+ ipmmu_flush_pgtable(mmu, pte, sizeof(*pte) * num_ptes);
+
+ /* Check whether the PMD is still needed. */
+ pte = pte_offset_kernel(pmd, 0);
+ for (i = 0; i < IPMMU_PTRS_PER_PTE; ++i) {
+ if (!pte_none(pte[i]))
+ return;
+ }
+
+ /* Clear the parent PMD. */
+ ipmmu_clear_pmd(mmu, pud, pmd);
+}
+
+static int ipmmu_split_pmd(struct ipmmu_vmsa_device *mmu, pmd_t *pmd)
+{
+ pte_t *pte, *start;
+ pteval_t pteval;
+ unsigned long pfn;
+ unsigned int i;
+
+ pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
+ if (!pte)
+ return -ENOMEM;
+
+ /* Copy the PMD attributes. */
+ pteval = (pmd_val(*pmd) & ARM_VMSA_PTE_ATTRS_MASK)
+ | ARM_VMSA_PTE_CONT | ARM_VMSA_PTE_PAGE;
+
+ pfn = pmd_pfn(*pmd);
+ start = pte;
+
+ for (i = IPMMU_PTRS_PER_PTE; i; --i)
+ *pte++ = pfn_pte(pfn++, __pgprot(pteval));
+
+ ipmmu_flush_pgtable(mmu, start, PAGE_SIZE);
+ *pmd = __pmd(__pa(start) | PMD_NSTABLE | PMD_TYPE_TABLE);
+ ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd));
+
+ return 0;
+}
+
+static void ipmmu_split_pte(struct ipmmu_vmsa_device *mmu, pte_t *pte)
+{
+ unsigned int i;
+
+ for (i = ARM_VMSA_PTE_CONT_ENTRIES; i; --i)
+ pte[i-1] = __pte(pte_val(*pte) & ~ARM_VMSA_PTE_CONT);
+
+ ipmmu_flush_pgtable(mmu, pte, sizeof(*pte) * ARM_VMSA_PTE_CONT_ENTRIES);
+}
+
+static int ipmmu_clear_mapping(struct ipmmu_vmsa_domain *domain,
+ unsigned long iova, size_t size)
+{
+ struct ipmmu_vmsa_device *mmu = domain->mmu;
+ unsigned long flags;
+ pgd_t *pgd = domain->pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ int ret = 0;
+
+ if (!pgd)
+ return -EINVAL;
+
+ if (size & ~PAGE_MASK)
+ return -EINVAL;
+
+ pgd += pgd_index(iova);
+ pud = (pud_t *)pgd;
+
+ spin_lock_irqsave(&domain->lock, flags);
+
+ /* If there's no PUD or PMD we're done. */
+ if (pud_none(*pud))
+ goto done;
+
+ pmd = pmd_offset(pud, iova);
+ if (pmd_none(*pmd))
+ goto done;
+
+ /*
+ * When freeing a 2MB block just clear the PMD. In the unlikely case the
+ * block is mapped as individual pages this will free the corresponding
+ * PTE page table.
+ */
+ if (size == SZ_2M) {
+ ipmmu_clear_pmd(mmu, pud, pmd);
+ goto done;
+ }
+
+ /*
+ * If the PMD has been mapped as a section remap it as pages to allow
+ * freeing individual pages.
+ */
+ if (pmd_sect(*pmd))
+ ipmmu_split_pmd(mmu, pmd);
+
+ pte = pte_offset_kernel(pmd, iova);
+
+ /*
+ * When freeing a 64kB block just clear the PTE entries. We don't have
+ * to care about the contiguous hint of the surrounding entries.
+ */
+ if (size == SZ_64K) {
+ ipmmu_clear_pte(mmu, pud, pmd, pte, ARM_VMSA_PTE_CONT_ENTRIES);
+ goto done;
+ }
+
+ /*
+ * If the PTE has been mapped with the contiguous hint set remap it and
+ * its surrounding PTEs to allow unmapping a single page.
+ */
+ if (pte_val(*pte) & ARM_VMSA_PTE_CONT)
+ ipmmu_split_pte(mmu, pte);
+
+ /* Clear the PTE. */
+ ipmmu_clear_pte(mmu, pud, pmd, pte, 1);
+
+done:
+ spin_unlock_irqrestore(&domain->lock, flags);
+
+ if (ret)
+ ipmmu_tlb_invalidate(domain);
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * IOMMU Operations
+ */
+
+static int ipmmu_domain_init(struct iommu_domain *io_domain)
+{
+ struct ipmmu_vmsa_domain *domain;
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return -ENOMEM;
+
+ spin_lock_init(&domain->lock);
+
+ domain->pgd = kzalloc(IPMMU_PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+ if (!domain->pgd) {
+ kfree(domain);
+ return -ENOMEM;
+ }
+
+ io_domain->priv = domain;
+ domain->io_domain = io_domain;
+
+ return 0;
+}
+
+static void ipmmu_domain_destroy(struct iommu_domain *io_domain)
+{
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+
+ /*
+ * Free the domain resources. We assume that all devices have already
+ * been detached.
+ */
+ ipmmu_domain_destroy_context(domain);
+ ipmmu_free_pgtables(domain);
+ kfree(domain);
+}
+
+static int ipmmu_attach_device(struct iommu_domain *io_domain,
+ struct device *dev)
+{
+ struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+ struct ipmmu_vmsa_device *mmu = archdata->mmu;
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!mmu) {
+ dev_err(dev, "Cannot attach to IPMMU\n");
+ return -ENXIO;
+ }
+
+ spin_lock_irqsave(&domain->lock, flags);
+
+ if (!domain->mmu) {
+ /* The domain hasn't been used yet, initialize it. */
+ domain->mmu = mmu;
+ ret = ipmmu_domain_init_context(domain);
+ } else if (domain->mmu != mmu) {
+ /*
+ * Something is wrong, we can't attach two devices using
+ * different IOMMUs to the same domain.
+ */
+ dev_err(dev, "Can't attach IPMMU %s to domain on IPMMU %s\n",
+ dev_name(mmu->dev), dev_name(domain->mmu->dev));
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&domain->lock, flags);
+
+ if (ret < 0)
+ return ret;
+
+ ipmmu_utlb_enable(domain, archdata->utlb);
+
+ return 0;
+}
+
+static void ipmmu_detach_device(struct iommu_domain *io_domain,
+ struct device *dev)
+{
+ struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+
+ ipmmu_utlb_disable(domain, archdata->utlb);
+
+ /*
+ * TODO: Optimize by disabling the context when no device is attached.
+ */
+}
+
+static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot)
+{
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+
+ if (!domain)
+ return -ENODEV;
+
+ return ipmmu_create_mapping(domain, iova, paddr, size, prot);
+}
+
+static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova,
+ size_t size)
+{
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+ int ret;
+
+ ret = ipmmu_clear_mapping(domain, iova, size);
+ return ret ? 0 : size;
+}
+
+static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain,
+ dma_addr_t iova)
+{
+ struct ipmmu_vmsa_domain *domain = io_domain->priv;
+ pgd_t pgd;
+ pud_t pud;
+ pmd_t pmd;
+ pte_t pte;
+
+ /* TODO: Is locking needed ? */
+
+ if (!domain->pgd)
+ return 0;
+
+ pgd = *(domain->pgd + pgd_index(iova));
+ if (pgd_none(pgd))
+ return 0;
+
+ pud = *pud_offset(&pgd, iova);
+ if (pud_none(pud))
+ return 0;
+
+ pmd = *pmd_offset(&pud, iova);
+ if (pmd_none(pmd))
+ return 0;
+
+ if (pmd_sect(pmd))
+ return __pfn_to_phys(pmd_pfn(pmd)) | (iova & ~PMD_MASK);
+
+ pte = *(pmd_page_vaddr(pmd) + pte_index(iova));
+ if (pte_none(pte))
+ return 0;
+
+ return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
+}
+
+static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev)
+{
+ const struct ipmmu_vmsa_master *master = mmu->pdata->masters;
+ const char *devname = dev_name(dev);
+ unsigned int i;
+
+ for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) {
+ if (strcmp(master->name, devname) == 0)
+ return master->utlb;
+ }
+
+ return -1;
+}
+
+static int ipmmu_add_device(struct device *dev)
+{
+ struct ipmmu_vmsa_archdata *archdata;
+ struct ipmmu_vmsa_device *mmu;
+ struct iommu_group *group;
+ int utlb = -1;
+ int ret;
+
+ if (dev->archdata.iommu) {
+ dev_warn(dev, "IOMMU driver already assigned to device %s\n",
+ dev_name(dev));
+ return -EINVAL;
+ }
+
+ /* Find the master corresponding to the device. */
+ spin_lock(&ipmmu_devices_lock);
+
+ list_for_each_entry(mmu, &ipmmu_devices, list) {
+ utlb = ipmmu_find_utlb(mmu, dev);
+ if (utlb >= 0) {
+ /*
+ * TODO Take a reference to the MMU to protect
+ * against device removal.
+ */
+ break;
+ }
+ }
+
+ spin_unlock(&ipmmu_devices_lock);
+
+ if (utlb < 0)
+ return -ENODEV;
+
+ if (utlb >= mmu->num_utlbs)
+ return -EINVAL;
+
+ /* Create a device group and add the device to it. */
+ group = iommu_group_alloc();
+ if (IS_ERR(group)) {
+ dev_err(dev, "Failed to allocate IOMMU group\n");
+ return PTR_ERR(group);
+ }
+
+ ret = iommu_group_add_device(group, dev);
+ iommu_group_put(group);
+
+ if (ret < 0) {
+ dev_err(dev, "Failed to add device to IPMMU group\n");
+ return ret;
+ }
+
+ archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
+ if (!archdata) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ archdata->mmu = mmu;
+ archdata->utlb = utlb;
+ dev->archdata.iommu = archdata;
+
+ /*
+ * Create the ARM mapping, used by the ARM DMA mapping core to allocate
+ * VAs. This will allocate a corresponding IOMMU domain.
+ *
+ * TODO:
+ * - Create one mapping per context (TLB).
+ * - Make the mapping size configurable ? We currently use a 2GB mapping
+ * at a 1GB offset to ensure that NULL VAs will fault.
+ */
+ if (!mmu->mapping) {
+ struct dma_iommu_mapping *mapping;
+
+ mapping = arm_iommu_create_mapping(&platform_bus_type,
+ SZ_1G, SZ_2G);
+ if (IS_ERR(mapping)) {
+ dev_err(mmu->dev, "failed to create ARM IOMMU mapping\n");
+ return PTR_ERR(mapping);
+ }
+
+ mmu->mapping = mapping;
+ }
+
+ /* Attach the ARM VA mapping to the device. */
+ ret = arm_iommu_attach_device(dev, mmu->mapping);
+ if (ret < 0) {
+ dev_err(dev, "Failed to attach device to VA mapping\n");
+ goto error;
+ }
+
+ return 0;
+
+error:
+ kfree(dev->archdata.iommu);
+ dev->archdata.iommu = NULL;
+ iommu_group_remove_device(dev);
+ return ret;
+}
+
+static void ipmmu_remove_device(struct device *dev)
+{
+ arm_iommu_detach_device(dev);
+ iommu_group_remove_device(dev);
+ kfree(dev->archdata.iommu);
+ dev->archdata.iommu = NULL;
+}
+
+static struct iommu_ops ipmmu_ops = {
+ .domain_init = ipmmu_domain_init,
+ .domain_destroy = ipmmu_domain_destroy,
+ .attach_dev = ipmmu_attach_device,
+ .detach_dev = ipmmu_detach_device,
+ .map = ipmmu_map,
+ .unmap = ipmmu_unmap,
+ .iova_to_phys = ipmmu_iova_to_phys,
+ .add_device = ipmmu_add_device,
+ .remove_device = ipmmu_remove_device,
+ .pgsize_bitmap = SZ_2M | SZ_64K | SZ_4K,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe/remove and init
+ */
+
+static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu)
+{
+ unsigned int i;
+
+ /* Disable all contexts. */
+ for (i = 0; i < 4; ++i)
+ ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
+}
+
+static int ipmmu_probe(struct platform_device *pdev)
+{
+ struct ipmmu_vmsa_device *mmu;
+ struct resource *res;
+ int irq;
+ int ret;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "missing platform data\n");
+ return -EINVAL;
+ }
+
+ mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL);
+ if (!mmu) {
+ dev_err(&pdev->dev, "cannot allocate device data\n");
+ return -ENOMEM;
+ }
+
+ mmu->dev = &pdev->dev;
+ mmu->pdata = pdev->dev.platform_data;
+ mmu->num_utlbs = 32;
+
+ /* Map I/O memory and request IRQ. */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mmu->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mmu->base))
+ return PTR_ERR(mmu->base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no IRQ found\n");
+ return irq;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0,
+ dev_name(&pdev->dev), mmu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ %d\n", irq);
+ return irq;
+ }
+
+ ipmmu_device_reset(mmu);
+
+ /*
+ * We can't create the ARM mapping here as it requires the bus to have
+ * an IOMMU, which only happens when bus_set_iommu() is called in
+ * ipmmu_init() after the probe function returns.
+ */
+
+ spin_lock(&ipmmu_devices_lock);
+ list_add(&mmu->list, &ipmmu_devices);
+ spin_unlock(&ipmmu_devices_lock);
+
+ platform_set_drvdata(pdev, mmu);
+
+ return 0;
+}
+
+static int ipmmu_remove(struct platform_device *pdev)
+{
+ struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev);
+
+ spin_lock(&ipmmu_devices_lock);
+ list_del(&mmu->list);
+ spin_unlock(&ipmmu_devices_lock);
+
+ arm_iommu_release_mapping(mmu->mapping);
+
+ ipmmu_device_reset(mmu);
+
+ return 0;
+}
+
+static struct platform_driver ipmmu_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "ipmmu-vmsa",
+ },
+ .probe = ipmmu_probe,
+ .remove = ipmmu_remove,
+};
+
+static int __init ipmmu_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&ipmmu_driver);
+ if (ret < 0)
+ return ret;
+
+ if (!iommu_present(&platform_bus_type))
+ bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+
+ return 0;
+}
+
+static void __exit ipmmu_exit(void)
+{
+ return platform_driver_unregister(&ipmmu_driver);
+}
+
+subsys_initcall(ipmmu_init);
+module_exit(ipmmu_exit);
+
+MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 08ba4972da9d..61def7cb5263 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -127,13 +127,12 @@ static void msm_iommu_reset(void __iomem *base, int ncb)
static int msm_iommu_probe(struct platform_device *pdev)
{
- struct resource *r, *r2;
+ struct resource *r;
struct clk *iommu_clk;
struct clk *iommu_pclk;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
void __iomem *regs_base;
- resource_size_t len;
int ret, irq, par;
if (pdev->id == -1) {
@@ -178,35 +177,16 @@ static int msm_iommu_probe(struct platform_device *pdev)
iommu_clk = NULL;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
-
- if (!r) {
- ret = -ENODEV;
- goto fail_clk;
- }
-
- len = resource_size(r);
-
- r2 = request_mem_region(r->start, len, r->name);
- if (!r2) {
- pr_err("Could not request memory region: start=%p, len=%d\n",
- (void *) r->start, len);
- ret = -EBUSY;
+ regs_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(regs_base)) {
+ ret = PTR_ERR(regs_base);
goto fail_clk;
}
- regs_base = ioremap(r2->start, len);
-
- if (!regs_base) {
- pr_err("Could not ioremap: start=%p, len=%d\n",
- (void *) r2->start, len);
- ret = -EBUSY;
- goto fail_mem;
- }
-
irq = platform_get_irq_byname(pdev, "secure_irq");
if (irq < 0) {
ret = -ENODEV;
- goto fail_io;
+ goto fail_clk;
}
msm_iommu_reset(regs_base, iommu_dev->ncb);
@@ -222,14 +202,14 @@ static int msm_iommu_probe(struct platform_device *pdev)
if (!par) {
pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
ret = -ENODEV;
- goto fail_io;
+ goto fail_clk;
}
ret = request_irq(irq, msm_iommu_fault_handler, 0,
"msm_iommu_secure_irpt_handler", drvdata);
if (ret) {
pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
- goto fail_io;
+ goto fail_clk;
}
@@ -250,10 +230,6 @@ static int msm_iommu_probe(struct platform_device *pdev)
clk_disable(iommu_pclk);
return 0;
-fail_io:
- iounmap(regs_base);
-fail_mem:
- release_mem_region(r->start, len);
fail_clk:
if (iommu_clk) {
clk_disable(iommu_clk);
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 7fcbfc498fa9..895af06a667f 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -34,6 +34,9 @@
#include "omap-iopgtable.h"
#include "omap-iommu.h"
+#define to_iommu(dev) \
+ ((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev)))
+
#define for_each_iotlb_cr(obj, n, __i, cr) \
for (__i = 0; \
(__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
@@ -391,6 +394,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da)
__func__, start, da, bytes);
iotlb_load_cr(obj, &cr);
iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
+ break;
}
}
pm_runtime_put_sync(obj->dev);
@@ -1037,19 +1041,18 @@ static void iopte_cachep_ctor(void *iopte)
clean_dcache_area(iopte, IOPTE_TABLE_SIZE);
}
-static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa,
- u32 flags)
+static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, int pgsz)
{
memset(e, 0, sizeof(*e));
e->da = da;
e->pa = pa;
- e->valid = 1;
+ e->valid = MMU_CAM_V;
/* FIXME: add OMAP1 support */
- e->pgsz = flags & MMU_CAM_PGSZ_MASK;
- e->endian = flags & MMU_RAM_ENDIAN_MASK;
- e->elsz = flags & MMU_RAM_ELSZ_MASK;
- e->mixed = flags & MMU_RAM_MIXED_MASK;
+ e->pgsz = pgsz;
+ e->endian = MMU_RAM_ENDIAN_LITTLE;
+ e->elsz = MMU_RAM_ELSZ_8;
+ e->mixed = 0;
return iopgsz_to_bytes(e->pgsz);
}
@@ -1062,9 +1065,8 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
struct device *dev = oiommu->dev;
struct iotlb_entry e;
int omap_pgsz;
- u32 ret, flags;
+ u32 ret;
- /* we only support mapping a single iommu page for now */
omap_pgsz = bytes_to_iopgsz(bytes);
if (omap_pgsz < 0) {
dev_err(dev, "invalid size to map: %d\n", bytes);
@@ -1073,9 +1075,7 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes);
- flags = omap_pgsz | prot;
-
- iotlb_init_entry(&e, da, pa, flags);
+ iotlb_init_entry(&e, da, pa, omap_pgsz);
ret = omap_iopgtable_store_entry(oiommu, &e);
if (ret)
@@ -1248,12 +1248,6 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
return ret;
}
-static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
- unsigned long cap)
-{
- return 0;
-}
-
static int omap_iommu_add_device(struct device *dev)
{
struct omap_iommu_arch_data *arch_data;
@@ -1305,7 +1299,6 @@ static struct iommu_ops omap_iommu_ops = {
.map = omap_iommu_map,
.unmap = omap_iommu_unmap,
.iova_to_phys = omap_iommu_iova_to_phys,
- .domain_has_cap = omap_iommu_domain_has_cap,
.add_device = omap_iommu_add_device,
.remove_device = omap_iommu_remove_device,
.pgsize_bitmap = OMAP_IOMMU_PGSIZES,
diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h
index b6f9a51746ca..f891683e3f05 100644
--- a/drivers/iommu/omap-iopgtable.h
+++ b/drivers/iommu/omap-iopgtable.h
@@ -93,6 +93,3 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask)
/* to find an entry in the second-level page table. */
#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1))
#define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da))
-
-#define to_iommu(dev) \
- (platform_get_drvdata(to_platform_device(dev)))
diff --git a/drivers/iommu/shmobile-ipmmu.c b/drivers/iommu/shmobile-ipmmu.c
index e3bc2e19b6dd..bd97adecb1fd 100644
--- a/drivers/iommu/shmobile-ipmmu.c
+++ b/drivers/iommu/shmobile-ipmmu.c
@@ -94,11 +94,6 @@ static int ipmmu_probe(struct platform_device *pdev)
struct resource *res;
struct shmobile_ipmmu_platform_data *pdata = pdev->dev.platform_data;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "cannot get platform resources\n");
- return -ENOENT;
- }
ipmmu = devm_kzalloc(&pdev->dev, sizeof(*ipmmu), GFP_KERNEL);
if (!ipmmu) {
dev_err(&pdev->dev, "cannot allocate device data\n");
@@ -106,19 +101,18 @@ static int ipmmu_probe(struct platform_device *pdev)
}
spin_lock_init(&ipmmu->flush_lock);
ipmmu->dev = &pdev->dev;
- ipmmu->ipmmu_base = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
- if (!ipmmu->ipmmu_base) {
- dev_err(&pdev->dev, "ioremap_nocache failed\n");
- return -ENOMEM;
- }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ipmmu->ipmmu_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ipmmu->ipmmu_base))
+ return PTR_ERR(ipmmu->ipmmu_base);
+
ipmmu->dev_names = pdata->dev_names;
ipmmu->num_dev_names = pdata->num_dev_names;
platform_set_drvdata(pdev, ipmmu);
ipmmu_reg_write(ipmmu, IMCTR1, 0x0); /* disable TLB */
ipmmu_reg_write(ipmmu, IMCTR2, 0x0); /* disable PMB */
- ipmmu_iommu_init(ipmmu);
- return 0;
+ return ipmmu_iommu_init(ipmmu);
}
static struct platform_driver ipmmu_driver = {
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 338baa4c23ef..1778d320272e 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -27,19 +27,21 @@
* REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
*/
-
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
+#include <linux/v4l2-dv-timings.h>
#include <linux/videodev2.h>
#include <linux/workqueue.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-device.h>
+
+#include <media/adv7604.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
#include <media/v4l2-dv-timings.h>
-#include <media/adv7604.h>
+#include <media/v4l2-of.h>
static int debug;
module_param(debug, int, 0644);
@@ -53,6 +55,76 @@ MODULE_LICENSE("GPL");
/* ADV7604 system clock frequency */
#define ADV7604_fsc (28636360)
+#define ADV7604_RGB_OUT (1 << 1)
+
+#define ADV7604_OP_FORMAT_SEL_8BIT (0 << 0)
+#define ADV7604_OP_FORMAT_SEL_10BIT (1 << 0)
+#define ADV7604_OP_FORMAT_SEL_12BIT (2 << 0)
+
+#define ADV7604_OP_MODE_SEL_SDR_422 (0 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_422 (1 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_444 (2 << 5)
+#define ADV7604_OP_MODE_SEL_DDR_444 (3 << 5)
+#define ADV7604_OP_MODE_SEL_SDR_422_2X (4 << 5)
+#define ADV7604_OP_MODE_SEL_ADI_CM (5 << 5)
+
+#define ADV7604_OP_CH_SEL_GBR (0 << 5)
+#define ADV7604_OP_CH_SEL_GRB (1 << 5)
+#define ADV7604_OP_CH_SEL_BGR (2 << 5)
+#define ADV7604_OP_CH_SEL_RGB (3 << 5)
+#define ADV7604_OP_CH_SEL_BRG (4 << 5)
+#define ADV7604_OP_CH_SEL_RBG (5 << 5)
+
+#define ADV7604_OP_SWAP_CB_CR (1 << 0)
+
+enum adv7604_type {
+ ADV7604,
+ ADV7611,
+};
+
+struct adv7604_reg_seq {
+ unsigned int reg;
+ u8 val;
+};
+
+struct adv7604_format_info {
+ enum v4l2_mbus_pixelcode code;
+ u8 op_ch_sel;
+ bool rgb_out;
+ bool swap_cb_cr;
+ u8 op_format_sel;
+};
+
+struct adv7604_chip_info {
+ enum adv7604_type type;
+
+ bool has_afe;
+ unsigned int max_port;
+ unsigned int num_dv_ports;
+
+ unsigned int edid_enable_reg;
+ unsigned int edid_status_reg;
+ unsigned int lcf_reg;
+
+ unsigned int cable_det_mask;
+ unsigned int tdms_lock_mask;
+ unsigned int fmt_change_digital_mask;
+
+ const struct adv7604_format_info *formats;
+ unsigned int nformats;
+
+ void (*set_termination)(struct v4l2_subdev *sd, bool enable);
+ void (*setup_irqs)(struct v4l2_subdev *sd);
+ unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd);
+ unsigned int (*read_cable_det)(struct v4l2_subdev *sd);
+
+ /* 0 = AFE, 1 = HDMI */
+ const struct adv7604_reg_seq *recommended_settings[2];
+ unsigned int num_recommended_settings[2];
+
+ unsigned long page_mask;
+};
+
/*
**********************************************************************
*
@@ -60,13 +132,24 @@ MODULE_LICENSE("GPL");
*
**********************************************************************
*/
+
struct adv7604_state {
+ const struct adv7604_chip_info *info;
struct adv7604_platform_data pdata;
+
+ struct gpio_desc *hpd_gpio[4];
+
struct v4l2_subdev sd;
- struct media_pad pad;
+ struct media_pad pads[ADV7604_PAD_MAX];
+ unsigned int source_pad;
+
struct v4l2_ctrl_handler hdl;
- enum adv7604_input_port selected_input;
+
+ enum adv7604_pad selected_input;
+
struct v4l2_dv_timings timings;
+ const struct adv7604_format_info *format;
+
struct {
u8 edid[256];
u32 present;
@@ -80,18 +163,7 @@ struct adv7604_state {
bool restart_stdi_once;
/* i2c clients */
- struct i2c_client *i2c_avlink;
- struct i2c_client *i2c_cec;
- struct i2c_client *i2c_infoframe;
- struct i2c_client *i2c_esdp;
- struct i2c_client *i2c_dpp;
- struct i2c_client *i2c_afe;
- struct i2c_client *i2c_repeater;
- struct i2c_client *i2c_edid;
- struct i2c_client *i2c_hdmi;
- struct i2c_client *i2c_test;
- struct i2c_client *i2c_cp;
- struct i2c_client *i2c_vdp;
+ struct i2c_client *i2c_clients[ADV7604_PAGE_MAX];
/* controls */
struct v4l2_ctrl *detect_tx_5v_ctrl;
@@ -101,6 +173,11 @@ struct adv7604_state {
struct v4l2_ctrl *rgb_quantization_range_ctrl;
};
+static bool adv7604_has_afe(struct adv7604_state *state)
+{
+ return state->info->has_afe;
+}
+
/* Supported CEA and DMT timings */
static const struct v4l2_dv_timings adv7604_timings[] = {
V4L2_DV_BT_CEA_720X480P59_94,
@@ -256,11 +333,6 @@ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
return container_of(sd, struct adv7604_state, sd);
}
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
- return &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
-}
-
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_BLANKING_WIDTH(t);
@@ -298,14 +370,18 @@ static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
return -EIO;
}
-static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command)
+static s32 adv_smbus_read_byte_data(struct adv7604_state *state,
+ enum adv7604_page page, u8 command)
{
- return adv_smbus_read_byte_data_check(client, command, true);
+ return adv_smbus_read_byte_data_check(state->i2c_clients[page],
+ command, true);
}
-static s32 adv_smbus_write_byte_data(struct i2c_client *client,
- u8 command, u8 value)
+static s32 adv_smbus_write_byte_data(struct adv7604_state *state,
+ enum adv7604_page page, u8 command,
+ u8 value)
{
+ struct i2c_client *client = state->i2c_clients[page];
union i2c_smbus_data data;
int err;
int i;
@@ -325,9 +401,11 @@ static s32 adv_smbus_write_byte_data(struct i2c_client *client,
return err;
}
-static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
- u8 command, unsigned length, const u8 *values)
+static s32 adv_smbus_write_i2c_block_data(struct adv7604_state *state,
+ enum adv7604_page page, u8 command,
+ unsigned length, const u8 *values)
{
+ struct i2c_client *client = state->i2c_clients[page];
union i2c_smbus_data data;
if (length > I2C_SMBUS_BLOCK_MAX)
@@ -343,149 +421,150 @@ static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
static inline int io_read(struct v4l2_subdev *sd, u8 reg)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(client, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_IO, reg);
}
static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(client, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_IO, reg, val);
}
-static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{
- return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
+ return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
}
static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_avlink, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_AVLINK, reg);
}
static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_avlink, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_AVLINK, reg, val);
}
static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_cec, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_CEC, reg);
}
static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
}
-static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cec_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{
- return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
+ return cec_write(sd, reg, (cec_read(sd, reg) & ~mask) | val);
}
static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_infoframe, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_INFOFRAME, reg);
}
static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_INFOFRAME,
+ reg, val);
}
static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_esdp, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_ESDP, reg);
}
static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_esdp, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_ESDP, reg, val);
}
static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_dpp, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_DPP, reg);
}
static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_dpp, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_DPP, reg, val);
}
static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_afe, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_AFE, reg);
}
static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_afe, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_AFE, reg, val);
}
static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_repeater, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_REP, reg);
}
static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_repeater, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_REP, reg, val);
}
-static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{
- return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val);
+ return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
}
static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_edid, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_EDID, reg);
}
static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_edid, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
}
static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
{
struct adv7604_state *state = to_state(sd);
- struct i2c_client *client = state->i2c_edid;
+ struct i2c_client *client = state->i2c_clients[ADV7604_PAGE_EDID];
u8 msgbuf0[1] = { 0 };
u8 msgbuf1[256];
struct i2c_msg msg[2] = {
@@ -518,11 +597,25 @@ static inline int edid_write_block(struct v4l2_subdev *sd,
v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
- err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
- I2C_SMBUS_BLOCK_MAX, val + i);
+ err = adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_EDID,
+ i, I2C_SMBUS_BLOCK_MAX, val + i);
return err;
}
+static void adv7604_set_hpd(struct adv7604_state *state, unsigned int hpd)
+{
+ unsigned int i;
+
+ for (i = 0; i < state->info->num_dv_ports; ++i) {
+ if (IS_ERR(state->hpd_gpio[i]))
+ continue;
+
+ gpiod_set_value_cansleep(state->hpd_gpio[i], hpd & BIT(i));
+ }
+
+ v4l2_subdev_notify(&state->sd, ADV7604_HOTPLUG, &hpd);
+}
+
static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -532,73 +625,210 @@ static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
+ adv7604_set_hpd(state, state->edid.present);
}
static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_hdmi, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_HDMI, reg);
+}
+
+static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
+{
+ return ((hdmi_read(sd, reg) << 8) | hdmi_read(sd, reg + 1)) & mask;
}
static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_HDMI, reg, val);
}
-static inline int hdmi_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{
- return hdmi_write(sd, reg, (hdmi_read(sd, reg) & mask) | val);
+ return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
}
static inline int test_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_test, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_TEST, reg);
}
static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_test, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_TEST, reg, val);
}
static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_cp, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_CP, reg);
+}
+
+static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
+{
+ return ((cp_read(sd, reg) << 8) | cp_read(sd, reg + 1)) & mask;
}
static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_cp, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_CP, reg, val);
}
-static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
{
- return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val);
+ return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
}
static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_read_byte_data(state->i2c_vdp, reg);
+ return adv_smbus_read_byte_data(state, ADV7604_PAGE_VDP, reg);
}
static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7604_state *state = to_state(sd);
- return adv_smbus_write_byte_data(state->i2c_vdp, reg, val);
+ return adv_smbus_write_byte_data(state, ADV7604_PAGE_VDP, reg, val);
+}
+
+#define ADV7604_REG(page, offset) (((page) << 8) | (offset))
+#define ADV7604_REG_SEQ_TERM 0xffff
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg)
+{
+ struct adv7604_state *state = to_state(sd);
+ unsigned int page = reg >> 8;
+
+ if (!(BIT(page) & state->info->page_mask))
+ return -EINVAL;
+
+ reg &= 0xff;
+
+ return adv_smbus_read_byte_data(state, page, reg);
+}
+#endif
+
+static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
+{
+ struct adv7604_state *state = to_state(sd);
+ unsigned int page = reg >> 8;
+
+ if (!(BIT(page) & state->info->page_mask))
+ return -EINVAL;
+
+ reg &= 0xff;
+
+ return adv_smbus_write_byte_data(state, page, reg, val);
+}
+
+static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
+ const struct adv7604_reg_seq *reg_seq)
+{
+ unsigned int i;
+
+ for (i = 0; reg_seq[i].reg != ADV7604_REG_SEQ_TERM; i++)
+ adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
+}
+
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static const struct adv7604_format_info adv7604_formats[] = {
+ { V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+ ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+ { V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info adv7611_formats[] = {
+ { V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+ ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
+ { V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+ { V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+ ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+};
+
+static const struct adv7604_format_info *
+adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
+{
+ unsigned int i;
+
+ for (i = 0; i < state->info->nformats; ++i) {
+ if (state->info->formats[i].code == code)
+ return &state->info->formats[i];
+ }
+
+ return NULL;
}
/* ----------------------------------------------------------------------- */
@@ -607,18 +837,18 @@ static inline bool is_analog_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
- return state->selected_input == ADV7604_INPUT_VGA_RGB ||
- state->selected_input == ADV7604_INPUT_VGA_COMP;
+ return state->selected_input == ADV7604_PAD_VGA_RGB ||
+ state->selected_input == ADV7604_PAD_VGA_COMP;
}
static inline bool is_digital_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
- return state->selected_input == ADV7604_INPUT_HDMI_PORT_A ||
- state->selected_input == ADV7604_INPUT_HDMI_PORT_B ||
- state->selected_input == ADV7604_INPUT_HDMI_PORT_C ||
- state->selected_input == ADV7604_INPUT_HDMI_PORT_D;
+ return state->selected_input == ADV7604_PAD_HDMI_PORT_A ||
+ state->selected_input == ADV7604_PAD_HDMI_PORT_B ||
+ state->selected_input == ADV7604_PAD_HDMI_PORT_C ||
+ state->selected_input == ADV7604_PAD_HDMI_PORT_D;
}
/* ----------------------------------------------------------------------- */
@@ -644,119 +874,61 @@ static void adv7604_inv_register(struct v4l2_subdev *sd)
static int adv7604_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
{
- reg->size = 1;
- switch (reg->reg >> 8) {
- case 0:
- reg->val = io_read(sd, reg->reg & 0xff);
- break;
- case 1:
- reg->val = avlink_read(sd, reg->reg & 0xff);
- break;
- case 2:
- reg->val = cec_read(sd, reg->reg & 0xff);
- break;
- case 3:
- reg->val = infoframe_read(sd, reg->reg & 0xff);
- break;
- case 4:
- reg->val = esdp_read(sd, reg->reg & 0xff);
- break;
- case 5:
- reg->val = dpp_read(sd, reg->reg & 0xff);
- break;
- case 6:
- reg->val = afe_read(sd, reg->reg & 0xff);
- break;
- case 7:
- reg->val = rep_read(sd, reg->reg & 0xff);
- break;
- case 8:
- reg->val = edid_read(sd, reg->reg & 0xff);
- break;
- case 9:
- reg->val = hdmi_read(sd, reg->reg & 0xff);
- break;
- case 0xa:
- reg->val = test_read(sd, reg->reg & 0xff);
- break;
- case 0xb:
- reg->val = cp_read(sd, reg->reg & 0xff);
- break;
- case 0xc:
- reg->val = vdp_read(sd, reg->reg & 0xff);
- break;
- default:
+ int ret;
+
+ ret = adv7604_read_reg(sd, reg->reg);
+ if (ret < 0) {
v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
adv7604_inv_register(sd);
- break;
+ return ret;
}
+
+ reg->size = 1;
+ reg->val = ret;
+
return 0;
}
static int adv7604_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg)
{
- u8 val = reg->val & 0xff;
+ int ret;
- switch (reg->reg >> 8) {
- case 0:
- io_write(sd, reg->reg & 0xff, val);
- break;
- case 1:
- avlink_write(sd, reg->reg & 0xff, val);
- break;
- case 2:
- cec_write(sd, reg->reg & 0xff, val);
- break;
- case 3:
- infoframe_write(sd, reg->reg & 0xff, val);
- break;
- case 4:
- esdp_write(sd, reg->reg & 0xff, val);
- break;
- case 5:
- dpp_write(sd, reg->reg & 0xff, val);
- break;
- case 6:
- afe_write(sd, reg->reg & 0xff, val);
- break;
- case 7:
- rep_write(sd, reg->reg & 0xff, val);
- break;
- case 8:
- edid_write(sd, reg->reg & 0xff, val);
- break;
- case 9:
- hdmi_write(sd, reg->reg & 0xff, val);
- break;
- case 0xa:
- test_write(sd, reg->reg & 0xff, val);
- break;
- case 0xb:
- cp_write(sd, reg->reg & 0xff, val);
- break;
- case 0xc:
- vdp_write(sd, reg->reg & 0xff, val);
- break;
- default:
+ ret = adv7604_write_reg(sd, reg->reg, reg->val);
+ if (ret < 0) {
v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
adv7604_inv_register(sd);
- break;
+ return ret;
}
+
return 0;
}
#endif
+static unsigned int adv7604_read_cable_det(struct v4l2_subdev *sd)
+{
+ u8 value = io_read(sd, 0x6f);
+
+ return ((value & 0x10) >> 4)
+ | ((value & 0x08) >> 2)
+ | ((value & 0x04) << 0)
+ | ((value & 0x02) << 2);
+}
+
+static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd)
+{
+ u8 value = io_read(sd, 0x6f);
+
+ return value & 1;
+}
+
static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
- u8 reg_io_6f = io_read(sd, 0x6f);
+ const struct adv7604_chip_info *info = state->info;
return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
- ((reg_io_6f & 0x10) >> 4) |
- ((reg_io_6f & 0x08) >> 2) |
- (reg_io_6f & 0x04) |
- ((reg_io_6f & 0x02) << 2));
+ info->read_cable_det(sd));
}
static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
@@ -787,11 +959,13 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
v4l2_dbg(1, debug, sd, "%s", __func__);
- /* reset to default values */
- io_write(sd, 0x16, 0x43);
- io_write(sd, 0x17, 0x5a);
+ if (adv7604_has_afe(state)) {
+ /* reset to default values */
+ io_write(sd, 0x16, 0x43);
+ io_write(sd, 0x17, 0x5a);
+ }
/* disable embedded syncs for auto graphics mode */
- cp_write_and_or(sd, 0x81, 0xef, 0x00);
+ cp_write_clr_set(sd, 0x81, 0x10, 0x00);
cp_write(sd, 0x8f, 0x00);
cp_write(sd, 0x90, 0x00);
cp_write(sd, 0xa2, 0x00);
@@ -829,7 +1003,6 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
const struct v4l2_bt_timings *bt)
{
struct adv7604_state *state = to_state(sd);
- struct i2c_client *client = v4l2_get_subdevdata(sd);
u32 width = htotal(bt);
u32 height = vtotal(bt);
u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
@@ -850,12 +1023,13 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
io_write(sd, 0x00, 0x07); /* video std */
io_write(sd, 0x01, 0x02); /* prim mode */
/* enable embedded syncs for auto graphics mode */
- cp_write_and_or(sd, 0x81, 0xef, 0x10);
+ cp_write_clr_set(sd, 0x81, 0x10, 0x10);
/* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
/* IO-map reg. 0x16 and 0x17 should be written in sequence */
- if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll))
+ if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_IO,
+ 0x16, 2, pll))
v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
/* active video - horizontal timing */
@@ -906,7 +1080,8 @@ static void adv7604_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 off
offset_buf[3] = offset_c & 0x0ff;
/* Registers must be written in this order with no i2c access in between */
- if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x77, 4, offset_buf))
+ if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+ 0x77, 4, offset_buf))
v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
}
@@ -935,7 +1110,8 @@ static void adv7604_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a,
gain_buf[3] = ((gain_c & 0x0ff));
/* Registers must be written in this order with no i2c access in between */
- if (adv_smbus_write_i2c_block_data(state->i2c_cp, 0x73, 4, gain_buf))
+ if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+ 0x73, 4, gain_buf))
v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
}
@@ -954,24 +1130,24 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
switch (state->rgb_quantization_range) {
case V4L2_DV_RGB_RANGE_AUTO:
- if (state->selected_input == ADV7604_INPUT_VGA_RGB) {
+ if (state->selected_input == ADV7604_PAD_VGA_RGB) {
/* Receiving analog RGB signal
* Set RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x10);
break;
}
- if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ if (state->selected_input == ADV7604_PAD_VGA_COMP) {
/* Receiving analog YPbPr signal
* Set automode */
- io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+ io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
break;
}
if (hdmi_signal) {
/* Receiving HDMI signal
* Set automode */
- io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+ io_write_clr_set(sd, 0x02, 0xf0, 0xf0);
break;
}
@@ -980,10 +1156,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
* input format (CE/IT) in automatic mode */
if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
/* RGB limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x00);
} else {
/* RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x10);
if (is_digital_input(sd) && rgb_output) {
adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
@@ -994,25 +1170,25 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
}
break;
case V4L2_DV_RGB_RANGE_LIMITED:
- if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ if (state->selected_input == ADV7604_PAD_VGA_COMP) {
/* YCrCb limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x20);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x20);
break;
}
/* RGB limited range (16-235) */
- io_write_and_or(sd, 0x02, 0x0f, 0x00);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x00);
break;
case V4L2_DV_RGB_RANGE_FULL:
- if (state->selected_input == ADV7604_INPUT_VGA_COMP) {
+ if (state->selected_input == ADV7604_PAD_VGA_COMP) {
/* YCrCb full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x60);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x60);
break;
}
/* RGB full range (0-255) */
- io_write_and_or(sd, 0x02, 0x0f, 0x10);
+ io_write_clr_set(sd, 0x02, 0xf0, 0x10);
if (is_analog_input(sd) || hdmi_signal)
break;
@@ -1030,7 +1206,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct v4l2_subdev *sd = to_sd(ctrl);
+ struct v4l2_subdev *sd =
+ &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
+
struct adv7604_state *state = to_state(sd);
switch (ctrl->id) {
@@ -1051,6 +1229,8 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
set_rgb_quantization_range(sd);
return 0;
case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
+ if (!adv7604_has_afe(state))
+ return -EINVAL;
/* Set the analog sampling phase. This is needed to find the
best sampling phase for analog video: an application or
driver has to try a number of phases and analyze the picture
@@ -1060,7 +1240,7 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
/* Use the default blue color for free running mode,
or supply your own. */
- cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2));
+ cp_write_clr_set(sd, 0xbf, 0x04, ctrl->val << 2);
return 0;
case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
@@ -1088,7 +1268,10 @@ static inline bool no_signal_tmds(struct v4l2_subdev *sd)
static inline bool no_lock_tmds(struct v4l2_subdev *sd)
{
- return (io_read(sd, 0x6a) & 0xe0) != 0xe0;
+ struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
+
+ return (io_read(sd, 0x6a) & info->tdms_lock_mask) != info->tdms_lock_mask;
}
static inline bool is_hdmi(struct v4l2_subdev *sd)
@@ -1098,6 +1281,15 @@ static inline bool is_hdmi(struct v4l2_subdev *sd)
static inline bool no_lock_sspd(struct v4l2_subdev *sd)
{
+ struct adv7604_state *state = to_state(sd);
+
+ /*
+ * Chips without a AFE don't expose registers for the SSPD, so just assume
+ * that we have a lock.
+ */
+ if (adv7604_has_afe(state))
+ return false;
+
/* TODO channel 2 */
return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0);
}
@@ -1127,6 +1319,11 @@ static inline bool no_signal(struct v4l2_subdev *sd)
static inline bool no_lock_cp(struct v4l2_subdev *sd)
{
+ struct adv7604_state *state = to_state(sd);
+
+ if (!adv7604_has_afe(state))
+ return false;
+
/* CP has detected a non standard number of lines on the incoming
video compared to what it is configured to receive by s_dv_timings */
return io_read(sd, 0x12) & 0x01;
@@ -1195,28 +1392,40 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
return -1;
}
+
static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
{
+ struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
+ u8 polarity;
+
if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__);
return -1;
}
/* read STDI */
- stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
- stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
+ stdi->bl = cp_read16(sd, 0xb1, 0x3fff);
+ stdi->lcf = cp_read16(sd, info->lcf_reg, 0x7ff);
stdi->lcvs = cp_read(sd, 0xb3) >> 3;
stdi->interlaced = io_read(sd, 0x12) & 0x10;
- /* read SSPD */
- if ((cp_read(sd, 0xb5) & 0x03) == 0x01) {
- stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ?
- ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x');
- stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ?
- ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x');
+ if (adv7604_has_afe(state)) {
+ /* read SSPD */
+ polarity = cp_read(sd, 0xb5);
+ if ((polarity & 0x03) == 0x01) {
+ stdi->hs_pol = polarity & 0x10
+ ? (polarity & 0x08 ? '+' : '-') : 'x';
+ stdi->vs_pol = polarity & 0x40
+ ? (polarity & 0x20 ? '+' : '-') : 'x';
+ } else {
+ stdi->hs_pol = 'x';
+ stdi->vs_pol = 'x';
+ }
} else {
- stdi->hs_pol = 'x';
- stdi->vs_pol = 'x';
+ polarity = hdmi_read(sd, 0x05);
+ stdi->hs_pol = polarity & 0x20 ? '+' : '-';
+ stdi->vs_pol = polarity & 0x10 ? '+' : '-';
}
if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
@@ -1243,8 +1452,14 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
struct v4l2_enum_dv_timings *timings)
{
+ struct adv7604_state *state = to_state(sd);
+
if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1)
return -EINVAL;
+
+ if (timings->pad >= state->source_pad)
+ return -EINVAL;
+
memset(timings->reserved, 0, sizeof(timings->reserved));
timings->timings = adv7604_timings[timings->index];
return 0;
@@ -1253,14 +1468,30 @@ static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
struct v4l2_dv_timings_cap *cap)
{
+ struct adv7604_state *state = to_state(sd);
+
+ if (cap->pad >= state->source_pad)
+ return -EINVAL;
+
cap->type = V4L2_DV_BT_656_1120;
cap->bt.max_width = 1920;
cap->bt.max_height = 1200;
cap->bt.min_pixelclock = 25000000;
- if (is_digital_input(sd))
+
+ switch (cap->pad) {
+ case ADV7604_PAD_HDMI_PORT_A:
+ case ADV7604_PAD_HDMI_PORT_B:
+ case ADV7604_PAD_HDMI_PORT_C:
+ case ADV7604_PAD_HDMI_PORT_D:
cap->bt.max_pixelclock = 225000000;
- else
+ break;
+ case ADV7604_PAD_VGA_RGB:
+ case ADV7604_PAD_VGA_COMP:
+ default:
cap->bt.max_pixelclock = 170000000;
+ break;
+ }
+
cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
@@ -1284,10 +1515,43 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
}
}
+static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd)
+{
+ unsigned int freq;
+ int a, b;
+
+ a = hdmi_read(sd, 0x06);
+ b = hdmi_read(sd, 0x3b);
+ if (a < 0 || b < 0)
+ return 0;
+ freq = a * 1000000 + ((b & 0x30) >> 4) * 250000;
+
+ if (is_hdmi(sd)) {
+ /* adjust for deep color mode */
+ unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
+
+ freq = freq * 8 / bits_per_channel;
+ }
+
+ return freq;
+}
+
+static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd)
+{
+ int a, b;
+
+ a = hdmi_read(sd, 0x51);
+ b = hdmi_read(sd, 0x52);
+ if (a < 0 || b < 0)
+ return 0;
+ return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128;
+}
+
static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
struct v4l2_bt_timings *bt = &timings->bt;
struct stdi_readback stdi;
@@ -1311,44 +1575,25 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
if (is_digital_input(sd)) {
- uint32_t freq;
-
timings->type = V4L2_DV_BT_656_1120;
- bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
- bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
- freq = (hdmi_read(sd, 0x06) * 1000000) +
- ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
- if (is_hdmi(sd)) {
- /* adjust for deep color mode */
- unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8;
-
- freq = freq * 8 / bits_per_channel;
- }
- bt->pixelclock = freq;
- bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
- hdmi_read(sd, 0x21);
- bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
- hdmi_read(sd, 0x23);
- bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 +
- hdmi_read(sd, 0x25);
- bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 +
- hdmi_read(sd, 0x2b)) / 2;
- bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 +
- hdmi_read(sd, 0x2f)) / 2;
- bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 +
- hdmi_read(sd, 0x33)) / 2;
+ /* FIXME: All masks are incorrect for ADV7611 */
+ bt->width = hdmi_read16(sd, 0x07, 0xfff);
+ bt->height = hdmi_read16(sd, 0x09, 0xfff);
+ bt->pixelclock = info->read_hdmi_pixelclock(sd);
+ bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff);
+ bt->hsync = hdmi_read16(sd, 0x22, 0x3ff);
+ bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff);
+ bt->vfrontporch = hdmi_read16(sd, 0x2a, 0x1fff) / 2;
+ bt->vsync = hdmi_read16(sd, 0x2e, 0x1fff) / 2;
+ bt->vbackporch = hdmi_read16(sd, 0x32, 0x1fff) / 2;
bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
if (bt->interlaced == V4L2_DV_INTERLACED) {
- bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 256 +
- hdmi_read(sd, 0x0c);
- bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x1f) * 256 +
- hdmi_read(sd, 0x2d)) / 2;
- bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 +
- hdmi_read(sd, 0x31)) / 2;
- bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
- hdmi_read(sd, 0x35)) / 2;
+ bt->height += hdmi_read16(sd, 0x0b, 0xfff);
+ bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2;
+ bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
+ bt->vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
}
adv7604_fill_optional_dv_timings_fields(sd, timings);
} else {
@@ -1378,11 +1623,11 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
/* TODO restart STDI for Sync Channel 2 */
/* enter one-shot mode */
- cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+ cp_write_clr_set(sd, 0x86, 0x06, 0x00);
/* trigger STDI restart */
- cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+ cp_write_clr_set(sd, 0x86, 0x06, 0x04);
/* reset to continuous mode */
- cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+ cp_write_clr_set(sd, 0x86, 0x06, 0x02);
state->restart_stdi_once = false;
return -ENOLINK;
}
@@ -1441,7 +1686,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
state->timings = *timings;
- cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+ cp_write_clr_set(sd, 0x91, 0x40, bt->interlaced ? 0x40 : 0x00);
/* Use prim_mode and vid_std when available */
err = configure_predefined_video_timings(sd, timings);
@@ -1468,6 +1713,16 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
return 0;
}
+static void adv7604_set_termination(struct v4l2_subdev *sd, bool enable)
+{
+ hdmi_write(sd, 0x01, enable ? 0x00 : 0x78);
+}
+
+static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable)
+{
+ hdmi_write(sd, 0x83, enable ? 0xfe : 0xff);
+}
+
static void enable_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
@@ -1475,10 +1730,10 @@ static void enable_input(struct v4l2_subdev *sd)
if (is_analog_input(sd)) {
io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */
} else if (is_digital_input(sd)) {
- hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input);
- hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
+ hdmi_write_clr_set(sd, 0x00, 0x03, state->selected_input);
+ state->info->set_termination(sd, true);
io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */
- hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */
+ hdmi_write_clr_set(sd, 0x1a, 0x10, 0x00); /* Unmute audio */
} else {
v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
__func__, state->selected_input);
@@ -1487,67 +1742,36 @@ static void enable_input(struct v4l2_subdev *sd)
static void disable_input(struct v4l2_subdev *sd)
{
- hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */
+ struct adv7604_state *state = to_state(sd);
+
+ hdmi_write_clr_set(sd, 0x1a, 0x10, 0x10); /* Mute audio */
msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */
- hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
+ state->info->set_termination(sd, false);
}
static void select_input(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
if (is_analog_input(sd)) {
- /* reset ADI recommended settings for HDMI: */
- /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
- hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
- hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */
- hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */
- hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
- hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */
- hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */
- hdmi_write(sd, 0x8d, 0x18); /* equaliser */
- hdmi_write(sd, 0x8e, 0x34); /* equaliser */
- hdmi_write(sd, 0x93, 0x88); /* equaliser */
- hdmi_write(sd, 0x94, 0x2e); /* equaliser */
- hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */
+ adv7604_write_reg_seq(sd, info->recommended_settings[0]);
afe_write(sd, 0x00, 0x08); /* power up ADC */
afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
afe_write(sd, 0xc8, 0x00); /* phase control */
-
- /* set ADI recommended settings for digitizer */
- /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
- afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */
- afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */
- cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */
- cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
- cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
} else if (is_digital_input(sd)) {
hdmi_write(sd, 0x00, state->selected_input & 0x03);
- /* set ADI recommended settings for HDMI: */
- /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
- hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
- hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */
- hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */
- hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
- hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */
- hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */
- hdmi_write(sd, 0x8d, 0x18); /* equaliser */
- hdmi_write(sd, 0x8e, 0x34); /* equaliser */
- hdmi_write(sd, 0x93, 0x8b); /* equaliser */
- hdmi_write(sd, 0x94, 0x2d); /* equaliser */
- hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */
-
- afe_write(sd, 0x00, 0xff); /* power down ADC */
- afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
- afe_write(sd, 0xc8, 0x40); /* phase control */
-
- /* reset ADI recommended settings for digitizer */
- /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
- afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */
- afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */
+ adv7604_write_reg_seq(sd, info->recommended_settings[1]);
+
+ if (adv7604_has_afe(state)) {
+ afe_write(sd, 0x00, 0xff); /* power down ADC */
+ afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
+ afe_write(sd, 0xc8, 0x40); /* phase control */
+ }
+
cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
@@ -1568,6 +1792,9 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
if (input == state->selected_input)
return 0;
+ if (input > state->info->max_port)
+ return -EINVAL;
+
state->selected_input = input;
disable_input(sd);
@@ -1579,34 +1806,139 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
return 0;
}
-static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- enum v4l2_mbus_pixelcode *code)
+static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ struct adv7604_state *state = to_state(sd);
+
+ if (code->index >= state->info->nformats)
+ return -EINVAL;
+
+ code->code = state->info->formats[code->index].code;
+
+ return 0;
+}
+
+static void adv7604_fill_format(struct adv7604_state *state,
+ struct v4l2_mbus_framefmt *format)
+{
+ memset(format, 0, sizeof(*format));
+
+ format->width = state->timings.bt.width;
+ format->height = state->timings.bt.height;
+ format->field = V4L2_FIELD_NONE;
+
+ if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861)
+ format->colorspace = (state->timings.bt.height <= 576) ?
+ V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+}
+
+/*
+ * Compute the op_ch_sel value required to obtain on the bus the component order
+ * corresponding to the selected format taking into account bus reordering
+ * applied by the board at the output of the device.
+ *
+ * The following table gives the op_ch_value from the format component order
+ * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
+ * adv7604_bus_order value in row).
+ *
+ * | GBR(0) GRB(1) BGR(2) RGB(3) BRG(4) RBG(5)
+ * ----------+-------------------------------------------------
+ * RGB (NOP) | GBR GRB BGR RGB BRG RBG
+ * GRB (1-2) | BGR RGB GBR GRB RBG BRG
+ * RBG (2-3) | GRB GBR BRG RBG BGR RGB
+ * BGR (1-3) | RBG BRG RGB BGR GRB GBR
+ * BRG (ROR) | BRG RBG GRB GBR RGB BGR
+ * GBR (ROL) | RGB BGR RBG BRG GBR GRB
+ */
+static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
+{
+#define _SEL(a,b,c,d,e,f) { \
+ ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, \
+ ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
+#define _BUS(x) [ADV7604_BUS_ORDER_##x]
+
+ static const unsigned int op_ch_sel[6][6] = {
+ _BUS(RGB) /* NOP */ = _SEL(GBR, GRB, BGR, RGB, BRG, RBG),
+ _BUS(GRB) /* 1-2 */ = _SEL(BGR, RGB, GBR, GRB, RBG, BRG),
+ _BUS(RBG) /* 2-3 */ = _SEL(GRB, GBR, BRG, RBG, BGR, RGB),
+ _BUS(BGR) /* 1-3 */ = _SEL(RBG, BRG, RGB, BGR, GRB, GBR),
+ _BUS(BRG) /* ROR */ = _SEL(BRG, RBG, GRB, GBR, RGB, BGR),
+ _BUS(GBR) /* ROL */ = _SEL(RGB, BGR, RBG, BRG, GBR, GRB),
+ };
+
+ return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
+}
+
+static void adv7604_setup_format(struct adv7604_state *state)
+{
+ struct v4l2_subdev *sd = &state->sd;
+
+ io_write_clr_set(sd, 0x02, 0x02,
+ state->format->rgb_out ? ADV7604_RGB_OUT : 0);
+ io_write(sd, 0x03, state->format->op_format_sel |
+ state->pdata.op_format_mode_sel);
+ io_write_clr_set(sd, 0x04, 0xe0, adv7604_op_ch_sel(state));
+ io_write_clr_set(sd, 0x05, 0x01,
+ state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
+}
+
+static int adv7604_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
{
- if (index)
+ struct adv7604_state *state = to_state(sd);
+
+ if (format->pad != state->source_pad)
return -EINVAL;
- /* Good enough for now */
- *code = V4L2_MBUS_FMT_FIXED;
+
+ adv7604_fill_format(state, &format->format);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_get_try_format(fh, format->pad);
+ format->format.code = fmt->code;
+ } else {
+ format->format.code = state->format->code;
+ }
+
return 0;
}
-static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7604_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_format_info *info;
- fmt->width = state->timings.bt.width;
- fmt->height = state->timings.bt.height;
- fmt->code = V4L2_MBUS_FMT_FIXED;
- fmt->field = V4L2_FIELD_NONE;
- if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
- fmt->colorspace = (state->timings.bt.height <= 576) ?
- V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+ if (format->pad != state->source_pad)
+ return -EINVAL;
+
+ info = adv7604_format_info(state, format->format.code);
+ if (info == NULL)
+ info = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
+
+ adv7604_fill_format(state, &format->format);
+ format->format.code = info->code;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ struct v4l2_mbus_framefmt *fmt;
+
+ fmt = v4l2_subdev_get_try_format(fh, format->pad);
+ fmt->code = format->format.code;
+ } else {
+ state->format = info;
+ adv7604_setup_format(state);
}
+
return 0;
}
static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
{
+ struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
const u8 irq_reg_0x43 = io_read(sd, 0x43);
const u8 irq_reg_0x6b = io_read(sd, 0x6b);
const u8 irq_reg_0x70 = io_read(sd, 0x70);
@@ -1625,7 +1957,9 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
/* format change */
fmt_change = irq_reg_0x43 & 0x98;
- fmt_change_digital = is_digital_input(sd) ? (irq_reg_0x6b & 0xc0) : 0;
+ fmt_change_digital = is_digital_input(sd)
+ ? irq_reg_0x6b & info->fmt_change_digital_mask
+ : 0;
if (fmt_change || fmt_change_digital) {
v4l2_dbg(1, debug, sd,
@@ -1647,7 +1981,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
}
/* tx 5v detect */
- tx_5v = io_read(sd, 0x70) & 0x1e;
+ tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
if (tx_5v) {
v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
io_write(sd, 0x71, tx_5v);
@@ -1663,7 +1997,7 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
struct adv7604_state *state = to_state(sd);
u8 *data = NULL;
- if (edid->pad > ADV7604_EDID_PORT_D)
+ if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
return -EINVAL;
if (edid->blocks == 0)
return -EINVAL;
@@ -1678,10 +2012,10 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
edid->blocks = state->edid.blocks;
switch (edid->pad) {
- case ADV7604_EDID_PORT_A:
- case ADV7604_EDID_PORT_B:
- case ADV7604_EDID_PORT_C:
- case ADV7604_EDID_PORT_D:
+ case ADV7604_PAD_HDMI_PORT_A:
+ case ADV7604_PAD_HDMI_PORT_B:
+ case ADV7604_PAD_HDMI_PORT_C:
+ case ADV7604_PAD_HDMI_PORT_D:
if (state->edid.present & (1 << edid->pad))
data = state->edid.edid;
break;
@@ -1729,20 +2063,20 @@ static int get_edid_spa_location(const u8 *edid)
static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
int spa_loc;
- int tmp = 0;
int err;
int i;
- if (edid->pad > ADV7604_EDID_PORT_D)
+ if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
return -EINVAL;
if (edid->start_block != 0)
return -EINVAL;
if (edid->blocks == 0) {
/* Disable hotplug and I2C access to EDID RAM from DDC port */
state->edid.present &= ~(1 << edid->pad);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present);
- rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+ adv7604_set_hpd(state, state->edid.present);
+ rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
/* Fall back to a 16:9 aspect ratio */
state->aspect_ratio.numerator = 16;
@@ -1765,35 +2099,41 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
/* Disable hotplug and I2C access to EDID RAM from DDC port */
cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
- v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp);
- rep_write_and_or(sd, 0x77, 0xf0, 0x00);
+ adv7604_set_hpd(state, 0);
+ rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
spa_loc = get_edid_spa_location(edid->edid);
if (spa_loc < 0)
spa_loc = 0xc0; /* Default value [REF_02, p. 116] */
switch (edid->pad) {
- case ADV7604_EDID_PORT_A:
+ case ADV7604_PAD_HDMI_PORT_A:
state->spa_port_a[0] = edid->edid[spa_loc];
state->spa_port_a[1] = edid->edid[spa_loc + 1];
break;
- case ADV7604_EDID_PORT_B:
+ case ADV7604_PAD_HDMI_PORT_B:
rep_write(sd, 0x70, edid->edid[spa_loc]);
rep_write(sd, 0x71, edid->edid[spa_loc + 1]);
break;
- case ADV7604_EDID_PORT_C:
+ case ADV7604_PAD_HDMI_PORT_C:
rep_write(sd, 0x72, edid->edid[spa_loc]);
rep_write(sd, 0x73, edid->edid[spa_loc + 1]);
break;
- case ADV7604_EDID_PORT_D:
+ case ADV7604_PAD_HDMI_PORT_D:
rep_write(sd, 0x74, edid->edid[spa_loc]);
rep_write(sd, 0x75, edid->edid[spa_loc + 1]);
break;
default:
return -EINVAL;
}
- rep_write(sd, 0x76, spa_loc & 0xff);
- rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40);
+
+ if (info->type == ADV7604) {
+ rep_write(sd, 0x76, spa_loc & 0xff);
+ rep_write_clr_set(sd, 0x77, 0x40, (spa_loc & 0x100) >> 2);
+ } else {
+ /* FIXME: Where is the SPA location LSB register ? */
+ rep_write_clr_set(sd, 0x71, 0x01, (spa_loc & 0x100) >> 8);
+ }
edid->edid[spa_loc] = state->spa_port_a[0];
edid->edid[spa_loc + 1] = state->spa_port_a[1];
@@ -1812,10 +2152,10 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
/* adv7604 calculates the checksums and enables I2C access to internal
EDID RAM from DDC port. */
- rep_write_and_or(sd, 0x77, 0xf0, state->edid.present);
+ rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
for (i = 0; i < 1000; i++) {
- if (rep_read(sd, 0x7d) & state->edid.present)
+ if (rep_read(sd, info->edid_status_reg) & state->edid.present)
break;
mdelay(1);
}
@@ -1878,17 +2218,20 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
static int adv7604_log_status(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
struct v4l2_dv_timings timings;
struct stdi_readback stdi;
u8 reg_io_0x02 = io_read(sd, 0x02);
+ u8 edid_enabled;
+ u8 cable_det;
- char *csc_coeff_sel_rb[16] = {
+ static const char * const csc_coeff_sel_rb[16] = {
"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
"reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
"reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709",
"reserved", "reserved", "reserved", "reserved", "manual"
};
- char *input_color_space_txt[16] = {
+ static const char * const input_color_space_txt[16] = {
"RGB limited range (16-235)", "RGB full range (0-255)",
"YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
"xvYCC Bt.601", "xvYCC Bt.709",
@@ -1896,12 +2239,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
"invalid", "invalid", "invalid", "invalid", "invalid",
"invalid", "invalid", "automatic"
};
- char *rgb_quantization_range_txt[] = {
+ static const char * const rgb_quantization_range_txt[] = {
"Automatic",
"RGB limited range (16-235)",
"RGB full range (0-255)",
};
- char *deep_color_mode_txt[4] = {
+ static const char * const deep_color_mode_txt[4] = {
"8-bits per channel",
"10-bits per channel",
"12-bits per channel",
@@ -1910,20 +2253,22 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
v4l2_info(sd, "-----Chip status-----\n");
v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
+ edid_enabled = rep_read(sd, info->edid_status_reg);
v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n",
- ((rep_read(sd, 0x7d) & 0x01) ? "Yes" : "No"),
- ((rep_read(sd, 0x7d) & 0x02) ? "Yes" : "No"),
- ((rep_read(sd, 0x7d) & 0x04) ? "Yes" : "No"),
- ((rep_read(sd, 0x7d) & 0x08) ? "Yes" : "No"));
+ ((edid_enabled & 0x01) ? "Yes" : "No"),
+ ((edid_enabled & 0x02) ? "Yes" : "No"),
+ ((edid_enabled & 0x04) ? "Yes" : "No"),
+ ((edid_enabled & 0x08) ? "Yes" : "No"));
v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?
"enabled" : "disabled");
v4l2_info(sd, "-----Signal status-----\n");
+ cable_det = info->read_cable_det(sd);
v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n",
- ((io_read(sd, 0x6f) & 0x10) ? "Yes" : "No"),
- ((io_read(sd, 0x6f) & 0x08) ? "Yes" : "No"),
- ((io_read(sd, 0x6f) & 0x04) ? "Yes" : "No"),
- ((io_read(sd, 0x6f) & 0x02) ? "Yes" : "No"));
+ ((cable_det & 0x01) ? "Yes" : "No"),
+ ((cable_det & 0x02) ? "Yes" : "No"),
+ ((cable_det & 0x04) ? "Yes" : "No"),
+ ((cable_det & 0x08) ? "Yes" : "No"));
v4l2_info(sd, "TMDS signal detected: %s\n",
no_signal_tmds(sd) ? "false" : "true");
v4l2_info(sd, "TMDS signal locked: %s\n",
@@ -2017,13 +2362,6 @@ static const struct v4l2_ctrl_ops adv7604_ctrl_ops = {
static const struct v4l2_subdev_core_ops adv7604_core_ops = {
.log_status = adv7604_log_status,
- .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
- .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
- .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
- .g_ctrl = v4l2_subdev_g_ctrl,
- .s_ctrl = v4l2_subdev_s_ctrl,
- .queryctrl = v4l2_subdev_queryctrl,
- .querymenu = v4l2_subdev_querymenu,
.interrupt_service_routine = adv7604_isr,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = adv7604_g_register,
@@ -2037,17 +2375,16 @@ static const struct v4l2_subdev_video_ops adv7604_video_ops = {
.s_dv_timings = adv7604_s_dv_timings,
.g_dv_timings = adv7604_g_dv_timings,
.query_dv_timings = adv7604_query_dv_timings,
- .enum_dv_timings = adv7604_enum_dv_timings,
- .dv_timings_cap = adv7604_dv_timings_cap,
- .enum_mbus_fmt = adv7604_enum_mbus_fmt,
- .g_mbus_fmt = adv7604_g_mbus_fmt,
- .try_mbus_fmt = adv7604_g_mbus_fmt,
- .s_mbus_fmt = adv7604_g_mbus_fmt,
};
static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
+ .enum_mbus_code = adv7604_enum_mbus_code,
+ .get_fmt = adv7604_get_format,
+ .set_fmt = adv7604_set_format,
.get_edid = adv7604_get_edid,
.set_edid = adv7604_set_edid,
+ .dv_timings_cap = adv7604_dv_timings_cap,
+ .enum_dv_timings = adv7604_enum_dv_timings,
};
static const struct v4l2_subdev_ops adv7604_ops = {
@@ -2096,6 +2433,7 @@ static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
static int adv7604_core_init(struct v4l2_subdev *sd)
{
struct adv7604_state *state = to_state(sd);
+ const struct adv7604_chip_info *info = state->info;
struct adv7604_platform_data *pdata = &state->pdata;
hdmi_write(sd, 0x48,
@@ -2104,28 +2442,33 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
disable_input(sd);
+ if (pdata->default_input >= 0 &&
+ pdata->default_input < state->source_pad) {
+ state->selected_input = pdata->default_input;
+ select_input(sd);
+ enable_input(sd);
+ }
+
/* power */
io_write(sd, 0x0c, 0x42); /* Power up part and power down VDP */
io_write(sd, 0x0b, 0x44); /* Power down ESDP block */
cp_write(sd, 0xcf, 0x01); /* Power down macrovision */
/* video format */
- io_write_and_or(sd, 0x02, 0xf0,
+ io_write_clr_set(sd, 0x02, 0x0f,
pdata->alt_gamma << 3 |
pdata->op_656_range << 2 |
- pdata->rgb_out << 1 |
pdata->alt_data_sat << 0);
- io_write(sd, 0x03, pdata->op_format_sel);
- io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
- io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
- pdata->insert_av_codes << 2 |
- pdata->replicate_av_codes << 1 |
- pdata->invert_cbcr << 0);
+ io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 |
+ pdata->insert_av_codes << 2 |
+ pdata->replicate_av_codes << 1);
+ adv7604_setup_format(state);
cp_write(sd, 0x69, 0x30); /* Enable CP CSC */
/* VS, HS polarities */
- io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 | pdata->inv_hs_pol << 1);
+ io_write(sd, 0x06, 0xa0 | pdata->inv_vs_pol << 2 |
+ pdata->inv_hs_pol << 1 | pdata->inv_llc_pol);
/* Adjust drive strength */
io_write(sd, 0x14, 0x40 | pdata->dr_str_data << 4 |
@@ -2142,52 +2485,46 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
for digital formats */
/* HDMI audio */
- hdmi_write_and_or(sd, 0x15, 0xfc, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
- hdmi_write_and_or(sd, 0x1a, 0xf1, 0x08); /* Wait 1 s before unmute */
- hdmi_write_and_or(sd, 0x68, 0xf9, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
+ hdmi_write_clr_set(sd, 0x15, 0x03, 0x03); /* Mute on FIFO over-/underflow [REF_01, c. 1.2.18] */
+ hdmi_write_clr_set(sd, 0x1a, 0x0e, 0x08); /* Wait 1 s before unmute */
+ hdmi_write_clr_set(sd, 0x68, 0x06, 0x06); /* FIFO reset on over-/underflow [REF_01, c. 1.2.19] */
/* TODO from platform data */
afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */
- afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
- io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+ if (adv7604_has_afe(state)) {
+ afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
+ io_write_clr_set(sd, 0x30, 1 << 4, pdata->output_bus_lsb_to_msb << 4);
+ }
/* interrupts */
- io_write(sd, 0x40, 0xc2); /* Configure INT1 */
- io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+ io_write(sd, 0x40, 0xc0 | pdata->int1_config); /* Configure INT1 */
io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
- io_write(sd, 0x6e, 0xc1); /* Enable V_LOCKED, DE_REGEN_LCK, HDMI_MODE interrupts */
- io_write(sd, 0x73, 0x1e); /* Enable CABLE_DET_A_ST (+5v) interrupts */
+ io_write(sd, 0x6e, info->fmt_change_digital_mask); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
+ io_write(sd, 0x73, info->cable_det_mask); /* Enable cable detection (+5v) interrupts */
+ info->setup_irqs(sd);
return v4l2_ctrl_handler_setup(sd->ctrl_handler);
}
+static void adv7604_setup_irqs(struct v4l2_subdev *sd)
+{
+ io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+}
+
+static void adv7611_setup_irqs(struct v4l2_subdev *sd)
+{
+ io_write(sd, 0x41, 0xd0); /* STDI irq for any change, disable INT2 */
+}
+
static void adv7604_unregister_clients(struct adv7604_state *state)
{
- if (state->i2c_avlink)
- i2c_unregister_device(state->i2c_avlink);
- if (state->i2c_cec)
- i2c_unregister_device(state->i2c_cec);
- if (state->i2c_infoframe)
- i2c_unregister_device(state->i2c_infoframe);
- if (state->i2c_esdp)
- i2c_unregister_device(state->i2c_esdp);
- if (state->i2c_dpp)
- i2c_unregister_device(state->i2c_dpp);
- if (state->i2c_afe)
- i2c_unregister_device(state->i2c_afe);
- if (state->i2c_repeater)
- i2c_unregister_device(state->i2c_repeater);
- if (state->i2c_edid)
- i2c_unregister_device(state->i2c_edid);
- if (state->i2c_hdmi)
- i2c_unregister_device(state->i2c_hdmi);
- if (state->i2c_test)
- i2c_unregister_device(state->i2c_test);
- if (state->i2c_cp)
- i2c_unregister_device(state->i2c_cp);
- if (state->i2c_vdp)
- i2c_unregister_device(state->i2c_vdp);
+ unsigned int i;
+
+ for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) {
+ if (state->i2c_clients[i])
+ i2c_unregister_device(state->i2c_clients[i]);
+ }
}
static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
@@ -2200,15 +2537,219 @@ static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1);
}
+static const struct adv7604_reg_seq adv7604_recommended_settings_afe[] = {
+ /* reset ADI recommended settings for HDMI: */
+ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */
+
+ /* set ADI recommended settings for digitizer */
+ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+ { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */
+ { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */
+ { ADV7604_REG(ADV7604_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */
+ { ADV7604_REG(ADV7604_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */
+ { ADV7604_REG(ADV7604_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */
+
+ { ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
+ /* set ADI recommended settings for HDMI: */
+ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */
+
+ /* reset ADI recommended settings for digitizer */
+ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+ { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */
+ { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */
+
+ { ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+ { ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x03), 0x98 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4c), 0x44 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x04 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x1e },
+
+ { ADV7604_REG_SEQ_TERM, 0 },
+};
+
+static const struct adv7604_chip_info adv7604_chip_info[] = {
+ [ADV7604] = {
+ .type = ADV7604,
+ .has_afe = true,
+ .max_port = ADV7604_PAD_VGA_COMP,
+ .num_dv_ports = 4,
+ .edid_enable_reg = 0x77,
+ .edid_status_reg = 0x7d,
+ .lcf_reg = 0xb3,
+ .tdms_lock_mask = 0xe0,
+ .cable_det_mask = 0x1e,
+ .fmt_change_digital_mask = 0xc1,
+ .formats = adv7604_formats,
+ .nformats = ARRAY_SIZE(adv7604_formats),
+ .set_termination = adv7604_set_termination,
+ .setup_irqs = adv7604_setup_irqs,
+ .read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock,
+ .read_cable_det = adv7604_read_cable_det,
+ .recommended_settings = {
+ [0] = adv7604_recommended_settings_afe,
+ [1] = adv7604_recommended_settings_hdmi,
+ },
+ .num_recommended_settings = {
+ [0] = ARRAY_SIZE(adv7604_recommended_settings_afe),
+ [1] = ARRAY_SIZE(adv7604_recommended_settings_hdmi),
+ },
+ .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) |
+ BIT(ADV7604_PAGE_CEC) | BIT(ADV7604_PAGE_INFOFRAME) |
+ BIT(ADV7604_PAGE_ESDP) | BIT(ADV7604_PAGE_DPP) |
+ BIT(ADV7604_PAGE_AFE) | BIT(ADV7604_PAGE_REP) |
+ BIT(ADV7604_PAGE_EDID) | BIT(ADV7604_PAGE_HDMI) |
+ BIT(ADV7604_PAGE_TEST) | BIT(ADV7604_PAGE_CP) |
+ BIT(ADV7604_PAGE_VDP),
+ },
+ [ADV7611] = {
+ .type = ADV7611,
+ .has_afe = false,
+ .max_port = ADV7604_PAD_HDMI_PORT_A,
+ .num_dv_ports = 1,
+ .edid_enable_reg = 0x74,
+ .edid_status_reg = 0x76,
+ .lcf_reg = 0xa3,
+ .tdms_lock_mask = 0x43,
+ .cable_det_mask = 0x01,
+ .fmt_change_digital_mask = 0x03,
+ .formats = adv7611_formats,
+ .nformats = ARRAY_SIZE(adv7611_formats),
+ .set_termination = adv7611_set_termination,
+ .setup_irqs = adv7611_setup_irqs,
+ .read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock,
+ .read_cable_det = adv7611_read_cable_det,
+ .recommended_settings = {
+ [1] = adv7611_recommended_settings_hdmi,
+ },
+ .num_recommended_settings = {
+ [1] = ARRAY_SIZE(adv7611_recommended_settings_hdmi),
+ },
+ .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_CEC) |
+ BIT(ADV7604_PAGE_INFOFRAME) | BIT(ADV7604_PAGE_AFE) |
+ BIT(ADV7604_PAGE_REP) | BIT(ADV7604_PAGE_EDID) |
+ BIT(ADV7604_PAGE_HDMI) | BIT(ADV7604_PAGE_CP),
+ },
+};
+
+static struct i2c_device_id adv7604_i2c_id[] = {
+ { "adv7604", (kernel_ulong_t)&adv7604_chip_info[ADV7604] },
+ { "adv7611", (kernel_ulong_t)&adv7604_chip_info[ADV7611] },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adv7604_i2c_id);
+
+static struct of_device_id adv7604_of_id[] __maybe_unused = {
+ { .compatible = "adi,adv7611", .data = &adv7604_chip_info[ADV7611] },
+ { }
+};
+MODULE_DEVICE_TABLE(of, adv7604_of_id);
+
+static int adv7604_parse_dt(struct adv7604_state *state)
+{
+ struct v4l2_of_endpoint bus_cfg;
+ struct device_node *endpoint;
+ struct device_node *np;
+ unsigned int flags;
+
+ np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
+
+ /* Parse the endpoint. */
+ endpoint = of_graph_get_next_endpoint(np, NULL);
+ if (!endpoint)
+ return -EINVAL;
+
+ v4l2_of_parse_endpoint(endpoint, &bus_cfg);
+ of_node_put(endpoint);
+
+ flags = bus_cfg.bus.parallel.flags;
+
+ if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+ state->pdata.inv_hs_pol = 1;
+
+ if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+ state->pdata.inv_vs_pol = 1;
+
+ if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+ state->pdata.inv_llc_pol = 1;
+
+ if (bus_cfg.bus_type == V4L2_MBUS_BT656) {
+ state->pdata.insert_av_codes = 1;
+ state->pdata.op_656_range = 1;
+ }
+
+ /* Disable the interrupt for now as no DT-based board uses it. */
+ state->pdata.int1_config = ADV7604_INT1_CONFIG_DISABLED;
+
+ /* Use the default I2C addresses. */
+ state->pdata.i2c_addresses[ADV7604_PAGE_AVLINK] = 0x42;
+ state->pdata.i2c_addresses[ADV7604_PAGE_CEC] = 0x40;
+ state->pdata.i2c_addresses[ADV7604_PAGE_INFOFRAME] = 0x3e;
+ state->pdata.i2c_addresses[ADV7604_PAGE_ESDP] = 0x38;
+ state->pdata.i2c_addresses[ADV7604_PAGE_DPP] = 0x3c;
+ state->pdata.i2c_addresses[ADV7604_PAGE_AFE] = 0x26;
+ state->pdata.i2c_addresses[ADV7604_PAGE_REP] = 0x32;
+ state->pdata.i2c_addresses[ADV7604_PAGE_EDID] = 0x36;
+ state->pdata.i2c_addresses[ADV7604_PAGE_HDMI] = 0x34;
+ state->pdata.i2c_addresses[ADV7604_PAGE_TEST] = 0x30;
+ state->pdata.i2c_addresses[ADV7604_PAGE_CP] = 0x22;
+ state->pdata.i2c_addresses[ADV7604_PAGE_VDP] = 0x24;
+
+ /* Hardcode the remaining platform data fields. */
+ state->pdata.disable_pwrdnb = 0;
+ state->pdata.disable_cable_det_rst = 0;
+ state->pdata.default_input = -1;
+ state->pdata.blank_data = 1;
+ state->pdata.alt_data_sat = 1;
+ state->pdata.op_format_mode_sel = ADV7604_OP_FORMAT_MODE0;
+ state->pdata.bus_order = ADV7604_BUS_ORDER_RGB;
+
+ return 0;
+}
+
static int adv7604_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const struct v4l2_dv_timings cea640x480 =
V4L2_DV_BT_CEA_640X480P59_94;
struct adv7604_state *state;
- struct adv7604_platform_data *pdata = client->dev.platform_data;
struct v4l2_ctrl_handler *hdl;
struct v4l2_subdev *sd;
+ unsigned int i;
+ u16 val;
int err;
/* Check if the adapter supports the needed features */
@@ -2223,32 +2764,80 @@ static int adv7604_probe(struct i2c_client *client,
return -ENOMEM;
}
+ state->i2c_clients[ADV7604_PAGE_IO] = client;
+
/* initialize variables */
state->restart_stdi_once = true;
state->selected_input = ~0;
- /* platform data */
- if (!pdata) {
+ if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
+ const struct of_device_id *oid;
+
+ oid = of_match_node(adv7604_of_id, client->dev.of_node);
+ state->info = oid->data;
+
+ err = adv7604_parse_dt(state);
+ if (err < 0) {
+ v4l_err(client, "DT parsing error\n");
+ return err;
+ }
+ } else if (client->dev.platform_data) {
+ struct adv7604_platform_data *pdata = client->dev.platform_data;
+
+ state->info = (const struct adv7604_chip_info *)id->driver_data;
+ state->pdata = *pdata;
+ } else {
v4l_err(client, "No platform data!\n");
return -ENODEV;
}
- state->pdata = *pdata;
+
+ /* Request GPIOs. */
+ for (i = 0; i < state->info->num_dv_ports; ++i) {
+ state->hpd_gpio[i] =
+ devm_gpiod_get_index(&client->dev, "hpd", i);
+ if (IS_ERR(state->hpd_gpio[i]))
+ continue;
+
+ gpiod_direction_output(state->hpd_gpio[i], 0);
+
+ v4l_info(client, "Handling HPD %u GPIO\n", i);
+ }
+
state->timings = cea640x480;
+ state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
+ snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
+ id->name, i2c_adapter_id(client->adapter),
+ client->addr);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- /* i2c access to adv7604? */
- if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
- v4l2_info(sd, "not an adv7604 on address 0x%x\n",
- client->addr << 1);
- return -ENODEV;
+ /*
+ * Verify that the chip is present. On ADV7604 the RD_INFO register only
+ * identifies the revision, while on ADV7611 it identifies the model as
+ * well. Use the HDMI slave address on ADV7604 and RD_INFO on ADV7611.
+ */
+ if (state->info->type == ADV7604) {
+ val = adv_smbus_read_byte_data_check(client, 0xfb, false);
+ if (val != 0x68) {
+ v4l2_info(sd, "not an adv7604 on address 0x%x\n",
+ client->addr << 1);
+ return -ENODEV;
+ }
+ } else {
+ val = (adv_smbus_read_byte_data_check(client, 0xea, false) << 8)
+ | (adv_smbus_read_byte_data_check(client, 0xeb, false) << 0);
+ if (val != 0x2051) {
+ v4l2_info(sd, "not an adv7611 on address 0x%x\n",
+ client->addr << 1);
+ return -ENODEV;
+ }
}
/* control handlers */
hdl = &state->hdl;
- v4l2_ctrl_handler_init(hdl, 9);
+ v4l2_ctrl_handler_init(hdl, adv7604_has_afe(state) ? 9 : 8);
v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
@@ -2261,15 +2850,17 @@ static int adv7604_probe(struct i2c_client *client,
/* private controls */
state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
- V4L2_CID_DV_RX_POWER_PRESENT, 0, 0x0f, 0, 0);
+ V4L2_CID_DV_RX_POWER_PRESENT, 0,
+ (1 << state->info->num_dv_ports) - 1, 0, 0);
state->rgb_quantization_range_ctrl =
v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
0, V4L2_DV_RGB_RANGE_AUTO);
/* custom controls */
- state->analog_sampling_phase_ctrl =
- v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
+ if (adv7604_has_afe(state))
+ state->analog_sampling_phase_ctrl =
+ v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
state->free_run_color_manual_ctrl =
v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
state->free_run_color_ctrl =
@@ -2282,7 +2873,8 @@ static int adv7604_probe(struct i2c_client *client,
}
state->detect_tx_5v_ctrl->is_private = true;
state->rgb_quantization_range_ctrl->is_private = true;
- state->analog_sampling_phase_ctrl->is_private = true;
+ if (adv7604_has_afe(state))
+ state->analog_sampling_phase_ctrl->is_private = true;
state->free_run_color_manual_ctrl->is_private = true;
state->free_run_color_ctrl->is_private = true;
@@ -2291,25 +2883,18 @@ static int adv7604_probe(struct i2c_client *client,
goto err_hdl;
}
- state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
- state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4);
- state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5);
- state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
- state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
- state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8);
- state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9);
- state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa);
- state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
- state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
- state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd);
- state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
- if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe ||
- !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe ||
- !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
- !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) {
- err = -ENOMEM;
- v4l2_err(sd, "failed to create all i2c clients\n");
- goto err_i2c;
+ for (i = 1; i < ADV7604_PAGE_MAX; ++i) {
+ if (!(BIT(i) & state->info->page_mask))
+ continue;
+
+ state->i2c_clients[i] =
+ adv7604_dummy_client(sd, state->pdata.i2c_addresses[i],
+ 0xf2 + i);
+ if (state->i2c_clients[i] == NULL) {
+ err = -ENOMEM;
+ v4l2_err(sd, "failed to create i2c client %u\n", i);
+ goto err_i2c;
+ }
}
/* work queues */
@@ -2323,8 +2908,14 @@ static int adv7604_probe(struct i2c_client *client,
INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
adv7604_delayed_work_enable_hotplug);
- state->pad.flags = MEDIA_PAD_FL_SOURCE;
- err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+ state->source_pad = state->info->num_dv_ports
+ + (state->info->has_afe ? 2 : 0);
+ for (i = 0; i < state->source_pad; ++i)
+ state->pads[i].flags = MEDIA_PAD_FL_SINK;
+ state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE;
+
+ err = media_entity_init(&sd->entity, state->source_pad + 1,
+ state->pads, 0);
if (err)
goto err_work_queues;
@@ -2333,6 +2924,11 @@ static int adv7604_probe(struct i2c_client *client,
goto err_entity;
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name);
+
+ err = v4l2_async_register_subdev(sd);
+ if (err)
+ goto err_entity;
+
return 0;
err_entity:
@@ -2356,6 +2952,7 @@ static int adv7604_remove(struct i2c_client *client)
cancel_delayed_work(&state->delayed_work_enable_hotplug);
destroy_workqueue(state->work_queues);
+ v4l2_async_unregister_subdev(sd);
v4l2_device_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);
adv7604_unregister_clients(to_state(sd));
@@ -2365,20 +2962,15 @@ static int adv7604_remove(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
-static struct i2c_device_id adv7604_id[] = {
- { "adv7604", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, adv7604_id);
-
static struct i2c_driver adv7604_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "adv7604",
+ .of_match_table = of_match_ptr(adv7604_of_id),
},
.probe = adv7604_probe,
.remove = adv7604_remove,
- .id_table = adv7604_id,
+ .id_table = adv7604_i2c_id,
};
module_i2c_driver(adv7604_driver);
diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index 151cecd0ea25..6a93f928dfde 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -1,6 +1,6 @@
vsp1-y := vsp1_drv.o vsp1_entity.o vsp1_video.o
vsp1-y += vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
vsp1-y += vsp1_hsit.o vsp1_lif.o vsp1_lut.o
-vsp1-y += vsp1_sru.o vsp1_uds.o
+vsp1-y += vsp1_bru.o vsp1_sru.o vsp1_uds.o
obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1.o
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 0313210c6e9e..6ca2cf20d545 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -28,6 +28,7 @@ struct clk;
struct device;
struct vsp1_platform_data;
+struct vsp1_bru;
struct vsp1_hsit;
struct vsp1_lif;
struct vsp1_lut;
@@ -45,11 +46,11 @@ struct vsp1_device {
void __iomem *mmio;
struct clk *clock;
- struct clk *rt_clock;
struct mutex lock;
int ref_count;
+ struct vsp1_bru *bru;
struct vsp1_hsit *hsi;
struct vsp1_hsit *hst;
struct vsp1_lif *lif;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
new file mode 100644
index 000000000000..f80695480060
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -0,0 +1,395 @@
+/*
+ * vsp1_bru.c -- R-Car VSP1 Blend ROP Unit
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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.
+ */
+
+#include <linux/device.h>
+#include <linux/gfp.h>
+
+#include <media/v4l2-subdev.h>
+
+#include "vsp1.h"
+#include "vsp1_bru.h"
+
+#define BRU_MIN_SIZE 4U
+#define BRU_MAX_SIZE 8190U
+
+/* -----------------------------------------------------------------------------
+ * Device Access
+ */
+
+static inline u32 vsp1_bru_read(struct vsp1_bru *bru, u32 reg)
+{
+ return vsp1_read(bru->entity.vsp1, reg);
+}
+
+static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data)
+{
+ vsp1_write(bru->entity.vsp1, reg, data);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
+static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input)
+{
+ return media_entity_remote_pad(&bru->entity.pads[input]) != NULL;
+}
+
+static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+ struct vsp1_bru *bru = to_bru(subdev);
+ struct v4l2_mbus_framefmt *format;
+ unsigned int i;
+
+ if (!enable)
+ return 0;
+
+ format = &bru->entity.formats[BRU_PAD_SOURCE];
+
+ /* The hardware is extremely flexible but we have no userspace API to
+ * expose all the parameters, nor is it clear whether we would have use
+ * cases for all the supported modes. Let's just harcode the parameters
+ * to sane default values for now.
+ */
+
+ /* Disable both color data normalization and dithering. */
+ vsp1_bru_write(bru, VI6_BRU_INCTRL, 0);
+
+ /* Set the background position to cover the whole output image and
+ * set its color to opaque black.
+ */
+ vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE,
+ (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
+ (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
+ vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0);
+ vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL,
+ 0xff << VI6_BRU_VIRRPF_COL_A_SHIFT);
+
+ /* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
+ * unit with a NOP operation to make BRU input 1 available as the
+ * Blend/ROP unit B SRC input.
+ */
+ vsp1_bru_write(bru, VI6_BRU_ROP, VI6_BRU_ROP_DSTSEL_BRUIN(1) |
+ VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
+ VI6_BRU_ROP_AROP(VI6_ROP_NOP));
+
+ for (i = 0; i < 4; ++i) {
+ u32 ctrl = 0;
+
+ /* Configure all Blend/ROP units corresponding to an enabled BRU
+ * input for alpha blending. Blend/ROP units corresponding to
+ * disabled BRU inputs are used in ROP NOP mode to ignore the
+ * SRC input.
+ */
+ if (bru_is_input_enabled(bru, i))
+ ctrl |= VI6_BRU_CTRL_RBC;
+ else
+ ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
+ | VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
+
+ /* Select the virtual RPF as the Blend/ROP unit A DST input to
+ * serve as a background color.
+ */
+ if (i == 0)
+ ctrl |= VI6_BRU_CTRL_DSTSEL_VRPF;
+
+ /* Route BRU inputs 0 to 3 as SRC inputs to Blend/ROP units A to
+ * D in that order. The Blend/ROP unit B SRC is hardwired to the
+ * ROP unit output, the corresponding register bits must be set
+ * to 0.
+ */
+ if (i != 1)
+ ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
+
+ vsp1_bru_write(bru, VI6_BRU_CTRL(i), ctrl);
+
+ /* Harcode the blending formula to
+ *
+ * DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
+ * DSTa = DSTa * (1 - SRCa) + SRCa
+ */
+ vsp1_bru_write(bru, VI6_BRU_BLD(i),
+ VI6_BRU_BLD_CCMDX_255_SRC_A |
+ VI6_BRU_BLD_CCMDY_SRC_A |
+ VI6_BRU_BLD_ACMDX_255_SRC_A |
+ VI6_BRU_BLD_ACMDY_COEFY |
+ (0xff << VI6_BRU_BLD_COEFY_SHIFT));
+ }
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+/*
+ * The BRU can't perform format conversion, all sink and source formats must be
+ * identical. We pick the format on the first sink pad (pad 0) and propagate it
+ * to all other pads.
+ */
+
+static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ static const unsigned int codes[] = {
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
+ };
+ struct v4l2_mbus_framefmt *format;
+
+ if (code->pad == BRU_PAD_SINK(0)) {
+ if (code->index >= ARRAY_SIZE(codes))
+ return -EINVAL;
+
+ code->code = codes[code->index];
+ } else {
+ if (code->index)
+ return -EINVAL;
+
+ format = v4l2_subdev_get_try_format(fh, BRU_PAD_SINK(0));
+ code->code = format->code;
+ }
+
+ return 0;
+}
+
+static int bru_enum_frame_size(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_frame_size_enum *fse)
+{
+ if (fse->index)
+ return -EINVAL;
+
+ if (fse->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fse->code != V4L2_MBUS_FMT_AYUV8_1X32)
+ return -EINVAL;
+
+ fse->min_width = BRU_MIN_SIZE;
+ fse->max_width = BRU_MAX_SIZE;
+ fse->min_height = BRU_MIN_SIZE;
+ fse->max_height = BRU_MAX_SIZE;
+
+ return 0;
+}
+
+static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
+ struct v4l2_subdev_fh *fh,
+ unsigned int pad, u32 which)
+{
+ switch (which) {
+ case V4L2_SUBDEV_FORMAT_TRY:
+ return v4l2_subdev_get_try_crop(fh, pad);
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
+ return &bru->compose[pad];
+ default:
+ return NULL;
+ }
+}
+
+static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct vsp1_bru *bru = to_bru(subdev);
+
+ fmt->format = *vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad,
+ fmt->which);
+
+ return 0;
+}
+
+static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_fh *fh,
+ unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_mbus_framefmt *format;
+
+ switch (pad) {
+ case BRU_PAD_SINK(0):
+ /* Default to YUV if the requested format is not supported. */
+ if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
+ break;
+
+ default:
+ /* The BRU can't perform format conversion. */
+ format = vsp1_entity_get_pad_format(&bru->entity, fh,
+ BRU_PAD_SINK(0), which);
+ fmt->code = format->code;
+ break;
+ }
+
+ fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE);
+ fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE);
+ fmt->field = V4L2_FIELD_NONE;
+ fmt->colorspace = V4L2_COLORSPACE_SRGB;
+}
+
+static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct vsp1_bru *bru = to_bru(subdev);
+ struct v4l2_mbus_framefmt *format;
+
+ bru_try_format(bru, fh, fmt->pad, &fmt->format, fmt->which);
+
+ format = vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad,
+ fmt->which);
+ *format = fmt->format;
+
+ /* Reset the compose rectangle */
+ if (fmt->pad != BRU_PAD_SOURCE) {
+ struct v4l2_rect *compose;
+
+ compose = bru_get_compose(bru, fh, fmt->pad, fmt->which);
+ compose->left = 0;
+ compose->top = 0;
+ compose->width = format->width;
+ compose->height = format->height;
+ }
+
+ /* Propagate the format code to all pads */
+ if (fmt->pad == BRU_PAD_SINK(0)) {
+ unsigned int i;
+
+ for (i = 0; i <= BRU_PAD_SOURCE; ++i) {
+ format = vsp1_entity_get_pad_format(&bru->entity, fh,
+ i, fmt->which);
+ format->code = fmt->format.code;
+ }
+ }
+
+ return 0;
+}
+
+static int bru_get_selection(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_selection *sel)
+{
+ struct vsp1_bru *bru = to_bru(subdev);
+
+ if (sel->pad == BRU_PAD_SOURCE)
+ return -EINVAL;
+
+ switch (sel->target) {
+ case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+ sel->r.left = 0;
+ sel->r.top = 0;
+ sel->r.width = BRU_MAX_SIZE;
+ sel->r.height = BRU_MAX_SIZE;
+ return 0;
+
+ case V4L2_SEL_TGT_COMPOSE:
+ sel->r = *bru_get_compose(bru, fh, sel->pad, sel->which);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bru_set_selection(struct v4l2_subdev *subdev,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_selection *sel)
+{
+ struct vsp1_bru *bru = to_bru(subdev);
+ struct v4l2_mbus_framefmt *format;
+ struct v4l2_rect *compose;
+
+ if (sel->pad == BRU_PAD_SOURCE)
+ return -EINVAL;
+
+ if (sel->target != V4L2_SEL_TGT_COMPOSE)
+ return -EINVAL;
+
+ /* The compose rectangle top left corner must be inside the output
+ * frame.
+ */
+ format = vsp1_entity_get_pad_format(&bru->entity, fh, BRU_PAD_SOURCE,
+ sel->which);
+ sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
+ sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
+
+ /* Scaling isn't supported, the compose rectangle size must be identical
+ * to the sink format size.
+ */
+ format = vsp1_entity_get_pad_format(&bru->entity, fh, sel->pad,
+ sel->which);
+ sel->r.width = format->width;
+ sel->r.height = format->height;
+
+ compose = bru_get_compose(bru, fh, sel->pad, sel->which);
+ *compose = sel->r;
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static struct v4l2_subdev_video_ops bru_video_ops = {
+ .s_stream = bru_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops bru_pad_ops = {
+ .enum_mbus_code = bru_enum_mbus_code,
+ .enum_frame_size = bru_enum_frame_size,
+ .get_fmt = bru_get_format,
+ .set_fmt = bru_set_format,
+ .get_selection = bru_get_selection,
+ .set_selection = bru_set_selection,
+};
+
+static struct v4l2_subdev_ops bru_ops = {
+ .video = &bru_video_ops,
+ .pad = &bru_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * Initialization and Cleanup
+ */
+
+struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
+{
+ struct v4l2_subdev *subdev;
+ struct vsp1_bru *bru;
+ int ret;
+
+ bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
+ if (bru == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ bru->entity.type = VSP1_ENTITY_BRU;
+
+ ret = vsp1_entity_init(vsp1, &bru->entity, 5);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ /* Initialize the V4L2 subdev. */
+ subdev = &bru->entity.subdev;
+ v4l2_subdev_init(subdev, &bru_ops);
+
+ subdev->entity.ops = &vsp1_media_ops;
+ subdev->internal_ops = &vsp1_subdev_internal_ops;
+ snprintf(subdev->name, sizeof(subdev->name), "%s bru",
+ dev_name(vsp1->dev));
+ v4l2_set_subdevdata(subdev, bru);
+ subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+ vsp1_entity_init_formats(subdev, NULL);
+
+ return bru;
+}
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h
new file mode 100644
index 000000000000..37062704dbf6
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_bru.h
@@ -0,0 +1,39 @@
+/*
+ * vsp1_bru.h -- R-Car VSP1 Blend ROP Unit
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.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.
+ */
+#ifndef __VSP1_BRU_H__
+#define __VSP1_BRU_H__
+
+#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
+
+#include "vsp1_entity.h"
+
+struct vsp1_device;
+
+#define BRU_PAD_SINK(n) (n)
+#define BRU_PAD_SOURCE 4
+
+struct vsp1_bru {
+ struct vsp1_entity entity;
+
+ struct v4l2_rect compose[4];
+};
+
+static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct vsp1_bru, entity.subdev);
+}
+
+struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1);
+
+#endif /* __VSP1_BRU_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 2f74f0e0ddf5..c69ee0657f75 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -16,10 +16,12 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include "vsp1.h"
+#include "vsp1_bru.h"
#include "vsp1_hsit.h"
#include "vsp1_lif.h"
#include "vsp1_lut.h"
@@ -155,6 +157,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
}
/* Instantiate all the entities. */
+ vsp1->bru = vsp1_bru_create(vsp1);
+ if (IS_ERR(vsp1->bru)) {
+ ret = PTR_ERR(vsp1->bru);
+ goto done;
+ }
+
+ list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities);
+
vsp1->hsi = vsp1_hsit_create(vsp1, true);
if (IS_ERR(vsp1->hsi)) {
ret = PTR_ERR(vsp1->hsi);
@@ -329,33 +339,6 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
return 0;
}
-static int vsp1_clocks_enable(struct vsp1_device *vsp1)
-{
- int ret;
-
- ret = clk_prepare_enable(vsp1->clock);
- if (ret < 0)
- return ret;
-
- if (IS_ERR(vsp1->rt_clock))
- return 0;
-
- ret = clk_prepare_enable(vsp1->rt_clock);
- if (ret < 0) {
- clk_disable_unprepare(vsp1->clock);
- return ret;
- }
-
- return 0;
-}
-
-static void vsp1_clocks_disable(struct vsp1_device *vsp1)
-{
- if (!IS_ERR(vsp1->rt_clock))
- clk_disable_unprepare(vsp1->rt_clock);
- clk_disable_unprepare(vsp1->clock);
-}
-
/*
* vsp1_device_get - Acquire the VSP1 device
*
@@ -373,7 +356,7 @@ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
if (vsp1->ref_count > 0)
goto done;
- ret = vsp1_clocks_enable(vsp1);
+ ret = clk_prepare_enable(vsp1->clock);
if (ret < 0) {
__vsp1 = NULL;
goto done;
@@ -381,7 +364,7 @@ struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
ret = vsp1_device_init(vsp1);
if (ret < 0) {
- vsp1_clocks_disable(vsp1);
+ clk_disable_unprepare(vsp1->clock);
__vsp1 = NULL;
goto done;
}
@@ -405,7 +388,7 @@ void vsp1_device_put(struct vsp1_device *vsp1)
mutex_lock(&vsp1->lock);
if (--vsp1->ref_count == 0)
- vsp1_clocks_disable(vsp1);
+ clk_disable_unprepare(vsp1->clock);
mutex_unlock(&vsp1->lock);
}
@@ -424,7 +407,7 @@ static int vsp1_pm_suspend(struct device *dev)
if (vsp1->ref_count == 0)
return 0;
- vsp1_clocks_disable(vsp1);
+ clk_disable_unprepare(vsp1->clock);
return 0;
}
@@ -437,7 +420,7 @@ static int vsp1_pm_resume(struct device *dev)
if (vsp1->ref_count)
return 0;
- return vsp1_clocks_enable(vsp1);
+ return clk_prepare_enable(vsp1->clock);
}
#endif
@@ -449,34 +432,59 @@ static const struct dev_pm_ops vsp1_pm_ops = {
* Platform Driver
*/
-static struct vsp1_platform_data *
-vsp1_get_platform_data(struct platform_device *pdev)
+static int vsp1_validate_platform_data(struct platform_device *pdev,
+ struct vsp1_platform_data *pdata)
{
- struct vsp1_platform_data *pdata = pdev->dev.platform_data;
-
if (pdata == NULL) {
dev_err(&pdev->dev, "missing platform data\n");
- return NULL;
+ return -EINVAL;
}
if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) {
dev_err(&pdev->dev, "invalid number of RPF (%u)\n",
pdata->rpf_count);
- return NULL;
+ return -EINVAL;
}
if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) {
dev_err(&pdev->dev, "invalid number of UDS (%u)\n",
pdata->uds_count);
- return NULL;
+ return -EINVAL;
}
if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) {
dev_err(&pdev->dev, "invalid number of WPF (%u)\n",
pdata->wpf_count);
- return NULL;
+ return -EINVAL;
}
+ return 0;
+}
+
+static struct vsp1_platform_data *
+vsp1_get_platform_data(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct vsp1_platform_data *pdata;
+
+ if (!IS_ENABLED(CONFIG_OF) || np == NULL)
+ return pdev->dev.platform_data;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL)
+ return NULL;
+
+ if (of_property_read_bool(np, "renesas,has-lif"))
+ pdata->features |= VSP1_HAS_LIF;
+ if (of_property_read_bool(np, "renesas,has-lut"))
+ pdata->features |= VSP1_HAS_LUT;
+ if (of_property_read_bool(np, "renesas,has-sru"))
+ pdata->features |= VSP1_HAS_SRU;
+
+ of_property_read_u32(np, "renesas,#rpf", &pdata->rpf_count);
+ of_property_read_u32(np, "renesas,#uds", &pdata->uds_count);
+ of_property_read_u32(np, "renesas,#wpf", &pdata->wpf_count);
+
return pdata;
}
@@ -499,6 +507,10 @@ static int vsp1_probe(struct platform_device *pdev)
if (vsp1->pdata == NULL)
return -ENODEV;
+ ret = vsp1_validate_platform_data(pdev, vsp1->pdata);
+ if (ret < 0)
+ return ret;
+
/* I/O, IRQ and clock resources */
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
vsp1->mmio = devm_ioremap_resource(&pdev->dev, io);
@@ -511,9 +523,6 @@ static int vsp1_probe(struct platform_device *pdev)
return PTR_ERR(vsp1->clock);
}
- /* The RT clock is optional */
- vsp1->rt_clock = devm_clk_get(&pdev->dev, "rt");
-
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "missing IRQ\n");
@@ -548,6 +557,11 @@ static int vsp1_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id vsp1_of_match[] = {
+ { .compatible = "renesas,vsp1" },
+ { },
+};
+
static struct platform_driver vsp1_platform_driver = {
.probe = vsp1_probe,
.remove = vsp1_remove,
@@ -555,6 +569,7 @@ static struct platform_driver vsp1_platform_driver = {
.owner = THIS_MODULE,
.name = "vsp1",
.pm = &vsp1_pm_ops,
+ .of_match_table = vsp1_of_match,
},
};
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 3fc9e4266caf..44167834285d 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -100,8 +100,10 @@ static int vsp1_entity_link_setup(struct media_entity *entity,
if (source->sink)
return -EBUSY;
source->sink = remote->entity;
+ source->sink_pad = remote->index;
} else {
source->sink = NULL;
+ source->sink_pad = 0;
}
return 0;
@@ -116,42 +118,43 @@ const struct media_entity_operations vsp1_media_ops = {
* Initialization
*/
+static const struct vsp1_route vsp1_routes[] = {
+ { VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE,
+ { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1),
+ VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), } },
+ { VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } },
+ { VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } },
+ { VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } },
+ { VSP1_ENTITY_LUT, 0, VI6_DPR_LUT_ROUTE, { VI6_DPR_NODE_LUT, } },
+ { VSP1_ENTITY_RPF, 0, VI6_DPR_RPF_ROUTE(0), { VI6_DPR_NODE_RPF(0), } },
+ { VSP1_ENTITY_RPF, 1, VI6_DPR_RPF_ROUTE(1), { VI6_DPR_NODE_RPF(1), } },
+ { VSP1_ENTITY_RPF, 2, VI6_DPR_RPF_ROUTE(2), { VI6_DPR_NODE_RPF(2), } },
+ { VSP1_ENTITY_RPF, 3, VI6_DPR_RPF_ROUTE(3), { VI6_DPR_NODE_RPF(3), } },
+ { VSP1_ENTITY_RPF, 4, VI6_DPR_RPF_ROUTE(4), { VI6_DPR_NODE_RPF(4), } },
+ { VSP1_ENTITY_SRU, 0, VI6_DPR_SRU_ROUTE, { VI6_DPR_NODE_SRU, } },
+ { VSP1_ENTITY_UDS, 0, VI6_DPR_UDS_ROUTE(0), { VI6_DPR_NODE_UDS(0), } },
+ { VSP1_ENTITY_UDS, 1, VI6_DPR_UDS_ROUTE(1), { VI6_DPR_NODE_UDS(1), } },
+ { VSP1_ENTITY_UDS, 2, VI6_DPR_UDS_ROUTE(2), { VI6_DPR_NODE_UDS(2), } },
+ { VSP1_ENTITY_WPF, 0, 0, { VI6_DPR_NODE_WPF(0), } },
+ { VSP1_ENTITY_WPF, 1, 0, { VI6_DPR_NODE_WPF(1), } },
+ { VSP1_ENTITY_WPF, 2, 0, { VI6_DPR_NODE_WPF(2), } },
+ { VSP1_ENTITY_WPF, 3, 0, { VI6_DPR_NODE_WPF(3), } },
+};
+
int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
unsigned int num_pads)
{
- static const struct {
- unsigned int id;
- unsigned int reg;
- } routes[] = {
- { VI6_DPR_NODE_HSI, VI6_DPR_HSI_ROUTE },
- { VI6_DPR_NODE_HST, VI6_DPR_HST_ROUTE },
- { VI6_DPR_NODE_LIF, 0 },
- { VI6_DPR_NODE_LUT, VI6_DPR_LUT_ROUTE },
- { VI6_DPR_NODE_RPF(0), VI6_DPR_RPF_ROUTE(0) },
- { VI6_DPR_NODE_RPF(1), VI6_DPR_RPF_ROUTE(1) },
- { VI6_DPR_NODE_RPF(2), VI6_DPR_RPF_ROUTE(2) },
- { VI6_DPR_NODE_RPF(3), VI6_DPR_RPF_ROUTE(3) },
- { VI6_DPR_NODE_RPF(4), VI6_DPR_RPF_ROUTE(4) },
- { VI6_DPR_NODE_SRU, VI6_DPR_SRU_ROUTE },
- { VI6_DPR_NODE_UDS(0), VI6_DPR_UDS_ROUTE(0) },
- { VI6_DPR_NODE_UDS(1), VI6_DPR_UDS_ROUTE(1) },
- { VI6_DPR_NODE_UDS(2), VI6_DPR_UDS_ROUTE(2) },
- { VI6_DPR_NODE_WPF(0), 0 },
- { VI6_DPR_NODE_WPF(1), 0 },
- { VI6_DPR_NODE_WPF(2), 0 },
- { VI6_DPR_NODE_WPF(3), 0 },
- };
-
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(routes); ++i) {
- if (routes[i].id == entity->id) {
- entity->route = routes[i].reg;
+ for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
+ if (vsp1_routes[i].type == entity->type &&
+ vsp1_routes[i].index == entity->index) {
+ entity->route = &vsp1_routes[i];
break;
}
}
- if (i == ARRAY_SIZE(routes))
+ if (i == ARRAY_SIZE(vsp1_routes))
return -EINVAL;
entity->vsp1 = vsp1;
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index f6fd6988aeb0..7afbd8a7ba66 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -20,6 +20,7 @@
struct vsp1_device;
enum vsp1_entity_type {
+ VSP1_ENTITY_BRU,
VSP1_ENTITY_HSI,
VSP1_ENTITY_HST,
VSP1_ENTITY_LIF,
@@ -30,13 +31,31 @@ enum vsp1_entity_type {
VSP1_ENTITY_WPF,
};
+/*
+ * struct vsp1_route - Entity routing configuration
+ * @type: Entity type this routing entry is associated with
+ * @index: Entity index this routing entry is associated with
+ * @reg: Output routing configuration register
+ * @inputs: Target node value for each input
+ *
+ * Each $vsp1_route entry describes routing configuration for the entity
+ * specified by the entry's @type and @index. @reg indicates the register that
+ * holds output routing configuration for the entity, and the @inputs array
+ * store the target node value for each input of the entity.
+ */
+struct vsp1_route {
+ enum vsp1_entity_type type;
+ unsigned int index;
+ unsigned int reg;
+ unsigned int inputs[4];
+};
+
struct vsp1_entity {
struct vsp1_device *vsp1;
enum vsp1_entity_type type;
unsigned int index;
- unsigned int id;
- unsigned int route;
+ const struct vsp1_route *route;
struct list_head list_dev;
struct list_head list_pipe;
@@ -45,6 +64,7 @@ struct vsp1_entity {
unsigned int source_pad;
struct media_entity *sink;
+ unsigned int sink_pad;
struct v4l2_subdev subdev;
struct v4l2_mbus_framefmt *formats;
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 285485350d82..db2950a73c60 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -193,13 +193,10 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse)
hsit->inverse = inverse;
- if (inverse) {
+ if (inverse)
hsit->entity.type = VSP1_ENTITY_HSI;
- hsit->entity.id = VI6_DPR_NODE_HSI;
- } else {
+ else
hsit->entity.type = VSP1_ENTITY_HST;
- hsit->entity.id = VI6_DPR_NODE_HST;
- }
ret = vsp1_entity_init(vsp1, &hsit->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 135a78957014..d4fb23e9c4a8 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -215,7 +215,6 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
return ERR_PTR(-ENOMEM);
lif->entity.type = VSP1_ENTITY_LIF;
- lif->entity.id = VI6_DPR_NODE_LIF;
ret = vsp1_entity_init(vsp1, &lif->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 4e9dc7c86ef8..fea36ebe2565 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -229,7 +229,6 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
return ERR_PTR(-ENOMEM);
lut->entity.type = VSP1_ENTITY_LUT;
- lut->entity.id = VI6_DPR_NODE_LUT;
ret = vsp1_entity_init(vsp1, &lut->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 28650806c20f..3e74b44286f6 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -451,13 +451,111 @@
* BRU Control Registers
*/
+#define VI6_ROP_NOP 0
+#define VI6_ROP_AND 1
+#define VI6_ROP_AND_REV 2
+#define VI6_ROP_COPY 3
+#define VI6_ROP_AND_INV 4
+#define VI6_ROP_CLEAR 5
+#define VI6_ROP_XOR 6
+#define VI6_ROP_OR 7
+#define VI6_ROP_NOR 8
+#define VI6_ROP_EQUIV 9
+#define VI6_ROP_INVERT 10
+#define VI6_ROP_OR_REV 11
+#define VI6_ROP_COPY_INV 12
+#define VI6_ROP_OR_INV 13
+#define VI6_ROP_NAND 14
+#define VI6_ROP_SET 15
+
#define VI6_BRU_INCTRL 0x2c00
+#define VI6_BRU_INCTRL_NRM (1 << 28)
+#define VI6_BRU_INCTRL_DnON (1 << (16 + (n)))
+#define VI6_BRU_INCTRL_DITHn_OFF (0 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_18BPP (1 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_16BPP (2 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_15BPP (3 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_12BPP (4 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_8BPP (5 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_MASK (7 << ((n) * 4))
+#define VI6_BRU_INCTRL_DITHn_SHIFT ((n) * 4)
+
#define VI6_BRU_VIRRPF_SIZE 0x2c04
+#define VI6_BRU_VIRRPF_SIZE_HSIZE_MASK (0x1fff << 16)
+#define VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT 16
+#define VI6_BRU_VIRRPF_SIZE_VSIZE_MASK (0x1fff << 0)
+#define VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT 0
+
#define VI6_BRU_VIRRPF_LOC 0x2c08
+#define VI6_BRU_VIRRPF_LOC_HCOORD_MASK (0x1fff << 16)
+#define VI6_BRU_VIRRPF_LOC_HCOORD_SHIFT 16
+#define VI6_BRU_VIRRPF_LOC_VCOORD_MASK (0x1fff << 0)
+#define VI6_BRU_VIRRPF_LOC_VCOORD_SHIFT 0
+
#define VI6_BRU_VIRRPF_COL 0x2c0c
+#define VI6_BRU_VIRRPF_COL_A_MASK (0xff << 24)
+#define VI6_BRU_VIRRPF_COL_A_SHIFT 24
+#define VI6_BRU_VIRRPF_COL_RCR_MASK (0xff << 16)
+#define VI6_BRU_VIRRPF_COL_RCR_SHIFT 16
+#define VI6_BRU_VIRRPF_COL_GY_MASK (0xff << 8)
+#define VI6_BRU_VIRRPF_COL_GY_SHIFT 8
+#define VI6_BRU_VIRRPF_COL_BCB_MASK (0xff << 0)
+#define VI6_BRU_VIRRPF_COL_BCB_SHIFT 0
+
#define VI6_BRU_CTRL(n) (0x2c10 + (n) * 8)
+#define VI6_BRU_CTRL_RBC (1 << 31)
+#define VI6_BRU_CTRL_DSTSEL_BRUIN(n) ((n) << 20)
+#define VI6_BRU_CTRL_DSTSEL_VRPF (4 << 20)
+#define VI6_BRU_CTRL_DSTSEL_MASK (7 << 20)
+#define VI6_BRU_CTRL_SRCSEL_BRUIN(n) ((n) << 16)
+#define VI6_BRU_CTRL_SRCSEL_VRPF (4 << 16)
+#define VI6_BRU_CTRL_SRCSEL_MASK (7 << 16)
+#define VI6_BRU_CTRL_CROP(rop) ((rop) << 4)
+#define VI6_BRU_CTRL_CROP_MASK (0xf << 4)
+#define VI6_BRU_CTRL_AROP(rop) ((rop) << 0)
+#define VI6_BRU_CTRL_AROP_MASK (0xf << 0)
+
#define VI6_BRU_BLD(n) (0x2c14 + (n) * 8)
+#define VI6_BRU_BLD_CBES (1 << 31)
+#define VI6_BRU_BLD_CCMDX_DST_A (0 << 28)
+#define VI6_BRU_BLD_CCMDX_255_DST_A (1 << 28)
+#define VI6_BRU_BLD_CCMDX_SRC_A (2 << 28)
+#define VI6_BRU_BLD_CCMDX_255_SRC_A (3 << 28)
+#define VI6_BRU_BLD_CCMDX_COEFX (4 << 28)
+#define VI6_BRU_BLD_CCMDX_MASK (7 << 28)
+#define VI6_BRU_BLD_CCMDY_DST_A (0 << 24)
+#define VI6_BRU_BLD_CCMDY_255_DST_A (1 << 24)
+#define VI6_BRU_BLD_CCMDY_SRC_A (2 << 24)
+#define VI6_BRU_BLD_CCMDY_255_SRC_A (3 << 24)
+#define VI6_BRU_BLD_CCMDY_COEFY (4 << 24)
+#define VI6_BRU_BLD_CCMDY_MASK (7 << 24)
+#define VI6_BRU_BLD_CCMDY_SHIFT 24
+#define VI6_BRU_BLD_ABES (1 << 23)
+#define VI6_BRU_BLD_ACMDX_DST_A (0 << 20)
+#define VI6_BRU_BLD_ACMDX_255_DST_A (1 << 20)
+#define VI6_BRU_BLD_ACMDX_SRC_A (2 << 20)
+#define VI6_BRU_BLD_ACMDX_255_SRC_A (3 << 20)
+#define VI6_BRU_BLD_ACMDX_COEFX (4 << 20)
+#define VI6_BRU_BLD_ACMDX_MASK (7 << 20)
+#define VI6_BRU_BLD_ACMDY_DST_A (0 << 16)
+#define VI6_BRU_BLD_ACMDY_255_DST_A (1 << 16)
+#define VI6_BRU_BLD_ACMDY_SRC_A (2 << 16)
+#define VI6_BRU_BLD_ACMDY_255_SRC_A (3 << 16)
+#define VI6_BRU_BLD_ACMDY_COEFY (4 << 16)
+#define VI6_BRU_BLD_ACMDY_MASK (7 << 16)
+#define VI6_BRU_BLD_COEFX_MASK (0xff << 8)
+#define VI6_BRU_BLD_COEFX_SHIFT 8
+#define VI6_BRU_BLD_COEFY_MASK (0xff << 0)
+#define VI6_BRU_BLD_COEFY_SHIFT 0
+
#define VI6_BRU_ROP 0x2c30
+#define VI6_BRU_ROP_DSTSEL_BRUIN(n) ((n) << 20)
+#define VI6_BRU_ROP_DSTSEL_VRPF (4 << 20)
+#define VI6_BRU_ROP_DSTSEL_MASK (7 << 20)
+#define VI6_BRU_ROP_CROP(rop) ((rop) << 4)
+#define VI6_BRU_ROP_CROP_MASK (0xf << 4)
+#define VI6_BRU_ROP_AROP(rop) ((rop) << 0)
+#define VI6_BRU_ROP_AROP_MASK (0xf << 0)
/* -----------------------------------------------------------------------------
* HGO Control Registers
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 2b04d0f95c62..c3d98642a4aa 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -96,8 +96,10 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
vsp1_rpf_write(rpf, VI6_RPF_INFMT, infmt);
vsp1_rpf_write(rpf, VI6_RPF_DSWAP, fmtinfo->swap);
- /* Output location. Composing isn't supported yet. */
- vsp1_rpf_write(rpf, VI6_RPF_LOC, 0);
+ /* Output location */
+ vsp1_rpf_write(rpf, VI6_RPF_LOC,
+ (rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) |
+ (rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT));
/* Disable alpha, mask and color key. Set the alpha channel to a fixed
* value of 255.
@@ -176,7 +178,6 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
rpf->entity.type = VSP1_ENTITY_RPF;
rpf->entity.index = index;
- rpf->entity.id = VI6_DPR_NODE_RPF(index);
ret = vsp1_entity_init(vsp1, &rpf->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 5c5ee81bbeae..b4fb65e58770 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -30,6 +30,10 @@ struct vsp1_rwpf {
unsigned int max_width;
unsigned int max_height;
+ struct {
+ unsigned int left;
+ unsigned int top;
+ } location;
struct v4l2_rect crop;
unsigned int offsets[2];
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 7ab1a0b2d656..aa0e04c56f3f 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -327,7 +327,6 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
return ERR_PTR(-ENOMEM);
sru->entity.type = VSP1_ENTITY_SRU;
- sru->entity.id = VI6_DPR_NODE_SRU;
ret = vsp1_entity_init(vsp1, &sru->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index 622342ac7770..0293bdbb4401 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -131,7 +131,7 @@ static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
return 0;
/* Enable multi-tap scaling. */
- vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_BC);
+ vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_AON | VI6_UDS_CTRL_BC);
vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
(uds_passband_width(uds->hscale)
@@ -139,7 +139,6 @@ static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
(uds_passband_width(uds->vscale)
<< VI6_UDS_PASS_BWIDTH_V_SHIFT));
-
/* Set the scaling ratios and the output size. */
format = &uds->entity.formats[UDS_PAD_SOURCE];
@@ -323,7 +322,6 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index)
uds->entity.type = VSP1_ENTITY_UDS;
uds->entity.index = index;
- uds->entity.id = VI6_DPR_NODE_UDS(index);
ret = vsp1_entity_init(vsp1, &uds->entity, 2);
if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index a0595c17700f..8a1253e51f04 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -28,6 +28,7 @@
#include <media/videobuf2-dma-contig.h>
#include "vsp1.h"
+#include "vsp1_bru.h"
#include "vsp1_entity.h"
#include "vsp1_rwpf.h"
#include "vsp1_video.h"
@@ -280,6 +281,9 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
struct media_pad *pad;
bool uds_found = false;
+ input->location.left = 0;
+ input->location.top = 0;
+
pad = media_entity_remote_pad(&input->entity.pads[RWPF_PAD_SOURCE]);
while (1) {
@@ -292,6 +296,17 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
+ /* A BRU is present in the pipeline, store the compose rectangle
+ * location in the input RPF for use when configuring the RPF.
+ */
+ if (entity->type == VSP1_ENTITY_BRU) {
+ struct vsp1_bru *bru = to_bru(&entity->subdev);
+ struct v4l2_rect *rect = &bru->compose[pad->index];
+
+ input->location.left = rect->left;
+ input->location.top = rect->top;
+ }
+
/* We've reached the WPF, we're done. */
if (entity->type == VSP1_ENTITY_WPF)
break;
@@ -363,6 +378,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
rwpf->video.pipe_index = 0;
} else if (e->type == VSP1_ENTITY_LIF) {
pipe->lif = e;
+ } else if (e->type == VSP1_ENTITY_BRU) {
+ pipe->bru = e;
}
}
@@ -392,6 +409,7 @@ error:
pipe->num_video = 0;
pipe->num_inputs = 0;
pipe->output = NULL;
+ pipe->bru = NULL;
pipe->lif = NULL;
return ret;
}
@@ -430,6 +448,7 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
pipe->num_video = 0;
pipe->num_inputs = 0;
pipe->output = NULL;
+ pipe->bru = NULL;
pipe->lif = NULL;
}
@@ -461,7 +480,7 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
list_for_each_entry(entity, &pipe->entities, list_pipe) {
if (entity->route)
- vsp1_write(entity->vsp1, entity->route,
+ vsp1_write(entity->vsp1, entity->route->reg,
VI6_DPR_NODE_UNUSED);
v4l2_subdev_call(&entity->subdev, video, s_stream, 0);
@@ -680,11 +699,12 @@ static void vsp1_entity_route_setup(struct vsp1_entity *source)
{
struct vsp1_entity *sink;
- if (source->route == 0)
+ if (source->route->reg == 0)
return;
sink = container_of(source->sink, struct vsp1_entity, subdev.entity);
- vsp1_write(source->vsp1, source->route, sink->id);
+ vsp1_write(source->vsp1, source->route->reg,
+ sink->route->inputs[source->sink_pad]);
}
static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 53e4b3745940..c04d48fa2999 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -75,6 +75,7 @@ struct vsp1_pipeline {
unsigned int num_inputs;
struct vsp1_rwpf *inputs[VPS1_MAX_RPF];
struct vsp1_rwpf *output;
+ struct vsp1_entity *bru;
struct vsp1_entity *lif;
struct list_head entities;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 11a61c601da0..1294340dcb36 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -58,13 +58,21 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
return 0;
}
- /* Sources */
+ /* Sources. If the pipeline has a single input configure it as the
+ * master layer. Otherwise configure all inputs as sub-layers and
+ * select the virtual RPF as the master layer.
+ */
for (i = 0; i < pipe->num_inputs; ++i) {
struct vsp1_rwpf *input = pipe->inputs[i];
- srcrpf |= VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index);
+ srcrpf |= pipe->num_inputs == 1
+ ? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
+ : VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
}
+ if (pipe->num_inputs > 1)
+ srcrpf |= VI6_WPF_SRCRPF_VIRACT_MST;
+
vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, srcrpf);
/* Destination stride. */
@@ -181,7 +189,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
wpf->entity.type = VSP1_ENTITY_WPF;
wpf->entity.index = index;
- wpf->entity.id = VI6_DPR_NODE_WPF(index);
ret = vsp1_entity_init(vsp1, &wpf->entity, 2);
if (ret < 0)
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
index 1b37cf8cd204..7310e32b5991 100644
--- a/drivers/memstick/host/Kconfig
+++ b/drivers/memstick/host/Kconfig
@@ -52,3 +52,13 @@ config MEMSTICK_REALTEK_PCI
To compile this driver as a module, choose M here: the module will
be called rtsx_pci_ms.
+
+config MEMSTICK_REALTEK_USB
+ tristate "Realtek USB Memstick Card Interface Driver"
+ depends on MFD_RTSX_USB
+ help
+ Say Y here to include driver code to support Memstick card interface
+ of Realtek RTS5129/39 series USB card reader
+
+ To compile this driver as a module, choose M here: the module will
+ be called rts5139_ms.
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index af3459d7686e..491c9557441d 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o
obj-$(CONFIG_MEMSTICK_R592) += r592.o
obj-$(CONFIG_MEMSTICK_REALTEK_PCI) += rtsx_pci_ms.o
+obj-$(CONFIG_MEMSTICK_REALTEK_USB) += rtsx_usb_ms.o
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
new file mode 100644
index 000000000000..a7282b7d4de8
--- /dev/null
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -0,0 +1,839 @@
+/* Realtek USB Memstick Card Interface driver
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Roger Tseng <rogerable@realtek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/memstick.h>
+#include <linux/kthread.h>
+#include <linux/mfd/rtsx_usb.h>
+#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <asm/unaligned.h>
+
+struct rtsx_usb_ms {
+ struct platform_device *pdev;
+ struct rtsx_ucr *ucr;
+ struct memstick_host *msh;
+ struct memstick_request *req;
+
+ struct mutex host_mutex;
+ struct work_struct handle_req;
+
+ struct task_struct *detect_ms;
+ struct completion detect_ms_exit;
+
+ u8 ssc_depth;
+ unsigned int clock;
+ int power_mode;
+ unsigned char ifmode;
+ bool eject;
+};
+
+static inline struct device *ms_dev(struct rtsx_usb_ms *host)
+{
+ return &(host->pdev->dev);
+}
+
+static inline void ms_clear_error(struct rtsx_usb_ms *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ rtsx_usb_ep0_write_register(ucr, CARD_STOP,
+ MS_STOP | MS_CLR_ERR,
+ MS_STOP | MS_CLR_ERR);
+
+ rtsx_usb_clear_dma_err(ucr);
+ rtsx_usb_clear_fsm_err(ucr);
+}
+
+#ifdef DEBUG
+
+static void ms_print_debug_regs(struct rtsx_usb_ms *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ u16 i;
+ u8 *ptr;
+
+ /* Print MS host internal registers */
+ rtsx_usb_init_cmd(ucr);
+
+ /* MS_CFG to MS_INT_REG */
+ for (i = 0xFD40; i <= 0xFD44; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);
+
+ /* CARD_SHARE_MODE to CARD_GPIO */
+ for (i = 0xFD51; i <= 0xFD56; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);
+
+ /* CARD_PULL_CTLx */
+ for (i = 0xFD60; i <= 0xFD65; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, i, 0, 0);
+
+ /* CARD_DATA_SOURCE, CARD_SELECT, CARD_CLK_EN, CARD_PWR_CTL */
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_DATA_SOURCE, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_SELECT, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_CLK_EN, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_PWR_CTL, 0, 0);
+
+ rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ rtsx_usb_get_rsp(ucr, 21, 100);
+
+ ptr = ucr->rsp_buf;
+ for (i = 0xFD40; i <= 0xFD44; i++)
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+ for (i = 0xFD51; i <= 0xFD56; i++)
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+ for (i = 0xFD60; i <= 0xFD65; i++)
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", i, *(ptr++));
+
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_DATA_SOURCE, *(ptr++));
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_SELECT, *(ptr++));
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_CLK_EN, *(ptr++));
+ dev_dbg(ms_dev(host), "0x%04X: 0x%02x\n", CARD_PWR_CTL, *(ptr++));
+}
+
+#else
+
+static void ms_print_debug_regs(struct rtsx_usb_ms *host)
+{
+}
+
+#endif
+
+static int ms_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int ms_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int ms_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int ms_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int ms_power_on(struct rtsx_usb_ms *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ dev_dbg(ms_dev(host), "%s\n", __func__);
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, MS_MOD_SEL);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_MS);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN,
+ MS_CLK_EN, MS_CLK_EN);
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (err < 0)
+ return err;
+
+ if (CHECK_PKG(ucr, LQFP48))
+ err = ms_pull_ctl_enable_lqfp48(ucr);
+ else
+ err = ms_pull_ctl_enable_qfn24(ucr);
+ if (err < 0)
+ return err;
+
+ err = rtsx_usb_write_register(ucr, CARD_PWR_CTL,
+ POWER_MASK, PARTIAL_POWER_ON);
+ if (err)
+ return err;
+
+ usleep_range(800, 1000);
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ POWER_MASK, POWER_ON);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE,
+ MS_OUTPUT_EN, MS_OUTPUT_EN);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int ms_power_off(struct rtsx_usb_ms *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ dev_dbg(ms_dev(host), "%s\n", __func__);
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, MS_CLK_EN, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, MS_OUTPUT_EN, 0);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (err < 0)
+ return err;
+
+ if (CHECK_PKG(ucr, LQFP48))
+ return ms_pull_ctl_disable_lqfp48(ucr);
+
+ return ms_pull_ctl_disable_qfn24(ucr);
+}
+
+static int ms_transfer_data(struct rtsx_usb_ms *host, unsigned char data_dir,
+ u8 tpc, u8 cfg, struct scatterlist *sg)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ unsigned int length = sg->length;
+ u16 sec_cnt = (u16)(length / 512);
+ u8 trans_mode, dma_dir, flag;
+ unsigned int pipe;
+ struct memstick_dev *card = host->msh->card;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n",
+ __func__, tpc, (data_dir == READ) ? "READ" : "WRITE",
+ length);
+
+ if (data_dir == READ) {
+ flag = MODE_CDIR;
+ dma_dir = DMA_DIR_FROM_CARD;
+ if (card->id.type != MEMSTICK_TYPE_PRO)
+ trans_mode = MS_TM_NORMAL_READ;
+ else
+ trans_mode = MS_TM_AUTO_READ;
+ pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN);
+ } else {
+ flag = MODE_CDOR;
+ dma_dir = DMA_DIR_TO_CARD;
+ if (card->id.type != MEMSTICK_TYPE_PRO)
+ trans_mode = MS_TM_NORMAL_WRITE;
+ else
+ trans_mode = MS_TM_AUTO_WRITE;
+ pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT);
+ }
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ if (card->id.type == MEMSTICK_TYPE_PRO) {
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_H,
+ 0xFF, (u8)(sec_cnt >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_SECTOR_CNT_L,
+ 0xFF, (u8)sec_cnt);
+ }
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3,
+ 0xFF, (u8)(length >> 24));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2,
+ 0xFF, (u8)(length >> 16));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1,
+ 0xFF, (u8)(length >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0, 0xFF,
+ (u8)length);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL,
+ 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, RING_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | trans_mode);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+
+ err = rtsx_usb_send_cmd(ucr, flag | STAGE_MS_STATUS, 100);
+ if (err)
+ return err;
+
+ err = rtsx_usb_transfer_data(ucr, pipe, sg, length,
+ 1, NULL, 10000);
+ if (err)
+ goto err_out;
+
+ err = rtsx_usb_get_rsp(ucr, 3, 15000);
+ if (err)
+ goto err_out;
+
+ if (ucr->rsp_buf[0] & MS_TRANSFER_ERR ||
+ ucr->rsp_buf[1] & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
+ err = -EIO;
+ goto err_out;
+ }
+ return 0;
+err_out:
+ ms_clear_error(host);
+ return err;
+}
+
+static int ms_write_bytes(struct rtsx_usb_ms *host, u8 tpc,
+ u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err, i;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+ rtsx_usb_init_cmd(ucr);
+
+ for (i = 0; i < cnt; i++)
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ PPBUF_BASE2 + i, 0xFF, data[i]);
+
+ if (cnt % 2)
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ PPBUF_BASE2 + i, 0xFF, 0xFF);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ if (err)
+ return err;
+
+ err = rtsx_usb_get_rsp(ucr, 2, 5000);
+ if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) {
+ u8 val;
+
+ rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val);
+ dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+ if (int_reg)
+ *int_reg = val & 0x0F;
+
+ ms_print_debug_regs(host);
+
+ ms_clear_error(host);
+
+ if (!(tpc & 0x08)) {
+ if (val & MS_CRC16_ERR)
+ return -EIO;
+ } else {
+ if (!(val & 0x80)) {
+ if (val & (MS_INT_ERR | MS_INT_CMDNK))
+ return -EIO;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ if (int_reg)
+ *int_reg = ucr->rsp_buf[1] & 0x0F;
+
+ return 0;
+}
+
+static int ms_read_bytes(struct rtsx_usb_ms *host, u8 tpc,
+ u8 cfg, u8 cnt, u8 *data, u8 *int_reg)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err, i;
+ u8 *ptr;
+
+ dev_dbg(ms_dev(host), "%s: tpc = 0x%02x\n", __func__, tpc);
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MS_TRANSFER,
+ 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, MS_TRANSFER,
+ MS_TRANSFER_END, MS_TRANSFER_END);
+ for (i = 0; i < cnt - 1; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+ if (cnt % 2)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, PPBUF_BASE2 + cnt, 0, 0);
+ else
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD,
+ PPBUF_BASE2 + cnt - 1, 0, 0);
+
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ if (err)
+ return err;
+
+ err = rtsx_usb_get_rsp(ucr, cnt + 2, 5000);
+ if (err || (ucr->rsp_buf[0] & MS_TRANSFER_ERR)) {
+ u8 val;
+
+ rtsx_usb_ep0_read_register(ucr, MS_TRANS_CFG, &val);
+ dev_dbg(ms_dev(host), "MS_TRANS_CFG: 0x%02x\n", val);
+
+ if (int_reg && (host->ifmode != MEMSTICK_SERIAL))
+ *int_reg = val & 0x0F;
+
+ ms_print_debug_regs(host);
+
+ ms_clear_error(host);
+
+ if (!(tpc & 0x08)) {
+ if (val & MS_CRC16_ERR)
+ return -EIO;
+ } else {
+ if (!(val & 0x80)) {
+ if (val & (MS_INT_ERR | MS_INT_CMDNK))
+ return -EIO;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ ptr = ucr->rsp_buf + 1;
+ for (i = 0; i < cnt; i++)
+ data[i] = *ptr++;
+
+
+ if (int_reg && (host->ifmode != MEMSTICK_SERIAL))
+ *int_reg = *ptr & 0x0F;
+
+ return 0;
+}
+
+static int rtsx_usb_ms_issue_cmd(struct rtsx_usb_ms *host)
+{
+ struct memstick_request *req = host->req;
+ int err = 0;
+ u8 cfg = 0, int_reg;
+
+ dev_dbg(ms_dev(host), "%s\n", __func__);
+
+ if (req->need_card_int) {
+ if (host->ifmode != MEMSTICK_SERIAL)
+ cfg = WAIT_INT;
+ }
+
+ if (req->long_data) {
+ err = ms_transfer_data(host, req->data_dir,
+ req->tpc, cfg, &(req->sg));
+ } else {
+ if (req->data_dir == READ)
+ err = ms_read_bytes(host, req->tpc, cfg,
+ req->data_len, req->data, &int_reg);
+ else
+ err = ms_write_bytes(host, req->tpc, cfg,
+ req->data_len, req->data, &int_reg);
+ }
+ if (err < 0)
+ return err;
+
+ if (req->need_card_int) {
+ if (host->ifmode == MEMSTICK_SERIAL) {
+ err = ms_read_bytes(host, MS_TPC_GET_INT,
+ NO_WAIT_INT, 1, &req->int_reg, NULL);
+ if (err < 0)
+ return err;
+ } else {
+
+ if (int_reg & MS_INT_CMDNK)
+ req->int_reg |= MEMSTICK_INT_CMDNAK;
+ if (int_reg & MS_INT_BREQ)
+ req->int_reg |= MEMSTICK_INT_BREQ;
+ if (int_reg & MS_INT_ERR)
+ req->int_reg |= MEMSTICK_INT_ERR;
+ if (int_reg & MS_INT_CED)
+ req->int_reg |= MEMSTICK_INT_CED;
+ }
+ dev_dbg(ms_dev(host), "int_reg: 0x%02x\n", req->int_reg);
+ }
+
+ return 0;
+}
+
+static void rtsx_usb_ms_handle_req(struct work_struct *work)
+{
+ struct rtsx_usb_ms *host = container_of(work,
+ struct rtsx_usb_ms, handle_req);
+ struct rtsx_ucr *ucr = host->ucr;
+ struct memstick_host *msh = host->msh;
+ int rc;
+
+ if (!host->req) {
+ do {
+ rc = memstick_next_req(msh, &host->req);
+ dev_dbg(ms_dev(host), "next req %d\n", rc);
+
+ if (!rc) {
+ mutex_lock(&ucr->dev_mutex);
+
+ if (rtsx_usb_card_exclusive_check(ucr,
+ RTSX_USB_MS_CARD))
+ host->req->error = -EIO;
+ else
+ host->req->error =
+ rtsx_usb_ms_issue_cmd(host);
+
+ mutex_unlock(&ucr->dev_mutex);
+
+ dev_dbg(ms_dev(host), "req result %d\n",
+ host->req->error);
+ }
+ } while (!rc);
+ }
+
+}
+
+static void rtsx_usb_ms_request(struct memstick_host *msh)
+{
+ struct rtsx_usb_ms *host = memstick_priv(msh);
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ if (!host->eject)
+ schedule_work(&host->handle_req);
+}
+
+static int rtsx_usb_ms_set_param(struct memstick_host *msh,
+ enum memstick_param param, int value)
+{
+ struct rtsx_usb_ms *host = memstick_priv(msh);
+ struct rtsx_ucr *ucr = host->ucr;
+ unsigned int clock = 0;
+ u8 ssc_depth = 0;
+ int err;
+
+ dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n",
+ __func__, param, value);
+
+ mutex_lock(&ucr->dev_mutex);
+
+ err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_MS_CARD);
+ if (err)
+ goto out;
+
+ switch (param) {
+ case MEMSTICK_POWER:
+ if (value == host->power_mode)
+ break;
+
+ if (value == MEMSTICK_POWER_ON) {
+ pm_runtime_get_sync(ms_dev(host));
+ err = ms_power_on(host);
+ } else if (value == MEMSTICK_POWER_OFF) {
+ err = ms_power_off(host);
+ if (host->msh->card)
+ pm_runtime_put_noidle(ms_dev(host));
+ else
+ pm_runtime_put(ms_dev(host));
+ } else
+ err = -EINVAL;
+ if (!err)
+ host->power_mode = value;
+ break;
+
+ case MEMSTICK_INTERFACE:
+ if (value == MEMSTICK_SERIAL) {
+ clock = 19000000;
+ ssc_depth = SSC_DEPTH_512K;
+ err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A,
+ MS_BUS_WIDTH_1 | PUSH_TIME_DEFAULT);
+ if (err < 0)
+ break;
+ } else if (value == MEMSTICK_PAR4) {
+ clock = 39000000;
+ ssc_depth = SSC_DEPTH_1M;
+
+ err = rtsx_usb_write_register(ucr, MS_CFG, 0x5A,
+ MS_BUS_WIDTH_4 | PUSH_TIME_ODD |
+ MS_NO_CHECK_INT);
+ if (err < 0)
+ break;
+ } else {
+ err = -EINVAL;
+ break;
+ }
+
+ err = rtsx_usb_switch_clock(ucr, clock,
+ ssc_depth, false, true, false);
+ if (err < 0) {
+ dev_dbg(ms_dev(host), "switch clock failed\n");
+ break;
+ }
+
+ host->ssc_depth = ssc_depth;
+ host->clock = clock;
+ host->ifmode = value;
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+out:
+ mutex_unlock(&ucr->dev_mutex);
+
+ /* power-on delay */
+ if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON)
+ usleep_range(10000, 12000);
+
+ dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err);
+ return err;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int rtsx_usb_ms_suspend(struct device *dev)
+{
+ struct rtsx_usb_ms *host = dev_get_drvdata(dev);
+ struct memstick_host *msh = host->msh;
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ memstick_suspend_host(msh);
+ return 0;
+}
+
+static int rtsx_usb_ms_resume(struct device *dev)
+{
+ struct rtsx_usb_ms *host = dev_get_drvdata(dev);
+ struct memstick_host *msh = host->msh;
+
+ dev_dbg(ms_dev(host), "--> %s\n", __func__);
+
+ memstick_resume_host(msh);
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+/*
+ * Thread function of ms card slot detection. The thread starts right after
+ * successful host addition. It stops while the driver removal function sets
+ * host->eject true.
+ */
+static int rtsx_usb_detect_ms_card(void *__host)
+{
+ struct rtsx_usb_ms *host = (struct rtsx_usb_ms *)__host;
+ struct rtsx_ucr *ucr = host->ucr;
+ u8 val = 0;
+ int err;
+
+ for (;;) {
+ mutex_lock(&ucr->dev_mutex);
+
+ /* Check pending MS card changes */
+ err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val);
+ if (err) {
+ mutex_unlock(&ucr->dev_mutex);
+ goto poll_again;
+ }
+
+ /* Clear the pending */
+ rtsx_usb_write_register(ucr, CARD_INT_PEND,
+ XD_INT | MS_INT | SD_INT,
+ XD_INT | MS_INT | SD_INT);
+
+ mutex_unlock(&ucr->dev_mutex);
+
+ if (val & MS_INT) {
+ dev_dbg(ms_dev(host), "MS slot change detected\n");
+ memstick_detect_change(host->msh);
+ }
+
+poll_again:
+ if (host->eject)
+ break;
+
+ msleep(1000);
+ }
+
+ complete(&host->detect_ms_exit);
+ return 0;
+}
+
+static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)
+{
+ struct memstick_host *msh;
+ struct rtsx_usb_ms *host;
+ struct rtsx_ucr *ucr;
+ int err;
+
+ ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent));
+ if (!ucr)
+ return -ENXIO;
+
+ dev_dbg(&(pdev->dev),
+ "Realtek USB Memstick controller found\n");
+
+ msh = memstick_alloc_host(sizeof(*host), &pdev->dev);
+ if (!msh)
+ return -ENOMEM;
+
+ host = memstick_priv(msh);
+ host->ucr = ucr;
+ host->msh = msh;
+ host->pdev = pdev;
+ host->power_mode = MEMSTICK_POWER_OFF;
+ platform_set_drvdata(pdev, host);
+
+ mutex_init(&host->host_mutex);
+ INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req);
+
+ init_completion(&host->detect_ms_exit);
+ host->detect_ms = kthread_create(rtsx_usb_detect_ms_card, host,
+ "rtsx_usb_ms_%d", pdev->id);
+ if (IS_ERR(host->detect_ms)) {
+ dev_dbg(&(pdev->dev),
+ "Unable to create polling thread.\n");
+ err = PTR_ERR(host->detect_ms);
+ goto err_out;
+ }
+
+ msh->request = rtsx_usb_ms_request;
+ msh->set_param = rtsx_usb_ms_set_param;
+ msh->caps = MEMSTICK_CAP_PAR4;
+
+ pm_runtime_enable(&pdev->dev);
+ err = memstick_add_host(msh);
+ if (err)
+ goto err_out;
+
+ wake_up_process(host->detect_ms);
+ return 0;
+err_out:
+ memstick_free_host(msh);
+ return err;
+}
+
+static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
+{
+ struct rtsx_usb_ms *host = platform_get_drvdata(pdev);
+ struct memstick_host *msh;
+ int err;
+
+ msh = host->msh;
+ host->eject = true;
+ cancel_work_sync(&host->handle_req);
+
+ mutex_lock(&host->host_mutex);
+ if (host->req) {
+ dev_dbg(&(pdev->dev),
+ "%s: Controller removed during transfer\n",
+ dev_name(&msh->dev));
+ host->req->error = -ENOMEDIUM;
+ do {
+ err = memstick_next_req(msh, &host->req);
+ if (!err)
+ host->req->error = -ENOMEDIUM;
+ } while (!err);
+ }
+ mutex_unlock(&host->host_mutex);
+
+ wait_for_completion(&host->detect_ms_exit);
+ memstick_remove_host(msh);
+ memstick_free_host(msh);
+
+ /* Balance possible unbalanced usage count
+ * e.g. unconditional module removal
+ */
+ if (pm_runtime_active(ms_dev(host)))
+ pm_runtime_put(ms_dev(host));
+
+ pm_runtime_disable(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+
+ dev_dbg(&(pdev->dev),
+ ": Realtek USB Memstick controller has been removed\n");
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(rtsx_usb_ms_pm_ops,
+ rtsx_usb_ms_suspend, rtsx_usb_ms_resume);
+
+static struct platform_device_id rtsx_usb_ms_ids[] = {
+ {
+ .name = "rtsx_usb_ms",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, rtsx_usb_ms_ids);
+
+static struct platform_driver rtsx_usb_ms_driver = {
+ .probe = rtsx_usb_ms_drv_probe,
+ .remove = rtsx_usb_ms_drv_remove,
+ .id_table = rtsx_usb_ms_ids,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rtsx_usb_ms",
+ .pm = &rtsx_usb_ms_pm_ops,
+ },
+};
+module_platform_driver(rtsx_usb_ms_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
+MODULE_DESCRIPTION("Realtek USB Memstick Card Host Driver");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6deb8a11c12f..ee8204cc31e9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -67,6 +67,18 @@ config MFD_BCM590XX
help
Support for the BCM590xx PMUs from Broadcom
+config MFD_AXP20X
+ bool "X-Powers AXP20X"
+ select MFD_CORE
+ select REGMAP_I2C
+ select REGMAP_IRQ
+ depends on I2C=y
+ help
+ If you say Y here you get support for the X-Powers AXP202 and AXP209.
+ This driver include only the core APIs. You have to select individual
+ components like regulators or the PEK (Power Enable Key) under the
+ corresponding menus.
+
config MFD_CROS_EC
tristate "ChromeOS Embedded Controller"
select MFD_CORE
@@ -250,6 +262,16 @@ config MFD_INTEL_MSIC
Passage) chip. This chip embeds audio, battery, GPIO, etc.
devices used in Intel Medfield platforms.
+config MFD_IPAQ_MICRO
+ bool "Atmel Micro ASIC (iPAQ h3100/h3600/h3700) Support"
+ depends on SA1100_H3100 || SA1100_H3600
+ select MFD_CORE
+ help
+ Select this to get support for the Microcontroller found in
+ the Compaq iPAQ handheld computers. This is an Atmel
+ AT90LS8535 microcontroller flashed with a special iPAQ
+ firmware using the custom protocol implemented in this driver.
+
config MFD_JANZ_CMODIO
tristate "Janz CMOD-IO PCI MODULbus Carrier Board"
select MFD_CORE
@@ -675,6 +697,7 @@ config MFD_DB8500_PRCMU
config MFD_STMPE
bool "STMicroelectronics STMPE"
depends on (I2C=y || SPI_MASTER=y)
+ depends on OF
select MFD_CORE
help
Support for the STMPE family of I/O Expanders from
@@ -719,6 +742,14 @@ config MFD_STA2X11
select MFD_CORE
select REGMAP_MMIO
+config MFD_SUN6I_PRCM
+ bool "Allwinner A31 PRCM controller"
+ depends on ARCH_SUNXI
+ select MFD_CORE
+ help
+ Support for the PRCM (Power/Reset/Clock Management) unit available
+ in A31 SoC.
+
config MFD_SYSCON
bool "System Controller Register R/W Based on Regmap"
select REGMAP_MMIO
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index cec3487b539e..8afedba535c7 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
obj-$(CONFIG_MFD_STMPE) += stmpe.o
obj-$(CONFIG_STMPE_I2C) += stmpe-i2c.o
obj-$(CONFIG_STMPE_SPI) += stmpe-spi.o
+obj-$(CONFIG_MFD_SUN6I_PRCM) += sun6i-prcm.o
obj-$(CONFIG_MFD_TC3589X) += tc3589x.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
@@ -102,6 +103,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-irq.o
obj-$(CONFIG_PMIC_DA9052) += da9052-core.o
obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o
obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o
+obj-$(CONFIG_MFD_AXP20X) += axp20x.o
obj-$(CONFIG_MFD_LP3943) += lp3943.o
obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o
@@ -166,3 +168,4 @@ obj-$(CONFIG_MFD_RETU) += retu-mfd.o
obj-$(CONFIG_MFD_AS3711) += as3711.o
obj-$(CONFIG_MFD_AS3722) += as3722.o
obj-$(CONFIG_MFD_STW481X) += stw481x.o
+obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
index f3a15aa54d7b..fe418995108c 100644
--- a/drivers/mfd/abx500-core.c
+++ b/drivers/mfd/abx500-core.c
@@ -151,22 +151,6 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
}
EXPORT_SYMBOL(abx500_startup_irq_enabled);
-void abx500_dump_all_banks(void)
-{
- struct abx500_ops *ops;
- struct device dummy_child = {NULL};
- struct abx500_device_entry *dev_entry;
-
- list_for_each_entry(dev_entry, &abx500_list, list) {
- dummy_child.parent = dev_entry->dev;
- ops = &dev_entry->ops;
-
- if ((ops != NULL) && (ops->dump_all_banks != NULL))
- ops->dump_all_banks(&dummy_child);
- }
-}
-EXPORT_SYMBOL(abx500_dump_all_banks);
-
MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
MODULE_DESCRIPTION("ABX500 core driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 07e6e27be23c..cfc191abae4a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -583,6 +583,7 @@ static const char *wm5102_supplies[] = {
"CPVDD",
"SPKVDDL",
"SPKVDDR",
+ "MICVDD",
};
static const struct mfd_cell wm5102_devs[] = {
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 88758ab9402b..17102f589100 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -285,7 +285,7 @@ int arizona_irq_init(struct arizona *arizona)
IRQF_ONESHOT, -1, irq,
&arizona->irq_chip);
if (ret != 0) {
- dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret);
+ dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret);
goto err_aod;
}
diff --git a/drivers/mfd/as3711.c b/drivers/mfd/as3711.c
index ec684fcedb42..d9706ede8d39 100644
--- a/drivers/mfd/as3711.c
+++ b/drivers/mfd/as3711.c
@@ -114,7 +114,7 @@ static const struct regmap_config as3711_regmap_config = {
};
#ifdef CONFIG_OF
-static struct of_device_id as3711_of_match[] = {
+static const struct of_device_id as3711_of_match[] = {
{.compatible = "ams,as3711",},
{}
};
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
new file mode 100644
index 000000000000..dee653989e3a
--- /dev/null
+++ b/drivers/mfd/axp20x.c
@@ -0,0 +1,258 @@
+/*
+ * axp20x.c - MFD core driver for the X-Powers AXP202 and AXP209
+ *
+ * AXP20x comprises an adaptive USB-Compatible PWM charger, 2 BUCK DC-DC
+ * converters, 5 LDOs, multiple 12-bit ADCs of voltage, current and temperature
+ * as well as 4 configurable GPIOs.
+ *
+ * Author: Carlo Caione <carlo@caione.org>
+ *
+ * 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/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/axp20x.h>
+#include <linux/mfd/core.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#define AXP20X_OFF 0x80
+
+static const struct regmap_range axp20x_writeable_ranges[] = {
+ regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+ regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
+};
+
+static const struct regmap_range axp20x_volatile_ranges[] = {
+ regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
+};
+
+static const struct regmap_access_table axp20x_writeable_table = {
+ .yes_ranges = axp20x_writeable_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges),
+};
+
+static const struct regmap_access_table axp20x_volatile_table = {
+ .yes_ranges = axp20x_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges),
+};
+
+static struct resource axp20x_pek_resources[] = {
+ {
+ .name = "PEK_DBR",
+ .start = AXP20X_IRQ_PEK_RIS_EDGE,
+ .end = AXP20X_IRQ_PEK_RIS_EDGE,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .name = "PEK_DBF",
+ .start = AXP20X_IRQ_PEK_FAL_EDGE,
+ .end = AXP20X_IRQ_PEK_FAL_EDGE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static const struct regmap_config axp20x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .wr_table = &axp20x_writeable_table,
+ .volatile_table = &axp20x_volatile_table,
+ .max_register = AXP20X_FG_RES,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+#define AXP20X_IRQ(_irq, _off, _mask) \
+ [AXP20X_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
+
+static const struct regmap_irq axp20x_regmap_irqs[] = {
+ AXP20X_IRQ(ACIN_OVER_V, 0, 7),
+ AXP20X_IRQ(ACIN_PLUGIN, 0, 6),
+ AXP20X_IRQ(ACIN_REMOVAL, 0, 5),
+ AXP20X_IRQ(VBUS_OVER_V, 0, 4),
+ AXP20X_IRQ(VBUS_PLUGIN, 0, 3),
+ AXP20X_IRQ(VBUS_REMOVAL, 0, 2),
+ AXP20X_IRQ(VBUS_V_LOW, 0, 1),
+ AXP20X_IRQ(BATT_PLUGIN, 1, 7),
+ AXP20X_IRQ(BATT_REMOVAL, 1, 6),
+ AXP20X_IRQ(BATT_ENT_ACT_MODE, 1, 5),
+ AXP20X_IRQ(BATT_EXIT_ACT_MODE, 1, 4),
+ AXP20X_IRQ(CHARG, 1, 3),
+ AXP20X_IRQ(CHARG_DONE, 1, 2),
+ AXP20X_IRQ(BATT_TEMP_HIGH, 1, 1),
+ AXP20X_IRQ(BATT_TEMP_LOW, 1, 0),
+ AXP20X_IRQ(DIE_TEMP_HIGH, 2, 7),
+ AXP20X_IRQ(CHARG_I_LOW, 2, 6),
+ AXP20X_IRQ(DCDC1_V_LONG, 2, 5),
+ AXP20X_IRQ(DCDC2_V_LONG, 2, 4),
+ AXP20X_IRQ(DCDC3_V_LONG, 2, 3),
+ AXP20X_IRQ(PEK_SHORT, 2, 1),
+ AXP20X_IRQ(PEK_LONG, 2, 0),
+ AXP20X_IRQ(N_OE_PWR_ON, 3, 7),
+ AXP20X_IRQ(N_OE_PWR_OFF, 3, 6),
+ AXP20X_IRQ(VBUS_VALID, 3, 5),
+ AXP20X_IRQ(VBUS_NOT_VALID, 3, 4),
+ AXP20X_IRQ(VBUS_SESS_VALID, 3, 3),
+ AXP20X_IRQ(VBUS_SESS_END, 3, 2),
+ AXP20X_IRQ(LOW_PWR_LVL1, 3, 1),
+ AXP20X_IRQ(LOW_PWR_LVL2, 3, 0),
+ AXP20X_IRQ(TIMER, 4, 7),
+ AXP20X_IRQ(PEK_RIS_EDGE, 4, 6),
+ AXP20X_IRQ(PEK_FAL_EDGE, 4, 5),
+ AXP20X_IRQ(GPIO3_INPUT, 4, 3),
+ AXP20X_IRQ(GPIO2_INPUT, 4, 2),
+ AXP20X_IRQ(GPIO1_INPUT, 4, 1),
+ AXP20X_IRQ(GPIO0_INPUT, 4, 0),
+};
+
+static const struct of_device_id axp20x_of_match[] = {
+ { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID },
+ { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID },
+ { },
+};
+MODULE_DEVICE_TABLE(of, axp20x_of_match);
+
+/*
+ * This is useless for OF-enabled devices, but it is needed by I2C subsystem
+ */
+static const struct i2c_device_id axp20x_i2c_id[] = {
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
+
+static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
+ .name = "axp20x_irq_chip",
+ .status_base = AXP20X_IRQ1_STATE,
+ .ack_base = AXP20X_IRQ1_STATE,
+ .mask_base = AXP20X_IRQ1_EN,
+ .num_regs = 5,
+ .irqs = axp20x_regmap_irqs,
+ .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs),
+ .mask_invert = true,
+ .init_ack_masked = true,
+};
+
+static const char * const axp20x_supplies[] = {
+ "acin",
+ "vin2",
+ "vin3",
+ "ldo24in",
+ "ldo3in",
+ "ldo5in",
+};
+
+static struct mfd_cell axp20x_cells[] = {
+ {
+ .name = "axp20x-pek",
+ .num_resources = ARRAY_SIZE(axp20x_pek_resources),
+ .resources = axp20x_pek_resources,
+ }, {
+ .name = "axp20x-regulator",
+ .parent_supplies = axp20x_supplies,
+ .num_parent_supplies = ARRAY_SIZE(axp20x_supplies),
+ },
+};
+
+static struct axp20x_dev *axp20x_pm_power_off;
+static void axp20x_power_off(void)
+{
+ regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
+ AXP20X_OFF);
+}
+
+static int axp20x_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct axp20x_dev *axp20x;
+ const struct of_device_id *of_id;
+ int ret;
+
+ axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL);
+ if (!axp20x)
+ return -ENOMEM;
+
+ of_id = of_match_device(axp20x_of_match, &i2c->dev);
+ if (!of_id) {
+ dev_err(&i2c->dev, "Unable to setup AXP20X data\n");
+ return -ENODEV;
+ }
+ axp20x->variant = (long) of_id->data;
+
+ axp20x->i2c_client = i2c;
+ axp20x->dev = &i2c->dev;
+ dev_set_drvdata(axp20x->dev, axp20x);
+
+ axp20x->regmap = devm_regmap_init_i2c(i2c, &axp20x_regmap_config);
+ if (IS_ERR(axp20x->regmap)) {
+ ret = PTR_ERR(axp20x->regmap);
+ dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq,
+ IRQF_ONESHOT | IRQF_SHARED, -1,
+ &axp20x_regmap_irq_chip,
+ &axp20x->regmap_irqc);
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret);
+ return ret;
+ }
+
+ ret = mfd_add_devices(axp20x->dev, -1, axp20x_cells,
+ ARRAY_SIZE(axp20x_cells), NULL, 0, NULL);
+
+ if (ret) {
+ dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
+ regmap_del_irq_chip(i2c->irq, axp20x->regmap_irqc);
+ return ret;
+ }
+
+ if (!pm_power_off) {
+ axp20x_pm_power_off = axp20x;
+ pm_power_off = axp20x_power_off;
+ }
+
+ dev_info(&i2c->dev, "AXP20X driver loaded\n");
+
+ return 0;
+}
+
+static int axp20x_i2c_remove(struct i2c_client *i2c)
+{
+ struct axp20x_dev *axp20x = i2c_get_clientdata(i2c);
+
+ if (axp20x == axp20x_pm_power_off) {
+ axp20x_pm_power_off = NULL;
+ pm_power_off = NULL;
+ }
+
+ mfd_remove_devices(axp20x->dev);
+ regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc);
+
+ return 0;
+}
+
+static struct i2c_driver axp20x_i2c_driver = {
+ .driver = {
+ .name = "axp20x",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(axp20x_of_match),
+ },
+ .probe = axp20x_i2c_probe,
+ .remove = axp20x_i2c_remove,
+ .id_table = axp20x_i2c_id,
+};
+
+module_i2c_driver(axp20x_i2c_driver);
+
+MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
+MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 43cba1a1973c..e334de000e8c 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -96,6 +96,12 @@ err:
return ret;
}
+static int bcm590xx_i2c_remove(struct i2c_client *i2c)
+{
+ mfd_remove_devices(&i2c->dev);
+ return 0;
+}
+
static const struct of_device_id bcm590xx_of_match[] = {
{ .compatible = "brcm,bcm59056" },
{ }
@@ -115,6 +121,7 @@ static struct i2c_driver bcm590xx_i2c_driver = {
.of_match_table = of_match_ptr(bcm590xx_of_match),
},
.probe = bcm590xx_i2c_probe,
+ .remove = bcm590xx_i2c_remove,
.id_table = bcm590xx_i2c_id,
};
module_i2c_driver(bcm590xx_i2c_driver);
@@ -122,4 +129,4 @@ module_i2c_driver(bcm590xx_i2c_driver);
MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
MODULE_DESCRIPTION("BCM590xx multi-function driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:bcm590xx");
+MODULE_ALIAS("i2c:bcm590xx");
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 783fe2e73e1e..38fe9bf0d169 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -30,7 +30,7 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
uint8_t *out;
int csum, i;
- BUG_ON(msg->out_len > EC_HOST_PARAM_SIZE);
+ BUG_ON(msg->out_len > EC_PROTO2_MAX_PARAM_SIZE);
out = ec_dev->dout;
out[0] = EC_CMD_VERSION0 + msg->version;
out[1] = msg->cmd;
@@ -90,6 +90,11 @@ static const struct mfd_cell cros_devs[] = {
.id = 1,
.of_compatible = "google,cros-ec-keyb",
},
+ {
+ .name = "cros-ec-i2c-tunnel",
+ .id = 2,
+ .of_compatible = "google,cros-ec-i2c-tunnel",
+ },
};
int cros_ec_register(struct cros_ec_device *ec_dev)
@@ -184,3 +189,6 @@ int cros_ec_resume(struct cros_ec_device *ec_dev)
EXPORT_SYMBOL(cros_ec_resume);
#endif
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC core driver");
diff --git a/drivers/mfd/cros_ec_spi.c b/drivers/mfd/cros_ec_spi.c
index 84af8d7a4295..0b8d32829166 100644
--- a/drivers/mfd/cros_ec_spi.c
+++ b/drivers/mfd/cros_ec_spi.c
@@ -39,14 +39,22 @@
#define EC_MSG_PREAMBLE_COUNT 32
/*
- * We must get a response from the EC in 5ms. This is a very long
- * time, but the flash write command can take 2-3ms. The EC command
- * processing is currently not very fast (about 500us). We could
- * look at speeding this up and making the flash write command a
- * 'slow' command, requiring a GET_STATUS wait loop, like flash
- * erase.
- */
-#define EC_MSG_DEADLINE_MS 5
+ * Allow for a long time for the EC to respond. We support i2c
+ * tunneling and support fairly long messages for the tunnel (249
+ * bytes long at the moment). If we're talking to a 100 kHz device
+ * on the other end and need to transfer ~256 bytes, then we need:
+ * 10 us/bit * ~10 bits/byte * ~256 bytes = ~25ms
+ *
+ * We'll wait 4 times that to handle clock stretching and other
+ * paranoia.
+ *
+ * It's pretty unlikely that we'll really see a 249 byte tunnel in
+ * anything other than testing. If this was more common we might
+ * consider having slow commands like this require a GET_STATUS
+ * wait loop. The 'flash write' command would be another candidate
+ * for this, clocking in at 2-3ms.
+ */
+#define EC_MSG_DEADLINE_MS 100
/*
* Time between raising the SPI chip select (for the end of a
@@ -65,11 +73,13 @@
* if no record
* @end_of_msg_delay: used to set the delay_usecs on the spi_transfer that
* is sent when we want to turn off CS at the end of a transaction.
+ * @lock: mutex to ensure only one user of cros_ec_command_spi_xfer at a time
*/
struct cros_ec_spi {
struct spi_device *spi;
s64 last_transfer_ns;
unsigned int end_of_msg_delay;
+ struct mutex lock;
};
static void debug_packet(struct device *dev, const char *name, u8 *ptr,
@@ -111,7 +121,9 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
/* Receive data until we see the header byte */
deadline = jiffies + msecs_to_jiffies(EC_MSG_DEADLINE_MS);
- do {
+ while (true) {
+ unsigned long start_jiffies = jiffies;
+
memset(&trans, 0, sizeof(trans));
trans.cs_change = 1;
trans.rx_buf = ptr = ec_dev->din;
@@ -132,12 +144,19 @@ static int cros_ec_spi_receive_response(struct cros_ec_device *ec_dev,
break;
}
}
+ if (ptr != end)
+ break;
- if (time_after(jiffies, deadline)) {
+ /*
+ * Use the time at the start of the loop as a timeout. This
+ * gives us one last shot at getting the transfer and is useful
+ * in case we got context switched out for a while.
+ */
+ if (time_after(start_jiffies, deadline)) {
dev_warn(ec_dev->dev, "EC failed to respond in time\n");
return -ETIMEDOUT;
}
- } while (ptr == end);
+ }
/*
* ptr now points to the header byte. Copy any valid data to the
@@ -208,6 +227,13 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
int ret = 0, final_ret;
struct timespec ts;
+ /*
+ * We have the shared ec_dev buffer plus we do lots of separate spi_sync
+ * calls, so we need to make sure only one person is using this at a
+ * time.
+ */
+ mutex_lock(&ec_spi->lock);
+
len = cros_ec_prepare_tx(ec_dev, ec_msg);
dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
@@ -219,7 +245,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
ktime_get_ts(&ts);
delay = timespec_to_ns(&ts) - ec_spi->last_transfer_ns;
if (delay < EC_SPI_RECOVERY_TIME_NS)
- ndelay(delay);
+ ndelay(EC_SPI_RECOVERY_TIME_NS - delay);
}
/* Transmit phase - send our message */
@@ -260,7 +286,7 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
ret = final_ret;
if (ret < 0) {
dev_err(ec_dev->dev, "spi transfer failed: %d\n", ret);
- return ret;
+ goto exit;
}
/* check response error code */
@@ -269,14 +295,16 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
dev_warn(ec_dev->dev, "command 0x%02x returned an error %d\n",
ec_msg->cmd, ptr[0]);
debug_packet(ec_dev->dev, "in_err", ptr, len);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
len = ptr[1];
sum = ptr[0] + ptr[1];
if (len > ec_msg->in_len) {
dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
len, ec_msg->in_len);
- return -ENOSPC;
+ ret = -ENOSPC;
+ goto exit;
}
/* copy response packet payload and compute checksum */
@@ -293,10 +321,14 @@ static int cros_ec_command_spi_xfer(struct cros_ec_device *ec_dev,
dev_err(ec_dev->dev,
"bad packet checksum, expected %02x, got %02x\n",
sum, ptr[len + 2]);
- return -EBADMSG;
+ ret = -EBADMSG;
+ goto exit;
}
- return 0;
+ ret = 0;
+exit:
+ mutex_unlock(&ec_spi->lock);
+ return ret;
}
static void cros_ec_spi_dt_probe(struct cros_ec_spi *ec_spi, struct device *dev)
@@ -327,6 +359,7 @@ static int cros_ec_spi_probe(struct spi_device *spi)
if (ec_spi == NULL)
return -ENOMEM;
ec_spi->spi = spi;
+ mutex_init(&ec_spi->lock);
ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
if (!ec_dev)
return -ENOMEM;
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index b11fdd63eecd..193cf168ba84 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2300,9 +2300,6 @@ int prcmu_ac_wake_req(void)
if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
msecs_to_jiffies(5000))) {
-#if defined(CONFIG_DBX500_PRCMU_DEBUG)
- db8500_prcmu_debug_dump(__func__, true, true);
-#endif
pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
__func__);
ret = -EFAULT;
@@ -3112,7 +3109,7 @@ static int db8500_prcmu_register_ab8500(struct device *parent,
{
struct device_node *np;
struct resource ab8500_resource;
- struct mfd_cell ab8500_cell = {
+ const struct mfd_cell ab8500_cell = {
.name = "ab8500-core",
.of_compatible = "stericsson,ab8500",
.id = AB8500_VERSION_AB8500,
diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c
new file mode 100644
index 000000000000..7e50fe0118e3
--- /dev/null
+++ b/drivers/mfd/ipaq-micro.c
@@ -0,0 +1,482 @@
+/*
+ * Compaq iPAQ h3xxx Atmel microcontroller companion support
+ *
+ * This is an Atmel AT90LS8535 with a special flashed-in firmware that
+ * implements the special protocol used by this driver.
+ *
+ * based on previous kernel 2.4 version by Andrew Christian
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Dmitry Artamonow <mad_soft@inbox.ru>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ipaq-micro.h>
+#include <linux/string.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+#include <mach/hardware.h>
+
+static void ipaq_micro_trigger_tx(struct ipaq_micro *micro)
+{
+ struct ipaq_micro_txdev *tx = &micro->tx;
+ struct ipaq_micro_msg *msg = micro->msg;
+ int i, bp;
+ u8 checksum;
+ u32 val;
+
+ bp = 0;
+ tx->buf[bp++] = CHAR_SOF;
+
+ checksum = ((msg->id & 0x0f) << 4) | (msg->tx_len & 0x0f);
+ tx->buf[bp++] = checksum;
+
+ for (i = 0; i < msg->tx_len; i++) {
+ tx->buf[bp++] = msg->tx_data[i];
+ checksum += msg->tx_data[i];
+ }
+
+ tx->buf[bp++] = checksum;
+ tx->len = bp;
+ tx->index = 0;
+ print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1,
+ tx->buf, tx->len, true);
+
+ /* Enable interrupt */
+ val = readl(micro->base + UTCR3);
+ val |= UTCR3_TIE;
+ writel(val, micro->base + UTCR3);
+}
+
+int ipaq_micro_tx_msg(struct ipaq_micro *micro, struct ipaq_micro_msg *msg)
+{
+ unsigned long flags;
+
+ dev_dbg(micro->dev, "TX msg: %02x, %d bytes\n", msg->id, msg->tx_len);
+
+ spin_lock_irqsave(&micro->lock, flags);
+ if (micro->msg) {
+ list_add_tail(&msg->node, &micro->queue);
+ spin_unlock_irqrestore(&micro->lock, flags);
+ return 0;
+ }
+ micro->msg = msg;
+ ipaq_micro_trigger_tx(micro);
+ spin_unlock_irqrestore(&micro->lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(ipaq_micro_tx_msg);
+
+static void micro_rx_msg(struct ipaq_micro *micro, u8 id, int len, u8 *data)
+{
+ int i;
+
+ dev_dbg(micro->dev, "RX msg: %02x, %d bytes\n", id, len);
+
+ spin_lock(&micro->lock);
+ switch (id) {
+ case MSG_VERSION:
+ case MSG_EEPROM_READ:
+ case MSG_EEPROM_WRITE:
+ case MSG_BACKLIGHT:
+ case MSG_NOTIFY_LED:
+ case MSG_THERMAL_SENSOR:
+ case MSG_BATTERY:
+ /* Handle synchronous messages */
+ if (micro->msg && micro->msg->id == id) {
+ struct ipaq_micro_msg *msg = micro->msg;
+
+ memcpy(msg->rx_data, data, len);
+ msg->rx_len = len;
+ complete(&micro->msg->ack);
+ if (!list_empty(&micro->queue)) {
+ micro->msg = list_entry(micro->queue.next,
+ struct ipaq_micro_msg,
+ node);
+ list_del_init(&micro->msg->node);
+ ipaq_micro_trigger_tx(micro);
+ } else
+ micro->msg = NULL;
+ dev_dbg(micro->dev, "OK RX message 0x%02x\n", id);
+ } else {
+ dev_err(micro->dev,
+ "out of band RX message 0x%02x\n", id);
+ if(!micro->msg)
+ dev_info(micro->dev, "no message queued\n");
+ else
+ dev_info(micro->dev, "expected message %02x\n",
+ micro->msg->id);
+ }
+ break;
+ case MSG_KEYBOARD:
+ if (micro->key)
+ micro->key(micro->key_data, len, data);
+ else
+ dev_dbg(micro->dev, "key message ignored, no handle \n");
+ break;
+ case MSG_TOUCHSCREEN:
+ if (micro->ts)
+ micro->ts(micro->ts_data, len, data);
+ else
+ dev_dbg(micro->dev, "touchscreen message ignored, no handle \n");
+ break;
+ default:
+ dev_err(micro->dev,
+ "unknown msg %d [%d] ", id, len);
+ for (i = 0; i < len; ++i)
+ pr_cont("0x%02x ", data[i]);
+ pr_cont("\n");
+ }
+ spin_unlock(&micro->lock);
+}
+
+static void micro_process_char(struct ipaq_micro *micro, u8 ch)
+{
+ struct ipaq_micro_rxdev *rx = &micro->rx;
+
+ switch (rx->state) {
+ case STATE_SOF: /* Looking for SOF */
+ if (ch == CHAR_SOF)
+ rx->state = STATE_ID; /* Next byte is the id and len */
+ break;
+ case STATE_ID: /* Looking for id and len byte */
+ rx->id = (ch & 0xf0) >> 4 ;
+ rx->len = (ch & 0x0f);
+ rx->index = 0;
+ rx->chksum = ch;
+ rx->state = (rx->len > 0) ? STATE_DATA : STATE_CHKSUM;
+ break;
+ case STATE_DATA: /* Looking for 'len' data bytes */
+ rx->chksum += ch;
+ rx->buf[rx->index] = ch;
+ if (++rx->index == rx->len)
+ rx->state = STATE_CHKSUM;
+ break;
+ case STATE_CHKSUM: /* Looking for the checksum */
+ if (ch == rx->chksum)
+ micro_rx_msg(micro, rx->id, rx->len, rx->buf);
+ rx->state = STATE_SOF;
+ break;
+ }
+}
+
+static void micro_rx_chars(struct ipaq_micro *micro)
+{
+ u32 status, ch;
+
+ while ((status = readl(micro->base + UTSR1)) & UTSR1_RNE) {
+ ch = readl(micro->base + UTDR);
+ if (status & UTSR1_PRE)
+ dev_err(micro->dev, "rx: parity error\n");
+ else if (status & UTSR1_FRE)
+ dev_err(micro->dev, "rx: framing error\n");
+ else if (status & UTSR1_ROR)
+ dev_err(micro->dev, "rx: overrun error\n");
+ micro_process_char(micro, ch);
+ }
+}
+
+static void ipaq_micro_get_version(struct ipaq_micro *micro)
+{
+ struct ipaq_micro_msg msg = {
+ .id = MSG_VERSION,
+ };
+
+ ipaq_micro_tx_msg_sync(micro, &msg);
+ if (msg.rx_len == 4) {
+ memcpy(micro->version, msg.rx_data, 4);
+ micro->version[4] = '\0';
+ } else if (msg.rx_len == 9) {
+ memcpy(micro->version, msg.rx_data, 4);
+ micro->version[4] = '\0';
+ /* Bytes 4-7 are "pack", byte 8 is "boot type" */
+ } else {
+ dev_err(micro->dev,
+ "illegal version message %d bytes\n", msg.rx_len);
+ }
+}
+
+static void ipaq_micro_eeprom_read(struct ipaq_micro *micro,
+ u8 address, u8 len, u8 *data)
+{
+ struct ipaq_micro_msg msg = {
+ .id = MSG_EEPROM_READ,
+ };
+ u8 i;
+
+ for (i = 0; i < len; i++) {
+ msg.tx_data[0] = address + i;
+ msg.tx_data[1] = 1;
+ msg.tx_len = 2;
+ ipaq_micro_tx_msg_sync(micro, &msg);
+ memcpy(data + (i * 2), msg.rx_data, 2);
+ }
+}
+
+static char *ipaq_micro_str(u8 *wchar, u8 len)
+{
+ char retstr[256];
+ u8 i;
+
+ for (i = 0; i < len / 2; i++)
+ retstr[i] = wchar[i * 2];
+ return kstrdup(retstr, GFP_KERNEL);
+}
+
+static u16 ipaq_micro_to_u16(u8 *data)
+{
+ return data[1] << 8 | data[0];
+}
+
+static void ipaq_micro_eeprom_dump(struct ipaq_micro *micro)
+{
+ u8 dump[256];
+ char *str;
+
+ ipaq_micro_eeprom_read(micro, 0, 128, dump);
+ str = ipaq_micro_str(dump, 10);
+ if (str) {
+ dev_info(micro->dev, "HM version %s\n", str);
+ kfree(str);
+ }
+ str = ipaq_micro_str(dump+10, 40);
+ if (str) {
+ dev_info(micro->dev, "serial number: %s\n", str);
+ /* Feed the random pool with this */
+ add_device_randomness(str, strlen(str));
+ kfree(str);
+ }
+ str = ipaq_micro_str(dump+50, 20);
+ if (str) {
+ dev_info(micro->dev, "module ID: %s\n", str);
+ kfree(str);
+ }
+ str = ipaq_micro_str(dump+70, 10);
+ if (str) {
+ dev_info(micro->dev, "product revision: %s\n", str);
+ kfree(str);
+ }
+ dev_info(micro->dev, "product ID: %u\n", ipaq_micro_to_u16(dump+80));
+ dev_info(micro->dev, "frame rate: %u fps\n",
+ ipaq_micro_to_u16(dump+82));
+ dev_info(micro->dev, "page mode: %u\n", ipaq_micro_to_u16(dump+84));
+ dev_info(micro->dev, "country ID: %u\n", ipaq_micro_to_u16(dump+86));
+ dev_info(micro->dev, "color display: %s\n",
+ ipaq_micro_to_u16(dump+88) ? "yes" : "no");
+ dev_info(micro->dev, "ROM size: %u MiB\n", ipaq_micro_to_u16(dump+90));
+ dev_info(micro->dev, "RAM size: %u KiB\n", ipaq_micro_to_u16(dump+92));
+ dev_info(micro->dev, "screen: %u x %u\n",
+ ipaq_micro_to_u16(dump+94), ipaq_micro_to_u16(dump+96));
+ print_hex_dump(KERN_DEBUG, "eeprom: ", DUMP_PREFIX_OFFSET, 16, 1,
+ dump, 256, true);
+
+}
+
+static void micro_tx_chars(struct ipaq_micro *micro)
+{
+ struct ipaq_micro_txdev *tx = &micro->tx;
+ u32 val;
+
+ while ((tx->index < tx->len) &&
+ (readl(micro->base + UTSR1) & UTSR1_TNF)) {
+ writel(tx->buf[tx->index], micro->base + UTDR);
+ tx->index++;
+ }
+
+ /* Stop interrupts */
+ val = readl(micro->base + UTCR3);
+ val &= ~UTCR3_TIE;
+ writel(val, micro->base + UTCR3);
+}
+
+static void micro_reset_comm(struct ipaq_micro *micro)
+{
+ struct ipaq_micro_rxdev *rx = &micro->rx;
+ u32 val;
+
+ if (micro->msg)
+ complete(&micro->msg->ack);
+
+ /* Initialize Serial channel protocol frame */
+ rx->state = STATE_SOF; /* Reset the state machine */
+
+ /* Set up interrupts */
+ writel(0x01, micro->sdlc + 0x0); /* Select UART mode */
+
+ /* Clean up CR3 */
+ writel(0x0, micro->base + UTCR3);
+
+ /* Format: 8N1 */
+ writel(UTCR0_8BitData | UTCR0_1StpBit, micro->base + UTCR0);
+
+ /* Baud rate: 115200 */
+ writel(0x0, micro->base + UTCR1);
+ writel(0x1, micro->base + UTCR2);
+
+ /* Clear SR0 */
+ writel(0xff, micro->base + UTSR0);
+
+ /* Enable RX int, disable TX int */
+ writel(UTCR3_TXE | UTCR3_RXE | UTCR3_RIE, micro->base + UTCR3);
+ val = readl(micro->base + UTCR3);
+ val &= ~UTCR3_TIE;
+ writel(val, micro->base + UTCR3);
+}
+
+static irqreturn_t micro_serial_isr(int irq, void *dev_id)
+{
+ struct ipaq_micro *micro = dev_id;
+ struct ipaq_micro_txdev *tx = &micro->tx;
+ u32 status;
+
+ status = readl(micro->base + UTSR0);
+ do {
+ if (status & (UTSR0_RID | UTSR0_RFS)) {
+ if (status & UTSR0_RID)
+ /* Clear the Receiver IDLE bit */
+ writel(UTSR0_RID, micro->base + UTSR0);
+ micro_rx_chars(micro);
+ }
+
+ /* Clear break bits */
+ if (status & (UTSR0_RBB | UTSR0_REB))
+ writel(status & (UTSR0_RBB | UTSR0_REB),
+ micro->base + UTSR0);
+
+ if (status & UTSR0_TFS)
+ micro_tx_chars(micro);
+
+ status = readl(micro->base + UTSR0);
+
+ } while (((tx->index < tx->len) && (status & UTSR0_TFS)) ||
+ (status & (UTSR0_RFS | UTSR0_RID)));
+
+ return IRQ_HANDLED;
+}
+
+static const struct mfd_cell micro_cells[] = {
+ { .name = "ipaq-micro-backlight", },
+ { .name = "ipaq-micro-battery", },
+ { .name = "ipaq-micro-keys", },
+ { .name = "ipaq-micro-ts", },
+ { .name = "ipaq-micro-leds", },
+};
+
+static int micro_resume(struct device *dev)
+{
+ struct ipaq_micro *micro = dev_get_drvdata(dev);
+
+ micro_reset_comm(micro);
+ mdelay(10);
+
+ return 0;
+}
+
+static int micro_probe(struct platform_device *pdev)
+{
+ struct ipaq_micro *micro;
+ struct resource *res;
+ int ret;
+ int irq;
+
+ micro = devm_kzalloc(&pdev->dev, sizeof(*micro), GFP_KERNEL);
+ if (!micro)
+ return -ENOMEM;
+
+ micro->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ micro->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(micro->base))
+ return PTR_ERR(micro->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -EINVAL;
+
+ micro->sdlc = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(micro->sdlc))
+ return PTR_ERR(micro->sdlc);
+
+ micro_reset_comm(micro);
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq)
+ return -EINVAL;
+ ret = devm_request_irq(&pdev->dev, irq, micro_serial_isr,
+ IRQF_SHARED, "ipaq-micro",
+ micro);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to grab serial port IRQ\n");
+ return ret;
+ } else
+ dev_info(&pdev->dev, "grabbed serial port IRQ\n");
+
+ spin_lock_init(&micro->lock);
+ INIT_LIST_HEAD(&micro->queue);
+ platform_set_drvdata(pdev, micro);
+
+ ret = mfd_add_devices(&pdev->dev, pdev->id, micro_cells,
+ ARRAY_SIZE(micro_cells), NULL, 0, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "error adding MFD cells");
+ return ret;
+ }
+
+ /* Check version */
+ ipaq_micro_get_version(micro);
+ dev_info(&pdev->dev, "Atmel micro ASIC version %s\n", micro->version);
+ ipaq_micro_eeprom_dump(micro);
+
+ return 0;
+}
+
+static int micro_remove(struct platform_device *pdev)
+{
+ struct ipaq_micro *micro = platform_get_drvdata(pdev);
+ u32 val;
+
+ mfd_remove_devices(&pdev->dev);
+
+ val = readl(micro->base + UTCR3);
+ val &= ~(UTCR3_RXE | UTCR3_RIE); /* disable receive interrupt */
+ val &= ~(UTCR3_TXE | UTCR3_TIE); /* disable transmit interrupt */
+ writel(val, micro->base + UTCR3);
+
+ return 0;
+}
+
+static const struct dev_pm_ops micro_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(NULL, micro_resume)
+};
+
+static struct platform_driver micro_device_driver = {
+ .driver = {
+ .name = "ipaq-h3xxx-micro",
+ .pm = &micro_dev_pm_ops,
+ },
+ .probe = micro_probe,
+ .remove = micro_remove,
+ /* .shutdown = micro_suspend, // FIXME */
+};
+module_platform_driver(micro_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro core and backlight");
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c
index 07692604e119..f7ff0188603d 100644
--- a/drivers/mfd/kempld-core.c
+++ b/drivers/mfd/kempld-core.c
@@ -86,7 +86,7 @@ enum kempld_cells {
KEMPLD_UART,
};
-static struct mfd_cell kempld_devs[] = {
+static const struct mfd_cell kempld_devs[] = {
[KEMPLD_I2C] = {
.name = "kempld-i2c",
},
@@ -288,9 +288,38 @@ 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);
+ char major, minor;
+
+ ret = pdata->get_info(pld);
+ if (ret)
+ return ret;
+
+ /* The Kontron PLD firmware version string has the following format:
+ * Pwxy.zzzz
+ * P: Fixed
+ * w: PLD number - 1 hex digit
+ * x: Major version - 1 alphanumerical digit (0-9A-V)
+ * y: Minor version - 1 alphanumerical digit (0-9A-V)
+ * zzzz: Build number - 4 zero padded hex digits */
- return pdata->get_info(pld);
+ if (pld->info.major < 10)
+ major = pld->info.major + '0';
+ else
+ major = (pld->info.major - 10) + 'A';
+ if (pld->info.minor < 10)
+ minor = pld->info.minor + '0';
+ else
+ minor = (pld->info.minor - 10) + 'A';
+
+ ret = scnprintf(pld->info.version, sizeof(pld->info.version),
+ "P%X%c%c.%04X", pld->info.number, major, minor,
+ pld->info.buildnr);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
/*
@@ -307,9 +336,71 @@ static int kempld_register_cells(struct kempld_device_data *pld)
return pdata->register_cells(pld);
}
+static const char *kempld_get_type_string(struct kempld_device_data *pld)
+{
+ const char *version_type;
+
+ switch (pld->info.type) {
+ case 0:
+ version_type = "release";
+ break;
+ case 1:
+ version_type = "debug";
+ break;
+ case 2:
+ version_type = "custom";
+ break;
+ default:
+ version_type = "unspecified";
+ break;
+ }
+
+ return version_type;
+}
+
+static ssize_t kempld_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kempld_device_data *pld = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version);
+}
+
+static ssize_t kempld_specification_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kempld_device_data *pld = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major,
+ pld->info.spec_minor);
+}
+
+static ssize_t kempld_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct kempld_device_data *pld = dev_get_drvdata(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld));
+}
+
+static DEVICE_ATTR(pld_version, S_IRUGO, kempld_version_show, NULL);
+static DEVICE_ATTR(pld_specification, S_IRUGO, kempld_specification_show,
+ NULL);
+static DEVICE_ATTR(pld_type, S_IRUGO, kempld_type_show, NULL);
+
+static struct attribute *pld_attributes[] = {
+ &dev_attr_pld_version.attr,
+ &dev_attr_pld_specification.attr,
+ &dev_attr_pld_type.attr,
+ NULL
+};
+
+static const struct attribute_group pld_attr_group = {
+ .attrs = pld_attributes,
+};
+
static int kempld_detect_device(struct kempld_device_data *pld)
{
- char *version_type;
u8 index_reg;
int ret;
@@ -335,27 +426,19 @@ static int kempld_detect_device(struct kempld_device_data *pld)
if (ret)
return ret;
- switch (pld->info.type) {
- case 0:
- version_type = "release";
- break;
- case 1:
- version_type = "debug";
- break;
- case 2:
- version_type = "custom";
- break;
- default:
- version_type = "unspecified";
- }
+ dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n",
+ pld->info.version, kempld_get_type_string(pld),
+ pld->info.spec_major, pld->info.spec_minor);
+
+ ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group);
+ if (ret)
+ return ret;
- dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number);
- dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n",
- version_type, pld->info.major, pld->info.minor,
- pld->info.buildnr, pld->info.spec_major,
- pld->info.spec_minor);
+ ret = kempld_register_cells(pld);
+ if (ret)
+ sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
- return kempld_register_cells(pld);
+ return ret;
}
static int kempld_probe(struct platform_device *pdev)
@@ -399,6 +482,8 @@ 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);
+ sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
+
mfd_remove_devices(&pdev->dev);
pdata->release_hardware_mutex(pld);
diff --git a/drivers/mfd/lp3943.c b/drivers/mfd/lp3943.c
index e32226836fb4..335b930112b2 100644
--- a/drivers/mfd/lp3943.c
+++ b/drivers/mfd/lp3943.c
@@ -62,7 +62,7 @@ static const struct lp3943_reg_cfg lp3943_mux_cfg[] = {
{ LP3943_REG_MUX3, 0xC0, 6 },
};
-static struct mfd_cell lp3943_devs[] = {
+static const struct mfd_cell lp3943_devs[] = {
{
.name = "lp3943-pwm",
.of_compatible = "ti,lp3943-pwm",
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 3f10ea3f45d1..7d8482ff5868 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -488,6 +488,7 @@ static struct lpc_ich_info lpc_chipset_info[] = {
[LPC_PPT] = {
.name = "Panther Point",
.iTCO_version = 2,
+ .gpio_version = ICH_V5_GPIO,
},
[LPC_LPT] = {
.name = "Lynx Point",
diff --git a/drivers/mfd/max14577.c b/drivers/mfd/max14577.c
index 484d372a4892..4a5e885383f8 100644
--- a/drivers/mfd/max14577.c
+++ b/drivers/mfd/max14577.c
@@ -26,7 +26,7 @@
#include <linux/mfd/max14577.h>
#include <linux/mfd/max14577-private.h>
-static struct mfd_cell max14577_devs[] = {
+static const struct mfd_cell max14577_devs[] = {
{
.name = "max14577-muic",
.of_compatible = "maxim,max14577-muic",
@@ -38,7 +38,7 @@ static struct mfd_cell max14577_devs[] = {
{ .name = "max14577-charger", },
};
-static struct mfd_cell max77836_devs[] = {
+static const struct mfd_cell max77836_devs[] = {
{
.name = "max77836-muic",
.of_compatible = "maxim,max77836-muic",
@@ -57,7 +57,7 @@ static struct mfd_cell max77836_devs[] = {
},
};
-static struct of_device_id max14577_dt_match[] = {
+static const struct of_device_id max14577_dt_match[] = {
{
.compatible = "maxim,max14577",
.data = (void *)MAXIM_DEVICE_TYPE_MAX14577,
@@ -292,7 +292,7 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
struct device_node *np = i2c->dev.of_node;
int ret = 0;
const struct regmap_irq_chip *irq_chip;
- struct mfd_cell *mfd_devs;
+ const struct mfd_cell *mfd_devs;
unsigned int mfd_devs_size;
int irq_flags;
@@ -331,7 +331,8 @@ static int max14577_i2c_probe(struct i2c_client *i2c,
of_id = of_match_device(max14577_dt_match, &i2c->dev);
if (of_id)
- max14577->dev_type = (unsigned int)of_id->data;
+ max14577->dev_type =
+ (enum maxim_device_type)of_id->data;
} else {
max14577->dev_type = id->driver_data;
}
@@ -414,20 +415,18 @@ static int max14577_suspend(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max14577 *max14577 = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev)) {
+ if (device_may_wakeup(dev))
enable_irq_wake(max14577->irq);
- /*
- * MUIC IRQ must be disabled during suspend if this is
- * a wake up source because it will be handled before
- * resuming I2C.
- *
- * When device is woken up from suspend (e.g. by ADC change),
- * an interrupt occurs before resuming I2C bus controller.
- * Interrupt handler tries to read registers but this read
- * will fail because I2C is still suspended.
- */
- disable_irq(max14577->irq);
- }
+ /*
+ * MUIC IRQ must be disabled during suspend because if it happens
+ * while suspended it will be handled before resuming I2C.
+ *
+ * When device is woken up from suspend (e.g. by ADC change),
+ * an interrupt occurs before resuming I2C bus controller.
+ * Interrupt handler tries to read registers but this read
+ * will fail because I2C is still suspended.
+ */
+ disable_irq(max14577->irq);
return 0;
}
@@ -437,10 +436,9 @@ static int max14577_resume(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct max14577 *max14577 = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev)) {
+ if (device_may_wakeup(dev))
disable_irq_wake(max14577->irq);
- enable_irq(max14577->irq);
- }
+ enable_irq(max14577->irq);
return 0;
}
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index e5fce765accb..ce869acf27ae 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -47,7 +47,7 @@ static struct regmap_config max77686_regmap_config = {
};
#ifdef CONFIG_OF
-static struct of_device_id max77686_pmic_dt_match[] = {
+static const struct of_device_id max77686_pmic_dt_match[] = {
{.compatible = "maxim,max77686", .data = NULL},
{},
};
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index c5535f018466..7e05428c756d 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -243,7 +243,7 @@ static const struct dev_pm_ops max77693_pm = {
};
#ifdef CONFIG_OF
-static struct of_device_id max77693_dt_match[] = {
+static const struct of_device_id max77693_dt_match[] = {
{ .compatible = "maxim,max77693" },
{},
};
diff --git a/drivers/mfd/max8907.c b/drivers/mfd/max8907.c
index 07740314b29d..232749c8813d 100644
--- a/drivers/mfd/max8907.c
+++ b/drivers/mfd/max8907.c
@@ -305,7 +305,7 @@ static int max8907_i2c_remove(struct i2c_client *i2c)
}
#ifdef CONFIG_OF
-static struct of_device_id max8907_of_match[] = {
+static const struct of_device_id max8907_of_match[] = {
{ .compatible = "maxim,max8907" },
{ },
};
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 8cf7a015cfe5..595364ee178a 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -51,7 +51,7 @@ static const struct mfd_cell max8997_devs[] = {
};
#ifdef CONFIG_OF
-static struct of_device_id max8997_pmic_dt_match[] = {
+static const struct of_device_id max8997_pmic_dt_match[] = {
{ .compatible = "maxim,max8997-pmic", .data = (void *)TYPE_MAX8997 },
{},
};
diff --git a/drivers/mfd/max8998.c b/drivers/mfd/max8998.c
index 592db06098e6..a37cb7444b6e 100644
--- a/drivers/mfd/max8998.c
+++ b/drivers/mfd/max8998.c
@@ -132,7 +132,7 @@ int max8998_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
EXPORT_SYMBOL(max8998_update_reg);
#ifdef CONFIG_OF
-static struct of_device_id max8998_dt_match[] = {
+static const struct of_device_id max8998_dt_match[] = {
{ .compatible = "maxim,max8998", .data = (void *)TYPE_MAX8998 },
{ .compatible = "national,lp3974", .data = (void *)TYPE_LP3974 },
{ .compatible = "ti,lp3974", .data = (void *)TYPE_LP3974 },
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 0c6c21c5b1a8..acf5dd712eb2 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -660,34 +660,22 @@ int mc13xxx_common_init(struct device *dev)
if (ret)
return ret;
+ mutex_init(&mc13xxx->lock);
+
ret = request_threaded_irq(mc13xxx->irq, NULL, mc13xxx_irq_thread,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13xxx", mc13xxx);
if (ret)
return ret;
- mutex_init(&mc13xxx->lock);
-
if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
mc13xxx->flags = pdata->flags;
if (mc13xxx->flags & MC13XXX_USE_ADC)
mc13xxx_add_subdevice(mc13xxx, "%s-adc");
- if (mc13xxx->flags & MC13XXX_USE_CODEC) {
- if (pdata)
- mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
- pdata->codec, sizeof(*pdata->codec));
- else
- mc13xxx_add_subdevice(mc13xxx, "%s-codec");
- }
-
if (mc13xxx->flags & MC13XXX_USE_RTC)
mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
- if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
- mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
- &pdata->touch, sizeof(pdata->touch));
-
if (pdata) {
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
&pdata->regulators, sizeof(pdata->regulators));
@@ -695,10 +683,20 @@ int mc13xxx_common_init(struct device *dev)
pdata->leds, sizeof(*pdata->leds));
mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
pdata->buttons, sizeof(*pdata->buttons));
+ if (mc13xxx->flags & MC13XXX_USE_CODEC)
+ mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
+ pdata->codec, sizeof(*pdata->codec));
+ if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
+ mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
+ &pdata->touch, sizeof(pdata->touch));
} else {
mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
mc13xxx_add_subdevice(mc13xxx, "%s-led");
mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
+ if (mc13xxx->flags & MC13XXX_USE_CODEC)
+ mc13xxx_add_subdevice(mc13xxx, "%s-codec");
+ if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
+ mc13xxx_add_subdevice(mc13xxx, "%s-ts");
}
return 0;
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index ad25bfa3fb02..5e2667afe2bc 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -1287,29 +1287,8 @@ static struct i2c_driver menelaus_i2c_driver = {
.id_table = menelaus_id,
};
-static int __init menelaus_init(void)
-{
- int res;
-
- res = i2c_add_driver(&menelaus_i2c_driver);
- if (res < 0) {
- pr_err(DRIVER_NAME ": driver registration failed\n");
- return res;
- }
-
- return 0;
-}
-
-static void __exit menelaus_exit(void)
-{
- i2c_del_driver(&menelaus_i2c_driver);
-
- /* FIXME: Shutdown menelaus parts that can be shut down */
-}
+module_i2c_driver(menelaus_i2c_driver);
MODULE_AUTHOR("Texas Instruments, Inc. (and others)");
MODULE_DESCRIPTION("I2C interface for Menelaus.");
MODULE_LICENSE("GPL");
-
-module_init(menelaus_init);
-module_exit(menelaus_exit);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 267649244737..892d343193ad 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -102,7 +102,7 @@ static int mfd_add_device(struct device *parent, int id,
pdev->dev.dma_mask = parent->dma_mask;
pdev->dev.dma_parms = parent->dma_parms;
- ret = devm_regulator_bulk_register_supply_alias(
+ ret = regulator_bulk_register_supply_alias(
&pdev->dev, cell->parent_supplies,
parent, cell->parent_supplies,
cell->num_parent_supplies);
@@ -182,9 +182,9 @@ static int mfd_add_device(struct device *parent, int id,
return 0;
fail_alias:
- devm_regulator_bulk_unregister_supply_alias(&pdev->dev,
- cell->parent_supplies,
- cell->num_parent_supplies);
+ regulator_bulk_unregister_supply_alias(&pdev->dev,
+ cell->parent_supplies,
+ cell->num_parent_supplies);
fail_res:
kfree(res);
fail_device:
@@ -238,6 +238,9 @@ static int mfd_remove_devices_fn(struct device *dev, void *c)
pdev = to_platform_device(dev);
cell = mfd_get_cell(pdev);
+ regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
+ cell->num_parent_supplies);
+
/* find the base address of usage_count pointers (for freeing) */
if (!*usage_count || (cell->usage_count < *usage_count))
*usage_count = cell->usage_count;
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 651e249287dc..b48d80c367f9 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -557,7 +557,7 @@ static int usbhs_omap_get_dt_pdata(struct device *dev,
return 0;
}
-static struct of_device_id usbhs_child_match_table[] = {
+static const struct of_device_id usbhs_child_match_table[] = {
{ .compatible = "ti,omap-ehci", },
{ .compatible = "ti,omap-ohci", },
{ }
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index b97a97187ae9..959513803542 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -26,7 +26,6 @@
#include <linux/regmap.h>
#include <linux/of_platform.h>
#include <linux/mfd/core.h>
-#include <linux/mfd/pm8xxx/core.h>
#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
@@ -57,7 +56,6 @@
#define PM8921_NR_IRQS 256
struct pm_irq_chip {
- struct device *dev;
struct regmap *regmap;
spinlock_t pm_irq_lock;
struct irq_domain *irqdomain;
@@ -67,11 +65,6 @@ struct pm_irq_chip {
u8 config[0];
};
-struct pm8921 {
- struct device *dev;
- struct pm_irq_chip *irq_chip;
-};
-
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
unsigned int *ip)
{
@@ -255,55 +248,6 @@ static struct irq_chip pm8xxx_irq_chip = {
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
-/**
- * pm8xxx_get_irq_stat - get the status of the irq line
- * @chip: pointer to identify a pmic irq controller
- * @irq: the irq number
- *
- * The pm8xxx gpio and mpp rely on the interrupt block to read
- * the values on their pins. This function is to facilitate reading
- * the status of a gpio or an mpp line. The caller has to convert the
- * gpio number to irq number.
- *
- * RETURNS:
- * an int indicating the value read on that line
- */
-static int pm8xxx_get_irq_stat(struct pm_irq_chip *chip, int irq)
-{
- int pmirq, rc;
- unsigned int block, bits, bit;
- unsigned long flags;
- struct irq_data *irq_data = irq_get_irq_data(irq);
-
- pmirq = irq_data->hwirq;
-
- block = pmirq / 8;
- bit = pmirq % 8;
-
- spin_lock_irqsave(&chip->pm_irq_lock, flags);
-
- rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
- if (rc) {
- pr_err("Failed Selecting block irq=%d pmirq=%d blk=%d rc=%d\n",
- irq, pmirq, block, rc);
- goto bail_out;
- }
-
- rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
- if (rc) {
- pr_err("Failed Configuring irq=%d pmirq=%d blk=%d rc=%d\n",
- irq, pmirq, block, rc);
- goto bail_out;
- }
-
- rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
- spin_unlock_irqrestore(&chip->pm_irq_lock, flags);
-
- return rc;
-}
-
static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
@@ -324,56 +268,6 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
.map = pm8xxx_irq_domain_map,
};
-static int pm8921_readb(const struct device *dev, u16 addr, u8 *val)
-{
- const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
- const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
-
- return ssbi_read(pmic->dev->parent, addr, val, 1);
-}
-
-static int pm8921_writeb(const struct device *dev, u16 addr, u8 val)
-{
- const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
- const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
-
- return ssbi_write(pmic->dev->parent, addr, &val, 1);
-}
-
-static int pm8921_read_buf(const struct device *dev, u16 addr, u8 *buf,
- int cnt)
-{
- const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
- const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
-
- return ssbi_read(pmic->dev->parent, addr, buf, cnt);
-}
-
-static int pm8921_write_buf(const struct device *dev, u16 addr, u8 *buf,
- int cnt)
-{
- const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
- const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
-
- return ssbi_write(pmic->dev->parent, addr, buf, cnt);
-}
-
-static int pm8921_read_irq_stat(const struct device *dev, int irq)
-{
- const struct pm8xxx_drvdata *pm8921_drvdata = dev_get_drvdata(dev);
- const struct pm8921 *pmic = pm8921_drvdata->pm_chip_data;
-
- return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
-}
-
-static struct pm8xxx_drvdata pm8921_drvdata = {
- .pmic_readb = pm8921_readb,
- .pmic_writeb = pm8921_writeb,
- .pmic_read_buf = pm8921_read_buf,
- .pmic_write_buf = pm8921_write_buf,
- .pmic_read_irq_stat = pm8921_read_irq_stat,
-};
-
static const struct regmap_config ssbi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
@@ -392,7 +286,6 @@ MODULE_DEVICE_TABLE(of, pm8921_id_table);
static int pm8921_probe(struct platform_device *pdev)
{
- struct pm8921 *pmic;
struct regmap *regmap;
int irq, rc;
unsigned int val;
@@ -404,12 +297,6 @@ static int pm8921_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- pmic = devm_kzalloc(&pdev->dev, sizeof(struct pm8921), GFP_KERNEL);
- if (!pmic) {
- pr_err("Cannot alloc pm8921 struct\n");
- return -ENOMEM;
- }
-
regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
&ssbi_regmap_config);
if (IS_ERR(regmap))
@@ -434,18 +321,13 @@ static int pm8921_probe(struct platform_device *pdev)
pr_info("PMIC revision 2: %02X\n", val);
rev |= val << BITS_PER_BYTE;
- pmic->dev = &pdev->dev;
- pm8921_drvdata.pm_chip_data = pmic;
- platform_set_drvdata(pdev, &pm8921_drvdata);
-
chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
sizeof(chip->config[0]) * nirqs,
GFP_KERNEL);
if (!chip)
return -ENOMEM;
- pmic->irq_chip = chip;
- chip->dev = &pdev->dev;
+ platform_set_drvdata(pdev, chip);
chip->regmap = regmap;
chip->num_irqs = nirqs;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
@@ -481,8 +363,7 @@ static int pm8921_remove_child(struct device *dev, void *unused)
static int pm8921_remove(struct platform_device *pdev)
{
int irq = platform_get_irq(pdev, 0);
- struct pm8921 *pmic = pm8921_drvdata.pm_chip_data;
- struct pm_irq_chip *chip = pmic->irq_chip;
+ struct pm_irq_chip *chip = platform_get_drvdata(pdev);
device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
irq_set_chained_handler(irq, NULL);
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c
index c79569750be9..6575585f1d1f 100644
--- a/drivers/mfd/rdc321x-southbridge.c
+++ b/drivers/mfd/rdc321x-southbridge.c
@@ -38,7 +38,7 @@ static struct resource rdc321x_wdt_resource[] = {
};
static struct rdc321x_gpio_pdata rdc321x_gpio_pdata = {
- .max_gpios = RDC321X_MAX_GPIO,
+ .max_gpios = RDC321X_NUM_GPIO,
};
static struct resource rdc321x_gpio_resources[] = {
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
index b53b9d46cc45..6352bec8419a 100644
--- a/drivers/mfd/rtsx_usb.c
+++ b/drivers/mfd/rtsx_usb.c
@@ -29,7 +29,7 @@ static int polling_pipe = 1;
module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
-static struct mfd_cell rtsx_usb_cells[] = {
+static const struct mfd_cell rtsx_usb_cells[] = {
[RTSX_USB_SD_CARD] = {
.name = "rtsx_usb_sdmmc",
.pdata_size = 0,
@@ -67,7 +67,7 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
add_timer(&ucr->sg_timer);
usb_sg_wait(&ucr->current_sg);
- del_timer(&ucr->sg_timer);
+ del_timer_sync(&ucr->sg_timer);
if (act_len)
*act_len = ucr->current_sg.bytes;
@@ -644,14 +644,14 @@ static int rtsx_usb_probe(struct usb_interface *intf,
if (ret)
goto out_init_fail;
+ /* initialize USB SG transfer timer */
+ setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
+
ret = mfd_add_devices(&intf->dev, usb_dev->devnum, rtsx_usb_cells,
ARRAY_SIZE(rtsx_usb_cells), NULL, 0, NULL);
if (ret)
goto out_init_fail;
- /* initialize USB SG transfer timer */
- init_timer(&ucr->sg_timer);
- setup_timer(&ucr->sg_timer, rtsx_usb_sg_timed_out, (unsigned long) ucr);
#ifdef CONFIG_PM
intf->needs_remote_wakeup = 1;
usb_enable_autosuspend(usb_dev);
@@ -687,9 +687,15 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
dev_dbg(&intf->dev, "%s called with pm message 0x%04u\n",
__func__, message.event);
+ /*
+ * Call to make sure LED is off during suspend to save more power.
+ * It is NOT a permanent state and could be turned on anytime later.
+ * Thus no need to call turn_on when resunming.
+ */
mutex_lock(&ucr->dev_mutex);
rtsx_usb_turn_off_led(ucr);
mutex_unlock(&ucr->dev_mutex);
+
return 0;
}
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c
index 1cf27521fff4..be06d0abbf19 100644
--- a/drivers/mfd/sec-core.c
+++ b/drivers/mfd/sec-core.c
@@ -25,7 +25,6 @@
#include <linux/mfd/core.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h>
-#include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
@@ -91,7 +90,7 @@ static const struct mfd_cell s2mpa01_devs[] = {
};
#ifdef CONFIG_OF
-static struct of_device_id sec_dt_match[] = {
+static const struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X,
}, {
@@ -196,20 +195,6 @@ static const struct regmap_config s5m8767_regmap_config = {
.cache_type = REGCACHE_FLAT,
};
-static const struct regmap_config s5m_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = SEC_RTC_REG_MAX,
-};
-
-static const struct regmap_config s2mps14_rtc_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-
- .max_register = S2MPS_RTC_REG_MAX,
-};
-
#ifdef CONFIG_OF
/*
* Only the common platform data elements for s5m8767 are parsed here from the
@@ -264,8 +249,9 @@ static int sec_pmic_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
- const struct regmap_config *regmap, *regmap_rtc;
+ const struct regmap_config *regmap;
struct sec_pmic_dev *sec_pmic;
+ unsigned long device_type;
int ret;
sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
@@ -277,7 +263,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
sec_pmic->dev = &i2c->dev;
sec_pmic->i2c = i2c;
sec_pmic->irq = i2c->irq;
- sec_pmic->type = sec_i2c_get_driver_data(i2c, id);
+ device_type = sec_i2c_get_driver_data(i2c, id);
if (sec_pmic->dev->of_node) {
pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);
@@ -285,7 +271,7 @@ static int sec_pmic_probe(struct i2c_client *i2c,
ret = PTR_ERR(pdata);
return ret;
}
- pdata->device_type = sec_pmic->type;
+ pdata->device_type = device_type;
}
if (pdata) {
sec_pmic->device_type = pdata->device_type;
@@ -298,39 +284,21 @@ static int sec_pmic_probe(struct i2c_client *i2c,
switch (sec_pmic->device_type) {
case S2MPA01:
regmap = &s2mpa01_regmap_config;
- /*
- * The rtc-s5m driver does not support S2MPA01 and there
- * is no mfd_cell for S2MPA01 RTC device.
- * However we must pass something to devm_regmap_init_i2c()
- * so use S5M-like regmap config even though it wouldn't work.
- */
- regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS11X:
regmap = &s2mps11_regmap_config;
- /*
- * The rtc-s5m driver does not support S2MPS11 and there
- * is no mfd_cell for S2MPS11 RTC device.
- * However we must pass something to devm_regmap_init_i2c()
- * so use S5M-like regmap config even though it wouldn't work.
- */
- regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
- regmap_rtc = &s2mps14_rtc_regmap_config;
break;
case S5M8763X:
regmap = &s5m8763_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
case S5M8767X:
regmap = &s5m8767_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
default:
regmap = &sec_regmap_config;
- regmap_rtc = &s5m_rtc_regmap_config;
break;
}
@@ -342,21 +310,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
return ret;
}
- sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
- if (!sec_pmic->rtc) {
- dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n");
- return -ENODEV;
- }
- i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
-
- sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc);
- if (IS_ERR(sec_pmic->regmap_rtc)) {
- ret = PTR_ERR(sec_pmic->regmap_rtc);
- dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
- ret);
- goto err_regmap_rtc;
- }
-
if (pdata && pdata->cfg_pmic_irq)
pdata->cfg_pmic_irq();
@@ -403,8 +356,6 @@ static int sec_pmic_probe(struct i2c_client *i2c,
err_mfd:
sec_irq_exit(sec_pmic);
-err_regmap_rtc:
- i2c_unregister_device(sec_pmic->rtc);
return ret;
}
@@ -414,7 +365,6 @@ static int sec_pmic_remove(struct i2c_client *i2c)
mfd_remove_devices(sec_pmic->dev);
sec_irq_exit(sec_pmic);
- i2c_unregister_device(sec_pmic->rtc);
return 0;
}
@@ -424,19 +374,18 @@ static int sec_pmic_suspend(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev)) {
+ if (device_may_wakeup(dev))
enable_irq_wake(sec_pmic->irq);
- /*
- * PMIC IRQ must be disabled during suspend for RTC alarm
- * to work properly.
- * When device is woken up from suspend by RTC Alarm, an
- * interrupt occurs before resuming I2C bus controller.
- * The interrupt is handled by regmap_irq_thread which tries
- * to read RTC registers. This read fails (I2C is still
- * suspended) and RTC Alarm interrupt is disabled.
- */
- disable_irq(sec_pmic->irq);
- }
+ /*
+ * PMIC IRQ must be disabled during suspend for RTC alarm
+ * to work properly.
+ * When device is woken up from suspend, an
+ * interrupt occurs before resuming I2C bus controller.
+ * The interrupt is handled by regmap_irq_thread which tries
+ * to read RTC registers. This read fails (I2C is still
+ * suspended) and RTC Alarm interrupt is disabled.
+ */
+ disable_irq(sec_pmic->irq);
return 0;
}
@@ -446,10 +395,9 @@ static int sec_pmic_resume(struct device *dev)
struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
- if (device_may_wakeup(dev)) {
+ if (device_may_wakeup(dev))
disable_irq_wake(sec_pmic->irq);
- enable_irq(sec_pmic->irq);
- }
+ enable_irq(sec_pmic->irq);
return 0;
}
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 64e7913aadc6..654e2c1dbf7a 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -385,7 +385,7 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
&sec_pmic->irq_data);
break;
default:
- dev_err(sec_pmic->dev, "Unknown device type %d\n",
+ dev_err(sec_pmic->dev, "Unknown device type %lu\n",
sec_pmic->device_type);
return -EINVAL;
}
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index e7dc441a8f8a..81e6d0932bf0 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1726,7 +1726,7 @@ static struct pci_driver sm501_pci_driver = {
MODULE_ALIAS("platform:sm501");
-static struct of_device_id of_sm501_match_tbl[] = {
+static const struct of_device_id of_sm501_match_tbl[] = {
{ .compatible = "smi,sm501", },
{ /* end */ }
};
diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index 0da02e11d58e..a45f9c0a330a 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/of_device.h>
#include "stmpe.h"
static int i2c_reg_read(struct stmpe *stmpe, u8 reg)
@@ -52,15 +53,41 @@ static struct stmpe_client_info i2c_ci = {
.write_block = i2c_block_write,
};
+static const struct of_device_id stmpe_of_match[] = {
+ { .compatible = "st,stmpe610", .data = (void *)STMPE610, },
+ { .compatible = "st,stmpe801", .data = (void *)STMPE801, },
+ { .compatible = "st,stmpe811", .data = (void *)STMPE811, },
+ { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
+ { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
+ { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
+ { .compatible = "st,stmpe2403", .data = (void *)STMPE2403, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, stmpe_of_match);
+
static int
stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
+ int partnum;
+ const struct of_device_id *of_id;
+
i2c_ci.data = (void *)id;
i2c_ci.irq = i2c->irq;
i2c_ci.client = i2c;
i2c_ci.dev = &i2c->dev;
- return stmpe_probe(&i2c_ci, id->driver_data);
+ of_id = of_match_device(stmpe_of_match, &i2c->dev);
+ if (!of_id) {
+ /*
+ * This happens when the I2C ID matches the node name
+ * but no real compatible string has been given.
+ */
+ dev_info(&i2c->dev, "matching on node name, compatible is preferred\n");
+ partnum = id->driver_data;
+ } else
+ partnum = (int)of_id->data;
+
+ return stmpe_probe(&i2c_ci, partnum);
}
static int stmpe_i2c_remove(struct i2c_client *i2c)
@@ -89,6 +116,7 @@ static struct i2c_driver stmpe_i2c_driver = {
#ifdef CONFIG_PM
.pm = &stmpe_dev_pm_ops,
#endif
+ .of_match_table = stmpe_of_match,
},
.probe = stmpe_i2c_probe,
.remove = stmpe_i2c_remove,
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 4a91f6771fb8..3b6bfa7184ad 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/mfd/core.h>
#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
#include "stmpe.h"
static int __stmpe_enable(struct stmpe *stmpe, unsigned int blocks)
@@ -605,9 +606,18 @@ static int stmpe1601_enable(struct stmpe *stmpe, unsigned int blocks,
if (blocks & STMPE_BLOCK_GPIO)
mask |= STMPE1601_SYS_CTRL_ENABLE_GPIO;
+ else
+ mask &= ~STMPE1601_SYS_CTRL_ENABLE_GPIO;
if (blocks & STMPE_BLOCK_KEYPAD)
mask |= STMPE1601_SYS_CTRL_ENABLE_KPC;
+ else
+ mask &= ~STMPE1601_SYS_CTRL_ENABLE_KPC;
+
+ if (blocks & STMPE_BLOCK_PWM)
+ mask |= STMPE1601_SYS_CTRL_ENABLE_SPWM;
+ else
+ mask &= ~STMPE1601_SYS_CTRL_ENABLE_SPWM;
return __stmpe_set_bits(stmpe, STMPE1601_REG_SYS_CTRL, mask,
enable ? mask : 0);
@@ -986,9 +996,6 @@ static int stmpe_irq_init(struct stmpe *stmpe, struct device_node *np)
int base = 0;
int num_irqs = stmpe->variant->num_irqs;
- if (!np)
- base = stmpe->irq_base;
-
stmpe->domain = irq_domain_add_simple(np, num_irqs, base,
&stmpe_irq_ops, stmpe);
if (!stmpe->domain) {
@@ -1067,7 +1074,7 @@ static int stmpe_chip_init(struct stmpe *stmpe)
static int stmpe_add_device(struct stmpe *stmpe, const struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base, stmpe->domain);
+ NULL, 0, stmpe->domain);
}
static int stmpe_devices_init(struct stmpe *stmpe)
@@ -1171,12 +1178,23 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum)
stmpe->dev = ci->dev;
stmpe->client = ci->client;
stmpe->pdata = pdata;
- stmpe->irq_base = pdata->irq_base;
stmpe->ci = ci;
stmpe->partnum = partnum;
stmpe->variant = stmpe_variant_info[partnum];
stmpe->regs = stmpe->variant->regs;
stmpe->num_gpios = stmpe->variant->num_gpios;
+ stmpe->vcc = devm_regulator_get_optional(ci->dev, "vcc");
+ if (!IS_ERR(stmpe->vcc)) {
+ ret = regulator_enable(stmpe->vcc);
+ if (ret)
+ dev_warn(ci->dev, "failed to enable VCC supply\n");
+ }
+ stmpe->vio = devm_regulator_get_optional(ci->dev, "vio");
+ if (!IS_ERR(stmpe->vio)) {
+ ret = regulator_enable(stmpe->vio);
+ if (ret)
+ dev_warn(ci->dev, "failed to enable VIO supply\n");
+ }
dev_set_drvdata(stmpe->dev, stmpe);
if (ci->init)
@@ -1243,6 +1261,11 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum)
int stmpe_remove(struct stmpe *stmpe)
{
+ if (!IS_ERR(stmpe->vio))
+ regulator_disable(stmpe->vio);
+ if (!IS_ERR(stmpe->vcc))
+ regulator_disable(stmpe->vcc);
+
mfd_remove_devices(stmpe->dev);
return 0;
diff --git a/drivers/mfd/stmpe.h b/drivers/mfd/stmpe.h
index 6639f1b0fef5..9e4d21d37a11 100644
--- a/drivers/mfd/stmpe.h
+++ b/drivers/mfd/stmpe.h
@@ -192,7 +192,7 @@ int stmpe_remove(struct stmpe *stmpe);
#define STMPE1601_SYS_CTRL_ENABLE_GPIO (1 << 3)
#define STMPE1601_SYS_CTRL_ENABLE_KPC (1 << 1)
-#define STMPE1601_SYSCON_ENABLE_SPWM (1 << 0)
+#define STMPE1601_SYS_CTRL_ENABLE_SPWM (1 << 0)
/* The 1601/2403 share the same masks */
#define STMPE1601_AUTOSLEEP_TIMEOUT_MASK (0x7)
diff --git a/drivers/mfd/sun6i-prcm.c b/drivers/mfd/sun6i-prcm.c
new file mode 100644
index 000000000000..718fc4d2adc0
--- /dev/null
+++ b/drivers/mfd/sun6i-prcm.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * Allwinner PRCM (Power/Reset/Clock Management) driver
+ *
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+struct prcm_data {
+ int nsubdevs;
+ const struct mfd_cell *subdevs;
+};
+
+static const struct resource sun6i_a31_ar100_clk_res[] = {
+ {
+ .start = 0x0,
+ .end = 0x3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const struct resource sun6i_a31_apb0_clk_res[] = {
+ {
+ .start = 0xc,
+ .end = 0xf,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const struct resource sun6i_a31_apb0_gates_clk_res[] = {
+ {
+ .start = 0x28,
+ .end = 0x2b,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const struct resource sun6i_a31_apb0_rstc_res[] = {
+ {
+ .start = 0xb0,
+ .end = 0xb3,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const struct mfd_cell sun6i_a31_prcm_subdevs[] = {
+ {
+ .name = "sun6i-a31-ar100-clk",
+ .of_compatible = "allwinner,sun6i-a31-ar100-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_ar100_clk_res),
+ .resources = sun6i_a31_ar100_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-clk",
+ .of_compatible = "allwinner,sun6i-a31-apb0-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res),
+ .resources = sun6i_a31_apb0_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-gates-clk",
+ .of_compatible = "allwinner,sun6i-a31-apb0-gates-clk",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res),
+ .resources = sun6i_a31_apb0_gates_clk_res,
+ },
+ {
+ .name = "sun6i-a31-apb0-clock-reset",
+ .of_compatible = "allwinner,sun6i-a31-clock-reset",
+ .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res),
+ .resources = sun6i_a31_apb0_rstc_res,
+ },
+};
+
+static const struct prcm_data sun6i_a31_prcm_data = {
+ .nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs),
+ .subdevs = sun6i_a31_prcm_subdevs,
+};
+
+static const struct of_device_id sun6i_prcm_dt_ids[] = {
+ {
+ .compatible = "allwinner,sun6i-a31-prcm",
+ .data = &sun6i_a31_prcm_data,
+ },
+ { /* sentinel */ },
+};
+
+static int sun6i_prcm_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ const struct prcm_data *data;
+ struct resource *res;
+ int ret;
+
+ match = of_match_node(sun6i_prcm_dt_ids, np);
+ if (!match)
+ return -EINVAL;
+
+ data = match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no prcm memory region provided\n");
+ return -ENOENT;
+ }
+
+ ret = mfd_add_devices(&pdev->dev, 0, data->subdevs, data->nsubdevs,
+ res, -1, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add subdevices\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver sun6i_prcm_driver = {
+ .driver = {
+ .name = "sun6i-prcm",
+ .owner = THIS_MODULE,
+ .of_match_table = sun6i_prcm_dt_ids,
+ },
+ .probe = sun6i_prcm_probe,
+};
+module_platform_driver(sun6i_prcm_driver);
+
+MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner sun6i PRCM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index e2a04bb8bc1e..ca15878ce5c0 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -95,7 +95,11 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
struct device_node *syscon_np;
struct regmap *regmap;
- syscon_np = of_parse_phandle(np, property, 0);
+ if (property)
+ syscon_np = of_parse_phandle(np, property, 0);
+ else
+ syscon_np = np;
+
if (!syscon_np)
return ERR_PTR(-ENODEV);
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c
index 3b27482a174f..a2e1990c9de7 100644
--- a/drivers/mfd/tps6507x.c
+++ b/drivers/mfd/tps6507x.c
@@ -119,7 +119,7 @@ static const struct i2c_device_id tps6507x_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id);
#ifdef CONFIG_OF
-static struct of_device_id tps6507x_of_match[] = {
+static const struct of_device_id tps6507x_of_match[] = {
{.compatible = "ti,tps6507x", },
{},
};
diff --git a/drivers/mfd/tps65218.c b/drivers/mfd/tps65218.c
index a74bfb59f18f..0d256cb002eb 100644
--- a/drivers/mfd/tps65218.c
+++ b/drivers/mfd/tps65218.c
@@ -197,6 +197,7 @@ static struct regmap_irq_chip tps65218_irq_chip = {
static const struct of_device_id of_tps65218_match_table[] = {
{ .compatible = "ti,tps65218", },
+ {}
};
static int tps65218_probe(struct i2c_client *client,
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 835e5549ecdd..8e1dbc469580 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -444,7 +444,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
return pdata;
}
-static struct of_device_id tps6586x_of_match[] = {
+static const struct of_device_id tps6586x_of_match[] = {
{ .compatible = "ti,tps6586x", },
{ },
};
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 460a014ca629..f9e42ea1cb1a 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -379,7 +379,7 @@ err_sleep_init:
}
#ifdef CONFIG_OF
-static struct of_device_id tps65910_of_match[] = {
+static const struct of_device_id tps65910_of_match[] = {
{ .compatible = "ti,tps65910", .data = (void *)TPS65910},
{ .compatible = "ti,tps65911", .data = (void *)TPS65911},
{ },
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index 6e88f25832fb..ae26d84b3a59 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -87,8 +87,13 @@ static struct reg_default twl6040_defaults[] = {
};
static struct reg_default twl6040_patch[] = {
- /* Select I2C bus access to dual access registers */
- { TWL6040_REG_ACCCTL, 0x09 },
+ /*
+ * Select I2C bus access to dual access registers
+ * Interrupt register is cleared on read
+ * Select fast mode for i2c (400KHz)
+ */
+ { TWL6040_REG_ACCCTL,
+ TWL6040_I2CSEL | TWL6040_INTCLRMODE | TWL6040_I2CMODE(1) },
};
@@ -286,6 +291,8 @@ int twl6040_power(struct twl6040 *twl6040, int on)
if (twl6040->power_count++)
goto out;
+ clk_prepare_enable(twl6040->clk32k);
+
/* Allow writes to the chip */
regcache_cache_only(twl6040->regmap, false);
@@ -341,6 +348,8 @@ int twl6040_power(struct twl6040 *twl6040, int on)
twl6040->sysclk = 0;
twl6040->mclk = 0;
+
+ clk_disable_unprepare(twl6040->clk32k);
}
out:
@@ -432,12 +441,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
TWL6040_HPLLENA;
break;
case 19200000:
- /*
- * PLL disabled
- * (enable PLL if MCLK jitter quality
- * doesn't meet specification)
- */
- hppllctl |= TWL6040_MCLK_19200KHZ;
+ /* PLL enabled, bypass mode */
+ hppllctl |= TWL6040_MCLK_19200KHZ |
+ TWL6040_HPLLBP | TWL6040_HPLLENA;
break;
case 26000000:
/* PLL enabled, active mode */
@@ -445,9 +451,9 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,
TWL6040_HPLLENA;
break;
case 38400000:
- /* PLL enabled, active mode */
+ /* PLL enabled, bypass mode */
hppllctl |= TWL6040_MCLK_38400KHZ |
- TWL6040_HPLLENA;
+ TWL6040_HPLLBP | TWL6040_HPLLENA;
break;
default:
dev_err(twl6040->dev,
@@ -639,6 +645,12 @@ static int twl6040_probe(struct i2c_client *client,
i2c_set_clientdata(client, twl6040);
+ twl6040->clk32k = devm_clk_get(&client->dev, "clk32k");
+ if (IS_ERR(twl6040->clk32k)) {
+ dev_info(&client->dev, "clk32k is not handled\n");
+ twl6040->clk32k = NULL;
+ }
+
twl6040->supplies[0].supply = "vio";
twl6040->supplies[1].supply = "v2v1";
ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES,
@@ -660,6 +672,9 @@ static int twl6040_probe(struct i2c_client *client,
mutex_init(&twl6040->mutex);
init_completion(&twl6040->ready);
+ regmap_register_patch(twl6040->regmap, twl6040_patch,
+ ARRAY_SIZE(twl6040_patch));
+
twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV);
if (twl6040->rev < 0) {
dev_err(&client->dev, "Failed to read revision register: %d\n",
@@ -679,6 +694,9 @@ static int twl6040_probe(struct i2c_client *client,
GPIOF_OUT_INIT_LOW, "audpwron");
if (ret)
goto gpio_err;
+
+ /* Clear any pending interrupt */
+ twl6040_reg_read(twl6040, TWL6040_REG_INTID);
}
ret = regmap_add_irq_chip(twl6040->regmap, twl6040->irq, IRQF_ONESHOT,
@@ -707,10 +725,6 @@ static int twl6040_probe(struct i2c_client *client,
goto readyirq_err;
}
- /* dual-access registers controlled by I2C only */
- regmap_register_patch(twl6040->regmap, twl6040_patch,
- ARRAY_SIZE(twl6040_patch));
-
/*
* The main functionality of twl6040 to provide audio on OMAP4+ systems.
* We can add the ASoC codec child whenever this driver has been loaded.
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 070f8cfbbd7a..c8a993bd17ae 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -333,7 +333,7 @@ static const struct reg_default wm5102_reg_default[] = {
{ 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */
{ 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */
{ 0x00000210, 0x00D4 }, /* R528 - LDO1 Control 1 */
- { 0x00000212, 0x0001 }, /* R530 - LDO1 Control 2 */
+ { 0x00000212, 0x0000 }, /* R530 - LDO1 Control 2 */
{ 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */
{ 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */
{ 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */
@@ -1037,6 +1037,8 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_5:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_6:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_7:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_8:
case ARIZONA_COMFORT_NOISE_GENERATOR:
case ARIZONA_HAPTICS_CONTROL_1:
case ARIZONA_HAPTICS_CONTROL_2:
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 1942b6f231da..41a7f6fb7802 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -468,10 +468,12 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */
{ 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */
{ 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */
- { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 1 */
- { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 2 */
- { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 3 */
- { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 4 */
+ { 0x00000066, 0x01FF }, /* R102 - Always On Triggers Sequence Select 1 */
+ { 0x00000067, 0x01FF }, /* R103 - Always On Triggers Sequence Select 2 */
+ { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 3 */
+ { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
+ { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
+ { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
{ 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
@@ -549,6 +551,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x000002A8, 0x1422 }, /* R680 - Mic Detect Level 3 */
{ 0x000002A9, 0x300A }, /* R681 - Mic Detect Level 4 */
{ 0x000002C3, 0x0000 }, /* R707 - Mic noise mix control 1 */
+ { 0x000002CB, 0x0000 }, /* R715 - Isolation control */
{ 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */
{ 0x00000300, 0x0000 }, /* R768 - Input Enables */
{ 0x00000308, 0x0000 }, /* R776 - Input Rate */
@@ -1498,6 +1501,8 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_5:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_6:
case ARIZONA_COMFORT_NOISE_GENERATOR:
case ARIZONA_HAPTICS_CONTROL_1:
case ARIZONA_HAPTICS_CONTROL_2:
@@ -1580,6 +1585,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_MIC_DETECT_LEVEL_3:
case ARIZONA_MIC_DETECT_LEVEL_4:
case ARIZONA_MIC_NOISE_MIX_CONTROL_1:
+ case ARIZONA_ISOLATION_CONTROL:
case ARIZONA_JACK_DETECT_ANALOGUE:
case ARIZONA_INPUT_ENABLES:
case ARIZONA_INPUT_ENABLES_STATUS:
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index e5eae751aa1b..c6fb5d16ca09 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -64,7 +64,7 @@ EXPORT_SYMBOL_GPL(wm8400_block_read);
static int wm8400_register_codec(struct wm8400 *wm8400)
{
- struct mfd_cell cell = {
+ const struct mfd_cell cell = {
.name = "wm8400-codec",
.platform_data = wm8400,
.pdata_size = sizeof(*wm8400),
diff --git a/drivers/mfd/wm8997-tables.c b/drivers/mfd/wm8997-tables.c
index 5aa807687777..c7a81da64ee1 100644
--- a/drivers/mfd/wm8997-tables.c
+++ b/drivers/mfd/wm8997-tables.c
@@ -174,10 +174,10 @@ static const struct reg_default wm8997_reg_default[] = {
{ 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */
{ 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */
{ 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */
- { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 1 */
- { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 2 */
- { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 3 */
- { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 4 */
+ { 0x00000068, 0x01FF }, /* R104 - Always On Triggers Sequence Select 3 */
+ { 0x00000069, 0x01FF }, /* R105 - Always On Triggers Sequence Select 4 */
+ { 0x0000006A, 0x01FF }, /* R106 - Always On Triggers Sequence Select 5 */
+ { 0x0000006B, 0x01FF }, /* R107 - Always On Triggers Sequence Select 6 */
{ 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */
{ 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */
{ 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */
@@ -814,10 +814,10 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2:
case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3:
case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4:
- case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
- case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3:
case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_5:
+ case ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_6:
case ARIZONA_COMFORT_NOISE_GENERATOR:
case ARIZONA_HAPTICS_CONTROL_1:
case ARIZONA_HAPTICS_CONTROL_2:
@@ -846,6 +846,7 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_RATE_ESTIMATOR_3:
case ARIZONA_RATE_ESTIMATOR_4:
case ARIZONA_RATE_ESTIMATOR_5:
+ case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
case ARIZONA_FLL1_CONTROL_1:
case ARIZONA_FLL1_CONTROL_2:
case ARIZONA_FLL1_CONTROL_3:
@@ -880,6 +881,7 @@ static bool wm8997_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_FLL2_GPIO_CLOCK:
case ARIZONA_MIC_CHARGE_PUMP_1:
case ARIZONA_LDO1_CONTROL_1:
+ case ARIZONA_LDO1_CONTROL_2:
case ARIZONA_LDO2_CONTROL_1:
case ARIZONA_MIC_BIAS_CTRL_1:
case ARIZONA_MIC_BIAS_CTRL_2:
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 8aaf8c1f3f63..b675882307e4 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -694,3 +694,10 @@ config MMC_REALTEK_PCI
help
Say Y here to include driver code to support SD/MMC card interface
of Realtek PCI-E card reader
+
+config MMC_REALTEK_USB
+ tristate "Realtek USB SD/MMC Card Interface Driver"
+ depends on MFD_RTSX_USB
+ help
+ Say Y here to include driver code to support SD/MMC card interface
+ of Realtek RTS5129/39 series card reader
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 0c8aa5e1e304..3eb48b656f25 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_MMC_USHC) += ushc.o
obj-$(CONFIG_MMC_WMT) += wmt-sdmmc.o
obj-$(CONFIG_MMC_REALTEK_PCI) += rtsx_pci_sdmmc.o
+obj-$(CONFIG_MMC_REALTEK_USB) += rtsx_usb_sdmmc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c
new file mode 100644
index 000000000000..e11fafa6fc6b
--- /dev/null
+++ b/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -0,0 +1,1455 @@
+/* Realtek USB SD/MMC Card Interface driver
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ * Roger Tseng <rogerable@realtek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/card.h>
+#include <linux/scatterlist.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mfd/rtsx_usb.h>
+#include <asm/unaligned.h>
+
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#define RTSX_USB_USE_LEDS_CLASS
+#endif
+
+struct rtsx_usb_sdmmc {
+ struct platform_device *pdev;
+ struct rtsx_ucr *ucr;
+ struct mmc_host *mmc;
+ struct mmc_request *mrq;
+
+ struct mutex host_mutex;
+
+ u8 ssc_depth;
+ unsigned int clock;
+ bool vpclk;
+ bool double_clk;
+ bool host_removal;
+ bool card_exist;
+ bool initial_mode;
+ bool ddr_mode;
+
+ unsigned char power_mode;
+
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
+ struct led_classdev led;
+ char led_name[32];
+ struct work_struct led_work;
+#endif
+};
+
+static inline struct device *sdmmc_dev(struct rtsx_usb_sdmmc *host)
+{
+ return &(host->pdev->dev);
+}
+
+static inline void sd_clear_error(struct rtsx_usb_sdmmc *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ rtsx_usb_ep0_write_register(ucr, CARD_STOP,
+ SD_STOP | SD_CLR_ERR,
+ SD_STOP | SD_CLR_ERR);
+
+ rtsx_usb_clear_dma_err(ucr);
+ rtsx_usb_clear_fsm_err(ucr);
+}
+
+#ifdef DEBUG
+static void sd_print_debug_regs(struct rtsx_usb_sdmmc *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ u8 val = 0;
+
+ rtsx_usb_ep0_read_register(ucr, SD_STAT1, &val);
+ dev_dbg(sdmmc_dev(host), "SD_STAT1: 0x%x\n", val);
+ rtsx_usb_ep0_read_register(ucr, SD_STAT2, &val);
+ dev_dbg(sdmmc_dev(host), "SD_STAT2: 0x%x\n", val);
+ rtsx_usb_ep0_read_register(ucr, SD_BUS_STAT, &val);
+ dev_dbg(sdmmc_dev(host), "SD_BUS_STAT: 0x%x\n", val);
+}
+#else
+#define sd_print_debug_regs(host)
+#endif /* DEBUG */
+
+static int sd_read_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd,
+ u16 byte_cnt, u8 *buf, int buf_len, int timeout)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ u8 trans_mode;
+
+ if (!buf)
+ buf_len = 0;
+
+ rtsx_usb_init_cmd(ucr);
+ if (cmd != NULL) {
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__
+ , cmd->opcode);
+ if (cmd->opcode == MMC_SEND_TUNING_BLOCK)
+ trans_mode = SD_TM_AUTO_TUNING;
+ else
+ trans_mode = SD_TM_NORMAL_READ;
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD1, 0xFF, (u8)(cmd->arg >> 24));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD2, 0xFF, (u8)(cmd->arg >> 16));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD3, 0xFF, (u8)(cmd->arg >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD4, 0xFF, (u8)cmd->arg);
+ } else {
+ trans_mode = SD_TM_AUTO_READ_3;
+ }
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+ 0xFF, (u8)(byte_cnt >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+ if (trans_mode != SD_TM_AUTO_TUNING)
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER,
+ 0xFF, trans_mode | SD_TRANSFER_START);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ if (cmd != NULL) {
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0);
+ }
+
+ err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout);
+ if (err) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_send_cmd failed (err = %d)\n", err);
+ return err;
+ }
+
+ err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout);
+ if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) {
+ sd_print_debug_regs(host);
+
+ if (!err) {
+ dev_dbg(sdmmc_dev(host),
+ "Transfer failed (SD_TRANSFER = %02x)\n",
+ ucr->rsp_buf[0]);
+ err = -EIO;
+ } else {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_get_rsp failed (err = %d)\n", err);
+ }
+
+ return err;
+ }
+
+ if (cmd != NULL) {
+ cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+ cmd->resp[0]);
+ }
+
+ if (buf && buf_len) {
+ /* 2-byte aligned part */
+ err = rtsx_usb_read_ppbuf(ucr, buf, byte_cnt - (byte_cnt % 2));
+ if (err) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_read_ppbuf failed (err = %d)\n", err);
+ return err;
+ }
+
+ /* unaligned byte */
+ if (byte_cnt % 2)
+ return rtsx_usb_read_register(ucr,
+ PPBUF_BASE2 + byte_cnt,
+ buf + byte_cnt - 1);
+ }
+
+ return 0;
+}
+
+static int sd_write_data(struct rtsx_usb_sdmmc *host, struct mmc_command *cmd,
+ u16 byte_cnt, u8 *buf, int buf_len, int timeout)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ u8 trans_mode;
+
+ if (!buf)
+ buf_len = 0;
+
+ if (buf && buf_len) {
+ err = rtsx_usb_write_ppbuf(ucr, buf, buf_len);
+ if (err) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_write_ppbuf failed (err = %d)\n",
+ err);
+ return err;
+ }
+ }
+
+ trans_mode = (cmd != NULL) ? SD_TM_AUTO_WRITE_2 : SD_TM_AUTO_WRITE_3;
+ rtsx_usb_init_cmd(ucr);
+
+ if (cmd != NULL) {
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD%d\n", __func__,
+ cmd->opcode);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD0, 0xFF, (u8)(cmd->opcode) | 0x40);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD1, 0xFF, (u8)(cmd->arg >> 24));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD2, 0xFF, (u8)(cmd->arg >> 16));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD3, 0xFF, (u8)(cmd->arg >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CMD4, 0xFF, (u8)cmd->arg);
+ }
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H,
+ 0xFF, (u8)(byte_cnt >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF,
+ SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_6);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+ trans_mode | SD_TRANSFER_START);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ if (cmd != NULL) {
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD1, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD2, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD3, 0, 0);
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_CMD4, 0, 0);
+ }
+
+ err = rtsx_usb_send_cmd(ucr, MODE_CR, timeout);
+ if (err) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_send_cmd failed (err = %d)\n", err);
+ return err;
+ }
+
+ err = rtsx_usb_get_rsp(ucr, !cmd ? 1 : 5, timeout);
+ if (err) {
+ sd_print_debug_regs(host);
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_get_rsp failed (err = %d)\n", err);
+ return err;
+ }
+
+ if (cmd != NULL) {
+ cmd->resp[0] = get_unaligned_be32(ucr->rsp_buf + 1);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+ cmd->resp[0]);
+ }
+
+ return 0;
+}
+
+static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host,
+ struct mmc_command *cmd)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ u8 cmd_idx = (u8)cmd->opcode;
+ u32 arg = cmd->arg;
+ int err = 0;
+ int timeout = 100;
+ int i;
+ u8 *ptr;
+ int stat_idx = 0;
+ int len = 2;
+ u8 rsp_type;
+
+ dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
+ __func__, cmd_idx, arg);
+
+ /* Response type:
+ * R0
+ * R1, R5, R6, R7
+ * R1b
+ * R2
+ * R3, R4
+ */
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE:
+ rsp_type = SD_RSP_TYPE_R0;
+ break;
+ case MMC_RSP_R1:
+ rsp_type = SD_RSP_TYPE_R1;
+ break;
+ case MMC_RSP_R1 & ~MMC_RSP_CRC:
+ rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7;
+ break;
+ case MMC_RSP_R1B:
+ rsp_type = SD_RSP_TYPE_R1b;
+ break;
+ case MMC_RSP_R2:
+ rsp_type = SD_RSP_TYPE_R2;
+ break;
+ case MMC_RSP_R3:
+ rsp_type = SD_RSP_TYPE_R3;
+ break;
+ default:
+ dev_dbg(sdmmc_dev(host), "cmd->flag is not valid\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R1b)
+ timeout = 3000;
+
+ if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+ err = rtsx_usb_write_register(ucr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
+ SD_CLK_TOGGLE_EN);
+ if (err)
+ goto out;
+ }
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD0, 0xFF, 0x40 | cmd_idx);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD1, 0xFF, (u8)(arg >> 24));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD2, 0xFF, (u8)(arg >> 16));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD3, 0xFF, (u8)(arg >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CMD4, 0xFF, (u8)arg);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, rsp_type);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, PINGPONG_BUFFER);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER,
+ 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END | SD_STAT_IDLE,
+ SD_TRANSFER_END | SD_STAT_IDLE);
+
+ if (rsp_type == SD_RSP_TYPE_R2) {
+ /* Read data from ping-pong buffer */
+ for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0);
+ stat_idx = 16;
+ } else if (rsp_type != SD_RSP_TYPE_R0) {
+ /* Read data from SD_CMDx registers */
+ for (i = SD_CMD0; i <= SD_CMD4; i++)
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, (u16)i, 0, 0);
+ stat_idx = 5;
+ }
+ len += stat_idx;
+
+ rtsx_usb_add_cmd(ucr, READ_REG_CMD, SD_STAT1, 0, 0);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+ if (err) {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_send_cmd error (err = %d)\n", err);
+ goto out;
+ }
+
+ err = rtsx_usb_get_rsp(ucr, len, timeout);
+ if (err || (ucr->rsp_buf[0] & SD_TRANSFER_ERR)) {
+ sd_print_debug_regs(host);
+ sd_clear_error(host);
+
+ if (!err) {
+ dev_dbg(sdmmc_dev(host),
+ "Transfer failed (SD_TRANSFER = %02x)\n",
+ ucr->rsp_buf[0]);
+ err = -EIO;
+ } else {
+ dev_dbg(sdmmc_dev(host),
+ "rtsx_usb_get_rsp failed (err = %d)\n", err);
+ }
+
+ goto out;
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R0) {
+ err = 0;
+ goto out;
+ }
+
+ /* Skip result of CHECK_REG_CMD */
+ ptr = ucr->rsp_buf + 1;
+
+ /* Check (Start,Transmission) bit of Response */
+ if ((ptr[0] & 0xC0) != 0) {
+ err = -EILSEQ;
+ dev_dbg(sdmmc_dev(host), "Invalid response bit\n");
+ goto out;
+ }
+
+ /* Check CRC7 */
+ if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+ if (ptr[stat_idx] & SD_CRC7_ERR) {
+ err = -EILSEQ;
+ dev_dbg(sdmmc_dev(host), "CRC7 error\n");
+ goto out;
+ }
+ }
+
+ if (rsp_type == SD_RSP_TYPE_R2) {
+ for (i = 0; i < 4; i++) {
+ cmd->resp[i] = get_unaligned_be32(ptr + 1 + i * 4);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[%d] = 0x%08x\n",
+ i, cmd->resp[i]);
+ }
+ } else {
+ cmd->resp[0] = get_unaligned_be32(ptr + 1);
+ dev_dbg(sdmmc_dev(host), "cmd->resp[0] = 0x%08x\n",
+ cmd->resp[0]);
+ }
+
+out:
+ cmd->error = err;
+}
+
+static int sd_rw_multi(struct rtsx_usb_sdmmc *host, struct mmc_request *mrq)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ struct mmc_data *data = mrq->data;
+ int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
+ u8 cfg2, trans_mode;
+ int err;
+ u8 flag;
+ size_t data_len = data->blksz * data->blocks;
+ unsigned int pipe;
+
+ if (read) {
+ dev_dbg(sdmmc_dev(host), "%s: read %zu bytes\n",
+ __func__, data_len);
+ cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
+ trans_mode = SD_TM_AUTO_READ_3;
+ } else {
+ dev_dbg(sdmmc_dev(host), "%s: write %zu bytes\n",
+ __func__, data_len);
+ cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
+ SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+ trans_mode = SD_TM_AUTO_WRITE_3;
+ }
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_L,
+ 0xFF, (u8)data->blocks);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BLOCK_CNT_H,
+ 0xFF, (u8)(data->blocks >> 8));
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DATA_SOURCE,
+ 0x01, RING_BUFFER);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC3,
+ 0xFF, (u8)(data_len >> 24));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC2,
+ 0xFF, (u8)(data_len >> 16));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC1,
+ 0xFF, (u8)(data_len >> 8));
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_TC0,
+ 0xFF, (u8)data_len);
+ if (read) {
+ flag = MODE_CDIR;
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL,
+ 0x03 | DMA_PACK_SIZE_MASK,
+ DMA_DIR_FROM_CARD | DMA_EN | DMA_512);
+ } else {
+ flag = MODE_CDOR;
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, MC_DMA_CTL,
+ 0x03 | DMA_PACK_SIZE_MASK,
+ DMA_DIR_TO_CARD | DMA_EN | DMA_512);
+ }
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG2, 0xFF, cfg2);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+ trans_mode | SD_TRANSFER_START);
+ rtsx_usb_add_cmd(ucr, CHECK_REG_CMD, SD_TRANSFER,
+ SD_TRANSFER_END, SD_TRANSFER_END);
+
+ err = rtsx_usb_send_cmd(ucr, flag, 100);
+ if (err)
+ return err;
+
+ if (read)
+ pipe = usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN);
+ else
+ pipe = usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT);
+
+ err = rtsx_usb_transfer_data(ucr, pipe, data->sg, data_len,
+ data->sg_len, NULL, 10000);
+ if (err) {
+ dev_dbg(sdmmc_dev(host), "rtsx_usb_transfer_data error %d\n"
+ , err);
+ sd_clear_error(host);
+ return err;
+ }
+
+ return rtsx_usb_get_rsp(ucr, 1, 2000);
+}
+
+static inline void sd_enable_initial_mode(struct rtsx_usb_sdmmc *host)
+{
+ rtsx_usb_write_register(host->ucr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct rtsx_usb_sdmmc *host)
+{
+ rtsx_usb_write_register(host->ucr, SD_CFG1,
+ SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
+static void sd_normal_rw(struct rtsx_usb_sdmmc *host,
+ struct mmc_request *mrq)
+{
+ struct mmc_command *cmd = mrq->cmd;
+ struct mmc_data *data = mrq->data;
+ u8 *buf;
+
+ buf = kzalloc(data->blksz, GFP_NOIO);
+ if (!buf) {
+ cmd->error = -ENOMEM;
+ return;
+ }
+
+ if (data->flags & MMC_DATA_READ) {
+ if (host->initial_mode)
+ sd_disable_initial_mode(host);
+
+ cmd->error = sd_read_data(host, cmd, (u16)data->blksz, buf,
+ data->blksz, 200);
+
+ if (host->initial_mode)
+ sd_enable_initial_mode(host);
+
+ sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz);
+ } else {
+ sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz);
+
+ cmd->error = sd_write_data(host, cmd, (u16)data->blksz, buf,
+ data->blksz, 200);
+ }
+
+ kfree(buf);
+}
+
+static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n",
+ __func__, tx ? "TX" : "RX", sample_point);
+
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
+
+ if (tx)
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ 0x0F, sample_point);
+ else
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK1_CTL,
+ 0x0F, sample_point);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+ PHASE_NOT_RESET, PHASE_NOT_RESET);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static inline u32 get_phase_point(u32 phase_map, unsigned int idx)
+{
+ idx &= MAX_PHASE;
+ return phase_map & (1 << idx);
+}
+
+static int get_phase_len(u32 phase_map, unsigned int idx)
+{
+ int i;
+
+ for (i = 0; i < MAX_PHASE + 1; i++) {
+ if (get_phase_point(phase_map, idx + i) == 0)
+ return i;
+ }
+ return MAX_PHASE + 1;
+}
+
+static u8 sd_search_final_phase(struct rtsx_usb_sdmmc *host, u32 phase_map)
+{
+ int start = 0, len = 0;
+ int start_final = 0, len_final = 0;
+ u8 final_phase = 0xFF;
+
+ if (phase_map == 0) {
+ dev_dbg(sdmmc_dev(host), "Phase: [map:%x]\n", phase_map);
+ return final_phase;
+ }
+
+ while (start < MAX_PHASE + 1) {
+ len = get_phase_len(phase_map, start);
+ if (len_final < len) {
+ start_final = start;
+ len_final = len;
+ }
+ start += len ? len : 1;
+ }
+
+ final_phase = (start_final + len_final / 2) & MAX_PHASE;
+ dev_dbg(sdmmc_dev(host), "Phase: [map:%x] [maxlen:%d] [final:%d]\n",
+ phase_map, len_final, final_phase);
+
+ return final_phase;
+}
+
+static void sd_wait_data_idle(struct rtsx_usb_sdmmc *host)
+{
+ int err, i;
+ u8 val = 0;
+
+ for (i = 0; i < 100; i++) {
+ err = rtsx_usb_ep0_read_register(host->ucr,
+ SD_DATA_STATE, &val);
+ if (val & SD_DATA_IDLE)
+ return;
+
+ usleep_range(100, 1000);
+ }
+}
+
+static int sd_tuning_rx_cmd(struct rtsx_usb_sdmmc *host,
+ u8 opcode, u8 sample_point)
+{
+ int err;
+ struct mmc_command cmd = {0};
+
+ err = sd_change_phase(host, sample_point, 0);
+ if (err)
+ return err;
+
+ cmd.opcode = MMC_SEND_TUNING_BLOCK;
+ err = sd_read_data(host, &cmd, 0x40, NULL, 0, 100);
+ if (err) {
+ /* Wait till SD DATA IDLE */
+ sd_wait_data_idle(host);
+ sd_clear_error(host);
+ return err;
+ }
+
+ return 0;
+}
+
+static void sd_tuning_phase(struct rtsx_usb_sdmmc *host,
+ u8 opcode, u16 *phase_map)
+{
+ int err, i;
+ u16 raw_phase_map = 0;
+
+ for (i = MAX_PHASE; i >= 0; i--) {
+ err = sd_tuning_rx_cmd(host, opcode, (u8)i);
+ if (!err)
+ raw_phase_map |= 1 << i;
+ }
+
+ if (phase_map)
+ *phase_map = raw_phase_map;
+}
+
+static int sd_tuning_rx(struct rtsx_usb_sdmmc *host, u8 opcode)
+{
+ int err, i;
+ u16 raw_phase_map[RX_TUNING_CNT] = {0}, phase_map;
+ u8 final_phase;
+
+ /* setting fixed default TX phase */
+ err = sd_change_phase(host, 0x01, 1);
+ if (err) {
+ dev_dbg(sdmmc_dev(host), "TX phase setting failed\n");
+ return err;
+ }
+
+ /* tuning RX phase */
+ for (i = 0; i < RX_TUNING_CNT; i++) {
+ sd_tuning_phase(host, opcode, &(raw_phase_map[i]));
+
+ if (raw_phase_map[i] == 0)
+ break;
+ }
+
+ phase_map = 0xFFFF;
+ for (i = 0; i < RX_TUNING_CNT; i++) {
+ dev_dbg(sdmmc_dev(host), "RX raw_phase_map[%d] = 0x%04x\n",
+ i, raw_phase_map[i]);
+ phase_map &= raw_phase_map[i];
+ }
+ dev_dbg(sdmmc_dev(host), "RX phase_map = 0x%04x\n", phase_map);
+
+ if (phase_map) {
+ final_phase = sd_search_final_phase(host, phase_map);
+ if (final_phase == 0xFF)
+ return -EINVAL;
+
+ err = sd_change_phase(host, final_phase, 0);
+ if (err)
+ return err;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sdmmc_get_ro(struct mmc_host *mmc)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ u16 val;
+
+ if (host->host_removal)
+ return -ENOMEDIUM;
+
+ mutex_lock(&ucr->dev_mutex);
+
+ /* Check SD card detect */
+ err = rtsx_usb_get_card_status(ucr, &val);
+
+ mutex_unlock(&ucr->dev_mutex);
+
+
+ /* Treat failed detection as non-ro */
+ if (err)
+ return 0;
+
+ if (val & SD_WP)
+ return 1;
+
+ return 0;
+}
+
+static int sdmmc_get_cd(struct mmc_host *mmc)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ u16 val;
+
+ if (host->host_removal)
+ return -ENOMEDIUM;
+
+ mutex_lock(&ucr->dev_mutex);
+
+ /* Check SD card detect */
+ err = rtsx_usb_get_card_status(ucr, &val);
+
+ mutex_unlock(&ucr->dev_mutex);
+
+ /* Treat failed detection as non-exist */
+ if (err)
+ goto no_card;
+
+ if (val & SD_CD) {
+ host->card_exist = true;
+ return 1;
+ }
+
+no_card:
+ host->card_exist = false;
+ return 0;
+}
+
+static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ struct mmc_command *cmd = mrq->cmd;
+ struct mmc_data *data = mrq->data;
+ unsigned int data_size = 0;
+
+ dev_dbg(sdmmc_dev(host), "%s\n", __func__);
+
+ if (host->host_removal) {
+ cmd->error = -ENOMEDIUM;
+ goto finish;
+ }
+
+ if ((!host->card_exist)) {
+ cmd->error = -ENOMEDIUM;
+ goto finish_detect_card;
+ }
+
+ /*
+ * Reject SDIO CMDs to speed up card identification
+ * since unsupported
+ */
+ if (cmd->opcode == SD_IO_SEND_OP_COND ||
+ cmd->opcode == SD_IO_RW_DIRECT ||
+ cmd->opcode == SD_IO_RW_EXTENDED) {
+ cmd->error = -EINVAL;
+ goto finish;
+ }
+
+ mutex_lock(&ucr->dev_mutex);
+
+ mutex_lock(&host->host_mutex);
+ host->mrq = mrq;
+ mutex_unlock(&host->host_mutex);
+
+ if (mrq->data)
+ data_size = data->blocks * data->blksz;
+
+ if (!data_size) {
+ sd_send_cmd_get_rsp(host, cmd);
+ } else if ((!(data_size % 512) && cmd->opcode != MMC_SEND_EXT_CSD) ||
+ mmc_op_multi(cmd->opcode)) {
+ sd_send_cmd_get_rsp(host, cmd);
+
+ if (!cmd->error) {
+ sd_rw_multi(host, mrq);
+
+ if (mmc_op_multi(cmd->opcode) && mrq->stop) {
+ sd_send_cmd_get_rsp(host, mrq->stop);
+ rtsx_usb_write_register(ucr, MC_FIFO_CTL,
+ FIFO_FLUSH, FIFO_FLUSH);
+ }
+ }
+ } else {
+ sd_normal_rw(host, mrq);
+ }
+
+ if (mrq->data) {
+ if (cmd->error || data->error)
+ data->bytes_xfered = 0;
+ else
+ data->bytes_xfered = data->blocks * data->blksz;
+ }
+
+ mutex_unlock(&ucr->dev_mutex);
+
+finish_detect_card:
+ if (cmd->error) {
+ /*
+ * detect card when fail to update card existence state and
+ * speed up card removal when retry
+ */
+ sdmmc_get_cd(mmc);
+ dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
+ }
+
+finish:
+ mutex_lock(&host->host_mutex);
+ host->mrq = NULL;
+ mutex_unlock(&host->host_mutex);
+
+ mmc_request_done(mmc, mrq);
+}
+
+static int sd_set_bus_width(struct rtsx_usb_sdmmc *host,
+ unsigned char bus_width)
+{
+ int err = 0;
+ u8 width[] = {
+ [MMC_BUS_WIDTH_1] = SD_BUS_WIDTH_1BIT,
+ [MMC_BUS_WIDTH_4] = SD_BUS_WIDTH_4BIT,
+ [MMC_BUS_WIDTH_8] = SD_BUS_WIDTH_8BIT,
+ };
+
+ if (bus_width <= MMC_BUS_WIDTH_8)
+ err = rtsx_usb_write_register(host->ucr, SD_CFG1,
+ 0x03, width[bus_width]);
+
+ return err;
+}
+
+static int sd_pull_ctl_disable_lqfp48(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int sd_pull_ctl_disable_qfn24(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x65);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x56);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x59);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int sd_pull_ctl_enable_lqfp48(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA9);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0xA5);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int sd_pull_ctl_enable_qfn24(struct rtsx_ucr *ucr)
+{
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA5);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x9A);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xA5);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x9A);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x65);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x5A);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int sd_power_on(struct rtsx_usb_sdmmc *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ dev_dbg(sdmmc_dev(host), "%s\n", __func__);
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_SHARE_MODE,
+ CARD_SHARE_MASK, CARD_SHARE_SD);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN,
+ SD_CLK_EN, SD_CLK_EN);
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (err)
+ return err;
+
+ if (CHECK_PKG(ucr, LQFP48))
+ err = sd_pull_ctl_enable_lqfp48(ucr);
+ else
+ err = sd_pull_ctl_enable_qfn24(ucr);
+ if (err)
+ return err;
+
+ err = rtsx_usb_write_register(ucr, CARD_PWR_CTL,
+ POWER_MASK, PARTIAL_POWER_ON);
+ if (err)
+ return err;
+
+ usleep_range(800, 1000);
+
+ rtsx_usb_init_cmd(ucr);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ POWER_MASK|LDO3318_PWR_MASK, POWER_ON|LDO_ON);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE,
+ SD_OUTPUT_EN, SD_OUTPUT_EN);
+
+ return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+static int sd_power_off(struct rtsx_usb_sdmmc *host)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ dev_dbg(sdmmc_dev(host), "%s\n", __func__);
+ rtsx_usb_init_cmd(ucr);
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_OE, SD_OUTPUT_EN, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ POWER_MASK, POWER_OFF);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+ POWER_MASK|LDO3318_PWR_MASK, POWER_OFF|LDO_SUSPEND);
+
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ if (err)
+ return err;
+
+ if (CHECK_PKG(ucr, LQFP48))
+ return sd_pull_ctl_disable_lqfp48(ucr);
+ return sd_pull_ctl_disable_qfn24(ucr);
+}
+
+static int sd_set_power_mode(struct rtsx_usb_sdmmc *host,
+ unsigned char power_mode)
+{
+ int err;
+
+ if (power_mode != MMC_POWER_OFF)
+ power_mode = MMC_POWER_ON;
+
+ if (power_mode == host->power_mode)
+ return 0;
+
+ if (power_mode == MMC_POWER_OFF) {
+ err = sd_power_off(host);
+ pm_runtime_put(sdmmc_dev(host));
+ } else {
+ pm_runtime_get_sync(sdmmc_dev(host));
+ err = sd_power_on(host);
+ }
+
+ if (!err)
+ host->power_mode = power_mode;
+
+ return err;
+}
+
+static int sd_set_timing(struct rtsx_usb_sdmmc *host,
+ unsigned char timing, bool *ddr_mode)
+{
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+
+ *ddr_mode = false;
+
+ rtsx_usb_init_cmd(ucr);
+
+ switch (timing) {
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_UHS_SDR50:
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C | SD_ASYNC_FIFO_RST,
+ SD_30_MODE | SD_ASYNC_FIFO_RST);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+ break;
+
+ case MMC_TIMING_UHS_DDR50:
+ *ddr_mode = true;
+
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C | SD_ASYNC_FIFO_RST,
+ SD_DDR_MODE | SD_ASYNC_FIFO_RST);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+ DDR_VAR_TX_CMD_DAT, DDR_VAR_TX_CMD_DAT);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
+ DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
+ break;
+
+ case MMC_TIMING_MMC_HS:
+ case MMC_TIMING_SD_HS:
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1,
+ 0x0C, SD_20_MODE);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PUSH_POINT_CTL,
+ SD20_TX_SEL_MASK, SD20_TX_14_AHEAD);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ SD20_RX_SEL_MASK, SD20_RX_14_DELAY);
+ break;
+
+ default:
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_CFG1, 0x0C, SD_20_MODE);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_CLK_SOURCE, 0xFF,
+ CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+ SD_PUSH_POINT_CTL, 0xFF, 0);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_SAMPLE_POINT_CTL,
+ SD20_RX_SEL_MASK, SD20_RX_POS_EDGE);
+ break;
+ }
+
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+
+ return err;
+}
+
+static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+
+ dev_dbg(sdmmc_dev(host), "%s\n", __func__);
+ mutex_lock(&ucr->dev_mutex);
+
+ if (rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD)) {
+ mutex_unlock(&ucr->dev_mutex);
+ return;
+ }
+
+ sd_set_power_mode(host, ios->power_mode);
+ sd_set_bus_width(host, ios->bus_width);
+ sd_set_timing(host, ios->timing, &host->ddr_mode);
+
+ host->vpclk = false;
+ host->double_clk = true;
+
+ switch (ios->timing) {
+ case MMC_TIMING_UHS_SDR104:
+ case MMC_TIMING_UHS_SDR50:
+ host->ssc_depth = SSC_DEPTH_2M;
+ host->vpclk = true;
+ host->double_clk = false;
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_UHS_SDR25:
+ host->ssc_depth = SSC_DEPTH_1M;
+ break;
+ default:
+ host->ssc_depth = SSC_DEPTH_512K;
+ break;
+ }
+
+ host->initial_mode = (ios->clock <= 1000000) ? true : false;
+ host->clock = ios->clock;
+
+ rtsx_usb_switch_clock(host->ucr, host->clock, host->ssc_depth,
+ host->initial_mode, host->double_clk, host->vpclk);
+
+ mutex_unlock(&ucr->dev_mutex);
+ dev_dbg(sdmmc_dev(host), "%s end\n", __func__);
+}
+
+static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ int err = 0;
+
+ dev_dbg(sdmmc_dev(host), "%s: signal_voltage = %d\n",
+ __func__, ios->signal_voltage);
+
+ if (host->host_removal)
+ return -ENOMEDIUM;
+
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120)
+ return -EPERM;
+
+ mutex_lock(&ucr->dev_mutex);
+
+ err = rtsx_usb_card_exclusive_check(ucr, RTSX_USB_SD_CARD);
+ if (err) {
+ mutex_unlock(&ucr->dev_mutex);
+ return err;
+ }
+
+ /* Let mmc core do the busy checking, simply stop the forced-toggle
+ * clock(while issuing CMD11) and switch voltage.
+ */
+ rtsx_usb_init_cmd(ucr);
+
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL,
+ SD_IO_USING_1V8, SD_IO_USING_3V3);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG,
+ TUNE_SD18_MASK, TUNE_SD18_3V3);
+ } else {
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
+ SD_CLK_FORCE_STOP);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_PAD_CTL,
+ SD_IO_USING_1V8, SD_IO_USING_1V8);
+ rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG,
+ TUNE_SD18_MASK, TUNE_SD18_1V8);
+ }
+
+ err = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+ mutex_unlock(&ucr->dev_mutex);
+
+ return err;
+}
+
+static int sdmmc_card_busy(struct mmc_host *mmc)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ int err;
+ u8 stat;
+ u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS
+ | SD_DAT0_STATUS;
+
+ dev_dbg(sdmmc_dev(host), "%s\n", __func__);
+
+ mutex_lock(&ucr->dev_mutex);
+
+ err = rtsx_usb_write_register(ucr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
+ SD_CLK_TOGGLE_EN);
+ if (err)
+ goto out;
+
+ mdelay(1);
+
+ err = rtsx_usb_read_register(ucr, SD_BUS_STAT, &stat);
+ if (err)
+ goto out;
+
+ err = rtsx_usb_write_register(ucr, SD_BUS_STAT,
+ SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+out:
+ mutex_unlock(&ucr->dev_mutex);
+
+ if (err)
+ return err;
+
+ /* check if any pin between dat[0:3] is low */
+ if ((stat & mask) != mask)
+ return 1;
+ else
+ return 0;
+}
+
+static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct rtsx_usb_sdmmc *host = mmc_priv(mmc);
+ struct rtsx_ucr *ucr = host->ucr;
+ int err = 0;
+
+ if (host->host_removal)
+ return -ENOMEDIUM;
+
+ mutex_lock(&ucr->dev_mutex);
+
+ if (!host->ddr_mode)
+ err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK);
+
+ mutex_unlock(&ucr->dev_mutex);
+
+ return err;
+}
+
+static const struct mmc_host_ops rtsx_usb_sdmmc_ops = {
+ .request = sdmmc_request,
+ .set_ios = sdmmc_set_ios,
+ .get_ro = sdmmc_get_ro,
+ .get_cd = sdmmc_get_cd,
+ .start_signal_voltage_switch = sdmmc_switch_voltage,
+ .card_busy = sdmmc_card_busy,
+ .execute_tuning = sdmmc_execute_tuning,
+};
+
+#ifdef RTSX_USB_USE_LEDS_CLASS
+static void rtsx_usb_led_control(struct led_classdev *led,
+ enum led_brightness brightness)
+{
+ struct rtsx_usb_sdmmc *host = container_of(led,
+ struct rtsx_usb_sdmmc, led);
+
+ if (host->host_removal)
+ return;
+
+ host->led.brightness = brightness;
+ schedule_work(&host->led_work);
+}
+
+static void rtsx_usb_update_led(struct work_struct *work)
+{
+ struct rtsx_usb_sdmmc *host =
+ container_of(work, struct rtsx_usb_sdmmc, led_work);
+ struct rtsx_ucr *ucr = host->ucr;
+
+ mutex_lock(&ucr->dev_mutex);
+
+ if (host->led.brightness == LED_OFF)
+ rtsx_usb_turn_off_led(ucr);
+ else
+ rtsx_usb_turn_on_led(ucr);
+
+ mutex_unlock(&ucr->dev_mutex);
+}
+#endif
+
+static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ mmc->f_min = 250000;
+ mmc->f_max = 208000000;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED |
+ MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST |
+ MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
+ MMC_CAP_NEEDS_POLL;
+
+ mmc->max_current_330 = 400;
+ mmc->max_current_180 = 800;
+ mmc->ops = &rtsx_usb_sdmmc_ops;
+ mmc->max_segs = 256;
+ mmc->max_seg_size = 65536;
+ mmc->max_blk_size = 512;
+ mmc->max_blk_count = 65535;
+ mmc->max_req_size = 524288;
+
+ host->power_mode = MMC_POWER_OFF;
+}
+
+static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct rtsx_usb_sdmmc *host;
+ struct rtsx_ucr *ucr;
+#ifdef RTSX_USB_USE_LEDS_CLASS
+ int err;
+#endif
+
+ ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent));
+ if (!ucr)
+ return -ENXIO;
+
+ dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC controller found\n");
+
+ mmc = mmc_alloc_host(sizeof(*host), &pdev->dev);
+ if (!mmc)
+ return -ENOMEM;
+
+ host = mmc_priv(mmc);
+ host->ucr = ucr;
+ host->mmc = mmc;
+ host->pdev = pdev;
+ platform_set_drvdata(pdev, host);
+
+ mutex_init(&host->host_mutex);
+ rtsx_usb_init_host(host);
+ pm_runtime_enable(&pdev->dev);
+
+#ifdef RTSX_USB_USE_LEDS_CLASS
+ snprintf(host->led_name, sizeof(host->led_name),
+ "%s::", mmc_hostname(mmc));
+ host->led.name = host->led_name;
+ host->led.brightness = LED_OFF;
+ host->led.default_trigger = mmc_hostname(mmc);
+ host->led.brightness_set = rtsx_usb_led_control;
+
+ err = led_classdev_register(mmc_dev(mmc), &host->led);
+ if (err)
+ dev_err(&(pdev->dev),
+ "Failed to register LED device: %d\n", err);
+ INIT_WORK(&host->led_work, rtsx_usb_update_led);
+
+#endif
+ mmc_add_host(mmc);
+
+ return 0;
+}
+
+static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev)
+{
+ struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev);
+ struct mmc_host *mmc;
+
+ if (!host)
+ return 0;
+
+ mmc = host->mmc;
+ host->host_removal = true;
+
+ mutex_lock(&host->host_mutex);
+ if (host->mrq) {
+ dev_dbg(&(pdev->dev),
+ "%s: Controller removed during transfer\n",
+ mmc_hostname(mmc));
+ host->mrq->cmd->error = -ENOMEDIUM;
+ if (host->mrq->stop)
+ host->mrq->stop->error = -ENOMEDIUM;
+ mmc_request_done(mmc, host->mrq);
+ }
+ mutex_unlock(&host->host_mutex);
+
+ mmc_remove_host(mmc);
+
+#ifdef RTSX_USB_USE_LEDS_CLASS
+ cancel_work_sync(&host->led_work);
+ led_classdev_unregister(&host->led);
+#endif
+
+ mmc_free_host(mmc);
+ pm_runtime_disable(&pdev->dev);
+ platform_set_drvdata(pdev, NULL);
+
+ dev_dbg(&(pdev->dev),
+ ": Realtek USB SD/MMC module has been removed\n");
+
+ return 0;
+}
+
+static struct platform_device_id rtsx_usb_sdmmc_ids[] = {
+ {
+ .name = "rtsx_usb_sdmmc",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids);
+
+static struct platform_driver rtsx_usb_sdmmc_driver = {
+ .probe = rtsx_usb_sdmmc_drv_probe,
+ .remove = rtsx_usb_sdmmc_drv_remove,
+ .id_table = rtsx_usb_sdmmc_ids,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rtsx_usb_sdmmc",
+ },
+};
+module_platform_driver(rtsx_usb_sdmmc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
+MODULE_DESCRIPTION("Realtek USB SD/MMC Card Host Driver");
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index 476af93543f6..8ec2d6a1dbe1 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -40,6 +40,7 @@
struct s5m_rtc_info {
struct device *dev;
+ struct i2c_client *i2c;
struct sec_pmic_dev *s5m87xx;
struct regmap *regmap;
struct rtc_device *rtc_dev;
@@ -49,6 +50,20 @@ struct s5m_rtc_info {
bool wtsr_smpl;
};
+static const struct regmap_config s5m_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = SEC_RTC_REG_MAX,
+};
+
+static const struct regmap_config s2mps14_rtc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = S2MPS_RTC_REG_MAX,
+};
+
static void s5m8767_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
@@ -554,6 +569,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = s5m87xx->pdata;
struct s5m_rtc_info *info;
+ const struct regmap_config *regmap_cfg;
int ret;
if (!pdata) {
@@ -565,9 +581,37 @@ static int s5m_rtc_probe(struct platform_device *pdev)
if (!info)
return -ENOMEM;
+ switch (pdata->device_type) {
+ case S2MPS14X:
+ regmap_cfg = &s2mps14_rtc_regmap_config;
+ break;
+ case S5M8763X:
+ regmap_cfg = &s5m_rtc_regmap_config;
+ break;
+ case S5M8767X:
+ regmap_cfg = &s5m_rtc_regmap_config;
+ break;
+ default:
+ dev_err(&pdev->dev, "Device type is not supported by RTC driver\n");
+ return -ENODEV;
+ }
+
+ info->i2c = i2c_new_dummy(s5m87xx->i2c->adapter, RTC_I2C_ADDR);
+ if (!info->i2c) {
+ dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
+ return -ENODEV;
+ }
+
+ info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg);
+ if (IS_ERR(info->regmap)) {
+ ret = PTR_ERR(info->regmap);
+ dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
+ ret);
+ goto err;
+ }
+
info->dev = &pdev->dev;
info->s5m87xx = s5m87xx;
- info->regmap = s5m87xx->regmap_rtc;
info->device_type = s5m87xx->device_type;
info->wtsr_smpl = s5m87xx->wtsr_smpl;
@@ -585,7 +629,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
default:
ret = -EINVAL;
dev_err(&pdev->dev, "Unsupported device type: %d\n", ret);
- return ret;
+ goto err;
}
platform_set_drvdata(pdev, info);
@@ -602,15 +646,24 @@ static int s5m_rtc_probe(struct platform_device *pdev)
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "s5m-rtc",
&s5m_rtc_ops, THIS_MODULE);
- if (IS_ERR(info->rtc_dev))
- return PTR_ERR(info->rtc_dev);
+ if (IS_ERR(info->rtc_dev)) {
+ ret = PTR_ERR(info->rtc_dev);
+ goto err;
+ }
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
s5m_rtc_alarm_irq, 0, "rtc-alarm0",
info);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ i2c_unregister_device(info->i2c);
return ret;
}
@@ -639,6 +692,17 @@ static void s5m_rtc_shutdown(struct platform_device *pdev)
s5m_rtc_enable_smpl(info, false);
}
+static int s5m_rtc_remove(struct platform_device *pdev)
+{
+ struct s5m_rtc_info *info = platform_get_drvdata(pdev);
+
+ /* Perform also all shutdown steps when removing */
+ s5m_rtc_shutdown(pdev);
+ i2c_unregister_device(info->i2c);
+
+ return 0;
+}
+
#ifdef CONFIG_PM_SLEEP
static int s5m_rtc_resume(struct device *dev)
{
@@ -676,6 +740,7 @@ static struct platform_driver s5m_rtc_driver = {
.pm = &s5m_rtc_pm_ops,
},
.probe = s5m_rtc_probe,
+ .remove = s5m_rtc_remove,
.shutdown = s5m_rtc_shutdown,
.id_table = s5m_rtc_id,
};
diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
index f7d90617c9d9..60228fae943f 100644
--- a/drivers/sh/intc/Kconfig
+++ b/drivers/sh/intc/Kconfig
@@ -6,7 +6,7 @@ comment "Interrupt controller options"
config INTC_USERIMASK
bool "Userspace interrupt masking support"
- depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) || COMPILE_TEST
+ depends on (SUPERH && CPU_SH4A) || COMPILE_TEST
help
This enables support for hardware-assisted userspace hardirq
masking.
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
index 10c65eb51f85..72f63817a1a0 100644
--- a/drivers/sh/pm_runtime.c
+++ b/drivers/sh/pm_runtime.c
@@ -21,18 +21,43 @@
#include <linux/slab.h>
#ifdef CONFIG_PM_RUNTIME
-
-static int default_platform_runtime_idle(struct device *dev)
+static int sh_pm_runtime_suspend(struct device *dev)
{
- /* suspend synchronously to disable clocks immediately */
+ int ret;
+
+ ret = pm_generic_runtime_suspend(dev);
+ if (ret) {
+ dev_err(dev, "failed to suspend device\n");
+ return ret;
+ }
+
+ ret = pm_clk_suspend(dev);
+ if (ret) {
+ dev_err(dev, "failed to suspend clock\n");
+ pm_generic_runtime_resume(dev);
+ return ret;
+ }
+
return 0;
}
+static int sh_pm_runtime_resume(struct device *dev)
+{
+ int ret;
+
+ ret = pm_clk_resume(dev);
+ if (ret) {
+ dev_err(dev, "failed to resume clock\n");
+ return ret;
+ }
+
+ return pm_generic_runtime_resume(dev);
+}
+
static struct dev_pm_domain default_pm_domain = {
.ops = {
- .runtime_suspend = pm_clk_suspend,
- .runtime_resume = pm_clk_resume,
- .runtime_idle = default_platform_runtime_idle,
+ .runtime_suspend = sh_pm_runtime_suspend,
+ .runtime_resume = sh_pm_runtime_resume,
USE_PLATFORM_PM_SLEEP_OPS
},
};
@@ -63,6 +88,9 @@ static int __init sh_pm_runtime_init(void)
!of_machine_is_compatible("renesas,r8a7779") &&
!of_machine_is_compatible("renesas,r8a7790") &&
!of_machine_is_compatible("renesas,r8a7791") &&
+ !of_machine_is_compatible("renesas,r8a7792") &&
+ !of_machine_is_compatible("renesas,r8a7793") &&
+ !of_machine_is_compatible("renesas,r8a7794") &&
!of_machine_is_compatible("renesas,sh7372") &&
!of_machine_is_compatible("renesas,sh73a0"))
return 0;
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 3301b2031c8d..552cc1d61cc7 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -330,7 +330,6 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
int abx500_get_chip_id(struct device *dev);
int abx500_event_registers_startup_state_get(struct device *dev, u8 *event);
int abx500_startup_irq_enabled(struct device *dev, unsigned int irq);
-void abx500_dump_all_banks(void);
struct abx500_ops {
int (*get_chip_id) (struct device *);
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 7b35c21170d5..7204d8138b24 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -42,12 +42,14 @@
#define ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2 0x62
#define ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3 0x63
#define ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4 0x64
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1 0x68
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2 0x69
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3 0x6A
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4 0x6B
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_5 0x6C
-#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_6 0x6D
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1 0x66
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2 0x67
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_3 0x68
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_4 0x69
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_5 0x6A
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_6 0x6B
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_7 0x6C
+#define ARIZONA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_8 0x6D
#define ARIZONA_COMFORT_NOISE_GENERATOR 0x70
#define ARIZONA_HAPTICS_CONTROL_1 0x90
#define ARIZONA_HAPTICS_CONTROL_2 0x91
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
new file mode 100644
index 000000000000..d0e31a2287ac
--- /dev/null
+++ b/include/linux/mfd/axp20x.h
@@ -0,0 +1,180 @@
+/*
+ * Functions and registers to access AXP20X power management chip.
+ *
+ * Copyright (C) 2013, Carlo Caione <carlo@caione.org>
+ *
+ * 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 __LINUX_MFD_AXP20X_H
+#define __LINUX_MFD_AXP20X_H
+
+enum {
+ AXP202_ID = 0,
+ AXP209_ID,
+};
+
+#define AXP20X_DATACACHE(m) (0x04 + (m))
+
+/* Power supply */
+#define AXP20X_PWR_INPUT_STATUS 0x00
+#define AXP20X_PWR_OP_MODE 0x01
+#define AXP20X_USB_OTG_STATUS 0x02
+#define AXP20X_PWR_OUT_CTRL 0x12
+#define AXP20X_DCDC2_V_OUT 0x23
+#define AXP20X_DCDC2_LDO3_V_SCAL 0x25
+#define AXP20X_DCDC3_V_OUT 0x27
+#define AXP20X_LDO24_V_OUT 0x28
+#define AXP20X_LDO3_V_OUT 0x29
+#define AXP20X_VBUS_IPSOUT_MGMT 0x30
+#define AXP20X_V_OFF 0x31
+#define AXP20X_OFF_CTRL 0x32
+#define AXP20X_CHRG_CTRL1 0x33
+#define AXP20X_CHRG_CTRL2 0x34
+#define AXP20X_CHRG_BAK_CTRL 0x35
+#define AXP20X_PEK_KEY 0x36
+#define AXP20X_DCDC_FREQ 0x37
+#define AXP20X_V_LTF_CHRG 0x38
+#define AXP20X_V_HTF_CHRG 0x39
+#define AXP20X_APS_WARN_L1 0x3a
+#define AXP20X_APS_WARN_L2 0x3b
+#define AXP20X_V_LTF_DISCHRG 0x3c
+#define AXP20X_V_HTF_DISCHRG 0x3d
+
+/* Interrupt */
+#define AXP20X_IRQ1_EN 0x40
+#define AXP20X_IRQ2_EN 0x41
+#define AXP20X_IRQ3_EN 0x42
+#define AXP20X_IRQ4_EN 0x43
+#define AXP20X_IRQ5_EN 0x44
+#define AXP20X_IRQ1_STATE 0x48
+#define AXP20X_IRQ2_STATE 0x49
+#define AXP20X_IRQ3_STATE 0x4a
+#define AXP20X_IRQ4_STATE 0x4b
+#define AXP20X_IRQ5_STATE 0x4c
+
+/* ADC */
+#define AXP20X_ACIN_V_ADC_H 0x56
+#define AXP20X_ACIN_V_ADC_L 0x57
+#define AXP20X_ACIN_I_ADC_H 0x58
+#define AXP20X_ACIN_I_ADC_L 0x59
+#define AXP20X_VBUS_V_ADC_H 0x5a
+#define AXP20X_VBUS_V_ADC_L 0x5b
+#define AXP20X_VBUS_I_ADC_H 0x5c
+#define AXP20X_VBUS_I_ADC_L 0x5d
+#define AXP20X_TEMP_ADC_H 0x5e
+#define AXP20X_TEMP_ADC_L 0x5f
+#define AXP20X_TS_IN_H 0x62
+#define AXP20X_TS_IN_L 0x63
+#define AXP20X_GPIO0_V_ADC_H 0x64
+#define AXP20X_GPIO0_V_ADC_L 0x65
+#define AXP20X_GPIO1_V_ADC_H 0x66
+#define AXP20X_GPIO1_V_ADC_L 0x67
+#define AXP20X_PWR_BATT_H 0x70
+#define AXP20X_PWR_BATT_M 0x71
+#define AXP20X_PWR_BATT_L 0x72
+#define AXP20X_BATT_V_H 0x78
+#define AXP20X_BATT_V_L 0x79
+#define AXP20X_BATT_CHRG_I_H 0x7a
+#define AXP20X_BATT_CHRG_I_L 0x7b
+#define AXP20X_BATT_DISCHRG_I_H 0x7c
+#define AXP20X_BATT_DISCHRG_I_L 0x7d
+#define AXP20X_IPSOUT_V_HIGH_H 0x7e
+#define AXP20X_IPSOUT_V_HIGH_L 0x7f
+
+/* Power supply */
+#define AXP20X_DCDC_MODE 0x80
+#define AXP20X_ADC_EN1 0x82
+#define AXP20X_ADC_EN2 0x83
+#define AXP20X_ADC_RATE 0x84
+#define AXP20X_GPIO10_IN_RANGE 0x85
+#define AXP20X_GPIO1_ADC_IRQ_RIS 0x86
+#define AXP20X_GPIO1_ADC_IRQ_FAL 0x87
+#define AXP20X_TIMER_CTRL 0x8a
+#define AXP20X_VBUS_MON 0x8b
+#define AXP20X_OVER_TMP 0x8f
+
+/* GPIO */
+#define AXP20X_GPIO0_CTRL 0x90
+#define AXP20X_LDO5_V_OUT 0x91
+#define AXP20X_GPIO1_CTRL 0x92
+#define AXP20X_GPIO2_CTRL 0x93
+#define AXP20X_GPIO20_SS 0x94
+#define AXP20X_GPIO3_CTRL 0x95
+
+/* Battery */
+#define AXP20X_CHRG_CC_31_24 0xb0
+#define AXP20X_CHRG_CC_23_16 0xb1
+#define AXP20X_CHRG_CC_15_8 0xb2
+#define AXP20X_CHRG_CC_7_0 0xb3
+#define AXP20X_DISCHRG_CC_31_24 0xb4
+#define AXP20X_DISCHRG_CC_23_16 0xb5
+#define AXP20X_DISCHRG_CC_15_8 0xb6
+#define AXP20X_DISCHRG_CC_7_0 0xb7
+#define AXP20X_CC_CTRL 0xb8
+#define AXP20X_FG_RES 0xb9
+
+/* Regulators IDs */
+enum {
+ AXP20X_LDO1 = 0,
+ AXP20X_LDO2,
+ AXP20X_LDO3,
+ AXP20X_LDO4,
+ AXP20X_LDO5,
+ AXP20X_DCDC2,
+ AXP20X_DCDC3,
+ AXP20X_REG_ID_MAX,
+};
+
+/* IRQs */
+enum {
+ AXP20X_IRQ_ACIN_OVER_V = 1,
+ AXP20X_IRQ_ACIN_PLUGIN,
+ AXP20X_IRQ_ACIN_REMOVAL,
+ AXP20X_IRQ_VBUS_OVER_V,
+ AXP20X_IRQ_VBUS_PLUGIN,
+ AXP20X_IRQ_VBUS_REMOVAL,
+ AXP20X_IRQ_VBUS_V_LOW,
+ AXP20X_IRQ_BATT_PLUGIN,
+ AXP20X_IRQ_BATT_REMOVAL,
+ AXP20X_IRQ_BATT_ENT_ACT_MODE,
+ AXP20X_IRQ_BATT_EXIT_ACT_MODE,
+ AXP20X_IRQ_CHARG,
+ AXP20X_IRQ_CHARG_DONE,
+ AXP20X_IRQ_BATT_TEMP_HIGH,
+ AXP20X_IRQ_BATT_TEMP_LOW,
+ AXP20X_IRQ_DIE_TEMP_HIGH,
+ AXP20X_IRQ_CHARG_I_LOW,
+ AXP20X_IRQ_DCDC1_V_LONG,
+ AXP20X_IRQ_DCDC2_V_LONG,
+ AXP20X_IRQ_DCDC3_V_LONG,
+ AXP20X_IRQ_PEK_SHORT = 22,
+ AXP20X_IRQ_PEK_LONG,
+ AXP20X_IRQ_N_OE_PWR_ON,
+ AXP20X_IRQ_N_OE_PWR_OFF,
+ AXP20X_IRQ_VBUS_VALID,
+ AXP20X_IRQ_VBUS_NOT_VALID,
+ AXP20X_IRQ_VBUS_SESS_VALID,
+ AXP20X_IRQ_VBUS_SESS_END,
+ AXP20X_IRQ_LOW_PWR_LVL1,
+ AXP20X_IRQ_LOW_PWR_LVL2,
+ AXP20X_IRQ_TIMER,
+ AXP20X_IRQ_PEK_RIS_EDGE,
+ AXP20X_IRQ_PEK_FAL_EDGE,
+ AXP20X_IRQ_GPIO3_INPUT,
+ AXP20X_IRQ_GPIO2_INPUT,
+ AXP20X_IRQ_GPIO1_INPUT,
+ AXP20X_IRQ_GPIO0_INPUT,
+};
+
+struct axp20x_dev {
+ struct device *dev;
+ struct i2c_client *i2c_client;
+ struct regmap *regmap;
+ struct regmap_irq_chip_data *regmap_irqc;
+ long variant;
+};
+
+#endif /* __LINUX_MFD_AXP20X_H */
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 032af7fc5b2e..887ef4f7bef7 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -29,8 +29,8 @@ enum {
EC_MSG_RX_PROTO_BYTES = 3,
/* Max length of messages */
- EC_MSG_BYTES = EC_HOST_PARAM_SIZE + EC_MSG_TX_PROTO_BYTES,
-
+ EC_MSG_BYTES = EC_PROTO2_MAX_PARAM_SIZE +
+ EC_MSG_TX_PROTO_BYTES,
};
/**
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
index 86fd06953bcd..7853a6410d14 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -24,25 +24,12 @@
#define __CROS_EC_COMMANDS_H
/*
- * Protocol overview
+ * Current version of this protocol
*
- * request: CMD [ P0 P1 P2 ... Pn S ]
- * response: ERR [ P0 P1 P2 ... Pn S ]
- *
- * where the bytes are defined as follow :
- * - CMD is the command code. (defined by EC_CMD_ constants)
- * - ERR is the error code. (defined by EC_RES_ constants)
- * - Px is the optional payload.
- * it is not sent if the error code is not success.
- * (defined by ec_params_ and ec_response_ structures)
- * - S is the checksum which is the sum of all payload bytes.
- *
- * On LPC, CMD and ERR are sent/received at EC_LPC_ADDR_KERNEL|USER_CMD
- * and the payloads are sent/received at EC_LPC_ADDR_KERNEL|USER_PARAM.
- * On I2C, all bytes are sent serially in the same message.
+ * TODO(crosbug.com/p/11223): This is effectively useless; protocol is
+ * determined in other ways. Remove this once the kernel code no longer
+ * depends on it.
*/
-
-/* Current version of this protocol */
#define EC_PROTO_VERSION 0x00000002
/* Command version mask */
@@ -57,13 +44,19 @@
#define EC_LPC_ADDR_HOST_CMD 0x204
/* I/O addresses for host command args and params */
-#define EC_LPC_ADDR_HOST_ARGS 0x800
-#define EC_LPC_ADDR_HOST_PARAM 0x804
-#define EC_HOST_PARAM_SIZE 0x0fc /* Size of param area in bytes */
-
-/* I/O addresses for host command params, old interface */
-#define EC_LPC_ADDR_OLD_PARAM 0x880
-#define EC_OLD_PARAM_SIZE 0x080 /* Size of param area in bytes */
+/* Protocol version 2 */
+#define EC_LPC_ADDR_HOST_ARGS 0x800 /* And 0x801, 0x802, 0x803 */
+#define EC_LPC_ADDR_HOST_PARAM 0x804 /* For version 2 params; size is
+ * EC_PROTO2_MAX_PARAM_SIZE */
+/* Protocol version 3 */
+#define EC_LPC_ADDR_HOST_PACKET 0x800 /* Offset of version 3 packet */
+#define EC_LPC_HOST_PACKET_SIZE 0x100 /* Max size of version 3 packet */
+
+/* The actual block is 0x800-0x8ff, but some BIOSes think it's 0x880-0x8ff
+ * and they tell the kernel that so we have to think of it as two parts. */
+#define EC_HOST_CMD_REGION0 0x800
+#define EC_HOST_CMD_REGION1 0x880
+#define EC_HOST_CMD_REGION_SIZE 0x80
/* EC command register bit functions */
#define EC_LPC_CMDR_DATA (1 << 0) /* Data ready for host to read */
@@ -79,18 +72,22 @@
#define EC_MEMMAP_TEXT_MAX 8 /* Size of a string in the memory map */
/* The offset address of each type of data in mapped memory. */
-#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors */
-#define EC_MEMMAP_FAN 0x10 /* Fan speeds */
-#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* Temp sensors (second set) */
-#define EC_MEMMAP_ID 0x20 /* 'E' 'C' */
+#define EC_MEMMAP_TEMP_SENSOR 0x00 /* Temp sensors 0x00 - 0x0f */
+#define EC_MEMMAP_FAN 0x10 /* Fan speeds 0x10 - 0x17 */
+#define EC_MEMMAP_TEMP_SENSOR_B 0x18 /* More temp sensors 0x18 - 0x1f */
+#define EC_MEMMAP_ID 0x20 /* 0x20 == 'E', 0x21 == 'C' */
#define EC_MEMMAP_ID_VERSION 0x22 /* Version of data in 0x20 - 0x2f */
#define EC_MEMMAP_THERMAL_VERSION 0x23 /* Version of data in 0x00 - 0x1f */
#define EC_MEMMAP_BATTERY_VERSION 0x24 /* Version of data in 0x40 - 0x7f */
#define EC_MEMMAP_SWITCHES_VERSION 0x25 /* Version of data in 0x30 - 0x33 */
#define EC_MEMMAP_EVENTS_VERSION 0x26 /* Version of data in 0x34 - 0x3f */
-#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host command interface flags */
-#define EC_MEMMAP_SWITCHES 0x30
-#define EC_MEMMAP_HOST_EVENTS 0x34
+#define EC_MEMMAP_HOST_CMD_FLAGS 0x27 /* Host cmd interface flags (8 bits) */
+/* Unused 0x28 - 0x2f */
+#define EC_MEMMAP_SWITCHES 0x30 /* 8 bits */
+/* Unused 0x31 - 0x33 */
+#define EC_MEMMAP_HOST_EVENTS 0x34 /* 32 bits */
+/* Reserve 0x38 - 0x3f for additional host event-related stuff */
+/* Battery values are all 32 bits */
#define EC_MEMMAP_BATT_VOLT 0x40 /* Battery Present Voltage */
#define EC_MEMMAP_BATT_RATE 0x44 /* Battery Present Rate */
#define EC_MEMMAP_BATT_CAP 0x48 /* Battery Remaining Capacity */
@@ -99,10 +96,24 @@
#define EC_MEMMAP_BATT_DVLT 0x54 /* Battery Design Voltage */
#define EC_MEMMAP_BATT_LFCC 0x58 /* Battery Last Full Charge Capacity */
#define EC_MEMMAP_BATT_CCNT 0x5c /* Battery Cycle Count */
+/* Strings are all 8 bytes (EC_MEMMAP_TEXT_MAX) */
#define EC_MEMMAP_BATT_MFGR 0x60 /* Battery Manufacturer String */
#define EC_MEMMAP_BATT_MODEL 0x68 /* Battery Model Number String */
#define EC_MEMMAP_BATT_SERIAL 0x70 /* Battery Serial Number String */
#define EC_MEMMAP_BATT_TYPE 0x78 /* Battery Type String */
+#define EC_MEMMAP_ALS 0x80 /* ALS readings in lux (2 X 16 bits) */
+/* Unused 0x84 - 0x8f */
+#define EC_MEMMAP_ACC_STATUS 0x90 /* Accelerometer status (8 bits )*/
+/* Unused 0x91 */
+#define EC_MEMMAP_ACC_DATA 0x92 /* Accelerometer data 0x92 - 0x9f */
+#define EC_MEMMAP_GYRO_DATA 0xa0 /* Gyroscope data 0xa0 - 0xa5 */
+/* Unused 0xa6 - 0xfe (remember, 0xff is NOT part of the memmap region) */
+
+
+/* Define the format of the accelerometer mapped memory status byte. */
+#define EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK 0x0f
+#define EC_MEMMAP_ACC_STATUS_BUSY_BIT (1 << 4)
+#define EC_MEMMAP_ACC_STATUS_PRESENCE_BIT (1 << 7)
/* Number of temp sensors at EC_MEMMAP_TEMP_SENSOR */
#define EC_TEMP_SENSOR_ENTRIES 16
@@ -112,6 +123,8 @@
* Valid only if EC_MEMMAP_THERMAL_VERSION returns >= 2.
*/
#define EC_TEMP_SENSOR_B_ENTRIES 8
+
+/* Special values for mapped temperature sensors */
#define EC_TEMP_SENSOR_NOT_PRESENT 0xff
#define EC_TEMP_SENSOR_ERROR 0xfe
#define EC_TEMP_SENSOR_NOT_POWERED 0xfd
@@ -122,6 +135,18 @@
*/
#define EC_TEMP_SENSOR_OFFSET 200
+/*
+ * Number of ALS readings at EC_MEMMAP_ALS
+ */
+#define EC_ALS_ENTRIES 2
+
+/*
+ * The default value a temperature sensor will return when it is present but
+ * has not been read this boot. This is a reasonable number to avoid
+ * triggering alarms on the host.
+ */
+#define EC_TEMP_SENSOR_DEFAULT (296 - EC_TEMP_SENSOR_OFFSET)
+
#define EC_FAN_SPEED_ENTRIES 4 /* Number of fans at EC_MEMMAP_FAN */
#define EC_FAN_SPEED_NOT_PRESENT 0xffff /* Entry not present */
#define EC_FAN_SPEED_STALLED 0xfffe /* Fan stalled */
@@ -137,8 +162,8 @@
#define EC_SWITCH_LID_OPEN 0x01
#define EC_SWITCH_POWER_BUTTON_PRESSED 0x02
#define EC_SWITCH_WRITE_PROTECT_DISABLED 0x04
-/* Recovery requested via keyboard */
-#define EC_SWITCH_KEYBOARD_RECOVERY 0x08
+/* Was recovery requested via keyboard; now unused. */
+#define EC_SWITCH_IGNORE1 0x08
/* Recovery requested via dedicated signal (from servo board) */
#define EC_SWITCH_DEDICATED_RECOVERY 0x10
/* Was fake developer mode switch; now unused. Remove in next refactor. */
@@ -147,10 +172,15 @@
/* Host command interface flags */
/* Host command interface supports LPC args (LPC interface only) */
#define EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED 0x01
+/* Host command interface supports version 3 protocol */
+#define EC_HOST_CMD_FLAG_VERSION_3 0x02
/* Wireless switch flags */
-#define EC_WIRELESS_SWITCH_WLAN 0x01
-#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02
+#define EC_WIRELESS_SWITCH_ALL ~0x00 /* All flags */
+#define EC_WIRELESS_SWITCH_WLAN 0x01 /* WLAN radio */
+#define EC_WIRELESS_SWITCH_BLUETOOTH 0x02 /* Bluetooth radio */
+#define EC_WIRELESS_SWITCH_WWAN 0x04 /* WWAN power */
+#define EC_WIRELESS_SWITCH_WLAN_POWER 0x08 /* WLAN power */
/*
* This header file is used in coreboot both in C and ACPI code. The ACPI code
@@ -159,6 +189,14 @@
*/
#ifndef __ACPI__
+/*
+ * Define __packed if someone hasn't beat us to it. Linux kernel style
+ * checking prefers __packed over __attribute__((packed)).
+ */
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
/* LPC command status byte masks */
/* EC has written a byte in the data register and host hasn't read it yet */
#define EC_LPC_STATUS_TO_HOST 0x01
@@ -198,6 +236,9 @@ enum ec_status {
EC_RES_UNAVAILABLE = 9, /* No response available */
EC_RES_TIMEOUT = 10, /* We got a timeout */
EC_RES_OVERFLOW = 11, /* Table / data overflow */
+ EC_RES_INVALID_HEADER = 12, /* Header contains invalid data */
+ EC_RES_REQUEST_TRUNCATED = 13, /* Didn't get the entire request */
+ EC_RES_RESPONSE_TOO_BIG = 14 /* Response was too big to handle */
};
/*
@@ -235,6 +276,16 @@ enum host_event_code {
/* Shutdown due to battery level too low */
EC_HOST_EVENT_BATTERY_SHUTDOWN = 17,
+ /* Suggest that the AP throttle itself */
+ EC_HOST_EVENT_THROTTLE_START = 18,
+ /* Suggest that the AP resume normal speed */
+ EC_HOST_EVENT_THROTTLE_STOP = 19,
+
+ /* Hang detect logic detected a hang and host event timeout expired */
+ EC_HOST_EVENT_HANG_DETECT = 20,
+ /* Hang detect logic detected a hang and warm rebooted the AP */
+ EC_HOST_EVENT_HANG_REBOOT = 21,
+
/*
* The high bit of the event mask is not used as a host event code. If
* it reads back as set, then the entire event mask should be
@@ -279,6 +330,188 @@ struct ec_lpc_host_args {
*/
#define EC_HOST_ARGS_FLAG_TO_HOST 0x02
+/*****************************************************************************/
+/*
+ * Byte codes returned by EC over SPI interface.
+ *
+ * These can be used by the AP to debug the EC interface, and to determine
+ * when the EC is not in a state where it will ever get around to responding
+ * to the AP.
+ *
+ * Example of sequence of bytes read from EC for a current good transfer:
+ * 1. - - AP asserts chip select (CS#)
+ * 2. EC_SPI_OLD_READY - AP sends first byte(s) of request
+ * 3. - - EC starts handling CS# interrupt
+ * 4. EC_SPI_RECEIVING - AP sends remaining byte(s) of request
+ * 5. EC_SPI_PROCESSING - EC starts processing request; AP is clocking in
+ * bytes looking for EC_SPI_FRAME_START
+ * 6. - - EC finishes processing and sets up response
+ * 7. EC_SPI_FRAME_START - AP reads frame byte
+ * 8. (response packet) - AP reads response packet
+ * 9. EC_SPI_PAST_END - Any additional bytes read by AP
+ * 10 - - AP deasserts chip select
+ * 11 - - EC processes CS# interrupt and sets up DMA for
+ * next request
+ *
+ * If the AP is waiting for EC_SPI_FRAME_START and sees any value other than
+ * the following byte values:
+ * EC_SPI_OLD_READY
+ * EC_SPI_RX_READY
+ * EC_SPI_RECEIVING
+ * EC_SPI_PROCESSING
+ *
+ * Then the EC found an error in the request, or was not ready for the request
+ * and lost data. The AP should give up waiting for EC_SPI_FRAME_START,
+ * because the EC is unable to tell when the AP is done sending its request.
+ */
+
+/*
+ * Framing byte which precedes a response packet from the EC. After sending a
+ * request, the AP will clock in bytes until it sees the framing byte, then
+ * clock in the response packet.
+ */
+#define EC_SPI_FRAME_START 0xec
+
+/*
+ * Padding bytes which are clocked out after the end of a response packet.
+ */
+#define EC_SPI_PAST_END 0xed
+
+/*
+ * EC is ready to receive, and has ignored the byte sent by the AP. EC expects
+ * that the AP will send a valid packet header (starting with
+ * EC_COMMAND_PROTOCOL_3) in the next 32 bytes.
+ */
+#define EC_SPI_RX_READY 0xf8
+
+/*
+ * EC has started receiving the request from the AP, but hasn't started
+ * processing it yet.
+ */
+#define EC_SPI_RECEIVING 0xf9
+
+/* EC has received the entire request from the AP and is processing it. */
+#define EC_SPI_PROCESSING 0xfa
+
+/*
+ * EC received bad data from the AP, such as a packet header with an invalid
+ * length. EC will ignore all data until chip select deasserts.
+ */
+#define EC_SPI_RX_BAD_DATA 0xfb
+
+/*
+ * EC received data from the AP before it was ready. That is, the AP asserted
+ * chip select and started clocking data before the EC was ready to receive it.
+ * EC will ignore all data until chip select deasserts.
+ */
+#define EC_SPI_NOT_READY 0xfc
+
+/*
+ * EC was ready to receive a request from the AP. EC has treated the byte sent
+ * by the AP as part of a request packet, or (for old-style ECs) is processing
+ * a fully received packet but is not ready to respond yet.
+ */
+#define EC_SPI_OLD_READY 0xfd
+
+/*****************************************************************************/
+
+/*
+ * Protocol version 2 for I2C and SPI send a request this way:
+ *
+ * 0 EC_CMD_VERSION0 + (command version)
+ * 1 Command number
+ * 2 Length of params = N
+ * 3..N+2 Params, if any
+ * N+3 8-bit checksum of bytes 0..N+2
+ *
+ * The corresponding response is:
+ *
+ * 0 Result code (EC_RES_*)
+ * 1 Length of params = M
+ * 2..M+1 Params, if any
+ * M+2 8-bit checksum of bytes 0..M+1
+ */
+#define EC_PROTO2_REQUEST_HEADER_BYTES 3
+#define EC_PROTO2_REQUEST_TRAILER_BYTES 1
+#define EC_PROTO2_REQUEST_OVERHEAD (EC_PROTO2_REQUEST_HEADER_BYTES + \
+ EC_PROTO2_REQUEST_TRAILER_BYTES)
+
+#define EC_PROTO2_RESPONSE_HEADER_BYTES 2
+#define EC_PROTO2_RESPONSE_TRAILER_BYTES 1
+#define EC_PROTO2_RESPONSE_OVERHEAD (EC_PROTO2_RESPONSE_HEADER_BYTES + \
+ EC_PROTO2_RESPONSE_TRAILER_BYTES)
+
+/* Parameter length was limited by the LPC interface */
+#define EC_PROTO2_MAX_PARAM_SIZE 0xfc
+
+/* Maximum request and response packet sizes for protocol version 2 */
+#define EC_PROTO2_MAX_REQUEST_SIZE (EC_PROTO2_REQUEST_OVERHEAD + \
+ EC_PROTO2_MAX_PARAM_SIZE)
+#define EC_PROTO2_MAX_RESPONSE_SIZE (EC_PROTO2_RESPONSE_OVERHEAD + \
+ EC_PROTO2_MAX_PARAM_SIZE)
+
+/*****************************************************************************/
+
+/*
+ * Value written to legacy command port / prefix byte to indicate protocol
+ * 3+ structs are being used. Usage is bus-dependent.
+ */
+#define EC_COMMAND_PROTOCOL_3 0xda
+
+#define EC_HOST_REQUEST_VERSION 3
+
+/* Version 3 request from host */
+struct ec_host_request {
+ /* Struct version (=3)
+ *
+ * EC will return EC_RES_INVALID_HEADER if it receives a header with a
+ * version it doesn't know how to parse.
+ */
+ uint8_t struct_version;
+
+ /*
+ * Checksum of request and data; sum of all bytes including checksum
+ * should total to 0.
+ */
+ uint8_t checksum;
+
+ /* Command code */
+ uint16_t command;
+
+ /* Command version */
+ uint8_t command_version;
+
+ /* Unused byte in current protocol version; set to 0 */
+ uint8_t reserved;
+
+ /* Length of data which follows this header */
+ uint16_t data_len;
+} __packed;
+
+#define EC_HOST_RESPONSE_VERSION 3
+
+/* Version 3 response from EC */
+struct ec_host_response {
+ /* Struct version (=3) */
+ uint8_t struct_version;
+
+ /*
+ * Checksum of response and data; sum of all bytes including checksum
+ * should total to 0.
+ */
+ uint8_t checksum;
+
+ /* Result code (EC_RES_*) */
+ uint16_t result;
+
+ /* Length of data which follows this header */
+ uint16_t data_len;
+
+ /* Unused bytes in current protocol version; set to 0 */
+ uint16_t reserved;
+} __packed;
+
+/*****************************************************************************/
/*
* Notes on commands:
*
@@ -418,6 +651,68 @@ struct ec_response_get_comms_status {
uint32_t flags; /* Mask of enum ec_comms_status */
} __packed;
+/* Fake a variety of responses, purely for testing purposes. */
+#define EC_CMD_TEST_PROTOCOL 0x0a
+
+/* Tell the EC what to send back to us. */
+struct ec_params_test_protocol {
+ uint32_t ec_result;
+ uint32_t ret_len;
+ uint8_t buf[32];
+} __packed;
+
+/* Here it comes... */
+struct ec_response_test_protocol {
+ uint8_t buf[32];
+} __packed;
+
+/* Get prococol information */
+#define EC_CMD_GET_PROTOCOL_INFO 0x0b
+
+/* Flags for ec_response_get_protocol_info.flags */
+/* EC_RES_IN_PROGRESS may be returned if a command is slow */
+#define EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED (1 << 0)
+
+struct ec_response_get_protocol_info {
+ /* Fields which exist if at least protocol version 3 supported */
+
+ /* Bitmask of protocol versions supported (1 << n means version n)*/
+ uint32_t protocol_versions;
+
+ /* Maximum request packet size, in bytes */
+ uint16_t max_request_packet_size;
+
+ /* Maximum response packet size, in bytes */
+ uint16_t max_response_packet_size;
+
+ /* Flags; see EC_PROTOCOL_INFO_* */
+ uint32_t flags;
+} __packed;
+
+
+/*****************************************************************************/
+/* Get/Set miscellaneous values */
+
+/* The upper byte of .flags tells what to do (nothing means "get") */
+#define EC_GSV_SET 0x80000000
+
+/* The lower three bytes of .flags identifies the parameter, if that has
+ meaning for an individual command. */
+#define EC_GSV_PARAM_MASK 0x00ffffff
+
+struct ec_params_get_set_value {
+ uint32_t flags;
+ uint32_t value;
+} __packed;
+
+struct ec_response_get_set_value {
+ uint32_t flags;
+ uint32_t value;
+} __packed;
+
+/* More than one command can use these structs to get/set paramters. */
+#define EC_CMD_GSV_PAUSE_IN_S5 0x0c
+
/*****************************************************************************/
/* Flash commands */
@@ -425,6 +720,7 @@ struct ec_response_get_comms_status {
/* Get flash info */
#define EC_CMD_FLASH_INFO 0x10
+/* Version 0 returns these fields */
struct ec_response_flash_info {
/* Usable flash size, in bytes */
uint32_t flash_size;
@@ -445,6 +741,37 @@ struct ec_response_flash_info {
uint32_t protect_block_size;
} __packed;
+/* Flags for version 1+ flash info command */
+/* EC flash erases bits to 0 instead of 1 */
+#define EC_FLASH_INFO_ERASE_TO_0 (1 << 0)
+
+/*
+ * Version 1 returns the same initial fields as version 0, with additional
+ * fields following.
+ *
+ * gcc anonymous structs don't seem to get along with the __packed directive;
+ * if they did we'd define the version 0 struct as a sub-struct of this one.
+ */
+struct ec_response_flash_info_1 {
+ /* Version 0 fields; see above for description */
+ uint32_t flash_size;
+ uint32_t write_block_size;
+ uint32_t erase_block_size;
+ uint32_t protect_block_size;
+
+ /* Version 1 adds these fields: */
+ /*
+ * Ideal write size in bytes. Writes will be fastest if size is
+ * exactly this and offset is a multiple of this. For example, an EC
+ * may have a write buffer which can do half-page operations if data is
+ * aligned, and a slower word-at-a-time write mode.
+ */
+ uint32_t write_ideal_size;
+
+ /* Flags; see EC_FLASH_INFO_* */
+ uint32_t flags;
+} __packed;
+
/*
* Read flash
*
@@ -459,15 +786,15 @@ struct ec_params_flash_read {
/* Write flash */
#define EC_CMD_FLASH_WRITE 0x12
+#define EC_VER_FLASH_WRITE 1
+
+/* Version 0 of the flash command supported only 64 bytes of data */
+#define EC_FLASH_WRITE_VER0_SIZE 64
struct ec_params_flash_write {
uint32_t offset; /* Byte offset to write */
uint32_t size; /* Size to write in bytes */
- /*
- * Data to write. Could really use EC_PARAM_SIZE - 8, but tidiest to
- * use a power of 2 so writes stay aligned.
- */
- uint8_t data[64];
+ /* Followed by data to write */
} __packed;
/* Erase flash */
@@ -543,7 +870,7 @@ struct ec_response_flash_protect {
enum ec_flash_region {
/* Region which holds read-only EC image */
- EC_FLASH_REGION_RO,
+ EC_FLASH_REGION_RO = 0,
/* Region which holds rewritable EC image */
EC_FLASH_REGION_RW,
/*
@@ -551,6 +878,8 @@ enum ec_flash_region {
* EC_FLASH_REGION_RO)
*/
EC_FLASH_REGION_WP_RO,
+ /* Number of regions */
+ EC_FLASH_REGION_COUNT,
};
struct ec_params_flash_region_info {
@@ -639,15 +968,15 @@ struct rgb_s {
*/
struct lightbar_params {
/* Timing */
- int google_ramp_up;
- int google_ramp_down;
- int s3s0_ramp_up;
- int s0_tick_delay[2]; /* AC=0/1 */
- int s0a_tick_delay[2]; /* AC=0/1 */
- int s0s3_ramp_down;
- int s3_sleep_for;
- int s3_ramp_up;
- int s3_ramp_down;
+ int32_t google_ramp_up;
+ int32_t google_ramp_down;
+ int32_t s3s0_ramp_up;
+ int32_t s0_tick_delay[2]; /* AC=0/1 */
+ int32_t s0a_tick_delay[2]; /* AC=0/1 */
+ int32_t s0s3_ramp_down;
+ int32_t s3_sleep_for;
+ int32_t s3_ramp_up;
+ int32_t s3_ramp_down;
/* Oscillation */
uint8_t new_s0;
@@ -676,7 +1005,7 @@ struct ec_params_lightbar {
union {
struct {
/* no args */
- } dump, off, on, init, get_seq, get_params;
+ } dump, off, on, init, get_seq, get_params, version;
struct num {
uint8_t num;
@@ -710,6 +1039,11 @@ struct ec_response_lightbar {
struct lightbar_params get_params;
+ struct version {
+ uint32_t num;
+ uint32_t flags;
+ } version;
+
struct {
/* no return params */
} off, on, init, brightness, seq, reg, rgb, demo, set_params;
@@ -730,10 +1064,62 @@ enum lightbar_command {
LIGHTBAR_CMD_DEMO = 9,
LIGHTBAR_CMD_GET_PARAMS = 10,
LIGHTBAR_CMD_SET_PARAMS = 11,
+ LIGHTBAR_CMD_VERSION = 12,
LIGHTBAR_NUM_CMDS
};
/*****************************************************************************/
+/* LED control commands */
+
+#define EC_CMD_LED_CONTROL 0x29
+
+enum ec_led_id {
+ /* LED to indicate battery state of charge */
+ EC_LED_ID_BATTERY_LED = 0,
+ /*
+ * LED to indicate system power state (on or in suspend).
+ * May be on power button or on C-panel.
+ */
+ EC_LED_ID_POWER_LED,
+ /* LED on power adapter or its plug */
+ EC_LED_ID_ADAPTER_LED,
+
+ EC_LED_ID_COUNT
+};
+
+/* LED control flags */
+#define EC_LED_FLAGS_QUERY (1 << 0) /* Query LED capability only */
+#define EC_LED_FLAGS_AUTO (1 << 1) /* Switch LED back to automatic control */
+
+enum ec_led_colors {
+ EC_LED_COLOR_RED = 0,
+ EC_LED_COLOR_GREEN,
+ EC_LED_COLOR_BLUE,
+ EC_LED_COLOR_YELLOW,
+ EC_LED_COLOR_WHITE,
+
+ EC_LED_COLOR_COUNT
+};
+
+struct ec_params_led_control {
+ uint8_t led_id; /* Which LED to control */
+ uint8_t flags; /* Control flags */
+
+ uint8_t brightness[EC_LED_COLOR_COUNT];
+} __packed;
+
+struct ec_response_led_control {
+ /*
+ * Available brightness value range.
+ *
+ * Range 0 means color channel not present.
+ * Range 1 means on/off control.
+ * Other values means the LED is control by PWM.
+ */
+ uint8_t brightness_range[EC_LED_COLOR_COUNT];
+} __packed;
+
+/*****************************************************************************/
/* Verified boot commands */
/*
@@ -790,6 +1176,181 @@ enum ec_vboot_hash_status {
#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
/*****************************************************************************/
+/*
+ * Motion sense commands. We'll make separate structs for sub-commands with
+ * different input args, so that we know how much to expect.
+ */
+#define EC_CMD_MOTION_SENSE_CMD 0x2B
+
+/* Motion sense commands */
+enum motionsense_command {
+ /*
+ * Dump command returns all motion sensor data including motion sense
+ * module flags and individual sensor flags.
+ */
+ MOTIONSENSE_CMD_DUMP = 0,
+
+ /*
+ * Info command returns data describing the details of a given sensor,
+ * including enum motionsensor_type, enum motionsensor_location, and
+ * enum motionsensor_chip.
+ */
+ MOTIONSENSE_CMD_INFO = 1,
+
+ /*
+ * EC Rate command is a setter/getter command for the EC sampling rate
+ * of all motion sensors in milliseconds.
+ */
+ MOTIONSENSE_CMD_EC_RATE = 2,
+
+ /*
+ * Sensor ODR command is a setter/getter command for the output data
+ * rate of a specific motion sensor in millihertz.
+ */
+ MOTIONSENSE_CMD_SENSOR_ODR = 3,
+
+ /*
+ * Sensor range command is a setter/getter command for the range of
+ * a specified motion sensor in +/-G's or +/- deg/s.
+ */
+ MOTIONSENSE_CMD_SENSOR_RANGE = 4,
+
+ /*
+ * Setter/getter command for the keyboard wake angle. When the lid
+ * angle is greater than this value, keyboard wake is disabled in S3,
+ * and when the lid angle goes less than this value, keyboard wake is
+ * enabled. Note, the lid angle measurement is an approximate,
+ * un-calibrated value, hence the wake angle isn't exact.
+ */
+ MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
+
+ /* Number of motionsense sub-commands. */
+ MOTIONSENSE_NUM_CMDS
+};
+
+enum motionsensor_id {
+ EC_MOTION_SENSOR_ACCEL_BASE = 0,
+ EC_MOTION_SENSOR_ACCEL_LID = 1,
+ EC_MOTION_SENSOR_GYRO = 2,
+
+ /*
+ * Note, if more sensors are added and this count changes, the padding
+ * in ec_response_motion_sense dump command must be modified.
+ */
+ EC_MOTION_SENSOR_COUNT = 3
+};
+
+/* List of motion sensor types. */
+enum motionsensor_type {
+ MOTIONSENSE_TYPE_ACCEL = 0,
+ MOTIONSENSE_TYPE_GYRO = 1,
+};
+
+/* List of motion sensor locations. */
+enum motionsensor_location {
+ MOTIONSENSE_LOC_BASE = 0,
+ MOTIONSENSE_LOC_LID = 1,
+};
+
+/* List of motion sensor chips. */
+enum motionsensor_chip {
+ MOTIONSENSE_CHIP_KXCJ9 = 0,
+};
+
+/* Module flag masks used for the dump sub-command. */
+#define MOTIONSENSE_MODULE_FLAG_ACTIVE (1<<0)
+
+/* Sensor flag masks used for the dump sub-command. */
+#define MOTIONSENSE_SENSOR_FLAG_PRESENT (1<<0)
+
+/*
+ * Send this value for the data element to only perform a read. If you
+ * send any other value, the EC will interpret it as data to set and will
+ * return the actual value set.
+ */
+#define EC_MOTION_SENSE_NO_VALUE -1
+
+struct ec_params_motion_sense {
+ uint8_t cmd;
+ union {
+ /* Used for MOTIONSENSE_CMD_DUMP. */
+ struct {
+ /* no args */
+ } dump;
+
+ /*
+ * Used for MOTIONSENSE_CMD_EC_RATE and
+ * MOTIONSENSE_CMD_KB_WAKE_ANGLE.
+ */
+ struct {
+ /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
+ int16_t data;
+ } ec_rate, kb_wake_angle;
+
+ /* Used for MOTIONSENSE_CMD_INFO. */
+ struct {
+ /* Should be element of enum motionsensor_id. */
+ uint8_t sensor_num;
+ } info;
+
+ /*
+ * Used for MOTIONSENSE_CMD_SENSOR_ODR and
+ * MOTIONSENSE_CMD_SENSOR_RANGE.
+ */
+ struct {
+ /* Should be element of enum motionsensor_id. */
+ uint8_t sensor_num;
+
+ /* Rounding flag, true for round-up, false for down. */
+ uint8_t roundup;
+
+ uint16_t reserved;
+
+ /* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
+ int32_t data;
+ } sensor_odr, sensor_range;
+ };
+} __packed;
+
+struct ec_response_motion_sense {
+ union {
+ /* Used for MOTIONSENSE_CMD_DUMP. */
+ struct {
+ /* Flags representing the motion sensor module. */
+ uint8_t module_flags;
+
+ /* Flags for each sensor in enum motionsensor_id. */
+ uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
+
+ /* Array of all sensor data. Each sensor is 3-axis. */
+ int16_t data[3*EC_MOTION_SENSOR_COUNT];
+ } dump;
+
+ /* Used for MOTIONSENSE_CMD_INFO. */
+ struct {
+ /* Should be element of enum motionsensor_type. */
+ uint8_t type;
+
+ /* Should be element of enum motionsensor_location. */
+ uint8_t location;
+
+ /* Should be element of enum motionsensor_chip. */
+ uint8_t chip;
+ } info;
+
+ /*
+ * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
+ * MOTIONSENSE_CMD_SENSOR_RANGE, and
+ * MOTIONSENSE_CMD_KB_WAKE_ANGLE.
+ */
+ struct {
+ /* Current value of the parameter queried. */
+ int32_t ret;
+ } ec_rate, sensor_odr, sensor_range, kb_wake_angle;
+ };
+} __packed;
+
+/*****************************************************************************/
/* USB charging control commands */
/* Set USB port charging mode */
@@ -868,20 +1429,27 @@ struct ec_response_port80_last_boot {
} __packed;
/*****************************************************************************/
-/* Thermal engine commands */
+/* Thermal engine commands. Note that there are two implementations. We'll
+ * reuse the command number, but the data and behavior is incompatible.
+ * Version 0 is what originally shipped on Link.
+ * Version 1 separates the CPU thermal limits from the fan control.
+ */
-/* Set thershold value */
#define EC_CMD_THERMAL_SET_THRESHOLD 0x50
+#define EC_CMD_THERMAL_GET_THRESHOLD 0x51
+
+/* The version 0 structs are opaque. You have to know what they are for
+ * the get/set commands to make any sense.
+ */
+/* Version 0 - set */
struct ec_params_thermal_set_threshold {
uint8_t sensor_type;
uint8_t threshold_id;
uint16_t value;
} __packed;
-/* Get threshold value */
-#define EC_CMD_THERMAL_GET_THRESHOLD 0x51
-
+/* Version 0 - get */
struct ec_params_thermal_get_threshold {
uint8_t sensor_type;
uint8_t threshold_id;
@@ -891,6 +1459,41 @@ struct ec_response_thermal_get_threshold {
uint16_t value;
} __packed;
+
+/* The version 1 structs are visible. */
+enum ec_temp_thresholds {
+ EC_TEMP_THRESH_WARN = 0,
+ EC_TEMP_THRESH_HIGH,
+ EC_TEMP_THRESH_HALT,
+
+ EC_TEMP_THRESH_COUNT
+};
+
+/* Thermal configuration for one temperature sensor. Temps are in degrees K.
+ * Zero values will be silently ignored by the thermal task.
+ */
+struct ec_thermal_config {
+ uint32_t temp_host[EC_TEMP_THRESH_COUNT]; /* levels of hotness */
+ uint32_t temp_fan_off; /* no active cooling needed */
+ uint32_t temp_fan_max; /* max active cooling needed */
+} __packed;
+
+/* Version 1 - get config for one sensor. */
+struct ec_params_thermal_get_threshold_v1 {
+ uint32_t sensor_num;
+} __packed;
+/* This returns a struct ec_thermal_config */
+
+/* Version 1 - set config for one sensor.
+ * Use read-modify-write for best results! */
+struct ec_params_thermal_set_threshold_v1 {
+ uint32_t sensor_num;
+ struct ec_thermal_config cfg;
+} __packed;
+/* This returns no data */
+
+/****************************************************************************/
+
/* Toggle automatic fan control */
#define EC_CMD_THERMAL_AUTO_FAN_CTRL 0x52
@@ -920,6 +1523,18 @@ struct ec_params_tmp006_set_calibration {
float b2;
} __packed;
+/* Read raw TMP006 data */
+#define EC_CMD_TMP006_GET_RAW 0x55
+
+struct ec_params_tmp006_get_raw {
+ uint8_t index;
+} __packed;
+
+struct ec_response_tmp006_get_raw {
+ int32_t t; /* In 1/100 K */
+ int32_t v; /* In nV */
+};
+
/*****************************************************************************/
/* MKBP - Matrix KeyBoard Protocol */
@@ -1118,11 +1733,41 @@ struct ec_params_switch_enable_backlight {
/* Enable/disable WLAN/Bluetooth */
#define EC_CMD_SWITCH_ENABLE_WIRELESS 0x91
+#define EC_VER_SWITCH_ENABLE_WIRELESS 1
-struct ec_params_switch_enable_wireless {
+/* Version 0 params; no response */
+struct ec_params_switch_enable_wireless_v0 {
uint8_t enabled;
} __packed;
+/* Version 1 params */
+struct ec_params_switch_enable_wireless_v1 {
+ /* Flags to enable now */
+ uint8_t now_flags;
+
+ /* Which flags to copy from now_flags */
+ uint8_t now_mask;
+
+ /*
+ * Flags to leave enabled in S3, if they're on at the S0->S3
+ * transition. (Other flags will be disabled by the S0->S3
+ * transition.)
+ */
+ uint8_t suspend_flags;
+
+ /* Which flags to copy from suspend_flags */
+ uint8_t suspend_mask;
+} __packed;
+
+/* Version 1 response */
+struct ec_response_switch_enable_wireless_v1 {
+ /* Flags to enable now */
+ uint8_t now_flags;
+
+ /* Flags to leave enabled in S3 */
+ uint8_t suspend_flags;
+} __packed;
+
/*****************************************************************************/
/* GPIO commands. Only available on EC if write protect has been disabled. */
@@ -1147,11 +1792,16 @@ struct ec_response_gpio_get {
/*****************************************************************************/
/* I2C commands. Only available when flash write protect is unlocked. */
+/*
+ * TODO(crosbug.com/p/23570): These commands are deprecated, and will be
+ * removed soon. Use EC_CMD_I2C_XFER instead.
+ */
+
/* Read I2C bus */
#define EC_CMD_I2C_READ 0x94
struct ec_params_i2c_read {
- uint16_t addr;
+ uint16_t addr; /* 8-bit address (7-bit shifted << 1) */
uint8_t read_size; /* Either 8 or 16. */
uint8_t port;
uint8_t offset;
@@ -1165,7 +1815,7 @@ struct ec_response_i2c_read {
struct ec_params_i2c_write {
uint16_t data;
- uint16_t addr;
+ uint16_t addr; /* 8-bit address (7-bit shifted << 1) */
uint8_t write_size; /* Either 8 or 16. */
uint8_t port;
uint8_t offset;
@@ -1174,11 +1824,20 @@ struct ec_params_i2c_write {
/*****************************************************************************/
/* Charge state commands. Only available when flash write protect unlocked. */
-/* Force charge state machine to stop in idle mode */
-#define EC_CMD_CHARGE_FORCE_IDLE 0x96
+/* Force charge state machine to stop charging the battery or force it to
+ * discharge the battery.
+ */
+#define EC_CMD_CHARGE_CONTROL 0x96
+#define EC_VER_CHARGE_CONTROL 1
-struct ec_params_force_idle {
- uint8_t enabled;
+enum ec_charge_control_mode {
+ CHARGE_CONTROL_NORMAL = 0,
+ CHARGE_CONTROL_IDLE,
+ CHARGE_CONTROL_DISCHARGE,
+};
+
+struct ec_params_charge_control {
+ uint32_t mode; /* enum charge_control_mode */
} __packed;
/*****************************************************************************/
@@ -1206,14 +1865,231 @@ struct ec_params_force_idle {
#define EC_CMD_BATTERY_CUT_OFF 0x99
/*****************************************************************************/
-/* Temporary debug commands. TODO: remove this crosbug.com/p/13849 */
+/* USB port mux control. */
/*
- * Dump charge state machine context.
- *
- * Response is a binary dump of charge state machine context.
+ * Switch USB mux or return to automatic switching.
+ */
+#define EC_CMD_USB_MUX 0x9a
+
+struct ec_params_usb_mux {
+ uint8_t mux;
+} __packed;
+
+/*****************************************************************************/
+/* LDOs / FETs control. */
+
+enum ec_ldo_state {
+ EC_LDO_STATE_OFF = 0, /* the LDO / FET is shut down */
+ EC_LDO_STATE_ON = 1, /* the LDO / FET is ON / providing power */
+};
+
+/*
+ * Switch on/off a LDO.
+ */
+#define EC_CMD_LDO_SET 0x9b
+
+struct ec_params_ldo_set {
+ uint8_t index;
+ uint8_t state;
+} __packed;
+
+/*
+ * Get LDO state.
+ */
+#define EC_CMD_LDO_GET 0x9c
+
+struct ec_params_ldo_get {
+ uint8_t index;
+} __packed;
+
+struct ec_response_ldo_get {
+ uint8_t state;
+} __packed;
+
+/*****************************************************************************/
+/* Power info. */
+
+/*
+ * Get power info.
+ */
+#define EC_CMD_POWER_INFO 0x9d
+
+struct ec_response_power_info {
+ uint32_t usb_dev_type;
+ uint16_t voltage_ac;
+ uint16_t voltage_system;
+ uint16_t current_system;
+ uint16_t usb_current_limit;
+} __packed;
+
+/*****************************************************************************/
+/* I2C passthru command */
+
+#define EC_CMD_I2C_PASSTHRU 0x9e
+
+/* Slave address is 10 (not 7) bit */
+#define EC_I2C_FLAG_10BIT (1 << 16)
+
+/* Read data; if not present, message is a write */
+#define EC_I2C_FLAG_READ (1 << 15)
+
+/* Mask for address */
+#define EC_I2C_ADDR_MASK 0x3ff
+
+#define EC_I2C_STATUS_NAK (1 << 0) /* Transfer was not acknowledged */
+#define EC_I2C_STATUS_TIMEOUT (1 << 1) /* Timeout during transfer */
+
+/* Any error */
+#define EC_I2C_STATUS_ERROR (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT)
+
+struct ec_params_i2c_passthru_msg {
+ uint16_t addr_flags; /* I2C slave address (7 or 10 bits) and flags */
+ uint16_t len; /* Number of bytes to read or write */
+} __packed;
+
+struct ec_params_i2c_passthru {
+ uint8_t port; /* I2C port number */
+ uint8_t num_msgs; /* Number of messages */
+ struct ec_params_i2c_passthru_msg msg[];
+ /* Data to write for all messages is concatenated here */
+} __packed;
+
+struct ec_response_i2c_passthru {
+ uint8_t i2c_status; /* Status flags (EC_I2C_STATUS_...) */
+ uint8_t num_msgs; /* Number of messages processed */
+ uint8_t data[]; /* Data read by messages concatenated here */
+} __packed;
+
+/*****************************************************************************/
+/* Power button hang detect */
+
+#define EC_CMD_HANG_DETECT 0x9f
+
+/* Reasons to start hang detection timer */
+/* Power button pressed */
+#define EC_HANG_START_ON_POWER_PRESS (1 << 0)
+
+/* Lid closed */
+#define EC_HANG_START_ON_LID_CLOSE (1 << 1)
+
+ /* Lid opened */
+#define EC_HANG_START_ON_LID_OPEN (1 << 2)
+
+/* Start of AP S3->S0 transition (booting or resuming from suspend) */
+#define EC_HANG_START_ON_RESUME (1 << 3)
+
+/* Reasons to cancel hang detection */
+
+/* Power button released */
+#define EC_HANG_STOP_ON_POWER_RELEASE (1 << 8)
+
+/* Any host command from AP received */
+#define EC_HANG_STOP_ON_HOST_COMMAND (1 << 9)
+
+/* Stop on end of AP S0->S3 transition (suspending or shutting down) */
+#define EC_HANG_STOP_ON_SUSPEND (1 << 10)
+
+/*
+ * If this flag is set, all the other fields are ignored, and the hang detect
+ * timer is started. This provides the AP a way to start the hang timer
+ * without reconfiguring any of the other hang detect settings. Note that
+ * you must previously have configured the timeouts.
+ */
+#define EC_HANG_START_NOW (1 << 30)
+
+/*
+ * If this flag is set, all the other fields are ignored (including
+ * EC_HANG_START_NOW). This provides the AP a way to stop the hang timer
+ * without reconfiguring any of the other hang detect settings.
*/
-#define EC_CMD_CHARGE_DUMP 0xa0
+#define EC_HANG_STOP_NOW (1 << 31)
+
+struct ec_params_hang_detect {
+ /* Flags; see EC_HANG_* */
+ uint32_t flags;
+
+ /* Timeout in msec before generating host event, if enabled */
+ uint16_t host_event_timeout_msec;
+
+ /* Timeout in msec before generating warm reboot, if enabled */
+ uint16_t warm_reboot_timeout_msec;
+} __packed;
+
+/*****************************************************************************/
+/* Commands for battery charging */
+
+/*
+ * This is the single catch-all host command to exchange data regarding the
+ * charge state machine (v2 and up).
+ */
+#define EC_CMD_CHARGE_STATE 0xa0
+
+/* Subcommands for this host command */
+enum charge_state_command {
+ CHARGE_STATE_CMD_GET_STATE,
+ CHARGE_STATE_CMD_GET_PARAM,
+ CHARGE_STATE_CMD_SET_PARAM,
+ CHARGE_STATE_NUM_CMDS
+};
+
+/*
+ * Known param numbers are defined here. Ranges are reserved for board-specific
+ * params, which are handled by the particular implementations.
+ */
+enum charge_state_params {
+ CS_PARAM_CHG_VOLTAGE, /* charger voltage limit */
+ CS_PARAM_CHG_CURRENT, /* charger current limit */
+ CS_PARAM_CHG_INPUT_CURRENT, /* charger input current limit */
+ CS_PARAM_CHG_STATUS, /* charger-specific status */
+ CS_PARAM_CHG_OPTION, /* charger-specific options */
+ /* How many so far? */
+ CS_NUM_BASE_PARAMS,
+
+ /* Range for CONFIG_CHARGER_PROFILE_OVERRIDE params */
+ CS_PARAM_CUSTOM_PROFILE_MIN = 0x10000,
+ CS_PARAM_CUSTOM_PROFILE_MAX = 0x1ffff,
+
+ /* Other custom param ranges go here... */
+};
+
+struct ec_params_charge_state {
+ uint8_t cmd; /* enum charge_state_command */
+ union {
+ struct {
+ /* no args */
+ } get_state;
+
+ struct {
+ uint32_t param; /* enum charge_state_param */
+ } get_param;
+
+ struct {
+ uint32_t param; /* param to set */
+ uint32_t value; /* value to set */
+ } set_param;
+ };
+} __packed;
+
+struct ec_response_charge_state {
+ union {
+ struct {
+ int ac;
+ int chg_voltage;
+ int chg_current;
+ int chg_input_current;
+ int batt_state_of_charge;
+ } get_state;
+
+ struct {
+ uint32_t value;
+ } get_param;
+ struct {
+ /* no return values */
+ } set_param;
+ };
+} __packed;
+
/*
* Set maximum battery charging current.
@@ -1221,15 +2097,59 @@ struct ec_params_force_idle {
#define EC_CMD_CHARGE_CURRENT_LIMIT 0xa1
struct ec_params_current_limit {
- uint32_t limit;
+ uint32_t limit; /* in mA */
+} __packed;
+
+/*
+ * Set maximum external power current.
+ */
+#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2
+
+struct ec_params_ext_power_current_limit {
+ uint32_t limit; /* in mA */
+} __packed;
+
+/*****************************************************************************/
+/* Smart battery pass-through */
+
+/* Get / Set 16-bit smart battery registers */
+#define EC_CMD_SB_READ_WORD 0xb0
+#define EC_CMD_SB_WRITE_WORD 0xb1
+
+/* Get / Set string smart battery parameters
+ * formatted as SMBUS "block".
+ */
+#define EC_CMD_SB_READ_BLOCK 0xb2
+#define EC_CMD_SB_WRITE_BLOCK 0xb3
+
+struct ec_params_sb_rd {
+ uint8_t reg;
+} __packed;
+
+struct ec_response_sb_rd_word {
+ uint16_t value;
+} __packed;
+
+struct ec_params_sb_wr_word {
+ uint8_t reg;
+ uint16_t value;
+} __packed;
+
+struct ec_response_sb_rd_block {
+ uint8_t data[32];
+} __packed;
+
+struct ec_params_sb_wr_block {
+ uint8_t reg;
+ uint16_t data[32];
} __packed;
/*****************************************************************************/
/* System commands */
/*
- * TODO: this is a confusing name, since it doesn't necessarily reboot the EC.
- * Rename to "set image" or something similar.
+ * TODO(crosbug.com/p/23747): This is a confusing name, since it doesn't
+ * necessarily reboot the EC. Rename to "image" or something similar?
*/
#define EC_CMD_REBOOT_EC 0xd2
@@ -1308,6 +2228,7 @@ struct ec_params_reboot_ec {
#define EC_CMD_ACPI_QUERY_EVENT 0x84
/* Valid addresses in ACPI memory space, for read/write commands */
+
/* Memory space version; set to EC_ACPI_MEM_VERSION_CURRENT */
#define EC_ACPI_MEM_VERSION 0x00
/*
@@ -1317,8 +2238,60 @@ struct ec_params_reboot_ec {
#define EC_ACPI_MEM_TEST 0x01
/* Test compliment; writes here are ignored. */
#define EC_ACPI_MEM_TEST_COMPLIMENT 0x02
+
/* Keyboard backlight brightness percent (0 - 100) */
#define EC_ACPI_MEM_KEYBOARD_BACKLIGHT 0x03
+/* DPTF Target Fan Duty (0-100, 0xff for auto/none) */
+#define EC_ACPI_MEM_FAN_DUTY 0x04
+
+/*
+ * DPTF temp thresholds. Any of the EC's temp sensors can have up to two
+ * independent thresholds attached to them. The current value of the ID
+ * register determines which sensor is affected by the THRESHOLD and COMMIT
+ * registers. The THRESHOLD register uses the same EC_TEMP_SENSOR_OFFSET scheme
+ * as the memory-mapped sensors. The COMMIT register applies those settings.
+ *
+ * The spec does not mandate any way to read back the threshold settings
+ * themselves, but when a threshold is crossed the AP needs a way to determine
+ * which sensor(s) are responsible. Each reading of the ID register clears and
+ * returns one sensor ID that has crossed one of its threshold (in either
+ * direction) since the last read. A value of 0xFF means "no new thresholds
+ * have tripped". Setting or enabling the thresholds for a sensor will clear
+ * the unread event count for that sensor.
+ */
+#define EC_ACPI_MEM_TEMP_ID 0x05
+#define EC_ACPI_MEM_TEMP_THRESHOLD 0x06
+#define EC_ACPI_MEM_TEMP_COMMIT 0x07
+/*
+ * Here are the bits for the COMMIT register:
+ * bit 0 selects the threshold index for the chosen sensor (0/1)
+ * bit 1 enables/disables the selected threshold (0 = off, 1 = on)
+ * Each write to the commit register affects one threshold.
+ */
+#define EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK (1 << 0)
+#define EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK (1 << 1)
+/*
+ * Example:
+ *
+ * Set the thresholds for sensor 2 to 50 C and 60 C:
+ * write 2 to [0x05] -- select temp sensor 2
+ * write 0x7b to [0x06] -- C_TO_K(50) - EC_TEMP_SENSOR_OFFSET
+ * write 0x2 to [0x07] -- enable threshold 0 with this value
+ * write 0x85 to [0x06] -- C_TO_K(60) - EC_TEMP_SENSOR_OFFSET
+ * write 0x3 to [0x07] -- enable threshold 1 with this value
+ *
+ * Disable the 60 C threshold, leaving the 50 C threshold unchanged:
+ * write 2 to [0x05] -- select temp sensor 2
+ * write 0x1 to [0x07] -- disable threshold 1
+ */
+
+/* DPTF battery charging current limit */
+#define EC_ACPI_MEM_CHARGING_LIMIT 0x08
+
+/* Charging limit is specified in 64 mA steps */
+#define EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA 64
+/* Value to disable DPTF battery charging limit */
+#define EC_ACPI_MEM_CHARGING_LIMIT_DISABLED 0xff
/* Current version of ACPI memory address space */
#define EC_ACPI_MEM_VERSION_CURRENT 1
@@ -1360,10 +2333,21 @@ struct ec_params_reboot_ec {
* Header bytes greater than this indicate a later version. For example,
* EC_CMD_VERSION0 + 1 means we are using version 1.
*
- * The old EC interface must not use commands 0dc or higher.
+ * The old EC interface must not use commands 0xdc or higher.
*/
#define EC_CMD_VERSION0 0xdc
#endif /* !__ACPI__ */
+/*****************************************************************************/
+/*
+ * Deprecated constants. These constants have been renamed for clarity. The
+ * meaning and size has not changed. Programs that use the old names should
+ * switch to the new names soon, as the old names may not be carried forward
+ * forever.
+ */
+#define EC_HOST_PARAM_SIZE EC_PROTO2_MAX_PARAM_SIZE
+#define EC_LPC_ADDR_OLD_PARAM EC_HOST_CMD_REGION1
+#define EC_OLD_PARAM_SIZE EC_HOST_CMD_REGION_SIZE
+
#endif /* __CROS_EC_COMMANDS_H */
diff --git a/include/linux/mfd/ipaq-micro.h b/include/linux/mfd/ipaq-micro.h
new file mode 100644
index 000000000000..5c4d29f6674f
--- /dev/null
+++ b/include/linux/mfd/ipaq-micro.h
@@ -0,0 +1,148 @@
+/*
+ * Header file for the compaq Micro MFD
+ */
+
+#ifndef _MFD_IPAQ_MICRO_H_
+#define _MFD_IPAQ_MICRO_H_
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+
+#define TX_BUF_SIZE 32
+#define RX_BUF_SIZE 16
+#define CHAR_SOF 0x02
+
+/*
+ * These are the different messages that can be sent to the microcontroller
+ * to control various aspects.
+ */
+#define MSG_VERSION 0x0
+#define MSG_KEYBOARD 0x2
+#define MSG_TOUCHSCREEN 0x3
+#define MSG_EEPROM_READ 0x4
+#define MSG_EEPROM_WRITE 0x5
+#define MSG_THERMAL_SENSOR 0x6
+#define MSG_NOTIFY_LED 0x8
+#define MSG_BATTERY 0x9
+#define MSG_SPI_READ 0xb
+#define MSG_SPI_WRITE 0xc
+#define MSG_BACKLIGHT 0xd /* H3600 only */
+#define MSG_CODEC_CTRL 0xe /* H3100 only */
+#define MSG_DISPLAY_CTRL 0xf /* H3100 only */
+
+/* state of receiver parser */
+enum rx_state {
+ STATE_SOF = 0, /* Next byte should be start of frame */
+ STATE_ID, /* Next byte is ID & message length */
+ STATE_DATA, /* Next byte is a data byte */
+ STATE_CHKSUM /* Next byte should be checksum */
+};
+
+/**
+ * struct ipaq_micro_txdev - TX state
+ * @len: length of message in TX buffer
+ * @index: current index into TX buffer
+ * @buf: TX buffer
+ */
+struct ipaq_micro_txdev {
+ u8 len;
+ u8 index;
+ u8 buf[TX_BUF_SIZE];
+};
+
+/**
+ * struct ipaq_micro_rxdev - RX state
+ * @state: context of RX state machine
+ * @chksum: calculated checksum
+ * @id: message ID from packet
+ * @len: RX buffer length
+ * @index: RX buffer index
+ * @buf: RX buffer
+ */
+struct ipaq_micro_rxdev {
+ enum rx_state state;
+ unsigned char chksum;
+ u8 id;
+ unsigned int len;
+ unsigned int index;
+ u8 buf[RX_BUF_SIZE];
+};
+
+/**
+ * struct ipaq_micro_msg - message to the iPAQ microcontroller
+ * @id: 4-bit ID of the message
+ * @tx_len: length of TX data
+ * @tx_data: TX data to send
+ * @rx_len: length of receieved RX data
+ * @rx_data: RX data to recieve
+ * @ack: a completion that will be completed when RX is complete
+ * @node: list node if message gets queued
+ */
+struct ipaq_micro_msg {
+ u8 id;
+ u8 tx_len;
+ u8 tx_data[TX_BUF_SIZE];
+ u8 rx_len;
+ u8 rx_data[RX_BUF_SIZE];
+ struct completion ack;
+ struct list_head node;
+};
+
+/**
+ * struct ipaq_micro - iPAQ microcontroller state
+ * @dev: corresponding platform device
+ * @base: virtual memory base for underlying serial device
+ * @sdlc: virtual memory base for Synchronous Data Link Controller
+ * @version: version string
+ * @tx: TX state
+ * @rx: RX state
+ * @lock: lock for this state container
+ * @msg: current message
+ * @queue: message queue
+ * @key: callback for asynchronous key events
+ * @key_data: data to pass along with key events
+ * @ts: callback for asynchronous touchscreen events
+ * @ts_data: data to pass along with key events
+ */
+struct ipaq_micro {
+ struct device *dev;
+ void __iomem *base;
+ void __iomem *sdlc;
+ char version[5];
+ struct ipaq_micro_txdev tx; /* transmit ISR state */
+ struct ipaq_micro_rxdev rx; /* receive ISR state */
+ spinlock_t lock;
+ struct ipaq_micro_msg *msg;
+ struct list_head queue;
+ void (*key) (void *data, int len, unsigned char *rxdata);
+ void *key_data;
+ void (*ts) (void *data, int len, unsigned char *rxdata);
+ void *ts_data;
+};
+
+extern int
+ipaq_micro_tx_msg(struct ipaq_micro *micro, struct ipaq_micro_msg *msg);
+
+static inline int
+ipaq_micro_tx_msg_sync(struct ipaq_micro *micro,
+ struct ipaq_micro_msg *msg)
+{
+ int ret;
+
+ init_completion(&msg->ack);
+ ret = ipaq_micro_tx_msg(micro, msg);
+ wait_for_completion(&msg->ack);
+
+ return ret;
+}
+
+static inline int
+ipaq_micro_tx_msg_async(struct ipaq_micro *micro,
+ struct ipaq_micro_msg *msg)
+{
+ init_completion(&msg->ack);
+ return ipaq_micro_tx_msg(micro, msg);
+}
+
+#endif /* _MFD_IPAQ_MICRO_H_ */
diff --git a/include/linux/mfd/kempld.h b/include/linux/mfd/kempld.h
index b911ef3add03..26e0b469e567 100644
--- a/include/linux/mfd/kempld.h
+++ b/include/linux/mfd/kempld.h
@@ -51,6 +51,8 @@
#define KEMPLD_TYPE_DEBUG 0x1
#define KEMPLD_TYPE_CUSTOM 0x2
+#define KEMPLD_VERSION_LEN 10
+
/**
* struct kempld_info - PLD device information structure
* @major: PLD major revision
@@ -60,6 +62,7 @@
* @type: PLD type
* @spec_major: PLD FW specification major revision
* @spec_minor: PLD FW specification minor revision
+ * @version: PLD version string
*/
struct kempld_info {
unsigned int major;
@@ -69,6 +72,7 @@ struct kempld_info {
unsigned int type;
unsigned int spec_major;
unsigned int spec_minor;
+ char version[KEMPLD_VERSION_LEN];
};
/**
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index a326c850f046..d63b1d309106 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -117,10 +117,6 @@ struct mc13xxx_led_platform_data {
#define MAX_LED_CONTROL_REGS 6
-struct mc13xxx_leds_platform_data {
- struct mc13xxx_led_platform_data *led;
- int num_leds;
-
/* MC13783 LED Control 0 */
#define MC13783_LED_C0_ENABLE (1 << 0)
#define MC13783_LED_C0_TRIODE_MD (1 << 7)
@@ -169,10 +165,13 @@ struct mc13xxx_leds_platform_data {
/* MC34708 LED Control 0 */
#define MC34708_LED_C0_CURRENT_R(x) (((x) & 0x3) << 9)
#define MC34708_LED_C0_CURRENT_G(x) (((x) & 0x3) << 21)
+
+struct mc13xxx_leds_platform_data {
+ struct mc13xxx_led_platform_data *led;
+ int num_leds;
u32 led_control[MAX_LED_CONTROL_REGS];
};
-struct mc13xxx_buttons_platform_data {
#define MC13783_BUTTON_DBNC_0MS 0
#define MC13783_BUTTON_DBNC_30MS 1
#define MC13783_BUTTON_DBNC_150MS 2
@@ -180,6 +179,8 @@ struct mc13xxx_buttons_platform_data {
#define MC13783_BUTTON_ENABLE (1 << 2)
#define MC13783_BUTTON_POL_INVERT (1 << 3)
#define MC13783_BUTTON_RESET_EN (1 << 4)
+
+struct mc13xxx_buttons_platform_data {
int b1on_flags;
unsigned short b1on_key;
int b2on_flags;
@@ -188,14 +189,14 @@ struct mc13xxx_buttons_platform_data {
unsigned short b3on_key;
};
+#define MC13783_TS_ATO_FIRST false
+#define MC13783_TS_ATO_EACH true
+
struct mc13xxx_ts_platform_data {
/* Delay between Touchscreen polarization and ADC Conversion.
* Given in clock ticks of a 32 kHz clock which gives a granularity of
* about 30.5ms */
u8 ato;
-
-#define MC13783_TS_ATO_FIRST false
-#define MC13783_TS_ATO_EACH true
/* Use the ATO delay only for the first conversion or for each one */
bool atox;
};
@@ -210,11 +211,12 @@ struct mc13xxx_codec_platform_data {
enum mc13783_ssi_port dac_ssi_port;
};
-struct mc13xxx_platform_data {
-#define MC13XXX_USE_TOUCHSCREEN (1 << 0)
+#define MC13XXX_USE_TOUCHSCREEN (1 << 0)
#define MC13XXX_USE_CODEC (1 << 1)
#define MC13XXX_USE_ADC (1 << 2)
#define MC13XXX_USE_RTC (1 << 3)
+
+struct mc13xxx_platform_data {
unsigned int flags;
struct mc13xxx_regulator_platform_data regulators;
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index b8f87b704409..3420e09e2e20 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -482,10 +482,10 @@ enum usb_irq_events {
/* helper macro to get correct slave number */
#define PALMAS_BASE_TO_SLAVE(x) ((x >> 8) - 1)
-#define PALMAS_BASE_TO_REG(x, y) ((x & 0xff) + y)
+#define PALMAS_BASE_TO_REG(x, y) ((x & 0xFF) + y)
/* Base addresses of IP blocks in Palmas */
-#define PALMAS_SMPS_DVS_BASE 0x20
+#define PALMAS_SMPS_DVS_BASE 0x020
#define PALMAS_RTC_BASE 0x100
#define PALMAS_VALIDITY_BASE 0x118
#define PALMAS_SMPS_BASE 0x120
@@ -504,19 +504,19 @@ enum usb_irq_events {
#define PALMAS_TRIM_GPADC_BASE 0x3CD
/* Registers for function RTC */
-#define PALMAS_SECONDS_REG 0x0
-#define PALMAS_MINUTES_REG 0x1
-#define PALMAS_HOURS_REG 0x2
-#define PALMAS_DAYS_REG 0x3
-#define PALMAS_MONTHS_REG 0x4
-#define PALMAS_YEARS_REG 0x5
-#define PALMAS_WEEKS_REG 0x6
-#define PALMAS_ALARM_SECONDS_REG 0x8
-#define PALMAS_ALARM_MINUTES_REG 0x9
-#define PALMAS_ALARM_HOURS_REG 0xA
-#define PALMAS_ALARM_DAYS_REG 0xB
-#define PALMAS_ALARM_MONTHS_REG 0xC
-#define PALMAS_ALARM_YEARS_REG 0xD
+#define PALMAS_SECONDS_REG 0x00
+#define PALMAS_MINUTES_REG 0x01
+#define PALMAS_HOURS_REG 0x02
+#define PALMAS_DAYS_REG 0x03
+#define PALMAS_MONTHS_REG 0x04
+#define PALMAS_YEARS_REG 0x05
+#define PALMAS_WEEKS_REG 0x06
+#define PALMAS_ALARM_SECONDS_REG 0x08
+#define PALMAS_ALARM_MINUTES_REG 0x09
+#define PALMAS_ALARM_HOURS_REG 0x0A
+#define PALMAS_ALARM_DAYS_REG 0x0B
+#define PALMAS_ALARM_MONTHS_REG 0x0C
+#define PALMAS_ALARM_YEARS_REG 0x0D
#define PALMAS_RTC_CTRL_REG 0x10
#define PALMAS_RTC_STATUS_REG 0x11
#define PALMAS_RTC_INTERRUPTS_REG 0x12
@@ -527,201 +527,201 @@ enum usb_irq_events {
/* Bit definitions for SECONDS_REG */
#define PALMAS_SECONDS_REG_SEC1_MASK 0x70
-#define PALMAS_SECONDS_REG_SEC1_SHIFT 4
-#define PALMAS_SECONDS_REG_SEC0_MASK 0x0f
-#define PALMAS_SECONDS_REG_SEC0_SHIFT 0
+#define PALMAS_SECONDS_REG_SEC1_SHIFT 0x04
+#define PALMAS_SECONDS_REG_SEC0_MASK 0x0F
+#define PALMAS_SECONDS_REG_SEC0_SHIFT 0x00
/* Bit definitions for MINUTES_REG */
#define PALMAS_MINUTES_REG_MIN1_MASK 0x70
-#define PALMAS_MINUTES_REG_MIN1_SHIFT 4
-#define PALMAS_MINUTES_REG_MIN0_MASK 0x0f
-#define PALMAS_MINUTES_REG_MIN0_SHIFT 0
+#define PALMAS_MINUTES_REG_MIN1_SHIFT 0x04
+#define PALMAS_MINUTES_REG_MIN0_MASK 0x0F
+#define PALMAS_MINUTES_REG_MIN0_SHIFT 0x00
/* Bit definitions for HOURS_REG */
#define PALMAS_HOURS_REG_PM_NAM 0x80
-#define PALMAS_HOURS_REG_PM_NAM_SHIFT 7
+#define PALMAS_HOURS_REG_PM_NAM_SHIFT 0x07
#define PALMAS_HOURS_REG_HOUR1_MASK 0x30
-#define PALMAS_HOURS_REG_HOUR1_SHIFT 4
-#define PALMAS_HOURS_REG_HOUR0_MASK 0x0f
-#define PALMAS_HOURS_REG_HOUR0_SHIFT 0
+#define PALMAS_HOURS_REG_HOUR1_SHIFT 0x04
+#define PALMAS_HOURS_REG_HOUR0_MASK 0x0F
+#define PALMAS_HOURS_REG_HOUR0_SHIFT 0x00
/* Bit definitions for DAYS_REG */
#define PALMAS_DAYS_REG_DAY1_MASK 0x30
-#define PALMAS_DAYS_REG_DAY1_SHIFT 4
-#define PALMAS_DAYS_REG_DAY0_MASK 0x0f
-#define PALMAS_DAYS_REG_DAY0_SHIFT 0
+#define PALMAS_DAYS_REG_DAY1_SHIFT 0x04
+#define PALMAS_DAYS_REG_DAY0_MASK 0x0F
+#define PALMAS_DAYS_REG_DAY0_SHIFT 0x00
/* Bit definitions for MONTHS_REG */
#define PALMAS_MONTHS_REG_MONTH1 0x10
-#define PALMAS_MONTHS_REG_MONTH1_SHIFT 4
-#define PALMAS_MONTHS_REG_MONTH0_MASK 0x0f
-#define PALMAS_MONTHS_REG_MONTH0_SHIFT 0
+#define PALMAS_MONTHS_REG_MONTH1_SHIFT 0x04
+#define PALMAS_MONTHS_REG_MONTH0_MASK 0x0F
+#define PALMAS_MONTHS_REG_MONTH0_SHIFT 0x00
/* Bit definitions for YEARS_REG */
#define PALMAS_YEARS_REG_YEAR1_MASK 0xf0
-#define PALMAS_YEARS_REG_YEAR1_SHIFT 4
-#define PALMAS_YEARS_REG_YEAR0_MASK 0x0f
-#define PALMAS_YEARS_REG_YEAR0_SHIFT 0
+#define PALMAS_YEARS_REG_YEAR1_SHIFT 0x04
+#define PALMAS_YEARS_REG_YEAR0_MASK 0x0F
+#define PALMAS_YEARS_REG_YEAR0_SHIFT 0x00
/* Bit definitions for WEEKS_REG */
#define PALMAS_WEEKS_REG_WEEK_MASK 0x07
-#define PALMAS_WEEKS_REG_WEEK_SHIFT 0
+#define PALMAS_WEEKS_REG_WEEK_SHIFT 0x00
/* Bit definitions for ALARM_SECONDS_REG */
#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC1_MASK 0x70
-#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC1_SHIFT 4
-#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_MASK 0x0f
-#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_SHIFT 0
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC1_SHIFT 0x04
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_MASK 0x0F
+#define PALMAS_ALARM_SECONDS_REG_ALARM_SEC0_SHIFT 0x00
/* Bit definitions for ALARM_MINUTES_REG */
#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN1_MASK 0x70
-#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN1_SHIFT 4
-#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_MASK 0x0f
-#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_SHIFT 0
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN1_SHIFT 0x04
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_MASK 0x0F
+#define PALMAS_ALARM_MINUTES_REG_ALARM_MIN0_SHIFT 0x00
/* Bit definitions for ALARM_HOURS_REG */
#define PALMAS_ALARM_HOURS_REG_ALARM_PM_NAM 0x80
-#define PALMAS_ALARM_HOURS_REG_ALARM_PM_NAM_SHIFT 7
+#define PALMAS_ALARM_HOURS_REG_ALARM_PM_NAM_SHIFT 0x07
#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR1_MASK 0x30
-#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR1_SHIFT 4
-#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_MASK 0x0f
-#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_SHIFT 0
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR1_SHIFT 0x04
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_MASK 0x0F
+#define PALMAS_ALARM_HOURS_REG_ALARM_HOUR0_SHIFT 0x00
/* Bit definitions for ALARM_DAYS_REG */
#define PALMAS_ALARM_DAYS_REG_ALARM_DAY1_MASK 0x30
-#define PALMAS_ALARM_DAYS_REG_ALARM_DAY1_SHIFT 4
-#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_MASK 0x0f
-#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_SHIFT 0
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY1_SHIFT 0x04
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_MASK 0x0F
+#define PALMAS_ALARM_DAYS_REG_ALARM_DAY0_SHIFT 0x00
/* Bit definitions for ALARM_MONTHS_REG */
#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH1 0x10
-#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH1_SHIFT 4
-#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_MASK 0x0f
-#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_SHIFT 0
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH1_SHIFT 0x04
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_MASK 0x0F
+#define PALMAS_ALARM_MONTHS_REG_ALARM_MONTH0_SHIFT 0x00
/* Bit definitions for ALARM_YEARS_REG */
#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR1_MASK 0xf0
-#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR1_SHIFT 4
-#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_MASK 0x0f
-#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_SHIFT 0
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR1_SHIFT 0x04
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_MASK 0x0F
+#define PALMAS_ALARM_YEARS_REG_ALARM_YEAR0_SHIFT 0x00
/* Bit definitions for RTC_CTRL_REG */
#define PALMAS_RTC_CTRL_REG_RTC_V_OPT 0x80
-#define PALMAS_RTC_CTRL_REG_RTC_V_OPT_SHIFT 7
+#define PALMAS_RTC_CTRL_REG_RTC_V_OPT_SHIFT 0x07
#define PALMAS_RTC_CTRL_REG_GET_TIME 0x40
-#define PALMAS_RTC_CTRL_REG_GET_TIME_SHIFT 6
+#define PALMAS_RTC_CTRL_REG_GET_TIME_SHIFT 0x06
#define PALMAS_RTC_CTRL_REG_SET_32_COUNTER 0x20
-#define PALMAS_RTC_CTRL_REG_SET_32_COUNTER_SHIFT 5
+#define PALMAS_RTC_CTRL_REG_SET_32_COUNTER_SHIFT 0x05
#define PALMAS_RTC_CTRL_REG_TEST_MODE 0x10
-#define PALMAS_RTC_CTRL_REG_TEST_MODE_SHIFT 4
+#define PALMAS_RTC_CTRL_REG_TEST_MODE_SHIFT 0x04
#define PALMAS_RTC_CTRL_REG_MODE_12_24 0x08
-#define PALMAS_RTC_CTRL_REG_MODE_12_24_SHIFT 3
+#define PALMAS_RTC_CTRL_REG_MODE_12_24_SHIFT 0x03
#define PALMAS_RTC_CTRL_REG_AUTO_COMP 0x04
-#define PALMAS_RTC_CTRL_REG_AUTO_COMP_SHIFT 2
+#define PALMAS_RTC_CTRL_REG_AUTO_COMP_SHIFT 0x02
#define PALMAS_RTC_CTRL_REG_ROUND_30S 0x02
-#define PALMAS_RTC_CTRL_REG_ROUND_30S_SHIFT 1
+#define PALMAS_RTC_CTRL_REG_ROUND_30S_SHIFT 0x01
#define PALMAS_RTC_CTRL_REG_STOP_RTC 0x01
-#define PALMAS_RTC_CTRL_REG_STOP_RTC_SHIFT 0
+#define PALMAS_RTC_CTRL_REG_STOP_RTC_SHIFT 0x00
/* Bit definitions for RTC_STATUS_REG */
#define PALMAS_RTC_STATUS_REG_POWER_UP 0x80
-#define PALMAS_RTC_STATUS_REG_POWER_UP_SHIFT 7
+#define PALMAS_RTC_STATUS_REG_POWER_UP_SHIFT 0x07
#define PALMAS_RTC_STATUS_REG_ALARM 0x40
-#define PALMAS_RTC_STATUS_REG_ALARM_SHIFT 6
+#define PALMAS_RTC_STATUS_REG_ALARM_SHIFT 0x06
#define PALMAS_RTC_STATUS_REG_EVENT_1D 0x20
-#define PALMAS_RTC_STATUS_REG_EVENT_1D_SHIFT 5
+#define PALMAS_RTC_STATUS_REG_EVENT_1D_SHIFT 0x05
#define PALMAS_RTC_STATUS_REG_EVENT_1H 0x10
-#define PALMAS_RTC_STATUS_REG_EVENT_1H_SHIFT 4
+#define PALMAS_RTC_STATUS_REG_EVENT_1H_SHIFT 0x04
#define PALMAS_RTC_STATUS_REG_EVENT_1M 0x08
-#define PALMAS_RTC_STATUS_REG_EVENT_1M_SHIFT 3
+#define PALMAS_RTC_STATUS_REG_EVENT_1M_SHIFT 0x03
#define PALMAS_RTC_STATUS_REG_EVENT_1S 0x04
-#define PALMAS_RTC_STATUS_REG_EVENT_1S_SHIFT 2
+#define PALMAS_RTC_STATUS_REG_EVENT_1S_SHIFT 0x02
#define PALMAS_RTC_STATUS_REG_RUN 0x02
-#define PALMAS_RTC_STATUS_REG_RUN_SHIFT 1
+#define PALMAS_RTC_STATUS_REG_RUN_SHIFT 0x01
/* Bit definitions for RTC_INTERRUPTS_REG */
#define PALMAS_RTC_INTERRUPTS_REG_IT_SLEEP_MASK_EN 0x10
-#define PALMAS_RTC_INTERRUPTS_REG_IT_SLEEP_MASK_EN_SHIFT 4
+#define PALMAS_RTC_INTERRUPTS_REG_IT_SLEEP_MASK_EN_SHIFT 0x04
#define PALMAS_RTC_INTERRUPTS_REG_IT_ALARM 0x08
-#define PALMAS_RTC_INTERRUPTS_REG_IT_ALARM_SHIFT 3
+#define PALMAS_RTC_INTERRUPTS_REG_IT_ALARM_SHIFT 0x03
#define PALMAS_RTC_INTERRUPTS_REG_IT_TIMER 0x04
-#define PALMAS_RTC_INTERRUPTS_REG_IT_TIMER_SHIFT 2
+#define PALMAS_RTC_INTERRUPTS_REG_IT_TIMER_SHIFT 0x02
#define PALMAS_RTC_INTERRUPTS_REG_EVERY_MASK 0x03
-#define PALMAS_RTC_INTERRUPTS_REG_EVERY_SHIFT 0
+#define PALMAS_RTC_INTERRUPTS_REG_EVERY_SHIFT 0x00
/* Bit definitions for RTC_COMP_LSB_REG */
-#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_MASK 0xff
-#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_SHIFT 0
+#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_MASK 0xFF
+#define PALMAS_RTC_COMP_LSB_REG_RTC_COMP_LSB_SHIFT 0x00
/* Bit definitions for RTC_COMP_MSB_REG */
-#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_MASK 0xff
-#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_SHIFT 0
+#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_MASK 0xFF
+#define PALMAS_RTC_COMP_MSB_REG_RTC_COMP_MSB_SHIFT 0x00
/* Bit definitions for RTC_RES_PROG_REG */
-#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_MASK 0x3f
-#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_SHIFT 0
+#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_MASK 0x3F
+#define PALMAS_RTC_RES_PROG_REG_SW_RES_PROG_SHIFT 0x00
/* Bit definitions for RTC_RESET_STATUS_REG */
#define PALMAS_RTC_RESET_STATUS_REG_RESET_STATUS 0x01
-#define PALMAS_RTC_RESET_STATUS_REG_RESET_STATUS_SHIFT 0
+#define PALMAS_RTC_RESET_STATUS_REG_RESET_STATUS_SHIFT 0x00
/* Registers for function BACKUP */
-#define PALMAS_BACKUP0 0x0
-#define PALMAS_BACKUP1 0x1
-#define PALMAS_BACKUP2 0x2
-#define PALMAS_BACKUP3 0x3
-#define PALMAS_BACKUP4 0x4
-#define PALMAS_BACKUP5 0x5
-#define PALMAS_BACKUP6 0x6
-#define PALMAS_BACKUP7 0x7
+#define PALMAS_BACKUP0 0x00
+#define PALMAS_BACKUP1 0x01
+#define PALMAS_BACKUP2 0x02
+#define PALMAS_BACKUP3 0x03
+#define PALMAS_BACKUP4 0x04
+#define PALMAS_BACKUP5 0x05
+#define PALMAS_BACKUP6 0x06
+#define PALMAS_BACKUP7 0x07
/* Bit definitions for BACKUP0 */
-#define PALMAS_BACKUP0_BACKUP_MASK 0xff
-#define PALMAS_BACKUP0_BACKUP_SHIFT 0
+#define PALMAS_BACKUP0_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP0_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP1 */
-#define PALMAS_BACKUP1_BACKUP_MASK 0xff
-#define PALMAS_BACKUP1_BACKUP_SHIFT 0
+#define PALMAS_BACKUP1_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP1_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP2 */
-#define PALMAS_BACKUP2_BACKUP_MASK 0xff
-#define PALMAS_BACKUP2_BACKUP_SHIFT 0
+#define PALMAS_BACKUP2_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP2_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP3 */
-#define PALMAS_BACKUP3_BACKUP_MASK 0xff
-#define PALMAS_BACKUP3_BACKUP_SHIFT 0
+#define PALMAS_BACKUP3_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP3_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP4 */
-#define PALMAS_BACKUP4_BACKUP_MASK 0xff
-#define PALMAS_BACKUP4_BACKUP_SHIFT 0
+#define PALMAS_BACKUP4_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP4_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP5 */
-#define PALMAS_BACKUP5_BACKUP_MASK 0xff
-#define PALMAS_BACKUP5_BACKUP_SHIFT 0
+#define PALMAS_BACKUP5_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP5_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP6 */
-#define PALMAS_BACKUP6_BACKUP_MASK 0xff
-#define PALMAS_BACKUP6_BACKUP_SHIFT 0
+#define PALMAS_BACKUP6_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP6_BACKUP_SHIFT 0x00
/* Bit definitions for BACKUP7 */
-#define PALMAS_BACKUP7_BACKUP_MASK 0xff
-#define PALMAS_BACKUP7_BACKUP_SHIFT 0
+#define PALMAS_BACKUP7_BACKUP_MASK 0xFF
+#define PALMAS_BACKUP7_BACKUP_SHIFT 0x00
/* Registers for function SMPS */
-#define PALMAS_SMPS12_CTRL 0x0
-#define PALMAS_SMPS12_TSTEP 0x1
-#define PALMAS_SMPS12_FORCE 0x2
-#define PALMAS_SMPS12_VOLTAGE 0x3
-#define PALMAS_SMPS3_CTRL 0x4
-#define PALMAS_SMPS3_VOLTAGE 0x7
-#define PALMAS_SMPS45_CTRL 0x8
-#define PALMAS_SMPS45_TSTEP 0x9
-#define PALMAS_SMPS45_FORCE 0xA
-#define PALMAS_SMPS45_VOLTAGE 0xB
-#define PALMAS_SMPS6_CTRL 0xC
-#define PALMAS_SMPS6_TSTEP 0xD
-#define PALMAS_SMPS6_FORCE 0xE
-#define PALMAS_SMPS6_VOLTAGE 0xF
+#define PALMAS_SMPS12_CTRL 0x00
+#define PALMAS_SMPS12_TSTEP 0x01
+#define PALMAS_SMPS12_FORCE 0x02
+#define PALMAS_SMPS12_VOLTAGE 0x03
+#define PALMAS_SMPS3_CTRL 0x04
+#define PALMAS_SMPS3_VOLTAGE 0x07
+#define PALMAS_SMPS45_CTRL 0x08
+#define PALMAS_SMPS45_TSTEP 0x09
+#define PALMAS_SMPS45_FORCE 0x0A
+#define PALMAS_SMPS45_VOLTAGE 0x0B
+#define PALMAS_SMPS6_CTRL 0x0C
+#define PALMAS_SMPS6_TSTEP 0x0D
+#define PALMAS_SMPS6_FORCE 0x0E
+#define PALMAS_SMPS6_VOLTAGE 0x0F
#define PALMAS_SMPS7_CTRL 0x10
#define PALMAS_SMPS7_VOLTAGE 0x13
#define PALMAS_SMPS8_CTRL 0x14
@@ -744,303 +744,303 @@ enum usb_irq_events {
/* Bit definitions for SMPS12_CTRL */
#define PALMAS_SMPS12_CTRL_WR_S 0x80
-#define PALMAS_SMPS12_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS12_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN 0x40
-#define PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS12_CTRL_ROOF_FLOOR_EN_SHIFT 0x06
#define PALMAS_SMPS12_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS12_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS12_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS12_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS12_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS12_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS12_TSTEP */
#define PALMAS_SMPS12_TSTEP_TSTEP_MASK 0x03
-#define PALMAS_SMPS12_TSTEP_TSTEP_SHIFT 0
+#define PALMAS_SMPS12_TSTEP_TSTEP_SHIFT 0x00
/* Bit definitions for SMPS12_FORCE */
#define PALMAS_SMPS12_FORCE_CMD 0x80
-#define PALMAS_SMPS12_FORCE_CMD_SHIFT 7
-#define PALMAS_SMPS12_FORCE_VSEL_MASK 0x7f
-#define PALMAS_SMPS12_FORCE_VSEL_SHIFT 0
+#define PALMAS_SMPS12_FORCE_CMD_SHIFT 0x07
+#define PALMAS_SMPS12_FORCE_VSEL_MASK 0x7F
+#define PALMAS_SMPS12_FORCE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS12_VOLTAGE */
#define PALMAS_SMPS12_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS12_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS12_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS12_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS12_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS12_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS12_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS3_CTRL */
#define PALMAS_SMPS3_CTRL_WR_S 0x80
-#define PALMAS_SMPS3_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS3_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS3_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS3_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS3_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS3_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS3_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS3_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS3_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS3_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS3_VOLTAGE */
#define PALMAS_SMPS3_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS3_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS3_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS3_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS3_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS3_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS3_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS45_CTRL */
#define PALMAS_SMPS45_CTRL_WR_S 0x80
-#define PALMAS_SMPS45_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS45_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS45_CTRL_ROOF_FLOOR_EN 0x40
-#define PALMAS_SMPS45_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS45_CTRL_ROOF_FLOOR_EN_SHIFT 0x06
#define PALMAS_SMPS45_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS45_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS45_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS45_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS45_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS45_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS45_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS45_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS45_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS45_TSTEP */
#define PALMAS_SMPS45_TSTEP_TSTEP_MASK 0x03
-#define PALMAS_SMPS45_TSTEP_TSTEP_SHIFT 0
+#define PALMAS_SMPS45_TSTEP_TSTEP_SHIFT 0x00
/* Bit definitions for SMPS45_FORCE */
#define PALMAS_SMPS45_FORCE_CMD 0x80
-#define PALMAS_SMPS45_FORCE_CMD_SHIFT 7
-#define PALMAS_SMPS45_FORCE_VSEL_MASK 0x7f
-#define PALMAS_SMPS45_FORCE_VSEL_SHIFT 0
+#define PALMAS_SMPS45_FORCE_CMD_SHIFT 0x07
+#define PALMAS_SMPS45_FORCE_VSEL_MASK 0x7F
+#define PALMAS_SMPS45_FORCE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS45_VOLTAGE */
#define PALMAS_SMPS45_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS45_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS45_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS45_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS45_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS45_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS45_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS6_CTRL */
#define PALMAS_SMPS6_CTRL_WR_S 0x80
-#define PALMAS_SMPS6_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS6_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS6_CTRL_ROOF_FLOOR_EN 0x40
-#define PALMAS_SMPS6_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS6_CTRL_ROOF_FLOOR_EN_SHIFT 0x06
#define PALMAS_SMPS6_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS6_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS6_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS6_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS6_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS6_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS6_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS6_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS6_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS6_TSTEP */
#define PALMAS_SMPS6_TSTEP_TSTEP_MASK 0x03
-#define PALMAS_SMPS6_TSTEP_TSTEP_SHIFT 0
+#define PALMAS_SMPS6_TSTEP_TSTEP_SHIFT 0x00
/* Bit definitions for SMPS6_FORCE */
#define PALMAS_SMPS6_FORCE_CMD 0x80
-#define PALMAS_SMPS6_FORCE_CMD_SHIFT 7
-#define PALMAS_SMPS6_FORCE_VSEL_MASK 0x7f
-#define PALMAS_SMPS6_FORCE_VSEL_SHIFT 0
+#define PALMAS_SMPS6_FORCE_CMD_SHIFT 0x07
+#define PALMAS_SMPS6_FORCE_VSEL_MASK 0x7F
+#define PALMAS_SMPS6_FORCE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS6_VOLTAGE */
#define PALMAS_SMPS6_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS6_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS6_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS6_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS6_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS6_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS6_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS7_CTRL */
#define PALMAS_SMPS7_CTRL_WR_S 0x80
-#define PALMAS_SMPS7_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS7_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS7_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS7_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS7_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS7_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS7_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS7_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS7_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS7_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS7_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS7_VOLTAGE */
#define PALMAS_SMPS7_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS7_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS7_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS7_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS7_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS7_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS7_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS8_CTRL */
#define PALMAS_SMPS8_CTRL_WR_S 0x80
-#define PALMAS_SMPS8_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS8_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS8_CTRL_ROOF_FLOOR_EN 0x40
-#define PALMAS_SMPS8_CTRL_ROOF_FLOOR_EN_SHIFT 6
+#define PALMAS_SMPS8_CTRL_ROOF_FLOOR_EN_SHIFT 0x06
#define PALMAS_SMPS8_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS8_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS8_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS8_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS8_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS8_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS8_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS8_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS8_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS8_TSTEP */
#define PALMAS_SMPS8_TSTEP_TSTEP_MASK 0x03
-#define PALMAS_SMPS8_TSTEP_TSTEP_SHIFT 0
+#define PALMAS_SMPS8_TSTEP_TSTEP_SHIFT 0x00
/* Bit definitions for SMPS8_FORCE */
#define PALMAS_SMPS8_FORCE_CMD 0x80
-#define PALMAS_SMPS8_FORCE_CMD_SHIFT 7
-#define PALMAS_SMPS8_FORCE_VSEL_MASK 0x7f
-#define PALMAS_SMPS8_FORCE_VSEL_SHIFT 0
+#define PALMAS_SMPS8_FORCE_CMD_SHIFT 0x07
+#define PALMAS_SMPS8_FORCE_VSEL_MASK 0x7F
+#define PALMAS_SMPS8_FORCE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS8_VOLTAGE */
#define PALMAS_SMPS8_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS8_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS8_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS8_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS8_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS8_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS8_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS9_CTRL */
#define PALMAS_SMPS9_CTRL_WR_S 0x80
-#define PALMAS_SMPS9_CTRL_WR_S_SHIFT 7
+#define PALMAS_SMPS9_CTRL_WR_S_SHIFT 0x07
#define PALMAS_SMPS9_CTRL_STATUS_MASK 0x30
-#define PALMAS_SMPS9_CTRL_STATUS_SHIFT 4
+#define PALMAS_SMPS9_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SMPS9_CTRL_MODE_SLEEP_MASK 0x0c
-#define PALMAS_SMPS9_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SMPS9_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SMPS9_CTRL_MODE_ACTIVE_MASK 0x03
-#define PALMAS_SMPS9_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS9_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS9_VOLTAGE */
#define PALMAS_SMPS9_VOLTAGE_RANGE 0x80
-#define PALMAS_SMPS9_VOLTAGE_RANGE_SHIFT 7
-#define PALMAS_SMPS9_VOLTAGE_VSEL_MASK 0x7f
-#define PALMAS_SMPS9_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_SMPS9_VOLTAGE_RANGE_SHIFT 0x07
+#define PALMAS_SMPS9_VOLTAGE_VSEL_MASK 0x7F
+#define PALMAS_SMPS9_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for SMPS10_CTRL */
#define PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK 0xf0
-#define PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT 4
-#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_MASK 0x0f
-#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT 0x04
+#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_MASK 0x0F
+#define PALMAS_SMPS10_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SMPS10_STATUS */
-#define PALMAS_SMPS10_STATUS_STATUS_MASK 0x0f
-#define PALMAS_SMPS10_STATUS_STATUS_SHIFT 0
+#define PALMAS_SMPS10_STATUS_STATUS_MASK 0x0F
+#define PALMAS_SMPS10_STATUS_STATUS_SHIFT 0x00
/* Bit definitions for SMPS_CTRL */
#define PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN 0x20
-#define PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN_SHIFT 5
+#define PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN_SHIFT 0x05
#define PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN 0x10
-#define PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN_SHIFT 4
+#define PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN_SHIFT 0x04
#define PALMAS_SMPS_CTRL_SMPS45_PHASE_CTRL_MASK 0x0c
-#define PALMAS_SMPS_CTRL_SMPS45_PHASE_CTRL_SHIFT 2
+#define PALMAS_SMPS_CTRL_SMPS45_PHASE_CTRL_SHIFT 0x02
#define PALMAS_SMPS_CTRL_SMPS123_PHASE_CTRL_MASK 0x03
-#define PALMAS_SMPS_CTRL_SMPS123_PHASE_CTRL_SHIFT 0
+#define PALMAS_SMPS_CTRL_SMPS123_PHASE_CTRL_SHIFT 0x00
/* Bit definitions for SMPS_PD_CTRL */
#define PALMAS_SMPS_PD_CTRL_SMPS9 0x40
-#define PALMAS_SMPS_PD_CTRL_SMPS9_SHIFT 6
+#define PALMAS_SMPS_PD_CTRL_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_PD_CTRL_SMPS8 0x20
-#define PALMAS_SMPS_PD_CTRL_SMPS8_SHIFT 5
+#define PALMAS_SMPS_PD_CTRL_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_PD_CTRL_SMPS7 0x10
-#define PALMAS_SMPS_PD_CTRL_SMPS7_SHIFT 4
+#define PALMAS_SMPS_PD_CTRL_SMPS7_SHIFT 0x04
#define PALMAS_SMPS_PD_CTRL_SMPS6 0x08
-#define PALMAS_SMPS_PD_CTRL_SMPS6_SHIFT 3
+#define PALMAS_SMPS_PD_CTRL_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_PD_CTRL_SMPS45 0x04
-#define PALMAS_SMPS_PD_CTRL_SMPS45_SHIFT 2
+#define PALMAS_SMPS_PD_CTRL_SMPS45_SHIFT 0x02
#define PALMAS_SMPS_PD_CTRL_SMPS3 0x02
-#define PALMAS_SMPS_PD_CTRL_SMPS3_SHIFT 1
+#define PALMAS_SMPS_PD_CTRL_SMPS3_SHIFT 0x01
#define PALMAS_SMPS_PD_CTRL_SMPS12 0x01
-#define PALMAS_SMPS_PD_CTRL_SMPS12_SHIFT 0
+#define PALMAS_SMPS_PD_CTRL_SMPS12_SHIFT 0x00
/* Bit definitions for SMPS_THERMAL_EN */
#define PALMAS_SMPS_THERMAL_EN_SMPS9 0x40
-#define PALMAS_SMPS_THERMAL_EN_SMPS9_SHIFT 6
+#define PALMAS_SMPS_THERMAL_EN_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_THERMAL_EN_SMPS8 0x20
-#define PALMAS_SMPS_THERMAL_EN_SMPS8_SHIFT 5
+#define PALMAS_SMPS_THERMAL_EN_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_THERMAL_EN_SMPS6 0x08
-#define PALMAS_SMPS_THERMAL_EN_SMPS6_SHIFT 3
+#define PALMAS_SMPS_THERMAL_EN_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_THERMAL_EN_SMPS457 0x04
-#define PALMAS_SMPS_THERMAL_EN_SMPS457_SHIFT 2
+#define PALMAS_SMPS_THERMAL_EN_SMPS457_SHIFT 0x02
#define PALMAS_SMPS_THERMAL_EN_SMPS123 0x01
-#define PALMAS_SMPS_THERMAL_EN_SMPS123_SHIFT 0
+#define PALMAS_SMPS_THERMAL_EN_SMPS123_SHIFT 0x00
/* Bit definitions for SMPS_THERMAL_STATUS */
#define PALMAS_SMPS_THERMAL_STATUS_SMPS9 0x40
-#define PALMAS_SMPS_THERMAL_STATUS_SMPS9_SHIFT 6
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_THERMAL_STATUS_SMPS8 0x20
-#define PALMAS_SMPS_THERMAL_STATUS_SMPS8_SHIFT 5
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_THERMAL_STATUS_SMPS6 0x08
-#define PALMAS_SMPS_THERMAL_STATUS_SMPS6_SHIFT 3
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_THERMAL_STATUS_SMPS457 0x04
-#define PALMAS_SMPS_THERMAL_STATUS_SMPS457_SHIFT 2
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS457_SHIFT 0x02
#define PALMAS_SMPS_THERMAL_STATUS_SMPS123 0x01
-#define PALMAS_SMPS_THERMAL_STATUS_SMPS123_SHIFT 0
+#define PALMAS_SMPS_THERMAL_STATUS_SMPS123_SHIFT 0x00
/* Bit definitions for SMPS_SHORT_STATUS */
#define PALMAS_SMPS_SHORT_STATUS_SMPS10 0x80
-#define PALMAS_SMPS_SHORT_STATUS_SMPS10_SHIFT 7
+#define PALMAS_SMPS_SHORT_STATUS_SMPS10_SHIFT 0x07
#define PALMAS_SMPS_SHORT_STATUS_SMPS9 0x40
-#define PALMAS_SMPS_SHORT_STATUS_SMPS9_SHIFT 6
+#define PALMAS_SMPS_SHORT_STATUS_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_SHORT_STATUS_SMPS8 0x20
-#define PALMAS_SMPS_SHORT_STATUS_SMPS8_SHIFT 5
+#define PALMAS_SMPS_SHORT_STATUS_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_SHORT_STATUS_SMPS7 0x10
-#define PALMAS_SMPS_SHORT_STATUS_SMPS7_SHIFT 4
+#define PALMAS_SMPS_SHORT_STATUS_SMPS7_SHIFT 0x04
#define PALMAS_SMPS_SHORT_STATUS_SMPS6 0x08
-#define PALMAS_SMPS_SHORT_STATUS_SMPS6_SHIFT 3
+#define PALMAS_SMPS_SHORT_STATUS_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_SHORT_STATUS_SMPS45 0x04
-#define PALMAS_SMPS_SHORT_STATUS_SMPS45_SHIFT 2
+#define PALMAS_SMPS_SHORT_STATUS_SMPS45_SHIFT 0x02
#define PALMAS_SMPS_SHORT_STATUS_SMPS3 0x02
-#define PALMAS_SMPS_SHORT_STATUS_SMPS3_SHIFT 1
+#define PALMAS_SMPS_SHORT_STATUS_SMPS3_SHIFT 0x01
#define PALMAS_SMPS_SHORT_STATUS_SMPS12 0x01
-#define PALMAS_SMPS_SHORT_STATUS_SMPS12_SHIFT 0
+#define PALMAS_SMPS_SHORT_STATUS_SMPS12_SHIFT 0x00
/* Bit definitions for SMPS_NEGATIVE_CURRENT_LIMIT_EN */
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS9 0x40
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS9_SHIFT 6
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS8 0x20
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS8_SHIFT 5
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS7 0x10
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS7_SHIFT 4
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS7_SHIFT 0x04
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS6 0x08
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS6_SHIFT 3
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS45 0x04
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS45_SHIFT 2
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS45_SHIFT 0x02
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS3 0x02
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS3_SHIFT 1
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS3_SHIFT 0x01
#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS12 0x01
-#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS12_SHIFT 0
+#define PALMAS_SMPS_NEGATIVE_CURRENT_LIMIT_EN_SMPS12_SHIFT 0x00
/* Bit definitions for SMPS_POWERGOOD_MASK1 */
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS10 0x80
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS10_SHIFT 7
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS10_SHIFT 0x07
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS9 0x40
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS9_SHIFT 6
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS9_SHIFT 0x06
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS8 0x20
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS8_SHIFT 5
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS8_SHIFT 0x05
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS7 0x10
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS7_SHIFT 4
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS7_SHIFT 0x04
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS6 0x08
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS6_SHIFT 3
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS6_SHIFT 0x03
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS45 0x04
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS45_SHIFT 2
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS45_SHIFT 0x02
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS3 0x02
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS3_SHIFT 1
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS3_SHIFT 0x01
#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS12 0x01
-#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS12_SHIFT 0
+#define PALMAS_SMPS_POWERGOOD_MASK1_SMPS12_SHIFT 0x00
/* Bit definitions for SMPS_POWERGOOD_MASK2 */
#define PALMAS_SMPS_POWERGOOD_MASK2_POWERGOOD_TYPE_SELECT 0x80
-#define PALMAS_SMPS_POWERGOOD_MASK2_POWERGOOD_TYPE_SELECT_SHIFT 7
+#define PALMAS_SMPS_POWERGOOD_MASK2_POWERGOOD_TYPE_SELECT_SHIFT 0x07
#define PALMAS_SMPS_POWERGOOD_MASK2_GPIO_7 0x04
-#define PALMAS_SMPS_POWERGOOD_MASK2_GPIO_7_SHIFT 2
+#define PALMAS_SMPS_POWERGOOD_MASK2_GPIO_7_SHIFT 0x02
#define PALMAS_SMPS_POWERGOOD_MASK2_VBUS 0x02
-#define PALMAS_SMPS_POWERGOOD_MASK2_VBUS_SHIFT 1
+#define PALMAS_SMPS_POWERGOOD_MASK2_VBUS_SHIFT 0x01
#define PALMAS_SMPS_POWERGOOD_MASK2_ACOK 0x01
-#define PALMAS_SMPS_POWERGOOD_MASK2_ACOK_SHIFT 0
+#define PALMAS_SMPS_POWERGOOD_MASK2_ACOK_SHIFT 0x00
/* Registers for function LDO */
-#define PALMAS_LDO1_CTRL 0x0
-#define PALMAS_LDO1_VOLTAGE 0x1
-#define PALMAS_LDO2_CTRL 0x2
-#define PALMAS_LDO2_VOLTAGE 0x3
-#define PALMAS_LDO3_CTRL 0x4
-#define PALMAS_LDO3_VOLTAGE 0x5
-#define PALMAS_LDO4_CTRL 0x6
-#define PALMAS_LDO4_VOLTAGE 0x7
-#define PALMAS_LDO5_CTRL 0x8
-#define PALMAS_LDO5_VOLTAGE 0x9
-#define PALMAS_LDO6_CTRL 0xA
-#define PALMAS_LDO6_VOLTAGE 0xB
-#define PALMAS_LDO7_CTRL 0xC
-#define PALMAS_LDO7_VOLTAGE 0xD
-#define PALMAS_LDO8_CTRL 0xE
-#define PALMAS_LDO8_VOLTAGE 0xF
+#define PALMAS_LDO1_CTRL 0x00
+#define PALMAS_LDO1_VOLTAGE 0x01
+#define PALMAS_LDO2_CTRL 0x02
+#define PALMAS_LDO2_VOLTAGE 0x03
+#define PALMAS_LDO3_CTRL 0x04
+#define PALMAS_LDO3_VOLTAGE 0x05
+#define PALMAS_LDO4_CTRL 0x06
+#define PALMAS_LDO4_VOLTAGE 0x07
+#define PALMAS_LDO5_CTRL 0x08
+#define PALMAS_LDO5_VOLTAGE 0x09
+#define PALMAS_LDO6_CTRL 0x0A
+#define PALMAS_LDO6_VOLTAGE 0x0B
+#define PALMAS_LDO7_CTRL 0x0C
+#define PALMAS_LDO7_VOLTAGE 0x0D
+#define PALMAS_LDO8_CTRL 0x0E
+#define PALMAS_LDO8_VOLTAGE 0x0F
#define PALMAS_LDO9_CTRL 0x10
#define PALMAS_LDO9_VOLTAGE 0x11
#define PALMAS_LDOLN_CTRL 0x12
@@ -1055,236 +1055,236 @@ enum usb_irq_events {
/* Bit definitions for LDO1_CTRL */
#define PALMAS_LDO1_CTRL_WR_S 0x80
-#define PALMAS_LDO1_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO1_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO1_CTRL_STATUS 0x10
-#define PALMAS_LDO1_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO1_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO1_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO1_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO1_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO1_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO1_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO1_VOLTAGE */
-#define PALMAS_LDO1_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO1_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO1_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO1_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO2_CTRL */
#define PALMAS_LDO2_CTRL_WR_S 0x80
-#define PALMAS_LDO2_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO2_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO2_CTRL_STATUS 0x10
-#define PALMAS_LDO2_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO2_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO2_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO2_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO2_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO2_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO2_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO2_VOLTAGE */
-#define PALMAS_LDO2_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO2_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO2_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO2_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO3_CTRL */
#define PALMAS_LDO3_CTRL_WR_S 0x80
-#define PALMAS_LDO3_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO3_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO3_CTRL_STATUS 0x10
-#define PALMAS_LDO3_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO3_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO3_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO3_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO3_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO3_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO3_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO3_VOLTAGE */
-#define PALMAS_LDO3_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO3_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO3_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO3_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO4_CTRL */
#define PALMAS_LDO4_CTRL_WR_S 0x80
-#define PALMAS_LDO4_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO4_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO4_CTRL_STATUS 0x10
-#define PALMAS_LDO4_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO4_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO4_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO4_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO4_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO4_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO4_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO4_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO4_VOLTAGE */
-#define PALMAS_LDO4_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO4_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO4_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO4_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO5_CTRL */
#define PALMAS_LDO5_CTRL_WR_S 0x80
-#define PALMAS_LDO5_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO5_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO5_CTRL_STATUS 0x10
-#define PALMAS_LDO5_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO5_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO5_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO5_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO5_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO5_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO5_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO5_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO5_VOLTAGE */
-#define PALMAS_LDO5_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO5_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO5_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO5_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO6_CTRL */
#define PALMAS_LDO6_CTRL_WR_S 0x80
-#define PALMAS_LDO6_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO6_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO6_CTRL_LDO_VIB_EN 0x40
-#define PALMAS_LDO6_CTRL_LDO_VIB_EN_SHIFT 6
+#define PALMAS_LDO6_CTRL_LDO_VIB_EN_SHIFT 0x06
#define PALMAS_LDO6_CTRL_STATUS 0x10
-#define PALMAS_LDO6_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO6_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO6_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO6_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO6_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO6_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO6_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO6_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO6_VOLTAGE */
-#define PALMAS_LDO6_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO6_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO6_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO6_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO7_CTRL */
#define PALMAS_LDO7_CTRL_WR_S 0x80
-#define PALMAS_LDO7_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO7_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO7_CTRL_STATUS 0x10
-#define PALMAS_LDO7_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO7_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO7_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO7_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO7_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO7_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO7_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO7_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO7_VOLTAGE */
-#define PALMAS_LDO7_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO7_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO7_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO7_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO8_CTRL */
#define PALMAS_LDO8_CTRL_WR_S 0x80
-#define PALMAS_LDO8_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO8_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO8_CTRL_LDO_TRACKING_EN 0x40
-#define PALMAS_LDO8_CTRL_LDO_TRACKING_EN_SHIFT 6
+#define PALMAS_LDO8_CTRL_LDO_TRACKING_EN_SHIFT 0x06
#define PALMAS_LDO8_CTRL_STATUS 0x10
-#define PALMAS_LDO8_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO8_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO8_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO8_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO8_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO8_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO8_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO8_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO8_VOLTAGE */
-#define PALMAS_LDO8_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO8_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO8_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO8_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO9_CTRL */
#define PALMAS_LDO9_CTRL_WR_S 0x80
-#define PALMAS_LDO9_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDO9_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDO9_CTRL_LDO_BYPASS_EN 0x40
-#define PALMAS_LDO9_CTRL_LDO_BYPASS_EN_SHIFT 6
+#define PALMAS_LDO9_CTRL_LDO_BYPASS_EN_SHIFT 0x06
#define PALMAS_LDO9_CTRL_STATUS 0x10
-#define PALMAS_LDO9_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDO9_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDO9_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDO9_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDO9_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDO9_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDO9_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDO9_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDO9_VOLTAGE */
-#define PALMAS_LDO9_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDO9_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDO9_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDO9_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDOLN_CTRL */
#define PALMAS_LDOLN_CTRL_WR_S 0x80
-#define PALMAS_LDOLN_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDOLN_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDOLN_CTRL_STATUS 0x10
-#define PALMAS_LDOLN_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDOLN_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDOLN_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDOLN_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDOLN_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDOLN_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDOLN_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDOLN_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDOLN_VOLTAGE */
-#define PALMAS_LDOLN_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDOLN_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDOLN_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDOLN_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDOUSB_CTRL */
#define PALMAS_LDOUSB_CTRL_WR_S 0x80
-#define PALMAS_LDOUSB_CTRL_WR_S_SHIFT 7
+#define PALMAS_LDOUSB_CTRL_WR_S_SHIFT 0x07
#define PALMAS_LDOUSB_CTRL_STATUS 0x10
-#define PALMAS_LDOUSB_CTRL_STATUS_SHIFT 4
+#define PALMAS_LDOUSB_CTRL_STATUS_SHIFT 0x04
#define PALMAS_LDOUSB_CTRL_MODE_SLEEP 0x04
-#define PALMAS_LDOUSB_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_LDOUSB_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_LDOUSB_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_LDOUSB_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_LDOUSB_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for LDOUSB_VOLTAGE */
-#define PALMAS_LDOUSB_VOLTAGE_VSEL_MASK 0x3f
-#define PALMAS_LDOUSB_VOLTAGE_VSEL_SHIFT 0
+#define PALMAS_LDOUSB_VOLTAGE_VSEL_MASK 0x3F
+#define PALMAS_LDOUSB_VOLTAGE_VSEL_SHIFT 0x00
/* Bit definitions for LDO_CTRL */
#define PALMAS_LDO_CTRL_LDOUSB_ON_VBUS_VSYS 0x01
-#define PALMAS_LDO_CTRL_LDOUSB_ON_VBUS_VSYS_SHIFT 0
+#define PALMAS_LDO_CTRL_LDOUSB_ON_VBUS_VSYS_SHIFT 0x00
/* Bit definitions for LDO_PD_CTRL1 */
#define PALMAS_LDO_PD_CTRL1_LDO8 0x80
-#define PALMAS_LDO_PD_CTRL1_LDO8_SHIFT 7
+#define PALMAS_LDO_PD_CTRL1_LDO8_SHIFT 0x07
#define PALMAS_LDO_PD_CTRL1_LDO7 0x40
-#define PALMAS_LDO_PD_CTRL1_LDO7_SHIFT 6
+#define PALMAS_LDO_PD_CTRL1_LDO7_SHIFT 0x06
#define PALMAS_LDO_PD_CTRL1_LDO6 0x20
-#define PALMAS_LDO_PD_CTRL1_LDO6_SHIFT 5
+#define PALMAS_LDO_PD_CTRL1_LDO6_SHIFT 0x05
#define PALMAS_LDO_PD_CTRL1_LDO5 0x10
-#define PALMAS_LDO_PD_CTRL1_LDO5_SHIFT 4
+#define PALMAS_LDO_PD_CTRL1_LDO5_SHIFT 0x04
#define PALMAS_LDO_PD_CTRL1_LDO4 0x08
-#define PALMAS_LDO_PD_CTRL1_LDO4_SHIFT 3
+#define PALMAS_LDO_PD_CTRL1_LDO4_SHIFT 0x03
#define PALMAS_LDO_PD_CTRL1_LDO3 0x04
-#define PALMAS_LDO_PD_CTRL1_LDO3_SHIFT 2
+#define PALMAS_LDO_PD_CTRL1_LDO3_SHIFT 0x02
#define PALMAS_LDO_PD_CTRL1_LDO2 0x02
-#define PALMAS_LDO_PD_CTRL1_LDO2_SHIFT 1
+#define PALMAS_LDO_PD_CTRL1_LDO2_SHIFT 0x01
#define PALMAS_LDO_PD_CTRL1_LDO1 0x01
-#define PALMAS_LDO_PD_CTRL1_LDO1_SHIFT 0
+#define PALMAS_LDO_PD_CTRL1_LDO1_SHIFT 0x00
/* Bit definitions for LDO_PD_CTRL2 */
#define PALMAS_LDO_PD_CTRL2_LDOUSB 0x04
-#define PALMAS_LDO_PD_CTRL2_LDOUSB_SHIFT 2
+#define PALMAS_LDO_PD_CTRL2_LDOUSB_SHIFT 0x02
#define PALMAS_LDO_PD_CTRL2_LDOLN 0x02
-#define PALMAS_LDO_PD_CTRL2_LDOLN_SHIFT 1
+#define PALMAS_LDO_PD_CTRL2_LDOLN_SHIFT 0x01
#define PALMAS_LDO_PD_CTRL2_LDO9 0x01
-#define PALMAS_LDO_PD_CTRL2_LDO9_SHIFT 0
+#define PALMAS_LDO_PD_CTRL2_LDO9_SHIFT 0x00
/* Bit definitions for LDO_SHORT_STATUS1 */
#define PALMAS_LDO_SHORT_STATUS1_LDO8 0x80
-#define PALMAS_LDO_SHORT_STATUS1_LDO8_SHIFT 7
+#define PALMAS_LDO_SHORT_STATUS1_LDO8_SHIFT 0x07
#define PALMAS_LDO_SHORT_STATUS1_LDO7 0x40
-#define PALMAS_LDO_SHORT_STATUS1_LDO7_SHIFT 6
+#define PALMAS_LDO_SHORT_STATUS1_LDO7_SHIFT 0x06
#define PALMAS_LDO_SHORT_STATUS1_LDO6 0x20
-#define PALMAS_LDO_SHORT_STATUS1_LDO6_SHIFT 5
+#define PALMAS_LDO_SHORT_STATUS1_LDO6_SHIFT 0x05
#define PALMAS_LDO_SHORT_STATUS1_LDO5 0x10
-#define PALMAS_LDO_SHORT_STATUS1_LDO5_SHIFT 4
+#define PALMAS_LDO_SHORT_STATUS1_LDO5_SHIFT 0x04
#define PALMAS_LDO_SHORT_STATUS1_LDO4 0x08
-#define PALMAS_LDO_SHORT_STATUS1_LDO4_SHIFT 3
+#define PALMAS_LDO_SHORT_STATUS1_LDO4_SHIFT 0x03
#define PALMAS_LDO_SHORT_STATUS1_LDO3 0x04
-#define PALMAS_LDO_SHORT_STATUS1_LDO3_SHIFT 2
+#define PALMAS_LDO_SHORT_STATUS1_LDO3_SHIFT 0x02
#define PALMAS_LDO_SHORT_STATUS1_LDO2 0x02
-#define PALMAS_LDO_SHORT_STATUS1_LDO2_SHIFT 1
+#define PALMAS_LDO_SHORT_STATUS1_LDO2_SHIFT 0x01
#define PALMAS_LDO_SHORT_STATUS1_LDO1 0x01
-#define PALMAS_LDO_SHORT_STATUS1_LDO1_SHIFT 0
+#define PALMAS_LDO_SHORT_STATUS1_LDO1_SHIFT 0x00
/* Bit definitions for LDO_SHORT_STATUS2 */
#define PALMAS_LDO_SHORT_STATUS2_LDOVANA 0x08
-#define PALMAS_LDO_SHORT_STATUS2_LDOVANA_SHIFT 3
+#define PALMAS_LDO_SHORT_STATUS2_LDOVANA_SHIFT 0x03
#define PALMAS_LDO_SHORT_STATUS2_LDOUSB 0x04
-#define PALMAS_LDO_SHORT_STATUS2_LDOUSB_SHIFT 2
+#define PALMAS_LDO_SHORT_STATUS2_LDOUSB_SHIFT 0x02
#define PALMAS_LDO_SHORT_STATUS2_LDOLN 0x02
-#define PALMAS_LDO_SHORT_STATUS2_LDOLN_SHIFT 1
+#define PALMAS_LDO_SHORT_STATUS2_LDOLN_SHIFT 0x01
#define PALMAS_LDO_SHORT_STATUS2_LDO9 0x01
-#define PALMAS_LDO_SHORT_STATUS2_LDO9_SHIFT 0
+#define PALMAS_LDO_SHORT_STATUS2_LDO9_SHIFT 0x00
/* Registers for function PMU_CONTROL */
-#define PALMAS_DEV_CTRL 0x0
-#define PALMAS_POWER_CTRL 0x1
-#define PALMAS_VSYS_LO 0x2
-#define PALMAS_VSYS_MON 0x3
-#define PALMAS_VBAT_MON 0x4
-#define PALMAS_WATCHDOG 0x5
-#define PALMAS_BOOT_STATUS 0x6
-#define PALMAS_BATTERY_BOUNCE 0x7
-#define PALMAS_BACKUP_BATTERY_CTRL 0x8
-#define PALMAS_LONG_PRESS_KEY 0x9
-#define PALMAS_OSC_THERM_CTRL 0xA
-#define PALMAS_BATDEBOUNCING 0xB
-#define PALMAS_SWOFF_HWRST 0xF
+#define PALMAS_DEV_CTRL 0x00
+#define PALMAS_POWER_CTRL 0x01
+#define PALMAS_VSYS_LO 0x02
+#define PALMAS_VSYS_MON 0x03
+#define PALMAS_VBAT_MON 0x04
+#define PALMAS_WATCHDOG 0x05
+#define PALMAS_BOOT_STATUS 0x06
+#define PALMAS_BATTERY_BOUNCE 0x07
+#define PALMAS_BACKUP_BATTERY_CTRL 0x08
+#define PALMAS_LONG_PRESS_KEY 0x09
+#define PALMAS_OSC_THERM_CTRL 0x0A
+#define PALMAS_BATDEBOUNCING 0x0B
+#define PALMAS_SWOFF_HWRST 0x0F
#define PALMAS_SWOFF_COLDRST 0x10
#define PALMAS_SWOFF_STATUS 0x11
#define PALMAS_PMU_CONFIG 0x12
@@ -1296,668 +1296,668 @@ enum usb_irq_events {
/* Bit definitions for DEV_CTRL */
#define PALMAS_DEV_CTRL_DEV_STATUS_MASK 0x0c
-#define PALMAS_DEV_CTRL_DEV_STATUS_SHIFT 2
+#define PALMAS_DEV_CTRL_DEV_STATUS_SHIFT 0x02
#define PALMAS_DEV_CTRL_SW_RST 0x02
-#define PALMAS_DEV_CTRL_SW_RST_SHIFT 1
+#define PALMAS_DEV_CTRL_SW_RST_SHIFT 0x01
#define PALMAS_DEV_CTRL_DEV_ON 0x01
-#define PALMAS_DEV_CTRL_DEV_ON_SHIFT 0
+#define PALMAS_DEV_CTRL_DEV_ON_SHIFT 0x00
/* Bit definitions for POWER_CTRL */
#define PALMAS_POWER_CTRL_ENABLE2_MASK 0x04
-#define PALMAS_POWER_CTRL_ENABLE2_MASK_SHIFT 2
+#define PALMAS_POWER_CTRL_ENABLE2_MASK_SHIFT 0x02
#define PALMAS_POWER_CTRL_ENABLE1_MASK 0x02
-#define PALMAS_POWER_CTRL_ENABLE1_MASK_SHIFT 1
+#define PALMAS_POWER_CTRL_ENABLE1_MASK_SHIFT 0x01
#define PALMAS_POWER_CTRL_NSLEEP_MASK 0x01
-#define PALMAS_POWER_CTRL_NSLEEP_MASK_SHIFT 0
+#define PALMAS_POWER_CTRL_NSLEEP_MASK_SHIFT 0x00
/* Bit definitions for VSYS_LO */
-#define PALMAS_VSYS_LO_THRESHOLD_MASK 0x1f
-#define PALMAS_VSYS_LO_THRESHOLD_SHIFT 0
+#define PALMAS_VSYS_LO_THRESHOLD_MASK 0x1F
+#define PALMAS_VSYS_LO_THRESHOLD_SHIFT 0x00
/* Bit definitions for VSYS_MON */
#define PALMAS_VSYS_MON_ENABLE 0x80
-#define PALMAS_VSYS_MON_ENABLE_SHIFT 7
-#define PALMAS_VSYS_MON_THRESHOLD_MASK 0x3f
-#define PALMAS_VSYS_MON_THRESHOLD_SHIFT 0
+#define PALMAS_VSYS_MON_ENABLE_SHIFT 0x07
+#define PALMAS_VSYS_MON_THRESHOLD_MASK 0x3F
+#define PALMAS_VSYS_MON_THRESHOLD_SHIFT 0x00
/* Bit definitions for VBAT_MON */
#define PALMAS_VBAT_MON_ENABLE 0x80
-#define PALMAS_VBAT_MON_ENABLE_SHIFT 7
-#define PALMAS_VBAT_MON_THRESHOLD_MASK 0x3f
-#define PALMAS_VBAT_MON_THRESHOLD_SHIFT 0
+#define PALMAS_VBAT_MON_ENABLE_SHIFT 0x07
+#define PALMAS_VBAT_MON_THRESHOLD_MASK 0x3F
+#define PALMAS_VBAT_MON_THRESHOLD_SHIFT 0x00
/* Bit definitions for WATCHDOG */
#define PALMAS_WATCHDOG_LOCK 0x20
-#define PALMAS_WATCHDOG_LOCK_SHIFT 5
+#define PALMAS_WATCHDOG_LOCK_SHIFT 0x05
#define PALMAS_WATCHDOG_ENABLE 0x10
-#define PALMAS_WATCHDOG_ENABLE_SHIFT 4
+#define PALMAS_WATCHDOG_ENABLE_SHIFT 0x04
#define PALMAS_WATCHDOG_MODE 0x08
-#define PALMAS_WATCHDOG_MODE_SHIFT 3
+#define PALMAS_WATCHDOG_MODE_SHIFT 0x03
#define PALMAS_WATCHDOG_TIMER_MASK 0x07
-#define PALMAS_WATCHDOG_TIMER_SHIFT 0
+#define PALMAS_WATCHDOG_TIMER_SHIFT 0x00
/* Bit definitions for BOOT_STATUS */
#define PALMAS_BOOT_STATUS_BOOT1 0x02
-#define PALMAS_BOOT_STATUS_BOOT1_SHIFT 1
+#define PALMAS_BOOT_STATUS_BOOT1_SHIFT 0x01
#define PALMAS_BOOT_STATUS_BOOT0 0x01
-#define PALMAS_BOOT_STATUS_BOOT0_SHIFT 0
+#define PALMAS_BOOT_STATUS_BOOT0_SHIFT 0x00
/* Bit definitions for BATTERY_BOUNCE */
-#define PALMAS_BATTERY_BOUNCE_BB_DELAY_MASK 0x3f
-#define PALMAS_BATTERY_BOUNCE_BB_DELAY_SHIFT 0
+#define PALMAS_BATTERY_BOUNCE_BB_DELAY_MASK 0x3F
+#define PALMAS_BATTERY_BOUNCE_BB_DELAY_SHIFT 0x00
/* Bit definitions for BACKUP_BATTERY_CTRL */
#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_18_15 0x80
-#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_18_15_SHIFT 7
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_18_15_SHIFT 0x07
#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_SLP 0x40
-#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_SLP_SHIFT 6
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_SLP_SHIFT 0x06
#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_OFF 0x20
-#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_OFF_SHIFT 5
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_EN_OFF_SHIFT 0x05
#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_PWEN 0x10
-#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_PWEN_SHIFT 4
+#define PALMAS_BACKUP_BATTERY_CTRL_VRTC_PWEN_SHIFT 0x04
#define PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG 0x08
-#define PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG_SHIFT 3
+#define PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG_SHIFT 0x03
#define PALMAS_BACKUP_BATTERY_CTRL_BB_SEL_MASK 0x06
-#define PALMAS_BACKUP_BATTERY_CTRL_BB_SEL_SHIFT 1
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_SEL_SHIFT 0x01
#define PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN 0x01
-#define PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN_SHIFT 0
+#define PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN_SHIFT 0x00
/* Bit definitions for LONG_PRESS_KEY */
#define PALMAS_LONG_PRESS_KEY_LPK_LOCK 0x80
-#define PALMAS_LONG_PRESS_KEY_LPK_LOCK_SHIFT 7
+#define PALMAS_LONG_PRESS_KEY_LPK_LOCK_SHIFT 0x07
#define PALMAS_LONG_PRESS_KEY_LPK_INT_CLR 0x10
-#define PALMAS_LONG_PRESS_KEY_LPK_INT_CLR_SHIFT 4
+#define PALMAS_LONG_PRESS_KEY_LPK_INT_CLR_SHIFT 0x04
#define PALMAS_LONG_PRESS_KEY_LPK_TIME_MASK 0x0c
-#define PALMAS_LONG_PRESS_KEY_LPK_TIME_SHIFT 2
+#define PALMAS_LONG_PRESS_KEY_LPK_TIME_SHIFT 0x02
#define PALMAS_LONG_PRESS_KEY_PWRON_DEBOUNCE_MASK 0x03
-#define PALMAS_LONG_PRESS_KEY_PWRON_DEBOUNCE_SHIFT 0
+#define PALMAS_LONG_PRESS_KEY_PWRON_DEBOUNCE_SHIFT 0x00
/* Bit definitions for OSC_THERM_CTRL */
#define PALMAS_OSC_THERM_CTRL_VANA_ON_IN_SLEEP 0x80
-#define PALMAS_OSC_THERM_CTRL_VANA_ON_IN_SLEEP_SHIFT 7
+#define PALMAS_OSC_THERM_CTRL_VANA_ON_IN_SLEEP_SHIFT 0x07
#define PALMAS_OSC_THERM_CTRL_INT_MASK_IN_SLEEP 0x40
-#define PALMAS_OSC_THERM_CTRL_INT_MASK_IN_SLEEP_SHIFT 6
+#define PALMAS_OSC_THERM_CTRL_INT_MASK_IN_SLEEP_SHIFT 0x06
#define PALMAS_OSC_THERM_CTRL_RC15MHZ_ON_IN_SLEEP 0x20
-#define PALMAS_OSC_THERM_CTRL_RC15MHZ_ON_IN_SLEEP_SHIFT 5
+#define PALMAS_OSC_THERM_CTRL_RC15MHZ_ON_IN_SLEEP_SHIFT 0x05
#define PALMAS_OSC_THERM_CTRL_THERM_OFF_IN_SLEEP 0x10
-#define PALMAS_OSC_THERM_CTRL_THERM_OFF_IN_SLEEP_SHIFT 4
+#define PALMAS_OSC_THERM_CTRL_THERM_OFF_IN_SLEEP_SHIFT 0x04
#define PALMAS_OSC_THERM_CTRL_THERM_HD_SEL_MASK 0x0c
-#define PALMAS_OSC_THERM_CTRL_THERM_HD_SEL_SHIFT 2
+#define PALMAS_OSC_THERM_CTRL_THERM_HD_SEL_SHIFT 0x02
#define PALMAS_OSC_THERM_CTRL_OSC_BYPASS 0x02
-#define PALMAS_OSC_THERM_CTRL_OSC_BYPASS_SHIFT 1
+#define PALMAS_OSC_THERM_CTRL_OSC_BYPASS_SHIFT 0x01
#define PALMAS_OSC_THERM_CTRL_OSC_HPMODE 0x01
-#define PALMAS_OSC_THERM_CTRL_OSC_HPMODE_SHIFT 0
+#define PALMAS_OSC_THERM_CTRL_OSC_HPMODE_SHIFT 0x00
/* Bit definitions for BATDEBOUNCING */
#define PALMAS_BATDEBOUNCING_BAT_DEB_BYPASS 0x80
-#define PALMAS_BATDEBOUNCING_BAT_DEB_BYPASS_SHIFT 7
+#define PALMAS_BATDEBOUNCING_BAT_DEB_BYPASS_SHIFT 0x07
#define PALMAS_BATDEBOUNCING_BINS_DEB_MASK 0x78
-#define PALMAS_BATDEBOUNCING_BINS_DEB_SHIFT 3
+#define PALMAS_BATDEBOUNCING_BINS_DEB_SHIFT 0x03
#define PALMAS_BATDEBOUNCING_BEXT_DEB_MASK 0x07
-#define PALMAS_BATDEBOUNCING_BEXT_DEB_SHIFT 0
+#define PALMAS_BATDEBOUNCING_BEXT_DEB_SHIFT 0x00
/* Bit definitions for SWOFF_HWRST */
#define PALMAS_SWOFF_HWRST_PWRON_LPK 0x80
-#define PALMAS_SWOFF_HWRST_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_HWRST_PWRON_LPK_SHIFT 0x07
#define PALMAS_SWOFF_HWRST_PWRDOWN 0x40
-#define PALMAS_SWOFF_HWRST_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_HWRST_PWRDOWN_SHIFT 0x06
#define PALMAS_SWOFF_HWRST_WTD 0x20
-#define PALMAS_SWOFF_HWRST_WTD_SHIFT 5
+#define PALMAS_SWOFF_HWRST_WTD_SHIFT 0x05
#define PALMAS_SWOFF_HWRST_TSHUT 0x10
-#define PALMAS_SWOFF_HWRST_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_HWRST_TSHUT_SHIFT 0x04
#define PALMAS_SWOFF_HWRST_RESET_IN 0x08
-#define PALMAS_SWOFF_HWRST_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_HWRST_RESET_IN_SHIFT 0x03
#define PALMAS_SWOFF_HWRST_SW_RST 0x04
-#define PALMAS_SWOFF_HWRST_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_HWRST_SW_RST_SHIFT 0x02
#define PALMAS_SWOFF_HWRST_VSYS_LO 0x02
-#define PALMAS_SWOFF_HWRST_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_HWRST_VSYS_LO_SHIFT 0x01
#define PALMAS_SWOFF_HWRST_GPADC_SHUTDOWN 0x01
-#define PALMAS_SWOFF_HWRST_GPADC_SHUTDOWN_SHIFT 0
+#define PALMAS_SWOFF_HWRST_GPADC_SHUTDOWN_SHIFT 0x00
/* Bit definitions for SWOFF_COLDRST */
#define PALMAS_SWOFF_COLDRST_PWRON_LPK 0x80
-#define PALMAS_SWOFF_COLDRST_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_COLDRST_PWRON_LPK_SHIFT 0x07
#define PALMAS_SWOFF_COLDRST_PWRDOWN 0x40
-#define PALMAS_SWOFF_COLDRST_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_COLDRST_PWRDOWN_SHIFT 0x06
#define PALMAS_SWOFF_COLDRST_WTD 0x20
-#define PALMAS_SWOFF_COLDRST_WTD_SHIFT 5
+#define PALMAS_SWOFF_COLDRST_WTD_SHIFT 0x05
#define PALMAS_SWOFF_COLDRST_TSHUT 0x10
-#define PALMAS_SWOFF_COLDRST_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_COLDRST_TSHUT_SHIFT 0x04
#define PALMAS_SWOFF_COLDRST_RESET_IN 0x08
-#define PALMAS_SWOFF_COLDRST_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_COLDRST_RESET_IN_SHIFT 0x03
#define PALMAS_SWOFF_COLDRST_SW_RST 0x04
-#define PALMAS_SWOFF_COLDRST_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_COLDRST_SW_RST_SHIFT 0x02
#define PALMAS_SWOFF_COLDRST_VSYS_LO 0x02
-#define PALMAS_SWOFF_COLDRST_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_COLDRST_VSYS_LO_SHIFT 0x01
#define PALMAS_SWOFF_COLDRST_GPADC_SHUTDOWN 0x01
-#define PALMAS_SWOFF_COLDRST_GPADC_SHUTDOWN_SHIFT 0
+#define PALMAS_SWOFF_COLDRST_GPADC_SHUTDOWN_SHIFT 0x00
/* Bit definitions for SWOFF_STATUS */
#define PALMAS_SWOFF_STATUS_PWRON_LPK 0x80
-#define PALMAS_SWOFF_STATUS_PWRON_LPK_SHIFT 7
+#define PALMAS_SWOFF_STATUS_PWRON_LPK_SHIFT 0x07
#define PALMAS_SWOFF_STATUS_PWRDOWN 0x40
-#define PALMAS_SWOFF_STATUS_PWRDOWN_SHIFT 6
+#define PALMAS_SWOFF_STATUS_PWRDOWN_SHIFT 0x06
#define PALMAS_SWOFF_STATUS_WTD 0x20
-#define PALMAS_SWOFF_STATUS_WTD_SHIFT 5
+#define PALMAS_SWOFF_STATUS_WTD_SHIFT 0x05
#define PALMAS_SWOFF_STATUS_TSHUT 0x10
-#define PALMAS_SWOFF_STATUS_TSHUT_SHIFT 4
+#define PALMAS_SWOFF_STATUS_TSHUT_SHIFT 0x04
#define PALMAS_SWOFF_STATUS_RESET_IN 0x08
-#define PALMAS_SWOFF_STATUS_RESET_IN_SHIFT 3
+#define PALMAS_SWOFF_STATUS_RESET_IN_SHIFT 0x03
#define PALMAS_SWOFF_STATUS_SW_RST 0x04
-#define PALMAS_SWOFF_STATUS_SW_RST_SHIFT 2
+#define PALMAS_SWOFF_STATUS_SW_RST_SHIFT 0x02
#define PALMAS_SWOFF_STATUS_VSYS_LO 0x02
-#define PALMAS_SWOFF_STATUS_VSYS_LO_SHIFT 1
+#define PALMAS_SWOFF_STATUS_VSYS_LO_SHIFT 0x01
#define PALMAS_SWOFF_STATUS_GPADC_SHUTDOWN 0x01
-#define PALMAS_SWOFF_STATUS_GPADC_SHUTDOWN_SHIFT 0
+#define PALMAS_SWOFF_STATUS_GPADC_SHUTDOWN_SHIFT 0x00
/* Bit definitions for PMU_CONFIG */
#define PALMAS_PMU_CONFIG_MULTI_CELL_EN 0x40
-#define PALMAS_PMU_CONFIG_MULTI_CELL_EN_SHIFT 6
+#define PALMAS_PMU_CONFIG_MULTI_CELL_EN_SHIFT 0x06
#define PALMAS_PMU_CONFIG_SPARE_MASK 0x30
-#define PALMAS_PMU_CONFIG_SPARE_SHIFT 4
+#define PALMAS_PMU_CONFIG_SPARE_SHIFT 0x04
#define PALMAS_PMU_CONFIG_SWOFF_DLY_MASK 0x0c
-#define PALMAS_PMU_CONFIG_SWOFF_DLY_SHIFT 2
+#define PALMAS_PMU_CONFIG_SWOFF_DLY_SHIFT 0x02
#define PALMAS_PMU_CONFIG_GATE_RESET_OUT 0x02
-#define PALMAS_PMU_CONFIG_GATE_RESET_OUT_SHIFT 1
+#define PALMAS_PMU_CONFIG_GATE_RESET_OUT_SHIFT 0x01
#define PALMAS_PMU_CONFIG_AUTODEVON 0x01
-#define PALMAS_PMU_CONFIG_AUTODEVON_SHIFT 0
+#define PALMAS_PMU_CONFIG_AUTODEVON_SHIFT 0x00
/* Bit definitions for SPARE */
#define PALMAS_SPARE_SPARE_MASK 0xf8
-#define PALMAS_SPARE_SPARE_SHIFT 3
+#define PALMAS_SPARE_SPARE_SHIFT 0x03
#define PALMAS_SPARE_REGEN3_OD 0x04
-#define PALMAS_SPARE_REGEN3_OD_SHIFT 2
+#define PALMAS_SPARE_REGEN3_OD_SHIFT 0x02
#define PALMAS_SPARE_REGEN2_OD 0x02
-#define PALMAS_SPARE_REGEN2_OD_SHIFT 1
+#define PALMAS_SPARE_REGEN2_OD_SHIFT 0x01
#define PALMAS_SPARE_REGEN1_OD 0x01
-#define PALMAS_SPARE_REGEN1_OD_SHIFT 0
+#define PALMAS_SPARE_REGEN1_OD_SHIFT 0x00
/* Bit definitions for PMU_SECONDARY_INT */
#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_INT_SRC 0x80
-#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_INT_SRC_SHIFT 7
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_INT_SRC_SHIFT 0x07
#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_INT_SRC 0x40
-#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_INT_SRC_SHIFT 6
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_INT_SRC_SHIFT 0x06
#define PALMAS_PMU_SECONDARY_INT_BB_INT_SRC 0x20
-#define PALMAS_PMU_SECONDARY_INT_BB_INT_SRC_SHIFT 5
+#define PALMAS_PMU_SECONDARY_INT_BB_INT_SRC_SHIFT 0x05
#define PALMAS_PMU_SECONDARY_INT_FBI_INT_SRC 0x10
-#define PALMAS_PMU_SECONDARY_INT_FBI_INT_SRC_SHIFT 4
+#define PALMAS_PMU_SECONDARY_INT_FBI_INT_SRC_SHIFT 0x04
#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_MASK 0x08
-#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_MASK_SHIFT 3
+#define PALMAS_PMU_SECONDARY_INT_VBUS_OVV_MASK_SHIFT 0x03
#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_MASK 0x04
-#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_MASK_SHIFT 2
+#define PALMAS_PMU_SECONDARY_INT_CHARG_DET_N_MASK_SHIFT 0x02
#define PALMAS_PMU_SECONDARY_INT_BB_MASK 0x02
-#define PALMAS_PMU_SECONDARY_INT_BB_MASK_SHIFT 1
+#define PALMAS_PMU_SECONDARY_INT_BB_MASK_SHIFT 0x01
#define PALMAS_PMU_SECONDARY_INT_FBI_MASK 0x01
-#define PALMAS_PMU_SECONDARY_INT_FBI_MASK_SHIFT 0
+#define PALMAS_PMU_SECONDARY_INT_FBI_MASK_SHIFT 0x00
/* Bit definitions for SW_REVISION */
-#define PALMAS_SW_REVISION_SW_REVISION_MASK 0xff
-#define PALMAS_SW_REVISION_SW_REVISION_SHIFT 0
+#define PALMAS_SW_REVISION_SW_REVISION_MASK 0xFF
+#define PALMAS_SW_REVISION_SW_REVISION_SHIFT 0x00
/* Bit definitions for EXT_CHRG_CTRL */
#define PALMAS_EXT_CHRG_CTRL_VBUS_OVV_STATUS 0x80
-#define PALMAS_EXT_CHRG_CTRL_VBUS_OVV_STATUS_SHIFT 7
+#define PALMAS_EXT_CHRG_CTRL_VBUS_OVV_STATUS_SHIFT 0x07
#define PALMAS_EXT_CHRG_CTRL_CHARG_DET_N_STATUS 0x40
-#define PALMAS_EXT_CHRG_CTRL_CHARG_DET_N_STATUS_SHIFT 6
+#define PALMAS_EXT_CHRG_CTRL_CHARG_DET_N_STATUS_SHIFT 0x06
#define PALMAS_EXT_CHRG_CTRL_VSYS_DEBOUNCE_DELAY 0x08
-#define PALMAS_EXT_CHRG_CTRL_VSYS_DEBOUNCE_DELAY_SHIFT 3
+#define PALMAS_EXT_CHRG_CTRL_VSYS_DEBOUNCE_DELAY_SHIFT 0x03
#define PALMAS_EXT_CHRG_CTRL_CHRG_DET_N 0x04
-#define PALMAS_EXT_CHRG_CTRL_CHRG_DET_N_SHIFT 2
+#define PALMAS_EXT_CHRG_CTRL_CHRG_DET_N_SHIFT 0x02
#define PALMAS_EXT_CHRG_CTRL_AUTO_ACA_EN 0x02
-#define PALMAS_EXT_CHRG_CTRL_AUTO_ACA_EN_SHIFT 1
+#define PALMAS_EXT_CHRG_CTRL_AUTO_ACA_EN_SHIFT 0x01
#define PALMAS_EXT_CHRG_CTRL_AUTO_LDOUSB_EN 0x01
-#define PALMAS_EXT_CHRG_CTRL_AUTO_LDOUSB_EN_SHIFT 0
+#define PALMAS_EXT_CHRG_CTRL_AUTO_LDOUSB_EN_SHIFT 0x00
/* Bit definitions for PMU_SECONDARY_INT2 */
#define PALMAS_PMU_SECONDARY_INT2_DVFS2_INT_SRC 0x20
-#define PALMAS_PMU_SECONDARY_INT2_DVFS2_INT_SRC_SHIFT 5
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_INT_SRC_SHIFT 0x05
#define PALMAS_PMU_SECONDARY_INT2_DVFS1_INT_SRC 0x10
-#define PALMAS_PMU_SECONDARY_INT2_DVFS1_INT_SRC_SHIFT 4
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_INT_SRC_SHIFT 0x04
#define PALMAS_PMU_SECONDARY_INT2_DVFS2_MASK 0x02
-#define PALMAS_PMU_SECONDARY_INT2_DVFS2_MASK_SHIFT 1
+#define PALMAS_PMU_SECONDARY_INT2_DVFS2_MASK_SHIFT 0x01
#define PALMAS_PMU_SECONDARY_INT2_DVFS1_MASK 0x01
-#define PALMAS_PMU_SECONDARY_INT2_DVFS1_MASK_SHIFT 0
+#define PALMAS_PMU_SECONDARY_INT2_DVFS1_MASK_SHIFT 0x00
/* Registers for function RESOURCE */
-#define PALMAS_CLK32KG_CTRL 0x0
-#define PALMAS_CLK32KGAUDIO_CTRL 0x1
-#define PALMAS_REGEN1_CTRL 0x2
-#define PALMAS_REGEN2_CTRL 0x3
-#define PALMAS_SYSEN1_CTRL 0x4
-#define PALMAS_SYSEN2_CTRL 0x5
-#define PALMAS_NSLEEP_RES_ASSIGN 0x6
-#define PALMAS_NSLEEP_SMPS_ASSIGN 0x7
-#define PALMAS_NSLEEP_LDO_ASSIGN1 0x8
-#define PALMAS_NSLEEP_LDO_ASSIGN2 0x9
-#define PALMAS_ENABLE1_RES_ASSIGN 0xA
-#define PALMAS_ENABLE1_SMPS_ASSIGN 0xB
-#define PALMAS_ENABLE1_LDO_ASSIGN1 0xC
-#define PALMAS_ENABLE1_LDO_ASSIGN2 0xD
-#define PALMAS_ENABLE2_RES_ASSIGN 0xE
-#define PALMAS_ENABLE2_SMPS_ASSIGN 0xF
+#define PALMAS_CLK32KG_CTRL 0x00
+#define PALMAS_CLK32KGAUDIO_CTRL 0x01
+#define PALMAS_REGEN1_CTRL 0x02
+#define PALMAS_REGEN2_CTRL 0x03
+#define PALMAS_SYSEN1_CTRL 0x04
+#define PALMAS_SYSEN2_CTRL 0x05
+#define PALMAS_NSLEEP_RES_ASSIGN 0x06
+#define PALMAS_NSLEEP_SMPS_ASSIGN 0x07
+#define PALMAS_NSLEEP_LDO_ASSIGN1 0x08
+#define PALMAS_NSLEEP_LDO_ASSIGN2 0x09
+#define PALMAS_ENABLE1_RES_ASSIGN 0x0A
+#define PALMAS_ENABLE1_SMPS_ASSIGN 0x0B
+#define PALMAS_ENABLE1_LDO_ASSIGN1 0x0C
+#define PALMAS_ENABLE1_LDO_ASSIGN2 0x0D
+#define PALMAS_ENABLE2_RES_ASSIGN 0x0E
+#define PALMAS_ENABLE2_SMPS_ASSIGN 0x0F
#define PALMAS_ENABLE2_LDO_ASSIGN1 0x10
#define PALMAS_ENABLE2_LDO_ASSIGN2 0x11
#define PALMAS_REGEN3_CTRL 0x12
/* Bit definitions for CLK32KG_CTRL */
#define PALMAS_CLK32KG_CTRL_STATUS 0x10
-#define PALMAS_CLK32KG_CTRL_STATUS_SHIFT 4
+#define PALMAS_CLK32KG_CTRL_STATUS_SHIFT 0x04
#define PALMAS_CLK32KG_CTRL_MODE_SLEEP 0x04
-#define PALMAS_CLK32KG_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_CLK32KG_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_CLK32KG_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_CLK32KG_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_CLK32KG_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for CLK32KGAUDIO_CTRL */
#define PALMAS_CLK32KGAUDIO_CTRL_STATUS 0x10
-#define PALMAS_CLK32KGAUDIO_CTRL_STATUS_SHIFT 4
+#define PALMAS_CLK32KGAUDIO_CTRL_STATUS_SHIFT 0x04
#define PALMAS_CLK32KGAUDIO_CTRL_RESERVED3 0x08
-#define PALMAS_CLK32KGAUDIO_CTRL_RESERVED3_SHIFT 3
+#define PALMAS_CLK32KGAUDIO_CTRL_RESERVED3_SHIFT 0x03
#define PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP 0x04
-#define PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_CLK32KGAUDIO_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for REGEN1_CTRL */
#define PALMAS_REGEN1_CTRL_STATUS 0x10
-#define PALMAS_REGEN1_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN1_CTRL_STATUS_SHIFT 0x04
#define PALMAS_REGEN1_CTRL_MODE_SLEEP 0x04
-#define PALMAS_REGEN1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN1_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_REGEN1_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_REGEN1_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_REGEN1_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for REGEN2_CTRL */
#define PALMAS_REGEN2_CTRL_STATUS 0x10
-#define PALMAS_REGEN2_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN2_CTRL_STATUS_SHIFT 0x04
#define PALMAS_REGEN2_CTRL_MODE_SLEEP 0x04
-#define PALMAS_REGEN2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN2_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_REGEN2_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_REGEN2_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_REGEN2_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SYSEN1_CTRL */
#define PALMAS_SYSEN1_CTRL_STATUS 0x10
-#define PALMAS_SYSEN1_CTRL_STATUS_SHIFT 4
+#define PALMAS_SYSEN1_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SYSEN1_CTRL_MODE_SLEEP 0x04
-#define PALMAS_SYSEN1_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SYSEN1_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SYSEN1_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_SYSEN1_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SYSEN1_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for SYSEN2_CTRL */
#define PALMAS_SYSEN2_CTRL_STATUS 0x10
-#define PALMAS_SYSEN2_CTRL_STATUS_SHIFT 4
+#define PALMAS_SYSEN2_CTRL_STATUS_SHIFT 0x04
#define PALMAS_SYSEN2_CTRL_MODE_SLEEP 0x04
-#define PALMAS_SYSEN2_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_SYSEN2_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_SYSEN2_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_SYSEN2_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_SYSEN2_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Bit definitions for NSLEEP_RES_ASSIGN */
#define PALMAS_NSLEEP_RES_ASSIGN_REGEN3 0x40
-#define PALMAS_NSLEEP_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN3_SHIFT 0x06
#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KGAUDIO 0x20
-#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KGAUDIO_SHIFT 0x05
#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KG 0x10
-#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_NSLEEP_RES_ASSIGN_CLK32KG_SHIFT 0x04
#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN2 0x08
-#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN2_SHIFT 0x03
#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN1 0x04
-#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_NSLEEP_RES_ASSIGN_SYSEN1_SHIFT 0x02
#define PALMAS_NSLEEP_RES_ASSIGN_REGEN2 0x02
-#define PALMAS_NSLEEP_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN2_SHIFT 0x01
#define PALMAS_NSLEEP_RES_ASSIGN_REGEN1 0x01
-#define PALMAS_NSLEEP_RES_ASSIGN_REGEN1_SHIFT 0
+#define PALMAS_NSLEEP_RES_ASSIGN_REGEN1_SHIFT 0x00
/* Bit definitions for NSLEEP_SMPS_ASSIGN */
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS10 0x80
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS10_SHIFT 0x07
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS9 0x40
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS9_SHIFT 0x06
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS8 0x20
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS8_SHIFT 0x05
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS7 0x10
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS7_SHIFT 0x04
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS6 0x08
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS6_SHIFT 0x03
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS45 0x04
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS45_SHIFT 0x02
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS3 0x02
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS3_SHIFT 0x01
#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS12 0x01
-#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS12_SHIFT 0
+#define PALMAS_NSLEEP_SMPS_ASSIGN_SMPS12_SHIFT 0x00
/* Bit definitions for NSLEEP_LDO_ASSIGN1 */
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO8 0x80
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO8_SHIFT 0x07
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO7 0x40
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO7_SHIFT 0x06
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO6 0x20
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO6_SHIFT 0x05
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO5 0x10
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO5_SHIFT 0x04
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO4 0x08
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO4_SHIFT 0x03
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO3 0x04
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO3_SHIFT 0x02
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO2 0x02
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO2_SHIFT 0x01
#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO1 0x01
-#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO1_SHIFT 0
+#define PALMAS_NSLEEP_LDO_ASSIGN1_LDO1_SHIFT 0x00
/* Bit definitions for NSLEEP_LDO_ASSIGN2 */
#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOUSB 0x04
-#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOUSB_SHIFT 0x02
#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOLN 0x02
-#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDOLN_SHIFT 0x01
#define PALMAS_NSLEEP_LDO_ASSIGN2_LDO9 0x01
-#define PALMAS_NSLEEP_LDO_ASSIGN2_LDO9_SHIFT 0
+#define PALMAS_NSLEEP_LDO_ASSIGN2_LDO9_SHIFT 0x00
/* Bit definitions for ENABLE1_RES_ASSIGN */
#define PALMAS_ENABLE1_RES_ASSIGN_REGEN3 0x40
-#define PALMAS_ENABLE1_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN3_SHIFT 0x06
#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KGAUDIO 0x20
-#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KGAUDIO_SHIFT 0x05
#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KG 0x10
-#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_ENABLE1_RES_ASSIGN_CLK32KG_SHIFT 0x04
#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN2 0x08
-#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN2_SHIFT 0x03
#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN1 0x04
-#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_ENABLE1_RES_ASSIGN_SYSEN1_SHIFT 0x02
#define PALMAS_ENABLE1_RES_ASSIGN_REGEN2 0x02
-#define PALMAS_ENABLE1_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN2_SHIFT 0x01
#define PALMAS_ENABLE1_RES_ASSIGN_REGEN1 0x01
-#define PALMAS_ENABLE1_RES_ASSIGN_REGEN1_SHIFT 0
+#define PALMAS_ENABLE1_RES_ASSIGN_REGEN1_SHIFT 0x00
/* Bit definitions for ENABLE1_SMPS_ASSIGN */
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS10 0x80
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS10_SHIFT 0x07
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS9 0x40
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS9_SHIFT 0x06
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS8 0x20
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS8_SHIFT 0x05
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS7 0x10
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS7_SHIFT 0x04
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS6 0x08
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS6_SHIFT 0x03
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS45 0x04
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS45_SHIFT 0x02
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS3 0x02
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS3_SHIFT 0x01
#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS12 0x01
-#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS12_SHIFT 0
+#define PALMAS_ENABLE1_SMPS_ASSIGN_SMPS12_SHIFT 0x00
/* Bit definitions for ENABLE1_LDO_ASSIGN1 */
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO8 0x80
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO8_SHIFT 0x07
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO7 0x40
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO7_SHIFT 0x06
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO6 0x20
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO6_SHIFT 0x05
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO5 0x10
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO5_SHIFT 0x04
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO4 0x08
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO4_SHIFT 0x03
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO3 0x04
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO3_SHIFT 0x02
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO2 0x02
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO2_SHIFT 0x01
#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO1 0x01
-#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO1_SHIFT 0
+#define PALMAS_ENABLE1_LDO_ASSIGN1_LDO1_SHIFT 0x00
/* Bit definitions for ENABLE1_LDO_ASSIGN2 */
#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOUSB 0x04
-#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOUSB_SHIFT 0x02
#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOLN 0x02
-#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDOLN_SHIFT 0x01
#define PALMAS_ENABLE1_LDO_ASSIGN2_LDO9 0x01
-#define PALMAS_ENABLE1_LDO_ASSIGN2_LDO9_SHIFT 0
+#define PALMAS_ENABLE1_LDO_ASSIGN2_LDO9_SHIFT 0x00
/* Bit definitions for ENABLE2_RES_ASSIGN */
#define PALMAS_ENABLE2_RES_ASSIGN_REGEN3 0x40
-#define PALMAS_ENABLE2_RES_ASSIGN_REGEN3_SHIFT 6
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN3_SHIFT 0x06
#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KGAUDIO 0x20
-#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KGAUDIO_SHIFT 5
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KGAUDIO_SHIFT 0x05
#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KG 0x10
-#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KG_SHIFT 4
+#define PALMAS_ENABLE2_RES_ASSIGN_CLK32KG_SHIFT 0x04
#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN2 0x08
-#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN2_SHIFT 3
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN2_SHIFT 0x03
#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN1 0x04
-#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN1_SHIFT 2
+#define PALMAS_ENABLE2_RES_ASSIGN_SYSEN1_SHIFT 0x02
#define PALMAS_ENABLE2_RES_ASSIGN_REGEN2 0x02
-#define PALMAS_ENABLE2_RES_ASSIGN_REGEN2_SHIFT 1
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN2_SHIFT 0x01
#define PALMAS_ENABLE2_RES_ASSIGN_REGEN1 0x01
-#define PALMAS_ENABLE2_RES_ASSIGN_REGEN1_SHIFT 0
+#define PALMAS_ENABLE2_RES_ASSIGN_REGEN1_SHIFT 0x00
/* Bit definitions for ENABLE2_SMPS_ASSIGN */
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS10 0x80
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS10_SHIFT 7
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS10_SHIFT 0x07
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS9 0x40
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS9_SHIFT 6
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS9_SHIFT 0x06
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS8 0x20
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS8_SHIFT 5
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS8_SHIFT 0x05
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS7 0x10
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS7_SHIFT 4
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS7_SHIFT 0x04
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS6 0x08
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS6_SHIFT 3
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS6_SHIFT 0x03
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS45 0x04
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS45_SHIFT 2
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS45_SHIFT 0x02
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS3 0x02
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS3_SHIFT 1
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS3_SHIFT 0x01
#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS12 0x01
-#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS12_SHIFT 0
+#define PALMAS_ENABLE2_SMPS_ASSIGN_SMPS12_SHIFT 0x00
/* Bit definitions for ENABLE2_LDO_ASSIGN1 */
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO8 0x80
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO8_SHIFT 7
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO8_SHIFT 0x07
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO7 0x40
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO7_SHIFT 6
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO7_SHIFT 0x06
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO6 0x20
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO6_SHIFT 5
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO6_SHIFT 0x05
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO5 0x10
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO5_SHIFT 4
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO5_SHIFT 0x04
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO4 0x08
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO4_SHIFT 3
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO4_SHIFT 0x03
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO3 0x04
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO3_SHIFT 2
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO3_SHIFT 0x02
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO2 0x02
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO2_SHIFT 1
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO2_SHIFT 0x01
#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO1 0x01
-#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO1_SHIFT 0
+#define PALMAS_ENABLE2_LDO_ASSIGN1_LDO1_SHIFT 0x00
/* Bit definitions for ENABLE2_LDO_ASSIGN2 */
#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOUSB 0x04
-#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOUSB_SHIFT 2
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOUSB_SHIFT 0x02
#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOLN 0x02
-#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOLN_SHIFT 1
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDOLN_SHIFT 0x01
#define PALMAS_ENABLE2_LDO_ASSIGN2_LDO9 0x01
-#define PALMAS_ENABLE2_LDO_ASSIGN2_LDO9_SHIFT 0
+#define PALMAS_ENABLE2_LDO_ASSIGN2_LDO9_SHIFT 0x00
/* Bit definitions for REGEN3_CTRL */
#define PALMAS_REGEN3_CTRL_STATUS 0x10
-#define PALMAS_REGEN3_CTRL_STATUS_SHIFT 4
+#define PALMAS_REGEN3_CTRL_STATUS_SHIFT 0x04
#define PALMAS_REGEN3_CTRL_MODE_SLEEP 0x04
-#define PALMAS_REGEN3_CTRL_MODE_SLEEP_SHIFT 2
+#define PALMAS_REGEN3_CTRL_MODE_SLEEP_SHIFT 0x02
#define PALMAS_REGEN3_CTRL_MODE_ACTIVE 0x01
-#define PALMAS_REGEN3_CTRL_MODE_ACTIVE_SHIFT 0
+#define PALMAS_REGEN3_CTRL_MODE_ACTIVE_SHIFT 0x00
/* Registers for function PAD_CONTROL */
-#define PALMAS_OD_OUTPUT_CTRL2 0x2
-#define PALMAS_POLARITY_CTRL2 0x3
-#define PALMAS_PU_PD_INPUT_CTRL1 0x4
-#define PALMAS_PU_PD_INPUT_CTRL2 0x5
-#define PALMAS_PU_PD_INPUT_CTRL3 0x6
-#define PALMAS_PU_PD_INPUT_CTRL5 0x7
-#define PALMAS_OD_OUTPUT_CTRL 0x8
-#define PALMAS_POLARITY_CTRL 0x9
-#define PALMAS_PRIMARY_SECONDARY_PAD1 0xA
-#define PALMAS_PRIMARY_SECONDARY_PAD2 0xB
-#define PALMAS_I2C_SPI 0xC
-#define PALMAS_PU_PD_INPUT_CTRL4 0xD
-#define PALMAS_PRIMARY_SECONDARY_PAD3 0xE
-#define PALMAS_PRIMARY_SECONDARY_PAD4 0xF
+#define PALMAS_OD_OUTPUT_CTRL2 0x02
+#define PALMAS_POLARITY_CTRL2 0x03
+#define PALMAS_PU_PD_INPUT_CTRL1 0x04
+#define PALMAS_PU_PD_INPUT_CTRL2 0x05
+#define PALMAS_PU_PD_INPUT_CTRL3 0x06
+#define PALMAS_PU_PD_INPUT_CTRL5 0x07
+#define PALMAS_OD_OUTPUT_CTRL 0x08
+#define PALMAS_POLARITY_CTRL 0x09
+#define PALMAS_PRIMARY_SECONDARY_PAD1 0x0A
+#define PALMAS_PRIMARY_SECONDARY_PAD2 0x0B
+#define PALMAS_I2C_SPI 0x0C
+#define PALMAS_PU_PD_INPUT_CTRL4 0x0D
+#define PALMAS_PRIMARY_SECONDARY_PAD3 0x0E
+#define PALMAS_PRIMARY_SECONDARY_PAD4 0x0F
/* Bit definitions for PU_PD_INPUT_CTRL1 */
#define PALMAS_PU_PD_INPUT_CTRL1_RESET_IN_PD 0x40
-#define PALMAS_PU_PD_INPUT_CTRL1_RESET_IN_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL1_RESET_IN_PD_SHIFT 0x06
#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PU 0x20
-#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PU_SHIFT 5
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PU_SHIFT 0x05
#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PD 0x10
-#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL1_GPADC_START_PD_SHIFT 0x04
#define PALMAS_PU_PD_INPUT_CTRL1_PWRDOWN_PD 0x04
-#define PALMAS_PU_PD_INPUT_CTRL1_PWRDOWN_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL1_PWRDOWN_PD_SHIFT 0x02
#define PALMAS_PU_PD_INPUT_CTRL1_NRESWARM_PU 0x02
-#define PALMAS_PU_PD_INPUT_CTRL1_NRESWARM_PU_SHIFT 1
+#define PALMAS_PU_PD_INPUT_CTRL1_NRESWARM_PU_SHIFT 0x01
/* Bit definitions for PU_PD_INPUT_CTRL2 */
#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PU 0x20
-#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PU_SHIFT 5
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PU_SHIFT 0x05
#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PD 0x10
-#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE2_PD_SHIFT 0x04
#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PU 0x08
-#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PU_SHIFT 3
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PU_SHIFT 0x03
#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PD 0x04
-#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL2_ENABLE1_PD_SHIFT 0x02
#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PU 0x02
-#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PU_SHIFT 1
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PU_SHIFT 0x01
#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PD 0x01
-#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PD_SHIFT 0
+#define PALMAS_PU_PD_INPUT_CTRL2_NSLEEP_PD_SHIFT 0x00
/* Bit definitions for PU_PD_INPUT_CTRL3 */
#define PALMAS_PU_PD_INPUT_CTRL3_ACOK_PD 0x40
-#define PALMAS_PU_PD_INPUT_CTRL3_ACOK_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL3_ACOK_PD_SHIFT 0x06
#define PALMAS_PU_PD_INPUT_CTRL3_CHRG_DET_N_PD 0x10
-#define PALMAS_PU_PD_INPUT_CTRL3_CHRG_DET_N_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL3_CHRG_DET_N_PD_SHIFT 0x04
#define PALMAS_PU_PD_INPUT_CTRL3_POWERHOLD_PD 0x04
-#define PALMAS_PU_PD_INPUT_CTRL3_POWERHOLD_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL3_POWERHOLD_PD_SHIFT 0x02
#define PALMAS_PU_PD_INPUT_CTRL3_MSECURE_PD 0x01
-#define PALMAS_PU_PD_INPUT_CTRL3_MSECURE_PD_SHIFT 0
+#define PALMAS_PU_PD_INPUT_CTRL3_MSECURE_PD_SHIFT 0x00
/* Bit definitions for OD_OUTPUT_CTRL */
#define PALMAS_OD_OUTPUT_CTRL_PWM_2_OD 0x80
-#define PALMAS_OD_OUTPUT_CTRL_PWM_2_OD_SHIFT 7
+#define PALMAS_OD_OUTPUT_CTRL_PWM_2_OD_SHIFT 0x07
#define PALMAS_OD_OUTPUT_CTRL_VBUSDET_OD 0x40
-#define PALMAS_OD_OUTPUT_CTRL_VBUSDET_OD_SHIFT 6
+#define PALMAS_OD_OUTPUT_CTRL_VBUSDET_OD_SHIFT 0x06
#define PALMAS_OD_OUTPUT_CTRL_PWM_1_OD 0x20
-#define PALMAS_OD_OUTPUT_CTRL_PWM_1_OD_SHIFT 5
+#define PALMAS_OD_OUTPUT_CTRL_PWM_1_OD_SHIFT 0x05
#define PALMAS_OD_OUTPUT_CTRL_INT_OD 0x08
-#define PALMAS_OD_OUTPUT_CTRL_INT_OD_SHIFT 3
+#define PALMAS_OD_OUTPUT_CTRL_INT_OD_SHIFT 0x03
/* Bit definitions for POLARITY_CTRL */
#define PALMAS_POLARITY_CTRL_INT_POLARITY 0x80
-#define PALMAS_POLARITY_CTRL_INT_POLARITY_SHIFT 7
+#define PALMAS_POLARITY_CTRL_INT_POLARITY_SHIFT 0x07
#define PALMAS_POLARITY_CTRL_ENABLE2_POLARITY 0x40
-#define PALMAS_POLARITY_CTRL_ENABLE2_POLARITY_SHIFT 6
+#define PALMAS_POLARITY_CTRL_ENABLE2_POLARITY_SHIFT 0x06
#define PALMAS_POLARITY_CTRL_ENABLE1_POLARITY 0x20
-#define PALMAS_POLARITY_CTRL_ENABLE1_POLARITY_SHIFT 5
+#define PALMAS_POLARITY_CTRL_ENABLE1_POLARITY_SHIFT 0x05
#define PALMAS_POLARITY_CTRL_NSLEEP_POLARITY 0x10
-#define PALMAS_POLARITY_CTRL_NSLEEP_POLARITY_SHIFT 4
+#define PALMAS_POLARITY_CTRL_NSLEEP_POLARITY_SHIFT 0x04
#define PALMAS_POLARITY_CTRL_RESET_IN_POLARITY 0x08
-#define PALMAS_POLARITY_CTRL_RESET_IN_POLARITY_SHIFT 3
+#define PALMAS_POLARITY_CTRL_RESET_IN_POLARITY_SHIFT 0x03
#define PALMAS_POLARITY_CTRL_GPIO_3_CHRG_DET_N_POLARITY 0x04
-#define PALMAS_POLARITY_CTRL_GPIO_3_CHRG_DET_N_POLARITY_SHIFT 2
+#define PALMAS_POLARITY_CTRL_GPIO_3_CHRG_DET_N_POLARITY_SHIFT 0x02
#define PALMAS_POLARITY_CTRL_POWERGOOD_USB_PSEL_POLARITY 0x02
-#define PALMAS_POLARITY_CTRL_POWERGOOD_USB_PSEL_POLARITY_SHIFT 1
+#define PALMAS_POLARITY_CTRL_POWERGOOD_USB_PSEL_POLARITY_SHIFT 0x01
#define PALMAS_POLARITY_CTRL_PWRDOWN_POLARITY 0x01
-#define PALMAS_POLARITY_CTRL_PWRDOWN_POLARITY_SHIFT 0
+#define PALMAS_POLARITY_CTRL_PWRDOWN_POLARITY_SHIFT 0x00
/* Bit definitions for PRIMARY_SECONDARY_PAD1 */
#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3 0x80
-#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3_SHIFT 7
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3_SHIFT 0x07
#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK 0x60
-#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT 5
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT 0x05
#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK 0x18
-#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT 3
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT 0x03
#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0 0x04
-#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0_SHIFT 2
+#define PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0_SHIFT 0x02
#define PALMAS_PRIMARY_SECONDARY_PAD1_VAC 0x02
-#define PALMAS_PRIMARY_SECONDARY_PAD1_VAC_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD1_VAC_SHIFT 0x01
#define PALMAS_PRIMARY_SECONDARY_PAD1_POWERGOOD 0x01
-#define PALMAS_PRIMARY_SECONDARY_PAD1_POWERGOOD_SHIFT 0
+#define PALMAS_PRIMARY_SECONDARY_PAD1_POWERGOOD_SHIFT 0x00
/* Bit definitions for PRIMARY_SECONDARY_PAD2 */
#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK 0x30
-#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_SHIFT 4
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_SHIFT 0x04
#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6 0x08
-#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6_SHIFT 3
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6_SHIFT 0x03
#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK 0x06
-#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_SHIFT 0x01
#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4 0x01
-#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4_SHIFT 0
+#define PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4_SHIFT 0x00
/* Bit definitions for I2C_SPI */
#define PALMAS_I2C_SPI_I2C2OTP_EN 0x80
-#define PALMAS_I2C_SPI_I2C2OTP_EN_SHIFT 7
+#define PALMAS_I2C_SPI_I2C2OTP_EN_SHIFT 0x07
#define PALMAS_I2C_SPI_I2C2OTP_PAGESEL 0x40
-#define PALMAS_I2C_SPI_I2C2OTP_PAGESEL_SHIFT 6
+#define PALMAS_I2C_SPI_I2C2OTP_PAGESEL_SHIFT 0x06
#define PALMAS_I2C_SPI_ID_I2C2 0x20
-#define PALMAS_I2C_SPI_ID_I2C2_SHIFT 5
+#define PALMAS_I2C_SPI_ID_I2C2_SHIFT 0x05
#define PALMAS_I2C_SPI_I2C_SPI 0x10
-#define PALMAS_I2C_SPI_I2C_SPI_SHIFT 4
-#define PALMAS_I2C_SPI_ID_I2C1_MASK 0x0f
-#define PALMAS_I2C_SPI_ID_I2C1_SHIFT 0
+#define PALMAS_I2C_SPI_I2C_SPI_SHIFT 0x04
+#define PALMAS_I2C_SPI_ID_I2C1_MASK 0x0F
+#define PALMAS_I2C_SPI_ID_I2C1_SHIFT 0x00
/* Bit definitions for PU_PD_INPUT_CTRL4 */
#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_DAT_PD 0x40
-#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_DAT_PD_SHIFT 6
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_DAT_PD_SHIFT 0x06
#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_CLK_PD 0x10
-#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_CLK_PD_SHIFT 4
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS2_CLK_PD_SHIFT 0x04
#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_DAT_PD 0x04
-#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_DAT_PD_SHIFT 2
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_DAT_PD_SHIFT 0x02
#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_CLK_PD 0x01
-#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_CLK_PD_SHIFT 0
+#define PALMAS_PU_PD_INPUT_CTRL4_DVFS1_CLK_PD_SHIFT 0x00
/* Bit definitions for PRIMARY_SECONDARY_PAD3 */
#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS2 0x02
-#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS2_SHIFT 1
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS2_SHIFT 0x01
#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS1 0x01
-#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS1_SHIFT 0
+#define PALMAS_PRIMARY_SECONDARY_PAD3_DVFS1_SHIFT 0x00
/* Registers for function LED_PWM */
-#define PALMAS_LED_PERIOD_CTRL 0x0
-#define PALMAS_LED_CTRL 0x1
-#define PALMAS_PWM_CTRL1 0x2
-#define PALMAS_PWM_CTRL2 0x3
+#define PALMAS_LED_PERIOD_CTRL 0x00
+#define PALMAS_LED_CTRL 0x01
+#define PALMAS_PWM_CTRL1 0x02
+#define PALMAS_PWM_CTRL2 0x03
/* Bit definitions for LED_PERIOD_CTRL */
#define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_MASK 0x38
-#define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT 3
+#define PALMAS_LED_PERIOD_CTRL_LED_2_PERIOD_SHIFT 0x03
#define PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_MASK 0x07
-#define PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT 0
+#define PALMAS_LED_PERIOD_CTRL_LED_1_PERIOD_SHIFT 0x00
/* Bit definitions for LED_CTRL */
#define PALMAS_LED_CTRL_LED_2_SEQ 0x20
-#define PALMAS_LED_CTRL_LED_2_SEQ_SHIFT 5
+#define PALMAS_LED_CTRL_LED_2_SEQ_SHIFT 0x05
#define PALMAS_LED_CTRL_LED_1_SEQ 0x10
-#define PALMAS_LED_CTRL_LED_1_SEQ_SHIFT 4
+#define PALMAS_LED_CTRL_LED_1_SEQ_SHIFT 0x04
#define PALMAS_LED_CTRL_LED_2_ON_TIME_MASK 0x0c
-#define PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT 2
+#define PALMAS_LED_CTRL_LED_2_ON_TIME_SHIFT 0x02
#define PALMAS_LED_CTRL_LED_1_ON_TIME_MASK 0x03
-#define PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT 0
+#define PALMAS_LED_CTRL_LED_1_ON_TIME_SHIFT 0x00
/* Bit definitions for PWM_CTRL1 */
#define PALMAS_PWM_CTRL1_PWM_FREQ_EN 0x02
-#define PALMAS_PWM_CTRL1_PWM_FREQ_EN_SHIFT 1
+#define PALMAS_PWM_CTRL1_PWM_FREQ_EN_SHIFT 0x01
#define PALMAS_PWM_CTRL1_PWM_FREQ_SEL 0x01
-#define PALMAS_PWM_CTRL1_PWM_FREQ_SEL_SHIFT 0
+#define PALMAS_PWM_CTRL1_PWM_FREQ_SEL_SHIFT 0x00
/* Bit definitions for PWM_CTRL2 */
-#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_MASK 0xff
-#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_SHIFT 0
+#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_MASK 0xFF
+#define PALMAS_PWM_CTRL2_PWM_DUTY_SEL_SHIFT 0x00
/* Registers for function INTERRUPT */
-#define PALMAS_INT1_STATUS 0x0
-#define PALMAS_INT1_MASK 0x1
-#define PALMAS_INT1_LINE_STATE 0x2
-#define PALMAS_INT1_EDGE_DETECT1_RESERVED 0x3
-#define PALMAS_INT1_EDGE_DETECT2_RESERVED 0x4
-#define PALMAS_INT2_STATUS 0x5
-#define PALMAS_INT2_MASK 0x6
-#define PALMAS_INT2_LINE_STATE 0x7
-#define PALMAS_INT2_EDGE_DETECT1_RESERVED 0x8
-#define PALMAS_INT2_EDGE_DETECT2_RESERVED 0x9
-#define PALMAS_INT3_STATUS 0xA
-#define PALMAS_INT3_MASK 0xB
-#define PALMAS_INT3_LINE_STATE 0xC
-#define PALMAS_INT3_EDGE_DETECT1_RESERVED 0xD
-#define PALMAS_INT3_EDGE_DETECT2_RESERVED 0xE
-#define PALMAS_INT4_STATUS 0xF
+#define PALMAS_INT1_STATUS 0x00
+#define PALMAS_INT1_MASK 0x01
+#define PALMAS_INT1_LINE_STATE 0x02
+#define PALMAS_INT1_EDGE_DETECT1_RESERVED 0x03
+#define PALMAS_INT1_EDGE_DETECT2_RESERVED 0x04
+#define PALMAS_INT2_STATUS 0x05
+#define PALMAS_INT2_MASK 0x06
+#define PALMAS_INT2_LINE_STATE 0x07
+#define PALMAS_INT2_EDGE_DETECT1_RESERVED 0x08
+#define PALMAS_INT2_EDGE_DETECT2_RESERVED 0x09
+#define PALMAS_INT3_STATUS 0x0A
+#define PALMAS_INT3_MASK 0x0B
+#define PALMAS_INT3_LINE_STATE 0x0C
+#define PALMAS_INT3_EDGE_DETECT1_RESERVED 0x0D
+#define PALMAS_INT3_EDGE_DETECT2_RESERVED 0x0E
+#define PALMAS_INT4_STATUS 0x0F
#define PALMAS_INT4_MASK 0x10
#define PALMAS_INT4_LINE_STATE 0x11
#define PALMAS_INT4_EDGE_DETECT1 0x12
@@ -1966,276 +1966,276 @@ enum usb_irq_events {
/* Bit definitions for INT1_STATUS */
#define PALMAS_INT1_STATUS_VBAT_MON 0x80
-#define PALMAS_INT1_STATUS_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_STATUS_VBAT_MON_SHIFT 0x07
#define PALMAS_INT1_STATUS_VSYS_MON 0x40
-#define PALMAS_INT1_STATUS_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_STATUS_VSYS_MON_SHIFT 0x06
#define PALMAS_INT1_STATUS_HOTDIE 0x20
-#define PALMAS_INT1_STATUS_HOTDIE_SHIFT 5
+#define PALMAS_INT1_STATUS_HOTDIE_SHIFT 0x05
#define PALMAS_INT1_STATUS_PWRDOWN 0x10
-#define PALMAS_INT1_STATUS_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_STATUS_PWRDOWN_SHIFT 0x04
#define PALMAS_INT1_STATUS_RPWRON 0x08
-#define PALMAS_INT1_STATUS_RPWRON_SHIFT 3
+#define PALMAS_INT1_STATUS_RPWRON_SHIFT 0x03
#define PALMAS_INT1_STATUS_LONG_PRESS_KEY 0x04
-#define PALMAS_INT1_STATUS_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_STATUS_LONG_PRESS_KEY_SHIFT 0x02
#define PALMAS_INT1_STATUS_PWRON 0x02
-#define PALMAS_INT1_STATUS_PWRON_SHIFT 1
+#define PALMAS_INT1_STATUS_PWRON_SHIFT 0x01
#define PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV 0x01
-#define PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV_SHIFT 0
+#define PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV_SHIFT 0x00
/* Bit definitions for INT1_MASK */
#define PALMAS_INT1_MASK_VBAT_MON 0x80
-#define PALMAS_INT1_MASK_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_MASK_VBAT_MON_SHIFT 0x07
#define PALMAS_INT1_MASK_VSYS_MON 0x40
-#define PALMAS_INT1_MASK_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_MASK_VSYS_MON_SHIFT 0x06
#define PALMAS_INT1_MASK_HOTDIE 0x20
-#define PALMAS_INT1_MASK_HOTDIE_SHIFT 5
+#define PALMAS_INT1_MASK_HOTDIE_SHIFT 0x05
#define PALMAS_INT1_MASK_PWRDOWN 0x10
-#define PALMAS_INT1_MASK_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_MASK_PWRDOWN_SHIFT 0x04
#define PALMAS_INT1_MASK_RPWRON 0x08
-#define PALMAS_INT1_MASK_RPWRON_SHIFT 3
+#define PALMAS_INT1_MASK_RPWRON_SHIFT 0x03
#define PALMAS_INT1_MASK_LONG_PRESS_KEY 0x04
-#define PALMAS_INT1_MASK_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_MASK_LONG_PRESS_KEY_SHIFT 0x02
#define PALMAS_INT1_MASK_PWRON 0x02
-#define PALMAS_INT1_MASK_PWRON_SHIFT 1
+#define PALMAS_INT1_MASK_PWRON_SHIFT 0x01
#define PALMAS_INT1_MASK_CHARG_DET_N_VBUS_OVV 0x01
-#define PALMAS_INT1_MASK_CHARG_DET_N_VBUS_OVV_SHIFT 0
+#define PALMAS_INT1_MASK_CHARG_DET_N_VBUS_OVV_SHIFT 0x00
/* Bit definitions for INT1_LINE_STATE */
#define PALMAS_INT1_LINE_STATE_VBAT_MON 0x80
-#define PALMAS_INT1_LINE_STATE_VBAT_MON_SHIFT 7
+#define PALMAS_INT1_LINE_STATE_VBAT_MON_SHIFT 0x07
#define PALMAS_INT1_LINE_STATE_VSYS_MON 0x40
-#define PALMAS_INT1_LINE_STATE_VSYS_MON_SHIFT 6
+#define PALMAS_INT1_LINE_STATE_VSYS_MON_SHIFT 0x06
#define PALMAS_INT1_LINE_STATE_HOTDIE 0x20
-#define PALMAS_INT1_LINE_STATE_HOTDIE_SHIFT 5
+#define PALMAS_INT1_LINE_STATE_HOTDIE_SHIFT 0x05
#define PALMAS_INT1_LINE_STATE_PWRDOWN 0x10
-#define PALMAS_INT1_LINE_STATE_PWRDOWN_SHIFT 4
+#define PALMAS_INT1_LINE_STATE_PWRDOWN_SHIFT 0x04
#define PALMAS_INT1_LINE_STATE_RPWRON 0x08
-#define PALMAS_INT1_LINE_STATE_RPWRON_SHIFT 3
+#define PALMAS_INT1_LINE_STATE_RPWRON_SHIFT 0x03
#define PALMAS_INT1_LINE_STATE_LONG_PRESS_KEY 0x04
-#define PALMAS_INT1_LINE_STATE_LONG_PRESS_KEY_SHIFT 2
+#define PALMAS_INT1_LINE_STATE_LONG_PRESS_KEY_SHIFT 0x02
#define PALMAS_INT1_LINE_STATE_PWRON 0x02
-#define PALMAS_INT1_LINE_STATE_PWRON_SHIFT 1
+#define PALMAS_INT1_LINE_STATE_PWRON_SHIFT 0x01
#define PALMAS_INT1_LINE_STATE_CHARG_DET_N_VBUS_OVV 0x01
-#define PALMAS_INT1_LINE_STATE_CHARG_DET_N_VBUS_OVV_SHIFT 0
+#define PALMAS_INT1_LINE_STATE_CHARG_DET_N_VBUS_OVV_SHIFT 0x00
/* Bit definitions for INT2_STATUS */
#define PALMAS_INT2_STATUS_VAC_ACOK 0x80
-#define PALMAS_INT2_STATUS_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_STATUS_VAC_ACOK_SHIFT 0x07
#define PALMAS_INT2_STATUS_SHORT 0x40
-#define PALMAS_INT2_STATUS_SHORT_SHIFT 6
+#define PALMAS_INT2_STATUS_SHORT_SHIFT 0x06
#define PALMAS_INT2_STATUS_FBI_BB 0x20
-#define PALMAS_INT2_STATUS_FBI_BB_SHIFT 5
+#define PALMAS_INT2_STATUS_FBI_BB_SHIFT 0x05
#define PALMAS_INT2_STATUS_RESET_IN 0x10
-#define PALMAS_INT2_STATUS_RESET_IN_SHIFT 4
+#define PALMAS_INT2_STATUS_RESET_IN_SHIFT 0x04
#define PALMAS_INT2_STATUS_BATREMOVAL 0x08
-#define PALMAS_INT2_STATUS_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_STATUS_BATREMOVAL_SHIFT 0x03
#define PALMAS_INT2_STATUS_WDT 0x04
-#define PALMAS_INT2_STATUS_WDT_SHIFT 2
+#define PALMAS_INT2_STATUS_WDT_SHIFT 0x02
#define PALMAS_INT2_STATUS_RTC_TIMER 0x02
-#define PALMAS_INT2_STATUS_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_STATUS_RTC_TIMER_SHIFT 0x01
#define PALMAS_INT2_STATUS_RTC_ALARM 0x01
-#define PALMAS_INT2_STATUS_RTC_ALARM_SHIFT 0
+#define PALMAS_INT2_STATUS_RTC_ALARM_SHIFT 0x00
/* Bit definitions for INT2_MASK */
#define PALMAS_INT2_MASK_VAC_ACOK 0x80
-#define PALMAS_INT2_MASK_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_MASK_VAC_ACOK_SHIFT 0x07
#define PALMAS_INT2_MASK_SHORT 0x40
-#define PALMAS_INT2_MASK_SHORT_SHIFT 6
+#define PALMAS_INT2_MASK_SHORT_SHIFT 0x06
#define PALMAS_INT2_MASK_FBI_BB 0x20
-#define PALMAS_INT2_MASK_FBI_BB_SHIFT 5
+#define PALMAS_INT2_MASK_FBI_BB_SHIFT 0x05
#define PALMAS_INT2_MASK_RESET_IN 0x10
-#define PALMAS_INT2_MASK_RESET_IN_SHIFT 4
+#define PALMAS_INT2_MASK_RESET_IN_SHIFT 0x04
#define PALMAS_INT2_MASK_BATREMOVAL 0x08
-#define PALMAS_INT2_MASK_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_MASK_BATREMOVAL_SHIFT 0x03
#define PALMAS_INT2_MASK_WDT 0x04
-#define PALMAS_INT2_MASK_WDT_SHIFT 2
+#define PALMAS_INT2_MASK_WDT_SHIFT 0x02
#define PALMAS_INT2_MASK_RTC_TIMER 0x02
-#define PALMAS_INT2_MASK_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_MASK_RTC_TIMER_SHIFT 0x01
#define PALMAS_INT2_MASK_RTC_ALARM 0x01
-#define PALMAS_INT2_MASK_RTC_ALARM_SHIFT 0
+#define PALMAS_INT2_MASK_RTC_ALARM_SHIFT 0x00
/* Bit definitions for INT2_LINE_STATE */
#define PALMAS_INT2_LINE_STATE_VAC_ACOK 0x80
-#define PALMAS_INT2_LINE_STATE_VAC_ACOK_SHIFT 7
+#define PALMAS_INT2_LINE_STATE_VAC_ACOK_SHIFT 0x07
#define PALMAS_INT2_LINE_STATE_SHORT 0x40
-#define PALMAS_INT2_LINE_STATE_SHORT_SHIFT 6
+#define PALMAS_INT2_LINE_STATE_SHORT_SHIFT 0x06
#define PALMAS_INT2_LINE_STATE_FBI_BB 0x20
-#define PALMAS_INT2_LINE_STATE_FBI_BB_SHIFT 5
+#define PALMAS_INT2_LINE_STATE_FBI_BB_SHIFT 0x05
#define PALMAS_INT2_LINE_STATE_RESET_IN 0x10
-#define PALMAS_INT2_LINE_STATE_RESET_IN_SHIFT 4
+#define PALMAS_INT2_LINE_STATE_RESET_IN_SHIFT 0x04
#define PALMAS_INT2_LINE_STATE_BATREMOVAL 0x08
-#define PALMAS_INT2_LINE_STATE_BATREMOVAL_SHIFT 3
+#define PALMAS_INT2_LINE_STATE_BATREMOVAL_SHIFT 0x03
#define PALMAS_INT2_LINE_STATE_WDT 0x04
-#define PALMAS_INT2_LINE_STATE_WDT_SHIFT 2
+#define PALMAS_INT2_LINE_STATE_WDT_SHIFT 0x02
#define PALMAS_INT2_LINE_STATE_RTC_TIMER 0x02
-#define PALMAS_INT2_LINE_STATE_RTC_TIMER_SHIFT 1
+#define PALMAS_INT2_LINE_STATE_RTC_TIMER_SHIFT 0x01
#define PALMAS_INT2_LINE_STATE_RTC_ALARM 0x01
-#define PALMAS_INT2_LINE_STATE_RTC_ALARM_SHIFT 0
+#define PALMAS_INT2_LINE_STATE_RTC_ALARM_SHIFT 0x00
/* Bit definitions for INT3_STATUS */
#define PALMAS_INT3_STATUS_VBUS 0x80
-#define PALMAS_INT3_STATUS_VBUS_SHIFT 7
+#define PALMAS_INT3_STATUS_VBUS_SHIFT 0x07
#define PALMAS_INT3_STATUS_VBUS_OTG 0x40
-#define PALMAS_INT3_STATUS_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_STATUS_VBUS_OTG_SHIFT 0x06
#define PALMAS_INT3_STATUS_ID 0x20
-#define PALMAS_INT3_STATUS_ID_SHIFT 5
+#define PALMAS_INT3_STATUS_ID_SHIFT 0x05
#define PALMAS_INT3_STATUS_ID_OTG 0x10
-#define PALMAS_INT3_STATUS_ID_OTG_SHIFT 4
+#define PALMAS_INT3_STATUS_ID_OTG_SHIFT 0x04
#define PALMAS_INT3_STATUS_GPADC_EOC_RT 0x08
-#define PALMAS_INT3_STATUS_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_STATUS_GPADC_EOC_RT_SHIFT 0x03
#define PALMAS_INT3_STATUS_GPADC_EOC_SW 0x04
-#define PALMAS_INT3_STATUS_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_STATUS_GPADC_EOC_SW_SHIFT 0x02
#define PALMAS_INT3_STATUS_GPADC_AUTO_1 0x02
-#define PALMAS_INT3_STATUS_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_STATUS_GPADC_AUTO_1_SHIFT 0x01
#define PALMAS_INT3_STATUS_GPADC_AUTO_0 0x01
-#define PALMAS_INT3_STATUS_GPADC_AUTO_0_SHIFT 0
+#define PALMAS_INT3_STATUS_GPADC_AUTO_0_SHIFT 0x00
/* Bit definitions for INT3_MASK */
#define PALMAS_INT3_MASK_VBUS 0x80
-#define PALMAS_INT3_MASK_VBUS_SHIFT 7
+#define PALMAS_INT3_MASK_VBUS_SHIFT 0x07
#define PALMAS_INT3_MASK_VBUS_OTG 0x40
-#define PALMAS_INT3_MASK_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_MASK_VBUS_OTG_SHIFT 0x06
#define PALMAS_INT3_MASK_ID 0x20
-#define PALMAS_INT3_MASK_ID_SHIFT 5
+#define PALMAS_INT3_MASK_ID_SHIFT 0x05
#define PALMAS_INT3_MASK_ID_OTG 0x10
-#define PALMAS_INT3_MASK_ID_OTG_SHIFT 4
+#define PALMAS_INT3_MASK_ID_OTG_SHIFT 0x04
#define PALMAS_INT3_MASK_GPADC_EOC_RT 0x08
-#define PALMAS_INT3_MASK_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_MASK_GPADC_EOC_RT_SHIFT 0x03
#define PALMAS_INT3_MASK_GPADC_EOC_SW 0x04
-#define PALMAS_INT3_MASK_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_MASK_GPADC_EOC_SW_SHIFT 0x02
#define PALMAS_INT3_MASK_GPADC_AUTO_1 0x02
-#define PALMAS_INT3_MASK_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_MASK_GPADC_AUTO_1_SHIFT 0x01
#define PALMAS_INT3_MASK_GPADC_AUTO_0 0x01
-#define PALMAS_INT3_MASK_GPADC_AUTO_0_SHIFT 0
+#define PALMAS_INT3_MASK_GPADC_AUTO_0_SHIFT 0x00
/* Bit definitions for INT3_LINE_STATE */
#define PALMAS_INT3_LINE_STATE_VBUS 0x80
-#define PALMAS_INT3_LINE_STATE_VBUS_SHIFT 7
+#define PALMAS_INT3_LINE_STATE_VBUS_SHIFT 0x07
#define PALMAS_INT3_LINE_STATE_VBUS_OTG 0x40
-#define PALMAS_INT3_LINE_STATE_VBUS_OTG_SHIFT 6
+#define PALMAS_INT3_LINE_STATE_VBUS_OTG_SHIFT 0x06
#define PALMAS_INT3_LINE_STATE_ID 0x20
-#define PALMAS_INT3_LINE_STATE_ID_SHIFT 5
+#define PALMAS_INT3_LINE_STATE_ID_SHIFT 0x05
#define PALMAS_INT3_LINE_STATE_ID_OTG 0x10
-#define PALMAS_INT3_LINE_STATE_ID_OTG_SHIFT 4
+#define PALMAS_INT3_LINE_STATE_ID_OTG_SHIFT 0x04
#define PALMAS_INT3_LINE_STATE_GPADC_EOC_RT 0x08
-#define PALMAS_INT3_LINE_STATE_GPADC_EOC_RT_SHIFT 3
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_RT_SHIFT 0x03
#define PALMAS_INT3_LINE_STATE_GPADC_EOC_SW 0x04
-#define PALMAS_INT3_LINE_STATE_GPADC_EOC_SW_SHIFT 2
+#define PALMAS_INT3_LINE_STATE_GPADC_EOC_SW_SHIFT 0x02
#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_1 0x02
-#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_1_SHIFT 1
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_1_SHIFT 0x01
#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_0 0x01
-#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_0_SHIFT 0
+#define PALMAS_INT3_LINE_STATE_GPADC_AUTO_0_SHIFT 0x00
/* Bit definitions for INT4_STATUS */
#define PALMAS_INT4_STATUS_GPIO_7 0x80
-#define PALMAS_INT4_STATUS_GPIO_7_SHIFT 7
+#define PALMAS_INT4_STATUS_GPIO_7_SHIFT 0x07
#define PALMAS_INT4_STATUS_GPIO_6 0x40
-#define PALMAS_INT4_STATUS_GPIO_6_SHIFT 6
+#define PALMAS_INT4_STATUS_GPIO_6_SHIFT 0x06
#define PALMAS_INT4_STATUS_GPIO_5 0x20
-#define PALMAS_INT4_STATUS_GPIO_5_SHIFT 5
+#define PALMAS_INT4_STATUS_GPIO_5_SHIFT 0x05
#define PALMAS_INT4_STATUS_GPIO_4 0x10
-#define PALMAS_INT4_STATUS_GPIO_4_SHIFT 4
+#define PALMAS_INT4_STATUS_GPIO_4_SHIFT 0x04
#define PALMAS_INT4_STATUS_GPIO_3 0x08
-#define PALMAS_INT4_STATUS_GPIO_3_SHIFT 3
+#define PALMAS_INT4_STATUS_GPIO_3_SHIFT 0x03
#define PALMAS_INT4_STATUS_GPIO_2 0x04
-#define PALMAS_INT4_STATUS_GPIO_2_SHIFT 2
+#define PALMAS_INT4_STATUS_GPIO_2_SHIFT 0x02
#define PALMAS_INT4_STATUS_GPIO_1 0x02
-#define PALMAS_INT4_STATUS_GPIO_1_SHIFT 1
+#define PALMAS_INT4_STATUS_GPIO_1_SHIFT 0x01
#define PALMAS_INT4_STATUS_GPIO_0 0x01
-#define PALMAS_INT4_STATUS_GPIO_0_SHIFT 0
+#define PALMAS_INT4_STATUS_GPIO_0_SHIFT 0x00
/* Bit definitions for INT4_MASK */
#define PALMAS_INT4_MASK_GPIO_7 0x80
-#define PALMAS_INT4_MASK_GPIO_7_SHIFT 7
+#define PALMAS_INT4_MASK_GPIO_7_SHIFT 0x07
#define PALMAS_INT4_MASK_GPIO_6 0x40
-#define PALMAS_INT4_MASK_GPIO_6_SHIFT 6
+#define PALMAS_INT4_MASK_GPIO_6_SHIFT 0x06
#define PALMAS_INT4_MASK_GPIO_5 0x20
-#define PALMAS_INT4_MASK_GPIO_5_SHIFT 5
+#define PALMAS_INT4_MASK_GPIO_5_SHIFT 0x05
#define PALMAS_INT4_MASK_GPIO_4 0x10
-#define PALMAS_INT4_MASK_GPIO_4_SHIFT 4
+#define PALMAS_INT4_MASK_GPIO_4_SHIFT 0x04
#define PALMAS_INT4_MASK_GPIO_3 0x08
-#define PALMAS_INT4_MASK_GPIO_3_SHIFT 3
+#define PALMAS_INT4_MASK_GPIO_3_SHIFT 0x03
#define PALMAS_INT4_MASK_GPIO_2 0x04
-#define PALMAS_INT4_MASK_GPIO_2_SHIFT 2
+#define PALMAS_INT4_MASK_GPIO_2_SHIFT 0x02
#define PALMAS_INT4_MASK_GPIO_1 0x02
-#define PALMAS_INT4_MASK_GPIO_1_SHIFT 1
+#define PALMAS_INT4_MASK_GPIO_1_SHIFT 0x01
#define PALMAS_INT4_MASK_GPIO_0 0x01
-#define PALMAS_INT4_MASK_GPIO_0_SHIFT 0
+#define PALMAS_INT4_MASK_GPIO_0_SHIFT 0x00
/* Bit definitions for INT4_LINE_STATE */
#define PALMAS_INT4_LINE_STATE_GPIO_7 0x80
-#define PALMAS_INT4_LINE_STATE_GPIO_7_SHIFT 7
+#define PALMAS_INT4_LINE_STATE_GPIO_7_SHIFT 0x07
#define PALMAS_INT4_LINE_STATE_GPIO_6 0x40
-#define PALMAS_INT4_LINE_STATE_GPIO_6_SHIFT 6
+#define PALMAS_INT4_LINE_STATE_GPIO_6_SHIFT 0x06
#define PALMAS_INT4_LINE_STATE_GPIO_5 0x20
-#define PALMAS_INT4_LINE_STATE_GPIO_5_SHIFT 5
+#define PALMAS_INT4_LINE_STATE_GPIO_5_SHIFT 0x05
#define PALMAS_INT4_LINE_STATE_GPIO_4 0x10
-#define PALMAS_INT4_LINE_STATE_GPIO_4_SHIFT 4
+#define PALMAS_INT4_LINE_STATE_GPIO_4_SHIFT 0x04
#define PALMAS_INT4_LINE_STATE_GPIO_3 0x08
-#define PALMAS_INT4_LINE_STATE_GPIO_3_SHIFT 3
+#define PALMAS_INT4_LINE_STATE_GPIO_3_SHIFT 0x03
#define PALMAS_INT4_LINE_STATE_GPIO_2 0x04
-#define PALMAS_INT4_LINE_STATE_GPIO_2_SHIFT 2
+#define PALMAS_INT4_LINE_STATE_GPIO_2_SHIFT 0x02
#define PALMAS_INT4_LINE_STATE_GPIO_1 0x02
-#define PALMAS_INT4_LINE_STATE_GPIO_1_SHIFT 1
+#define PALMAS_INT4_LINE_STATE_GPIO_1_SHIFT 0x01
#define PALMAS_INT4_LINE_STATE_GPIO_0 0x01
-#define PALMAS_INT4_LINE_STATE_GPIO_0_SHIFT 0
+#define PALMAS_INT4_LINE_STATE_GPIO_0_SHIFT 0x00
/* Bit definitions for INT4_EDGE_DETECT1 */
#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_RISING 0x80
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_RISING_SHIFT 7
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_RISING_SHIFT 0x07
#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_FALLING 0x40
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_FALLING_SHIFT 6
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_3_FALLING_SHIFT 0x06
#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_RISING 0x20
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_RISING_SHIFT 5
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_RISING_SHIFT 0x05
#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_FALLING 0x10
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_FALLING_SHIFT 4
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_2_FALLING_SHIFT 0x04
#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_RISING 0x08
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_RISING_SHIFT 3
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_RISING_SHIFT 0x03
#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_FALLING 0x04
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_FALLING_SHIFT 2
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_1_FALLING_SHIFT 0x02
#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_RISING 0x02
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_RISING_SHIFT 1
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_RISING_SHIFT 0x01
#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_FALLING 0x01
-#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_FALLING_SHIFT 0
+#define PALMAS_INT4_EDGE_DETECT1_GPIO_0_FALLING_SHIFT 0x00
/* Bit definitions for INT4_EDGE_DETECT2 */
#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_RISING 0x80
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_RISING_SHIFT 7
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_RISING_SHIFT 0x07
#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_FALLING 0x40
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_FALLING_SHIFT 6
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_7_FALLING_SHIFT 0x06
#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_RISING 0x20
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_RISING_SHIFT 5
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_RISING_SHIFT 0x05
#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_FALLING 0x10
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_FALLING_SHIFT 4
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_6_FALLING_SHIFT 0x04
#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_RISING 0x08
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_RISING_SHIFT 3
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_RISING_SHIFT 0x03
#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_FALLING 0x04
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_FALLING_SHIFT 2
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_5_FALLING_SHIFT 0x02
#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_RISING 0x02
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_RISING_SHIFT 1
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_RISING_SHIFT 0x01
#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_FALLING 0x01
-#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_FALLING_SHIFT 0
+#define PALMAS_INT4_EDGE_DETECT2_GPIO_4_FALLING_SHIFT 0x00
/* Bit definitions for INT_CTRL */
#define PALMAS_INT_CTRL_INT_PENDING 0x04
-#define PALMAS_INT_CTRL_INT_PENDING_SHIFT 2
+#define PALMAS_INT_CTRL_INT_PENDING_SHIFT 0x02
#define PALMAS_INT_CTRL_INT_CLEAR 0x01
-#define PALMAS_INT_CTRL_INT_CLEAR_SHIFT 0
+#define PALMAS_INT_CTRL_INT_CLEAR_SHIFT 0x00
/* Registers for function USB_OTG */
-#define PALMAS_USB_WAKEUP 0x3
-#define PALMAS_USB_VBUS_CTRL_SET 0x4
-#define PALMAS_USB_VBUS_CTRL_CLR 0x5
-#define PALMAS_USB_ID_CTRL_SET 0x6
-#define PALMAS_USB_ID_CTRL_CLEAR 0x7
-#define PALMAS_USB_VBUS_INT_SRC 0x8
-#define PALMAS_USB_VBUS_INT_LATCH_SET 0x9
-#define PALMAS_USB_VBUS_INT_LATCH_CLR 0xA
-#define PALMAS_USB_VBUS_INT_EN_LO_SET 0xB
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR 0xC
-#define PALMAS_USB_VBUS_INT_EN_HI_SET 0xD
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR 0xE
-#define PALMAS_USB_ID_INT_SRC 0xF
+#define PALMAS_USB_WAKEUP 0x03
+#define PALMAS_USB_VBUS_CTRL_SET 0x04
+#define PALMAS_USB_VBUS_CTRL_CLR 0x05
+#define PALMAS_USB_ID_CTRL_SET 0x06
+#define PALMAS_USB_ID_CTRL_CLEAR 0x07
+#define PALMAS_USB_VBUS_INT_SRC 0x08
+#define PALMAS_USB_VBUS_INT_LATCH_SET 0x09
+#define PALMAS_USB_VBUS_INT_LATCH_CLR 0x0A
+#define PALMAS_USB_VBUS_INT_EN_LO_SET 0x0B
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR 0x0C
+#define PALMAS_USB_VBUS_INT_EN_HI_SET 0x0D
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR 0x0E
+#define PALMAS_USB_ID_INT_SRC 0x0F
#define PALMAS_USB_ID_INT_LATCH_SET 0x10
#define PALMAS_USB_ID_INT_LATCH_CLR 0x11
#define PALMAS_USB_ID_INT_EN_LO_SET 0x12
@@ -2250,306 +2250,306 @@ enum usb_irq_events {
/* Bit definitions for USB_WAKEUP */
#define PALMAS_USB_WAKEUP_ID_WK_UP_COMP 0x01
-#define PALMAS_USB_WAKEUP_ID_WK_UP_COMP_SHIFT 0
+#define PALMAS_USB_WAKEUP_ID_WK_UP_COMP_SHIFT 0x00
/* Bit definitions for USB_VBUS_CTRL_SET */
#define PALMAS_USB_VBUS_CTRL_SET_VBUS_CHRG_VSYS 0x80
-#define PALMAS_USB_VBUS_CTRL_SET_VBUS_CHRG_VSYS_SHIFT 7
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_CHRG_VSYS_SHIFT 0x07
#define PALMAS_USB_VBUS_CTRL_SET_VBUS_DISCHRG 0x20
-#define PALMAS_USB_VBUS_CTRL_SET_VBUS_DISCHRG_SHIFT 5
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_DISCHRG_SHIFT 0x05
#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SRC 0x10
-#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SRC_SHIFT 4
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SRC_SHIFT 0x04
#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SINK 0x08
-#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SINK_SHIFT 3
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_IADP_SINK_SHIFT 0x03
#define PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP 0x04
-#define PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP_SHIFT 2
+#define PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP_SHIFT 0x02
/* Bit definitions for USB_VBUS_CTRL_CLR */
#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_CHRG_VSYS 0x80
-#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_CHRG_VSYS_SHIFT 7
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_CHRG_VSYS_SHIFT 0x07
#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_DISCHRG 0x20
-#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_DISCHRG_SHIFT 5
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_DISCHRG_SHIFT 0x05
#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SRC 0x10
-#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SRC_SHIFT 4
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SRC_SHIFT 0x04
#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SINK 0x08
-#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SINK_SHIFT 3
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_IADP_SINK_SHIFT 0x03
#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_ACT_COMP 0x04
-#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_ACT_COMP_SHIFT 2
+#define PALMAS_USB_VBUS_CTRL_CLR_VBUS_ACT_COMP_SHIFT 0x02
/* Bit definitions for USB_ID_CTRL_SET */
#define PALMAS_USB_ID_CTRL_SET_ID_PU_220K 0x80
-#define PALMAS_USB_ID_CTRL_SET_ID_PU_220K_SHIFT 7
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_220K_SHIFT 0x07
#define PALMAS_USB_ID_CTRL_SET_ID_PU_100K 0x40
-#define PALMAS_USB_ID_CTRL_SET_ID_PU_100K_SHIFT 6
+#define PALMAS_USB_ID_CTRL_SET_ID_PU_100K_SHIFT 0x06
#define PALMAS_USB_ID_CTRL_SET_ID_GND_DRV 0x20
-#define PALMAS_USB_ID_CTRL_SET_ID_GND_DRV_SHIFT 5
+#define PALMAS_USB_ID_CTRL_SET_ID_GND_DRV_SHIFT 0x05
#define PALMAS_USB_ID_CTRL_SET_ID_SRC_16U 0x10
-#define PALMAS_USB_ID_CTRL_SET_ID_SRC_16U_SHIFT 4
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_16U_SHIFT 0x04
#define PALMAS_USB_ID_CTRL_SET_ID_SRC_5U 0x08
-#define PALMAS_USB_ID_CTRL_SET_ID_SRC_5U_SHIFT 3
+#define PALMAS_USB_ID_CTRL_SET_ID_SRC_5U_SHIFT 0x03
#define PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP 0x04
-#define PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP_SHIFT 2
+#define PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP_SHIFT 0x02
/* Bit definitions for USB_ID_CTRL_CLEAR */
#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_220K 0x80
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_220K_SHIFT 7
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_220K_SHIFT 0x07
#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_100K 0x40
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_100K_SHIFT 6
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_PU_100K_SHIFT 0x06
#define PALMAS_USB_ID_CTRL_CLEAR_ID_GND_DRV 0x20
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_GND_DRV_SHIFT 5
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_GND_DRV_SHIFT 0x05
#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_16U 0x10
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_16U_SHIFT 4
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_16U_SHIFT 0x04
#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_5U 0x08
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_5U_SHIFT 3
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_SRC_5U_SHIFT 0x03
#define PALMAS_USB_ID_CTRL_CLEAR_ID_ACT_COMP 0x04
-#define PALMAS_USB_ID_CTRL_CLEAR_ID_ACT_COMP_SHIFT 2
+#define PALMAS_USB_ID_CTRL_CLEAR_ID_ACT_COMP_SHIFT 0x02
/* Bit definitions for USB_VBUS_INT_SRC */
#define PALMAS_USB_VBUS_INT_SRC_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_SRC_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_SRC_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_SRC_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_SRC_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_SRC_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_SRC_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_SRC_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_SRC_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_SRC_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_SRC_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_SRC_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_SRC_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_SRC_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_SRC_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_SRC_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_LATCH_SET */
#define PALMAS_USB_VBUS_INT_LATCH_SET_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_LATCH_SET_ADP 0x10
-#define PALMAS_USB_VBUS_INT_LATCH_SET_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_LATCH_SET_ADP_SHIFT 0x04
#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_LATCH_SET_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_LATCH_CLR */
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_LATCH_CLR_ADP 0x10
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_ADP_SHIFT 0x04
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_LATCH_CLR_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_EN_LO_SET */
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_EN_LO_SET_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_EN_LO_CLR */
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_EN_LO_CLR_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_EN_HI_SET */
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_EN_HI_SET_ADP 0x10
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_ADP_SHIFT 0x04
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_EN_HI_SET_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_VBUS_INT_EN_HI_CLR */
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VOTG_SESS_VLD 0x80
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VOTG_SESS_VLD_SHIFT 7
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VOTG_SESS_VLD_SHIFT 0x07
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_PRB 0x40
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_PRB_SHIFT 6
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_PRB_SHIFT 0x06
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_SNS 0x20
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_SNS_SHIFT 5
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VADP_SNS_SHIFT 0x05
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_ADP 0x10
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_ADP_SHIFT 4
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_ADP_SHIFT 0x04
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_VBUS_VLD 0x08
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_VBUS_VLD_SHIFT 3
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_VBUS_VLD_SHIFT 0x03
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_SESS_VLD 0x04
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_SESS_VLD_SHIFT 2
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VA_SESS_VLD_SHIFT 0x02
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_VLD 0x02
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_VLD_SHIFT 1
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_VLD_SHIFT 0x01
#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_END 0x01
-#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_END_SHIFT 0
+#define PALMAS_USB_VBUS_INT_EN_HI_CLR_VB_SESS_END_SHIFT 0x00
/* Bit definitions for USB_ID_INT_SRC */
#define PALMAS_USB_ID_INT_SRC_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_SRC_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_SRC_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_SRC_ID_A 0x08
-#define PALMAS_USB_ID_INT_SRC_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_SRC_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_SRC_ID_B 0x04
-#define PALMAS_USB_ID_INT_SRC_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_SRC_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_SRC_ID_C 0x02
-#define PALMAS_USB_ID_INT_SRC_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_SRC_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_SRC_ID_GND 0x01
-#define PALMAS_USB_ID_INT_SRC_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_SRC_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_LATCH_SET */
#define PALMAS_USB_ID_INT_LATCH_SET_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_LATCH_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_LATCH_SET_ID_A 0x08
-#define PALMAS_USB_ID_INT_LATCH_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_LATCH_SET_ID_B 0x04
-#define PALMAS_USB_ID_INT_LATCH_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_LATCH_SET_ID_C 0x02
-#define PALMAS_USB_ID_INT_LATCH_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_LATCH_SET_ID_GND 0x01
-#define PALMAS_USB_ID_INT_LATCH_SET_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_LATCH_SET_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_LATCH_CLR */
#define PALMAS_USB_ID_INT_LATCH_CLR_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_LATCH_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_LATCH_CLR_ID_A 0x08
-#define PALMAS_USB_ID_INT_LATCH_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_LATCH_CLR_ID_B 0x04
-#define PALMAS_USB_ID_INT_LATCH_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_LATCH_CLR_ID_C 0x02
-#define PALMAS_USB_ID_INT_LATCH_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_LATCH_CLR_ID_GND 0x01
-#define PALMAS_USB_ID_INT_LATCH_CLR_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_LATCH_CLR_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_EN_LO_SET */
#define PALMAS_USB_ID_INT_EN_LO_SET_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_EN_LO_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_EN_LO_SET_ID_A 0x08
-#define PALMAS_USB_ID_INT_EN_LO_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_EN_LO_SET_ID_B 0x04
-#define PALMAS_USB_ID_INT_EN_LO_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_EN_LO_SET_ID_C 0x02
-#define PALMAS_USB_ID_INT_EN_LO_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_EN_LO_SET_ID_GND 0x01
-#define PALMAS_USB_ID_INT_EN_LO_SET_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_EN_LO_SET_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_EN_LO_CLR */
#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_A 0x08
-#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_B 0x04
-#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_C 0x02
-#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_GND 0x01
-#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_EN_LO_CLR_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_EN_HI_SET */
#define PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_EN_HI_SET_ID_A 0x08
-#define PALMAS_USB_ID_INT_EN_HI_SET_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_EN_HI_SET_ID_B 0x04
-#define PALMAS_USB_ID_INT_EN_HI_SET_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_EN_HI_SET_ID_C 0x02
-#define PALMAS_USB_ID_INT_EN_HI_SET_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_EN_HI_SET_ID_GND 0x01
-#define PALMAS_USB_ID_INT_EN_HI_SET_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_EN_HI_SET_ID_GND_SHIFT 0x00
/* Bit definitions for USB_ID_INT_EN_HI_CLR */
#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT 0x10
-#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT_SHIFT 4
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT_SHIFT 0x04
#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_A 0x08
-#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_A_SHIFT 3
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_A_SHIFT 0x03
#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_B 0x04
-#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_B_SHIFT 2
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_B_SHIFT 0x02
#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_C 0x02
-#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_C_SHIFT 1
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_C_SHIFT 0x01
#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND 0x01
-#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND_SHIFT 0
+#define PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND_SHIFT 0x00
/* Bit definitions for USB_OTG_ADP_CTRL */
#define PALMAS_USB_OTG_ADP_CTRL_ADP_EN 0x04
-#define PALMAS_USB_OTG_ADP_CTRL_ADP_EN_SHIFT 2
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_EN_SHIFT 0x02
#define PALMAS_USB_OTG_ADP_CTRL_ADP_MODE_MASK 0x03
-#define PALMAS_USB_OTG_ADP_CTRL_ADP_MODE_SHIFT 0
+#define PALMAS_USB_OTG_ADP_CTRL_ADP_MODE_SHIFT 0x00
/* Bit definitions for USB_OTG_ADP_HIGH */
-#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_MASK 0xff
-#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_SHIFT 0
+#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_MASK 0xFF
+#define PALMAS_USB_OTG_ADP_HIGH_T_ADP_HIGH_SHIFT 0x00
/* Bit definitions for USB_OTG_ADP_LOW */
-#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_MASK 0xff
-#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_SHIFT 0
+#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_MASK 0xFF
+#define PALMAS_USB_OTG_ADP_LOW_T_ADP_LOW_SHIFT 0x00
/* Bit definitions for USB_OTG_ADP_RISE */
-#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_MASK 0xff
-#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_SHIFT 0
+#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_MASK 0xFF
+#define PALMAS_USB_OTG_ADP_RISE_T_ADP_RISE_SHIFT 0x00
/* Bit definitions for USB_OTG_REVISION */
#define PALMAS_USB_OTG_REVISION_OTG_REV 0x01
-#define PALMAS_USB_OTG_REVISION_OTG_REV_SHIFT 0
+#define PALMAS_USB_OTG_REVISION_OTG_REV_SHIFT 0x00
/* Registers for function VIBRATOR */
-#define PALMAS_VIBRA_CTRL 0x0
+#define PALMAS_VIBRA_CTRL 0x00
/* Bit definitions for VIBRA_CTRL */
#define PALMAS_VIBRA_CTRL_PWM_DUTY_SEL_MASK 0x06
-#define PALMAS_VIBRA_CTRL_PWM_DUTY_SEL_SHIFT 1
+#define PALMAS_VIBRA_CTRL_PWM_DUTY_SEL_SHIFT 0x01
#define PALMAS_VIBRA_CTRL_PWM_FREQ_SEL 0x01
-#define PALMAS_VIBRA_CTRL_PWM_FREQ_SEL_SHIFT 0
+#define PALMAS_VIBRA_CTRL_PWM_FREQ_SEL_SHIFT 0x00
/* Registers for function GPIO */
-#define PALMAS_GPIO_DATA_IN 0x0
-#define PALMAS_GPIO_DATA_DIR 0x1
-#define PALMAS_GPIO_DATA_OUT 0x2
-#define PALMAS_GPIO_DEBOUNCE_EN 0x3
-#define PALMAS_GPIO_CLEAR_DATA_OUT 0x4
-#define PALMAS_GPIO_SET_DATA_OUT 0x5
-#define PALMAS_PU_PD_GPIO_CTRL1 0x6
-#define PALMAS_PU_PD_GPIO_CTRL2 0x7
-#define PALMAS_OD_OUTPUT_GPIO_CTRL 0x8
-#define PALMAS_GPIO_DATA_IN2 0x9
+#define PALMAS_GPIO_DATA_IN 0x00
+#define PALMAS_GPIO_DATA_DIR 0x01
+#define PALMAS_GPIO_DATA_OUT 0x02
+#define PALMAS_GPIO_DEBOUNCE_EN 0x03
+#define PALMAS_GPIO_CLEAR_DATA_OUT 0x04
+#define PALMAS_GPIO_SET_DATA_OUT 0x05
+#define PALMAS_PU_PD_GPIO_CTRL1 0x06
+#define PALMAS_PU_PD_GPIO_CTRL2 0x07
+#define PALMAS_OD_OUTPUT_GPIO_CTRL 0x08
+#define PALMAS_GPIO_DATA_IN2 0x09
#define PALMAS_GPIO_DATA_DIR2 0x0A
#define PALMAS_GPIO_DATA_OUT2 0x0B
#define PALMAS_GPIO_DEBOUNCE_EN2 0x0C
@@ -2561,167 +2561,167 @@ enum usb_irq_events {
/* Bit definitions for GPIO_DATA_IN */
#define PALMAS_GPIO_DATA_IN_GPIO_7_IN 0x80
-#define PALMAS_GPIO_DATA_IN_GPIO_7_IN_SHIFT 7
+#define PALMAS_GPIO_DATA_IN_GPIO_7_IN_SHIFT 0x07
#define PALMAS_GPIO_DATA_IN_GPIO_6_IN 0x40
-#define PALMAS_GPIO_DATA_IN_GPIO_6_IN_SHIFT 6
+#define PALMAS_GPIO_DATA_IN_GPIO_6_IN_SHIFT 0x06
#define PALMAS_GPIO_DATA_IN_GPIO_5_IN 0x20
-#define PALMAS_GPIO_DATA_IN_GPIO_5_IN_SHIFT 5
+#define PALMAS_GPIO_DATA_IN_GPIO_5_IN_SHIFT 0x05
#define PALMAS_GPIO_DATA_IN_GPIO_4_IN 0x10
-#define PALMAS_GPIO_DATA_IN_GPIO_4_IN_SHIFT 4
+#define PALMAS_GPIO_DATA_IN_GPIO_4_IN_SHIFT 0x04
#define PALMAS_GPIO_DATA_IN_GPIO_3_IN 0x08
-#define PALMAS_GPIO_DATA_IN_GPIO_3_IN_SHIFT 3
+#define PALMAS_GPIO_DATA_IN_GPIO_3_IN_SHIFT 0x03
#define PALMAS_GPIO_DATA_IN_GPIO_2_IN 0x04
-#define PALMAS_GPIO_DATA_IN_GPIO_2_IN_SHIFT 2
+#define PALMAS_GPIO_DATA_IN_GPIO_2_IN_SHIFT 0x02
#define PALMAS_GPIO_DATA_IN_GPIO_1_IN 0x02
-#define PALMAS_GPIO_DATA_IN_GPIO_1_IN_SHIFT 1
+#define PALMAS_GPIO_DATA_IN_GPIO_1_IN_SHIFT 0x01
#define PALMAS_GPIO_DATA_IN_GPIO_0_IN 0x01
-#define PALMAS_GPIO_DATA_IN_GPIO_0_IN_SHIFT 0
+#define PALMAS_GPIO_DATA_IN_GPIO_0_IN_SHIFT 0x00
/* Bit definitions for GPIO_DATA_DIR */
#define PALMAS_GPIO_DATA_DIR_GPIO_7_DIR 0x80
-#define PALMAS_GPIO_DATA_DIR_GPIO_7_DIR_SHIFT 7
+#define PALMAS_GPIO_DATA_DIR_GPIO_7_DIR_SHIFT 0x07
#define PALMAS_GPIO_DATA_DIR_GPIO_6_DIR 0x40
-#define PALMAS_GPIO_DATA_DIR_GPIO_6_DIR_SHIFT 6
+#define PALMAS_GPIO_DATA_DIR_GPIO_6_DIR_SHIFT 0x06
#define PALMAS_GPIO_DATA_DIR_GPIO_5_DIR 0x20
-#define PALMAS_GPIO_DATA_DIR_GPIO_5_DIR_SHIFT 5
+#define PALMAS_GPIO_DATA_DIR_GPIO_5_DIR_SHIFT 0x05
#define PALMAS_GPIO_DATA_DIR_GPIO_4_DIR 0x10
-#define PALMAS_GPIO_DATA_DIR_GPIO_4_DIR_SHIFT 4
+#define PALMAS_GPIO_DATA_DIR_GPIO_4_DIR_SHIFT 0x04
#define PALMAS_GPIO_DATA_DIR_GPIO_3_DIR 0x08
-#define PALMAS_GPIO_DATA_DIR_GPIO_3_DIR_SHIFT 3
+#define PALMAS_GPIO_DATA_DIR_GPIO_3_DIR_SHIFT 0x03
#define PALMAS_GPIO_DATA_DIR_GPIO_2_DIR 0x04
-#define PALMAS_GPIO_DATA_DIR_GPIO_2_DIR_SHIFT 2
+#define PALMAS_GPIO_DATA_DIR_GPIO_2_DIR_SHIFT 0x02
#define PALMAS_GPIO_DATA_DIR_GPIO_1_DIR 0x02
-#define PALMAS_GPIO_DATA_DIR_GPIO_1_DIR_SHIFT 1
+#define PALMAS_GPIO_DATA_DIR_GPIO_1_DIR_SHIFT 0x01
#define PALMAS_GPIO_DATA_DIR_GPIO_0_DIR 0x01
-#define PALMAS_GPIO_DATA_DIR_GPIO_0_DIR_SHIFT 0
+#define PALMAS_GPIO_DATA_DIR_GPIO_0_DIR_SHIFT 0x00
/* Bit definitions for GPIO_DATA_OUT */
#define PALMAS_GPIO_DATA_OUT_GPIO_7_OUT 0x80
-#define PALMAS_GPIO_DATA_OUT_GPIO_7_OUT_SHIFT 7
+#define PALMAS_GPIO_DATA_OUT_GPIO_7_OUT_SHIFT 0x07
#define PALMAS_GPIO_DATA_OUT_GPIO_6_OUT 0x40
-#define PALMAS_GPIO_DATA_OUT_GPIO_6_OUT_SHIFT 6
+#define PALMAS_GPIO_DATA_OUT_GPIO_6_OUT_SHIFT 0x06
#define PALMAS_GPIO_DATA_OUT_GPIO_5_OUT 0x20
-#define PALMAS_GPIO_DATA_OUT_GPIO_5_OUT_SHIFT 5
+#define PALMAS_GPIO_DATA_OUT_GPIO_5_OUT_SHIFT 0x05
#define PALMAS_GPIO_DATA_OUT_GPIO_4_OUT 0x10
-#define PALMAS_GPIO_DATA_OUT_GPIO_4_OUT_SHIFT 4
+#define PALMAS_GPIO_DATA_OUT_GPIO_4_OUT_SHIFT 0x04
#define PALMAS_GPIO_DATA_OUT_GPIO_3_OUT 0x08
-#define PALMAS_GPIO_DATA_OUT_GPIO_3_OUT_SHIFT 3
+#define PALMAS_GPIO_DATA_OUT_GPIO_3_OUT_SHIFT 0x03
#define PALMAS_GPIO_DATA_OUT_GPIO_2_OUT 0x04
-#define PALMAS_GPIO_DATA_OUT_GPIO_2_OUT_SHIFT 2
+#define PALMAS_GPIO_DATA_OUT_GPIO_2_OUT_SHIFT 0x02
#define PALMAS_GPIO_DATA_OUT_GPIO_1_OUT 0x02
-#define PALMAS_GPIO_DATA_OUT_GPIO_1_OUT_SHIFT 1
+#define PALMAS_GPIO_DATA_OUT_GPIO_1_OUT_SHIFT 0x01
#define PALMAS_GPIO_DATA_OUT_GPIO_0_OUT 0x01
-#define PALMAS_GPIO_DATA_OUT_GPIO_0_OUT_SHIFT 0
+#define PALMAS_GPIO_DATA_OUT_GPIO_0_OUT_SHIFT 0x00
/* Bit definitions for GPIO_DEBOUNCE_EN */
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_7_DEBOUNCE_EN 0x80
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_7_DEBOUNCE_EN_SHIFT 7
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_7_DEBOUNCE_EN_SHIFT 0x07
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_6_DEBOUNCE_EN 0x40
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_6_DEBOUNCE_EN_SHIFT 6
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_6_DEBOUNCE_EN_SHIFT 0x06
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_5_DEBOUNCE_EN 0x20
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_5_DEBOUNCE_EN_SHIFT 5
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_5_DEBOUNCE_EN_SHIFT 0x05
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_4_DEBOUNCE_EN 0x10
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_4_DEBOUNCE_EN_SHIFT 4
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_4_DEBOUNCE_EN_SHIFT 0x04
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_3_DEBOUNCE_EN 0x08
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_3_DEBOUNCE_EN_SHIFT 3
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_3_DEBOUNCE_EN_SHIFT 0x03
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_2_DEBOUNCE_EN 0x04
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_2_DEBOUNCE_EN_SHIFT 2
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_2_DEBOUNCE_EN_SHIFT 0x02
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_1_DEBOUNCE_EN 0x02
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_1_DEBOUNCE_EN_SHIFT 1
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_1_DEBOUNCE_EN_SHIFT 0x01
#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_0_DEBOUNCE_EN 0x01
-#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_0_DEBOUNCE_EN_SHIFT 0
+#define PALMAS_GPIO_DEBOUNCE_EN_GPIO_0_DEBOUNCE_EN_SHIFT 0x00
/* Bit definitions for GPIO_CLEAR_DATA_OUT */
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_7_CLEAR_DATA_OUT 0x80
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_7_CLEAR_DATA_OUT_SHIFT 7
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_7_CLEAR_DATA_OUT_SHIFT 0x07
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_6_CLEAR_DATA_OUT 0x40
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_6_CLEAR_DATA_OUT_SHIFT 6
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_6_CLEAR_DATA_OUT_SHIFT 0x06
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_5_CLEAR_DATA_OUT 0x20
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_5_CLEAR_DATA_OUT_SHIFT 5
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_5_CLEAR_DATA_OUT_SHIFT 0x05
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_4_CLEAR_DATA_OUT 0x10
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_4_CLEAR_DATA_OUT_SHIFT 4
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_4_CLEAR_DATA_OUT_SHIFT 0x04
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_3_CLEAR_DATA_OUT 0x08
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_3_CLEAR_DATA_OUT_SHIFT 3
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_3_CLEAR_DATA_OUT_SHIFT 0x03
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_2_CLEAR_DATA_OUT 0x04
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_2_CLEAR_DATA_OUT_SHIFT 2
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_2_CLEAR_DATA_OUT_SHIFT 0x02
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_1_CLEAR_DATA_OUT 0x02
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_1_CLEAR_DATA_OUT_SHIFT 1
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_1_CLEAR_DATA_OUT_SHIFT 0x01
#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_0_CLEAR_DATA_OUT 0x01
-#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_0_CLEAR_DATA_OUT_SHIFT 0
+#define PALMAS_GPIO_CLEAR_DATA_OUT_GPIO_0_CLEAR_DATA_OUT_SHIFT 0x00
/* Bit definitions for GPIO_SET_DATA_OUT */
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_7_SET_DATA_OUT 0x80
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_7_SET_DATA_OUT_SHIFT 7
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_7_SET_DATA_OUT_SHIFT 0x07
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_6_SET_DATA_OUT 0x40
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_6_SET_DATA_OUT_SHIFT 6
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_6_SET_DATA_OUT_SHIFT 0x06
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_5_SET_DATA_OUT 0x20
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_5_SET_DATA_OUT_SHIFT 5
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_5_SET_DATA_OUT_SHIFT 0x05
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_4_SET_DATA_OUT 0x10
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_4_SET_DATA_OUT_SHIFT 4
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_4_SET_DATA_OUT_SHIFT 0x04
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_3_SET_DATA_OUT 0x08
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_3_SET_DATA_OUT_SHIFT 3
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_3_SET_DATA_OUT_SHIFT 0x03
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_2_SET_DATA_OUT 0x04
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_2_SET_DATA_OUT_SHIFT 2
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_2_SET_DATA_OUT_SHIFT 0x02
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_1_SET_DATA_OUT 0x02
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_1_SET_DATA_OUT_SHIFT 1
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_1_SET_DATA_OUT_SHIFT 0x01
#define PALMAS_GPIO_SET_DATA_OUT_GPIO_0_SET_DATA_OUT 0x01
-#define PALMAS_GPIO_SET_DATA_OUT_GPIO_0_SET_DATA_OUT_SHIFT 0
+#define PALMAS_GPIO_SET_DATA_OUT_GPIO_0_SET_DATA_OUT_SHIFT 0x00
/* Bit definitions for PU_PD_GPIO_CTRL1 */
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_3_PD 0x40
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_3_PD_SHIFT 6
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_3_PD_SHIFT 0x06
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PU 0x20
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PU_SHIFT 5
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PU_SHIFT 0x05
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PD 0x10
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PD_SHIFT 4
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_2_PD_SHIFT 0x04
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PU 0x08
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PU_SHIFT 3
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PU_SHIFT 0x03
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PD 0x04
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PD_SHIFT 2
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_1_PD_SHIFT 0x02
#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_0_PD 0x01
-#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_0_PD_SHIFT 0
+#define PALMAS_PU_PD_GPIO_CTRL1_GPIO_0_PD_SHIFT 0x00
/* Bit definitions for PU_PD_GPIO_CTRL2 */
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_7_PD 0x40
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_7_PD_SHIFT 6
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_7_PD_SHIFT 0x06
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PU 0x20
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PU_SHIFT 5
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PU_SHIFT 0x05
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PD 0x10
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PD_SHIFT 4
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_6_PD_SHIFT 0x04
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PU 0x08
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PU_SHIFT 3
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PU_SHIFT 0x03
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PD 0x04
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PD_SHIFT 2
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_5_PD_SHIFT 0x02
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PU 0x02
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PU_SHIFT 1
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PU_SHIFT 0x01
#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PD 0x01
-#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PD_SHIFT 0
+#define PALMAS_PU_PD_GPIO_CTRL2_GPIO_4_PD_SHIFT 0x00
/* Bit definitions for OD_OUTPUT_GPIO_CTRL */
#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_5_OD 0x20
-#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_5_OD_SHIFT 5
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_5_OD_SHIFT 0x05
#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_2_OD 0x04
-#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_2_OD_SHIFT 2
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_2_OD_SHIFT 0x02
#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_1_OD 0x02
-#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_1_OD_SHIFT 1
+#define PALMAS_OD_OUTPUT_GPIO_CTRL_GPIO_1_OD_SHIFT 0x01
/* Registers for function GPADC */
-#define PALMAS_GPADC_CTRL1 0x0
-#define PALMAS_GPADC_CTRL2 0x1
-#define PALMAS_GPADC_RT_CTRL 0x2
-#define PALMAS_GPADC_AUTO_CTRL 0x3
-#define PALMAS_GPADC_STATUS 0x4
-#define PALMAS_GPADC_RT_SELECT 0x5
-#define PALMAS_GPADC_RT_CONV0_LSB 0x6
-#define PALMAS_GPADC_RT_CONV0_MSB 0x7
-#define PALMAS_GPADC_AUTO_SELECT 0x8
-#define PALMAS_GPADC_AUTO_CONV0_LSB 0x9
-#define PALMAS_GPADC_AUTO_CONV0_MSB 0xA
-#define PALMAS_GPADC_AUTO_CONV1_LSB 0xB
-#define PALMAS_GPADC_AUTO_CONV1_MSB 0xC
-#define PALMAS_GPADC_SW_SELECT 0xD
-#define PALMAS_GPADC_SW_CONV0_LSB 0xE
-#define PALMAS_GPADC_SW_CONV0_MSB 0xF
+#define PALMAS_GPADC_CTRL1 0x00
+#define PALMAS_GPADC_CTRL2 0x01
+#define PALMAS_GPADC_RT_CTRL 0x02
+#define PALMAS_GPADC_AUTO_CTRL 0x03
+#define PALMAS_GPADC_STATUS 0x04
+#define PALMAS_GPADC_RT_SELECT 0x05
+#define PALMAS_GPADC_RT_CONV0_LSB 0x06
+#define PALMAS_GPADC_RT_CONV0_MSB 0x07
+#define PALMAS_GPADC_AUTO_SELECT 0x08
+#define PALMAS_GPADC_AUTO_CONV0_LSB 0x09
+#define PALMAS_GPADC_AUTO_CONV0_MSB 0x0A
+#define PALMAS_GPADC_AUTO_CONV1_LSB 0x0B
+#define PALMAS_GPADC_AUTO_CONV1_MSB 0x0C
+#define PALMAS_GPADC_SW_SELECT 0x0D
+#define PALMAS_GPADC_SW_CONV0_LSB 0x0E
+#define PALMAS_GPADC_SW_CONV0_MSB 0x0F
#define PALMAS_GPADC_THRES_CONV0_LSB 0x10
#define PALMAS_GPADC_THRES_CONV0_MSB 0x11
#define PALMAS_GPADC_THRES_CONV1_LSB 0x12
@@ -2731,150 +2731,150 @@ enum usb_irq_events {
/* Bit definitions for GPADC_CTRL1 */
#define PALMAS_GPADC_CTRL1_RESERVED_MASK 0xc0
-#define PALMAS_GPADC_CTRL1_RESERVED_SHIFT 6
+#define PALMAS_GPADC_CTRL1_RESERVED_SHIFT 0x06
#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_MASK 0x30
-#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT 4
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH3_SHIFT 0x04
#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_MASK 0x0c
-#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT 2
+#define PALMAS_GPADC_CTRL1_CURRENT_SRC_CH0_SHIFT 0x02
#define PALMAS_GPADC_CTRL1_BAT_REMOVAL_DET 0x02
-#define PALMAS_GPADC_CTRL1_BAT_REMOVAL_DET_SHIFT 1
+#define PALMAS_GPADC_CTRL1_BAT_REMOVAL_DET_SHIFT 0x01
#define PALMAS_GPADC_CTRL1_GPADC_FORCE 0x01
-#define PALMAS_GPADC_CTRL1_GPADC_FORCE_SHIFT 0
+#define PALMAS_GPADC_CTRL1_GPADC_FORCE_SHIFT 0x00
/* Bit definitions for GPADC_CTRL2 */
#define PALMAS_GPADC_CTRL2_RESERVED_MASK 0x06
-#define PALMAS_GPADC_CTRL2_RESERVED_SHIFT 1
+#define PALMAS_GPADC_CTRL2_RESERVED_SHIFT 0x01
/* Bit definitions for GPADC_RT_CTRL */
#define PALMAS_GPADC_RT_CTRL_EXTEND_DELAY 0x02
-#define PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT 1
+#define PALMAS_GPADC_RT_CTRL_EXTEND_DELAY_SHIFT 0x01
#define PALMAS_GPADC_RT_CTRL_START_POLARITY 0x01
-#define PALMAS_GPADC_RT_CTRL_START_POLARITY_SHIFT 0
+#define PALMAS_GPADC_RT_CTRL_START_POLARITY_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_CTRL */
#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1 0x80
-#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1_SHIFT 7
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV1_SHIFT 0x07
#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0 0x40
-#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0_SHIFT 6
+#define PALMAS_GPADC_AUTO_CTRL_SHUTDOWN_CONV0_SHIFT 0x06
#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN 0x20
-#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN_SHIFT 5
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV1_EN_SHIFT 0x05
#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN 0x10
-#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN_SHIFT 4
-#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK 0x0f
-#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_SHIFT 0
+#define PALMAS_GPADC_AUTO_CTRL_AUTO_CONV0_EN_SHIFT 0x04
+#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_MASK 0x0F
+#define PALMAS_GPADC_AUTO_CTRL_COUNTER_CONV_SHIFT 0x00
/* Bit definitions for GPADC_STATUS */
#define PALMAS_GPADC_STATUS_GPADC_AVAILABLE 0x10
-#define PALMAS_GPADC_STATUS_GPADC_AVAILABLE_SHIFT 4
+#define PALMAS_GPADC_STATUS_GPADC_AVAILABLE_SHIFT 0x04
/* Bit definitions for GPADC_RT_SELECT */
#define PALMAS_GPADC_RT_SELECT_RT_CONV_EN 0x80
-#define PALMAS_GPADC_RT_SELECT_RT_CONV_EN_SHIFT 7
-#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_MASK 0x0f
-#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_SHIFT 0
+#define PALMAS_GPADC_RT_SELECT_RT_CONV_EN_SHIFT 0x07
+#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_MASK 0x0F
+#define PALMAS_GPADC_RT_SELECT_RT_CONV0_SEL_SHIFT 0x00
/* Bit definitions for GPADC_RT_CONV0_LSB */
-#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_MASK 0xff
-#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_SHIFT 0
+#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_MASK 0xFF
+#define PALMAS_GPADC_RT_CONV0_LSB_RT_CONV0_LSB_SHIFT 0x00
/* Bit definitions for GPADC_RT_CONV0_MSB */
-#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_MASK 0x0f
-#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_SHIFT 0
+#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_MASK 0x0F
+#define PALMAS_GPADC_RT_CONV0_MSB_RT_CONV0_MSB_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_SELECT */
-#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_MASK 0xf0
-#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_SHIFT 4
-#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_MASK 0x0f
-#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_SHIFT 0
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_MASK 0xF0
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV1_SEL_SHIFT 0x04
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_MASK 0x0F
+#define PALMAS_GPADC_AUTO_SELECT_AUTO_CONV0_SEL_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_CONV0_LSB */
-#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_MASK 0xff
-#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_SHIFT 0
+#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_MASK 0xFF
+#define PALMAS_GPADC_AUTO_CONV0_LSB_AUTO_CONV0_LSB_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_CONV0_MSB */
-#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_MASK 0x0f
-#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_SHIFT 0
+#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_MASK 0x0F
+#define PALMAS_GPADC_AUTO_CONV0_MSB_AUTO_CONV0_MSB_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_CONV1_LSB */
-#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_MASK 0xff
-#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_SHIFT 0
+#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_MASK 0xFF
+#define PALMAS_GPADC_AUTO_CONV1_LSB_AUTO_CONV1_LSB_SHIFT 0x00
/* Bit definitions for GPADC_AUTO_CONV1_MSB */
-#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_MASK 0x0f
-#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_SHIFT 0
+#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_MASK 0x0F
+#define PALMAS_GPADC_AUTO_CONV1_MSB_AUTO_CONV1_MSB_SHIFT 0x00
/* Bit definitions for GPADC_SW_SELECT */
#define PALMAS_GPADC_SW_SELECT_SW_CONV_EN 0x80
-#define PALMAS_GPADC_SW_SELECT_SW_CONV_EN_SHIFT 7
+#define PALMAS_GPADC_SW_SELECT_SW_CONV_EN_SHIFT 0x07
#define PALMAS_GPADC_SW_SELECT_SW_START_CONV0 0x10
-#define PALMAS_GPADC_SW_SELECT_SW_START_CONV0_SHIFT 4
-#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK 0x0f
-#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_SHIFT 0
+#define PALMAS_GPADC_SW_SELECT_SW_START_CONV0_SHIFT 0x04
+#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_MASK 0x0F
+#define PALMAS_GPADC_SW_SELECT_SW_CONV0_SEL_SHIFT 0x00
/* Bit definitions for GPADC_SW_CONV0_LSB */
-#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_MASK 0xff
-#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_SHIFT 0
+#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_MASK 0xFF
+#define PALMAS_GPADC_SW_CONV0_LSB_SW_CONV0_LSB_SHIFT 0x00
/* Bit definitions for GPADC_SW_CONV0_MSB */
-#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_MASK 0x0f
-#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_SHIFT 0
+#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_MASK 0x0F
+#define PALMAS_GPADC_SW_CONV0_MSB_SW_CONV0_MSB_SHIFT 0x00
/* Bit definitions for GPADC_THRES_CONV0_LSB */
-#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_MASK 0xff
-#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_SHIFT 0
+#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_MASK 0xFF
+#define PALMAS_GPADC_THRES_CONV0_LSB_THRES_CONV0_LSB_SHIFT 0x00
/* Bit definitions for GPADC_THRES_CONV0_MSB */
#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL 0x80
-#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL_SHIFT 7
-#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_MASK 0x0f
-#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_SHIFT 0
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_POL_SHIFT 0x07
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_MASK 0x0F
+#define PALMAS_GPADC_THRES_CONV0_MSB_THRES_CONV0_MSB_SHIFT 0x00
/* Bit definitions for GPADC_THRES_CONV1_LSB */
-#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_MASK 0xff
-#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_SHIFT 0
+#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_MASK 0xFF
+#define PALMAS_GPADC_THRES_CONV1_LSB_THRES_CONV1_LSB_SHIFT 0x00
/* Bit definitions for GPADC_THRES_CONV1_MSB */
#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL 0x80
-#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL_SHIFT 7
-#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_MASK 0x0f
-#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_SHIFT 0
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_POL_SHIFT 0x07
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_MASK 0x0F
+#define PALMAS_GPADC_THRES_CONV1_MSB_THRES_CONV1_MSB_SHIFT 0x00
/* Bit definitions for GPADC_SMPS_ILMONITOR_EN */
#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_EN 0x20
-#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_EN_SHIFT 5
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_EN_SHIFT 0x05
#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_REXT 0x10
-#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_REXT_SHIFT 4
-#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_MASK 0x0f
-#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_SHIFT 0
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_REXT_SHIFT 0x04
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_MASK 0x0F
+#define PALMAS_GPADC_SMPS_ILMONITOR_EN_SMPS_ILMON_SEL_SHIFT 0x00
/* Bit definitions for GPADC_SMPS_VSEL_MONITORING */
#define PALMAS_GPADC_SMPS_VSEL_MONITORING_ACTIVE_PHASE 0x80
-#define PALMAS_GPADC_SMPS_VSEL_MONITORING_ACTIVE_PHASE_SHIFT 7
-#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_MASK 0x7f
-#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_SHIFT 0
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_ACTIVE_PHASE_SHIFT 0x07
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_MASK 0x7F
+#define PALMAS_GPADC_SMPS_VSEL_MONITORING_SMPS_VSEL_MONITORING_SHIFT 0x00
/* Registers for function GPADC */
-#define PALMAS_GPADC_TRIM1 0x0
-#define PALMAS_GPADC_TRIM2 0x1
-#define PALMAS_GPADC_TRIM3 0x2
-#define PALMAS_GPADC_TRIM4 0x3
-#define PALMAS_GPADC_TRIM5 0x4
-#define PALMAS_GPADC_TRIM6 0x5
-#define PALMAS_GPADC_TRIM7 0x6
-#define PALMAS_GPADC_TRIM8 0x7
-#define PALMAS_GPADC_TRIM9 0x8
-#define PALMAS_GPADC_TRIM10 0x9
-#define PALMAS_GPADC_TRIM11 0xA
-#define PALMAS_GPADC_TRIM12 0xB
-#define PALMAS_GPADC_TRIM13 0xC
-#define PALMAS_GPADC_TRIM14 0xD
-#define PALMAS_GPADC_TRIM15 0xE
-#define PALMAS_GPADC_TRIM16 0xF
+#define PALMAS_GPADC_TRIM1 0x00
+#define PALMAS_GPADC_TRIM2 0x01
+#define PALMAS_GPADC_TRIM3 0x02
+#define PALMAS_GPADC_TRIM4 0x03
+#define PALMAS_GPADC_TRIM5 0x04
+#define PALMAS_GPADC_TRIM6 0x05
+#define PALMAS_GPADC_TRIM7 0x06
+#define PALMAS_GPADC_TRIM8 0x07
+#define PALMAS_GPADC_TRIM9 0x08
+#define PALMAS_GPADC_TRIM10 0x09
+#define PALMAS_GPADC_TRIM11 0x0A
+#define PALMAS_GPADC_TRIM12 0x0B
+#define PALMAS_GPADC_TRIM13 0x0C
+#define PALMAS_GPADC_TRIM14 0x0D
+#define PALMAS_GPADC_TRIM15 0x0E
+#define PALMAS_GPADC_TRIM16 0x0F
static inline int palmas_read(struct palmas *palmas, unsigned int base,
unsigned int reg, unsigned int *val)
{
- unsigned int addr = PALMAS_BASE_TO_REG(base, reg);
+ unsigned int addr = PALMAS_BASE_TO_REG(base, reg);
int slave_id = PALMAS_BASE_TO_SLAVE(base);
return regmap_read(palmas->regmap[slave_id], addr, val);
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
deleted file mode 100644
index bd2f4f64e931..000000000000
--- a/include/linux/mfd/pm8xxx/core.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-/*
- * Qualcomm PMIC 8xxx driver header file
- *
- */
-
-#ifndef __MFD_PM8XXX_CORE_H
-#define __MFD_PM8XXX_CORE_H
-
-#include <linux/mfd/core.h>
-
-struct pm8xxx_drvdata {
- int (*pmic_readb) (const struct device *dev, u16 addr, u8 *val);
- int (*pmic_writeb) (const struct device *dev, u16 addr, u8 val);
- int (*pmic_read_buf) (const struct device *dev, u16 addr, u8 *buf,
- int n);
- int (*pmic_write_buf) (const struct device *dev, u16 addr, u8 *buf,
- int n);
- int (*pmic_read_irq_stat) (const struct device *dev, int irq);
- void *pm_chip_data;
-};
-
-static inline int pm8xxx_readb(const struct device *dev, u16 addr, u8 *val)
-{
- struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
-
- if (!dd)
- return -EINVAL;
- return dd->pmic_readb(dev, addr, val);
-}
-
-static inline int pm8xxx_writeb(const struct device *dev, u16 addr, u8 val)
-{
- struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
-
- if (!dd)
- return -EINVAL;
- return dd->pmic_writeb(dev, addr, val);
-}
-
-static inline int pm8xxx_read_buf(const struct device *dev, u16 addr, u8 *buf,
- int n)
-{
- struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
-
- if (!dd)
- return -EINVAL;
- return dd->pmic_read_buf(dev, addr, buf, n);
-}
-
-static inline int pm8xxx_write_buf(const struct device *dev, u16 addr, u8 *buf,
- int n)
-{
- struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
-
- if (!dd)
- return -EINVAL;
- return dd->pmic_write_buf(dev, addr, buf, n);
-}
-
-static inline int pm8xxx_read_irq_stat(const struct device *dev, int irq)
-{
- struct pm8xxx_drvdata *dd = dev_get_drvdata(dev);
-
- if (!dd)
- return -EINVAL;
- return dd->pmic_read_irq_stat(dev, irq);
-}
-
-#endif
diff --git a/include/linux/mfd/rdc321x.h b/include/linux/mfd/rdc321x.h
index 4bdf19c8eedf..442743a8f915 100644
--- a/include/linux/mfd/rdc321x.h
+++ b/include/linux/mfd/rdc321x.h
@@ -12,7 +12,7 @@
#define RDC321X_GPIO_CTRL_REG2 0x84
#define RDC321X_GPIO_DATA_REG2 0x88
-#define RDC321X_MAX_GPIO 58
+#define RDC321X_NUM_GPIO 59
struct rdc321x_gpio_pdata {
struct pci_dev *sb_pdev;
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 157e32b6ca28..47d84242940b 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -24,35 +24,36 @@ enum sec_device_type {
};
/**
- * struct sec_pmic_dev - s5m87xx master device for sub-drivers
- * @dev: master device of the chip (can be used to access platform data)
- * @pdata: pointer to private data used to pass platform data to child
- * @i2c: i2c client private data for regulator
- * @rtc: i2c client private data for rtc
- * @iolock: mutex for serializing io access
- * @irqlock: mutex for buslock
- * @irq_base: base IRQ number for sec-pmic, required for IRQs
- * @irq: generic IRQ number for s5m87xx
- * @ono: power onoff IRQ number for s5m87xx
- * @irq_masks_cur: currently active value
- * @irq_masks_cache: cached hardware value
- * @type: indicate which s5m87xx "variant" is used
+ * struct sec_pmic_dev - s2m/s5m master device for sub-drivers
+ * @dev: Master device of the chip
+ * @pdata: Platform data populated with data from DTS
+ * or board files
+ * @regmap_pmic: Regmap associated with PMIC's I2C address
+ * @i2c: I2C client of the main driver
+ * @device_type: Type of device, matches enum sec_device_type
+ * @irq_base: Base IRQ number for device, required for IRQs
+ * @irq: Generic IRQ number for device
+ * @irq_data: Runtime data structure for IRQ controller
+ * @ono: Power onoff IRQ number for s5m87xx
+ * @wakeup: Whether or not this is a wakeup device
+ * @wtsr_smpl: Whether or not to enable in RTC driver the Watchdog
+ * Timer Software Reset (registers set to default value
+ * after PWRHOLD falling) and Sudden Momentary Power Loss
+ * (PMIC will enter power on sequence after short drop in
+ * VBATT voltage).
*/
struct sec_pmic_dev {
struct device *dev;
struct sec_platform_data *pdata;
struct regmap *regmap_pmic;
- struct regmap *regmap_rtc;
struct i2c_client *i2c;
- struct i2c_client *rtc;
- int device_type;
+ unsigned long device_type;
int irq_base;
int irq;
struct regmap_irq_chip_data *irq_data;
int ono;
- unsigned long type;
bool wakeup;
bool wtsr_smpl;
};
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index 48395a69a7e9..575a86c7fcbd 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -11,6 +11,7 @@
#include <linux/mutex.h>
struct device;
+struct regulator;
enum stmpe_block {
STMPE_BLOCK_GPIO = 1 << 0,
@@ -62,6 +63,8 @@ struct stmpe_client_info;
/**
* struct stmpe - STMPE MFD structure
+ * @vcc: optional VCC regulator
+ * @vio: optional VIO regulator
* @lock: lock protecting I/O operations
* @irq_lock: IRQ bus lock
* @dev: device, mostly for dev_dbg()
@@ -73,13 +76,14 @@ struct stmpe_client_info;
* @regs: list of addresses of registers which are at different addresses on
* different variants. Indexed by one of STMPE_IDX_*.
* @irq: irq number for stmpe
- * @irq_base: starting IRQ number for internal IRQs
* @num_gpios: number of gpios, differs for variants
* @ier: cache of IER registers for bus_lock
* @oldier: cache of IER registers for bus_lock
* @pdata: platform data
*/
struct stmpe {
+ struct regulator *vcc;
+ struct regulator *vio;
struct mutex lock;
struct mutex irq_lock;
struct device *dev;
@@ -91,7 +95,6 @@ struct stmpe {
const u8 *regs;
int irq;
- int irq_base;
int num_gpios;
u8 ier[2];
u8 oldier[2];
@@ -132,8 +135,6 @@ struct stmpe_keypad_platform_data {
/**
* struct stmpe_gpio_platform_data - STMPE GPIO platform data
- * @gpio_base: first gpio number assigned. A maximum of
- * %STMPE_NR_GPIOS GPIOs will be allocated.
* @norequest_mask: bitmask specifying which GPIOs should _not_ be
* requestable due to different usage (e.g. touch, keypad)
* STMPE_GPIO_NOREQ_* macros can be used here.
@@ -141,7 +142,6 @@ struct stmpe_keypad_platform_data {
* @remove: board specific remove callback
*/
struct stmpe_gpio_platform_data {
- int gpio_base;
unsigned norequest_mask;
void (*setup)(struct stmpe *stmpe, unsigned gpio_base);
void (*remove)(struct stmpe *stmpe, unsigned gpio_base);
@@ -195,8 +195,6 @@ struct stmpe_ts_platform_data {
* @irq_trigger: IRQ trigger to use for the interrupt to the host
* @autosleep: bool to enable/disable stmpe autosleep
* @autosleep_timeout: inactivity timeout in milliseconds for autosleep
- * @irq_base: base IRQ number. %STMPE_NR_IRQS irqs will be used, or
- * %STMPE_NR_INTERNAL_IRQS if the GPIO driver is not used.
* @irq_over_gpio: true if gpio is used to get irq
* @irq_gpio: gpio number over which irq will be requested (significant only if
* irq_over_gpio is true)
@@ -207,7 +205,6 @@ struct stmpe_ts_platform_data {
struct stmpe_platform_data {
int id;
unsigned int blocks;
- int irq_base;
unsigned int irq_trigger;
bool autosleep;
bool irq_over_gpio;
@@ -219,10 +216,4 @@ struct stmpe_platform_data {
struct stmpe_ts_platform_data *ts;
};
-#define STMPE_NR_INTERNAL_IRQS 9
-#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x))
-
-#define STMPE_NR_GPIOS 24
-#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS)
-
#endif
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index 8789fa3c7fd9..75e543b78f53 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -15,6 +15,8 @@
#ifndef __LINUX_MFD_SYSCON_H__
#define __LINUX_MFD_SYSCON_H__
+#include <linux/err.h>
+
struct device_node;
#ifdef CONFIG_MFD_SYSCON
diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h
index d2e357df5a0e..2f9b593246ee 100644
--- a/include/linux/mfd/tps65218.h
+++ b/include/linux/mfd/tps65218.h
@@ -267,7 +267,6 @@ struct tps65218 {
u32 irq_mask;
struct regmap_irq_chip_data *irq_data;
struct regulator_desc desc[TPS65218_NUM_REGULATOR];
- struct regulator_dev *rdev[TPS65218_NUM_REGULATOR];
struct tps_info *info[TPS65218_NUM_REGULATOR];
struct regmap *regmap;
};
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 81f639bc1ae6..8f9fc3d26e6d 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
#define TWL6040_REG_ASICID 0x01
#define TWL6040_REG_ASICREV 0x02
@@ -157,6 +158,7 @@
#define TWL6040_I2CSEL 0x01
#define TWL6040_RESETSPLIT 0x04
#define TWL6040_INTCLRMODE 0x08
+#define TWL6040_I2CMODE(x) ((x & 0x3) << 4)
/* STATUS (0x2E) fields */
@@ -222,6 +224,7 @@ struct twl6040 {
struct regmap *regmap;
struct regmap_irq_chip_data *irq_data;
struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */
+ struct clk *clk32k;
struct mutex mutex;
struct mutex irq_mutex;
struct mfd_cell cells[TWL6040_CELLS];
diff --git a/include/linux/platform_data/ipmmu-vmsa.h b/include/linux/platform_data/ipmmu-vmsa.h
new file mode 100644
index 000000000000..5275b3ac6d37
--- /dev/null
+++ b/include/linux/platform_data/ipmmu-vmsa.h
@@ -0,0 +1,24 @@
+/*
+ * IPMMU VMSA Platform Data
+ *
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#ifndef __IPMMU_VMSA_H__
+#define __IPMMU_VMSA_H__
+
+struct ipmmu_vmsa_master {
+ const char *name;
+ unsigned int utlb;
+};
+
+struct ipmmu_vmsa_platform_data {
+ const struct ipmmu_vmsa_master *masters;
+ unsigned int num_masters;
+};
+
+#endif /* __IPMMU_VMSA_H__ */
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
index c6b39372eed7..aa1c4477722d 100644
--- a/include/media/adv7604.h
+++ b/include/media/adv7604.h
@@ -32,14 +32,18 @@ enum adv7604_ain_sel {
ADV7604_AIN9_4_5_6_SYNC_2_1 = 4,
};
-/* Bus rotation and reordering (IO register 0x04, [7:5]) */
-enum adv7604_op_ch_sel {
- ADV7604_OP_CH_SEL_GBR = 0,
- ADV7604_OP_CH_SEL_GRB = 1,
- ADV7604_OP_CH_SEL_BGR = 2,
- ADV7604_OP_CH_SEL_RGB = 3,
- ADV7604_OP_CH_SEL_BRG = 4,
- ADV7604_OP_CH_SEL_RBG = 5,
+/*
+ * Bus rotation and reordering. This is used to specify component reordering on
+ * the board and describes the components order on the bus when the ADV7604
+ * outputs RGB.
+ */
+enum adv7604_bus_order {
+ ADV7604_BUS_ORDER_RGB, /* No operation */
+ ADV7604_BUS_ORDER_GRB, /* Swap 1-2 */
+ ADV7604_BUS_ORDER_RBG, /* Swap 2-3 */
+ ADV7604_BUS_ORDER_BGR, /* Swap 1-3 */
+ ADV7604_BUS_ORDER_BRG, /* Rotate right */
+ ADV7604_BUS_ORDER_GBR, /* Rotate left */
};
/* Input Color Space (IO register 0x02, [7:4]) */
@@ -55,29 +59,11 @@ enum adv7604_inp_color_space {
ADV7604_INP_COLOR_SPACE_AUTO = 0xf,
};
-/* Select output format (IO register 0x03, [7:0]) */
-enum adv7604_op_format_sel {
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_8 = 0x00,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_10 = 0x01,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE0 = 0x02,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE1 = 0x06,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE2 = 0x0a,
- ADV7604_OP_FORMAT_SEL_DDR_422_8 = 0x20,
- ADV7604_OP_FORMAT_SEL_DDR_422_10 = 0x21,
- ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE0 = 0x22,
- ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE1 = 0x23,
- ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE2 = 0x24,
- ADV7604_OP_FORMAT_SEL_SDR_444_24 = 0x40,
- ADV7604_OP_FORMAT_SEL_SDR_444_30 = 0x41,
- ADV7604_OP_FORMAT_SEL_SDR_444_36_MODE0 = 0x42,
- ADV7604_OP_FORMAT_SEL_DDR_444_24 = 0x60,
- ADV7604_OP_FORMAT_SEL_DDR_444_30 = 0x61,
- ADV7604_OP_FORMAT_SEL_DDR_444_36 = 0x62,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_16 = 0x80,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_20 = 0x81,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE0 = 0x82,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE1 = 0x86,
- ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE2 = 0x8a,
+/* Select output format (IO register 0x03, [4:2]) */
+enum adv7604_op_format_mode_sel {
+ ADV7604_OP_FORMAT_MODE0 = 0x00,
+ ADV7604_OP_FORMAT_MODE1 = 0x04,
+ ADV7604_OP_FORMAT_MODE2 = 0x08,
};
enum adv7604_drive_strength {
@@ -86,6 +72,30 @@ enum adv7604_drive_strength {
ADV7604_DR_STR_HIGH = 3,
};
+enum adv7604_int1_config {
+ ADV7604_INT1_CONFIG_OPEN_DRAIN,
+ ADV7604_INT1_CONFIG_ACTIVE_LOW,
+ ADV7604_INT1_CONFIG_ACTIVE_HIGH,
+ ADV7604_INT1_CONFIG_DISABLED,
+};
+
+enum adv7604_page {
+ ADV7604_PAGE_IO,
+ ADV7604_PAGE_AVLINK,
+ ADV7604_PAGE_CEC,
+ ADV7604_PAGE_INFOFRAME,
+ ADV7604_PAGE_ESDP,
+ ADV7604_PAGE_DPP,
+ ADV7604_PAGE_AFE,
+ ADV7604_PAGE_REP,
+ ADV7604_PAGE_EDID,
+ ADV7604_PAGE_HDMI,
+ ADV7604_PAGE_TEST,
+ ADV7604_PAGE_CP,
+ ADV7604_PAGE_VDP,
+ ADV7604_PAGE_MAX,
+};
+
/* Platform dependent definition */
struct adv7604_platform_data {
/* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
@@ -94,30 +104,34 @@ struct adv7604_platform_data {
/* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
unsigned disable_cable_det_rst:1;
+ int default_input;
+
/* Analog input muxing mode */
enum adv7604_ain_sel ain_sel;
/* Bus rotation and reordering */
- enum adv7604_op_ch_sel op_ch_sel;
+ enum adv7604_bus_order bus_order;
- /* Select output format */
- enum adv7604_op_format_sel op_format_sel;
+ /* Select output format mode */
+ enum adv7604_op_format_mode_sel op_format_mode_sel;
+
+ /* Configuration of the INT1 pin */
+ enum adv7604_int1_config int1_config;
/* IO register 0x02 */
unsigned alt_gamma:1;
unsigned op_656_range:1;
- unsigned rgb_out:1;
unsigned alt_data_sat:1;
/* IO register 0x05 */
unsigned blank_data:1;
unsigned insert_av_codes:1;
unsigned replicate_av_codes:1;
- unsigned invert_cbcr:1;
/* IO register 0x06 */
unsigned inv_vs_pol:1;
unsigned inv_hs_pol:1;
+ unsigned inv_llc_pol:1;
/* IO register 0x14 */
enum adv7604_drive_strength dr_str_data;
@@ -131,34 +145,22 @@ struct adv7604_platform_data {
unsigned hdmi_free_run_mode;
/* i2c addresses: 0 == use default */
- u8 i2c_avlink;
- u8 i2c_cec;
- u8 i2c_infoframe;
- u8 i2c_esdp;
- u8 i2c_dpp;
- u8 i2c_afe;
- u8 i2c_repeater;
- u8 i2c_edid;
- u8 i2c_hdmi;
- u8 i2c_test;
- u8 i2c_cp;
- u8 i2c_vdp;
+ u8 i2c_addresses[ADV7604_PAGE_MAX];
};
-enum adv7604_input_port {
- ADV7604_INPUT_HDMI_PORT_A,
- ADV7604_INPUT_HDMI_PORT_B,
- ADV7604_INPUT_HDMI_PORT_C,
- ADV7604_INPUT_HDMI_PORT_D,
- ADV7604_INPUT_VGA_RGB,
- ADV7604_INPUT_VGA_COMP,
+enum adv7604_pad {
+ ADV7604_PAD_HDMI_PORT_A = 0,
+ ADV7604_PAD_HDMI_PORT_B = 1,
+ ADV7604_PAD_HDMI_PORT_C = 2,
+ ADV7604_PAD_HDMI_PORT_D = 3,
+ ADV7604_PAD_VGA_RGB = 4,
+ ADV7604_PAD_VGA_COMP = 5,
+ /* The source pad is either 1 (ADV7611) or 6 (ADV7604) */
+ ADV7604_PAD_SOURCE = 6,
+ ADV7611_PAD_SOURCE = 1,
+ ADV7604_PAD_MAX = 7,
};
-#define ADV7604_EDID_PORT_A 0
-#define ADV7604_EDID_PORT_B 1
-#define ADV7604_EDID_PORT_C 2
-#define ADV7604_EDID_PORT_D 3
-
#define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE (V4L2_CID_DV_CLASS_BASE + 0x1000)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL (V4L2_CID_DV_CLASS_BASE + 0x1001)
#define V4L2_CID_ADV_RX_FREE_RUN_COLOR (V4L2_CID_DV_CLASS_BASE + 0x1002)
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 9fab013eea86..d7465725773d 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -338,12 +338,8 @@ struct v4l2_subdev_video_ops {
struct v4l2_dv_timings *timings);
int (*g_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
- int (*enum_dv_timings)(struct v4l2_subdev *sd,
- struct v4l2_enum_dv_timings *timings);
int (*query_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
- int (*dv_timings_cap)(struct v4l2_subdev *sd,
- struct v4l2_dv_timings_cap *cap);
int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
enum v4l2_mbus_pixelcode *code);
int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,