diff options
619 files changed, 43806 insertions, 17363 deletions
diff --git a/Documentation/ABI/stable/sysfs-bus-firewire b/Documentation/ABI/stable/sysfs-bus-firewire index 3d484e5dc84..41e5a0cd1e3 100644 --- a/Documentation/ABI/stable/sysfs-bus-firewire +++ b/Documentation/ABI/stable/sysfs-bus-firewire @@ -39,6 +39,17 @@ Users: udev rules to set ownership and access permissions or ACLs of /dev/fw[0-9]+ character device files +What: /sys/bus/firewire/devices/fw[0-9]+/is_local +Date: July 2012 +KernelVersion: 3.6 +Contact: linux1394-devel@lists.sourceforge.net +Description: + IEEE 1394 node device attribute. + Read-only and immutable. +Values: 1: The sysfs entry represents a local node (a controller card). + 0: The sysfs entry represents a remote node. + + What: /sys/bus/firewire/devices/fw[0-9]+[.][0-9]+/ Date: May 2007 KernelVersion: 2.6.22 diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac new file mode 100644 index 00000000000..30ee78aaed7 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-edac @@ -0,0 +1,140 @@ +What: /sys/devices/system/edac/mc/mc*/reset_counters +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This write-only control file will zero all the statistical + counters for UE and CE errors on the given memory controller. + Zeroing the counters will also reset the timer indicating how + long since the last counter were reset. This is useful for + computing errors/time. Since the counters are always reset + at driver initialization time, no module/kernel parameter + is available. + +What: /sys/devices/system/edac/mc/mc*/seconds_since_reset +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays how many seconds have elapsed + since the last counter reset. This can be used with the error + counters to measure error rates. + +What: /sys/devices/system/edac/mc/mc*/mc_name +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the type of memory controller + that is being utilized. + +What: /sys/devices/system/edac/mc/mc*/size_mb +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays, in count of megabytes, of memory + that this memory controller manages. + +What: /sys/devices/system/edac/mc/mc*/ue_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the total count of uncorrectable + errors that have occurred on this memory controller. If + panic_on_ue is set, this counter will not have a chance to + increment, since EDAC will panic the system + +What: /sys/devices/system/edac/mc/mc*/ue_noinfo_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the number of UEs that have + occurred on this memory controller with no information as to + which DIMM slot is having errors. + +What: /sys/devices/system/edac/mc/mc*/ce_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the total count of correctable + errors that have occurred on this memory controller. This + count is very important to examine. CEs provide early + indications that a DIMM is beginning to fail. This count + field should be monitored for non-zero values and report + such information to the system administrator. + +What: /sys/devices/system/edac/mc/mc*/ce_noinfo_count +Date: January 2006 +Contact: linux-edac@vger.kernel.org +Description: This attribute file displays the number of CEs that + have occurred on this memory controller wherewith no + information as to which DIMM slot is having errors. Memory is + handicapped, but operational, yet no information is available + to indicate which slot the failing memory is in. This count + field should be also be monitored for non-zero values. + +What: /sys/devices/system/edac/mc/mc*/sdram_scrub_rate +Date: February 2007 +Contact: linux-edac@vger.kernel.org +Description: Read/Write attribute file that controls memory scrubbing. + The scrubbing rate used by the memory controller is set by + writing a minimum bandwidth in bytes/sec to the attribute file. + The rate will be translated to an internal value that gives at + least the specified rate. + Reading the file will return the actual scrubbing rate employed. + If configuration fails or memory scrubbing is not implemented, + the value of the attribute file will be -1. + +What: /sys/devices/system/edac/mc/mc*/max_location +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file displays the information about the last + available memory slot in this memory controller. It is used by + userspace tools in order to display the memory filling layout. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file will display the size of dimm or rank. + For dimm*/size, this is the size, in MB of the DIMM memory + stick. For rank*/size, this is the size, in MB for one rank + of the DIMM memory stick. On single rank memories (1R), this + is also the total size of the dimm. On dual rank (2R) memories, + this is half the size of the total DIMM memories. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file will display what type of DRAM device is + being utilized on this DIMM (x1, x2, x4, x8, ...). + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file will display what type of Error detection + and correction is being utilized. For example: S4ECD4ED would + mean a Chipkill with x4 DRAM. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This control file allows this DIMM to have a label assigned + to it. With this label in the module, when errors occur + the output can provide the DIMM label in the system log. + This becomes vital for panic events to isolate the + cause of the UE event. + DIMM Labels must be assigned after booting, with information + that correctly identifies the physical slot with its + silk screen label. This information is currently very + motherboard specific and determination of this information + must occur in userland at this time. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file will display the location (csrow/channel, + branch/channel/slot or channel/slot) of the dimm or rank. + +What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type +Date: April 2012 +Contact: Mauro Carvalho Chehab <mchehab@redhat.com> + linux-edac@vger.kernel.org +Description: This attribute file will display what type of memory is + currently on this csrow. Normally, either buffered or + unbuffered memory (for example, Unbuffered-DDR3). diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi index 2e7df91620d..019e1e29370 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi @@ -29,3 +29,10 @@ KernelVersion: 2.6.39 Contact: "Corentin Chary" <corentincj@iksaif.net> Description: Control the card touchpad. 1 means on, 0 means off. + +What: /sys/devices/platform/<platform>/lid_resume +Date: May 2012 +KernelVersion: 3.5 +Contact: "AceLan Kao" <acelan.kao@canonical.com> +Description: + Resume on lid open. 1 means on, 0 means off. diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt index 5c72eed8956..f50309081ac 100644 --- a/Documentation/DMA-attributes.txt +++ b/Documentation/DMA-attributes.txt @@ -49,3 +49,45 @@ DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either consistent or non-consistent memory as it sees fit. By using this API, you are guaranteeing to the platform that you have all the correct and necessary sync points for this memory in the driver. + +DMA_ATTR_NO_KERNEL_MAPPING +-------------------------- + +DMA_ATTR_NO_KERNEL_MAPPING lets the platform to avoid creating a kernel +virtual mapping for the allocated buffer. On some architectures creating +such mapping is non-trivial task and consumes very limited resources +(like kernel virtual address space or dma consistent address space). +Buffers allocated with this attribute can be only passed to user space +by calling dma_mmap_attrs(). By using this API, you are guaranteeing +that you won't dereference the pointer returned by dma_alloc_attr(). You +can threat it as a cookie that must be passed to dma_mmap_attrs() and +dma_free_attrs(). Make sure that both of these also get this attribute +set on each call. + +Since it is optional for platforms to implement +DMA_ATTR_NO_KERNEL_MAPPING, those that do not will simply ignore the +attribute and exhibit default behavior. + +DMA_ATTR_SKIP_CPU_SYNC +---------------------- + +By default dma_map_{single,page,sg} functions family transfer a given +buffer from CPU domain to device domain. Some advanced use cases might +require sharing a buffer between more than one device. This requires +having a mapping created separately for each device and is usually +performed by calling dma_map_{single,page,sg} function more than once +for the given buffer with device pointer to each device taking part in +the buffer sharing. The first call transfers a buffer from 'CPU' domain +to 'device' domain, what synchronizes CPU caches for the given region +(usually it means that the cache has been flushed or invalidated +depending on the dma direction). However, next calls to +dma_map_{single,page,sg}() for other devices will perform exactly the +same sychronization operation on the CPU cache. CPU cache sychronization +might be a time consuming operation, especially if the buffers are +large, so it is highly recommended to avoid it if possible. +DMA_ATTR_SKIP_CPU_SYNC allows platform code to skip synchronization of +the CPU cache for the given buffer assuming that it has been already +transferred to 'device' domain. This attribute can be also used for +dma_unmap_{single,page,sg} functions family to force buffer to stay in +device domain after releasing a mapping for it. Use this attribute with +care! diff --git a/Documentation/device-mapper/striped.txt b/Documentation/device-mapper/striped.txt index f34d3236b9d..45f3b91ea4c 100644 --- a/Documentation/device-mapper/striped.txt +++ b/Documentation/device-mapper/striped.txt @@ -9,15 +9,14 @@ devices in parallel. Parameters: <num devs> <chunk size> [<dev path> <offset>]+ <num devs>: Number of underlying devices. - <chunk size>: Size of each chunk of data. Must be a power-of-2 and at - least as large as the system's PAGE_SIZE. + <chunk size>: Size of each chunk of data. Must be at least as + large as the system's PAGE_SIZE. <dev path>: Full pathname to the underlying block-device, or a "major:minor" device-number. <offset>: Starting sector within the device. One or more underlying devices can be specified. The striped device size must -be a multiple of the chunk size and a multiple of the number of underlying -devices. +be a multiple of the chunk size multiplied by the number of underlying devices. Example scripts diff --git a/Documentation/device-mapper/thin-provisioning.txt b/Documentation/device-mapper/thin-provisioning.txt index f5cfc62b7ad..30b8b83bd33 100644 --- a/Documentation/device-mapper/thin-provisioning.txt +++ b/Documentation/device-mapper/thin-provisioning.txt @@ -231,6 +231,9 @@ i) Constructor no_discard_passdown: Don't pass discards down to the underlying data device, but just remove the mapping. + read_only: Don't allow any changes to be made to the pool + metadata. + Data block size must be between 64KB (128 sectors) and 1GB (2097152 sectors) inclusive. @@ -239,7 +242,7 @@ ii) Status <transaction id> <used metadata blocks>/<total metadata blocks> <used data blocks>/<total data blocks> <held metadata root> - + [no_]discard_passdown ro|rw transaction id: A 64-bit number used by userspace to help synchronise with metadata @@ -257,6 +260,21 @@ ii) Status held root. This feature is not yet implemented so '-' is always returned. + discard_passdown|no_discard_passdown + Whether or not discards are actually being passed down to the + underlying device. When this is enabled when loading the table, + it can get disabled if the underlying device doesn't support it. + + ro|rw + If the pool encounters certain types of device failures it will + drop into a read-only metadata mode in which no changes to + the pool metadata (like allocating new blocks) are permitted. + + In serious cases where even a read-only mode is deemed unsafe + no further I/O will be permitted and the status will just + contain the string 'Fail'. The userspace recovery tools + should then be used. + iii) Messages create_thin <dev id> @@ -329,3 +347,7 @@ regain some space then send the 'trim' message to the pool. ii) Status <nr mapped sectors> <highest mapped sector> + + If the pool has encountered device errors and failed, the status + will just contain the string 'Fail'. The userspace recovery + tools should then be used. diff --git a/Documentation/devicetree/bindings/arm/calxeda/l2ecc.txt b/Documentation/devicetree/bindings/arm/calxeda/l2ecc.txt new file mode 100644 index 00000000000..94e642a33db --- /dev/null +++ b/Documentation/devicetree/bindings/arm/calxeda/l2ecc.txt @@ -0,0 +1,15 @@ +Calxeda Highbank L2 cache ECC + +Properties: +- compatible : Should be "calxeda,hb-sregs-l2-ecc" +- reg : Address and size for ECC error interrupt clear registers. +- interrupts : Should be single bit error interrupt, then double bit error + interrupt. + +Example: + + sregs@fff3c200 { + compatible = "calxeda,hb-sregs-l2-ecc"; + reg = <0xfff3c200 0x100>; + interrupts = <0 71 4 0 72 4>; + }; diff --git a/Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt b/Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt new file mode 100644 index 00000000000..f770ac0893d --- /dev/null +++ b/Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt @@ -0,0 +1,14 @@ +Calxeda DDR memory controller + +Properties: +- compatible : Should be "calxeda,hb-ddr-ctrl" +- reg : Address and size for DDR controller registers. +- interrupts : Interrupt for DDR controller. + +Example: + + memory-controller@fff00000 { + compatible = "calxeda,hb-ddr-ctrl"; + reg = <0xfff00000 0x1000>; + interrupts = <0 91 4>; + }; diff --git a/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt b/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt new file mode 100644 index 00000000000..93986a5a801 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt @@ -0,0 +1,30 @@ +* Compact Flash + +The Cavium Compact Flash device is connected to the Octeon Boot Bus, +and is thus a child of the Boot Bus device. It can read and write +industry standard compact flash devices. + +Properties: +- compatible: "cavium,ebt3000-compact-flash"; + + Compatibility with many Cavium evaluation boards. + +- reg: The base address of the the CF chip select banks. Depending on + the device configuration, there may be one or two banks. + +- cavium,bus-width: The width of the connection to the CF devices. Valid + values are 8 and 16. + +- cavium,true-ide: Optional, if present the CF connection is in True IDE mode. + +- cavium,dma-engine-handle: Optional, a phandle for the DMA Engine connected + to this device. + +Example: + compact-flash@5,0 { + compatible = "cavium,ebt3000-compact-flash"; + reg = <5 0 0x10000>, <6 0 0x10000>; + cavium,bus-width = <16>; + cavium,true-ide; + cavium,dma-engine-handle = <&dma0>; + }; diff --git a/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt b/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt new file mode 100644 index 00000000000..9d6dcd3fe7f --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt @@ -0,0 +1,49 @@ +* General Purpose Input Output (GPIO) bus. + +Properties: +- compatible: "cavium,octeon-3860-gpio" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the GPIO unit's register bank. + +- gpio-controller: This is a GPIO controller. + +- #gpio-cells: Must be <2>. The first cell is the GPIO pin. + +- interrupt-controller: The GPIO controller is also an interrupt + controller, many of its pins may be configured as an interrupt + source. + +- #interrupt-cells: Must be <2>. The first cell is the GPIO pin + connected to the interrupt source. The second cell is the interrupt + triggering protocol and may have one of four values: + 1 - edge triggered on the rising edge. + 2 - edge triggered on the falling edge + 4 - level triggered active high. + 8 - level triggered active low. + +- interrupts: Interrupt routing for each pin. + +Example: + + gpio-controller@1070000000800 { + #gpio-cells = <2>; + compatible = "cavium,octeon-3860-gpio"; + reg = <0x10700 0x00000800 0x0 0x100>; + gpio-controller; + /* Interrupts are specified by two parts: + * 1) GPIO pin number (0..15) + * 2) Triggering (1 - edge rising + * 2 - edge falling + * 4 - level active high + * 8 - level active low) + */ + interrupt-controller; + #interrupt-cells = <2>; + /* The GPIO pin connect to 16 consecutive CUI bits */ + interrupts = <0 16>, <0 17>, <0 18>, <0 19>, + <0 20>, <0 21>, <0 22>, <0 23>, + <0 24>, <0 25>, <0 26>, <0 27>, + <0 28>, <0 29>, <0 30>, <0 31>; + }; diff --git a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt b/Documentation/devicetree/bindings/i2c/cavium-i2c.txt new file mode 100644 index 00000000000..dced82ebe31 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/cavium-i2c.txt @@ -0,0 +1,34 @@ +* Two Wire Serial Interface (TWSI) / I2C + +- compatible: "cavium,octeon-3860-twsi" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the TWSI/I2C bus controller register bank. + +- #address-cells: Must be <1>. + +- #size-cells: Must be <0>. I2C addresses have no size component. + +- interrupts: A single interrupt specifier. + +- clock-frequency: The I2C bus clock rate in Hz. + +Example: + twsi0: i2c@1180000001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001000 0x0 0x200>; + interrupts = <0 45>; + clock-frequency = <100000>; + + rtc@68 { + compatible = "dallas,ds1337"; + reg = <0x68>; + }; + tmp@4c { + compatible = "ti,tmp421"; + reg = <0x4c>; + }; + }; diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt new file mode 100644 index 00000000000..69e757a657a --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -0,0 +1,123 @@ +* AB8500 Multi-Functional Device (MFD) + +Required parent device properties: +- compatible : contains "stericsson,ab8500"; +- interrupts : contains the IRQ line for the AB8500 +- interrupt-controller : describes the AB8500 as an Interrupt Controller (has its own domain) +- #interrupt-cells : should be 2, for 2-cell format + - The first cell is the AB8500 local IRQ number + - The second cell is used to specify optional parameters + - bits[3:0] trigger type and level flags: + 1 = low-to-high edge triggered + 2 = high-to-low edge triggered + 4 = active high level-sensitive + 8 = active low level-sensitive + +Optional parent device properties: +- reg : contains the PRCMU mailbox address for the AB8500 i2c port + +The AB8500 consists of a large and varied group of sub-devices: + +Device IRQ Names Supply Names Description +------ --------- ------------ ----------- +ab8500-bm : : : Battery Manager +ab8500-btemp : : : Battery Temperature +ab8500-charger : : : Battery Charger +ab8500-fg : : : Fuel Gauge +ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter + SW_CONV_END : : +ab8500-gpio : : : GPIO Controller +ab8500-ponkey : ONKEY_DBF : : Power-on Key + ONKEY_DBR : : +ab8500-pwm : : : Pulse Width Modulator +ab8500-regulator : : : Regulators +ab8500-rtc : 60S : : Real Time Clock + : ALARM : : +ab8500-sysctrl : : : System Control +ab8500-usb : ID_WAKEUP_R : vddulpivio18 : Universal Serial Bus + : ID_WAKEUP_F : v-ape : + : VBUS_DET_F : musb_1v8 : + : VBUS_DET_R : : + : USB_LINK_STATUS : : + : USB_ADP_PROBE_PLUG : : + : USB_ADP_PROBE_UNPLUG : : + +Required child device properties: +- compatible : "stericsson,ab8500-[bm|btemp|charger|fg|gpadc|gpio|ponkey| + pwm|regulator|rtc|sysctrl|usb]"; + +Optional child device properties: +- interrupts : contains the device IRQ(s) using the 2-cell format (see above) +- interrupt-names : contains names of IRQ resource in the order in which they were + supplied in the interrupts property +- <supply_name>-supply : contains a phandle to the regulator supply node in Device Tree + +ab8500@5 { + compatible = "stericsson,ab8500"; + reg = <5>; /* mailbox 5 is i2c */ + interrupts = <0 40 0x4>; + interrupt-controller; + #interrupt-cells = <2>; + + ab8500-rtc { + compatible = "stericsson,ab8500-rtc"; + interrupts = <17 0x4 + 18 0x4>; + interrupt-names = "60S", "ALARM"; + }; + + ab8500-gpadc { + compatible = "stericsson,ab8500-gpadc"; + interrupts = <32 0x4 + 39 0x4>; + interrupt-names = "HW_CONV_END", "SW_CONV_END"; + vddadc-supply = <&ab8500_ldo_tvout_reg>; + }; + + ab8500-usb { + compatible = "stericsson,ab8500-usb"; + interrupts = < 90 0x4 + 96 0x4 + 14 0x4 + 15 0x4 + 79 0x4 + 74 0x4 + 75 0x4>; + interrupt-names = "ID_WAKEUP_R", + "ID_WAKEUP_F", + "VBUS_DET_F", + "VBUS_DET_R", + "USB_LINK_STATUS", + "USB_ADP_PROBE_PLUG", + "USB_ADP_PROBE_UNPLUG"; + vddulpivio18-supply = <&ab8500_ldo_initcore_reg>; + v-ape-supply = <&db8500_vape_reg>; + musb_1v8-supply = <&db8500_vsmps2_reg>; + }; + + ab8500-ponkey { + compatible = "stericsson,ab8500-ponkey"; + interrupts = <6 0x4 + 7 0x4>; + interrupt-names = "ONKEY_DBF", "ONKEY_DBR"; + }; + + ab8500-sysctrl { + compatible = "stericsson,ab8500-sysctrl"; + }; + + ab8500-pwm { + compatible = "stericsson,ab8500-pwm"; + }; + + ab8500-regulators { + compatible = "stericsson,ab8500-regulator"; + + ab8500_ldo_aux1_reg: ab8500_ldo_aux1 { + /* + * See: Documentation/devicetree/bindings/regulator/regulator.txt + * for more information on regulators + */ + }; + }; +}; diff --git a/Documentation/devicetree/bindings/mfd/max77686.txt b/Documentation/devicetree/bindings/mfd/max77686.txt new file mode 100644 index 00000000000..c6a3469d343 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/max77686.txt @@ -0,0 +1,59 @@ +Maxim MAX77686 multi-function device + +MAX77686 is a Mulitifunction device with PMIC, RTC and Charger on chip. It is +interfaced to host controller using i2c interface. PMIC and Charger submodules +are addressed using same i2c slave address whereas RTC submodule uses +different i2c slave address,presently for which we are statically creating i2c +client while probing.This document describes the binding for mfd device and +PMIC submodule. + +Required properties: +- compatible : Must be "maxim,max77686"; +- reg : Specifies the i2c slave address of PMIC block. +- interrupts : This i2c device has an IRQ line connected to the main SoC. +- interrupt-parent : The parent interrupt controller. + +Optional node: +- voltage-regulators : The regulators of max77686 have to be instantiated + under subnode named "voltage-regulators" using the following format. + + regulator_name { + regulator-compatible = LDOn/BUCKn + standard regulator constraints.... + }; + refer Documentation/devicetree/bindings/regulator/regulator.txt + + The regulator-compatible property of regulator should initialized with string +to get matched with their hardware counterparts as follow: + + -LDOn : for LDOs, where n can lie in range 1 to 26. + example: LDO1, LDO2, LDO26. + -BUCKn : for BUCKs, where n can lie in range 1 to 9. + example: BUCK1, BUCK5, BUCK9. + +Example: + + max77686@09 { + compatible = "maxim,max77686"; + interrupt-parent = <&wakeup_eint>; + interrupts = <26 0>; + reg = <0x09>; + + voltage-regulators { + ldo11_reg { + regulator-compatible = "LDO11"; + regulator-name = "vdd_ldo11"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + regulator-always-on; + }; + + buck1_reg { + regulator-compatible = "BUCK1"; + regulator-name = "vdd_mif"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + } diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt index d2802d4717b..db03599ae4d 100644 --- a/Documentation/devicetree/bindings/mfd/tps65910.txt +++ b/Documentation/devicetree/bindings/mfd/tps65910.txt @@ -81,7 +81,7 @@ Example: ti,vmbch-threshold = 0; ti,vmbch2-threshold = 0; - + ti,en-ck32k-xtal; ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>; vcc1-supply = <®_parent>; diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt index bc67c6f424a..c855240f3a0 100644 --- a/Documentation/devicetree/bindings/mfd/twl6040.txt +++ b/Documentation/devicetree/bindings/mfd/twl6040.txt @@ -6,7 +6,7 @@ They are connected ot the host processor via i2c for commands, McPDM for audio data and commands. Required properties: -- compatible : Must be "ti,twl6040"; +- compatible : "ti,twl6040" for twl6040, "ti,twl6041" for twl6041 - reg: must be 0x4b for i2c address - interrupts: twl6040 has one interrupt line connecteded to the main SoC - interrupt-parent: The parent interrupt controller diff --git a/Documentation/devicetree/bindings/mips/cavium/bootbus.txt b/Documentation/devicetree/bindings/mips/cavium/bootbus.txt new file mode 100644 index 00000000000..6581478225a --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/bootbus.txt @@ -0,0 +1,126 @@ +* Boot Bus + +The Octeon Boot Bus is a configurable parallel bus with 8 chip +selects. Each chip select is independently configurable. + +Properties: +- compatible: "cavium,octeon-3860-bootbus" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the Boot Bus' register bank. + +- #address-cells: Must be <2>. The first cell is the chip select + within the bootbus. The second cell is the offset from the chip select. + +- #size-cells: Must be <1>. + +- ranges: There must be one one triplet of (child-bus-address, + parent-bus-address, length) for each active chip select. If the + length element for any triplet is zero, the chip select is disabled, + making it inactive. + +The configuration parameters for each chip select are stored in child +nodes. + +Configuration Properties: +- compatible: "cavium,octeon-3860-bootbus-config" + +- cavium,cs-index: A single cell indicating the chip select that + corresponds to this configuration. + +- cavium,t-adr: A cell specifying the ADR timing (in nS). + +- cavium,t-ce: A cell specifying the CE timing (in nS). + +- cavium,t-oe: A cell specifying the OE timing (in nS). + +- cavium,t-we: A cell specifying the WE timing (in nS). + +- cavium,t-rd-hld: A cell specifying the RD_HLD timing (in nS). + +- cavium,t-wr-hld: A cell specifying the WR_HLD timing (in nS). + +- cavium,t-pause: A cell specifying the PAUSE timing (in nS). + +- cavium,t-wait: A cell specifying the WAIT timing (in nS). + +- cavium,t-page: A cell specifying the PAGE timing (in nS). + +- cavium,t-rd-dly: A cell specifying the RD_DLY timing (in nS). + +- cavium,pages: A cell specifying the PAGES parameter (0 = 8 bytes, 1 + = 2 bytes, 2 = 4 bytes, 3 = 8 bytes). + +- cavium,wait-mode: Optional. If present, wait mode (WAITM) is selected. + +- cavium,page-mode: Optional. If present, page mode (PAGEM) is selected. + +- cavium,bus-width: A cell specifying the WIDTH parameter (in bits) of + the bus for this chip select. + +- cavium,ale-mode: Optional. If present, ALE mode is selected. + +- cavium,sam-mode: Optional. If present, SAM mode is selected. + +- cavium,or-mode: Optional. If present, OR mode is selected. + +Example: + bootbus: bootbus@1180000000000 { + compatible = "cavium,octeon-3860-bootbus"; + reg = <0x11800 0x00000000 0x0 0x200>; + /* The chip select number and offset */ + #address-cells = <2>; + /* The size of the chip select region */ + #size-cells = <1>; + ranges = <0 0 0x0 0x1f400000 0xc00000>, + <1 0 0x10000 0x30000000 0>, + <2 0 0x10000 0x40000000 0>, + <3 0 0x10000 0x50000000 0>, + <4 0 0x0 0x1d020000 0x10000>, + <5 0 0x0 0x1d040000 0x10000>, + <6 0 0x0 0x1d050000 0x10000>, + <7 0 0x10000 0x90000000 0>; + + cavium,cs-config@0 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <0>; + cavium,t-adr = <20>; + cavium,t-ce = <60>; + cavium,t-oe = <60>; + cavium,t-we = <45>; + cavium,t-rd-hld = <35>; + cavium,t-wr-hld = <45>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <35>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + . + . + . + cavium,cs-config@6 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <6>; + cavium,t-adr = <5>; + cavium,t-ce = <300>; + cavium,t-oe = <270>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <70>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,wait-mode; + cavium,bus-width = <16>; + }; + . + . + . + }; diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu.txt b/Documentation/devicetree/bindings/mips/cavium/ciu.txt new file mode 100644 index 00000000000..2c2d0746b43 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/ciu.txt @@ -0,0 +1,26 @@ +* Central Interrupt Unit + +Properties: +- compatible: "cavium,octeon-3860-ciu" + + Compatibility with all cn3XXX, cn5XXX and cn63XX SOCs. + +- interrupt-controller: This is an interrupt controller. + +- reg: The base address of the CIU's register bank. + +- #interrupt-cells: Must be <2>. The first cell is the bank within + the CIU and may have a value of 0 or 1. The second cell is the bit + within the bank and may have a value between 0 and 63. + +Example: + interrupt-controller@1070000000000 { + compatible = "cavium,octeon-3860-ciu"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Controller register (0 or 1) + * 2) Bit within the register (0..63) + */ + #interrupt-cells = <2>; + reg = <0x10700 0x00000000 0x0 0x7000>; + }; diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu2.txt b/Documentation/devicetree/bindings/mips/cavium/ciu2.txt new file mode 100644 index 00000000000..0ec7ba8bbbc --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/ciu2.txt @@ -0,0 +1,27 @@ +* Central Interrupt Unit + +Properties: +- compatible: "cavium,octeon-6880-ciu2" + + Compatibility with 68XX SOCs. + +- interrupt-controller: This is an interrupt controller. + +- reg: The base address of the CIU's register bank. + +- #interrupt-cells: Must be <2>. The first cell is the bank within + the CIU and may have a value between 0 and 63. The second cell is + the bit within the bank and may also have a value between 0 and 63. + +Example: + interrupt-controller@1070100000000 { + compatible = "cavium,octeon-6880-ciu2"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Controller register (0..63) + * 2) Bit within the register (0..63) + */ + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x10701 0x00000000 0x0 0x4000000>; + }; diff --git a/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt new file mode 100644 index 00000000000..cb4291e3b1d --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt @@ -0,0 +1,21 @@ +* DMA Engine. + +The Octeon DMA Engine transfers between the Boot Bus and main memory. +The DMA Engine will be refered to by phandle by any device that is +connected to it. + +Properties: +- compatible: "cavium,octeon-5750-bootbus-dma" + + Compatibility with all cn52XX, cn56XX and cn6XXX SOCs. + +- reg: The base address of the DMA Engine's register bank. + +- interrupts: A single interrupt specifier. + +Example: + dma0: dma-engine@1180000000100 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000100 0x0 0x8>; + interrupts = <0 63>; + }; diff --git a/Documentation/devicetree/bindings/mips/cavium/uctl.txt b/Documentation/devicetree/bindings/mips/cavium/uctl.txt new file mode 100644 index 00000000000..aa66b9b8d80 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/uctl.txt @@ -0,0 +1,46 @@ +* UCTL USB controller glue + +Properties: +- compatible: "cavium,octeon-6335-uctl" + + Compatibility with all cn6XXX SOCs. + +- reg: The base address of the UCTL register bank. + +- #address-cells: Must be <2>. + +- #size-cells: Must be <2>. + +- ranges: Empty to signify direct mapping of the children. + +- refclk-frequency: A single cell containing the reference clock + frequency in Hz. + +- refclk-type: A string describing the reference clock connection + either "crystal" or "external". + +Example: + uctl@118006f000000 { + compatible = "cavium,octeon-6335-uctl"; + reg = <0x11800 0x6f000000 0x0 0x100>; + ranges; /* Direct mapping */ + #address-cells = <2>; + #size-cells = <2>; + /* 12MHz, 24MHz and 48MHz allowed */ + refclk-frequency = <24000000>; + /* Either "crystal" or "external" */ + refclk-type = "crystal"; + + ehci@16f0000000000 { + compatible = "cavium,octeon-6335-ehci","usb-ehci"; + reg = <0x16f00 0x00000000 0x0 0x100>; + interrupts = <0 56>; + big-endian-regs; + }; + ohci@16f0000000400 { + compatible = "cavium,octeon-6335-ohci","usb-ohci"; + reg = <0x16f00 0x00000400 0x0 0x100>; + interrupts = <0 56>; + big-endian-regs; + }; + }; diff --git a/Documentation/devicetree/bindings/net/cavium-mdio.txt b/Documentation/devicetree/bindings/net/cavium-mdio.txt new file mode 100644 index 00000000000..04cb7491d23 --- /dev/null +++ b/Documentation/devicetree/bindings/net/cavium-mdio.txt @@ -0,0 +1,27 @@ +* System Management Interface (SMI) / MDIO + +Properties: +- compatible: "cavium,octeon-3860-mdio" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the MDIO bus controller register bank. + +- #address-cells: Must be <1>. + +- #size-cells: Must be <0>. MDIO addresses have no size component. + +Typically an MDIO bus might have several children. + +Example: + mdio@1180000001800 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00001800 0x0 0x40>; + + ethernet-phy@0 { + ... + reg = <0>; + }; + }; diff --git a/Documentation/devicetree/bindings/net/cavium-mix.txt b/Documentation/devicetree/bindings/net/cavium-mix.txt new file mode 100644 index 00000000000..5da628db68b --- /dev/null +++ b/Documentation/devicetree/bindings/net/cavium-mix.txt @@ -0,0 +1,39 @@ +* MIX Ethernet controller. + +Properties: +- compatible: "cavium,octeon-5750-mix" + + Compatibility with all cn5XXX and cn6XXX SOCs populated with MIX + devices. + +- reg: The base addresses of four separate register banks. The first + bank contains the MIX registers. The second bank the corresponding + AGL registers. The third bank are the AGL registers shared by all + MIX devices present. The fourth bank is the AGL_PRT_CTL shared by + all MIX devices present. + +- cell-index: A single cell specifying which portion of the shared + register banks corresponds to this MIX device. + +- interrupts: Two interrupt specifiers. The first is the MIX + interrupt routing and the second the routing for the AGL interrupts. + +- mac-address: Optional, the MAC address to assign to the device. + +- local-mac-address: Optional, the MAC address to assign to the device + if mac-address is not specified. + +- phy-handle: Optional, a phandle for the PHY device connected to this device. + +Example: + ethernet@1070000100800 { + compatible = "cavium,octeon-5750-mix"; + reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */ + <0x11800 0xE0000800 0x0 0x300>, /* AGL */ + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ + <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */ + cell-index = <1>; + interrupts = <1 18>, < 1 46>; + local-mac-address = [ 00 0f b7 10 63 54 ]; + phy-handle = <&phy1>; + }; diff --git a/Documentation/devicetree/bindings/net/cavium-pip.txt b/Documentation/devicetree/bindings/net/cavium-pip.txt new file mode 100644 index 00000000000..d4c53ba04b3 --- /dev/null +++ b/Documentation/devicetree/bindings/net/cavium-pip.txt @@ -0,0 +1,98 @@ +* PIP Ethernet nexus. + +The PIP Ethernet nexus can control several data packet input/output +devices. The devices have a two level grouping scheme. There may be +several interfaces, and each interface may have several ports. These +ports might be an individual Ethernet PHY. + + +Properties for the PIP nexus: +- compatible: "cavium,octeon-3860-pip" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the PIP's register bank. + +- #address-cells: Must be <1>. + +- #size-cells: Must be <0>. + +Properties for PIP interfaces which is a child the PIP nexus: +- compatible: "cavium,octeon-3860-pip-interface" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The interface number. + +- #address-cells: Must be <1>. + +- #size-cells: Must be <0>. + +Properties for PIP port which is a child the PIP interface: +- compatible: "cavium,octeon-3860-pip-port" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The port number within the interface group. + +- mac-address: Optional, the MAC address to assign to the device. + +- local-mac-address: Optional, the MAC address to assign to the device + if mac-address is not specified. + +- phy-handle: Optional, a phandle for the PHY device connected to this device. + +Example: + + pip@11800a0000000 { + compatible = "cavium,octeon-3860-pip"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0xa0000000 0x0 0x2000>; + + interface@0 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 0f b7 10 63 60 ]; + phy-handle = <&phy2>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 0f b7 10 63 61 ]; + phy-handle = <&phy3>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 0f b7 10 63 62 ]; + phy-handle = <&phy4>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 0f b7 10 63 63 ]; + phy-handle = <&phy5>; + }; + }; + + interface@1 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 0f b7 10 63 64 ]; + phy-handle = <&phy6>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt new file mode 100644 index 00000000000..cfe1db3bb6e --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt @@ -0,0 +1,12 @@ +LPC32XX PWM controller + +Required properties: +- compatible: should be "nxp,lpc3220-pwm" +- reg: physical base address and length of the controller's registers + +Examples: + +pwm@0x4005C000 { + compatible = "nxp,lpc3220-pwm"; + reg = <0x4005C000 0x8>; +}; diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt new file mode 100644 index 00000000000..b16f4a57d11 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt @@ -0,0 +1,17 @@ +Freescale MXS PWM controller + +Required properties: +- compatible: should be "fsl,imx23-pwm" +- reg: physical base address and length of the controller's registers +- #pwm-cells: should be 2. The first cell specifies the per-chip index + of the PWM to use and the second cell is the duty cycle in nanoseconds. +- fsl,pwm-number: the number of PWM devices + +Example: + +pwm: pwm@80064000 { + compatible = "fsl,imx28-pwm", "fsl,imx23-pwm"; + reg = <0x80064000 2000>; + #pwm-cells = <2>; + fsl,pwm-number = <8>; +}; diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt new file mode 100644 index 00000000000..bbbeedb4ec0 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt @@ -0,0 +1,18 @@ +Tegra SoC PWFM controller + +Required properties: +- compatible: should be one of: + - "nvidia,tegra20-pwm" + - "nvidia,tegra30-pwm" +- reg: physical base address and length of the controller's registers +- #pwm-cells: On Tegra the number of cells used to specify a PWM is 2. The + first cell specifies the per-chip index of the PWM to use and the second + cell is the duty cycle in nanoseconds. + +Example: + + pwm: pwm@7000a000 { + compatible = "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/pwm/pwm.txt b/Documentation/devicetree/bindings/pwm/pwm.txt new file mode 100644 index 00000000000..73ec962bfe8 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm.txt @@ -0,0 +1,57 @@ +Specifying PWM information for devices +====================================== + +1) PWM user nodes +----------------- + +PWM users should specify a list of PWM devices that they want to use +with a property containing a 'pwm-list': + + pwm-list ::= <single-pwm> [pwm-list] + single-pwm ::= <pwm-phandle> <pwm-specifier> + pwm-phandle : phandle to PWM controller node + pwm-specifier : array of #pwm-cells specifying the given PWM + (controller specific) + +PWM properties should be named "pwms". The exact meaning of each pwms +property must be documented in the device tree binding for each device. +An optional property "pwm-names" may contain a list of strings to label +each of the PWM devices listed in the "pwms" property. If no "pwm-names" +property is given, the name of the user node will be used as fallback. + +Drivers for devices that use more than a single PWM device can use the +"pwm-names" property to map the name of the PWM device requested by the +pwm_get() call to an index into the list given by the "pwms" property. + +The following example could be used to describe a PWM-based backlight +device: + + pwm: pwm { + #pwm-cells = <2>; + }; + + [...] + + bl: backlight { + pwms = <&pwm 0 5000000>; + pwm-names = "backlight"; + }; + +pwm-specifier typically encodes the chip-relative PWM number and the PWM +period in nanoseconds. Note that in the example above, specifying the +"pwm-names" is redundant because the name "backlight" would be used as +fallback anyway. + +2) PWM controller nodes +----------------------- + +PWM controller nodes must specify the number of cells used for the +specifier using the '#pwm-cells' property. + +An example PWM controller might look like this: + + pwm: pwm@7000a000 { + compatible = "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + }; diff --git a/Documentation/devicetree/bindings/serial/cavium-uart.txt b/Documentation/devicetree/bindings/serial/cavium-uart.txt new file mode 100644 index 00000000000..87a6c375cd4 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/cavium-uart.txt @@ -0,0 +1,19 @@ +* Universal Asynchronous Receiver/Transmitter (UART) + +- compatible: "cavium,octeon-3860-uart" + + Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs. + +- reg: The base address of the UART register bank. + +- interrupts: A single interrupt specifier. + +- current-speed: Optional, the current bit rate in bits per second. + +Example: + uart1: serial@1180000000c00 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000c00 0x0 0x400>; + current-speed = <115200>; + interrupts = <0 35>; + }; diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt new file mode 100644 index 00000000000..1e4fc727f3b --- /dev/null +++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt @@ -0,0 +1,28 @@ +pwm-backlight bindings + +Required properties: + - compatible: "pwm-backlight" + - pwms: OF device-tree PWM specification (see PWM binding[0]) + - brightness-levels: Array of distinct brightness levels. Typically these + are in the range from 0 to 255, but any range starting at 0 will do. + The actual brightness level (PWM duty cycle) will be interpolated + from these values. 0 means a 0% duty cycle (darkest/off), while the + last value in the array represents a 100% duty cycle (brightest). + - default-brightness-level: the default brightness level (index into the + array defined by the "brightness-levels" property) + +Optional properties: + - pwm-names: a list of names for the PWM devices specified in the + "pwms" property (see PWM binding[0]) + +[0]: Documentation/devicetree/bindings/pwm/pwm.txt + +Example: + + backlight { + compatible = "pwm-backlight"; + pwms = <&pwm 0 5000000>; + + brightness-levels = <0 4 8 16 32 64 128 255>; + default-brightness-level = <6>; + }; diff --git a/Documentation/dontdiff b/Documentation/dontdiff index b4a898f43c3..39462cf35cd 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -150,7 +150,6 @@ keywords.c ksym.c* ksym.h* kxgettext -lkc_defs.h lex.c lex.*.c linux diff --git a/Documentation/edac.txt b/Documentation/edac.txt index 03df2b02033..56c7e936430 100644 --- a/Documentation/edac.txt +++ b/Documentation/edac.txt @@ -232,116 +232,20 @@ EDAC control and attribute files. In 'mcX' directories are EDAC control and attribute files for -this 'X' instance of the memory controllers: - - -Counter reset control file: - - 'reset_counters' - - This write-only control file will zero all the statistical counters - for UE and CE errors. Zeroing the counters will also reset the timer - indicating how long since the last counter zero. This is useful - for computing errors/time. Since the counters are always reset at - driver initialization time, no module/kernel parameter is available. - - RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset - - This resets the counters on memory controller 0 - - -Seconds since last counter reset control file: - - 'seconds_since_reset' - - This attribute file displays how many seconds have elapsed since the - last counter reset. This can be used with the error counters to - measure error rates. - - - -Memory Controller name attribute file: - - 'mc_name' - - This attribute file displays the type of memory controller - that is being utilized. - - -Total memory managed by this memory controller attribute file: - - 'size_mb' - - This attribute file displays, in count of megabytes, of memory - that this instance of memory controller manages. - - -Total Uncorrectable Errors count attribute file: - - 'ue_count' - - This attribute file displays the total count of uncorrectable - errors that have occurred on this memory controller. If panic_on_ue - is set this counter will not have a chance to increment, - since EDAC will panic the system. - - -Total UE count that had no information attribute fileY: - - 'ue_noinfo_count' - - This attribute file displays the number of UEs that have occurred - with no information as to which DIMM slot is having errors. - - -Total Correctable Errors count attribute file: - - 'ce_count' - - This attribute file displays the total count of correctable - errors that have occurred on this memory controller. This - count is very important to examine. CEs provide early - indications that a DIMM is beginning to fail. This count - field should be monitored for non-zero values and report - such information to the system administrator. - - -Total Correctable Errors count attribute file: - - 'ce_noinfo_count' - - This attribute file displays the number of CEs that - have occurred wherewith no information as to which DIMM slot - is having errors. Memory is handicapped, but operational, - yet no information is available to indicate which slot - the failing memory is in. This count field should be also - be monitored for non-zero values. - -Device Symlink: - - 'device' - - Symlink to the memory controller device. - -Sdram memory scrubbing rate: - - 'sdram_scrub_rate' - - Read/Write attribute file that controls memory scrubbing. The scrubbing - rate is set by writing a minimum bandwidth in bytes/sec to the attribute - file. The rate will be translated to an internal value that gives at - least the specified rate. - - Reading the file will return the actual scrubbing rate employed. - - If configuration fails or memory scrubbing is not implemented, accessing - that attribute will fail. +this 'X' instance of the memory controllers. +For a description of the sysfs API, please see: + Documentation/ABI/testing/sysfs/devices-edac ============================================================================ 'csrowX' DIRECTORIES +When CONFIG_EDAC_LEGACY_SYSFS is enabled, the sysfs will contain the +csrowX directories. As this API doesn't work properly for Rambus, FB-DIMMs +and modern Intel Memory Controllers, this is being deprecated in favor +of dimmX directories. + In the 'csrowX' directories are EDAC control and attribute files for this 'X' instance of csrow: diff --git a/Documentation/input/edt-ft5x06.txt b/Documentation/input/edt-ft5x06.txt new file mode 100644 index 00000000000..2032f0b7a8f --- /dev/null +++ b/Documentation/input/edt-ft5x06.txt @@ -0,0 +1,54 @@ +EDT ft5x06 based Polytouch devices +---------------------------------- + +The edt-ft5x06 driver is useful for the EDT "Polytouch" family of capacitive +touch screens. Note that it is *not* suitable for other devices based on the +focaltec ft5x06 devices, since they contain vendor-specific firmware. In +particular this driver is not suitable for the Nook tablet. + +It has been tested with the following devices: + * EP0350M06 + * EP0430M06 + * EP0570M06 + * EP0700M06 + +The driver allows configuration of the touch screen via a set of sysfs files: + +/sys/class/input/eventX/device/device/threshold: + allows setting the "click"-threshold in the range from 20 to 80. + +/sys/class/input/eventX/device/device/gain: + allows setting the sensitivity in the range from 0 to 31. Note that + lower values indicate higher sensitivity. + +/sys/class/input/eventX/device/device/offset: + allows setting the edge compensation in the range from 0 to 31. + +/sys/class/input/eventX/device/device/report_rate: + allows setting the report rate in the range from 3 to 14. + + +For debugging purposes the driver provides a few files in the debug +filesystem (if available in the kernel). In /sys/kernel/debug/edt_ft5x06 +you'll find the following files: + +num_x, num_y: + (readonly) contains the number of sensor fields in X- and + Y-direction. + +mode: + allows switching the sensor between "factory mode" and "operation + mode" by writing "1" or "0" to it. In factory mode (1) it is + possible to get the raw data from the sensor. Note that in factory + mode regular events don't get delivered and the options described + above are unavailable. + +raw_data: + contains num_x * num_y big endian 16 bit values describing the raw + values for each sensor field. Note that each read() call on this + files triggers a new readout. It is recommended to provide a buffer + big enough to contain num_x * num_y * 2 bytes. + +Note that reading raw_data gives a I/O error when the device is not in factory +mode. The same happens when reading/writing to the parameter files when the +device is not in regular operation mode. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c2619ef44a7..ad7e2e5088c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -526,7 +526,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. coherent_pool=nn[KMG] [ARM,KNL] Sets the size of memory pool for coherent, atomic dma - allocations if Contiguous Memory Allocator (CMA) is used. + allocations, by default set to 256K. code_bytes [X86] How many bytes of object code to print in an oops report. diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt new file mode 100644 index 00000000000..554290ebab9 --- /dev/null +++ b/Documentation/pwm.txt @@ -0,0 +1,76 @@ +Pulse Width Modulation (PWM) interface + +This provides an overview about the Linux PWM interface + +PWMs are commonly used for controlling LEDs, fans or vibrators in +cell phones. PWMs with a fixed purpose have no need implementing +the Linux PWM API (although they could). However, PWMs are often +found as discrete devices on SoCs which have no fixed purpose. It's +up to the board designer to connect them to LEDs or fans. To provide +this kind of flexibility the generic PWM API exists. + +Identifying PWMs +---------------- + +Users of the legacy PWM API use unique IDs to refer to PWM devices. + +Instead of referring to a PWM device via its unique ID, board setup code +should instead register a static mapping that can be used to match PWM +consumers to providers, as given in the following example: + + static struct pwm_lookup board_pwm_lookup[] = { + PWM_LOOKUP("tegra-pwm", 0, "pwm-backlight", NULL), + }; + + static void __init board_init(void) + { + ... + pwm_add_table(board_pwm_lookup, ARRAY_SIZE(board_pwm_lookup)); + ... + } + +Using PWMs +---------- + +Legacy users can request a PWM device using pwm_request() and free it +after usage with pwm_free(). + +New users should use the pwm_get() function and pass to it the consumer +device or a consumer name. pwm_put() is used to free the PWM device. + +After being requested a PWM has to be configured using: + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); + +To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). + +Implementing a PWM driver +------------------------- + +Currently there are two ways to implement pwm drivers. Traditionally +there only has been the barebone API meaning that each driver has +to implement the pwm_*() functions itself. This means that it's impossible +to have multiple PWM drivers in the system. For this reason it's mandatory +for new drivers to use the generic PWM framework. + +A new PWM controller/chip can be added using pwmchip_add() and removed +again with pwmchip_remove(). pwmchip_add() takes a filled in struct +pwm_chip as argument which provides a description of the PWM chip, the +number of PWM devices provider by the chip and the chip-specific +implementation of the supported PWM operations to the framework. + +Locking +------- + +The PWM core list manipulations are protected by a mutex, so pwm_request() +and pwm_free() may not be called from an atomic context. Currently the +PWM core does not enforce any locking to pwm_enable(), pwm_disable() and +pwm_config(), so the calling context is currently driver specific. This +is an issue derived from the former barebone API and should be fixed soon. + +Helpers +------- + +Currently a PWM can only be configured with period_ns and duty_ns. For several +use cases freq_hz and duty_percent might be better. Instead of calculating +this in your driver please consider adding appropriate helpers to the framework. diff --git a/MAINTAINERS b/MAINTAINERS index c8804c048ac..b2e3d88ff4c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5527,6 +5527,18 @@ S: Maintained F: Documentation/video4linux/README.pvrusb2 F: drivers/media/video/pvrusb2/ +PWM SUBSYSTEM +M: Thierry Reding <thierry.reding@avionic-design.de> +L: linux-kernel@vger.kernel.org +S: Maintained +W: http://gitorious.org/linux-pwm +T: git git://gitorious.org/linux-pwm/linux-pwm.git +F: Documentation/pwm.txt +F: Documentation/devicetree/bindings/pwm/ +F: include/linux/pwm.h +F: include/linux/of_pwm.h +F: drivers/pwm/ + PXA2xx/PXA3xx SUPPORT M: Eric Miao <eric.y.miao@gmail.com> M: Russell King <linux@arm.linux.org.uk> @@ -5901,6 +5913,16 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/s3c-fb.c +SAMSUNG MULTIFUNCTION DEVICE DRIVERS +M: Sangbeom Kim <sbkim73@samsung.com> +L: linux-kernel@vger.kernel.org +S: Supported +F: drivers/mfd/sec*.c +F: drivers/regulator/s2m*.c +F: drivers/regulator/s5m*.c +F: drivers/rtc/rtc-sec.c +F: include/linux/mfd/samsung/ + SERIAL DRIVERS M: Alan Cox <alan@linux.intel.com> L: linux-serial@vger.kernel.org @@ -535,11 +535,11 @@ PHONY += include/config/auto.conf include/config/auto.conf: $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \ - echo; \ - echo " ERROR: Kernel configuration is invalid."; \ - echo " include/generated/autoconf.h or $@ are missing.";\ - echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ - echo; \ + echo >&2; \ + echo >&2 " ERROR: Kernel configuration is invalid."; \ + echo >&2 " include/generated/autoconf.h or $@ are missing.";\ + echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ + echo >&2 ; \ /bin/false) endif # KBUILD_EXTMOD @@ -796,8 +796,8 @@ prepare3: include/config/kernel.release ifneq ($(KBUILD_SRC),) @$(kecho) ' Using $(srctree) as source for kernel' $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ - echo " $(srctree) is not clean, please run 'make mrproper'"; \ - echo " in the '$(srctree)' directory.";\ + echo >&2 " $(srctree) is not clean, please run 'make mrproper'"; \ + echo >&2 " in the '$(srctree)' directory.";\ /bin/false; \ fi; endif @@ -971,11 +971,11 @@ else # CONFIG_MODULES # --------------------------------------------------------------------------- modules modules_install: FORCE - @echo - @echo "The present kernel configuration has modules disabled." - @echo "Type 'make config' and enable loadable module support." - @echo "Then build a kernel with module support enabled." - @echo + @echo >&2 + @echo >&2 "The present kernel configuration has modules disabled." + @echo >&2 "Type 'make config' and enable loadable module support." + @echo >&2 "Then build a kernel with module support enabled." + @echo >&2 @exit 1 endif # CONFIG_MODULES diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5df11147be8..7980873525b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1011,7 +1011,6 @@ config ARCH_VT8500 select ARCH_HAS_CPUFREQ select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB - select HAVE_PWM help Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts index 2e1cfa00c25..9fecf1ae777 100644 --- a/arch/arm/boot/dts/highbank.dts +++ b/arch/arm/boot/dts/highbank.dts @@ -130,6 +130,12 @@ clocks = <&eclk>; }; + memory-controller@fff00000 { + compatible = "calxeda,hb-ddr-ctrl"; + reg = <0xfff00000 0x1000>; + interrupts = <0 91 4>; + }; + ipc@fff20000 { compatible = "arm,pl320", "arm,primecell"; reg = <0xfff20000 0x1000>; @@ -275,6 +281,12 @@ }; }; + sregs@fff3c200 { + compatible = "calxeda,hb-sregs-l2-ecc"; + reg = <0xfff3c200 0x100>; + interrupts = <0 71 4 0 72 4>; + }; + dma@fff3d000 { compatible = "arm,pl330", "arm,primecell"; reg = <0xfff3d000 0x1000>; diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi new file mode 100644 index 00000000000..798fa35c000 --- /dev/null +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -0,0 +1,21 @@ +/* + * Device Tree Source for the r8a7740 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,r8a7740"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a9"; + }; + }; +}; diff --git a/arch/arm/boot/dts/sh7377.dtsi b/arch/arm/boot/dts/sh7377.dtsi new file mode 100644 index 00000000000..767ee0796da --- /dev/null +++ b/arch/arm/boot/dts/sh7377.dtsi @@ -0,0 +1,21 @@ +/* + * Device Tree Source for the sh7377 SoC + * + * Copyright (C) 2012 Renesas Solutions Corp. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "renesas,sh7377"; + + cpus { + cpu@0 { + compatible = "arm,cortex-a8"; + }; + }; +}; diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 9f1921634eb..405d1673904 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -123,6 +123,12 @@ status = "disabled"; }; + pwm { + compatible = "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + }; + i2c@7000c000 { compatible = "nvidia,tegra20-i2c"; reg = <0x7000c000 0x100>; diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index da740191771..3e4334d14ef 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -117,6 +117,12 @@ status = "disabled"; }; + pwm { + compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm"; + reg = <0x7000a000 0x100>; + #pwm-cells = <2>; + }; + i2c@7000c000 { compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; reg = <0x7000c000 0x100>; diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index aa07f5938f0..1143c4d5c56 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -452,6 +452,7 @@ static struct dma_map_ops dmabounce_ops = { .alloc = arm_dma_alloc, .free = arm_dma_free, .mmap = arm_dma_mmap, + .get_sgtable = arm_dma_get_sgtable, .map_page = dmabounce_map_page, .unmap_page = dmabounce_unmap_page, .sync_single_for_cpu = dmabounce_sync_for_cpu, diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig index ddc9fe6a78a..7d8718468e0 100644 --- a/arch/arm/configs/armadillo800eva_defconfig +++ b/arch/arm/configs/armadillo800eva_defconfig @@ -5,10 +5,7 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 # CONFIG_UTS_NS is not set # CONFIG_IPC_NS is not set -# CONFIG_USER_NS is not set # CONFIG_PID_NS is not set -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SLAB=y CONFIG_MODULES=y @@ -21,7 +18,7 @@ CONFIG_ARCH_SHMOBILE=y CONFIG_ARCH_R8A7740=y CONFIG_MACH_ARMADILLO800EVA=y # CONFIG_SH_TIMER_TMU is not set -# CONFIG_ARM_THUMB is not set +CONFIG_ARM_THUMB=y CONFIG_CPU_BPREDICT_DISABLE=y # CONFIG_CACHE_L2X0 is not set CONFIG_ARM_ERRATA_430973=y @@ -39,6 +36,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" CONFIG_CMDLINE_FORCE=y CONFIG_KEXEC=y +CONFIG_VFP=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_SUSPEND is not set CONFIG_NET=y @@ -89,26 +87,32 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_I2C=y CONFIG_I2C_SH_MOBILE=y # CONFIG_HWMON is not set +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +# CONFIG_RC_CORE is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +# CONFIG_V4L_USB_DRIVERS is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_MT9T112=y +CONFIG_VIDEO_SH_MOBILE_CEU=y +# CONFIG_RADIO_ADAPTERS is not set CONFIG_FB=y -CONFIG_FB_MODE_HELPERS=y CONFIG_FB_SH_MOBILE_LCDC=y +CONFIG_FB_SH_MOBILE_HDMI=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_SOUND=y -CONFIG_SND=y # CONFIG_SND_SUPPORT_OLD_API is not set # CONFIG_SND_VERBOSE_PROCFS is not set # CONFIG_SND_DRIVERS is not set # CONFIG_SND_ARM is not set -CONFIG_SND_SOC=y CONFIG_SND_SOC_SH4_FSI=y # CONFIG_HID_SUPPORT is not set CONFIG_USB=y -# CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_GADGET=y CONFIG_USB_RENESAS_USBHS_UDC=y @@ -116,6 +120,8 @@ CONFIG_USB_ETH=m CONFIG_MMC=y CONFIG_MMC_SDHI=y CONFIG_MMC_SH_MMCIF=y +CONFIG_DMADEVICES=y +CONFIG_SH_DMAE=y CONFIG_UIO=y CONFIG_UIO_PDRV_GENIRQ=y # CONFIG_DNOTIFY is not set @@ -124,7 +130,6 @@ CONFIG_VFAT_FS=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig new file mode 100644 index 00000000000..26146ffea1a --- /dev/null +++ b/arch/arm/configs/kzm9d_defconfig @@ -0,0 +1,89 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_EXPERIMENTAL=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_EMBEDDED=y +CONFIG_SLAB=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_SHMOBILE=y +CONFIG_ARCH_EMEV2=y +CONFIG_MACH_KZM9D=y +CONFIG_MEMORY_START=0x40000000 +CONFIG_MEMORY_SIZE=0x10000000 +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_SWP_EMULATE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +# CONFIG_LOCAL_TIMERS is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ARM_APPENDED_DTB=y +CONFIG_CMDLINE="console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" +CONFIG_CMDLINE_FORCE=y +CONFIG_VFP=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_EM=y +# CONFIG_HW_RANDOM is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_EM=y +# CONFIG_HWMON is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +# CONFIG_FTRACE is not set diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index e3ebc20ed0a..2388c861062 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig @@ -100,7 +100,12 @@ CONFIG_SND_SOC_SH4_FSI=y CONFIG_USB=y CONFIG_USB_DEVICEFS=y CONFIG_USB_R8A66597_HCD=y +CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_RENESAS_USBHS_UDC=y +CONFIG_USB_ETH=m +CONFIG_USB_MASS_STORAGE=m CONFIG_MMC=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_MMC_SDHI=y @@ -108,12 +113,13 @@ CONFIG_MMC_SH_MMCIF=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_RS5C372=y CONFIG_DMADEVICES=y CONFIG_SH_DMAE=y CONFIG_ASYNC_TX_DMA=y CONFIG_STAGING=y # CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set +CONFIG_INOTIFY_USER=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 4be9c1e80ee..db2245353f0 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -106,6 +106,7 @@ CONFIG_I2C_TEGRA=y CONFIG_SPI=y CONFIG_SPI_TEGRA=y CONFIG_GPIO_TPS65910=y +CONFIG_GPIO_TPS6586X=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_SBS=y CONFIG_SENSORS_LM90=y diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index bbef15d0489..2ae842df455 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -186,17 +186,6 @@ extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs); -#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL) - -static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t dma_addr, - size_t size, struct dma_attrs *attrs) -{ - struct dma_map_ops *ops = get_dma_ops(dev); - BUG_ON(!ops); - return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs); -} - static inline void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { @@ -213,20 +202,12 @@ static inline void dma_free_writecombine(struct device *dev, size_t size, return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs); } -static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t dma_addr, size_t size) -{ - DEFINE_DMA_ATTRS(attrs); - dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); - return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs); -} - /* * This can be called during boot to increase the size of the consistent * DMA region above it's default value of 2MB. It must be called before the * memory allocator is initialised, i.e. before any core_initcall. */ -extern void __init init_consistent_dma_size(unsigned long size); +static inline void init_consistent_dma_size(unsigned long size) { } /* * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic" @@ -280,6 +261,9 @@ extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int, enum dma_data_direction); extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int, enum dma_data_direction); +extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t dma_addr, size_t size, + struct dma_attrs *attrs); #endif /* __KERNEL__ */ #endif diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index 26fe9de35ec..2f51293c187 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -620,10 +620,6 @@ static struct clk exynos4_init_clocks_off[] = { .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 27), }, { - .name = "fimg2d", - .enable = exynos4_clk_ip_image_ctrl, - .ctrlbit = (1 << 0), - }, { .name = "mfc", .devname = "s5p-mfc", .enable = exynos4_clk_ip_mfc_ctrl, @@ -819,47 +815,21 @@ static struct clk *exynos4_clkset_mout_g2d0_list[] = { [1] = &exynos4_clk_sclk_apll.clk, }; -static struct clksrc_sources exynos4_clkset_mout_g2d0 = { +struct clksrc_sources exynos4_clkset_mout_g2d0 = { .sources = exynos4_clkset_mout_g2d0_list, .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g2d0_list), }; -static struct clksrc_clk exynos4_clk_mout_g2d0 = { - .clk = { - .name = "mout_g2d0", - }, - .sources = &exynos4_clkset_mout_g2d0, - .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 }, -}; - static struct clk *exynos4_clkset_mout_g2d1_list[] = { [0] = &exynos4_clk_mout_epll.clk, [1] = &exynos4_clk_sclk_vpll.clk, }; -static struct clksrc_sources exynos4_clkset_mout_g2d1 = { +struct clksrc_sources exynos4_clkset_mout_g2d1 = { .sources = exynos4_clkset_mout_g2d1_list, .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g2d1_list), }; -static struct clksrc_clk exynos4_clk_mout_g2d1 = { - .clk = { - .name = "mout_g2d1", - }, - .sources = &exynos4_clkset_mout_g2d1, - .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 }, -}; - -static struct clk *exynos4_clkset_mout_g2d_list[] = { - [0] = &exynos4_clk_mout_g2d0.clk, - [1] = &exynos4_clk_mout_g2d1.clk, -}; - -static struct clksrc_sources exynos4_clkset_mout_g2d = { - .sources = exynos4_clkset_mout_g2d_list, - .nr_sources = ARRAY_SIZE(exynos4_clkset_mout_g2d_list), -}; - static struct clk *exynos4_clkset_mout_mfc0_list[] = { [0] = &exynos4_clk_mout_mpll.clk, [1] = &exynos4_clk_sclk_apll.clk, @@ -1126,13 +1096,6 @@ static struct clksrc_clk exynos4_clksrcs[] = { .reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 }, }, { .clk = { - .name = "sclk_fimg2d", - }, - .sources = &exynos4_clkset_mout_g2d, - .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 }, - .reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 }, - }, { - .clk = { .name = "sclk_mfc", .devname = "s5p-mfc", }, diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h index 28a11970118..bd12d5f8b63 100644 --- a/arch/arm/mach-exynos/clock-exynos4.h +++ b/arch/arm/mach-exynos/clock-exynos4.h @@ -23,6 +23,9 @@ extern struct clksrc_sources exynos4_clkset_group; extern struct clk *exynos4_clkset_aclk_top_list[]; extern struct clk *exynos4_clkset_group_list[]; +extern struct clksrc_sources exynos4_clkset_mout_g2d0; +extern struct clksrc_sources exynos4_clkset_mout_g2d1; + extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable); extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable); diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c index b8689ff60ba..fed4c26e9da 100644 --- a/arch/arm/mach-exynos/clock-exynos4210.c +++ b/arch/arm/mach-exynos/clock-exynos4210.c @@ -48,6 +48,32 @@ static struct clksrc_clk *sysclks[] = { /* nothing here yet */ }; +static struct clksrc_clk exynos4210_clk_mout_g2d0 = { + .clk = { + .name = "mout_g2d0", + }, + .sources = &exynos4_clkset_mout_g2d0, + .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 }, +}; + +static struct clksrc_clk exynos4210_clk_mout_g2d1 = { + .clk = { + .name = "mout_g2d1", + }, + .sources = &exynos4_clkset_mout_g2d1, + .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 }, +}; + +static struct clk *exynos4210_clkset_mout_g2d_list[] = { + [0] = &exynos4210_clk_mout_g2d0.clk, + [1] = &exynos4210_clk_mout_g2d1.clk, +}; + +static struct clksrc_sources exynos4210_clkset_mout_g2d = { + .sources = exynos4210_clkset_mout_g2d_list, + .nr_sources = ARRAY_SIZE(exynos4210_clkset_mout_g2d_list), +}; + static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable); @@ -74,6 +100,13 @@ static struct clksrc_clk clksrcs[] = { .sources = &exynos4_clkset_group, .reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 }, .reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimg2d", + }, + .sources = &exynos4210_clkset_mout_g2d, + .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 }, + .reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 }, }, }; @@ -105,6 +138,10 @@ static struct clk init_clocks_off[] = { .devname = SYSMMU_CLOCK_DEVNAME(fimd1, 11), .enable = exynos4_clk_ip_lcd1_ctrl, .ctrlbit = (1 << 4), + }, { + .name = "fimg2d", + .enable = exynos4_clk_ip_image_ctrl, + .ctrlbit = (1 << 0), }, }; diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c index da397d21bbc..8fba0b5fb8a 100644 --- a/arch/arm/mach-exynos/clock-exynos4212.c +++ b/arch/arm/mach-exynos/clock-exynos4212.c @@ -68,12 +68,45 @@ static struct clksrc_clk clk_mout_mpll_user = { .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 }, }; +static struct clksrc_clk exynos4x12_clk_mout_g2d0 = { + .clk = { + .name = "mout_g2d0", + }, + .sources = &exynos4_clkset_mout_g2d0, + .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 }, +}; + +static struct clksrc_clk exynos4x12_clk_mout_g2d1 = { + .clk = { + .name = "mout_g2d1", + }, + .sources = &exynos4_clkset_mout_g2d1, + .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 }, +}; + +static struct clk *exynos4x12_clkset_mout_g2d_list[] = { + [0] = &exynos4x12_clk_mout_g2d0.clk, + [1] = &exynos4x12_clk_mout_g2d1.clk, +}; + +static struct clksrc_sources exynos4x12_clkset_mout_g2d = { + .sources = exynos4x12_clkset_mout_g2d_list, + .nr_sources = ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list), +}; + static struct clksrc_clk *sysclks[] = { &clk_mout_mpll_user, }; static struct clksrc_clk clksrcs[] = { - /* nothing here yet */ + { + .clk = { + .name = "sclk_fimg2d", + }, + .sources = &exynos4x12_clkset_mout_g2d, + .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 }, + .reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 }, + }, }; static struct clk init_clocks_off[] = { @@ -102,7 +135,11 @@ static struct clk init_clocks_off[] = { .devname = "exynos-fimc-lite.1", .enable = exynos4212_clk_ip_isp0_ctrl, .ctrlbit = (1 << 3), - } + }, { + .name = "fimg2d", + .enable = exynos4_clk_ip_dmc_ctrl, + .ctrlbit = (1 << 23), + }, }; #ifdef CONFIG_PM_SLEEP diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index f98a83a81ce..ea785fcaf6c 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -1066,12 +1066,8 @@ static struct platform_device nuri_max8903_device = { static void __init nuri_power_init(void) { int gpio; - int irq_base = IRQ_GPIO_END + 1; int ta_en = 0; - nuri_max8997_pdata.irq_base = irq_base; - irq_base += MAX8997_IRQ_NR; - gpio = EXYNOS4_GPX0(7); gpio_request(gpio, "AP_PMIC_IRQ"); s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf)); diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 5a12dc26f49..5ca80307d6d 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -426,7 +426,6 @@ static struct max8997_platform_data __initdata origen_max8997_pdata = { .buck1_gpiodvs = false, .buck2_gpiodvs = false, .buck5_gpiodvs = false, - .irq_base = IRQ_GPIO_END + 1, .ignore_gpiodvs_side_effect = true, .buck125_default_idx = 0x0, diff --git a/arch/arm/mach-pxa/eseries.h b/arch/arm/mach-pxa/eseries.h deleted file mode 100644 index b96949dd5ad..00000000000 --- a/arch/arm/mach-pxa/eseries.h +++ /dev/null @@ -1,14 +0,0 @@ -void __init eseries_fixup(struct tag *tags, char **cmdline, struct meminfo *mi); - -extern struct pxa2xx_udc_mach_info e7xx_udc_mach_info; -extern struct pxaficp_platform_data e7xx_ficp_platform_data; -extern int e7xx_irda_init(void); - -extern int eseries_tmio_enable(struct platform_device *dev); -extern int eseries_tmio_disable(struct platform_device *dev); -extern int eseries_tmio_suspend(struct platform_device *dev); -extern int eseries_tmio_resume(struct platform_device *dev); -extern void eseries_get_tmio_gpios(void); -extern struct resource eseries_tmio_resources[]; -extern struct platform_device e300_tc6387xb_device; - diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index d3de84b0dcb..e6311988add 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -296,27 +296,11 @@ static struct asic3_led asic3_leds[ASIC3_NUM_LEDS] = { static struct resource asic3_resources[] = { /* GPIO part */ - [0] = { - .start = ASIC3_PHYS, - .end = ASIC3_PHYS + ASIC3_MAP_SIZE_16BIT - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), - .end = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(ASIC3_PHYS, ASIC3_MAP_SIZE_16BIT), + [1] = DEFINE_RES_IRQ(PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ)), /* SD part */ - [2] = { - .start = ASIC3_SD_PHYS, - .end = ASIC3_SD_PHYS + ASIC3_MAP_SIZE_16BIT - 1, - .flags = IORESOURCE_MEM, - }, - [3] = { - .start = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), - .end = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), - .flags = IORESOURCE_IRQ, - }, + [2] = DEFINE_RES_MEM(ASIC3_SD_PHYS, ASIC3_MAP_SIZE_16BIT), + [3] = DEFINE_RES_IRQ(PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ)), }; static struct asic3_platform_data asic3_platform_data = { @@ -343,11 +327,7 @@ static struct platform_device asic3 = { */ static struct resource egpio_resources[] = { - [0] = { - .start = PXA_CS5_PHYS, - .end = PXA_CS5_PHYS + 0x4 - 1, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(PXA_CS5_PHYS, 0x4), }; static struct htc_egpio_chip egpio_chips[] = { @@ -537,11 +517,7 @@ static struct w100fb_mach_info w3220_info = { }; static struct resource w3220_resources[] = { - [0] = { - .start = ATI_W3220_PHYS, - .end = ATI_W3220_PHYS + 0x00ffffff, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(ATI_W3220_PHYS, SZ_16M), }; static struct platform_device w3220 = { @@ -683,20 +659,12 @@ static struct pda_power_pdata power_supply_info = { }; static struct resource power_supply_resources[] = { - [0] = { - .name = "ac", - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | - IORESOURCE_IRQ_LOWEDGE, - .start = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), - .end = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), - }, - [1] = { - .name = "usb", - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | - IORESOURCE_IRQ_LOWEDGE, - .start = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), - .end = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), - }, + [0] = DEFINE_RES_NAMED(PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), 1, "ac", + IORESOURCE_IRQ | + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE), + [1] = DEFINE_RES_NAMED(PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), 1, "usb", + IORESOURCE_IRQ | + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE), }; static struct platform_device power_supply = { diff --git a/arch/arm/mach-s3c64xx/include/mach/pm-core.h b/arch/arm/mach-s3c64xx/include/mach/pm-core.h index fcf3dcabb69..c0537f40a3d 100644 --- a/arch/arm/mach-s3c64xx/include/mach/pm-core.h +++ b/arch/arm/mach-s3c64xx/include/mach/pm-core.h @@ -12,6 +12,9 @@ * published by the Free Software Foundation. */ +#ifndef __MACH_S3C64XX_PM_CORE_H +#define __MACH_S3C64XX_PM_CORE_H __FILE__ + #include <mach/regs-gpio.h> static inline void s3c_pm_debug_init_uart(void) @@ -113,3 +116,4 @@ static inline void samsung_pm_saved_gpios(void) __raw_writel(S3C64XX_SLPEN_USE_xSLP, S3C64XX_SLPEN); } +#endif /* __MACH_S3C64XX_PM_CORE_H */ diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index df33909205e..4cacc2d22fb 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -19,6 +19,7 @@ config ARCH_SH7372 select CPU_V7 select SH_CLK_CPG select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_CPU_SUSPEND if PM || CPU_IDLE config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" @@ -58,6 +59,7 @@ config MACH_G4EVM bool "G4EVM board" depends on ARCH_SH7377 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_AP4EVB bool "AP4EVB board" @@ -65,6 +67,7 @@ config MACH_AP4EVB select ARCH_REQUIRE_GPIOLIB select SH_LCD_MIPI_DSI select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR choice prompt "AP4EVB LCD panel selection" @@ -83,6 +86,7 @@ config MACH_AG5EVM bool "AG5EVM board" select ARCH_REQUIRE_GPIOLIB select SH_LCD_MIPI_DSI + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_SH73A0 config MACH_MACKEREL @@ -90,15 +94,18 @@ config MACH_MACKEREL depends on ARCH_SH7372 select ARCH_REQUIRE_GPIOLIB select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KOTA2 bool "KOTA2 board" select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_SH73A0 config MACH_BONITO bool "bonito board" select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR depends on ARCH_R8A7740 config MACH_ARMADILLO800EVA @@ -106,22 +113,28 @@ config MACH_ARMADILLO800EVA depends on ARCH_R8A7740 select ARCH_REQUIRE_GPIOLIB select USE_OF + select REGULATOR_FIXED_VOLTAGE if REGULATOR + select SND_SOC_WM8978 if SND_SIMPLE_CARD config MACH_MARZEN bool "MARZEN board" depends on ARCH_R8A7779 select ARCH_REQUIRE_GPIOLIB + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KZM9D bool "KZM9D board" depends on ARCH_EMEV2 select USE_OF + select REGULATOR_FIXED_VOLTAGE if REGULATOR config MACH_KZM9G bool "KZM-A9-GT board" depends on ARCH_SH73A0 select ARCH_REQUIRE_GPIOLIB select USE_OF + select SND_SOC_AK4642 if SND_SIMPLE_CARD + select REGULATOR_FIXED_VOLTAGE if REGULATOR comment "SH-Mobile System Configuration" diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 8aa1962c22a..0df5ae6740c 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -39,7 +39,9 @@ obj-$(CONFIG_ARCH_R8A7740) += entry-intc.o # PM objects obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o +obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o +obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o # Board objects diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 5a6f22f05e9..d82c010fdfc 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -27,6 +27,8 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/serial_sci.h> #include <linux/smsc911x.h> #include <linux/gpio.h> @@ -52,6 +54,12 @@ #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + static struct resource smsc9220_resources[] = { [0] = { .start = 0x14000000, @@ -142,6 +150,13 @@ static struct platform_device fsi_device = { .resource = fsi_resources, }; +/* Fixed 1.8V regulator to be used by MMCIF */ +static struct regulator_consumer_supply fixed1v8_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), +}; + static struct resource sh_mmcif_resources[] = { [0] = { .name = "MMCIF", @@ -364,6 +379,13 @@ static struct platform_device mipidsi0_device = { }, }; +/* Fixed 2.8V regulators to be used by SDHI0 */ +static struct regulator_consumer_supply fixed2v8_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), +}; + /* SDHI0 */ static struct sh_mobile_sdhi_info sdhi0_info = { .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, @@ -408,8 +430,57 @@ static struct platform_device sdhi0_device = { }, }; -void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) +/* Fixed 3.3V regulator to be used by SDHI1 */ +static struct regulator_consumer_supply cn4_power_consumers[] = { + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), +}; + +static struct regulator_init_data cn4_power_init_data = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(cn4_power_consumers), + .consumer_supplies = cn4_power_consumers, +}; + +static struct fixed_voltage_config cn4_power_info = { + .supply_name = "CN4 SD/MMC Vdd", + .microvolts = 3300000, + .gpio = GPIO_PORT114, + .enable_high = 1, + .init_data = &cn4_power_init_data, +}; + +static struct platform_device cn4_power = { + .name = "reg-fixed-voltage", + .id = 2, + .dev = { + .platform_data = &cn4_power_info, + }, +}; + +static void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state) +{ + static int power_gpio = -EINVAL; + + if (power_gpio < 0) { + int ret = gpio_request(GPIO_PORT114, "sdhi1_power"); + if (!ret) { + power_gpio = GPIO_PORT114; + gpio_direction_output(power_gpio, 0); + } + } + + /* + * If requesting the GPIO above failed, it means, that the regulator got + * probed and grabbed the GPIO, but we don't know, whether the sdhi + * driver already uses the regulator. If it doesn't, we have to toggle + * the GPIO ourselves, even though it is now owned by the fixed + * regulator driver. We have to live with the race in case the driver + * gets unloaded and the GPIO freed between these two steps. + */ gpio_set_value(GPIO_PORT114, state); } @@ -455,6 +526,7 @@ static struct platform_device sdhi1_device = { }; static struct platform_device *ag5evm_devices[] __initdata = { + &cn4_power, ð_device, &keysc_device, &fsi_device, @@ -468,6 +540,12 @@ static struct platform_device *ag5evm_devices[] __initdata = { static void __init ag5evm_init(void) { + regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers, + ARRAY_SIZE(fixed1v8_power_consumers), 1800000); + regulator_register_always_on(1, "fixed-2.8V", fixed2v8_power_consumers, + ARRAY_SIZE(fixed2v8_power_consumers), 3300000); + regulator_register_fixed(3, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + sh73a0_pinmux_init(); /* enable SCIFA2 */ @@ -562,8 +640,6 @@ static void __init ag5evm_init(void) gpio_request(GPIO_FN_SDHID1_2_PU, NULL); gpio_request(GPIO_FN_SDHID1_1_PU, NULL); gpio_request(GPIO_FN_SDHID1_0_PU, NULL); - gpio_request(GPIO_PORT114, "sdhi1_power"); - gpio_direction_output(GPIO_PORT114, 0); #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index ace60246a5d..f172ca85905 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -34,6 +34,8 @@ #include <linux/i2c.h> #include <linux/i2c/tsc2007.h> #include <linux/io.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <linux/sh_intc.h> #include <linux/sh_clk.h> @@ -159,6 +161,27 @@ * CN12: 3.3v */ +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply fixed1v8_power_consumers[] = +{ + /* J22 default position: 1.8V */ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), +}; + +static struct regulator_consumer_supply fixed3v3_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), +}; + +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + /* MTD */ static struct mtd_partition nor_flash_partitions[] = { { @@ -1138,21 +1161,6 @@ static void __init fsi_init_pm_clock(void) clk_put(fsia_ick); } -/* - * FIXME !! - * - * gpio_no_direction - * are quick_hack. - * - * current gpio frame work doesn't have - * the method to control only pull up/down/free. - * this function should be replaced by correct gpio function - */ -static void __init gpio_no_direction(u32 addr) -{ - __raw_writeb(0x00, addr); -} - /* TouchScreen */ #ifdef CONFIG_AP4EVB_QHD # define GPIO_TSC_IRQ GPIO_FN_IRQ28_123 @@ -1224,6 +1232,12 @@ static void __init ap4evb_init(void) u32 srcr4; struct clk *clk; + regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers, + ARRAY_SIZE(fixed1v8_power_consumers), 1800000); + regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + /* External clock source */ clk_set_rate(&sh7372_dv_clki_clk, 27000000); @@ -1302,8 +1316,8 @@ static void __init ap4evb_init(void) gpio_request(GPIO_PORT9, NULL); gpio_request(GPIO_PORT10, NULL); - gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */ - gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */ + gpio_direction_none(GPIO_PORT9CR); /* FSIAOBT needs no direction */ + gpio_direction_none(GPIO_PORT10CR); /* FSIAOLR needs no direction */ /* card detect pin for MMC slot (CN7) */ gpio_request(GPIO_PORT41, NULL); @@ -1447,14 +1461,14 @@ static void __init ap4evb_init(void) platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices)); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc1_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); hdmi_init_pm_clock(); fsi_init_pm_clock(); diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 9bd135531d7..cf10f92856d 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -28,6 +28,8 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/sh_eth.h> #include <linux/videodev2.h> #include <linux/usb/renesas_usbhs.h> @@ -37,14 +39,20 @@ #include <linux/mmc/sh_mobile_sdhi.h> #include <mach/common.h> #include <mach/irqs.h> +#include <mach/r8a7740.h> +#include <media/mt9t112.h> +#include <media/sh_mobile_ceu.h> +#include <media/soc_camera.h> #include <asm/page.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> #include <asm/mach/time.h> #include <asm/hardware/cache-l2x0.h> -#include <mach/r8a7740.h> #include <video/sh_mobile_lcdc.h> +#include <video/sh_mobile_hdmi.h> +#include <sound/sh_fsi.h> +#include <sound/simple_card.h> /* * CON1 Camera Module @@ -108,6 +116,14 @@ */ /* + * FSI-WM8978 + * + * this command is required when playback. + * + * # amixer set "Headphone" 50 + */ + +/* * USB function * * When you use USB Function, @@ -117,14 +133,8 @@ * These are a little bit complex. * see * usbhsf_power_ctrl() - * - * CAUTION - * - * It uses autonomy mode for USB hotplug at this point - * (= usbhs_private.platform_callback.get_vbus is NULL), - * since we don't know what's happen on PM control - * on this workaround. */ +#define IRQ7 evt2irq(0x02e0) #define USBCR1 0xe605810a #define USBH 0xC6700000 #define USBH_USBCTR 0x10834 @@ -204,6 +214,20 @@ static void usbhsf_power_ctrl(struct platform_device *pdev, } } +static int usbhsf_get_vbus(struct platform_device *pdev) +{ + return gpio_get_value(GPIO_PORT209); +} + +static irqreturn_t usbhsf_interrupt(int irq, void *data) +{ + struct platform_device *pdev = data; + + renesas_usbhs_call_notify_hotplug(pdev); + + return IRQ_HANDLED; +} + static void usbhsf_hardware_exit(struct platform_device *pdev) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); @@ -227,11 +251,14 @@ static void usbhsf_hardware_exit(struct platform_device *pdev) priv->host = NULL; priv->func = NULL; priv->usbh_base = NULL; + + free_irq(IRQ7, pdev); } static int usbhsf_hardware_init(struct platform_device *pdev) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); + int ret; priv->phy = clk_get(&pdev->dev, "phy"); priv->usb24 = clk_get(&pdev->dev, "usb24"); @@ -251,6 +278,14 @@ static int usbhsf_hardware_init(struct platform_device *pdev) return -EIO; } + ret = request_irq(IRQ7, usbhsf_interrupt, IRQF_TRIGGER_NONE, + dev_name(&pdev->dev), pdev); + if (ret) { + dev_err(&pdev->dev, "request_irq err\n"); + return ret; + } + irq_set_irq_type(IRQ7, IRQ_TYPE_EDGE_BOTH); + /* usb24 use 1/1 of parent clock (= usb24s = 24MHz) */ clk_set_rate(priv->usb24, clk_get_rate(clk_get_parent(priv->usb24))); @@ -262,6 +297,7 @@ static struct usbhsf_private usbhsf_private = { .info = { .platform_callback = { .get_id = usbhsf_get_id, + .get_vbus = usbhsf_get_vbus, .hardware_init = usbhsf_hardware_init, .hardware_exit = usbhsf_hardware_exit, .power_ctrl = usbhsf_power_ctrl, @@ -269,6 +305,8 @@ static struct usbhsf_private usbhsf_private = { .driver_param = { .buswait_bwait = 5, .detection_delay = 5, + .d0_rx_id = SHDMA_SLAVE_USBHS_RX, + .d1_tx_id = SHDMA_SLAVE_USBHS_TX, }, } }; @@ -384,6 +422,103 @@ static struct platform_device lcdc0_device = { }, }; +/* + * LCDC1/HDMI + */ +static struct sh_mobile_hdmi_info hdmi_info = { + .flags = HDMI_OUTPUT_PUSH_PULL | + HDMI_OUTPUT_POLARITY_HI | + HDMI_32BIT_REG | + HDMI_HAS_HTOP1 | + HDMI_SND_SRC_SPDIF, +}; + +static struct resource hdmi_resources[] = { + [0] = { + .name = "HDMI", + .start = 0xe6be0000, + .end = 0xe6be03ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1700), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .name = "HDMI emma3pf", + .start = 0xe6be4000, + .end = 0xe6be43ff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device hdmi_device = { + .name = "sh-mobile-hdmi", + .num_resources = ARRAY_SIZE(hdmi_resources), + .resource = hdmi_resources, + .id = -1, + .dev = { + .platform_data = &hdmi_info, + }, +}; + +static const struct fb_videomode lcdc1_mode = { + .name = "HDMI 720p", + .xres = 1280, + .yres = 720, + .pixclock = 13468, + .left_margin = 220, + .right_margin = 110, + .hsync_len = 40, + .upper_margin = 20, + .lower_margin = 5, + .vsync_len = 5, + .refresh = 60, + .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, +}; + +static struct sh_mobile_lcdc_info hdmi_lcdc_info = { + .clock_source = LCDC_CLK_PERIPHERAL, /* HDMI clock */ + .ch[0] = { + .chan = LCDC_CHAN_MAINLCD, + .fourcc = V4L2_PIX_FMT_RGB565, + .interface_type = RGB24, + .clock_divider = 1, + .flags = LCDC_FLAGS_DWPOL, + .lcd_modes = &lcdc1_mode, + .num_modes = 1, + .tx_dev = &hdmi_device, + .panel_cfg = { + .width = 1280, + .height = 720, + }, + }, +}; + +static struct resource hdmi_lcdc_resources[] = { + [0] = { + .name = "LCDC1", + .start = 0xfe944000, + .end = 0xfe948000 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0x1780), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device hdmi_lcdc_device = { + .name = "sh_mobile_lcdc_fb", + .num_resources = ARRAY_SIZE(hdmi_lcdc_resources), + .resource = hdmi_lcdc_resources, + .id = 1, + .dev = { + .platform_data = &hdmi_lcdc_info, + .coherent_dma_mask = ~0, + }, +}; + /* GPIO KEY */ #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } @@ -407,6 +542,17 @@ static struct platform_device gpio_keys_device = { }, }; +/* Fixed 3.3V regulator to be used by SDHI0, SDHI1, MMCIF */ +static struct regulator_consumer_supply fixed3v3_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vmmc", "sh_mmcif"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif"), +}; + /* SDHI0 */ /* * FIXME @@ -418,6 +564,8 @@ static struct platform_device gpio_keys_device = { */ #define IRQ31 evt2irq(0x33E0) static struct sh_mobile_sdhi_info sdhi0_info = { + .dma_slave_tx = SHDMA_SLAVE_SDHI0_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI0_RX, .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |\ MMC_CAP_NEEDS_POLL, .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, @@ -458,6 +606,8 @@ static struct platform_device sdhi0_device = { /* SDHI1 */ static struct sh_mobile_sdhi_info sdhi1_info = { + .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, + .dma_slave_rx = SHDMA_SLAVE_SDHI1_RX, .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, .tmio_ocr_mask = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, @@ -532,12 +682,209 @@ static struct platform_device sh_mmcif_device = { .resource = sh_mmcif_resources, }; +/* Camera */ +static int mt9t111_power(struct device *dev, int mode) +{ + struct clk *mclk = clk_get(NULL, "video1"); + + if (IS_ERR(mclk)) { + dev_err(dev, "can't get video1 clock\n"); + return -EINVAL; + } + + if (mode) { + /* video1 (= CON1 camera) expect 24MHz */ + clk_set_rate(mclk, clk_round_rate(mclk, 24000000)); + clk_enable(mclk); + gpio_direction_output(GPIO_PORT158, 1); + } else { + gpio_direction_output(GPIO_PORT158, 0); + clk_disable(mclk); + } + + clk_put(mclk); + + return 0; +} + +static struct i2c_board_info i2c_camera_mt9t111 = { + I2C_BOARD_INFO("mt9t112", 0x3d), +}; + +static struct mt9t112_camera_info mt9t111_info = { + .divider = { 16, 0, 0, 7, 0, 10, 14, 7, 7 }, +}; + +static struct soc_camera_link mt9t111_link = { + .i2c_adapter_id = 0, + .bus_id = 0, + .board_info = &i2c_camera_mt9t111, + .power = mt9t111_power, + .priv = &mt9t111_info, +}; + +static struct platform_device camera_device = { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &mt9t111_link, + }, +}; + +/* CEU0 */ +static struct sh_mobile_ceu_info sh_mobile_ceu0_info = { + .flags = SH_CEU_FLAG_LOWER_8BIT, +}; + +static struct resource ceu0_resources[] = { + [0] = { + .name = "CEU", + .start = 0xfe910000, + .end = 0xfe91009f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0x0500), + .flags = IORESOURCE_IRQ, + }, + [2] = { + /* place holder for contiguous memory */ + }, +}; + +static struct platform_device ceu0_device = { + .name = "sh_mobile_ceu", + .id = 0, + .num_resources = ARRAY_SIZE(ceu0_resources), + .resource = ceu0_resources, + .dev = { + .platform_data = &sh_mobile_ceu0_info, + .coherent_dma_mask = 0xffffffff, + }, +}; + +/* FSI */ +static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable) +{ + struct clk *fsib; + int ret; + + /* it support 48KHz only */ + if (48000 != rate) + return -EINVAL; + + fsib = clk_get(dev, "ickb"); + if (IS_ERR(fsib)) + return -EINVAL; + + if (enable) { + ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64; + clk_enable(fsib); + } else { + ret = 0; + clk_disable(fsib); + } + + clk_put(fsib); + + return ret; +} + +static struct sh_fsi_platform_info fsi_info = { + /* FSI-WM8978 */ + .port_a = { + .tx_id = SHDMA_SLAVE_FSIA_TX, + }, + /* FSI-HDMI */ + .port_b = { + .flags = SH_FSI_FMT_SPDIF | + SH_FSI_ENABLE_STREAM_MODE, + .set_rate = fsi_hdmi_set_rate, + .tx_id = SHDMA_SLAVE_FSIB_TX, + } +}; + +static struct resource fsi_resources[] = { + [0] = { + .name = "FSI", + .start = 0xfe1f0000, + .end = 0xfe1f8400 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = evt2irq(0x1840), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device fsi_device = { + .name = "sh_fsi2", + .id = -1, + .num_resources = ARRAY_SIZE(fsi_resources), + .resource = fsi_resources, + .dev = { + .platform_data = &fsi_info, + }, +}; + +/* FSI-WM8978 */ +static struct asoc_simple_dai_init_info fsi_wm8978_init_info = { + .fmt = SND_SOC_DAIFMT_I2S, + .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_NB_NF, + .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, + .sysclk = 12288000, +}; + +static struct asoc_simple_card_info fsi_wm8978_info = { + .name = "wm8978", + .card = "FSI2A-WM8978", + .cpu_dai = "fsia-dai", + .codec = "wm8978.0-001a", + .platform = "sh_fsi2", + .codec_dai = "wm8978-hifi", + .init = &fsi_wm8978_init_info, +}; + +static struct platform_device fsi_wm8978_device = { + .name = "asoc-simple-card", + .id = 0, + .dev = { + .platform_data = &fsi_wm8978_info, + }, +}; + +/* FSI-HDMI */ +static struct asoc_simple_dai_init_info fsi2_hdmi_init_info = { + .cpu_daifmt = SND_SOC_DAIFMT_CBM_CFM, +}; + +static struct asoc_simple_card_info fsi2_hdmi_info = { + .name = "HDMI", + .card = "FSI2B-HDMI", + .cpu_dai = "fsib-dai", + .codec = "sh-mobile-hdmi", + .platform = "sh_fsi2", + .codec_dai = "sh_mobile_hdmi-hifi", + .init = &fsi2_hdmi_init_info, +}; + +static struct platform_device fsi_hdmi_device = { + .name = "asoc-simple-card", + .id = 1, + .dev = { + .platform_data = &fsi2_hdmi_info, + }, +}; + /* I2C */ static struct i2c_board_info i2c0_devices[] = { { I2C_BOARD_INFO("st1232-ts", 0x55), .irq = evt2irq(0x0340), }, + { + I2C_BOARD_INFO("wm8978", 0x1a), + }, }; /* @@ -549,6 +896,13 @@ static struct platform_device *eva_devices[] __initdata = { &sh_eth_device, &sdhi0_device, &sh_mmcif_device, + &hdmi_device, + &hdmi_lcdc_device, + &camera_device, + &ceu0_device, + &fsi_device, + &fsi_hdmi_device, + &fsi_wm8978_device, }; static void __init eva_clock_init(void) @@ -556,10 +910,14 @@ static void __init eva_clock_init(void) struct clk *system = clk_get(NULL, "system_clk"); struct clk *xtal1 = clk_get(NULL, "extal1"); struct clk *usb24s = clk_get(NULL, "usb24s"); + struct clk *fsibck = clk_get(NULL, "fsibck"); + struct clk *fsib = clk_get(&fsi_device.dev, "ickb"); if (IS_ERR(system) || IS_ERR(xtal1) || - IS_ERR(usb24s)) { + IS_ERR(usb24s) || + IS_ERR(fsibck) || + IS_ERR(fsib)) { pr_err("armadillo800eva board clock init failed\n"); goto clock_error; } @@ -570,6 +928,11 @@ static void __init eva_clock_init(void) /* usb24s use extal1 (= system) clock (= 24MHz) */ clk_set_parent(usb24s, system); + /* FSIBCK is 12.288MHz, and it is parent of FSI-B */ + clk_set_parent(fsib, fsibck); + clk_set_rate(fsibck, 12288000); + clk_set_rate(fsib, 12288000); + clock_error: if (!IS_ERR(system)) clk_put(system); @@ -577,16 +940,26 @@ clock_error: clk_put(xtal1); if (!IS_ERR(usb24s)) clk_put(usb24s); + if (!IS_ERR(fsibck)) + clk_put(fsibck); + if (!IS_ERR(fsib)) + clk_put(fsib); } /* * board init */ +#define GPIO_PORT7CR 0xe6050007 +#define GPIO_PORT8CR 0xe6050008 static void __init eva_init(void) { - eva_clock_init(); + struct platform_device *usb = NULL; + + regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); r8a7740_pinmux_init(); + r8a7740_meram_workaround(); /* SCIFA1 */ gpio_request(GPIO_FN_SCIFA1_RXD, NULL); @@ -667,8 +1040,19 @@ static void __init eva_init(void) /* USB Host */ } else { /* USB Func */ - gpio_request(GPIO_FN_VBUS, NULL); + /* + * A1 chip has 2 IRQ7 pin and it was controled by MSEL register. + * OTOH, usbhs interrupt needs its value (HI/LOW) to decide + * USB connection/disconnection (usbhsf_get_vbus()). + * This means we needs to select GPIO_FN_IRQ7_PORT209 first, + * and select GPIO_PORT209 here + */ + gpio_request(GPIO_FN_IRQ7_PORT209, NULL); + gpio_request(GPIO_PORT209, NULL); + gpio_direction_input(GPIO_PORT209); + platform_device_register(&usbhsf_device); + usb = &usbhsf_device; } /* SDHI0 */ @@ -706,6 +1090,48 @@ static void __init eva_init(void) gpio_request(GPIO_FN_MMC1_D6_PORT143, NULL); gpio_request(GPIO_FN_MMC1_D7_PORT142, NULL); + /* CEU0 */ + gpio_request(GPIO_FN_VIO0_D7, NULL); + gpio_request(GPIO_FN_VIO0_D6, NULL); + gpio_request(GPIO_FN_VIO0_D5, NULL); + gpio_request(GPIO_FN_VIO0_D4, NULL); + gpio_request(GPIO_FN_VIO0_D3, NULL); + gpio_request(GPIO_FN_VIO0_D2, NULL); + gpio_request(GPIO_FN_VIO0_D1, NULL); + gpio_request(GPIO_FN_VIO0_D0, NULL); + gpio_request(GPIO_FN_VIO0_CLK, NULL); + gpio_request(GPIO_FN_VIO0_HD, NULL); + gpio_request(GPIO_FN_VIO0_VD, NULL); + gpio_request(GPIO_FN_VIO0_FIELD, NULL); + gpio_request(GPIO_FN_VIO_CKO, NULL); + + /* CON1/CON15 Camera */ + gpio_request(GPIO_PORT173, NULL); /* STANDBY */ + gpio_request(GPIO_PORT172, NULL); /* RST */ + gpio_request(GPIO_PORT158, NULL); /* CAM_PON */ + gpio_direction_output(GPIO_PORT173, 0); + gpio_direction_output(GPIO_PORT172, 1); + gpio_direction_output(GPIO_PORT158, 0); /* see mt9t111_power() */ + + /* FSI-WM8978 */ + gpio_request(GPIO_FN_FSIAIBT, NULL); + gpio_request(GPIO_FN_FSIAILR, NULL); + gpio_request(GPIO_FN_FSIAOMC, NULL); + gpio_request(GPIO_FN_FSIAOSLD, NULL); + gpio_request(GPIO_FN_FSIAISLD_PORT5, NULL); + + gpio_request(GPIO_PORT7, NULL); + gpio_request(GPIO_PORT8, NULL); + gpio_direction_none(GPIO_PORT7CR); /* FSIAOBT needs no direction */ + gpio_direction_none(GPIO_PORT8CR); /* FSIAOLR needs no direction */ + + /* FSI-HDMI */ + gpio_request(GPIO_FN_FSIBCK, NULL); + + /* HDMI */ + gpio_request(GPIO_FN_HDMI_HPD, NULL); + gpio_request(GPIO_FN_HDMI_CEC, NULL); + /* * CAUTION * @@ -752,6 +1178,13 @@ static void __init eva_init(void) platform_add_devices(eva_devices, ARRAY_SIZE(eva_devices)); + + eva_clock_init(); + + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device); + rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device); + if (usb) + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb); } static void __init eva_earlytimer_init(void) diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c index e9b32cfbf74..4129008eae2 100644 --- a/arch/arm/mach-shmobile/board-bonito.c +++ b/arch/arm/mach-shmobile/board-bonito.c @@ -26,6 +26,8 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/gpio.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <linux/videodev2.h> #include <mach/common.h> @@ -75,6 +77,12 @@ * S38.2 = OFF */ +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + /* * FPGA */ @@ -360,6 +368,8 @@ static void __init bonito_init(void) { u16 val; + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + r8a7740_pinmux_init(); bonito_fpga_init(); diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c index f1257321999..fa5dfc5c8ed 100644 --- a/arch/arm/mach-shmobile/board-g4evm.c +++ b/arch/arm/mach-shmobile/board-g4evm.c @@ -26,6 +26,8 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/usb/r8a66597.h> #include <linux/io.h> #include <linux/input.h> @@ -196,6 +198,15 @@ static struct platform_device keysc_device = { }, }; +/* Fixed 3.3V regulator to be used by SDHI0 and SDHI1 */ +static struct regulator_consumer_supply fixed3v3_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), +}; + /* SDHI */ static struct sh_mobile_sdhi_info sdhi0_info = { .tmio_caps = MMC_CAP_SDIO_IRQ, @@ -271,26 +282,11 @@ static struct platform_device *g4evm_devices[] __initdata = { #define GPIO_SDHID1_D3 0xe6052106 #define GPIO_SDHICMD1 0xe6052107 -/* - * FIXME !! - * - * gpio_pull_up is quick_hack. - * - * current gpio frame work doesn't have - * the method to control only pull up/down/free. - * this function should be replaced by correct gpio function - */ -static void __init gpio_pull_up(u32 addr) -{ - u8 data = __raw_readb(addr); - - data &= 0x0F; - data |= 0xC0; - __raw_writeb(data, addr); -} - static void __init g4evm_init(void) { + regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + sh7377_pinmux_init(); /* Lit DS14 LED */ @@ -351,11 +347,11 @@ static void __init g4evm_init(void) gpio_request(GPIO_FN_SDHID0_3, NULL); gpio_request(GPIO_FN_SDHICMD0, NULL); gpio_request(GPIO_FN_SDHIWP0, NULL); - gpio_pull_up(GPIO_SDHID0_D0); - gpio_pull_up(GPIO_SDHID0_D1); - gpio_pull_up(GPIO_SDHID0_D2); - gpio_pull_up(GPIO_SDHID0_D3); - gpio_pull_up(GPIO_SDHICMD0); + gpio_request_pullup(GPIO_SDHID0_D0); + gpio_request_pullup(GPIO_SDHID0_D1); + gpio_request_pullup(GPIO_SDHID0_D2); + gpio_request_pullup(GPIO_SDHID0_D3); + gpio_request_pullup(GPIO_SDHICMD0); /* SDHI1 */ gpio_request(GPIO_FN_SDHICLK1, NULL); @@ -364,11 +360,11 @@ static void __init g4evm_init(void) gpio_request(GPIO_FN_SDHID1_2, NULL); gpio_request(GPIO_FN_SDHID1_3, NULL); gpio_request(GPIO_FN_SDHICMD1, NULL); - gpio_pull_up(GPIO_SDHID1_D0); - gpio_pull_up(GPIO_SDHID1_D1); - gpio_pull_up(GPIO_SDHID1_D2); - gpio_pull_up(GPIO_SDHID1_D3); - gpio_pull_up(GPIO_SDHICMD1); + gpio_request_pullup(GPIO_SDHID1_D0); + gpio_request_pullup(GPIO_SDHID1_D1); + gpio_request_pullup(GPIO_SDHID1_D2); + gpio_request_pullup(GPIO_SDHID1_D3); + gpio_request_pullup(GPIO_SDHICMD1); sh7377_add_standard_devices(); diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index f60f1b281cc..21dbe54304d 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -27,6 +27,8 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <linux/gpio.h> #include <linux/input.h> @@ -49,6 +51,12 @@ #include <asm/hardware/cache-l2x0.h> #include <asm/traps.h> +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + /* SMSC 9220 */ static struct resource smsc9220_resources[] = { [0] = { @@ -288,6 +296,13 @@ static struct platform_device leds_tpu30_device = { .resource = tpu30_resources, }; +/* Fixed 1.8V regulator to be used by MMCIF */ +static struct regulator_consumer_supply fixed1v8_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), +}; + /* MMCIF */ static struct resource mmcif_resources[] = { [0] = { @@ -321,6 +336,15 @@ static struct platform_device mmcif_device = { .resource = mmcif_resources, }; +/* Fixed 3.3V regulator to be used by SDHI0 and SDHI1 */ +static struct regulator_consumer_supply fixed3v3_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), +}; + /* SDHI0 */ static struct sh_mobile_sdhi_info sdhi0_info = { .tmio_caps = MMC_CAP_SD_HIGHSPEED, @@ -411,6 +435,12 @@ static struct platform_device *kota2_devices[] __initdata = { static void __init kota2_init(void) { + regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers, + ARRAY_SIZE(fixed1v8_power_consumers), 1800000); + regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + sh73a0_pinmux_init(); /* SCIFA2 (UART2) */ diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c index 6a33cf39342..2c986eaae7b 100644 --- a/arch/arm/mach-shmobile/board-kzm9d.c +++ b/arch/arm/mach-shmobile/board-kzm9d.c @@ -21,6 +21,8 @@ #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <mach/common.h> #include <mach/emev2.h> @@ -28,6 +30,12 @@ #include <asm/mach/arch.h> #include <asm/hardware/gic.h> +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + /* Ether */ static struct resource smsc911x_resources[] = { [0] = { @@ -63,6 +71,8 @@ static struct platform_device *kzm9d_devices[] __initdata = { void __init kzm9d_add_standard_devices(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + emev2_add_standard_devices(); platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices)); diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index c0ae815e7be..53b7ea92c32 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -30,9 +30,14 @@ #include <linux/mmc/sh_mobile_sdhi.h> #include <linux/mfd/tmio.h> #include <linux/platform_device.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <linux/usb/r8a66597.h> +#include <linux/usb/renesas_usbhs.h> #include <linux/videodev2.h> +#include <sound/sh_fsi.h> +#include <sound/simple_card.h> #include <mach/irqs.h> #include <mach/sh73a0.h> #include <mach/common.h> @@ -54,6 +59,20 @@ #define GPIO_PCF8575_PORT15 (GPIO_NR + 13) #define GPIO_PCF8575_PORT16 (GPIO_NR + 14) +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + +/* + * FSI-AK4648 + * + * this command is required when playback. + * + * # amixer set "LINEOUT Mixer DACL" on + */ + /* SMSC 9221 */ static struct resource smsc9221_resources[] = { [0] = { @@ -112,6 +131,151 @@ static struct platform_device usb_host_device = { .resource = usb_resources, }; +/* USB Func CN17 */ +struct usbhs_private { + unsigned int phy; + unsigned int cr2; + struct renesas_usbhs_platform_info info; +}; + +#define IRQ15 intcs_evt2irq(0x03e0) +#define USB_PHY_MODE (1 << 4) +#define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) +#define USB_PHY_ON (1 << 1) +#define USB_PHY_OFF (1 << 0) +#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF) + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info) + +static int usbhs_get_vbus(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + return !((1 << 7) & __raw_readw(priv->cr2)); +} + +static void usbhs_phy_reset(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* init phy */ + __raw_writew(0x8a0a, priv->cr2); +} + +static int usbhs_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static irqreturn_t usbhs_interrupt(int irq, void *data) +{ + struct platform_device *pdev = data; + struct usbhs_private *priv = usbhs_get_priv(pdev); + + renesas_usbhs_call_notify_hotplug(pdev); + + /* clear status */ + __raw_writew(__raw_readw(priv->phy) | USB_PHY_INT_CLR, priv->phy); + + return IRQ_HANDLED; +} + +static int usbhs_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + int ret; + + /* clear interrupt status */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy); + + ret = request_irq(IRQ15, usbhs_interrupt, IRQF_TRIGGER_HIGH, + dev_name(&pdev->dev), pdev); + if (ret) { + dev_err(&pdev->dev, "request_irq err\n"); + return ret; + } + + /* enable USB phy interrupt */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->phy); + + return 0; +} + +static void usbhs_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + /* clear interrupt status */ + __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy); + + free_irq(IRQ15, pdev); +} + +static u32 usbhs_pipe_cfg[] = { + USB_ENDPOINT_XFER_CONTROL, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, +}; + +static struct usbhs_private usbhs_private = { + .phy = 0xe60781e0, /* USBPHYINT */ + .cr2 = 0xe605810c, /* USBCR2 */ + .info = { + .platform_callback = { + .hardware_init = usbhs_hardware_init, + .hardware_exit = usbhs_hardware_exit, + .get_id = usbhs_get_id, + .phy_reset = usbhs_phy_reset, + .get_vbus = usbhs_get_vbus, + }, + .driver_param = { + .buswait_bwait = 4, + .has_otg = 1, + .pipe_type = usbhs_pipe_cfg, + .pipe_size = ARRAY_SIZE(usbhs_pipe_cfg), + }, + }, +}; + +static struct resource usbhs_resources[] = { + [0] = { + .start = 0xE6890000, + .end = 0xE68900e6 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(62), + .end = gic_spi(62), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usbhs_device = { + .name = "renesas_usbhs", + .id = -1, + .dev = { + .dma_mask = NULL, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbhs_private.info, + }, + .num_resources = ARRAY_SIZE(usbhs_resources), + .resource = usbhs_resources, +}; + /* LCDC */ static struct fb_videomode kzm_lcdc_mode = { .name = "WVGA Panel", @@ -166,6 +330,13 @@ static struct platform_device lcdc_device = { }, }; +/* Fixed 1.8V regulator to be used by MMCIF */ +static struct regulator_consumer_supply fixed1v8_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), +}; + /* MMCIF */ static struct resource sh_mmcif_resources[] = { [0] = { @@ -187,6 +358,8 @@ static struct resource sh_mmcif_resources[] = { static struct sh_mmcif_plat_data sh_mmcif_platdata = { .ocr = MMC_VDD_165_195, .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, + .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, + .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; static struct platform_device mmc_device = { @@ -200,6 +373,15 @@ static struct platform_device mmc_device = { .resource = sh_mmcif_resources, }; +/* Fixed 2.8V regulators to be used by SDHI0 and SDHI2 */ +static struct regulator_consumer_supply fixed2v8_power_consumers[] = +{ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.2"), +}; + /* SDHI */ static struct sh_mobile_sdhi_info sdhi0_info = { .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT, @@ -240,6 +422,50 @@ static struct platform_device sdhi0_device = { }, }; +/* Micro SD */ +static struct sh_mobile_sdhi_info sdhi2_info = { + .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | + TMIO_MMC_USE_GPIO_CD | + TMIO_MMC_WRPROTECT_DISABLE, + .tmio_caps = MMC_CAP_SD_HIGHSPEED, + .tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, + .cd_gpio = GPIO_PORT13, +}; + +static struct resource sdhi2_resources[] = { + [0] = { + .name = "SDHI2", + .start = 0xee140000, + .end = 0xee1400ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = SH_MOBILE_SDHI_IRQ_CARD_DETECT, + .start = gic_spi(103), + .flags = IORESOURCE_IRQ, + }, + [2] = { + .name = SH_MOBILE_SDHI_IRQ_SDCARD, + .start = gic_spi(104), + .flags = IORESOURCE_IRQ, + }, + [3] = { + .name = SH_MOBILE_SDHI_IRQ_SDIO, + .start = gic_spi(105), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi2_device = { + .name = "sh_mobile_sdhi", + .id = 2, + .num_resources = ARRAY_SIZE(sdhi2_resources), + .resource = sdhi2_resources, + .dev = { + .platform_data = &sdhi2_info, + }, +}; + /* KEY */ #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 } @@ -267,11 +493,74 @@ static struct platform_device gpio_keys_device = { }, }; +/* FSI-AK4648 */ +static struct sh_fsi_platform_info fsi_info = { + .port_a = { + .tx_id = SHDMA_SLAVE_FSI2A_TX, + }, +}; + +static struct resource fsi_resources[] = { + [0] = { + .name = "FSI", + .start = 0xEC230000, + .end = 0xEC230400 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(146), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device fsi_device = { + .name = "sh_fsi2", + .id = -1, + .num_resources = ARRAY_SIZE(fsi_resources), + .resource = fsi_resources, + .dev = { + .platform_data = &fsi_info, + }, +}; + +static struct asoc_simple_dai_init_info fsi2_ak4648_init_info = { + .fmt = SND_SOC_DAIFMT_LEFT_J, + .codec_daifmt = SND_SOC_DAIFMT_CBM_CFM, + .cpu_daifmt = SND_SOC_DAIFMT_CBS_CFS, + .sysclk = 11289600, +}; + +static struct asoc_simple_card_info fsi2_ak4648_info = { + .name = "AK4648", + .card = "FSI2A-AK4648", + .cpu_dai = "fsia-dai", + .codec = "ak4642-codec.0-0012", + .platform = "sh_fsi2", + .codec_dai = "ak4642-hifi", + .init = &fsi2_ak4648_init_info, +}; + +static struct platform_device fsi_ak4648_device = { + .name = "asoc-simple-card", + .dev = { + .platform_data = &fsi2_ak4648_info, + }, +}; + /* I2C */ static struct pcf857x_platform_data pcf8575_pdata = { .gpio_base = GPIO_PCF8575_BASE, }; +static struct i2c_board_info i2c0_devices[] = { + { + I2C_BOARD_INFO("ak4648", 0x12), + }, + { + I2C_BOARD_INFO("r2025sd", 0x32), + } +}; + static struct i2c_board_info i2c1_devices[] = { { I2C_BOARD_INFO("st1232-ts", 0x55), @@ -289,10 +578,14 @@ static struct i2c_board_info i2c3_devices[] = { static struct platform_device *kzm_devices[] __initdata = { &smsc_device, &usb_host_device, + &usbhs_device, &lcdc_device, &mmc_device, &sdhi0_device, + &sdhi2_device, &gpio_keys_device, + &fsi_device, + &fsi_ak4648_device, }; /* @@ -350,6 +643,12 @@ device_initcall(as3711_enable_lcdc_backlight); static void __init kzm_init(void) { + regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers, + ARRAY_SIZE(fixed1v8_power_consumers), 1800000); + regulator_register_always_on(1, "fixed-2.8V", fixed2v8_power_consumers, + ARRAY_SIZE(fixed2v8_power_consumers), 2800000); + regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + sh73a0_pinmux_init(); /* enable SCIFA4 */ @@ -427,15 +726,36 @@ static void __init kzm_init(void) gpio_request(GPIO_PORT15, NULL); gpio_direction_output(GPIO_PORT15, 1); /* power */ + /* enable Micro SD */ + gpio_request(GPIO_FN_SDHID2_0, NULL); + gpio_request(GPIO_FN_SDHID2_1, NULL); + gpio_request(GPIO_FN_SDHID2_2, NULL); + gpio_request(GPIO_FN_SDHID2_3, NULL); + gpio_request(GPIO_FN_SDHICMD2, NULL); + gpio_request(GPIO_FN_SDHICLK2, NULL); + gpio_request(GPIO_PORT14, NULL); + gpio_direction_output(GPIO_PORT14, 1); /* power */ + /* I2C 3 */ gpio_request(GPIO_FN_PORT27_I2C_SCL3, NULL); gpio_request(GPIO_FN_PORT28_I2C_SDA3, NULL); + /* enable FSI2 port A (ak4648) */ + gpio_request(GPIO_FN_FSIACK, NULL); + gpio_request(GPIO_FN_FSIAILR, NULL); + gpio_request(GPIO_FN_FSIAIBT, NULL); + gpio_request(GPIO_FN_FSIAISLD, NULL); + gpio_request(GPIO_FN_FSIAOSLD, NULL); + + /* enable USB */ + gpio_request(GPIO_FN_VBUS_0, NULL); + #ifdef CONFIG_CACHE_L2X0 /* Early BRESP enable, Shared attribute override enable, 64K*8way */ l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff); #endif + i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); i2c_register_board_info(3, i2c3_devices, ARRAY_SIZE(i2c3_devices)); diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 150122a4463..7ea2b31e319 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -41,6 +41,8 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/sh_flctl.h> #include <linux/pm_clock.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <linux/sh_intc.h> #include <linux/tca6416_keypad.h> @@ -203,31 +205,32 @@ * amixer set "HPOUTR Mixer DACH" on */ -/* - * FIXME !! - * - * gpio_no_direction - * gpio_pull_down - * are quick_hack. - * - * current gpio frame work doesn't have - * the method to control only pull up/down/free. - * this function should be replaced by correct gpio function - */ -static void __init gpio_no_direction(u32 addr) +/* Fixed 3.3V and 1.8V regulators to be used by multiple devices */ +static struct regulator_consumer_supply fixed1v8_power_consumers[] = { - __raw_writeb(0x00, addr); -} + /* + * J22 on mackerel switches mmcif.0 and sdhi.1 between 1.8V and 3.3V + * Since we cannot support both voltages, we support the default 1.8V + */ + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"), + REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"), +}; -static void __init gpio_pull_down(u32 addr) +static struct regulator_consumer_supply fixed3v3_power_consumers[] = { - u8 data = __raw_readb(addr); - - data &= 0x0F; - data |= 0xA0; + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"), + REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"), + REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.2"), +}; - __raw_writeb(data, addr); -} +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; /* MTD */ static struct mtd_partition nor_flash_partitions[] = { @@ -1409,6 +1412,12 @@ static void __init mackerel_init(void) u32 srcr4; struct clk *clk; + regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers, + ARRAY_SIZE(fixed1v8_power_consumers), 1800000); + regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers, + ARRAY_SIZE(fixed3v3_power_consumers), 3300000); + regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + /* External clock source */ clk_set_rate(&sh7372_dv_clki_clk, 27000000); @@ -1458,11 +1467,11 @@ static void __init mackerel_init(void) /* USBHS0 */ gpio_request(GPIO_FN_VBUS0_0, NULL); - gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */ + gpio_request_pulldown(GPIO_PORT168CR); /* VBUS0_0 pull down */ /* USBHS1 */ gpio_request(GPIO_FN_VBUS0_1, NULL); - gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ + gpio_request_pulldown(GPIO_PORT167CR); /* VBUS0_1 pull down */ gpio_request(GPIO_FN_IDIN_1_113, NULL); /* enable FSI2 port A (ak4643) */ @@ -1475,8 +1484,8 @@ static void __init mackerel_init(void) gpio_request(GPIO_PORT9, NULL); gpio_request(GPIO_PORT10, NULL); - gpio_no_direction(GPIO_PORT9CR); /* FSIAOBT needs no direction */ - gpio_no_direction(GPIO_PORT10CR); /* FSIAOLR needs no direction */ + gpio_direction_none(GPIO_PORT9CR); /* FSIAOBT needs no direction */ + gpio_direction_none(GPIO_PORT10CR); /* FSIAOLR needs no direction */ intc_set_priority(IRQ_FSI, 3); /* irq priority FSI(3) > SMSC911X(2) */ @@ -1614,20 +1623,20 @@ static void __init mackerel_init(void) platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); - sh7372_add_device_to_domain(&sh7372_a4lc, &lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &hdmi_lcdc_device); - sh7372_add_device_to_domain(&sh7372_a4lc, &meram_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &fsi_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usbhs1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &nand_flash_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sh_mmcif_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device); + rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device); #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device); #endif - sh7372_add_device_to_domain(&sh7372_a3sp, &sdhi2_device); - sh7372_add_device_to_domain(&sh7372_a4r, &ceu_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device); hdmi_init_pm_clock(); sh7372_pm_init(); diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c index 14de3787caf..3a528cf4366 100644 --- a/arch/arm/mach-shmobile/board-marzen.c +++ b/arch/arm/mach-shmobile/board-marzen.c @@ -27,6 +27,8 @@ #include <linux/io.h> #include <linux/gpio.h> #include <linux/dma-mapping.h> +#include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #include <linux/smsc911x.h> #include <mach/hardware.h> #include <mach/r8a7779.h> @@ -37,6 +39,12 @@ #include <asm/hardware/gic.h> #include <asm/traps.h> +/* Dummy supplies, where voltage doesn't matter */ +static struct regulator_consumer_supply dummy_supplies[] = { + REGULATOR_SUPPLY("vddvario", "smsc911x"), + REGULATOR_SUPPLY("vdd33a", "smsc911x"), +}; + /* SMSC LAN89218 */ static struct resource smsc911x_resources[] = { [0] = { @@ -73,6 +81,8 @@ static struct platform_device *marzen_devices[] __initdata = { static void __init marzen_init(void) { + regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies)); + r8a7779_pinmux_init(); /* SCIF2 (CN18: DEBUG0) */ diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c index 26eea5f2105..ad5fccc7b5e 100644 --- a/arch/arm/mach-shmobile/clock-r8a7740.c +++ b/arch/arm/mach-shmobile/clock-r8a7740.c @@ -43,7 +43,10 @@ /* CPG registers */ #define FRQCRA 0xe6150000 #define FRQCRB 0xe6150004 +#define VCLKCR1 0xE6150008 +#define VCLKCR2 0xE615000c #define FRQCRC 0xe61500e0 +#define FSIACKCR 0xe6150018 #define PLLC01CR 0xe6150028 #define SUBCKCR 0xe6150080 @@ -54,6 +57,8 @@ #define MSTPSR2 0xe6150040 #define MSTPSR3 0xe6150048 #define MSTPSR4 0xe615004c +#define FSIBCKCR 0xe6150090 +#define HDMICKCR 0xe6150094 #define SMSTPCR0 0xe6150130 #define SMSTPCR1 0xe6150134 #define SMSTPCR2 0xe6150138 @@ -271,6 +276,13 @@ static struct clk usb24_clk = { .parent = &usb24s_clk, }; +/* External FSIACK/FSIBCK clock */ +static struct clk fsiack_clk = { +}; + +static struct clk fsibck_clk = { +}; + struct clk *main_clks[] = { &extalr_clk, &extal1_clk, @@ -288,6 +300,8 @@ struct clk *main_clks[] = { &pllc1_div2_clk, &usb24s_clk, &usb24_clk, + &fsiack_clk, + &fsibck_clk, }; static void div4_kick(struct clk *clk) @@ -313,6 +327,107 @@ static struct clk_div4_table div4_table = { .kick = div4_kick, }; +/* DIV6 reparent */ +enum { + DIV6_HDMI, + DIV6_VCLK1, DIV6_VCLK2, + DIV6_FSIA, DIV6_FSIB, + DIV6_REPARENT_NR, +}; + +static struct clk *hdmi_parent[] = { + [0] = &pllc1_div2_clk, + [1] = &system_clk, + [2] = &dv_clk +}; + +static struct clk *vclk_parents[8] = { + [0] = &pllc1_div2_clk, + [2] = &dv_clk, + [3] = &usb24s_clk, + [4] = &extal1_div2_clk, + [5] = &extalr_clk, +}; + +static struct clk *fsia_parents[] = { + [0] = &pllc1_div2_clk, + [1] = &fsiack_clk, /* external clock */ +}; + +static struct clk *fsib_parents[] = { + [0] = &pllc1_div2_clk, + [1] = &fsibck_clk, /* external clock */ +}; + +static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { + [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, + hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), + [DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0, + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + [DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0, + vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3), + [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, + fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2), + [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, + fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2), +}; + +/* HDMI1/2 clock */ +static unsigned long hdmi12_recalc(struct clk *clk) +{ + u32 val = __raw_readl(HDMICKCR); + int shift = (int)clk->priv; + + val >>= shift; + val &= 0x3; + + return clk->parent->rate / (1 << val); +}; + +static int hdmi12_set_rate(struct clk *clk, unsigned long rate) +{ + u32 val, mask; + int i, shift; + + for (i = 0; i < 3; i++) + if (rate == clk->parent->rate / (1 << i)) + goto find; + return -ENODEV; + +find: + shift = (int)clk->priv; + + val = __raw_readl(HDMICKCR); + mask = ~(0x3 << shift); + val = (val & mask) | i << shift; + __raw_writel(val, HDMICKCR); + + return 0; +}; + +static struct sh_clk_ops hdmi12_clk_ops = { + .recalc = hdmi12_recalc, + .set_rate = hdmi12_set_rate, +}; + +static struct clk hdmi1_clk = { + .ops = &hdmi12_clk_ops, + .priv = (void *)9, + .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ +}; + +static struct clk hdmi2_clk = { + .ops = &hdmi12_clk_ops, + .priv = (void *)11, + .parent = &div6_reparent_clks[DIV6_HDMI], /* late install */ +}; + +static struct clk *late_main_clks[] = { + &hdmi1_clk, + &hdmi2_clk, +}; + +/* MSTP */ enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP, DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP, @@ -343,11 +458,12 @@ static struct clk div6_clks[DIV6_NR] = { }; enum { - MSTP125, + MSTP128, MSTP127, MSTP125, MSTP116, MSTP111, MSTP100, MSTP117, MSTP230, MSTP222, + MSTP218, MSTP217, MSTP216, MSTP214, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, MSTP329, MSTP328, MSTP323, MSTP320, @@ -360,6 +476,8 @@ enum { }; static struct clk mstp_clks[MSTP_NR] = { + [MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 28, 0), /* CEU21 */ + [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S], SMSTPCR1, 27, 0), /* CEU20 */ [MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ [MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ [MSTP116] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ @@ -368,6 +486,10 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 30, 0), /* SCIFA6 */ [MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 22, 0), /* SCIFA7 */ + [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */ + [MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */ + [MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */ + [MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */ [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ @@ -408,6 +530,12 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("pllc1_clk", &pllc1_clk), CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk), CLKDEV_CON_ID("usb24s", &usb24s_clk), + CLKDEV_CON_ID("hdmi1", &hdmi1_clk), + CLKDEV_CON_ID("hdmi2", &hdmi2_clk), + CLKDEV_CON_ID("video1", &div6_reparent_clks[DIV6_VCLK1]), + CLKDEV_CON_ID("video2", &div6_reparent_clks[DIV6_VCLK2]), + CLKDEV_CON_ID("fsiack", &fsiack_clk), + CLKDEV_CON_ID("fsibck", &fsibck_clk), /* DIV4 clocks */ CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]), @@ -430,6 +558,8 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), + CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]), CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), @@ -438,7 +568,10 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), - + CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), + CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), + CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]), CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]), @@ -459,6 +592,10 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]), CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]), CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk), + CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), + + CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]), + CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]), }; void __init r8a7740_clock_init(u8 md_ck) @@ -495,7 +632,14 @@ void __init r8a7740_clock_init(u8 md_ck) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_div6_reparent_register(div6_reparent_clks, + DIV6_REPARENT_NR); + + if (!ret) + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); + + for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) + ret = clk_register(late_main_clks[k]); clkdev_add_table(lookups, ARRAY_SIZE(lookups)); diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 7d6e9fe47b5..339c62c824d 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -162,7 +162,7 @@ void __init r8a7779_clock_init(void) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) ret = clk_register(late_main_clks[k]); diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c index 006e7b5d304..162b791b898 100644 --- a/arch/arm/mach-shmobile/clock-sh7367.c +++ b/arch/arm/mach-shmobile/clock-sh7367.c @@ -344,7 +344,7 @@ void __init sh7367_clock_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); clkdev_add_table(lookups, ARRAY_SIZE(lookups)); diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 94d1f88246d..5a2894b1c96 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -704,7 +704,7 @@ void __init sh7372_clock_init(void) ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) ret = clk_register(late_main_clks[k]); diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c index 0798a15936c..85f2a3ec2c4 100644 --- a/arch/arm/mach-shmobile/clock-sh7377.c +++ b/arch/arm/mach-shmobile/clock-sh7377.c @@ -355,7 +355,7 @@ void __init sh7377_clock_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); clkdev_add_table(lookups, ARRAY_SIZE(lookups)); diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 3946c4ba2aa..7f8da18a858 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -475,9 +475,9 @@ static struct clk *late_main_clks[] = { enum { MSTP001, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, - MSTP219, MSTP218, + MSTP219, MSTP218, MSTP217, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP331, MSTP329, MSTP325, MSTP323, + MSTP331, MSTP329, MSTP328, MSTP325, MSTP323, MSTP322, MSTP314, MSTP313, MSTP312, MSTP311, MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, @@ -498,6 +498,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */ [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* SY-DMAC */ + [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* MP-DMAC */ [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */ @@ -507,8 +508,10 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */ [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ + [MSTP328] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /*FSI*/ [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ + [MSTP322] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 22, 0), /* USB */ [MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */ [MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ @@ -553,6 +556,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */ + CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* MP-DMAC */ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */ @@ -562,8 +566,10 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ + CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ + CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ @@ -612,7 +618,7 @@ void __init sh73a0_clock_init(void) ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); + ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++) ret = clk_register(late_main_clks[k]); diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 01e2bc014f1..45e61dada03 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -77,6 +77,7 @@ extern void r8a7779_add_standard_devices(void); extern void r8a7779_clock_init(void); extern void r8a7779_pinmux_init(void); extern void r8a7779_pm_init(void); +extern void r8a7740_meram_workaround(void); extern unsigned int r8a7779_get_core_count(void); extern int r8a7779_platform_cpu_kill(unsigned int cpu); diff --git a/arch/arm/mach-shmobile/include/mach/dma-register.h b/arch/arm/mach-shmobile/include/mach/dma-register.h new file mode 100644 index 00000000000..97c40bd9b94 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/dma-register.h @@ -0,0 +1,84 @@ +/* + * SH-ARM CPU-specific DMA definitions, used by both DMA drivers + * + * Copyright (C) 2012 Renesas Solutions Corp + * + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * Based on arch/sh/include/cpu-sh4/cpu/dma-register.h + * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * + * 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 DMA_REGISTER_H +#define DMA_REGISTER_H + +/* + * Direct Memory Access Controller + */ + +/* Transmit sizes and respective CHCR register values */ +enum { + XMIT_SZ_8BIT = 0, + XMIT_SZ_16BIT = 1, + XMIT_SZ_32BIT = 2, + XMIT_SZ_64BIT = 7, + XMIT_SZ_128BIT = 3, + XMIT_SZ_256BIT = 4, + XMIT_SZ_512BIT = 5, +}; + +/* log2(size / 8) - used to calculate number of transfers */ +static const unsigned int dma_ts_shift[] = { + [XMIT_SZ_8BIT] = 0, + [XMIT_SZ_16BIT] = 1, + [XMIT_SZ_32BIT] = 2, + [XMIT_SZ_64BIT] = 3, + [XMIT_SZ_128BIT] = 4, + [XMIT_SZ_256BIT] = 5, + [XMIT_SZ_512BIT] = 6, +}; + +#define TS_LOW_BIT 0x3 /* --xx */ +#define TS_HI_BIT 0xc /* xx-- */ + +#define TS_LOW_SHIFT (3) +#define TS_HI_SHIFT (20 - 2) /* 2 bits for shifted low TS */ + +#define TS_INDEX2VAL(i) \ + ((((i) & TS_LOW_BIT) << TS_LOW_SHIFT) |\ + (((i) & TS_HI_BIT) << TS_HI_SHIFT)) + +#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) +#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) + + +/* + * USB High-Speed DMAC + */ +/* Transmit sizes and respective CHCR register values */ +enum { + USBTS_XMIT_SZ_8BYTE = 0, + USBTS_XMIT_SZ_16BYTE = 1, + USBTS_XMIT_SZ_32BYTE = 2, +}; + +/* log2(size / 8) - used to calculate number of transfers */ +static const unsigned int dma_usbts_shift[] = { + [USBTS_XMIT_SZ_8BYTE] = 3, + [USBTS_XMIT_SZ_16BYTE] = 4, + [USBTS_XMIT_SZ_32BYTE] = 5, +}; + +#define USBTS_LOW_BIT 0x3 /* --xx */ +#define USBTS_HI_BIT 0x0 /* ---- */ + +#define USBTS_LOW_SHIFT 6 +#define USBTS_HI_SHIFT 0 + +#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) + +#endif /* DMA_REGISTER_H */ diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h index de795b42232..844507d937c 100644 --- a/arch/arm/mach-shmobile/include/mach/gpio.h +++ b/arch/arm/mach-shmobile/include/mach/gpio.h @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/sh_pfc.h> +#include <linux/io.h> #ifdef CONFIG_GPIOLIB @@ -27,4 +28,35 @@ static inline int irq_to_gpio(unsigned int irq) #endif /* CONFIG_GPIOLIB */ +/* + * FIXME !! + * + * current gpio frame work doesn't have + * the method to control only pull up/down/free. + * this function should be replaced by correct gpio function + */ +static inline void __init gpio_direction_none(u32 addr) +{ + __raw_writeb(0x00, addr); +} + +static inline void __init gpio_request_pullup(u32 addr) +{ + u8 data = __raw_readb(addr); + + data &= 0x0F; + data |= 0xC0; + __raw_writeb(data, addr); +} + +static inline void __init gpio_request_pulldown(u32 addr) +{ + u8 data = __raw_readb(addr); + + data &= 0x0F; + data |= 0xA0; + + __raw_writeb(data, addr); +} + #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h new file mode 100644 index 00000000000..5a402840fe2 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Renesas Solutions Corp. + * + * Kuninori Morimoto <morimoto.kuninori@renesas.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef PM_RMOBILE_H +#define PM_RMOBILE_H + +#include <linux/pm_domain.h> + +struct platform_device; + +struct rmobile_pm_domain { + struct generic_pm_domain genpd; + struct dev_power_governor *gov; + int (*suspend)(void); + void (*resume)(void); + unsigned int bit_shift; + bool no_debug; +}; + +static inline +struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d) +{ + return container_of(d, struct rmobile_pm_domain, genpd); +} + +#ifdef CONFIG_PM +extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd); +extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, + struct platform_device *pdev); +extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, + struct rmobile_pm_domain *rmobile_sd); +#else +#define rmobile_init_pm_domain(pd) do { } while (0) +#define rmobile_add_device_to_domain(pd, pdev) do { } while (0) +#define rmobile_pm_add_subdomain(pd, sd) do { } while (0) +#endif /* CONFIG_PM */ + +#endif /* PM_RMOBILE_H */ diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h index 9d447abb969..7143147780d 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7740.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h @@ -19,6 +19,8 @@ #ifndef __ASM_R8A7740_H__ #define __ASM_R8A7740_H__ +#include <mach/pm-rmobile.h> + /* * MD_CKx pin */ @@ -139,7 +141,7 @@ enum { GPIO_FN_DBGMD10, GPIO_FN_DBGMD11, GPIO_FN_DBGMD20, GPIO_FN_DBGMD21, - /* FSI */ + /* FSI-A */ GPIO_FN_FSIAISLD_PORT0, /* FSIAISLD Port 0/5 */ GPIO_FN_FSIAISLD_PORT5, GPIO_FN_FSIASPDIF_PORT9, /* FSIASPDIF Port 9/18 */ @@ -150,6 +152,9 @@ enum { GPIO_FN_FSIACK, GPIO_FN_FSIAILR, GPIO_FN_FSIAIBT, + /* FSI-B */ + GPIO_FN_FSIBCK, + /* FMSI */ GPIO_FN_FMSISLD_PORT1, /* FMSISLD Port 1/6 */ GPIO_FN_FMSISLD_PORT6, @@ -565,6 +570,10 @@ enum { GPIO_FN_RESETP_PULLUP, GPIO_FN_RESETP_PLAIN, + /* HDMI */ + GPIO_FN_HDMI_HPD, + GPIO_FN_HDMI_CEC, + /* SDENC */ GPIO_FN_SDENC_CPG, GPIO_FN_SDENC_DV_CLKI, @@ -581,4 +590,26 @@ enum { GPIO_FN_TRACEAUD_FROM_MEMC, }; +/* DMA slave IDs */ +enum { + SHDMA_SLAVE_INVALID, + SHDMA_SLAVE_SDHI0_RX, + SHDMA_SLAVE_SDHI0_TX, + SHDMA_SLAVE_SDHI1_RX, + SHDMA_SLAVE_SDHI1_TX, + SHDMA_SLAVE_SDHI2_RX, + SHDMA_SLAVE_SDHI2_TX, + SHDMA_SLAVE_FSIA_RX, + SHDMA_SLAVE_FSIA_TX, + SHDMA_SLAVE_FSIB_TX, + SHDMA_SLAVE_USBHS_TX, + SHDMA_SLAVE_USBHS_RX, +}; + +#ifdef CONFIG_PM +extern struct rmobile_pm_domain r8a7740_pd_a4s; +extern struct rmobile_pm_domain r8a7740_pd_a3sp; +extern struct rmobile_pm_domain r8a7740_pd_a4lc; +#endif /* CONFIG_PM */ + #endif /* __ASM_R8A7740_H__ */ diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h index 915d0093da0..b59048e6d8f 100644 --- a/arch/arm/mach-shmobile/include/mach/sh7372.h +++ b/arch/arm/mach-shmobile/include/mach/sh7372.h @@ -13,6 +13,7 @@ #include <linux/sh_clk.h> #include <linux/pm_domain.h> +#include <mach/pm-rmobile.h> /* * Pin Function Controller: @@ -477,42 +478,16 @@ extern struct clk sh7372_fsibck_clk; extern struct clk sh7372_fsidiva_clk; extern struct clk sh7372_fsidivb_clk; -struct platform_device; - -struct sh7372_pm_domain { - struct generic_pm_domain genpd; - struct dev_power_governor *gov; - int (*suspend)(void); - void (*resume)(void); - unsigned int bit_shift; - bool no_debug; -}; - -static inline struct sh7372_pm_domain *to_sh7372_pd(struct generic_pm_domain *d) -{ - return container_of(d, struct sh7372_pm_domain, genpd); -} - #ifdef CONFIG_PM -extern struct sh7372_pm_domain sh7372_a4lc; -extern struct sh7372_pm_domain sh7372_a4mp; -extern struct sh7372_pm_domain sh7372_d4; -extern struct sh7372_pm_domain sh7372_a4r; -extern struct sh7372_pm_domain sh7372_a3rv; -extern struct sh7372_pm_domain sh7372_a3ri; -extern struct sh7372_pm_domain sh7372_a4s; -extern struct sh7372_pm_domain sh7372_a3sp; -extern struct sh7372_pm_domain sh7372_a3sg; - -extern void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd); -extern void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, - struct platform_device *pdev); -extern void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, - struct sh7372_pm_domain *sh7372_sd); -#else -#define sh7372_init_pm_domain(pd) do { } while(0) -#define sh7372_add_device_to_domain(pd, pdev) do { } while(0) -#define sh7372_pm_add_subdomain(pd, sd) do { } while(0) +extern struct rmobile_pm_domain sh7372_pd_a4lc; +extern struct rmobile_pm_domain sh7372_pd_a4mp; +extern struct rmobile_pm_domain sh7372_pd_d4; +extern struct rmobile_pm_domain sh7372_pd_a4r; +extern struct rmobile_pm_domain sh7372_pd_a3rv; +extern struct rmobile_pm_domain sh7372_pd_a3ri; +extern struct rmobile_pm_domain sh7372_pd_a4s; +extern struct rmobile_pm_domain sh7372_pd_a3sp; +extern struct rmobile_pm_domain sh7372_pd_a3sg; #endif /* CONFIG_PM */ extern void sh7372_intcs_suspend(void); diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index 398e2c10913..fe950f25d79 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h @@ -516,6 +516,13 @@ enum { SHDMA_SLAVE_SDHI2_RX, SHDMA_SLAVE_MMCIF_TX, SHDMA_SLAVE_MMCIF_RX, + SHDMA_SLAVE_FSI2A_TX, + SHDMA_SLAVE_FSI2A_RX, + SHDMA_SLAVE_FSI2B_TX, + SHDMA_SLAVE_FSI2B_RX, + SHDMA_SLAVE_FSI2C_TX, + SHDMA_SLAVE_FSI2C_RX, + SHDMA_SLAVE_FSI2D_RX, }; /* diff --git a/arch/arm/mach-shmobile/intc-r8a7740.c b/arch/arm/mach-shmobile/intc-r8a7740.c index 09c42afcb22..9a69a31918b 100644 --- a/arch/arm/mach-shmobile/intc-r8a7740.c +++ b/arch/arm/mach-shmobile/intc-r8a7740.c @@ -71,10 +71,12 @@ enum { DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3, DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, + HDMI, USBH_INT, USBH_OHCI, USBH_EHCI, USBH_PME, USBH_BIND, RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, SPU2_0, SPU2_1, FSI, FMSI, + HDMI_SSS, HDMI_KEY, IPMMU, AP_ARM_CTIIRQ, AP_ARM_PMURQ, MFIS2, @@ -182,6 +184,7 @@ static struct intc_vect intca_vectors[] __initdata = { INTC_VECT(USBH_EHCI, 0x1580), INTC_VECT(USBH_PME, 0x15A0), INTC_VECT(USBH_BIND, 0x15C0), + INTC_VECT(HDMI, 0x1700), INTC_VECT(RSPI_OVRF, 0x1780), INTC_VECT(RSPI_SPTEF, 0x17A0), INTC_VECT(RSPI_SPRF, 0x17C0), @@ -189,6 +192,8 @@ static struct intc_vect intca_vectors[] __initdata = { INTC_VECT(SPU2_1, 0x1820), INTC_VECT(FSI, 0x1840), INTC_VECT(FMSI, 0x1860), + INTC_VECT(HDMI_SSS, 0x18A0), + INTC_VECT(HDMI_KEY, 0x18C0), INTC_VECT(IPMMU, 0x1920), INTC_VECT(AP_ARM_CTIIRQ, 0x1980), INTC_VECT(AP_ARM_PMURQ, 0x19A0), @@ -304,11 +309,11 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { USBH_EHCI, USBH_PME, USBH_BIND, 0 } }, /* IMR3A3 / IMCR3A3 */ { /* IMR4A3 / IMCR4A3 */ 0xe6950090, 0xe69500d0, 8, - { 0, 0, 0, 0, + { HDMI, 0, 0, 0, RSPI_OVRF, RSPI_SPTEF, RSPI_SPRF, 0 } }, { /* IMR5A3 / IMCR5A3 */ 0xe6950094, 0xe69500d4, 8, { SPU2_0, SPU2_1, FSI, FMSI, - 0, 0, 0, 0 } }, + 0, HDMI_SSS, HDMI_KEY, 0 } }, { /* IMR6A3 / IMCR6A3 */ 0xe6950098, 0xe69500d8, 8, { 0, IPMMU, 0, 0, AP_ARM_CTIIRQ, AP_ARM_PMURQ, 0, 0 } }, @@ -353,10 +358,10 @@ static struct intc_prio_reg intca_prio_registers[] __initdata = { { 0xe6950014, 0, 16, 4, /* IPRFA3 */ { USBH2, 0, 0, 0 } }, /* IPRGA3 */ /* IPRHA3 */ - /* IPRIA3 */ + { 0xe6950020, 0, 16, 4, /* IPRIA3 */ { HDMI, 0, 0, 0 } }, { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { RSPI, 0, 0, 0 } }, { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } }, - /* IPRLA3 */ + { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, HDMI_SSS, HDMI_KEY, 0 } }, { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU, 0, 0, 0 } }, { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } }, { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S, diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c index 670fe1869db..ce9e7fa5cc8 100644 --- a/arch/arm/mach-shmobile/pfc-r8a7740.c +++ b/arch/arm/mach-shmobile/pfc-r8a7740.c @@ -169,7 +169,7 @@ enum { DBGMD10_MARK, DBGMD11_MARK, DBGMD20_MARK, DBGMD21_MARK, - /* FSI */ + /* FSI-A */ FSIAISLD_PORT0_MARK, /* FSIAISLD Port 0/5 */ FSIAISLD_PORT5_MARK, FSIASPDIF_PORT9_MARK, /* FSIASPDIF Port 9/18 */ @@ -178,6 +178,9 @@ enum { FSIAOBT_MARK, FSIAOSLD_MARK, FSIAOMC_MARK, FSIACK_MARK, FSIAILR_MARK, FSIAIBT_MARK, + /* FSI-B */ + FSIBCK_MARK, + /* FMSI */ FMSISLD_PORT1_MARK, /* FMSISLD Port 1/6 */ FMSISLD_PORT6_MARK, @@ -560,6 +563,9 @@ enum { /* SDENC */ SDENC_CPG_MARK, SDENC_DV_CLKI_MARK, + /* HDMI */ + HDMI_HPD_MARK, HDMI_CEC_MARK, + /* DEBUG */ EDEBGREQ_PULLUP_MARK, /* for JTAG */ EDEBGREQ_PULLDOWN_MARK, @@ -771,6 +777,7 @@ static pinmux_enum_t pinmux_data[] = { /* Port11 */ PINMUX_DATA(FSIACK_MARK, PORT11_FN1), + PINMUX_DATA(FSIBCK_MARK, PORT11_FN2), PINMUX_DATA(IRQ2_PORT11_MARK, PORT11_FN0, MSEL1CR_2_0), /* Port12 */ @@ -1254,7 +1261,7 @@ static pinmux_enum_t pinmux_data[] = { PINMUX_DATA(A21_MARK, PORT120_FN1), PINMUX_DATA(MSIOF0_RSYNC_MARK, PORT120_FN2), PINMUX_DATA(MSIOF1_TSYNC_PORT120_MARK, PORT120_FN3, MSEL4CR_10_0), - PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_0), + PINMUX_DATA(IRQ7_PORT120_MARK, PORT120_FN0, MSEL1CR_7_1), /* Port121 */ PINMUX_DATA(A20_MARK, PORT121_FN1), @@ -1616,13 +1623,15 @@ static pinmux_enum_t pinmux_data[] = { /* Port209 */ PINMUX_DATA(VBUS_MARK, PORT209_FN1), - PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_1), + PINMUX_DATA(IRQ7_PORT209_MARK, PORT209_FN0, MSEL1CR_7_0), /* Port210 */ PINMUX_DATA(IRQ9_PORT210_MARK, PORT210_FN0, MSEL1CR_9_1), + PINMUX_DATA(HDMI_HPD_MARK, PORT210_FN1), /* Port211 */ PINMUX_DATA(IRQ16_PORT211_MARK, PORT211_FN0, MSEL1CR_16_1), + PINMUX_DATA(HDMI_CEC_MARK, PORT211_FN1), /* LCDC select */ PINMUX_DATA(LCDC0_SELECT_MARK, MSEL3CR_6_0), @@ -1691,7 +1700,7 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(DBGMD10), GPIO_FN(DBGMD11), GPIO_FN(DBGMD20), GPIO_FN(DBGMD21), - /* FSI */ + /* FSI-A */ GPIO_FN(FSIAISLD_PORT0), /* FSIAISLD Port 0/5 */ GPIO_FN(FSIAISLD_PORT5), GPIO_FN(FSIASPDIF_PORT9), /* FSIASPDIF Port 9/18 */ @@ -1700,6 +1709,9 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(FSIAOBT), GPIO_FN(FSIAOSLD), GPIO_FN(FSIAOMC), GPIO_FN(FSIACK), GPIO_FN(FSIAILR), GPIO_FN(FSIAIBT), + /* FSI-B */ + GPIO_FN(FSIBCK), + /* FMSI */ GPIO_FN(FMSISLD_PORT1), /* FMSISLD Port 1/6 */ GPIO_FN(FMSISLD_PORT6), @@ -2097,6 +2109,10 @@ static struct pinmux_gpio pinmux_gpios[] = { GPIO_FN(SDENC_CPG), GPIO_FN(SDENC_DV_CLKI), + /* HDMI */ + GPIO_FN(HDMI_HPD), + GPIO_FN(HDMI_CEC), + /* SYSC */ GPIO_FN(RESETP_PULLUP), GPIO_FN(RESETP_PLAIN), diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c new file mode 100644 index 00000000000..893504d012a --- /dev/null +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -0,0 +1,54 @@ +/* + * r8a7740 power management support + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/console.h> +#include <mach/pm-rmobile.h> + +#ifdef CONFIG_PM +static int r8a7740_pd_a4s_suspend(void) +{ + /* + * The A4S domain contains the CPU core and therefore it should + * only be turned off if the CPU is in use. + */ + return -EBUSY; +} + +struct rmobile_pm_domain r8a7740_pd_a4s = { + .genpd.name = "A4S", + .bit_shift = 10, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a4s_suspend, +}; + +static int r8a7740_pd_a3sp_suspend(void) +{ + /* + * Serial consoles make use of SCIF hardware located in A3SP, + * keep such power domain on if "no_console_suspend" is set. + */ + return console_suspend_enabled ? 0 : -EBUSY; +} + +struct rmobile_pm_domain r8a7740_pd_a3sp = { + .genpd.name = "A3SP", + .bit_shift = 11, + .gov = &pm_domain_always_on_gov, + .no_debug = true, + .suspend = r8a7740_pd_a3sp_suspend, +}; + +struct rmobile_pm_domain r8a7740_pd_a4lc = { + .genpd.name = "A4LC", + .bit_shift = 1, +}; + +#endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c new file mode 100644 index 00000000000..a8562540f1d --- /dev/null +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -0,0 +1,167 @@ +/* + * rmobile power management support + * + * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * + * based on pm-sh7372.c + * Copyright (C) 2011 Magnus Damm + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/pm_clock.h> +#include <asm/io.h> +#include <mach/pm-rmobile.h> + +/* SYSC */ +#define SPDCR 0xe6180008 +#define SWUCR 0xe6180014 +#define PSTR 0xe6180080 + +#define PSTR_RETRIES 100 +#define PSTR_DELAY_US 10 + +#ifdef CONFIG_PM +static int rmobile_pd_power_down(struct generic_pm_domain *genpd) +{ + struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd); + unsigned int mask = 1 << rmobile_pd->bit_shift; + + if (rmobile_pd->suspend) { + int ret = rmobile_pd->suspend(); + + if (ret) + return ret; + } + + if (__raw_readl(PSTR) & mask) { + unsigned int retry_count; + __raw_writel(mask, SPDCR); + + for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(SPDCR) & mask)) + break; + cpu_relax(); + } + } + + if (!rmobile_pd->no_debug) + pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", + genpd->name, mask, __raw_readl(PSTR)); + + return 0; +} + +static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, + bool do_resume) +{ + unsigned int mask = 1 << rmobile_pd->bit_shift; + unsigned int retry_count; + int ret = 0; + + if (__raw_readl(PSTR) & mask) + goto out; + + __raw_writel(mask, SWUCR); + + for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { + if (!(__raw_readl(SWUCR) & mask)) + break; + if (retry_count > PSTR_RETRIES) + udelay(PSTR_DELAY_US); + else + cpu_relax(); + } + if (!retry_count) + ret = -EIO; + + if (!rmobile_pd->no_debug) + pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", + rmobile_pd->genpd.name, mask, __raw_readl(PSTR)); + +out: + if (ret == 0 && rmobile_pd->resume && do_resume) + rmobile_pd->resume(); + + return ret; +} + +static int rmobile_pd_power_up(struct generic_pm_domain *genpd) +{ + return __rmobile_pd_power_up(to_rmobile_pd(genpd), true); +} + +static bool rmobile_pd_active_wakeup(struct device *dev) +{ + bool (*active_wakeup)(struct device *dev); + + active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; + return active_wakeup ? active_wakeup(dev) : true; +} + +static int rmobile_pd_stop_dev(struct device *dev) +{ + int (*stop)(struct device *dev); + + stop = dev_gpd_data(dev)->ops.stop; + if (stop) { + int ret = stop(dev); + if (ret) + return ret; + } + return pm_clk_suspend(dev); +} + +static int rmobile_pd_start_dev(struct device *dev) +{ + int (*start)(struct device *dev); + int ret; + + ret = pm_clk_resume(dev); + if (ret) + return ret; + + start = dev_gpd_data(dev)->ops.start; + if (start) + ret = start(dev); + + return ret; +} + +void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) +{ + struct generic_pm_domain *genpd = &rmobile_pd->genpd; + struct dev_power_governor *gov = rmobile_pd->gov; + + pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); + genpd->dev_ops.stop = rmobile_pd_stop_dev; + genpd->dev_ops.start = rmobile_pd_start_dev; + genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; + genpd->dev_irq_safe = true; + genpd->power_off = rmobile_pd_power_down; + genpd->power_on = rmobile_pd_power_up; + __rmobile_pd_power_up(rmobile_pd, false); +} + +void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd, + struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + pm_genpd_add_device(&rmobile_pd->genpd, dev); + if (pm_clk_no_clocks(dev)) + pm_clk_add(dev, NULL); +} + +void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd, + struct rmobile_pm_domain *rmobile_sd) +{ + pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd); +} +#endif /* CONFIG_PM */ diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index a3bdb12acde..79203706922 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -26,6 +26,7 @@ #include <asm/suspend.h> #include <mach/common.h> #include <mach/sh7372.h> +#include <mach/pm-rmobile.h> /* DBG */ #define DBGREG1 0xe6100020 @@ -41,13 +42,10 @@ #define PLLC01STPCR 0xe61500c8 /* SYSC */ -#define SPDCR 0xe6180008 -#define SWUCR 0xe6180014 #define SBAR 0xe6180020 #define WUPRMSK 0xe6180028 #define WUPSMSK 0xe618002c #define WUPSMSK2 0xe6180048 -#define PSTR 0xe6180080 #define WUPSFAC 0xe6180098 #define IRQCR 0xe618022c #define IRQCR2 0xe6180238 @@ -71,188 +69,48 @@ /* AP-System Core */ #define APARMBAREA 0xe6f10020 -#define PSTR_RETRIES 100 -#define PSTR_DELAY_US 10 - #ifdef CONFIG_PM -static int pd_power_down(struct generic_pm_domain *genpd) -{ - struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd); - unsigned int mask = 1 << sh7372_pd->bit_shift; - - if (sh7372_pd->suspend) { - int ret = sh7372_pd->suspend(); - - if (ret) - return ret; - } - - if (__raw_readl(PSTR) & mask) { - unsigned int retry_count; - - __raw_writel(mask, SPDCR); - - for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SPDCR) & mask)) - break; - cpu_relax(); - } - } - - if (!sh7372_pd->no_debug) - pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", - genpd->name, mask, __raw_readl(PSTR)); - - return 0; -} - -static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume) -{ - unsigned int mask = 1 << sh7372_pd->bit_shift; - unsigned int retry_count; - int ret = 0; - - if (__raw_readl(PSTR) & mask) - goto out; - - __raw_writel(mask, SWUCR); - - for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SWUCR) & mask)) - break; - if (retry_count > PSTR_RETRIES) - udelay(PSTR_DELAY_US); - else - cpu_relax(); - } - if (!retry_count) - ret = -EIO; - - if (!sh7372_pd->no_debug) - pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - sh7372_pd->genpd.name, mask, __raw_readl(PSTR)); - - out: - if (ret == 0 && sh7372_pd->resume && do_resume) - sh7372_pd->resume(); - - return ret; -} - -static int pd_power_up(struct generic_pm_domain *genpd) -{ - return __pd_power_up(to_sh7372_pd(genpd), true); -} - -static int sh7372_a4r_suspend(void) -{ - sh7372_intcs_suspend(); - __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ - return 0; -} - -static bool pd_active_wakeup(struct device *dev) -{ - bool (*active_wakeup)(struct device *dev); - - active_wakeup = dev_gpd_data(dev)->ops.active_wakeup; - return active_wakeup ? active_wakeup(dev) : true; -} - -static int sh7372_stop_dev(struct device *dev) -{ - int (*stop)(struct device *dev); - - stop = dev_gpd_data(dev)->ops.stop; - if (stop) { - int ret = stop(dev); - if (ret) - return ret; - } - return pm_clk_suspend(dev); -} - -static int sh7372_start_dev(struct device *dev) -{ - int (*start)(struct device *dev); - int ret; - - ret = pm_clk_resume(dev); - if (ret) - return ret; - - start = dev_gpd_data(dev)->ops.start; - if (start) - ret = start(dev); - - return ret; -} - -void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd) -{ - struct generic_pm_domain *genpd = &sh7372_pd->genpd; - struct dev_power_governor *gov = sh7372_pd->gov; - - pm_genpd_init(genpd, gov ? : &simple_qos_governor, false); - genpd->dev_ops.stop = sh7372_stop_dev; - genpd->dev_ops.start = sh7372_start_dev; - genpd->dev_ops.active_wakeup = pd_active_wakeup; - genpd->dev_irq_safe = true; - genpd->power_off = pd_power_down; - genpd->power_on = pd_power_up; - __pd_power_up(sh7372_pd, false); -} - -void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd, - struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - - pm_genpd_add_device(&sh7372_pd->genpd, dev); - if (pm_clk_no_clocks(dev)) - pm_clk_add(dev, NULL); -} - -void sh7372_pm_add_subdomain(struct sh7372_pm_domain *sh7372_pd, - struct sh7372_pm_domain *sh7372_sd) -{ - pm_genpd_add_subdomain(&sh7372_pd->genpd, &sh7372_sd->genpd); -} - -struct sh7372_pm_domain sh7372_a4lc = { +struct rmobile_pm_domain sh7372_pd_a4lc = { .genpd.name = "A4LC", .bit_shift = 1, }; -struct sh7372_pm_domain sh7372_a4mp = { +struct rmobile_pm_domain sh7372_pd_a4mp = { .genpd.name = "A4MP", .bit_shift = 2, }; -struct sh7372_pm_domain sh7372_d4 = { +struct rmobile_pm_domain sh7372_pd_d4 = { .genpd.name = "D4", .bit_shift = 3, }; -struct sh7372_pm_domain sh7372_a4r = { +static int sh7372_a4r_pd_suspend(void) +{ + sh7372_intcs_suspend(); + __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */ + return 0; +} + +struct rmobile_pm_domain sh7372_pd_a4r = { .genpd.name = "A4R", .bit_shift = 5, - .suspend = sh7372_a4r_suspend, + .suspend = sh7372_a4r_pd_suspend, .resume = sh7372_intcs_resume, }; -struct sh7372_pm_domain sh7372_a3rv = { +struct rmobile_pm_domain sh7372_pd_a3rv = { .genpd.name = "A3RV", .bit_shift = 6, }; -struct sh7372_pm_domain sh7372_a3ri = { +struct rmobile_pm_domain sh7372_pd_a3ri = { .genpd.name = "A3RI", .bit_shift = 8, }; -static int sh7372_a4s_suspend(void) +static int sh7372_pd_a4s_suspend(void) { /* * The A4S domain contains the CPU core and therefore it should @@ -261,15 +119,15 @@ static int sh7372_a4s_suspend(void) return -EBUSY; } -struct sh7372_pm_domain sh7372_a4s = { +struct rmobile_pm_domain sh7372_pd_a4s = { .genpd.name = "A4S", .bit_shift = 10, .gov = &pm_domain_always_on_gov, .no_debug = true, - .suspend = sh7372_a4s_suspend, + .suspend = sh7372_pd_a4s_suspend, }; -static int sh7372_a3sp_suspend(void) +static int sh7372_a3sp_pd_suspend(void) { /* * Serial consoles make use of SCIF hardware located in A3SP, @@ -278,32 +136,22 @@ static int sh7372_a3sp_suspend(void) return console_suspend_enabled ? 0 : -EBUSY; } -struct sh7372_pm_domain sh7372_a3sp = { +struct rmobile_pm_domain sh7372_pd_a3sp = { .genpd.name = "A3SP", .bit_shift = 11, .gov = &pm_domain_always_on_gov, .no_debug = true, - .suspend = sh7372_a3sp_suspend, + .suspend = sh7372_a3sp_pd_suspend, }; -struct sh7372_pm_domain sh7372_a3sg = { +struct rmobile_pm_domain sh7372_pd_a3sg = { .genpd.name = "A3SG", .bit_shift = 13, }; -#else /* !CONFIG_PM */ - -static inline void sh7372_a3sp_init(void) {} - -#endif /* !CONFIG_PM */ +#endif /* CONFIG_PM */ #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE) -static int sh7372_do_idle_core_standby(unsigned long unused) -{ - cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ - return 0; -} - static void sh7372_set_reset_vector(unsigned long address) { /* set reset vector, translate 4k */ @@ -311,21 +159,6 @@ static void sh7372_set_reset_vector(unsigned long address) __raw_writel(0, APARMBAREA); } -static void sh7372_enter_core_standby(void) -{ - sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); - - /* enter sleep mode with SYSTBCR to 0x10 */ - __raw_writel(0x10, SYSTBCR); - cpu_suspend(0, sh7372_do_idle_core_standby); - __raw_writel(0, SYSTBCR); - - /* disable reset vector translation */ - __raw_writel(0, SBAR); -} -#endif - -#ifdef CONFIG_SUSPEND static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode) { if (pllc0_on) @@ -465,22 +298,42 @@ static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2) static void sh7372_enter_a3sm_common(int pllc0_on) { + /* use INTCA together with SYSC for wakeup */ + sh7372_setup_sysc(1 << 0, 0); sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); sh7372_enter_sysc(pllc0_on, 1 << 12); } +#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */ -static void sh7372_enter_a4s_common(int pllc0_on) +#ifdef CONFIG_CPU_IDLE +static int sh7372_do_idle_core_standby(unsigned long unused) { - sh7372_intca_suspend(); - memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); - sh7372_set_reset_vector(SMFRAM); - sh7372_enter_sysc(pllc0_on, 1 << 10); - sh7372_intca_resume(); + cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */ + return 0; } -#endif +static void sh7372_enter_core_standby(void) +{ + sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc)); -#ifdef CONFIG_CPU_IDLE + /* enter sleep mode with SYSTBCR to 0x10 */ + __raw_writel(0x10, SYSTBCR); + cpu_suspend(0, sh7372_do_idle_core_standby); + __raw_writel(0, SYSTBCR); + + /* disable reset vector translation */ + __raw_writel(0, SBAR); +} + +static void sh7372_enter_a3sm_pll_on(void) +{ + sh7372_enter_a3sm_common(1); +} + +static void sh7372_enter_a3sm_pll_off(void) +{ + sh7372_enter_a3sm_common(0); +} static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) { @@ -492,7 +345,24 @@ static void sh7372_cpuidle_setup(struct cpuidle_driver *drv) state->target_residency = 20 + 10; state->flags = CPUIDLE_FLAG_TIME_VALID; shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby; + drv->state_count++; + + state = &drv->states[drv->state_count]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); + strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN); + state->exit_latency = 20; + state->target_residency = 30 + 20; + state->flags = CPUIDLE_FLAG_TIME_VALID; + shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on; + drv->state_count++; + state = &drv->states[drv->state_count]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C4"); + strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN); + state->exit_latency = 120; + state->target_residency = 30 + 120; + state->flags = CPUIDLE_FLAG_TIME_VALID; + shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off; drv->state_count++; } @@ -505,6 +375,14 @@ static void sh7372_cpuidle_init(void) {} #endif #ifdef CONFIG_SUSPEND +static void sh7372_enter_a4s_common(int pllc0_on) +{ + sh7372_intca_suspend(); + memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100); + sh7372_set_reset_vector(SMFRAM); + sh7372_enter_sysc(pllc0_on, 1 << 10); + sh7372_intca_resume(); +} static int sh7372_enter_suspend(suspend_state_t suspend_state) { @@ -512,24 +390,21 @@ static int sh7372_enter_suspend(suspend_state_t suspend_state) /* check active clocks to determine potential wakeup sources */ if (sh7372_sysc_valid(&msk, &msk2)) { - /* convert INTC mask and sense to SYSC mask and sense */ - sh7372_setup_sysc(msk, msk2); - if (!console_suspend_enabled && - sh7372_a4s.genpd.status == GPD_STATE_POWER_OFF) { + sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) { + /* convert INTC mask/sense to SYSC mask/sense */ + sh7372_setup_sysc(msk, msk2); + /* enter A4S sleep with PLLC0 off */ pr_debug("entering A4S\n"); sh7372_enter_a4s_common(0); - } else { - /* enter A3SM sleep with PLLC0 off */ - pr_debug("entering A3SM\n"); - sh7372_enter_a3sm_common(0); + return 0; } - } else { - /* default to Core Standby that supports all wakeup sources */ - pr_debug("entering Core Standby\n"); - sh7372_enter_core_standby(); } + + /* default to enter A3SM sleep with PLLC0 off */ + pr_debug("entering A3SM\n"); + sh7372_enter_a3sm_common(0); return 0; } @@ -550,7 +425,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier, * executed during system suspend and resume, respectively, so * that those functions don't crash while accessing the INTCS. */ - pm_genpd_poweron(&sh7372_a4r.genpd); + pm_genpd_poweron(&sh7372_pd_a4r.genpd); break; case PM_POST_SUSPEND: pm_genpd_poweroff_unused(); diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index ec4eb49c169..78948a9dba0 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -23,9 +23,14 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/serial_sci.h> +#include <linux/sh_dma.h> #include <linux/sh_timer.h> +#include <linux/dma-mapping.h> +#include <mach/dma-register.h> #include <mach/r8a7740.h> +#include <mach/pm-rmobile.h> #include <mach/common.h> #include <mach/irqs.h> #include <asm/mach-types.h> @@ -276,6 +281,272 @@ static struct platform_device *r8a7740_early_devices[] __initdata = { &cmt10_device, }; +/* DMA */ +static const struct sh_dmae_slave_config r8a7740_dmae_slaves[] = { + { + .slave_id = SHDMA_SLAVE_SDHI0_TX, + .addr = 0xe6850030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xc1, + }, { + .slave_id = SHDMA_SLAVE_SDHI0_RX, + .addr = 0xe6850030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xc2, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_TX, + .addr = 0xe6860030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xc9, + }, { + .slave_id = SHDMA_SLAVE_SDHI1_RX, + .addr = 0xe6860030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xca, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_TX, + .addr = 0xe6870030, + .chcr = CHCR_TX(XMIT_SZ_16BIT), + .mid_rid = 0xcd, + }, { + .slave_id = SHDMA_SLAVE_SDHI2_RX, + .addr = 0xe6870030, + .chcr = CHCR_RX(XMIT_SZ_16BIT), + .mid_rid = 0xce, + }, { + .slave_id = SHDMA_SLAVE_FSIA_TX, + .addr = 0xfe1f0024, + .chcr = CHCR_TX(XMIT_SZ_32BIT), + .mid_rid = 0xb1, + }, { + .slave_id = SHDMA_SLAVE_FSIA_RX, + .addr = 0xfe1f0020, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0xb2, + }, { + .slave_id = SHDMA_SLAVE_FSIB_TX, + .addr = 0xfe1f0064, + .chcr = CHCR_TX(XMIT_SZ_32BIT), + .mid_rid = 0xb5, + }, +}; + +#define DMA_CHANNEL(a, b, c) \ +{ \ + .offset = a, \ + .dmars = b, \ + .dmars_bit = c, \ + .chclr_offset = (0x220 - 0x20) + a \ +} + +static const struct sh_dmae_channel r8a7740_dmae_channels[] = { + DMA_CHANNEL(0x00, 0, 0), + DMA_CHANNEL(0x10, 0, 8), + DMA_CHANNEL(0x20, 4, 0), + DMA_CHANNEL(0x30, 4, 8), + DMA_CHANNEL(0x50, 8, 0), + DMA_CHANNEL(0x60, 8, 8), +}; + +static struct sh_dmae_pdata dma_platform_data = { + .slave = r8a7740_dmae_slaves, + .slave_num = ARRAY_SIZE(r8a7740_dmae_slaves), + .channel = r8a7740_dmae_channels, + .channel_num = ARRAY_SIZE(r8a7740_dmae_channels), + .ts_low_shift = TS_LOW_SHIFT, + .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, + .ts_high_shift = TS_HI_SHIFT, + .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, + .ts_shift = dma_ts_shift, + .ts_shift_num = ARRAY_SIZE(dma_ts_shift), + .dmaor_init = DMAOR_DME, + .chclr_present = 1, +}; + +/* Resource order important! */ +static struct resource r8a7740_dmae0_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe008020, + .end = 0xfe00828f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe009000, + .end = 0xfe00900b, + .flags = IORESOURCE_MEM, + }, + { + .name = "error_irq", + .start = evt2irq(0x20c0), + .end = evt2irq(0x20c0), + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = evt2irq(0x2000), + .end = evt2irq(0x20a0), + .flags = IORESOURCE_IRQ, + }, +}; + +/* Resource order important! */ +static struct resource r8a7740_dmae1_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe018020, + .end = 0xfe01828f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe019000, + .end = 0xfe01900b, + .flags = IORESOURCE_MEM, + }, + { + .name = "error_irq", + .start = evt2irq(0x21c0), + .end = evt2irq(0x21c0), + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = evt2irq(0x2100), + .end = evt2irq(0x21a0), + .flags = IORESOURCE_IRQ, + }, +}; + +/* Resource order important! */ +static struct resource r8a7740_dmae2_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe028020, + .end = 0xfe02828f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xfe029000, + .end = 0xfe02900b, + .flags = IORESOURCE_MEM, + }, + { + .name = "error_irq", + .start = evt2irq(0x22c0), + .end = evt2irq(0x22c0), + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = evt2irq(0x2200), + .end = evt2irq(0x22a0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dma0_device = { + .name = "sh-dma-engine", + .id = 0, + .resource = r8a7740_dmae0_resources, + .num_resources = ARRAY_SIZE(r8a7740_dmae0_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + +static struct platform_device dma1_device = { + .name = "sh-dma-engine", + .id = 1, + .resource = r8a7740_dmae1_resources, + .num_resources = ARRAY_SIZE(r8a7740_dmae1_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + +static struct platform_device dma2_device = { + .name = "sh-dma-engine", + .id = 2, + .resource = r8a7740_dmae2_resources, + .num_resources = ARRAY_SIZE(r8a7740_dmae2_resources), + .dev = { + .platform_data = &dma_platform_data, + }, +}; + +/* USB-DMAC */ +static const struct sh_dmae_channel r8a7740_usb_dma_channels[] = { + { + .offset = 0, + }, { + .offset = 0x20, + }, +}; + +static const struct sh_dmae_slave_config r8a7740_usb_dma_slaves[] = { + { + .slave_id = SHDMA_SLAVE_USBHS_TX, + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), + }, { + .slave_id = SHDMA_SLAVE_USBHS_RX, + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), + }, +}; + +static struct sh_dmae_pdata usb_dma_platform_data = { + .slave = r8a7740_usb_dma_slaves, + .slave_num = ARRAY_SIZE(r8a7740_usb_dma_slaves), + .channel = r8a7740_usb_dma_channels, + .channel_num = ARRAY_SIZE(r8a7740_usb_dma_channels), + .ts_low_shift = USBTS_LOW_SHIFT, + .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT, + .ts_high_shift = USBTS_HI_SHIFT, + .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT, + .ts_shift = dma_usbts_shift, + .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), + .dmaor_init = DMAOR_DME, + .chcr_offset = 0x14, + .chcr_ie_bit = 1 << 5, + .dmaor_is_32bit = 1, + .needs_tend_set = 1, + .no_dmars = 1, + .slave_only = 1, +}; + +static struct resource r8a7740_usb_dma_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xe68a0020, + .end = 0xe68a0064 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* VCR/SWR/DMICR */ + .start = 0xe68a0000, + .end = 0xe68a0014 - 1, + .flags = IORESOURCE_MEM, + }, + { + /* IRQ for channels */ + .start = evt2irq(0x0a00), + .end = evt2irq(0x0a00), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_dma_device = { + .name = "sh-dma-engine", + .id = 3, + .resource = r8a7740_usb_dma_resources, + .num_resources = ARRAY_SIZE(r8a7740_usb_dma_resources), + .dev = { + .platform_data = &usb_dma_platform_data, + }, +}; + /* I2C */ static struct resource i2c0_resources[] = { [0] = { @@ -322,8 +593,30 @@ static struct platform_device i2c1_device = { static struct platform_device *r8a7740_late_devices[] __initdata = { &i2c0_device, &i2c1_device, + &dma0_device, + &dma1_device, + &dma2_device, + &usb_dma_device, }; +/* + * r8a7740 chip has lasting errata on MERAM buffer. + * this is work-around for it. + * see + * "Media RAM (MERAM)" on r8a7740 documentation + */ +#define MEBUFCNTR 0xFE950098 +void r8a7740_meram_workaround(void) +{ + void __iomem *reg; + + reg = ioremap_nocache(MEBUFCNTR, 4); + if (reg) { + iowrite32(0x01600164, reg); + iounmap(reg); + } +} + #define ICCR 0x0004 #define ICSTART 0x0070 @@ -380,10 +673,31 @@ void __init r8a7740_add_standard_devices(void) r8a7740_i2c_workaround(&i2c0_device); r8a7740_i2c_workaround(&i2c1_device); + /* PM domain */ + rmobile_init_pm_domain(&r8a7740_pd_a4s); + rmobile_init_pm_domain(&r8a7740_pd_a3sp); + rmobile_init_pm_domain(&r8a7740_pd_a4lc); + + rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp); + + /* add devices */ platform_add_devices(r8a7740_early_devices, ARRAY_SIZE(r8a7740_early_devices)); platform_add_devices(r8a7740_late_devices, ARRAY_SIZE(r8a7740_late_devices)); + + /* add devices to PM domain */ + + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif0_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif1_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif2_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif3_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif4_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif5_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif6_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scif7_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &scifb_device); + rmobile_add_device_to_domain(&r8a7740_pd_a3sp, &i2c1_device); } static void __init r8a7740_earlytimer_init(void) @@ -403,3 +717,49 @@ void __init r8a7740_add_early_devices(void) /* override timer setup with soc-specific code */ shmobile_timer.init = r8a7740_earlytimer_init; } + +#ifdef CONFIG_USE_OF + +void __init r8a7740_add_early_devices_dt(void) +{ + shmobile_setup_delay(800, 1, 3); /* Cortex-A9 @ 800MHz */ + + early_platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + + /* setup early console here as well */ + shmobile_setup_console(); +} + +static const struct of_dev_auxdata r8a7740_auxdata_lookup[] __initconst = { + { } +}; + +void __init r8a7740_add_standard_devices_dt(void) +{ + /* clocks are setup late during boot in the case of DT */ + r8a7740_clock_init(0); + + platform_add_devices(r8a7740_early_devices, + ARRAY_SIZE(r8a7740_early_devices)); + + of_platform_populate(NULL, of_default_bus_match_table, + r8a7740_auxdata_lookup, NULL); +} + +static const char *r8a7740_boards_compat_dt[] __initdata = { + "renesas,r8a7740", + NULL, +}; + +DT_MACHINE_START(SH7372_DT, "Generic R8A7740 (Flattened Device Tree)") + .map_io = r8a7740_map_io, + .init_early = r8a7740_add_early_devices_dt, + .init_irq = r8a7740_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = r8a7740_add_standard_devices_dt, + .timer = &shmobile_timer, + .dt_compat = r8a7740_boards_compat_dt, +MACHINE_END + +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index fafce9ce821..838a87be1d5 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -33,6 +33,7 @@ #include <linux/sh_timer.h> #include <linux/pm_domain.h> #include <linux/dma-mapping.h> +#include <mach/dma-register.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/sh7372.h> @@ -335,151 +336,126 @@ static struct platform_device iic1_device = { }; /* DMA */ -/* Transmit sizes and respective CHCR register values */ -enum { - XMIT_SZ_8BIT = 0, - XMIT_SZ_16BIT = 1, - XMIT_SZ_32BIT = 2, - XMIT_SZ_64BIT = 7, - XMIT_SZ_128BIT = 3, - XMIT_SZ_256BIT = 4, - XMIT_SZ_512BIT = 5, -}; - -/* log2(size / 8) - used to calculate number of transfers */ -#define TS_SHIFT { \ - [XMIT_SZ_8BIT] = 0, \ - [XMIT_SZ_16BIT] = 1, \ - [XMIT_SZ_32BIT] = 2, \ - [XMIT_SZ_64BIT] = 3, \ - [XMIT_SZ_128BIT] = 4, \ - [XMIT_SZ_256BIT] = 5, \ - [XMIT_SZ_512BIT] = 6, \ -} - -#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | \ - (((i) & 0xc) << (20 - 2))) - static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF0_TX, .addr = 0xe6c40020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x21, }, { .slave_id = SHDMA_SLAVE_SCIF0_RX, .addr = 0xe6c40024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x22, }, { .slave_id = SHDMA_SLAVE_SCIF1_TX, .addr = 0xe6c50020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x25, }, { .slave_id = SHDMA_SLAVE_SCIF1_RX, .addr = 0xe6c50024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x26, }, { .slave_id = SHDMA_SLAVE_SCIF2_TX, .addr = 0xe6c60020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x29, }, { .slave_id = SHDMA_SLAVE_SCIF2_RX, .addr = 0xe6c60024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x2a, }, { .slave_id = SHDMA_SLAVE_SCIF3_TX, .addr = 0xe6c70020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x2d, }, { .slave_id = SHDMA_SLAVE_SCIF3_RX, .addr = 0xe6c70024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x2e, }, { .slave_id = SHDMA_SLAVE_SCIF4_TX, .addr = 0xe6c80020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x39, }, { .slave_id = SHDMA_SLAVE_SCIF4_RX, .addr = 0xe6c80024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x3a, }, { .slave_id = SHDMA_SLAVE_SCIF5_TX, .addr = 0xe6cb0020, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x35, }, { .slave_id = SHDMA_SLAVE_SCIF5_RX, .addr = 0xe6cb0024, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x36, }, { .slave_id = SHDMA_SLAVE_SCIF6_TX, .addr = 0xe6c30040, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_TX(XMIT_SZ_8BIT), .mid_rid = 0x3d, }, { .slave_id = SHDMA_SLAVE_SCIF6_RX, .addr = 0xe6c30060, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT), + .chcr = CHCR_RX(XMIT_SZ_8BIT), .mid_rid = 0x3e, }, { .slave_id = SHDMA_SLAVE_SDHI0_TX, .addr = 0xe6850030, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_TX(XMIT_SZ_16BIT), .mid_rid = 0xc1, }, { .slave_id = SHDMA_SLAVE_SDHI0_RX, .addr = 0xe6850030, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_RX(XMIT_SZ_16BIT), .mid_rid = 0xc2, }, { .slave_id = SHDMA_SLAVE_SDHI1_TX, .addr = 0xe6860030, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_TX(XMIT_SZ_16BIT), .mid_rid = 0xc9, }, { .slave_id = SHDMA_SLAVE_SDHI1_RX, .addr = 0xe6860030, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_RX(XMIT_SZ_16BIT), .mid_rid = 0xca, }, { .slave_id = SHDMA_SLAVE_SDHI2_TX, .addr = 0xe6870030, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_TX(XMIT_SZ_16BIT), .mid_rid = 0xcd, }, { .slave_id = SHDMA_SLAVE_SDHI2_RX, .addr = 0xe6870030, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT), + .chcr = CHCR_RX(XMIT_SZ_16BIT), .mid_rid = 0xce, }, { .slave_id = SHDMA_SLAVE_FSIA_TX, .addr = 0xfe1f0024, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .chcr = CHCR_TX(XMIT_SZ_32BIT), .mid_rid = 0xb1, }, { .slave_id = SHDMA_SLAVE_FSIA_RX, .addr = 0xfe1f0020, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .chcr = CHCR_RX(XMIT_SZ_32BIT), .mid_rid = 0xb2, }, { .slave_id = SHDMA_SLAVE_MMCIF_TX, .addr = 0xe6bd0034, - .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .chcr = CHCR_TX(XMIT_SZ_32BIT), .mid_rid = 0xd1, }, { .slave_id = SHDMA_SLAVE_MMCIF_RX, .addr = 0xe6bd0034, - .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT), + .chcr = CHCR_RX(XMIT_SZ_32BIT), .mid_rid = 0xd2, }, }; @@ -520,19 +496,17 @@ static const struct sh_dmae_channel sh7372_dmae_channels[] = { } }; -static const unsigned int ts_shift[] = TS_SHIFT; - static struct sh_dmae_pdata dma_platform_data = { .slave = sh7372_dmae_slaves, .slave_num = ARRAY_SIZE(sh7372_dmae_slaves), .channel = sh7372_dmae_channels, .channel_num = ARRAY_SIZE(sh7372_dmae_channels), - .ts_low_shift = 3, - .ts_low_mask = 0x18, - .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */ - .ts_high_mask = 0x00300000, - .ts_shift = ts_shift, - .ts_shift_num = ARRAY_SIZE(ts_shift), + .ts_low_shift = TS_LOW_SHIFT, + .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, + .ts_high_shift = TS_HI_SHIFT, + .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, + .ts_shift = dma_ts_shift, + .ts_shift_num = ARRAY_SIZE(dma_ts_shift), .dmaor_init = DMAOR_DME, .chclr_present = 1, }; @@ -654,17 +628,6 @@ static struct platform_device dma2_device = { /* * USB-DMAC */ - -unsigned int usbts_shift[] = {3, 4, 5}; - -enum { - XMIT_SZ_8BYTE = 0, - XMIT_SZ_16BYTE = 1, - XMIT_SZ_32BYTE = 2, -}; - -#define USBTS_INDEX2VAL(i) (((i) & 3) << 6) - static const struct sh_dmae_channel sh7372_usb_dmae_channels[] = { { .offset = 0, @@ -677,10 +640,10 @@ static const struct sh_dmae_channel sh7372_usb_dmae_channels[] = { static const struct sh_dmae_slave_config sh7372_usb_dmae0_slaves[] = { { .slave_id = SHDMA_SLAVE_USB0_TX, - .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), }, { .slave_id = SHDMA_SLAVE_USB0_RX, - .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), }, }; @@ -689,12 +652,12 @@ static struct sh_dmae_pdata usb_dma0_platform_data = { .slave_num = ARRAY_SIZE(sh7372_usb_dmae0_slaves), .channel = sh7372_usb_dmae_channels, .channel_num = ARRAY_SIZE(sh7372_usb_dmae_channels), - .ts_low_shift = 6, - .ts_low_mask = 0xc0, - .ts_high_shift = 0, - .ts_high_mask = 0, - .ts_shift = usbts_shift, - .ts_shift_num = ARRAY_SIZE(usbts_shift), + .ts_low_shift = USBTS_LOW_SHIFT, + .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT, + .ts_high_shift = USBTS_HI_SHIFT, + .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT, + .ts_shift = dma_usbts_shift, + .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), .dmaor_init = DMAOR_DME, .chcr_offset = 0x14, .chcr_ie_bit = 1 << 5, @@ -739,10 +702,10 @@ static struct platform_device usb_dma0_device = { static const struct sh_dmae_slave_config sh7372_usb_dmae1_slaves[] = { { .slave_id = SHDMA_SLAVE_USB1_TX, - .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), }, { .slave_id = SHDMA_SLAVE_USB1_RX, - .chcr = USBTS_INDEX2VAL(XMIT_SZ_8BYTE), + .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE), }, }; @@ -751,12 +714,12 @@ static struct sh_dmae_pdata usb_dma1_platform_data = { .slave_num = ARRAY_SIZE(sh7372_usb_dmae1_slaves), .channel = sh7372_usb_dmae_channels, .channel_num = ARRAY_SIZE(sh7372_usb_dmae_channels), - .ts_low_shift = 6, - .ts_low_mask = 0xc0, - .ts_high_shift = 0, - .ts_high_mask = 0, - .ts_shift = usbts_shift, - .ts_shift_num = ARRAY_SIZE(usbts_shift), + .ts_low_shift = USBTS_LOW_SHIFT, + .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT, + .ts_high_shift = USBTS_HI_SHIFT, + .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT, + .ts_shift = dma_usbts_shift, + .ts_shift_num = ARRAY_SIZE(dma_usbts_shift), .dmaor_init = DMAOR_DME, .chcr_offset = 0x14, .chcr_ie_bit = 1 << 5, @@ -1038,21 +1001,21 @@ static struct platform_device *sh7372_late_devices[] __initdata = { void __init sh7372_add_standard_devices(void) { - sh7372_init_pm_domain(&sh7372_a4lc); - sh7372_init_pm_domain(&sh7372_a4mp); - sh7372_init_pm_domain(&sh7372_d4); - sh7372_init_pm_domain(&sh7372_a4r); - sh7372_init_pm_domain(&sh7372_a3rv); - sh7372_init_pm_domain(&sh7372_a3ri); - sh7372_init_pm_domain(&sh7372_a4s); - sh7372_init_pm_domain(&sh7372_a3sp); - sh7372_init_pm_domain(&sh7372_a3sg); - - sh7372_pm_add_subdomain(&sh7372_a4lc, &sh7372_a3rv); - sh7372_pm_add_subdomain(&sh7372_a4r, &sh7372_a4lc); - - sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sg); - sh7372_pm_add_subdomain(&sh7372_a4s, &sh7372_a3sp); + rmobile_init_pm_domain(&sh7372_pd_a4lc); + rmobile_init_pm_domain(&sh7372_pd_a4mp); + rmobile_init_pm_domain(&sh7372_pd_d4); + rmobile_init_pm_domain(&sh7372_pd_a4r); + rmobile_init_pm_domain(&sh7372_pd_a3rv); + rmobile_init_pm_domain(&sh7372_pd_a3ri); + rmobile_init_pm_domain(&sh7372_pd_a4s); + rmobile_init_pm_domain(&sh7372_pd_a3sp); + rmobile_init_pm_domain(&sh7372_pd_a3sg); + + rmobile_pm_add_subdomain(&sh7372_pd_a4lc, &sh7372_pd_a3rv); + rmobile_pm_add_subdomain(&sh7372_pd_a4r, &sh7372_pd_a4lc); + + rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sg); + rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sp); platform_add_devices(sh7372_early_devices, ARRAY_SIZE(sh7372_early_devices)); @@ -1060,30 +1023,30 @@ void __init sh7372_add_standard_devices(void) platform_add_devices(sh7372_late_devices, ARRAY_SIZE(sh7372_late_devices)); - sh7372_add_device_to_domain(&sh7372_a3rv, &vpu_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &spu0_device); - sh7372_add_device_to_domain(&sh7372_a4mp, &spu1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif2_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif3_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif4_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif5_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &scif6_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &iic1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma1_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &dma2_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma0_device); - sh7372_add_device_to_domain(&sh7372_a3sp, &usb_dma1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &iic0_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu0_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu1_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); - sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); - sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); - sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device); - sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device); + rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif2_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif3_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif4_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif5_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif6_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &iic1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma1_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma2_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma0_device); + rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &iic0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu0_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu1_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu2_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu3_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &jpu_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu00_device); + rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu01_device); } static void __init sh7372_earlytimer_init(void) diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c index d576a6abbad..855b1506caf 100644 --- a/arch/arm/mach-shmobile/setup-sh7377.c +++ b/arch/arm/mach-shmobile/setup-sh7377.c @@ -22,6 +22,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/of_platform.h> #include <linux/uio_driver.h> #include <linux/delay.h> #include <linux/input.h> @@ -500,3 +501,49 @@ void __init sh7377_add_early_devices(void) /* override timer setup with soc-specific code */ shmobile_timer.init = sh7377_earlytimer_init; } + +#ifdef CONFIG_USE_OF + +void __init sh7377_add_early_devices_dt(void) +{ + shmobile_setup_delay(600, 1, 3); /* Cortex-A8 @ 600MHz */ + + early_platform_add_devices(sh7377_early_devices, + ARRAY_SIZE(sh7377_early_devices)); + + /* setup early console here as well */ + shmobile_setup_console(); +} + +static const struct of_dev_auxdata sh7377_auxdata_lookup[] __initconst = { + { } +}; + +void __init sh7377_add_standard_devices_dt(void) +{ + /* clocks are setup late during boot in the case of DT */ + sh7377_clock_init(); + + platform_add_devices(sh7377_early_devices, + ARRAY_SIZE(sh7377_early_devices)); + + of_platform_populate(NULL, of_default_bus_match_table, + sh7377_auxdata_lookup, NULL); +} + +static const char *sh7377_boards_compat_dt[] __initdata = { + "renesas,sh7377", + NULL, +}; + +DT_MACHINE_START(SH7377_DT, "Generic SH7377 (Flattened Device Tree)") + .map_io = sh7377_map_io, + .init_early = sh7377_add_early_devices_dt, + .init_irq = sh7377_init_irq, + .handle_irq = shmobile_handle_irq_intc, + .init_machine = sh7377_add_standard_devices_dt, + .timer = &shmobile_timer, + .dt_compat = sh7377_boards_compat_dt, +MACHINE_END + +#endif /* CONFIG_USE_OF */ diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 04a0dfe7549..d230af656fc 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -30,6 +30,7 @@ #include <linux/sh_dma.h> #include <linux/sh_intc.h> #include <linux/sh_timer.h> +#include <mach/dma-register.h> #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/sh73a0.h> @@ -415,32 +416,6 @@ static struct platform_device i2c4_device = { .num_resources = ARRAY_SIZE(i2c4_resources), }; -/* Transmit sizes and respective CHCR register values */ -enum { - XMIT_SZ_8BIT = 0, - XMIT_SZ_16BIT = 1, - XMIT_SZ_32BIT = 2, - XMIT_SZ_64BIT = 7, - XMIT_SZ_128BIT = 3, - XMIT_SZ_256BIT = 4, - XMIT_SZ_512BIT = 5, -}; - -/* log2(size / 8) - used to calculate number of transfers */ -#define TS_SHIFT { \ - [XMIT_SZ_8BIT] = 0, \ - [XMIT_SZ_16BIT] = 1, \ - [XMIT_SZ_32BIT] = 2, \ - [XMIT_SZ_64BIT] = 3, \ - [XMIT_SZ_128BIT] = 4, \ - [XMIT_SZ_256BIT] = 5, \ - [XMIT_SZ_512BIT] = 6, \ -} - -#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | (((i) & 0xc) << (20 - 2))) -#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz))) -#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz))) - static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF0_TX, @@ -604,19 +579,17 @@ static const struct sh_dmae_channel sh73a0_dmae_channels[] = { DMAE_CHANNEL(0x8980), }; -static const unsigned int ts_shift[] = TS_SHIFT; - static struct sh_dmae_pdata sh73a0_dmae_platform_data = { .slave = sh73a0_dmae_slaves, .slave_num = ARRAY_SIZE(sh73a0_dmae_slaves), .channel = sh73a0_dmae_channels, .channel_num = ARRAY_SIZE(sh73a0_dmae_channels), - .ts_low_shift = 3, - .ts_low_mask = 0x18, - .ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */ - .ts_high_mask = 0x00300000, - .ts_shift = ts_shift, - .ts_shift_num = ARRAY_SIZE(ts_shift), + .ts_low_shift = TS_LOW_SHIFT, + .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, + .ts_high_shift = TS_HI_SHIFT, + .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, + .ts_shift = dma_ts_shift, + .ts_shift_num = ARRAY_SIZE(dma_ts_shift), .dmaor_init = DMAOR_DME, }; @@ -651,6 +624,116 @@ static struct platform_device dma0_device = { }, }; +/* MPDMAC */ +static const struct sh_dmae_slave_config sh73a0_mpdma_slaves[] = { + { + .slave_id = SHDMA_SLAVE_FSI2A_RX, + .addr = 0xec230020, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0xd6, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2A_TX, + .addr = 0xec230024, + .chcr = CHCR_TX(XMIT_SZ_32BIT), + .mid_rid = 0xd5, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2C_RX, + .addr = 0xec230060, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0xda, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2C_TX, + .addr = 0xec230064, + .chcr = CHCR_TX(XMIT_SZ_32BIT), + .mid_rid = 0xd9, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2B_RX, + .addr = 0xec240020, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0x8e, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2B_TX, + .addr = 0xec240024, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0x8d, /* CHECK ME */ + }, { + .slave_id = SHDMA_SLAVE_FSI2D_RX, + .addr = 0xec240060, + .chcr = CHCR_RX(XMIT_SZ_32BIT), + .mid_rid = 0x9a, /* CHECK ME */ + }, +}; + +#define MPDMA_CHANNEL(a, b, c) \ +{ \ + .offset = a, \ + .dmars = b, \ + .dmars_bit = c, \ + .chclr_offset = (0x220 - 0x20) + a \ +} + +static const struct sh_dmae_channel sh73a0_mpdma_channels[] = { + MPDMA_CHANNEL(0x00, 0, 0), + MPDMA_CHANNEL(0x10, 0, 8), + MPDMA_CHANNEL(0x20, 4, 0), + MPDMA_CHANNEL(0x30, 4, 8), + MPDMA_CHANNEL(0x50, 8, 0), + MPDMA_CHANNEL(0x70, 8, 8), +}; + +static struct sh_dmae_pdata sh73a0_mpdma_platform_data = { + .slave = sh73a0_mpdma_slaves, + .slave_num = ARRAY_SIZE(sh73a0_mpdma_slaves), + .channel = sh73a0_mpdma_channels, + .channel_num = ARRAY_SIZE(sh73a0_mpdma_channels), + .ts_low_shift = TS_LOW_SHIFT, + .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, + .ts_high_shift = TS_HI_SHIFT, + .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, + .ts_shift = dma_ts_shift, + .ts_shift_num = ARRAY_SIZE(dma_ts_shift), + .dmaor_init = DMAOR_DME, + .chclr_present = 1, +}; + +/* Resource order important! */ +static struct resource sh73a0_mpdma_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xec618020, + .end = 0xec61828f, + .flags = IORESOURCE_MEM, + }, + { + /* DMARSx */ + .start = 0xec619000, + .end = 0xec61900b, + .flags = IORESOURCE_MEM, + }, + { + .name = "error_irq", + .start = gic_spi(181), + .end = gic_spi(181), + .flags = IORESOURCE_IRQ, + }, + { + /* IRQ for channels 0-5 */ + .start = gic_spi(175), + .end = gic_spi(180), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device mpdma0_device = { + .name = "sh-dma-engine", + .id = 1, + .resource = sh73a0_mpdma_resources, + .num_resources = ARRAY_SIZE(sh73a0_mpdma_resources), + .dev = { + .platform_data = &sh73a0_mpdma_platform_data, + }, +}; + static struct platform_device *sh73a0_early_devices[] __initdata = { &scif0_device, &scif1_device, @@ -673,6 +756,7 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { &i2c3_device, &i2c4_device, &dma0_device, + &mpdma0_device, }; #define SRCR2 0xe61580b0 diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index d0de9c1192f..c0999633a9a 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -64,7 +64,8 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { &tegra_ehci2_pdata), OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2", &tegra_ehci3_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-apbdma", 0x6000a000, "tegra-apbdma", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL), + OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), {} }; diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index ee48214bfd8..53bf60f1158 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -33,6 +33,8 @@ #include <asm/mach/arch.h> #include <asm/hardware/gic.h> +#include <mach/iomap.h> + #include "board.h" #include "clock.h" @@ -48,6 +50,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL), OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL), OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL), + OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL), {} }; diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 8f421c0ca45..8674a890fd1 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -211,24 +211,6 @@ static struct ab8500_platform_data ab8500_platdata = { .codec = &ab8500_codec_pdata, }; -static struct resource ab8500_resources[] = { - [0] = { - .start = IRQ_DB8500_AB8500, - .end = IRQ_DB8500_AB8500, - .flags = IORESOURCE_IRQ - } -}; - -struct platform_device ab8500_device = { - .name = "ab8500-core", - .id = 0, - .dev = { - .platform_data = &ab8500_platdata, - }, - .num_resources = 1, - .resource = ab8500_resources, -}; - /* * TPS61052 */ @@ -443,7 +425,6 @@ static struct hash_platform_data u8500_hash1_platform_data = { /* add any platform devices here - TODO */ static struct platform_device *mop500_platform_devs[] __initdata = { &mop500_gpio_keys_device, - &ab8500_device, }; #ifdef CONFIG_STE_DMA40 @@ -605,7 +586,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = { &snowball_led_dev, &snowball_key_dev, &snowball_sbnet_dev, - &ab8500_device, }; static void __init mop500_init_machine(void) @@ -617,9 +597,8 @@ static void __init mop500_init_machine(void) mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; mop500_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); - /* FIXME: parent of ab8500 should be prcmu */ for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -652,7 +631,7 @@ static void __init snowball_init_machine(void) int i; snowball_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) snowball_platform_devs[i]->dev.parent = parent; @@ -684,7 +663,7 @@ static void __init hrefv60_init_machine(void) mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; hrefv60_pinmaps_init(); - parent = u8500_init_devices(); + parent = u8500_init_devices(&ab8500_platdata); for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) mop500_platform_devs[i]->dev.parent = parent; @@ -785,9 +764,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, { .compatible = "stericsson,db8500-prcmu", }, - { .compatible = "stericsson,db8500-prcmu-regulator", }, - { .compatible = "stericsson,ab8500", }, - { .compatible = "stericsson,ab8500-regulator", }, { .compatible = "simple-bus"}, { }, }; diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index c8dd94f606d..db3c52d56ca 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -16,6 +16,7 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/mfd/abx500/ab8500.h> #include <asm/mach/map.h> #include <asm/pmu.h> @@ -115,7 +116,7 @@ static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler) return ret; } -static struct arm_pmu_platdata db8500_pmu_platdata = { +struct arm_pmu_platdata db8500_pmu_platdata = { .handle_irq = db8500_pmu_handler, }; @@ -206,7 +207,7 @@ static struct device * __init db8500_soc_device_init(void) /* * This function is called from the board init */ -struct device * __init u8500_init_devices(void) +struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500) { struct device *parent; int i; @@ -223,6 +224,8 @@ struct device * __init u8500_init_devices(void) for (i = 0; i < ARRAY_SIZE(platform_devs); i++) platform_devs[i]->dev.parent = parent; + db8500_prcmu_device.dev.platform_data = ab8500; + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return parent; diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 8b7ed82a286..7914e5eaa9c 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -13,11 +13,12 @@ #include <asm/mach/time.h> #include <linux/init.h> +#include <linux/mfd/abx500/ab8500.h> void __init ux500_map_io(void); extern void __init u8500_map_io(void); -extern struct device * __init u8500_init_devices(void); +extern struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500); extern void __init ux500_init_irq(void); extern void __init ux500_init_late(void); diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile index 54e69973f39..7ce51767c99 100644 --- a/arch/arm/mach-vt8500/Makefile +++ b/arch/arm/mach-vt8500/Makefile @@ -5,5 +5,3 @@ obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o obj-$(CONFIG_MACH_BV07) += bv07.o obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o - -obj-$(CONFIG_HAVE_PWM) += pwm.o diff --git a/arch/arm/mach-vt8500/pwm.c b/arch/arm/mach-vt8500/pwm.c deleted file mode 100644 index 8ad825e9359..00000000000 --- a/arch/arm/mach-vt8500/pwm.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * arch/arm/mach-vt8500/pwm.c - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/pwm.h> -#include <linux/delay.h> - -#include <asm/div64.h> - -#define VT8500_NR_PWMS 4 - -static DEFINE_MUTEX(pwm_lock); -static LIST_HEAD(pwm_list); - -struct pwm_device { - struct list_head node; - struct platform_device *pdev; - - const char *label; - - void __iomem *regbase; - - unsigned int use_count; - unsigned int pwm_id; -}; - -#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) -static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) -{ - int loops = msecs_to_loops(10); - while ((readb(reg) & bitmask) && --loops) - cpu_relax(); - - if (unlikely(!loops)) - pr_warning("Waiting for status bits 0x%x to clear timed out\n", - bitmask); -} - -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) -{ - unsigned long long c; - unsigned long period_cycles, prescale, pv, dc; - - if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) - return -EINVAL; - - c = 25000000/2; /* wild guess --- need to implement clocks */ - c = c * period_ns; - do_div(c, 1000000000); - period_cycles = c; - - if (period_cycles < 1) - period_cycles = 1; - prescale = (period_cycles - 1) / 4096; - pv = period_cycles / (prescale + 1) - 1; - if (pv > 4095) - pv = 4095; - - if (prescale > 1023) - return -EINVAL; - - c = (unsigned long long)pv * duty_ns; - do_div(c, period_ns); - dc = c; - - pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 1)); - writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4)); - - pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 2)); - writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4)); - - pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 3)); - writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4)); - - return 0; -} -EXPORT_SYMBOL(pwm_config); - -int pwm_enable(struct pwm_device *pwm) -{ - pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0)); - writel(5, pwm->regbase + (pwm->pwm_id << 4)); - return 0; -} -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) -{ - pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0)); - writel(0, pwm->regbase + (pwm->pwm_id << 4)); -} -EXPORT_SYMBOL(pwm_disable); - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int found = 0; - - mutex_lock(&pwm_lock); - - list_for_each_entry(pwm, &pwm_list, node) { - if (pwm->pwm_id == pwm_id) { - found = 1; - break; - } - } - - if (found) { - if (pwm->use_count == 0) { - pwm->use_count++; - pwm->label = label; - } else { - pwm = ERR_PTR(-EBUSY); - } - } else { - pwm = ERR_PTR(-ENOENT); - } - - mutex_unlock(&pwm_lock); - return pwm; -} -EXPORT_SYMBOL(pwm_request); - -void pwm_free(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - - if (pwm->use_count) { - pwm->use_count--; - pwm->label = NULL; - } else { - pr_warning("PWM device already freed\n"); - } - - mutex_unlock(&pwm_lock); -} -EXPORT_SYMBOL(pwm_free); - -static inline void __add_pwm(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - list_add_tail(&pwm->node, &pwm_list); - mutex_unlock(&pwm_lock); -} - -static int __devinit pwm_probe(struct platform_device *pdev) -{ - struct pwm_device *pwms; - struct resource *r; - int ret = 0; - int i; - - pwms = kzalloc(sizeof(struct pwm_device) * VT8500_NR_PWMS, GFP_KERNEL); - if (pwms == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - for (i = 0; i < VT8500_NR_PWMS; i++) { - pwms[i].use_count = 0; - pwms[i].pwm_id = i; - pwms[i].pdev = pdev; - } - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto err_free; - } - - r = request_mem_region(r->start, resource_size(r), pdev->name); - if (r == NULL) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - ret = -EBUSY; - goto err_free; - } - - pwms[0].regbase = ioremap(r->start, resource_size(r)); - if (pwms[0].regbase == NULL) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); - ret = -ENODEV; - goto err_free_mem; - } - - for (i = 1; i < VT8500_NR_PWMS; i++) - pwms[i].regbase = pwms[0].regbase; - - for (i = 0; i < VT8500_NR_PWMS; i++) - __add_pwm(&pwms[i]); - - platform_set_drvdata(pdev, pwms); - return 0; - -err_free_mem: - release_mem_region(r->start, resource_size(r)); -err_free: - kfree(pwms); - return ret; -} - -static int __devexit pwm_remove(struct platform_device *pdev) -{ - struct pwm_device *pwms; - struct resource *r; - int i; - - pwms = platform_get_drvdata(pdev); - if (pwms == NULL) - return -ENODEV; - - mutex_lock(&pwm_lock); - - for (i = 0; i < VT8500_NR_PWMS; i++) - list_del(&pwms[i].node); - mutex_unlock(&pwm_lock); - - iounmap(pwms[0].regbase); - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(r->start, resource_size(r)); - - kfree(pwms); - return 0; -} - -static struct platform_driver pwm_driver = { - .driver = { - .name = "vt8500-pwm", - .owner = THIS_MODULE, - }, - .probe = pwm_probe, - .remove = __devexit_p(pwm_remove), -}; - -static int __init pwm_init(void) -{ - return platform_driver_register(&pwm_driver); -} -arch_initcall(pwm_init); - -static void __exit pwm_exit(void) -{ - platform_driver_unregister(&pwm_driver); -} -module_exit(pwm_exit); - -MODULE_LICENSE("GPL"); diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 5cfc9899407..c2cdf6500f7 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -22,6 +22,7 @@ #include <linux/memblock.h> #include <linux/slab.h> #include <linux/iommu.h> +#include <linux/io.h> #include <linux/vmalloc.h> #include <linux/sizes.h> @@ -72,7 +73,7 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - if (!arch_is_coherent()) + if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_cpu_to_dev(page, offset, size, dir); return pfn_to_dma(dev, page_to_pfn(page)) + offset; } @@ -95,7 +96,7 @@ static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size, enum dma_data_direction dir, struct dma_attrs *attrs) { - if (!arch_is_coherent()) + if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)), handle & ~PAGE_MASK, size, dir); } @@ -124,6 +125,7 @@ struct dma_map_ops arm_dma_ops = { .alloc = arm_dma_alloc, .free = arm_dma_free, .mmap = arm_dma_mmap, + .get_sgtable = arm_dma_get_sgtable, .map_page = arm_dma_map_page, .unmap_page = arm_dma_unmap_page, .map_sg = arm_dma_map_sg, @@ -217,115 +219,70 @@ static void __dma_free_buffer(struct page *page, size_t size) } #ifdef CONFIG_MMU +#ifdef CONFIG_HUGETLB_PAGE +#error ARM Coherent DMA allocator does not (yet) support huge TLB +#endif -#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT) -#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT) - -/* - * These are the page tables (2MB each) covering uncached, DMA consistent allocations - */ -static pte_t **consistent_pte; - -#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M +static void *__alloc_from_contiguous(struct device *dev, size_t size, + pgprot_t prot, struct page **ret_page); -static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; +static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, + pgprot_t prot, struct page **ret_page, + const void *caller); -void __init init_consistent_dma_size(unsigned long size) +static void * +__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, + const void *caller) { - unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M); + struct vm_struct *area; + unsigned long addr; - BUG_ON(consistent_pte); /* Check we're called before DMA region init */ - BUG_ON(base < VMALLOC_END); + /* + * DMA allocation can be mapped to user space, so lets + * set VM_USERMAP flags too. + */ + area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP, + caller); + if (!area) + return NULL; + addr = (unsigned long)area->addr; + area->phys_addr = __pfn_to_phys(page_to_pfn(page)); - /* Grow region to accommodate specified size */ - if (base < consistent_base) - consistent_base = base; + if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) { + vunmap((void *)addr); + return NULL; + } + return (void *)addr; } -#include "vmregion.h" - -static struct arm_vmregion_head consistent_head = { - .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock), - .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), - .vm_end = CONSISTENT_END, -}; - -#ifdef CONFIG_HUGETLB_PAGE -#error ARM Coherent DMA allocator does not (yet) support huge TLB -#endif - -/* - * Initialise the consistent memory allocation. - */ -static int __init consistent_init(void) +static void __dma_free_remap(void *cpu_addr, size_t size) { - int ret = 0; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - int i = 0; - unsigned long base = consistent_base; - unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT; - - if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) - return 0; - - consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); - if (!consistent_pte) { - pr_err("%s: no memory\n", __func__); - return -ENOMEM; + unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP; + struct vm_struct *area = find_vm_area(cpu_addr); + if (!area || (area->flags & flags) != flags) { + WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); + return; } - - pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END); - consistent_head.vm_start = base; - - do { - pgd = pgd_offset(&init_mm, base); - - pud = pud_alloc(&init_mm, pgd, base); - if (!pud) { - pr_err("%s: no pud tables\n", __func__); - ret = -ENOMEM; - break; - } - - pmd = pmd_alloc(&init_mm, pud, base); - if (!pmd) { - pr_err("%s: no pmd tables\n", __func__); - ret = -ENOMEM; - break; - } - WARN_ON(!pmd_none(*pmd)); - - pte = pte_alloc_kernel(pmd, base); - if (!pte) { - pr_err("%s: no pte tables\n", __func__); - ret = -ENOMEM; - break; - } - - consistent_pte[i++] = pte; - base += PMD_SIZE; - } while (base < CONSISTENT_END); - - return ret; + unmap_kernel_range((unsigned long)cpu_addr, size); + vunmap(cpu_addr); } -core_initcall(consistent_init); -static void *__alloc_from_contiguous(struct device *dev, size_t size, - pgprot_t prot, struct page **ret_page); - -static struct arm_vmregion_head coherent_head = { - .vm_lock = __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock), - .vm_list = LIST_HEAD_INIT(coherent_head.vm_list), +struct dma_pool { + size_t size; + spinlock_t lock; + unsigned long *bitmap; + unsigned long nr_pages; + void *vaddr; + struct page *page; }; -static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8; +static struct dma_pool atomic_pool = { + .size = SZ_256K, +}; static int __init early_coherent_pool(char *p) { - coherent_pool_size = memparse(p, &p); + atomic_pool.size = memparse(p, &p); return 0; } early_param("coherent_pool", early_coherent_pool); @@ -333,32 +290,45 @@ early_param("coherent_pool", early_coherent_pool); /* * Initialise the coherent pool for atomic allocations. */ -static int __init coherent_init(void) +static int __init atomic_pool_init(void) { + struct dma_pool *pool = &atomic_pool; pgprot_t prot = pgprot_dmacoherent(pgprot_kernel); - size_t size = coherent_pool_size; + unsigned long nr_pages = pool->size >> PAGE_SHIFT; + unsigned long *bitmap; struct page *page; void *ptr; + int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long); - if (!IS_ENABLED(CONFIG_CMA)) - return 0; + bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!bitmap) + goto no_bitmap; - ptr = __alloc_from_contiguous(NULL, size, prot, &page); + if (IS_ENABLED(CONFIG_CMA)) + ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page); + else + ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot, + &page, NULL); if (ptr) { - coherent_head.vm_start = (unsigned long) ptr; - coherent_head.vm_end = (unsigned long) ptr + size; - printk(KERN_INFO "DMA: preallocated %u KiB pool for atomic coherent allocations\n", - (unsigned)size / 1024); + spin_lock_init(&pool->lock); + pool->vaddr = ptr; + pool->page = page; + pool->bitmap = bitmap; + pool->nr_pages = nr_pages; + pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n", + (unsigned)pool->size / 1024); return 0; } - printk(KERN_ERR "DMA: failed to allocate %u KiB pool for atomic coherent allocation\n", - (unsigned)size / 1024); + kfree(bitmap); +no_bitmap: + pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n", + (unsigned)pool->size / 1024); return -ENOMEM; } /* * CMA is activated by core_initcall, so we must be called after it. */ -postcore_initcall(coherent_init); +postcore_initcall(atomic_pool_init); struct dma_contig_early_reserve { phys_addr_t base; @@ -406,112 +376,6 @@ void __init dma_contiguous_remap(void) } } -static void * -__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, - const void *caller) -{ - struct arm_vmregion *c; - size_t align; - int bit; - - if (!consistent_pte) { - pr_err("%s: not initialised\n", __func__); - dump_stack(); - return NULL; - } - - /* - * Align the virtual region allocation - maximum alignment is - * a section size, minimum is a page size. This helps reduce - * fragmentation of the DMA space, and also prevents allocations - * smaller than a section from crossing a section boundary. - */ - bit = fls(size - 1); - if (bit > SECTION_SHIFT) - bit = SECTION_SHIFT; - align = 1 << bit; - - /* - * Allocate a virtual address in the consistent mapping region. - */ - c = arm_vmregion_alloc(&consistent_head, align, size, - gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller); - if (c) { - pte_t *pte; - int idx = CONSISTENT_PTE_INDEX(c->vm_start); - u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1); - - pte = consistent_pte[idx] + off; - c->priv = page; - - do { - BUG_ON(!pte_none(*pte)); - - set_pte_ext(pte, mk_pte(page, prot), 0); - page++; - pte++; - off++; - if (off >= PTRS_PER_PTE) { - off = 0; - pte = consistent_pte[++idx]; - } - } while (size -= PAGE_SIZE); - - dsb(); - - return (void *)c->vm_start; - } - return NULL; -} - -static void __dma_free_remap(void *cpu_addr, size_t size) -{ - struct arm_vmregion *c; - unsigned long addr; - pte_t *ptep; - int idx; - u32 off; - - c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr); - if (!c) { - pr_err("%s: trying to free invalid coherent area: %p\n", - __func__, cpu_addr); - dump_stack(); - return; - } - - if ((c->vm_end - c->vm_start) != size) { - pr_err("%s: freeing wrong coherent size (%ld != %d)\n", - __func__, c->vm_end - c->vm_start, size); - dump_stack(); - size = c->vm_end - c->vm_start; - } - - idx = CONSISTENT_PTE_INDEX(c->vm_start); - off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1); - ptep = consistent_pte[idx] + off; - addr = c->vm_start; - do { - pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep); - - ptep++; - addr += PAGE_SIZE; - off++; - if (off >= PTRS_PER_PTE) { - off = 0; - ptep = consistent_pte[++idx]; - } - - if (pte_none(pte) || !pte_present(pte)) - pr_crit("%s: bad page in kernel page table\n", - __func__); - } while (size -= PAGE_SIZE); - - flush_tlb_kernel_range(c->vm_start, c->vm_end); - - arm_vmregion_free(&consistent_head, c); -} - static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr, void *data) { @@ -552,16 +416,17 @@ static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, return ptr; } -static void *__alloc_from_pool(struct device *dev, size_t size, - struct page **ret_page, const void *caller) +static void *__alloc_from_pool(size_t size, struct page **ret_page) { - struct arm_vmregion *c; + struct dma_pool *pool = &atomic_pool; + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + unsigned int pageno; + unsigned long flags; + void *ptr = NULL; size_t align; - if (!coherent_head.vm_start) { - printk(KERN_ERR "%s: coherent pool not initialised!\n", - __func__); - dump_stack(); + if (!pool->vaddr) { + WARN(1, "coherent pool not initialised!\n"); return NULL; } @@ -571,35 +436,41 @@ static void *__alloc_from_pool(struct device *dev, size_t size, * size. This helps reduce fragmentation of the DMA space. */ align = PAGE_SIZE << get_order(size); - c = arm_vmregion_alloc(&coherent_head, align, size, 0, caller); - if (c) { - void *ptr = (void *)c->vm_start; - struct page *page = virt_to_page(ptr); - *ret_page = page; - return ptr; + + spin_lock_irqsave(&pool->lock, flags); + pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages, + 0, count, (1 << align) - 1); + if (pageno < pool->nr_pages) { + bitmap_set(pool->bitmap, pageno, count); + ptr = pool->vaddr + PAGE_SIZE * pageno; + *ret_page = pool->page + pageno; } - return NULL; + spin_unlock_irqrestore(&pool->lock, flags); + + return ptr; } -static int __free_from_pool(void *cpu_addr, size_t size) +static int __free_from_pool(void *start, size_t size) { - unsigned long start = (unsigned long)cpu_addr; - unsigned long end = start + size; - struct arm_vmregion *c; + struct dma_pool *pool = &atomic_pool; + unsigned long pageno, count; + unsigned long flags; - if (start < coherent_head.vm_start || end > coherent_head.vm_end) + if (start < pool->vaddr || start > pool->vaddr + pool->size) return 0; - c = arm_vmregion_find_remove(&coherent_head, (unsigned long)start); - - if ((c->vm_end - c->vm_start) != size) { - printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n", - __func__, c->vm_end - c->vm_start, size); - dump_stack(); - size = c->vm_end - c->vm_start; + if (start + size > pool->vaddr + pool->size) { + WARN(1, "freeing wrong coherent size from pool\n"); + return 0; } - arm_vmregion_free(&coherent_head, c); + pageno = (start - pool->vaddr) >> PAGE_SHIFT; + count = size >> PAGE_SHIFT; + + spin_lock_irqsave(&pool->lock, flags); + bitmap_clear(pool->bitmap, pageno, count); + spin_unlock_irqrestore(&pool->lock, flags); + return 1; } @@ -644,7 +515,7 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot) #define __get_dma_pgprot(attrs, prot) __pgprot(0) #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c) NULL -#define __alloc_from_pool(dev, size, ret_page, c) NULL +#define __alloc_from_pool(size, ret_page) NULL #define __alloc_from_contiguous(dev, size, prot, ret) NULL #define __free_from_pool(cpu_addr, size) 0 #define __free_from_contiguous(dev, page, size) do { } while (0) @@ -702,10 +573,10 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, if (arch_is_coherent() || nommu()) addr = __alloc_simple_buffer(dev, size, gfp, &page); + else if (gfp & GFP_ATOMIC) + addr = __alloc_from_pool(size, &page); else if (!IS_ENABLED(CONFIG_CMA)) addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); - else if (gfp & GFP_ATOMIC) - addr = __alloc_from_pool(dev, size, &page, caller); else addr = __alloc_from_contiguous(dev, size, prot, &page); @@ -741,16 +612,22 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma, { int ret = -ENXIO; #ifdef CONFIG_MMU + unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; unsigned long pfn = dma_to_pfn(dev, dma_addr); + unsigned long off = vma->vm_pgoff; + vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot); if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) return ret; - ret = remap_pfn_range(vma, vma->vm_start, - pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); + if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) { + ret = remap_pfn_range(vma, vma->vm_start, + pfn + off, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + } #endif /* CONFIG_MMU */ return ret; @@ -785,6 +662,21 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr, } } +int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size, + struct dma_attrs *attrs) +{ + struct page *page = pfn_to_page(dma_to_pfn(dev, handle)); + int ret; + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (unlikely(ret)) + return ret; + + sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); + return 0; +} + static void dma_cache_maint_page(struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, void (*op)(const void *, size_t, int)) @@ -998,9 +890,6 @@ static int arm_dma_set_mask(struct device *dev, u64 dma_mask) static int __init dma_debug_do_init(void) { -#ifdef CONFIG_MMU - arm_vmregion_create_proc("dma-mappings", &consistent_head); -#endif dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); return 0; } @@ -1088,7 +977,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t return pages; error: - while (--i) + while (i--) if (pages[i]) __free_pages(pages[i], 0); if (array_size <= PAGE_SIZE) @@ -1117,61 +1006,32 @@ static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t s * Create a CPU mapping for a specified pages */ static void * -__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot) +__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot, + const void *caller) { - struct arm_vmregion *c; - size_t align; - size_t count = size >> PAGE_SHIFT; - int bit; + unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; + struct vm_struct *area; + unsigned long p; - if (!consistent_pte[0]) { - pr_err("%s: not initialised\n", __func__); - dump_stack(); + area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP, + caller); + if (!area) return NULL; - } - - /* - * Align the virtual region allocation - maximum alignment is - * a section size, minimum is a page size. This helps reduce - * fragmentation of the DMA space, and also prevents allocations - * smaller than a section from crossing a section boundary. - */ - bit = fls(size - 1); - if (bit > SECTION_SHIFT) - bit = SECTION_SHIFT; - align = 1 << bit; - - /* - * Allocate a virtual address in the consistent mapping region. - */ - c = arm_vmregion_alloc(&consistent_head, align, size, - gfp & ~(__GFP_DMA | __GFP_HIGHMEM), NULL); - if (c) { - pte_t *pte; - int idx = CONSISTENT_PTE_INDEX(c->vm_start); - int i = 0; - u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1); - - pte = consistent_pte[idx] + off; - c->priv = pages; - - do { - BUG_ON(!pte_none(*pte)); - - set_pte_ext(pte, mk_pte(pages[i], prot), 0); - pte++; - off++; - i++; - if (off >= PTRS_PER_PTE) { - off = 0; - pte = consistent_pte[++idx]; - } - } while (i < count); - dsb(); + area->pages = pages; + area->nr_pages = nr_pages; + p = (unsigned long)area->addr; - return (void *)c->vm_start; + for (i = 0; i < nr_pages; i++) { + phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i])); + if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot)) + goto err; + p += PAGE_SIZE; } + return area->addr; +err: + unmap_kernel_range((unsigned long)area->addr, size); + vunmap(area->addr); return NULL; } @@ -1230,6 +1090,19 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si return 0; } +static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs) +{ + struct vm_struct *area; + + if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) + return cpu_addr; + + area = find_vm_area(cpu_addr); + if (area && (area->flags & VM_ARM_DMA_CONSISTENT)) + return area->pages; + return NULL; +} + static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) { @@ -1248,7 +1121,11 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, if (*handle == DMA_ERROR_CODE) goto err_buffer; - addr = __iommu_alloc_remap(pages, size, gfp, prot); + if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) + return pages; + + addr = __iommu_alloc_remap(pages, size, gfp, prot, + __builtin_return_address(0)); if (!addr) goto err_mapping; @@ -1265,31 +1142,25 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs) { - struct arm_vmregion *c; + unsigned long uaddr = vma->vm_start; + unsigned long usize = vma->vm_end - vma->vm_start; + struct page **pages = __iommu_get_pages(cpu_addr, attrs); vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot); - c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr); - - if (c) { - struct page **pages = c->priv; - - unsigned long uaddr = vma->vm_start; - unsigned long usize = vma->vm_end - vma->vm_start; - int i = 0; - do { - int ret; + if (!pages) + return -ENXIO; - ret = vm_insert_page(vma, uaddr, pages[i++]); - if (ret) { - pr_err("Remapping memory, error: %d\n", ret); - return ret; - } + do { + int ret = vm_insert_page(vma, uaddr, *pages++); + if (ret) { + pr_err("Remapping memory failed: %d\n", ret); + return ret; + } + uaddr += PAGE_SIZE; + usize -= PAGE_SIZE; + } while (usize > 0); - uaddr += PAGE_SIZE; - usize -= PAGE_SIZE; - } while (usize > 0); - } return 0; } @@ -1300,16 +1171,35 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs) { - struct arm_vmregion *c; + struct page **pages = __iommu_get_pages(cpu_addr, attrs); size = PAGE_ALIGN(size); - c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr); - if (c) { - struct page **pages = c->priv; - __dma_free_remap(cpu_addr, size); - __iommu_remove_mapping(dev, handle, size); - __iommu_free_buffer(dev, pages, size); + if (!pages) { + WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); + return; } + + if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) { + unmap_kernel_range((unsigned long)cpu_addr, size); + vunmap(cpu_addr); + } + + __iommu_remove_mapping(dev, handle, size); + __iommu_free_buffer(dev, pages, size); +} + +static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t dma_addr, + size_t size, struct dma_attrs *attrs) +{ + unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; + struct page **pages = __iommu_get_pages(cpu_addr, attrs); + + if (!pages) + return -ENXIO; + + return sg_alloc_table_from_pages(sgt, pages, count, 0, size, + GFP_KERNEL); } /* @@ -1317,7 +1207,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, */ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, size_t size, dma_addr_t *handle, - enum dma_data_direction dir) + enum dma_data_direction dir, struct dma_attrs *attrs) { struct dma_iommu_mapping *mapping = dev->archdata.mapping; dma_addr_t iova, iova_base; @@ -1336,7 +1226,8 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, phys_addr_t phys = page_to_phys(sg_page(s)); unsigned int len = PAGE_ALIGN(s->offset + s->length); - if (!arch_is_coherent()) + if (!arch_is_coherent() && + !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir); ret = iommu_map(mapping->domain, iova, phys, len, 0); @@ -1383,7 +1274,7 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents, if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) { if (__map_sg_chunk(dev, start, size, &dma->dma_address, - dir) < 0) + dir, attrs) < 0) goto bad_mapping; dma->dma_address += offset; @@ -1396,7 +1287,7 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents, } size += s->length; } - if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir) < 0) + if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir, attrs) < 0) goto bad_mapping; dma->dma_address += offset; @@ -1430,7 +1321,8 @@ void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, if (sg_dma_len(s)) __iommu_remove_mapping(dev, sg_dma_address(s), sg_dma_len(s)); - if (!arch_is_coherent()) + if (!arch_is_coherent() && + !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir); } @@ -1492,7 +1384,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page, dma_addr_t dma_addr; int ret, len = PAGE_ALIGN(size + offset); - if (!arch_is_coherent()) + if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_cpu_to_dev(page, offset, size, dir); dma_addr = __alloc_iova(mapping, len); @@ -1531,7 +1423,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle, if (!iova) return; - if (!arch_is_coherent()) + if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_dev_to_cpu(page, offset, size, dir); iommu_unmap(mapping->domain, iova, len); @@ -1571,6 +1463,7 @@ struct dma_map_ops iommu_ops = { .alloc = arm_iommu_alloc_attrs, .free = arm_iommu_free_attrs, .mmap = arm_iommu_mmap_attrs, + .get_sgtable = arm_iommu_get_sgtable, .map_page = arm_iommu_map_page, .unmap_page = arm_iommu_unmap_page, diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 2e8a1efdf7b..6776160618e 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -59,6 +59,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #define VM_ARM_MTYPE(mt) ((mt) << 20) #define VM_ARM_MTYPE_MASK (0x1f << 20) +/* consistent regions used by dma_alloc_attrs() */ +#define VM_ARM_DMA_CONSISTENT 0x20000000 + #endif #ifdef CONFIG_ZONE_DMA diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index c722f9ce691..baf9064c084 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -47,12 +47,6 @@ config MXC_TZIC config MXC_AVIC bool -config MXC_PWM - tristate "Enable PWM driver" - select HAVE_PWM - help - Enable support for the i.MX PWM controller(s). - config MXC_DEBUG_BOARD bool "Enable MXC debug board(for 3-stack)" help diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile index 63b064b5c1d..6ac72003115 100644 --- a/arch/arm/plat-mxc/Makefile +++ b/arch/arm/plat-mxc/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_MXC_AVIC) += avic.o obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o -obj-$(CONFIG_MXC_PWM) += pwm.o obj-$(CONFIG_MXC_ULPI) += ulpi.o obj-$(CONFIG_MXC_USE_EPIT) += epit.o obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index f302d048392..af8e484001e 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -8,5 +8,4 @@ obj-$(CONFIG_PXA3xx) += mfp.o obj-$(CONFIG_PXA95x) += mfp.o obj-$(CONFIG_ARCH_MMP) += mfp.o -obj-$(CONFIG_HAVE_PWM) += pwm.o obj-$(CONFIG_PXA_SSP) += ssp.o diff --git a/arch/arm/plat-pxa/pwm.c b/arch/arm/plat-pxa/pwm.c deleted file mode 100644 index ef32686feef..00000000000 --- a/arch/arm/plat-pxa/pwm.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/pwm.c - * - * simple driver for PWM (Pulse Width Modulator) controller - * - * 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. - * - * 2008-02-13 initial version - * eric miao <eric.miao@marvell.com> - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/pwm.h> - -#include <asm/div64.h> - -#define HAS_SECONDARY_PWM 0x10 -#define PWM_ID_BASE(d) ((d) & 0xf) - -static const struct platform_device_id pwm_id_table[] = { - /* PWM has_secondary_pwm? */ - { "pxa25x-pwm", 0 }, - { "pxa27x-pwm", 0 | HAS_SECONDARY_PWM }, - { "pxa168-pwm", 1 }, - { "pxa910-pwm", 1 }, - { }, -}; -MODULE_DEVICE_TABLE(platform, pwm_id_table); - -/* PWM registers and bits definitions */ -#define PWMCR (0x00) -#define PWMDCR (0x04) -#define PWMPCR (0x08) - -#define PWMCR_SD (1 << 6) -#define PWMDCR_FD (1 << 10) - -struct pwm_device { - struct list_head node; - struct pwm_device *secondary; - struct platform_device *pdev; - - const char *label; - struct clk *clk; - int clk_enabled; - void __iomem *mmio_base; - - unsigned int use_count; - unsigned int pwm_id; -}; - -/* - * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE - * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE - */ -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) -{ - unsigned long long c; - unsigned long period_cycles, prescale, pv, dc; - - if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) - return -EINVAL; - - c = clk_get_rate(pwm->clk); - c = c * period_ns; - do_div(c, 1000000000); - period_cycles = c; - - if (period_cycles < 1) - period_cycles = 1; - prescale = (period_cycles - 1) / 1024; - pv = period_cycles / (prescale + 1) - 1; - - if (prescale > 63) - return -EINVAL; - - if (duty_ns == period_ns) - dc = PWMDCR_FD; - else - dc = (pv + 1) * duty_ns / period_ns; - - /* NOTE: the clock to PWM has to be enabled first - * before writing to the registers - */ - clk_enable(pwm->clk); - __raw_writel(prescale, pwm->mmio_base + PWMCR); - __raw_writel(dc, pwm->mmio_base + PWMDCR); - __raw_writel(pv, pwm->mmio_base + PWMPCR); - clk_disable(pwm->clk); - - return 0; -} -EXPORT_SYMBOL(pwm_config); - -int pwm_enable(struct pwm_device *pwm) -{ - int rc = 0; - - if (!pwm->clk_enabled) { - rc = clk_enable(pwm->clk); - if (!rc) - pwm->clk_enabled = 1; - } - return rc; -} -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) -{ - if (pwm->clk_enabled) { - clk_disable(pwm->clk); - pwm->clk_enabled = 0; - } -} -EXPORT_SYMBOL(pwm_disable); - -static DEFINE_MUTEX(pwm_lock); -static LIST_HEAD(pwm_list); - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int found = 0; - - mutex_lock(&pwm_lock); - - list_for_each_entry(pwm, &pwm_list, node) { - if (pwm->pwm_id == pwm_id) { - found = 1; - break; - } - } - - if (found) { - if (pwm->use_count == 0) { - pwm->use_count++; - pwm->label = label; - } else - pwm = ERR_PTR(-EBUSY); - } else - pwm = ERR_PTR(-ENOENT); - - mutex_unlock(&pwm_lock); - return pwm; -} -EXPORT_SYMBOL(pwm_request); - -void pwm_free(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - - if (pwm->use_count) { - pwm->use_count--; - pwm->label = NULL; - } else - pr_warning("PWM device already freed\n"); - - mutex_unlock(&pwm_lock); -} -EXPORT_SYMBOL(pwm_free); - -static inline void __add_pwm(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - list_add_tail(&pwm->node, &pwm_list); - mutex_unlock(&pwm_lock); -} - -static int __devinit pwm_probe(struct platform_device *pdev) -{ - const struct platform_device_id *id = platform_get_device_id(pdev); - struct pwm_device *pwm, *secondary = NULL; - struct resource *r; - int ret = 0; - - pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); - if (pwm == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - pwm->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) { - ret = PTR_ERR(pwm->clk); - goto err_free; - } - pwm->clk_enabled = 0; - - pwm->use_count = 0; - pwm->pwm_id = PWM_ID_BASE(id->driver_data) + pdev->id; - pwm->pdev = pdev; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto err_free_clk; - } - - r = request_mem_region(r->start, resource_size(r), pdev->name); - if (r == NULL) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - ret = -EBUSY; - goto err_free_clk; - } - - pwm->mmio_base = ioremap(r->start, resource_size(r)); - if (pwm->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); - ret = -ENODEV; - goto err_free_mem; - } - - if (id->driver_data & HAS_SECONDARY_PWM) { - secondary = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); - if (secondary == NULL) { - ret = -ENOMEM; - goto err_free_mem; - } - - *secondary = *pwm; - pwm->secondary = secondary; - - /* registers for the second PWM has offset of 0x10 */ - secondary->mmio_base = pwm->mmio_base + 0x10; - secondary->pwm_id = pdev->id + 2; - } - - __add_pwm(pwm); - if (secondary) - __add_pwm(secondary); - - platform_set_drvdata(pdev, pwm); - return 0; - -err_free_mem: - release_mem_region(r->start, resource_size(r)); -err_free_clk: - clk_put(pwm->clk); -err_free: - kfree(pwm); - return ret; -} - -static int __devexit pwm_remove(struct platform_device *pdev) -{ - struct pwm_device *pwm; - struct resource *r; - - pwm = platform_get_drvdata(pdev); - if (pwm == NULL) - return -ENODEV; - - mutex_lock(&pwm_lock); - - if (pwm->secondary) { - list_del(&pwm->secondary->node); - kfree(pwm->secondary); - } - - list_del(&pwm->node); - mutex_unlock(&pwm_lock); - - iounmap(pwm->mmio_base); - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(r->start, resource_size(r)); - - clk_put(pwm->clk); - kfree(pwm); - return 0; -} - -static struct platform_driver pwm_driver = { - .driver = { - .name = "pxa25x-pwm", - .owner = THIS_MODULE, - }, - .probe = pwm_probe, - .remove = __devexit_p(pwm_remove), - .id_table = pwm_id_table, -}; - -static int __init pwm_init(void) -{ - return platform_driver_register(&pwm_driver); -} -arch_initcall(pwm_init); - -static void __exit pwm_exit(void) -{ - platform_driver_unregister(&pwm_driver); -} -module_exit(pwm_exit); - -MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index b7871749667..9e40e8d0074 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -59,7 +59,3 @@ obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o obj-$(CONFIG_S5P_PM) += s5p-pm.o s5p-irq-pm.o obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o - -# PWM support - -obj-$(CONFIG_HAVE_PWM) += pwm.o diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index fb9fe00e51a..f3486192063 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -1003,16 +1003,6 @@ config BFIN_GPTIMERS To compile this driver as a module, choose M here: the module will be called gptimers. -config HAVE_PWM - tristate "Enable PWM API support" - depends on BFIN_GPTIMERS - help - Enable support for the Pulse Width Modulation framework (as - found in linux/pwm.h). - - To compile this driver as a module, choose M here: the module - will be called pwm. - choice prompt "Uncached DMA region" default DMA_UNCACHED_1M diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 08e6625106b..735f24e0742 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o CFLAGS_REMOVE_ftrace.o = -pg -obj-$(CONFIG_HAVE_PWM) += pwm.o obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o obj-$(CONFIG_CPLB_INFO) += cplbinfo.o diff --git a/arch/blackfin/kernel/pwm.c b/arch/blackfin/kernel/pwm.c deleted file mode 100644 index 33f5942733b..00000000000 --- a/arch/blackfin/kernel/pwm.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Blackfin Pulse Width Modulation (PWM) core - * - * Copyright (c) 2011 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/pwm.h> -#include <linux/slab.h> - -#include <asm/gptimers.h> -#include <asm/portmux.h> - -struct pwm_device { - unsigned id; - unsigned short pin; -}; - -static const unsigned short pwm_to_gptimer_per[] = { - P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5, - P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11, -}; - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int ret; - - /* XXX: pwm_id really should be unsigned */ - if (pwm_id < 0) - return NULL; - - pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); - if (!pwm) - return pwm; - - pwm->id = pwm_id; - if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per)) - goto err; - - pwm->pin = pwm_to_gptimer_per[pwm->id]; - ret = peripheral_request(pwm->pin, label); - if (ret) - goto err; - - return pwm; - err: - kfree(pwm); - return NULL; -} -EXPORT_SYMBOL(pwm_request); - -void pwm_free(struct pwm_device *pwm) -{ - peripheral_free(pwm->pin); - kfree(pwm); -} -EXPORT_SYMBOL(pwm_free); - -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) -{ - unsigned long period, duty; - unsigned long long val; - - if (duty_ns < 0 || duty_ns > period_ns) - return -EINVAL; - - val = (unsigned long long)get_sclk() * period_ns; - do_div(val, NSEC_PER_SEC); - period = val; - - val = (unsigned long long)period * duty_ns; - do_div(val, period_ns); - duty = period - val; - - if (duty >= period) - duty = period - 1; - - set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT); - set_gptimer_pwidth(pwm->id, duty); - set_gptimer_period(pwm->id, period); - - return 0; -} -EXPORT_SYMBOL(pwm_config); - -int pwm_enable(struct pwm_device *pwm) -{ - enable_gptimer(pwm->id); - return 0; -} -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) -{ - disable_gptimer(pwm->id); -} -EXPORT_SYMBOL(pwm_disable); diff --git a/arch/frv/include/asm/cpumask.h b/arch/frv/include/asm/cpumask.h deleted file mode 100644 index d999c20c84d..00000000000 --- a/arch/frv/include/asm/cpumask.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_CPUMASK_H -#define _ASM_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _ASM_CPUMASK_H */ diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 9aa17f1917e..06906427c0a 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -7,7 +7,6 @@ header-y += user.h generic-y += auxvec.h generic-y += bug.h generic-y += bugs.h -generic-y += cpumask.h generic-y += cputime.h generic-y += current.h generic-y += device.h @@ -23,7 +22,6 @@ generic-y += ioctl.h generic-y += ioctls.h generic-y += iomap.h generic-y += ipcbuf.h -generic-y += ipc.h generic-y += irq_regs.h generic-y += kdebug.h generic-y += kmap_types.h diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 8186ec5ea15..310cf5781fa 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -126,6 +126,7 @@ config AUDIT_ARCH menuconfig PARAVIRT_GUEST bool "Paravirtualized guest support" + depends on BROKEN help Say Y here to get to see options related to running Linux under various hypervisors. This option alone does not add any kernel code. @@ -138,8 +139,6 @@ config PARAVIRT bool "Enable paravirtualization code" depends on PARAVIRT_GUEST default y - bool - default y help This changes the kernel so it can modify itself when it is run under a hypervisor, potentially improving performance significantly diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 7d9116600a3..6e6fe1839f5 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -17,8 +17,8 @@ #include <asm/intrinsics.h> -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h index 367d299d993..2d1ad4b11a8 100644 --- a/arch/ia64/include/asm/machvec.h +++ b/arch/ia64/include/asm/machvec.h @@ -120,7 +120,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # ifdef MACHVEC_PLATFORM_HEADER # include MACHVEC_PLATFORM_HEADER # else -# define platform_name ia64_mv.name +# define ia64_platform_name ia64_mv.name # define platform_setup ia64_mv.setup # define platform_cpu_init ia64_mv.cpu_init # define platform_irq_init ia64_mv.irq_init diff --git a/arch/ia64/include/asm/machvec_dig.h b/arch/ia64/include/asm/machvec_dig.h index 8a0752f4098..1f7403a2fbe 100644 --- a/arch/ia64/include/asm/machvec_dig.h +++ b/arch/ia64/include/asm/machvec_dig.h @@ -10,7 +10,7 @@ extern ia64_mv_setup_t dig_setup; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "dig" +#define ia64_platform_name "dig" #define platform_setup dig_setup #endif /* _ASM_IA64_MACHVEC_DIG_h */ diff --git a/arch/ia64/include/asm/machvec_dig_vtd.h b/arch/ia64/include/asm/machvec_dig_vtd.h index 6ab1de5c45e..44308b4c3f6 100644 --- a/arch/ia64/include/asm/machvec_dig_vtd.h +++ b/arch/ia64/include/asm/machvec_dig_vtd.h @@ -11,7 +11,7 @@ extern ia64_mv_dma_init pci_iommu_alloc; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "dig_vtd" +#define ia64_platform_name "dig_vtd" #define platform_setup dig_setup #define platform_dma_init pci_iommu_alloc diff --git a/arch/ia64/include/asm/machvec_hpsim.h b/arch/ia64/include/asm/machvec_hpsim.h index cf72fc87fdf..e7571127936 100644 --- a/arch/ia64/include/asm/machvec_hpsim.h +++ b/arch/ia64/include/asm/machvec_hpsim.h @@ -11,7 +11,7 @@ extern ia64_mv_irq_init_t hpsim_irq_init; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "hpsim" +#define ia64_platform_name "hpsim" #define platform_setup hpsim_setup #define platform_irq_init hpsim_irq_init diff --git a/arch/ia64/include/asm/machvec_hpzx1.h b/arch/ia64/include/asm/machvec_hpzx1.h index 3bd83d78a41..c74d3159e9e 100644 --- a/arch/ia64/include/asm/machvec_hpzx1.h +++ b/arch/ia64/include/asm/machvec_hpzx1.h @@ -11,7 +11,7 @@ extern ia64_mv_dma_init sba_dma_init; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "hpzx1" +#define ia64_platform_name "hpzx1" #define platform_setup dig_setup #define platform_dma_init sba_dma_init diff --git a/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h b/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h index 1091ac39740..906ef621077 100644 --- a/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h +++ b/arch/ia64/include/asm/machvec_hpzx1_swiotlb.h @@ -11,7 +11,7 @@ extern ia64_mv_dma_get_ops hwsw_dma_get_ops; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "hpzx1_swiotlb" +#define ia64_platform_name "hpzx1_swiotlb" #define platform_setup dig_setup #define platform_dma_init machvec_noop #define platform_dma_get_ops hwsw_dma_get_ops diff --git a/arch/ia64/include/asm/machvec_sn2.h b/arch/ia64/include/asm/machvec_sn2.h index f061a30aac4..ece9fa85be8 100644 --- a/arch/ia64/include/asm/machvec_sn2.h +++ b/arch/ia64/include/asm/machvec_sn2.h @@ -71,7 +71,7 @@ extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "sn2" +#define ia64_platform_name "sn2" #define platform_setup sn_setup #define platform_cpu_init sn_cpu_init #define platform_irq_init sn_irq_init diff --git a/arch/ia64/include/asm/machvec_uv.h b/arch/ia64/include/asm/machvec_uv.h index 2931447f381..2c50853f35a 100644 --- a/arch/ia64/include/asm/machvec_uv.h +++ b/arch/ia64/include/asm/machvec_uv.h @@ -20,7 +20,7 @@ extern ia64_mv_setup_t uv_setup; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "uv" +#define ia64_platform_name "uv" #define platform_setup uv_setup #endif /* _ASM_IA64_MACHVEC_UV_H */ diff --git a/arch/ia64/include/asm/machvec_xen.h b/arch/ia64/include/asm/machvec_xen.h index 55f9228056c..8b8bd0eb392 100644 --- a/arch/ia64/include/asm/machvec_xen.h +++ b/arch/ia64/include/asm/machvec_xen.h @@ -13,7 +13,7 @@ extern ia64_mv_send_ipi_t xen_platform_send_ipi; * platform's machvec structure. When compiling a non-generic kernel, * the macros are used directly. */ -#define platform_name "xen" +#define ia64_platform_name "xen" #define platform_setup dig_setup #define platform_cpu_init xen_cpu_init #define platform_irq_init xen_irq_init diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 832dd3789e9..944152a5091 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -719,7 +719,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT, void default_idle(void); -#define ia64_platform_is(x) (strcmp(x, platform_name) == 0) +#define ia64_platform_is(x) (strcmp(x, ia64_platform_name) == 0) #endif /* !__ASSEMBLY__ */ diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index df5351e3eed..e7947528aee 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -23,6 +23,7 @@ config KVM depends on HAVE_KVM && MODULES && EXPERIMENTAL # for device assignment: depends on PCI + depends on BROKEN select PREEMPT_NOTIFIERS select ANON_INODES select HAVE_KVM_IRQCHIP diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c index f5959c0c181..eab28e31402 100644 --- a/arch/ia64/pci/fixup.c +++ b/arch/ia64/pci/fixup.c @@ -30,8 +30,8 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) struct pci_bus *bus; u16 config; - if ((strcmp(platform_name, "dig") != 0) - && (strcmp(platform_name, "hpzx1") != 0)) + if ((strcmp(ia64_platform_name, "dig") != 0) + && (strcmp(ia64_platform_name, "hpzx1") != 0)) return; /* Maybe, this machine supports legacy memory map. */ diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 5ce8029f558..d64786d5e2f 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -14,6 +14,7 @@ platforms += jz4740 platforms += lantiq platforms += lasat platforms += loongson +platforms += loongson1 platforms += mipssim platforms += mti-malta platforms += netlogic diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2d56cd5af33..e3efc06e640 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -211,6 +211,7 @@ config MACH_JZ4740 select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_ZBOOT_UART16550 select DMA_NONCOHERENT select IRQ_CPU select GENERIC_GPIO @@ -266,6 +267,16 @@ config MACH_LOONGSON Chinese Academy of Sciences (CAS) in the People's Republic of China. The chief architect is Professor Weiwu Hu. +config MACH_LOONGSON1 + bool "Loongson 1 family of machines" + select SYS_SUPPORTS_ZBOOT + help + This enables support for the Loongson 1 based machines. + + Loongson 1 is a family of 32-bit MIPS-compatible SoCs developed by + the ICT (Institute of Computing Technology) and the Chinese Academy + of Sciences. + config MIPS_MALTA bool "MIPS Malta board" select ARCH_MAY_HAVE_PC_FDC @@ -789,6 +800,8 @@ config NLM_XLR_BOARD select ZONE_DMA if 64BIT select SYNC_R4K select SYS_HAS_EARLY_PRINTK + select USB_ARCH_HAS_OHCI if USB_SUPPORT + select USB_ARCH_HAS_EHCI if USB_SUPPORT help Support for systems based on Netlogic XLR and XLS processors. Say Y here if you have a XLR or XLS based board. @@ -801,7 +814,6 @@ config NLM_XLP_BOARD select SYS_HAS_CPU_XLP select SYS_SUPPORTS_SMP select HW_HAS_PCI - select SWAP_IO_SPACE select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select 64BIT_PHYS_ADDR @@ -838,6 +850,7 @@ source "arch/mips/txx9/Kconfig" source "arch/mips/vr41xx/Kconfig" source "arch/mips/cavium-octeon/Kconfig" source "arch/mips/loongson/Kconfig" +source "arch/mips/loongson1/Kconfig" source "arch/mips/netlogic/Kconfig" endmenu @@ -1219,6 +1232,14 @@ config CPU_LOONGSON2F have a similar programming interface with FPGA northbridge used in Loongson2E. +config CPU_LOONGSON1B + bool "Loongson 1B" + depends on SYS_HAS_CPU_LOONGSON1B + select CPU_LOONGSON1 + help + The Loongson 1B is a 32-bit SoC, which implements the MIPS32 + release 2 instruction set. + config CPU_MIPS32_R1 bool "MIPS32 Release 1" depends on SYS_HAS_CPU_MIPS32_R1 @@ -1434,6 +1455,8 @@ config CPU_CAVIUM_OCTEON select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES + select LIBFDT + select USE_OF help The Cavium Octeon processor is a highly integrated chip containing many ethernet hardware widgets for networking tasks. The processor @@ -1546,6 +1569,14 @@ config CPU_LOONGSON2 select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_HIGHMEM +config CPU_LOONGSON1 + bool + select CPU_MIPS32 + select CPU_MIPSR2 + select CPU_HAS_PREFETCH + select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM + config CPU_BMIPS bool select CPU_MIPS32 @@ -1564,6 +1595,9 @@ config SYS_HAS_CPU_LOONGSON2F select CPU_SUPPORTS_ADDRWINCFG if 64BIT select CPU_SUPPORTS_UNCACHED_ACCELERATED +config SYS_HAS_CPU_LOONGSON1B + bool + config SYS_HAS_CPU_MIPS32_R1 bool @@ -2368,6 +2402,8 @@ config PCI_DOMAINS source "drivers/pci/Kconfig" +source "drivers/pci/pcie/Kconfig" + # # ISA support is now enabled via select. Too many systems still have the one # or other ISA chip on the board that users don't know about so don't expect diff --git a/arch/mips/alchemy/board-mtx1.c b/arch/mips/alchemy/board-mtx1.c index 295f1a95f74..99969484c47 100644 --- a/arch/mips/alchemy/board-mtx1.c +++ b/arch/mips/alchemy/board-mtx1.c @@ -81,10 +81,10 @@ static void mtx1_power_off(void) void __init board_setup(void) { -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +#if IS_ENABLED(CONFIG_USB_OHCI_HCD) /* Enable USB power switch */ alchemy_gpio_direction_output(204, 0); -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ +#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */ /* Initialize sys_pinfunc */ au_writel(SYS_PF_NI2, SYS_PINFUNC); diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c index 95cb9113b12..c0f3ce6dcb5 100644 --- a/arch/mips/alchemy/common/platform.c +++ b/arch/mips/alchemy/common/platform.c @@ -334,13 +334,12 @@ static void __init alchemy_setup_macs(int ctype) if (alchemy_get_macs(ctype) < 1) return; - macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); + macres = kmemdup(au1xxx_eth0_resources[ctype], + sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); if (!macres) { printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n"); return; } - memcpy(macres, au1xxx_eth0_resources[ctype], - sizeof(struct resource) * MAC_RES_COUNT); au1xxx_eth0_device.resource = macres; i = prom_get_ethernet_addr(ethaddr); @@ -356,13 +355,12 @@ static void __init alchemy_setup_macs(int ctype) if (alchemy_get_macs(ctype) < 2) return; - macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); + macres = kmemdup(au1xxx_eth1_resources[ctype], + sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); if (!macres) { printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n"); return; } - memcpy(macres, au1xxx_eth1_resources[ctype], - sizeof(struct resource) * MAC_RES_COUNT); au1xxx_eth1_device.resource = macres; ethaddr[5] += 1; /* next addr for 2nd MAC */ diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile index 3c37fb30336..c9e747dd9fc 100644 --- a/arch/mips/alchemy/devboards/Makefile +++ b/arch/mips/alchemy/devboards/Makefile @@ -2,7 +2,7 @@ # Alchemy Develboards # -obj-y += prom.o bcsr.o platform.o +obj-y += bcsr.o platform.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_MIPS_PB1100) += pb1100.o obj-$(CONFIG_MIPS_PB1500) += pb1500.o diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c index 1e83ce2e114..f2039ef2c29 100644 --- a/arch/mips/alchemy/devboards/bcsr.c +++ b/arch/mips/alchemy/devboards/bcsr.c @@ -90,10 +90,7 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT); disable_irq_nosync(irq); - - for ( ; bisr; bisr &= bisr - 1) - generic_handle_irq(bcsr_csc_base + __ffs(bisr)); - + generic_handle_irq(bcsr_csc_base + __ffs(bisr)); enable_irq(irq); } diff --git a/arch/mips/alchemy/devboards/pb1100.c b/arch/mips/alchemy/devboards/pb1100.c index cff50d05ddd..78c77a44a31 100644 --- a/arch/mips/alchemy/devboards/pb1100.c +++ b/arch/mips/alchemy/devboards/pb1100.c @@ -46,7 +46,7 @@ void __init board_setup(void) alchemy_gpio1_input_enable(); udelay(100); -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +#if IS_ENABLED(CONFIG_USB_OHCI_HCD) { u32 pin_func, sys_freqctrl, sys_clksrc; @@ -93,7 +93,7 @@ void __init board_setup(void) pin_func |= SYS_PF_USB; au_writel(pin_func, SYS_PINFUNC); } -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ +#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */ /* Enable sys bus clock divider when IDLE state or no bus activity. */ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); diff --git a/arch/mips/alchemy/devboards/pb1500.c b/arch/mips/alchemy/devboards/pb1500.c index e7b807b3ec5..232fee94200 100644 --- a/arch/mips/alchemy/devboards/pb1500.c +++ b/arch/mips/alchemy/devboards/pb1500.c @@ -53,7 +53,7 @@ void __init board_setup(void) alchemy_gpio_direction_input(201); alchemy_gpio_direction_input(203); -#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +#if IS_ENABLED(CONFIG_USB_OHCI_HCD) /* Zero and disable FREQ2 */ sys_freqctrl = au_readl(SYS_FREQCTRL0); @@ -87,7 +87,7 @@ void __init board_setup(void) /* 2nd USB port is USB host */ pin_func |= SYS_PF_USB; au_writel(pin_func, SYS_PINFUNC); -#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ +#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */ #ifdef CONFIG_PCI { diff --git a/arch/mips/alchemy/devboards/platform.c b/arch/mips/alchemy/devboards/platform.c index 621f70afb63..f39042e99d0 100644 --- a/arch/mips/alchemy/devboards/platform.c +++ b/arch/mips/alchemy/devboards/platform.c @@ -10,9 +10,39 @@ #include <linux/platform_device.h> #include <linux/pm.h> +#include <asm/bootinfo.h> #include <asm/reboot.h> +#include <asm/mach-au1x00/au1000.h> #include <asm/mach-db1x00/bcsr.h> +#include <prom.h> + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = (int)fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str || kstrtoul(memsize_str, 0, &memsize)) + memsize = 64 << 20; /* all devboards have at least 64MB RAM */ + + add_memory_region(0, memsize, BOOT_MEM_RAM); +} + +void prom_putchar(unsigned char c) +{ +#ifdef CONFIG_MIPS_DB1300 + alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c); +#else + alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c); +#endif +} + static struct platform_device db1x00_rtc_dev = { .name = "rtc-au1xxx", diff --git a/arch/mips/alchemy/devboards/prom.c b/arch/mips/alchemy/devboards/prom.c deleted file mode 100644 index 93a22107cc4..00000000000 --- a/arch/mips/alchemy/devboards/prom.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Common code used by all Alchemy develboards. - * - * Extracted from files which had this to say: - * - * Copyright 2000, 2008 MontaVista Software Inc. - * Author: MontaVista Software, Inc. <source@mvista.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. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <asm/bootinfo.h> -#include <asm/mach-au1x00/au1000.h> -#include <prom.h> - -#if defined(CONFIG_MIPS_DB1000) || \ - defined(CONFIG_MIPS_PB1100) || \ - defined(CONFIG_MIPS_PB1500) -#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x04000000 - -#else /* Au1550/Au1200-based develboards */ -#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x08000000 -#endif - -void __init prom_init(void) -{ - unsigned char *memsize_str; - unsigned long memsize; - - prom_argc = (int)fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - memsize_str = prom_getenv("memsize"); - if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize)) - memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE; - - add_memory_region(0, memsize, BOOT_MEM_RAM); -} - -void prom_putchar(unsigned char c) -{ -#ifdef CONFIG_MIPS_DB1300 - alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c); -#else - alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c); -#endif -} diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig index 6b1b9ad8d85..d03e8799d1c 100644 --- a/arch/mips/bcm63xx/Kconfig +++ b/arch/mips/bcm63xx/Kconfig @@ -1,6 +1,10 @@ menu "CPU support" depends on BCM63XX +config BCM63XX_CPU_6328 + bool "support 6328 CPU" + select HW_HAS_PCI + config BCM63XX_CPU_6338 bool "support 6338 CPU" select HW_HAS_PCI diff --git a/arch/mips/bcm63xx/Makefile b/arch/mips/bcm63xx/Makefile index 6dfdc69928a..833af72c852 100644 --- a/arch/mips/bcm63xx/Makefile +++ b/arch/mips/bcm63xx/Makefile @@ -1,5 +1,6 @@ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ - dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o + dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \ + dev-spi.o dev-uart.o dev-wdt.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += boards/ diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c index 2f1773f3fb7..feb05258a4d 100644 --- a/arch/mips/bcm63xx/boards/board_bcm963xx.c +++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c @@ -11,9 +11,6 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/platform_device.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/physmap.h> #include <linux/ssb/ssb.h> #include <asm/addrspace.h> #include <bcm63xx_board.h> @@ -24,7 +21,9 @@ #include <bcm63xx_dev_pci.h> #include <bcm63xx_dev_enet.h> #include <bcm63xx_dev_dsp.h> +#include <bcm63xx_dev_flash.h> #include <bcm63xx_dev_pcmcia.h> +#include <bcm63xx_dev_spi.h> #include <board_bcm963xx.h> #define PFX "board_bcm963xx: " @@ -34,6 +33,48 @@ static unsigned int mac_addr_used; static struct board_info board; /* + * known 6328 boards + */ +#ifdef CONFIG_BCM63XX_CPU_6328 +static struct board_info __initdata board_96328avng = { + .name = "96328avng", + .expected_cpu_id = 0x6328, + + .has_uart0 = 1, + .has_pci = 1, + + .leds = { + { + .name = "96328avng::ppp-fail", + .gpio = 2, + .active_low = 1, + }, + { + .name = "96328avng::power", + .gpio = 4, + .active_low = 1, + .default_trigger = "default-on", + }, + { + .name = "96328avng::power-fail", + .gpio = 8, + .active_low = 1, + }, + { + .name = "96328avng::wps", + .gpio = 9, + .active_low = 1, + }, + { + .name = "96328avng::ppp", + .gpio = 11, + .active_low = 1, + }, + }, +}; +#endif + +/* * known 6338 boards */ #ifdef CONFIG_BCM63XX_CPU_6338 @@ -592,6 +633,9 @@ static struct board_info __initdata board_DWVS0 = { * all boards */ static const struct board_info __initdata *bcm963xx_boards[] = { +#ifdef CONFIG_BCM63XX_CPU_6328 + &board_96328avng, +#endif #ifdef CONFIG_BCM63XX_CPU_6338 &board_96338gw, &board_96338w, @@ -709,9 +753,15 @@ void __init board_prom_init(void) char cfe_version[32]; u32 val; - /* read base address of boot chip select (0) */ - val = bcm_mpi_readl(MPI_CSBASE_REG(0)); - val &= MPI_CSBASE_BASE_MASK; + /* read base address of boot chip select (0) + * 6328 does not have MPI but boots from a fixed address + */ + if (BCMCPU_IS_6328()) + val = 0x18000000; + else { + val = bcm_mpi_readl(MPI_CSBASE_REG(0)); + val &= MPI_CSBASE_BASE_MASK; + } boot_addr = (u8 *)KSEG1ADDR(val); /* dump cfe version */ @@ -808,40 +858,6 @@ void __init board_setup(void) panic("unexpected CPU for bcm963xx board"); } -static struct mtd_partition mtd_partitions[] = { - { - .name = "cfe", - .offset = 0x0, - .size = 0x40000, - } -}; - -static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL }; - -static struct physmap_flash_data flash_data = { - .width = 2, - .nr_parts = ARRAY_SIZE(mtd_partitions), - .parts = mtd_partitions, - .part_probe_types = bcm63xx_part_types, -}; - -static struct resource mtd_resources[] = { - { - .start = 0, /* filled at runtime */ - .end = 0, /* filled at runtime */ - .flags = IORESOURCE_MEM, - } -}; - -static struct platform_device mtd_dev = { - .name = "physmap-flash", - .resource = mtd_resources, - .num_resources = ARRAY_SIZE(mtd_resources), - .dev = { - .platform_data = &flash_data, - }, -}; - static struct gpio_led_platform_data bcm63xx_led_data; static struct platform_device bcm63xx_gpio_leds = { @@ -855,8 +871,6 @@ static struct platform_device bcm63xx_gpio_leds = { */ int __init board_register_devices(void) { - u32 val; - if (board.has_uart0) bcm63xx_uart_register(0); @@ -890,14 +904,9 @@ int __init board_register_devices(void) } #endif - /* read base address of boot chip select (0) */ - val = bcm_mpi_readl(MPI_CSBASE_REG(0)); - val &= MPI_CSBASE_BASE_MASK; - - mtd_resources[0].start = val; - mtd_resources[0].end = 0x1FFFFFFF; + bcm63xx_spi_register(); - platform_device_register(&mtd_dev); + bcm63xx_flash_register(); bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); bcm63xx_led_data.leds = board.leds; diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c index 9d57c71b7b5..1db48adb543 100644 --- a/arch/mips/bcm63xx/clk.c +++ b/arch/mips/bcm63xx/clk.c @@ -120,7 +120,7 @@ static void enetsw_set(struct clk *clk, int enable) { if (!BCMCPU_IS_6368()) return; - bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN | + bcm_hwclock_set(CKCTL_6368_ROBOSW_EN | CKCTL_6368_SWPKT_USB_EN | CKCTL_6368_SWPKT_SAR_EN, enable); if (enable) { @@ -163,7 +163,7 @@ static void usbh_set(struct clk *clk, int enable) if (BCMCPU_IS_6348()) bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); else if (BCMCPU_IS_6368()) - bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); + bcm_hwclock_set(CKCTL_6368_USBH_EN, enable); } static struct clk clk_usbh = { @@ -181,9 +181,11 @@ static void spi_set(struct clk *clk, int enable) mask = CKCTL_6338_SPI_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_SPI_EN; - else - /* BCMCPU_IS_6358 */ + else if (BCMCPU_IS_6358()) mask = CKCTL_6358_SPI_EN; + else + /* BCMCPU_IS_6368 */ + mask = CKCTL_6368_SPI_EN; bcm_hwclock_set(mask, enable); } @@ -199,7 +201,7 @@ static void xtm_set(struct clk *clk, int enable) if (!BCMCPU_IS_6368()) return; - bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN | + bcm_hwclock_set(CKCTL_6368_SAR_EN | CKCTL_6368_SWPKT_SAR_EN, enable); if (enable) { @@ -222,6 +224,18 @@ static struct clk clk_xtm = { }; /* + * IPsec clock + */ +static void ipsec_set(struct clk *clk, int enable) +{ + bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable); +} + +static struct clk clk_ipsec = { + .set = ipsec_set, +}; + +/* * Internal peripheral clock */ static struct clk clk_periph = { @@ -278,6 +292,8 @@ struct clk *clk_get(struct device *dev, const char *id) return &clk_periph; if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) return &clk_pcm; + if (BCMCPU_IS_6368() && !strcmp(id, "ipsec")) + return &clk_ipsec; return ERR_PTR(-ENOENT); } diff --git a/arch/mips/bcm63xx/cpu.c b/arch/mips/bcm63xx/cpu.c index 8f0d6c7725e..a7afb289b15 100644 --- a/arch/mips/bcm63xx/cpu.c +++ b/arch/mips/bcm63xx/cpu.c @@ -29,6 +29,14 @@ static u16 bcm63xx_cpu_rev; static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_memory_size; +static const unsigned long bcm6328_regs_base[] = { + __GEN_CPU_REGS_TABLE(6328) +}; + +static const int bcm6328_irqs[] = { + __GEN_CPU_IRQ_TABLE(6328) +}; + static const unsigned long bcm6338_regs_base[] = { __GEN_CPU_REGS_TABLE(6338) }; @@ -99,6 +107,33 @@ unsigned int bcm63xx_get_memory_size(void) static unsigned int detect_cpu_clock(void) { switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + { + unsigned int tmp, mips_pll_fcvo; + + tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG); + mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK) + >> STRAPBUS_6328_FCVO_SHIFT; + + switch (mips_pll_fcvo) { + case 0x12: + case 0x14: + case 0x19: + return 160000000; + case 0x1c: + return 192000000; + case 0x13: + case 0x15: + return 200000000; + case 0x1a: + return 384000000; + case 0x16: + return 400000000; + default: + return 320000000; + } + + } case BCM6338_CPU_ID: /* BCM6338 has a fixed 240 Mhz frequency */ return 240000000; @@ -170,6 +205,9 @@ static unsigned int detect_memory_size(void) unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; + if (BCMCPU_IS_6328()) + return bcm_ddr_readl(DDR_CSEND_REG) << 24; + if (BCMCPU_IS_6345()) { val = bcm_sdram_readl(SDRAM_MBASE_REG); return (val * 8 * 1024 * 1024); @@ -228,17 +266,26 @@ void __init bcm63xx_cpu_init(void) bcm63xx_irqs = bcm6345_irqs; break; case CPU_BMIPS4350: - switch (read_c0_prid() & 0xf0) { - case 0x10: + if ((read_c0_prid() & 0xf0) == 0x10) { expected_cpu_id = BCM6358_CPU_ID; bcm63xx_regs_base = bcm6358_regs_base; bcm63xx_irqs = bcm6358_irqs; - break; - case 0x30: - expected_cpu_id = BCM6368_CPU_ID; - bcm63xx_regs_base = bcm6368_regs_base; - bcm63xx_irqs = bcm6368_irqs; - break; + } else { + /* all newer chips have the same chip id location */ + u16 chip_id = bcm_readw(BCM_6368_PERF_BASE); + + switch (chip_id) { + case BCM6328_CPU_ID: + expected_cpu_id = BCM6328_CPU_ID; + bcm63xx_regs_base = bcm6328_regs_base; + bcm63xx_irqs = bcm6328_irqs; + break; + case BCM6368_CPU_ID: + expected_cpu_id = BCM6368_CPU_ID; + bcm63xx_regs_base = bcm6368_regs_base; + bcm63xx_irqs = bcm6368_irqs; + break; + } } break; } diff --git a/arch/mips/bcm63xx/dev-dsp.c b/arch/mips/bcm63xx/dev-dsp.c index da46d1d3c77..5bb5b154c9b 100644 --- a/arch/mips/bcm63xx/dev-dsp.c +++ b/arch/mips/bcm63xx/dev-dsp.c @@ -31,7 +31,7 @@ static struct resource voip_dsp_resources[] = { static struct platform_device bcm63xx_voip_dsp_device = { .name = "bcm63xx-voip-dsp", - .id = 0, + .id = -1, .num_resources = ARRAY_SIZE(voip_dsp_resources), .resource = voip_dsp_resources, }; diff --git a/arch/mips/bcm63xx/dev-flash.c b/arch/mips/bcm63xx/dev-flash.c new file mode 100644 index 00000000000..58371c7deac --- /dev/null +++ b/arch/mips/bcm63xx/dev-flash.c @@ -0,0 +1,123 @@ +/* + * Broadcom BCM63xx flash registration + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> + * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> + +#include <bcm63xx_cpu.h> +#include <bcm63xx_dev_flash.h> +#include <bcm63xx_regs.h> +#include <bcm63xx_io.h> + +static struct mtd_partition mtd_partitions[] = { + { + .name = "cfe", + .offset = 0x0, + .size = 0x40000, + } +}; + +static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL }; + +static struct physmap_flash_data flash_data = { + .width = 2, + .parts = mtd_partitions, + .part_probe_types = bcm63xx_part_types, +}; + +static struct resource mtd_resources[] = { + { + .start = 0, /* filled at runtime */ + .end = 0, /* filled at runtime */ + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device mtd_dev = { + .name = "physmap-flash", + .resource = mtd_resources, + .num_resources = ARRAY_SIZE(mtd_resources), + .dev = { + .platform_data = &flash_data, + }, +}; + +static int __init bcm63xx_detect_flash_type(void) +{ + u32 val; + + switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + val = bcm_misc_readl(MISC_STRAPBUS_6328_REG); + if (val & STRAPBUS_6328_BOOT_SEL_SERIAL) + return BCM63XX_FLASH_TYPE_SERIAL; + else + return BCM63XX_FLASH_TYPE_NAND; + case BCM6338_CPU_ID: + case BCM6345_CPU_ID: + case BCM6348_CPU_ID: + /* no way to auto detect so assume parallel */ + return BCM63XX_FLASH_TYPE_PARALLEL; + case BCM6358_CPU_ID: + val = bcm_gpio_readl(GPIO_STRAPBUS_REG); + if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL) + return BCM63XX_FLASH_TYPE_PARALLEL; + else + return BCM63XX_FLASH_TYPE_SERIAL; + case BCM6368_CPU_ID: + val = bcm_gpio_readl(GPIO_STRAPBUS_REG); + switch (val & STRAPBUS_6368_BOOT_SEL_MASK) { + case STRAPBUS_6368_BOOT_SEL_NAND: + return BCM63XX_FLASH_TYPE_NAND; + case STRAPBUS_6368_BOOT_SEL_SERIAL: + return BCM63XX_FLASH_TYPE_SERIAL; + case STRAPBUS_6368_BOOT_SEL_PARALLEL: + return BCM63XX_FLASH_TYPE_PARALLEL; + } + default: + return -EINVAL; + } +} + +int __init bcm63xx_flash_register(void) +{ + int flash_type; + u32 val; + + flash_type = bcm63xx_detect_flash_type(); + + switch (flash_type) { + case BCM63XX_FLASH_TYPE_PARALLEL: + /* read base address of boot chip select (0) */ + val = bcm_mpi_readl(MPI_CSBASE_REG(0)); + val &= MPI_CSBASE_BASE_MASK; + + mtd_resources[0].start = val; + mtd_resources[0].end = 0x1FFFFFFF; + + return platform_device_register(&mtd_dev); + case BCM63XX_FLASH_TYPE_SERIAL: + pr_warn("unsupported serial flash detected\n"); + return -ENODEV; + case BCM63XX_FLASH_TYPE_NAND: + pr_warn("unsupported NAND flash detected\n"); + return -ENODEV; + default: + pr_err("flash detection failed for BCM%x: %d\n", + bcm63xx_get_cpu_id(), flash_type); + return -ENODEV; + } +} diff --git a/arch/mips/bcm63xx/dev-rng.c b/arch/mips/bcm63xx/dev-rng.c new file mode 100644 index 00000000000..d277b4dc6c6 --- /dev/null +++ b/arch/mips/bcm63xx/dev-rng.c @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2011 Florian Fainelli <florian@openwrt.org> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <bcm63xx_cpu.h> + +static struct resource rng_resources[] = { + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device bcm63xx_rng_device = { + .name = "bcm63xx-rng", + .id = -1, + .num_resources = ARRAY_SIZE(rng_resources), + .resource = rng_resources, +}; + +int __init bcm63xx_rng_register(void) +{ + if (!BCMCPU_IS_6368()) + return -ENODEV; + + rng_resources[0].start = bcm63xx_regset_address(RSET_RNG); + rng_resources[0].end = rng_resources[0].start; + rng_resources[0].end += RSET_RNG_SIZE - 1; + + return platform_device_register(&bcm63xx_rng_device); +} +arch_initcall(bcm63xx_rng_register); diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c new file mode 100644 index 00000000000..e39f73048d4 --- /dev/null +++ b/arch/mips/bcm63xx/dev-spi.c @@ -0,0 +1,119 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <bcm63xx_cpu.h> +#include <bcm63xx_dev_spi.h> +#include <bcm63xx_regs.h> + +#ifdef BCMCPU_RUNTIME_DETECT +/* + * register offsets + */ +static const unsigned long bcm6338_regs_spi[] = { + __GEN_SPI_REGS_TABLE(6338) +}; + +static const unsigned long bcm6348_regs_spi[] = { + __GEN_SPI_REGS_TABLE(6348) +}; + +static const unsigned long bcm6358_regs_spi[] = { + __GEN_SPI_REGS_TABLE(6358) +}; + +static const unsigned long bcm6368_regs_spi[] = { + __GEN_SPI_REGS_TABLE(6368) +}; + +const unsigned long *bcm63xx_regs_spi; +EXPORT_SYMBOL(bcm63xx_regs_spi); + +static __init void bcm63xx_spi_regs_init(void) +{ + if (BCMCPU_IS_6338()) + bcm63xx_regs_spi = bcm6338_regs_spi; + if (BCMCPU_IS_6348()) + bcm63xx_regs_spi = bcm6348_regs_spi; + if (BCMCPU_IS_6358()) + bcm63xx_regs_spi = bcm6358_regs_spi; + if (BCMCPU_IS_6368()) + bcm63xx_regs_spi = bcm6368_regs_spi; +} +#else +static __init void bcm63xx_spi_regs_init(void) { } +#endif + +static struct resource spi_resources[] = { + { + .start = -1, /* filled at runtime */ + .end = -1, /* filled at runtime */ + .flags = IORESOURCE_MEM, + }, + { + .start = -1, /* filled at runtime */ + .flags = IORESOURCE_IRQ, + }, +}; + +static struct bcm63xx_spi_pdata spi_pdata = { + .bus_num = 0, + .num_chipselect = 8, +}; + +static struct platform_device bcm63xx_spi_device = { + .name = "bcm63xx-spi", + .id = -1, + .num_resources = ARRAY_SIZE(spi_resources), + .resource = spi_resources, + .dev = { + .platform_data = &spi_pdata, + }, +}; + +int __init bcm63xx_spi_register(void) +{ + struct clk *periph_clk; + + if (BCMCPU_IS_6328() || BCMCPU_IS_6345()) + return -ENODEV; + + periph_clk = clk_get(NULL, "periph"); + if (IS_ERR(periph_clk)) { + pr_err("unable to get periph clock\n"); + return -ENODEV; + } + + /* Set bus frequency */ + spi_pdata.speed_hz = clk_get_rate(periph_clk); + + spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); + spi_resources[0].end = spi_resources[0].start; + spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); + + if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { + spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; + spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; + } + + if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { + spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; + spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; + } + + bcm63xx_spi_regs_init(); + + return platform_device_register(&bcm63xx_spi_device); +} diff --git a/arch/mips/bcm63xx/dev-wdt.c b/arch/mips/bcm63xx/dev-wdt.c index 3e6c716a4c1..2a2346a99bc 100644 --- a/arch/mips/bcm63xx/dev-wdt.c +++ b/arch/mips/bcm63xx/dev-wdt.c @@ -21,7 +21,7 @@ static struct resource wdt_resources[] = { static struct platform_device bcm63xx_wdt_device = { .name = "bcm63xx-wdt", - .id = 0, + .id = -1, .num_resources = ARRAY_SIZE(wdt_resources), .resource = wdt_resources, }; diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index 9a216a451d9..18e051ad18a 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c @@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; #ifndef BCMCPU_RUNTIME_DETECT +#ifdef CONFIG_BCM63XX_CPU_6328 +#define irq_stat_reg PERF_IRQSTAT_6328_REG +#define irq_mask_reg PERF_IRQMASK_6328_REG +#define irq_bits 64 +#define is_ext_irq_cascaded 1 +#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE) +#define ext_irq_end (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE) +#define ext_irq_count 4 +#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6328 +#define ext_irq_cfg_reg2 0 +#endif #ifdef CONFIG_BCM63XX_CPU_6338 #define irq_stat_reg PERF_IRQSTAT_6338_REG #define irq_mask_reg PERF_IRQMASK_6338_REG @@ -118,6 +129,16 @@ static void bcm63xx_init_irq(void) irq_mask_addr = bcm63xx_regset_address(RSET_PERF); switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + irq_stat_addr += PERF_IRQSTAT_6328_REG; + irq_mask_addr += PERF_IRQMASK_6328_REG; + irq_bits = 64; + ext_irq_count = 4; + is_ext_irq_cascaded = 1; + ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE; + ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE; + ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328; + break; case BCM6338_CPU_ID: irq_stat_addr += PERF_IRQSTAT_6338_REG; irq_mask_addr += PERF_IRQMASK_6338_REG; diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c index 99d7f405cbe..10eaff45807 100644 --- a/arch/mips/bcm63xx/prom.c +++ b/arch/mips/bcm63xx/prom.c @@ -26,7 +26,9 @@ void __init prom_init(void) bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); /* disable all hardware blocks clock for now */ - if (BCMCPU_IS_6338()) + if (BCMCPU_IS_6328()) + mask = CKCTL_6328_ALL_SAFE_EN; + else if (BCMCPU_IS_6338()) mask = CKCTL_6338_ALL_SAFE_EN; else if (BCMCPU_IS_6345()) mask = CKCTL_6345_ALL_SAFE_EN; diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c index 356b05583e1..0e74a13639c 100644 --- a/arch/mips/bcm63xx/setup.c +++ b/arch/mips/bcm63xx/setup.c @@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void) /* mask and clear all external irq */ switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328; + break; case BCM6338_CPU_ID: perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338; break; @@ -95,9 +98,13 @@ void bcm63xx_machine_reboot(void) bcm6348_a1_reboot(); printk(KERN_INFO "triggering watchdog soft-reset...\n"); - reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG); - reg |= SYS_PLL_SOFT_RESET; - bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG); + if (BCMCPU_IS_6328()) { + bcm_wdt_writel(1, WDT_SOFTRESET_REG); + } else { + reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG); + reg |= SYS_PLL_SOFT_RESET; + bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG); + } while (1) ; } diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 5042d51b051..c2a3fb0ffc8 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -58,8 +58,12 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE # Calculate the load address of the compressed kernel image hostprogs-y := calc_vmlinuz_load_addr +ifeq ($(CONFIG_MACH_JZ4740),y) +VMLINUZ_LOAD_ADDRESS := 0x80600000 +else VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS)) +endif vmlinuzobjs-y += $(obj)/piggy.o diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c index c9caaf4fbf6..1c7b739b6a1 100644 --- a/arch/mips/boot/compressed/uart-16550.c +++ b/arch/mips/boot/compressed/uart-16550.c @@ -18,6 +18,11 @@ #define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset)) #endif +#ifdef CONFIG_MACH_JZ4740 +#define UART0_BASE 0xB0030000 +#define PORT(offset) (UART0_BASE + (4 * offset)) +#endif + #ifndef PORT #error please define the serial port address for your own machine #endif diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore new file mode 100644 index 00000000000..39c968605ff --- /dev/null +++ b/arch/mips/cavium-octeon/.gitignore @@ -0,0 +1,2 @@ +*.dtb.S +*.dtb diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 19eb0434269..bc96e2908f1 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -9,9 +9,25 @@ # Copyright (C) 2005-2009 Cavium Networks # +CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt +CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt + obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o flash_setup.o obj-y += octeon-memcpy.o obj-y += executive/ obj-$(CONFIG_SMP) += smp.o + +DTS_FILES = octeon_3xxx.dts octeon_68xx.dts +DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES)) + +obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES)) + +$(obj)/%.dtb: $(src)/%.dts FORCE + $(call if_changed_dep,dtc) + +# Let's keep the .dtb files around in case we want to look at them. +.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES)) + +clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES)) diff --git a/arch/mips/cavium-octeon/executive/cvmx-fpa.c b/arch/mips/cavium-octeon/executive/cvmx-fpa.c deleted file mode 100644 index ad44b8bd805..00000000000 --- a/arch/mips/cavium-octeon/executive/cvmx-fpa.c +++ /dev/null @@ -1,183 +0,0 @@ -/***********************license start*************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK - * - * Copyright (c) 2003-2008 Cavium Networks - * - * This file 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 file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information - ***********************license end**************************************/ - -/** - * @file - * - * Support library for the hardware Free Pool Allocator. - * - * - */ - -#include "cvmx-config.h" -#include "cvmx.h" -#include "cvmx-fpa.h" -#include "cvmx-ipd.h" - -/** - * Current state of all the pools. Use access functions - * instead of using it directly. - */ -CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; - -/** - * Setup a FPA pool to control a new block of memory. The - * buffer pointer must be a physical address. - * - * @pool: Pool to initialize - * 0 <= pool < 8 - * @name: Constant character string to name this pool. - * String is not copied. - * @buffer: Pointer to the block of memory to use. This must be - * accessible by all processors and external hardware. - * @block_size: Size for each block controlled by the FPA - * @num_blocks: Number of blocks - * - * Returns 0 on Success, - * -1 on failure - */ -int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, - uint64_t block_size, uint64_t num_blocks) -{ - char *ptr; - if (!buffer) { - cvmx_dprintf - ("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n"); - return -1; - } - if (pool >= CVMX_FPA_NUM_POOLS) { - cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n"); - return -1; - } - - if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) { - cvmx_dprintf - ("ERROR: cvmx_fpa_setup_pool: Block size too small.\n"); - return -1; - } - - if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) { - cvmx_dprintf - ("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n"); - return -1; - } - - cvmx_fpa_pool_info[pool].name = name; - cvmx_fpa_pool_info[pool].size = block_size; - cvmx_fpa_pool_info[pool].starting_element_count = num_blocks; - cvmx_fpa_pool_info[pool].base = buffer; - - ptr = (char *)buffer; - while (num_blocks--) { - cvmx_fpa_free(ptr, pool, 0); - ptr += block_size; - } - return 0; -} - -/** - * Shutdown a Memory pool and validate that it had all of - * the buffers originally placed in it. - * - * @pool: Pool to shutdown - * Returns Zero on success - * - Positive is count of missing buffers - * - Negative is too many buffers or corrupted pointers - */ -uint64_t cvmx_fpa_shutdown_pool(uint64_t pool) -{ - uint64_t errors = 0; - uint64_t count = 0; - uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base); - uint64_t finish = - base + - cvmx_fpa_pool_info[pool].size * - cvmx_fpa_pool_info[pool].starting_element_count; - void *ptr; - uint64_t address; - - count = 0; - do { - ptr = cvmx_fpa_alloc(pool); - if (ptr) - address = cvmx_ptr_to_phys(ptr); - else - address = 0; - if (address) { - if ((address >= base) && (address < finish) && - (((address - - base) % cvmx_fpa_pool_info[pool].size) == 0)) { - count++; - } else { - cvmx_dprintf - ("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n", - (unsigned long long)address, - cvmx_fpa_pool_info[pool].name, (int)pool); - errors++; - } - } - } while (address); - -#ifdef CVMX_ENABLE_PKO_FUNCTIONS - if (pool == 0) - cvmx_ipd_free_ptr(); -#endif - - if (errors) { - cvmx_dprintf - ("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n", - cvmx_fpa_pool_info[pool].name, (int)pool, - (unsigned long long)base, (unsigned long long)finish, - (unsigned long long)cvmx_fpa_pool_info[pool].size); - return -errors; - } else - return 0; -} - -uint64_t cvmx_fpa_get_block_size(uint64_t pool) -{ - switch (pool) { - case 0: - return CVMX_FPA_POOL_0_SIZE; - case 1: - return CVMX_FPA_POOL_1_SIZE; - case 2: - return CVMX_FPA_POOL_2_SIZE; - case 3: - return CVMX_FPA_POOL_3_SIZE; - case 4: - return CVMX_FPA_POOL_4_SIZE; - case 5: - return CVMX_FPA_POOL_5_SIZE; - case 6: - return CVMX_FPA_POOL_6_SIZE; - case 7: - return CVMX_FPA_POOL_7_SIZE; - default: - return 0; - } -} diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c b/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c deleted file mode 100644 index c239e5f4ab9..00000000000 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c +++ /dev/null @@ -1,243 +0,0 @@ -/***********************license start*************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK - * - * Copyright (c) 2003-2008 Cavium Networks - * - * This file 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 file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information - ***********************license end**************************************/ - -/** - * @file - * - * Helper functions for FPA setup. - * - */ -#include "executive-config.h" -#include "cvmx-config.h" -#include "cvmx.h" -#include "cvmx-bootmem.h" -#include "cvmx-fpa.h" -#include "cvmx-helper-fpa.h" - -/** - * Allocate memory for and initialize a single FPA pool. - * - * @pool: Pool to initialize - * @buffer_size: Size of buffers to allocate in bytes - * @buffers: Number of buffers to put in the pool. Zero is allowed - * @name: String name of the pool for debugging purposes - * Returns Zero on success, non-zero on failure - */ -static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size, - uint64_t buffers, const char *name) -{ - uint64_t current_num; - void *memory; - uint64_t align = CVMX_CACHE_LINE_SIZE; - - /* - * Align the allocation so that power of 2 size buffers are - * naturally aligned. - */ - while (align < buffer_size) - align = align << 1; - - if (buffers == 0) - return 0; - - current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool)); - if (current_num) { - cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. " - "Skipping setup.\n", - pool, name, (unsigned long long)current_num); - return 0; - } - - memory = cvmx_bootmem_alloc(buffer_size * buffers, align); - if (memory == NULL) { - cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n", - pool, name); - return -1; - } - cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers); - return 0; -} - -/** - * Allocate memory and initialize the FPA pools using memory - * from cvmx-bootmem. Specifying zero for the number of - * buffers will cause that FPA pool to not be setup. This is - * useful if you aren't using some of the hardware and want - * to save memory. Use cvmx_helper_initialize_fpa instead of - * this function directly. - * - * @pip_pool: Should always be CVMX_FPA_PACKET_POOL - * @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE - * @pip_buffers: - * Number of packet buffers. - * @wqe_pool: Should always be CVMX_FPA_WQE_POOL - * @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE - * @wqe_entries: - * Number of work queue entries - * @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL - * @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE - * @pko_buffers: - * PKO Command buffers. You should at minimum have two per - * each PKO queue. - * @tim_pool: Should always be CVMX_FPA_TIMER_POOL - * @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE - * @tim_buffers: - * TIM ring buffer command queues. At least two per timer bucket - * is recommened. - * @dfa_pool: Should always be CVMX_FPA_DFA_POOL - * @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE - * @dfa_buffers: - * DFA command buffer. A relatively small (32 for example) - * number should work. - * Returns Zero on success, non-zero if out of memory - */ -static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size, - int pip_buffers, int wqe_pool, - int wqe_size, int wqe_entries, - int pko_pool, int pko_size, - int pko_buffers, int tim_pool, - int tim_size, int tim_buffers, - int dfa_pool, int dfa_size, - int dfa_buffers) -{ - int status; - - cvmx_fpa_enable(); - - if ((pip_buffers > 0) && (pip_buffers <= 64)) - cvmx_dprintf - ("Warning: %d packet buffers may not be enough for hardware" - " prefetch. 65 or more is recommended.\n", pip_buffers); - - if (pip_pool >= 0) { - status = - __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size, - pip_buffers, - "Packet Buffers"); - if (status) - return status; - } - - if (wqe_pool >= 0) { - status = - __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size, - wqe_entries, - "Work Queue Entries"); - if (status) - return status; - } - - if (pko_pool >= 0) { - status = - __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size, - pko_buffers, - "PKO Command Buffers"); - if (status) - return status; - } - - if (tim_pool >= 0) { - status = - __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size, - tim_buffers, - "TIM Command Buffers"); - if (status) - return status; - } - - if (dfa_pool >= 0) { - status = - __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size, - dfa_buffers, - "DFA Command Buffers"); - if (status) - return status; - } - - return 0; -} - -/** - * Allocate memory and initialize the FPA pools using memory - * from cvmx-bootmem. Sizes of each element in the pools is - * controlled by the cvmx-config.h header file. Specifying - * zero for any parameter will cause that FPA pool to not be - * setup. This is useful if you aren't using some of the - * hardware and want to save memory. - * - * @packet_buffers: - * Number of packet buffers to allocate - * @work_queue_entries: - * Number of work queue entries - * @pko_buffers: - * PKO Command buffers. You should at minimum have two per - * each PKO queue. - * @tim_buffers: - * TIM ring buffer command queues. At least two per timer bucket - * is recommened. - * @dfa_buffers: - * DFA command buffer. A relatively small (32 for example) - * number should work. - * Returns Zero on success, non-zero if out of memory - */ -int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries, - int pko_buffers, int tim_buffers, - int dfa_buffers) -{ -#ifndef CVMX_FPA_PACKET_POOL -#define CVMX_FPA_PACKET_POOL -1 -#define CVMX_FPA_PACKET_POOL_SIZE 0 -#endif -#ifndef CVMX_FPA_WQE_POOL -#define CVMX_FPA_WQE_POOL -1 -#define CVMX_FPA_WQE_POOL_SIZE 0 -#endif -#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL -#define CVMX_FPA_OUTPUT_BUFFER_POOL -1 -#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0 -#endif -#ifndef CVMX_FPA_TIMER_POOL -#define CVMX_FPA_TIMER_POOL -1 -#define CVMX_FPA_TIMER_POOL_SIZE 0 -#endif -#ifndef CVMX_FPA_DFA_POOL -#define CVMX_FPA_DFA_POOL -1 -#define CVMX_FPA_DFA_POOL_SIZE 0 -#endif - return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL, - CVMX_FPA_PACKET_POOL_SIZE, - packet_buffers, CVMX_FPA_WQE_POOL, - CVMX_FPA_WQE_POOL_SIZE, - work_queue_entries, - CVMX_FPA_OUTPUT_BUFFER_POOL, - CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, - pko_buffers, CVMX_FPA_TIMER_POOL, - CVMX_FPA_TIMER_POOL_SIZE, - tim_buffers, CVMX_FPA_DFA_POOL, - CVMX_FPA_DFA_POOL_SIZE, - dfa_buffers); -} diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index ffd4ae660f7..7fb1f222b8a 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -3,14 +3,17 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks + * Copyright (C) 2004-2012 Cavium, Inc. */ #include <linux/interrupt.h> +#include <linux/irqdomain.h> #include <linux/bitops.h> #include <linux/percpu.h> +#include <linux/slab.h> #include <linux/irq.h> #include <linux/smp.h> +#include <linux/of.h> #include <asm/octeon/octeon.h> @@ -42,9 +45,9 @@ struct octeon_core_chip_data { static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; -static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit, - struct irq_chip *chip, - irq_flow_handler_t handler) +static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, + struct irq_chip *chip, + irq_flow_handler_t handler) { union octeon_ciu_chip_data cd; @@ -505,6 +508,85 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) } } +static void octeon_irq_gpio_setup(struct irq_data *data) +{ + union cvmx_gpio_bit_cfgx cfg; + union octeon_ciu_chip_data cd; + u32 t = irqd_get_trigger_type(data); + + cd.p = irq_data_get_irq_chip_data(data); + + cfg.u64 = 0; + cfg.s.int_en = 1; + cfg.s.int_type = (t & IRQ_TYPE_EDGE_BOTH) != 0; + cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0; + + /* 140 nS glitch filter*/ + cfg.s.fil_cnt = 7; + cfg.s.fil_sel = 3; + + cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64); +} + +static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data) +{ + octeon_irq_gpio_setup(data); + octeon_irq_ciu_enable_v2(data); +} + +static void octeon_irq_ciu_enable_gpio(struct irq_data *data) +{ + octeon_irq_gpio_setup(data); + octeon_irq_ciu_enable(data); +} + +static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t) +{ + irqd_set_trigger_type(data, t); + octeon_irq_gpio_setup(data); + + return IRQ_SET_MASK_OK; +} + +static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data) +{ + union octeon_ciu_chip_data cd; + + cd.p = irq_data_get_irq_chip_data(data); + cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); + + octeon_irq_ciu_disable_all_v2(data); +} + +static void octeon_irq_ciu_disable_gpio(struct irq_data *data) +{ + union octeon_ciu_chip_data cd; + + cd.p = irq_data_get_irq_chip_data(data); + cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); + + octeon_irq_ciu_disable_all(data); +} + +static void octeon_irq_ciu_gpio_ack(struct irq_data *data) +{ + union octeon_ciu_chip_data cd; + u64 mask; + + cd.p = irq_data_get_irq_chip_data(data); + mask = 1ull << (cd.s.bit - 16); + + cvmx_write_csr(CVMX_GPIO_INT_CLR, mask); +} + +static void octeon_irq_handle_gpio(unsigned int irq, struct irq_desc *desc) +{ + if (irqd_get_trigger_type(irq_desc_get_irq_data(desc)) & IRQ_TYPE_EDGE_BOTH) + handle_edge_irq(irq, desc); + else + handle_level_irq(irq, desc); +} + #ifdef CONFIG_SMP static void octeon_irq_cpu_offline_ciu(struct irq_data *data) @@ -650,18 +732,6 @@ static struct irq_chip octeon_irq_chip_ciu_v2 = { .name = "CIU", .irq_enable = octeon_irq_ciu_enable_v2, .irq_disable = octeon_irq_ciu_disable_all_v2, - .irq_mask = octeon_irq_ciu_disable_local_v2, - .irq_unmask = octeon_irq_ciu_enable_v2, -#ifdef CONFIG_SMP - .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, - .irq_cpu_offline = octeon_irq_cpu_offline_ciu, -#endif -}; - -static struct irq_chip octeon_irq_chip_ciu_edge_v2 = { - .name = "CIU-E", - .irq_enable = octeon_irq_ciu_enable_v2, - .irq_disable = octeon_irq_ciu_disable_all_v2, .irq_ack = octeon_irq_ciu_ack, .irq_mask = octeon_irq_ciu_disable_local_v2, .irq_unmask = octeon_irq_ciu_enable_v2, @@ -675,19 +745,8 @@ static struct irq_chip octeon_irq_chip_ciu = { .name = "CIU", .irq_enable = octeon_irq_ciu_enable, .irq_disable = octeon_irq_ciu_disable_all, - .irq_mask = octeon_irq_dummy_mask, -#ifdef CONFIG_SMP - .irq_set_affinity = octeon_irq_ciu_set_affinity, - .irq_cpu_offline = octeon_irq_cpu_offline_ciu, -#endif -}; - -static struct irq_chip octeon_irq_chip_ciu_edge = { - .name = "CIU-E", - .irq_enable = octeon_irq_ciu_enable, - .irq_disable = octeon_irq_ciu_disable_all, - .irq_mask = octeon_irq_dummy_mask, .irq_ack = octeon_irq_ciu_ack, + .irq_mask = octeon_irq_dummy_mask, #ifdef CONFIG_SMP .irq_set_affinity = octeon_irq_ciu_set_affinity, .irq_cpu_offline = octeon_irq_cpu_offline_ciu, @@ -717,6 +776,33 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = { .flags = IRQCHIP_ONOFFLINE_ENABLED, }; +static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = { + .name = "CIU-GPIO", + .irq_enable = octeon_irq_ciu_enable_gpio_v2, + .irq_disable = octeon_irq_ciu_disable_gpio_v2, + .irq_ack = octeon_irq_ciu_gpio_ack, + .irq_mask = octeon_irq_ciu_disable_local_v2, + .irq_unmask = octeon_irq_ciu_enable_v2, + .irq_set_type = octeon_irq_ciu_gpio_set_type, +#ifdef CONFIG_SMP + .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, +#endif + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + +static struct irq_chip octeon_irq_chip_ciu_gpio = { + .name = "CIU-GPIO", + .irq_enable = octeon_irq_ciu_enable_gpio, + .irq_disable = octeon_irq_ciu_disable_gpio, + .irq_mask = octeon_irq_dummy_mask, + .irq_ack = octeon_irq_ciu_gpio_ack, + .irq_set_type = octeon_irq_ciu_gpio_set_type, +#ifdef CONFIG_SMP + .irq_set_affinity = octeon_irq_ciu_set_affinity, +#endif + .flags = IRQCHIP_SET_TYPE_MASKED, +}; + /* * Watchdog interrupts are special. They are associated with a single * core, so we hardwire the affinity to that core. @@ -764,6 +850,178 @@ static struct irq_chip octeon_irq_chip_ciu_wd = { .irq_mask = octeon_irq_dummy_mask, }; +static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit) +{ + bool edge = false; + + if (line == 0) + switch (bit) { + case 48 ... 49: /* GMX DRP */ + case 50: /* IPD_DRP */ + case 52 ... 55: /* Timers */ + case 58: /* MPI */ + edge = true; + break; + default: + break; + } + else /* line == 1 */ + switch (bit) { + case 47: /* PTP */ + edge = true; + break; + default: + break; + } + return edge; +} + +struct octeon_irq_gpio_domain_data { + unsigned int base_hwirq; +}; + +static int octeon_irq_gpio_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + unsigned int type; + unsigned int pin; + unsigned int trigger; + struct octeon_irq_gpio_domain_data *gpiod; + + if (d->of_node != node) + return -EINVAL; + + if (intsize < 2) + return -EINVAL; + + pin = intspec[0]; + if (pin >= 16) + return -EINVAL; + + trigger = intspec[1]; + + switch (trigger) { + case 1: + type = IRQ_TYPE_EDGE_RISING; + break; + case 2: + type = IRQ_TYPE_EDGE_FALLING; + break; + case 4: + type = IRQ_TYPE_LEVEL_HIGH; + break; + case 8: + type = IRQ_TYPE_LEVEL_LOW; + break; + default: + pr_err("Error: (%s) Invalid irq trigger specification: %x\n", + node->name, + trigger); + type = IRQ_TYPE_LEVEL_LOW; + break; + } + *out_type = type; + gpiod = d->host_data; + *out_hwirq = gpiod->base_hwirq + pin; + + return 0; +} + +static int octeon_irq_ciu_xlat(struct irq_domain *d, + struct device_node *node, + const u32 *intspec, + unsigned int intsize, + unsigned long *out_hwirq, + unsigned int *out_type) +{ + unsigned int ciu, bit; + + ciu = intspec[0]; + bit = intspec[1]; + + if (ciu > 1 || bit > 63) + return -EINVAL; + + /* These are the GPIO lines */ + if (ciu == 0 && bit >= 16 && bit < 32) + return -EINVAL; + + *out_hwirq = (ciu << 6) | bit; + *out_type = 0; + + return 0; +} + +static struct irq_chip *octeon_irq_ciu_chip; +static struct irq_chip *octeon_irq_gpio_chip; + +static bool octeon_irq_virq_in_range(unsigned int virq) +{ + /* We cannot let it overflow the mapping array. */ + if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0]))) + return true; + + WARN_ONCE(true, "virq out of range %u.\n", virq); + return false; +} + +static int octeon_irq_ciu_map(struct irq_domain *d, + unsigned int virq, irq_hw_number_t hw) +{ + unsigned int line = hw >> 6; + unsigned int bit = hw & 63; + + if (!octeon_irq_virq_in_range(virq)) + return -EINVAL; + + if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) + return -EINVAL; + + if (octeon_irq_ciu_is_edge(line, bit)) + octeon_irq_set_ciu_mapping(virq, line, bit, + octeon_irq_ciu_chip, + handle_edge_irq); + else + octeon_irq_set_ciu_mapping(virq, line, bit, + octeon_irq_ciu_chip, + handle_level_irq); + + return 0; +} + +static int octeon_irq_gpio_map(struct irq_domain *d, + unsigned int virq, irq_hw_number_t hw) +{ + unsigned int line = hw >> 6; + unsigned int bit = hw & 63; + + if (!octeon_irq_virq_in_range(virq)) + return -EINVAL; + + if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) + return -EINVAL; + + octeon_irq_set_ciu_mapping(virq, line, bit, + octeon_irq_gpio_chip, + octeon_irq_handle_gpio); + + return 0; +} + +static struct irq_domain_ops octeon_irq_domain_ciu_ops = { + .map = octeon_irq_ciu_map, + .xlate = octeon_irq_ciu_xlat, +}; + +static struct irq_domain_ops octeon_irq_domain_gpio_ops = { + .map = octeon_irq_gpio_map, + .xlate = octeon_irq_gpio_xlat, +}; + static void octeon_irq_ip2_v1(void) { const unsigned long core_id = cvmx_get_core_num(); @@ -887,9 +1145,10 @@ static void __init octeon_irq_init_ciu(void) { unsigned int i; struct irq_chip *chip; - struct irq_chip *chip_edge; struct irq_chip *chip_mbox; struct irq_chip *chip_wd; + struct device_node *gpio_node; + struct device_node *ciu_node; octeon_irq_init_ciu_percpu(); octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; @@ -901,17 +1160,18 @@ static void __init octeon_irq_init_ciu(void) octeon_irq_ip2 = octeon_irq_ip2_v2; octeon_irq_ip3 = octeon_irq_ip3_v2; chip = &octeon_irq_chip_ciu_v2; - chip_edge = &octeon_irq_chip_ciu_edge_v2; chip_mbox = &octeon_irq_chip_ciu_mbox_v2; chip_wd = &octeon_irq_chip_ciu_wd_v2; + octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio_v2; } else { octeon_irq_ip2 = octeon_irq_ip2_v1; octeon_irq_ip3 = octeon_irq_ip3_v1; chip = &octeon_irq_chip_ciu; - chip_edge = &octeon_irq_chip_ciu_edge; chip_mbox = &octeon_irq_chip_ciu_mbox; chip_wd = &octeon_irq_chip_ciu_wd; + octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio; } + octeon_irq_ciu_chip = chip; octeon_irq_ip4 = octeon_irq_ip4_mask; /* Mips internal */ @@ -920,80 +1180,49 @@ static void __init octeon_irq_init_ciu(void) /* CIU_0 */ for (i = 0; i < 16; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); - for (i = 0; i < 16; i++) - octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq); - for (i = 0; i < 4; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); for (i = 0; i < 4; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq); - - for (i = 0; i < 2; i++) - octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq); - for (i = 0; i < 4; i++) - octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq); + octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); /* CIU_1 */ for (i = 0; i < 16; i++) octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq); - - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq); - octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq); + + gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio"); + if (gpio_node) { + struct octeon_irq_gpio_domain_data *gpiod; + + gpiod = kzalloc(sizeof(*gpiod), GFP_KERNEL); + if (gpiod) { + /* gpio domain host_data is the base hwirq number. */ + gpiod->base_hwirq = 16; + irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, gpiod); + of_node_put(gpio_node); + } else + pr_warn("Cannot allocate memory for GPIO irq_domain.\n"); + } else + pr_warn("Cannot find device node for cavium,octeon-3860-gpio.\n"); + + ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu"); + if (ciu_node) { + irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL); + of_node_put(ciu_node); + } else + pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n"); /* Enable the CIU lines */ set_c0_status(STATUSF_IP3 | STATUSF_IP2); diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index 88e0cddca20..db478dbb9c7 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -164,6 +164,14 @@ .set noat /* + * t7 is used as a flag to note inatomic mode. + */ +LEAF(__copy_user_inatomic) + b __copy_user_common + li t7, 1 + END(__copy_user_inatomic) + +/* * A combined memcpy/__copy_user * __copy_user sets len to 0 for success; else to an upper bound of * the number of uncopied bytes. @@ -174,6 +182,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ move v0, dst /* return value */ __memcpy: FEXPORT(__copy_user) + li t7, 0 /* not inatomic */ +__copy_user_common: /* * Note: dst & src may be unaligned, len may be 0 * Temps @@ -412,7 +422,6 @@ l_exc_copy: * Assumes src < THREAD_BUADDR($28) */ LOAD t0, TI_TASK($28) - nop LOAD t0, THREAD_BUADDR(t0) 1: EXC( lb t1, 0(src), l_exc) @@ -422,10 +431,9 @@ EXC( lb t1, 0(src), l_exc) ADD dst, dst, 1 l_exc: LOAD t0, TI_TASK($28) - nop LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address - nop SUB len, AT, t0 # len number of uncopied bytes + bnez t7, 2f /* Skip the zeroing out part if inatomic */ /* * Here's where we rely on src and dst being incremented in tandem, * See (3) above. @@ -443,7 +451,7 @@ l_exc: ADD dst, dst, 1 bnez src, 1b SUB src, src, 1 - jr ra +2: jr ra nop diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index cd61d7281d9..0938df10a71 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004-2010 Cavium Networks + * Copyright (C) 2004-2011 Cavium Networks * Copyright (C) 2008 Wind River Systems */ @@ -13,10 +13,16 @@ #include <linux/usb.h> #include <linux/dma-mapping.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/platform_device.h> +#include <linux/of_platform.h> +#include <linux/of_fdt.h> +#include <linux/libfdt.h> #include <asm/octeon/octeon.h> #include <asm/octeon/cvmx-rnm-defs.h> +#include <asm/octeon/cvmx-helper.h> +#include <asm/octeon/cvmx-helper-board.h> static struct octeon_cf_data octeon_cf_data; @@ -162,182 +168,6 @@ out: } device_initcall(octeon_rng_device_init); -static struct i2c_board_info __initdata octeon_i2c_devices[] = { - { - I2C_BOARD_INFO("ds1337", 0x68), - }, -}; - -static int __init octeon_i2c_devices_init(void) -{ - return i2c_register_board_info(0, octeon_i2c_devices, - ARRAY_SIZE(octeon_i2c_devices)); -} -arch_initcall(octeon_i2c_devices_init); - -#define OCTEON_I2C_IO_BASE 0x1180000001000ull -#define OCTEON_I2C_IO_UNIT_OFFSET 0x200 - -static struct octeon_i2c_data octeon_i2c_data[2]; - -static int __init octeon_i2c_device_init(void) -{ - struct platform_device *pd; - int ret = 0; - int port, num_ports; - - struct resource i2c_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) - num_ports = 2; - else - num_ports = 1; - - for (port = 0; port < num_ports; port++) { - octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate(); - /*FIXME: should be examined. At the moment is set for 100Khz */ - octeon_i2c_data[port].i2c_freq = 100000; - - pd = platform_device_alloc("i2c-octeon", port); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - pd->dev.platform_data = octeon_i2c_data + port; - - i2c_resources[0].start = - OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET); - i2c_resources[0].end = i2c_resources[0].start + 0x1f; - switch (port) { - case 0: - i2c_resources[1].start = OCTEON_IRQ_TWSI; - i2c_resources[1].end = OCTEON_IRQ_TWSI; - break; - case 1: - i2c_resources[1].start = OCTEON_IRQ_TWSI2; - i2c_resources[1].end = OCTEON_IRQ_TWSI2; - break; - default: - BUG(); - } - - ret = platform_device_add_resources(pd, - i2c_resources, - ARRAY_SIZE(i2c_resources)); - if (ret) - goto fail; - - ret = platform_device_add(pd); - if (ret) - goto fail; - } - return ret; -fail: - platform_device_put(pd); -out: - return ret; -} -device_initcall(octeon_i2c_device_init); - -/* Octeon SMI/MDIO interface. */ -static int __init octeon_mdiobus_device_init(void) -{ - struct platform_device *pd; - int ret = 0; - - if (octeon_is_simulation()) - return 0; /* No mdio in the simulator. */ - - /* The bus number is the platform_device id. */ - pd = platform_device_alloc("mdio-octeon", 0); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - ret = platform_device_add(pd); - if (ret) - goto fail; - - return ret; -fail: - platform_device_put(pd); - -out: - return ret; - -} -device_initcall(octeon_mdiobus_device_init); - -/* Octeon mgmt port Ethernet interface. */ -static int __init octeon_mgmt_device_init(void) -{ - struct platform_device *pd; - int ret = 0; - int port, num_ports; - - struct resource mgmt_port_resource = { - .flags = IORESOURCE_IRQ, - .start = -1, - .end = -1 - }; - - if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX)) - return 0; - - if (OCTEON_IS_MODEL(OCTEON_CN56XX)) - num_ports = 1; - else - num_ports = 2; - - for (port = 0; port < num_ports; port++) { - pd = platform_device_alloc("octeon_mgmt", port); - if (!pd) { - ret = -ENOMEM; - goto out; - } - /* No DMA restrictions */ - pd->dev.coherent_dma_mask = DMA_BIT_MASK(64); - pd->dev.dma_mask = &pd->dev.coherent_dma_mask; - - switch (port) { - case 0: - mgmt_port_resource.start = OCTEON_IRQ_MII0; - break; - case 1: - mgmt_port_resource.start = OCTEON_IRQ_MII1; - break; - default: - BUG(); - } - mgmt_port_resource.end = mgmt_port_resource.start; - - ret = platform_device_add_resources(pd, &mgmt_port_resource, 1); - - if (ret) - goto fail; - - ret = platform_device_add(pd); - if (ret) - goto fail; - } - return ret; -fail: - platform_device_put(pd); - -out: - return ret; - -} -device_initcall(octeon_mgmt_device_init); - #ifdef CONFIG_USB static int __init octeon_ehci_device_init(void) @@ -440,6 +270,521 @@ device_initcall(octeon_ohci_device_init); #endif /* CONFIG_USB */ +static struct of_device_id __initdata octeon_ids[] = { + { .compatible = "simple-bus", }, + { .compatible = "cavium,octeon-6335-uctl", }, + { .compatible = "cavium,octeon-3860-bootbus", }, + { .compatible = "cavium,mdio-mux", }, + { .compatible = "gpio-leds", }, + {}, +}; + +static bool __init octeon_has_88e1145(void) +{ + return !OCTEON_IS_MODEL(OCTEON_CN52XX) && + !OCTEON_IS_MODEL(OCTEON_CN6XXX) && + !OCTEON_IS_MODEL(OCTEON_CN56XX); +} + +static void __init octeon_fdt_set_phy(int eth, int phy_addr) +{ + const __be32 *phy_handle; + const __be32 *alt_phy_handle; + const __be32 *reg; + u32 phandle; + int phy; + int alt_phy; + const char *p; + int current_len; + char new_name[20]; + + phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL); + if (!phy_handle) + return; + + phandle = be32_to_cpup(phy_handle); + phy = fdt_node_offset_by_phandle(initial_boot_params, phandle); + + alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL); + if (alt_phy_handle) { + u32 alt_phandle = be32_to_cpup(alt_phy_handle); + alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle); + } else { + alt_phy = -1; + } + + if (phy_addr < 0 || phy < 0) { + /* Delete the PHY things */ + fdt_nop_property(initial_boot_params, eth, "phy-handle"); + /* This one may fail */ + fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle"); + if (phy >= 0) + fdt_nop_node(initial_boot_params, phy); + if (alt_phy >= 0) + fdt_nop_node(initial_boot_params, alt_phy); + return; + } + + if (phy_addr >= 256 && alt_phy > 0) { + const struct fdt_property *phy_prop; + struct fdt_property *alt_prop; + u32 phy_handle_name; + + /* Use the alt phy node instead.*/ + phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL); + phy_handle_name = phy_prop->nameoff; + fdt_nop_node(initial_boot_params, phy); + fdt_nop_property(initial_boot_params, eth, "phy-handle"); + alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL); + alt_prop->nameoff = phy_handle_name; + phy = alt_phy; + } + + phy_addr &= 0xff; + + if (octeon_has_88e1145()) { + fdt_nop_property(initial_boot_params, phy, "marvell,reg-init"); + memset(new_name, 0, sizeof(new_name)); + strcpy(new_name, "marvell,88e1145"); + p = fdt_getprop(initial_boot_params, phy, "compatible", + ¤t_len); + if (p && current_len >= strlen(new_name)) + fdt_setprop_inplace(initial_boot_params, phy, + "compatible", new_name, current_len); + } + + reg = fdt_getprop(initial_boot_params, phy, "reg", NULL); + if (phy_addr == be32_to_cpup(reg)) + return; + + fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr); + + snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr); + + p = fdt_get_name(initial_boot_params, phy, ¤t_len); + if (p && current_len == strlen(new_name)) + fdt_set_name(initial_boot_params, phy, new_name); + else + pr_err("Error: could not rename ethernet phy: <%s>", p); +} + +static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac) +{ + u8 new_mac[6]; + u64 mac = *pmac; + int r; + + new_mac[0] = (mac >> 40) & 0xff; + new_mac[1] = (mac >> 32) & 0xff; + new_mac[2] = (mac >> 24) & 0xff; + new_mac[3] = (mac >> 16) & 0xff; + new_mac[4] = (mac >> 8) & 0xff; + new_mac[5] = mac & 0xff; + + r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address", + new_mac, sizeof(new_mac)); + + if (r) { + pr_err("Setting \"local-mac-address\" failed %d", r); + return; + } + *pmac = mac + 1; +} + +static void __init octeon_fdt_rm_ethernet(int node) +{ + const __be32 *phy_handle; + + phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL); + if (phy_handle) { + u32 ph = be32_to_cpup(phy_handle); + int p = fdt_node_offset_by_phandle(initial_boot_params, ph); + if (p >= 0) + fdt_nop_node(initial_boot_params, p); + } + fdt_nop_node(initial_boot_params, node); +} + +static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac) +{ + char name_buffer[20]; + int eth; + int phy_addr; + int ipd_port; + + snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p); + eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer); + if (eth < 0) + return; + if (p > max) { + pr_debug("Deleting port %x:%x\n", i, p); + octeon_fdt_rm_ethernet(eth); + return; + } + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + ipd_port = (0x100 * i) + (0x10 * p) + 0x800; + else + ipd_port = 16 * i + p; + + phy_addr = cvmx_helper_board_get_mii_address(ipd_port); + octeon_fdt_set_phy(eth, phy_addr); + octeon_fdt_set_mac_addr(eth, pmac); +} + +static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) +{ + char name_buffer[20]; + int iface; + int p; + int count; + + count = cvmx_helper_interface_enumerate(idx); + + snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx); + iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer); + if (iface < 0) + return; + + for (p = 0; p < 16; p++) + octeon_fdt_pip_port(iface, idx, p, count - 1, pmac); +} + +int __init octeon_prune_device_tree(void) +{ + int i, max_port, uart_mask; + const char *pip_path; + const char *alias_prop; + char name_buffer[20]; + int aliases; + u64 mac_addr_base; + + if (fdt_check_header(initial_boot_params)) + panic("Corrupt Device Tree."); + + aliases = fdt_path_offset(initial_boot_params, "/aliases"); + if (aliases < 0) { + pr_err("Error: No /aliases node in device tree."); + return -EINVAL; + } + + + mac_addr_base = + ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 | + ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 | + ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 | + ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 | + ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 | + (octeon_bootinfo->mac_addr_base[5] & 0xffull); + + if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX)) + max_port = 2; + else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX)) + max_port = 1; + else + max_port = 0; + + if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E) + max_port = 0; + + for (i = 0; i < 2; i++) { + int mgmt; + snprintf(name_buffer, sizeof(name_buffer), + "mix%d", i); + alias_prop = fdt_getprop(initial_boot_params, aliases, + name_buffer, NULL); + if (alias_prop) { + mgmt = fdt_path_offset(initial_boot_params, alias_prop); + if (mgmt < 0) + continue; + if (i >= max_port) { + pr_debug("Deleting mix%d\n", i); + octeon_fdt_rm_ethernet(mgmt); + fdt_nop_property(initial_boot_params, aliases, + name_buffer); + } else { + int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i); + octeon_fdt_set_phy(mgmt, phy_addr); + octeon_fdt_set_mac_addr(mgmt, &mac_addr_base); + } + } + } + + pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL); + if (pip_path) { + int pip = fdt_path_offset(initial_boot_params, pip_path); + if (pip >= 0) + for (i = 0; i <= 4; i++) + octeon_fdt_pip_iface(pip, i, &mac_addr_base); + } + + /* I2C */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX) || + OCTEON_IS_MODEL(OCTEON_CN63XX) || + OCTEON_IS_MODEL(OCTEON_CN68XX) || + OCTEON_IS_MODEL(OCTEON_CN56XX)) + max_port = 2; + else + max_port = 1; + + for (i = 0; i < 2; i++) { + int i2c; + snprintf(name_buffer, sizeof(name_buffer), + "twsi%d", i); + alias_prop = fdt_getprop(initial_boot_params, aliases, + name_buffer, NULL); + + if (alias_prop) { + i2c = fdt_path_offset(initial_boot_params, alias_prop); + if (i2c < 0) + continue; + if (i >= max_port) { + pr_debug("Deleting twsi%d\n", i); + fdt_nop_node(initial_boot_params, i2c); + fdt_nop_property(initial_boot_params, aliases, + name_buffer); + } + } + } + + /* SMI/MDIO */ + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + max_port = 4; + else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || + OCTEON_IS_MODEL(OCTEON_CN63XX) || + OCTEON_IS_MODEL(OCTEON_CN56XX)) + max_port = 2; + else + max_port = 1; + + for (i = 0; i < 2; i++) { + int i2c; + snprintf(name_buffer, sizeof(name_buffer), + "smi%d", i); + alias_prop = fdt_getprop(initial_boot_params, aliases, + name_buffer, NULL); + + if (alias_prop) { + i2c = fdt_path_offset(initial_boot_params, alias_prop); + if (i2c < 0) + continue; + if (i >= max_port) { + pr_debug("Deleting smi%d\n", i); + fdt_nop_node(initial_boot_params, i2c); + fdt_nop_property(initial_boot_params, aliases, + name_buffer); + } + } + } + + /* Serial */ + uart_mask = 3; + + /* Right now CN52XX is the only chip with a third uart */ + if (OCTEON_IS_MODEL(OCTEON_CN52XX)) + uart_mask |= 4; /* uart2 */ + + for (i = 0; i < 3; i++) { + int uart; + snprintf(name_buffer, sizeof(name_buffer), + "uart%d", i); + alias_prop = fdt_getprop(initial_boot_params, aliases, + name_buffer, NULL); + + if (alias_prop) { + uart = fdt_path_offset(initial_boot_params, alias_prop); + if (uart_mask & (1 << i)) + continue; + pr_debug("Deleting uart%d\n", i); + fdt_nop_node(initial_boot_params, uart); + fdt_nop_property(initial_boot_params, aliases, + name_buffer); + } + } + + /* Compact Flash */ + alias_prop = fdt_getprop(initial_boot_params, aliases, + "cf0", NULL); + if (alias_prop) { + union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; + unsigned long base_ptr, region_base, region_size; + unsigned long region1_base = 0; + unsigned long region1_size = 0; + int cs, bootbus; + bool is_16bit = false; + bool is_true_ide = false; + __be32 new_reg[6]; + __be32 *ranges; + int len; + + int cf = fdt_path_offset(initial_boot_params, alias_prop); + base_ptr = 0; + if (octeon_bootinfo->major_version == 1 + && octeon_bootinfo->minor_version >= 1) { + if (octeon_bootinfo->compact_flash_common_base_addr) + base_ptr = octeon_bootinfo->compact_flash_common_base_addr; + } else { + base_ptr = 0x1d000800; + } + + if (!base_ptr) + goto no_cf; + + /* Find CS0 region. */ + for (cs = 0; cs < 8; cs++) { + mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); + region_base = mio_boot_reg_cfg.s.base << 16; + region_size = (mio_boot_reg_cfg.s.size + 1) << 16; + if (mio_boot_reg_cfg.s.en && base_ptr >= region_base + && base_ptr < region_base + region_size) { + is_16bit = mio_boot_reg_cfg.s.width; + break; + } + } + if (cs >= 7) { + /* cs and cs + 1 are CS0 and CS1, both must be less than 8. */ + goto no_cf; + } + + if (!(base_ptr & 0xfffful)) { + /* + * Boot loader signals availability of DMA (true_ide + * mode) by setting low order bits of base_ptr to + * zero. + */ + + /* Asume that CS1 immediately follows. */ + mio_boot_reg_cfg.u64 = + cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1)); + region1_base = mio_boot_reg_cfg.s.base << 16; + region1_size = (mio_boot_reg_cfg.s.size + 1) << 16; + if (!mio_boot_reg_cfg.s.en) + goto no_cf; + is_true_ide = true; + + } else { + fdt_nop_property(initial_boot_params, cf, "cavium,true-ide"); + fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle"); + if (!is_16bit) { + __be32 width = cpu_to_be32(8); + fdt_setprop_inplace(initial_boot_params, cf, + "cavium,bus-width", &width, sizeof(width)); + } + } + new_reg[0] = cpu_to_be32(cs); + new_reg[1] = cpu_to_be32(0); + new_reg[2] = cpu_to_be32(0x10000); + new_reg[3] = cpu_to_be32(cs + 1); + new_reg[4] = cpu_to_be32(0); + new_reg[5] = cpu_to_be32(0x10000); + fdt_setprop_inplace(initial_boot_params, cf, + "reg", new_reg, sizeof(new_reg)); + + bootbus = fdt_parent_offset(initial_boot_params, cf); + if (bootbus < 0) + goto no_cf; + ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len); + if (!ranges || len < (5 * 8 * sizeof(__be32))) + goto no_cf; + + ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32); + ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff); + ranges[(cs * 5) + 4] = cpu_to_be32(region_size); + if (is_true_ide) { + cs++; + ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32); + ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff); + ranges[(cs * 5) + 4] = cpu_to_be32(region1_size); + } + goto end_cf; +no_cf: + fdt_nop_node(initial_boot_params, cf); + +end_cf: + ; + } + + /* 8 char LED */ + alias_prop = fdt_getprop(initial_boot_params, aliases, + "led0", NULL); + if (alias_prop) { + union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; + unsigned long base_ptr, region_base, region_size; + int cs, bootbus; + __be32 new_reg[6]; + __be32 *ranges; + int len; + int led = fdt_path_offset(initial_boot_params, alias_prop); + + base_ptr = octeon_bootinfo->led_display_base_addr; + if (base_ptr == 0) + goto no_led; + /* Find CS0 region. */ + for (cs = 0; cs < 8; cs++) { + mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); + region_base = mio_boot_reg_cfg.s.base << 16; + region_size = (mio_boot_reg_cfg.s.size + 1) << 16; + if (mio_boot_reg_cfg.s.en && base_ptr >= region_base + && base_ptr < region_base + region_size) + break; + } + + if (cs > 7) + goto no_led; + + new_reg[0] = cpu_to_be32(cs); + new_reg[1] = cpu_to_be32(0x20); + new_reg[2] = cpu_to_be32(0x20); + new_reg[3] = cpu_to_be32(cs); + new_reg[4] = cpu_to_be32(0); + new_reg[5] = cpu_to_be32(0x20); + fdt_setprop_inplace(initial_boot_params, led, + "reg", new_reg, sizeof(new_reg)); + + bootbus = fdt_parent_offset(initial_boot_params, led); + if (bootbus < 0) + goto no_led; + ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len); + if (!ranges || len < (5 * 8 * sizeof(__be32))) + goto no_led; + + ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32); + ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff); + ranges[(cs * 5) + 4] = cpu_to_be32(region_size); + goto end_led; + +no_led: + fdt_nop_node(initial_boot_params, led); +end_led: + ; + } + + /* OHCI/UHCI USB */ + alias_prop = fdt_getprop(initial_boot_params, aliases, + "uctl", NULL); + if (alias_prop) { + int uctl = fdt_path_offset(initial_boot_params, alias_prop); + + if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) || + octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) { + pr_debug("Deleting uctl\n"); + fdt_nop_node(initial_boot_params, uctl); + fdt_nop_property(initial_boot_params, aliases, "uctl"); + } else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E || + octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) { + /* Missing "refclk-type" defaults to crystal. */ + fdt_nop_property(initial_boot_params, uctl, "refclk-type"); + } + } + + return 0; +} + +static int __init octeon_publish_devices(void) +{ + return of_platform_bus_probe(NULL, octeon_ids, NULL); +} +device_initcall(octeon_publish_devices); + MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Platform driver for Octeon SOC"); diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts new file mode 100644 index 00000000000..f28b2d0fde2 --- /dev/null +++ b/arch/mips/cavium-octeon/octeon_3xxx.dts @@ -0,0 +1,571 @@ +/dts-v1/; +/* + * OCTEON 3XXX, 5XXX, 63XX device tree skeleton. + * + * This device tree is pruned and patched by early boot code before + * use. Because of this, it contains a super-set of the available + * devices and properties. + */ +/ { + compatible = "cavium,octeon-3860"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&ciu>; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; /* Direct mapping */ + + ciu: interrupt-controller@1070000000000 { + compatible = "cavium,octeon-3860-ciu"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Controller register (0 or 1) + * 2) Bit within the register (0..63) + */ + #interrupt-cells = <2>; + reg = <0x10700 0x00000000 0x0 0x7000>; + }; + + gpio: gpio-controller@1070000000800 { + #gpio-cells = <2>; + compatible = "cavium,octeon-3860-gpio"; + reg = <0x10700 0x00000800 0x0 0x100>; + gpio-controller; + /* Interrupts are specified by two parts: + * 1) GPIO pin number (0..15) + * 2) Triggering (1 - edge rising + * 2 - edge falling + * 4 - level active high + * 8 - level active low) + */ + interrupt-controller; + #interrupt-cells = <2>; + /* The GPIO pin connect to 16 consecutive CUI bits */ + interrupts = <0 16>, <0 17>, <0 18>, <0 19>, + <0 20>, <0 21>, <0 22>, <0 23>, + <0 24>, <0 25>, <0 26>, <0 27>, + <0 28>, <0 29>, <0 30>, <0 31>; + }; + + smi0: mdio@1180000001800 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00001800 0x0 0x40>; + + phy0: ethernet-phy@0 { + compatible = "marvell,88e1118"; + marvell,reg-init = + /* Fix rx and tx clock transition timing */ + <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ + /* Adjust LED drive. */ + <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ + /* irq, blink-activity, blink-link */ + <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ + reg = <0>; + }; + + phy1: ethernet-phy@1 { + compatible = "marvell,88e1118"; + marvell,reg-init = + /* Fix rx and tx clock transition timing */ + <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ + /* Adjust LED drive. */ + <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ + /* irq, blink-activity, blink-link */ + <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ + reg = <1>; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy3: ethernet-phy@3 { + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy4: ethernet-phy@4 { + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + + phy6: ethernet-phy@6 { + reg = <6>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy7: ethernet-phy@7 { + reg = <7>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy8: ethernet-phy@8 { + reg = <8>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy9: ethernet-phy@9 { + reg = <9>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + }; + + smi1: mdio@1180000001900 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00001900 0x0 0x40>; + + phy100: ethernet-phy@1 { + reg = <1>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + interrupt-parent = <&gpio>; + interrupts = <12 8>; /* Pin 12, active low */ + }; + phy101: ethernet-phy@2 { + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + interrupt-parent = <&gpio>; + interrupts = <12 8>; /* Pin 12, active low */ + }; + phy102: ethernet-phy@3 { + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + interrupt-parent = <&gpio>; + interrupts = <12 8>; /* Pin 12, active low */ + }; + phy103: ethernet-phy@4 { + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + interrupt-parent = <&gpio>; + interrupts = <12 8>; /* Pin 12, active low */ + }; + }; + + mix0: ethernet@1070000100000 { + compatible = "cavium,octeon-5750-mix"; + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */ + <0x11800 0xE0000000 0x0 0x300>, /* AGL */ + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */ + cell-index = <0>; + interrupts = <0 62>, <1 46>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy0>; + }; + + mix1: ethernet@1070000100800 { + compatible = "cavium,octeon-5750-mix"; + reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */ + <0x11800 0xE0000800 0x0 0x300>, /* AGL */ + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ + <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */ + cell-index = <1>; + interrupts = <1 18>, < 1 46>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy1>; + }; + + pip: pip@11800a0000000 { + compatible = "cavium,octeon-3860-pip"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0xa0000000 0x0 0x2000>; + + interface@0 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy2>; + cavium,alt-phy-handle = <&phy100>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy3>; + cavium,alt-phy-handle = <&phy101>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy4>; + cavium,alt-phy-handle = <&phy102>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy5>; + cavium,alt-phy-handle = <&phy103>; + }; + ethernet@4 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x4>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@5 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x5>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@6 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x6>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@7 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x7>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@8 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x8>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@9 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x9>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@a { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xa>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@b { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xb>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@c { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xc>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@d { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xd>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@e { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xe>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + ethernet@f { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0xf>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + + interface@1 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy6>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy7>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy8>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy9>; + }; + }; + }; + + twsi0: i2c@1180000001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001000 0x0 0x200>; + interrupts = <0 45>; + clock-frequency = <100000>; + + rtc@68 { + compatible = "dallas,ds1337"; + reg = <0x68>; + }; + tmp@4c { + compatible = "ti,tmp421"; + reg = <0x4c>; + }; + }; + + twsi1: i2c@1180000001200 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001200 0x0 0x200>; + interrupts = <0 59>; + clock-frequency = <100000>; + }; + + uart0: serial@1180000000800 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000800 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <0 34>; + }; + + uart1: serial@1180000000c00 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000c00 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <0 35>; + }; + + uart2: serial@1180000000400 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000400 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <1 16>; + }; + + bootbus: bootbus@1180000000000 { + compatible = "cavium,octeon-3860-bootbus"; + reg = <0x11800 0x00000000 0x0 0x200>; + /* The chip select number and offset */ + #address-cells = <2>; + /* The size of the chip select region */ + #size-cells = <1>; + ranges = <0 0 0x0 0x1f400000 0xc00000>, + <1 0 0x10000 0x30000000 0>, + <2 0 0x10000 0x40000000 0>, + <3 0 0x10000 0x50000000 0>, + <4 0 0x0 0x1d020000 0x10000>, + <5 0 0x0 0x1d040000 0x10000>, + <6 0 0x0 0x1d050000 0x10000>, + <7 0 0x10000 0x90000000 0>; + + cavium,cs-config@0 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <0>; + cavium,t-adr = <20>; + cavium,t-ce = <60>; + cavium,t-oe = <60>; + cavium,t-we = <45>; + cavium,t-rd-hld = <35>; + cavium,t-wr-hld = <45>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <35>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@4 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <4>; + cavium,t-adr = <320>; + cavium,t-ce = <320>; + cavium,t-oe = <320>; + cavium,t-we = <320>; + cavium,t-rd-hld = <320>; + cavium,t-wr-hld = <320>; + cavium,t-pause = <320>; + cavium,t-wait = <320>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@5 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <5>; + cavium,t-adr = <5>; + cavium,t-ce = <300>; + cavium,t-oe = <125>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <30>; + cavium,t-pause = <0>; + cavium,t-wait = <30>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <16>; + }; + cavium,cs-config@6 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <6>; + cavium,t-adr = <5>; + cavium,t-ce = <300>; + cavium,t-oe = <270>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <70>; + cavium,t-pause = <0>; + cavium,t-wait = <0>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,wait-mode; + cavium,bus-width = <16>; + }; + + flash0: nor@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x800000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + led0: led-display@4,0 { + compatible = "avago,hdsp-253x"; + reg = <4 0x20 0x20>, <4 0 0x20>; + }; + + cf0: compact-flash@5,0 { + compatible = "cavium,ebt3000-compact-flash"; + reg = <5 0 0x10000>, <6 0 0x10000>; + cavium,bus-width = <16>; + cavium,true-ide; + cavium,dma-engine-handle = <&dma0>; + }; + }; + + dma0: dma-engine@1180000000100 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000100 0x0 0x8>; + interrupts = <0 63>; + }; + dma1: dma-engine@1180000000108 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000108 0x0 0x8>; + interrupts = <0 63>; + }; + + uctl: uctl@118006f000000 { + compatible = "cavium,octeon-6335-uctl"; + reg = <0x11800 0x6f000000 0x0 0x100>; + ranges; /* Direct mapping */ + #address-cells = <2>; + #size-cells = <2>; + /* 12MHz, 24MHz and 48MHz allowed */ + refclk-frequency = <12000000>; + /* Either "crystal" or "external" */ + refclk-type = "crystal"; + + ehci@16f0000000000 { + compatible = "cavium,octeon-6335-ehci","usb-ehci"; + reg = <0x16f00 0x00000000 0x0 0x100>; + interrupts = <0 56>; + big-endian-regs; + }; + ohci@16f0000000400 { + compatible = "cavium,octeon-6335-ohci","usb-ohci"; + reg = <0x16f00 0x00000400 0x0 0x100>; + interrupts = <0 56>; + big-endian-regs; + }; + }; + }; + + aliases { + mix0 = &mix0; + mix1 = &mix1; + pip = &pip; + smi0 = &smi0; + smi1 = &smi1; + twsi0 = &twsi0; + twsi1 = &twsi1; + uart0 = &uart0; + uart1 = &uart1; + uart2 = &uart2; + flash0 = &flash0; + cf0 = &cf0; + uctl = &uctl; + led0 = &led0; + }; + }; diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts new file mode 100644 index 00000000000..1839468932b --- /dev/null +++ b/arch/mips/cavium-octeon/octeon_68xx.dts @@ -0,0 +1,625 @@ +/dts-v1/; +/* + * OCTEON 68XX device tree skeleton. + * + * This device tree is pruned and patched by early boot code before + * use. Because of this, it contains a super-set of the available + * devices and properties. + */ +/ { + compatible = "cavium,octeon-6880"; + #address-cells = <2>; + #size-cells = <2>; + interrupt-parent = <&ciu2>; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; /* Direct mapping */ + + ciu2: interrupt-controller@1070100000000 { + compatible = "cavium,octeon-6880-ciu2"; + interrupt-controller; + /* Interrupts are specified by two parts: + * 1) Controller register (0 or 7) + * 2) Bit within the register (0..63) + */ + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <0x10701 0x00000000 0x0 0x4000000>; + }; + + gpio: gpio-controller@1070000000800 { + #gpio-cells = <2>; + compatible = "cavium,octeon-3860-gpio"; + reg = <0x10700 0x00000800 0x0 0x100>; + gpio-controller; + /* Interrupts are specified by two parts: + * 1) GPIO pin number (0..15) + * 2) Triggering (1 - edge rising + * 2 - edge falling + * 4 - level active high + * 8 - level active low) + */ + interrupt-controller; + #interrupt-cells = <2>; + /* The GPIO pins connect to 16 consecutive CUI bits */ + interrupts = <7 0>, <7 1>, <7 2>, <7 3>, + <7 4>, <7 5>, <7 6>, <7 7>, + <7 8>, <7 9>, <7 10>, <7 11>, + <7 12>, <7 13>, <7 14>, <7 15>; + }; + + smi0: mdio@1180000003800 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00003800 0x0 0x40>; + + phy0: ethernet-phy@6 { + compatible = "marvell,88e1118"; + marvell,reg-init = + /* Fix rx and tx clock transition timing */ + <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ + /* Adjust LED drive. */ + <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ + /* irq, blink-activity, blink-link */ + <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ + reg = <6>; + }; + + phy1: ethernet-phy@1 { + cavium,qlm-trim = "4,sgmii"; + reg = <1>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy2: ethernet-phy@2 { + cavium,qlm-trim = "4,sgmii"; + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy3: ethernet-phy@3 { + cavium,qlm-trim = "4,sgmii"; + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy4: ethernet-phy@4 { + cavium,qlm-trim = "4,sgmii"; + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + }; + + smi1: mdio@1180000003880 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00003880 0x0 0x40>; + + phy41: ethernet-phy@1 { + cavium,qlm-trim = "0,sgmii"; + reg = <1>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy42: ethernet-phy@2 { + cavium,qlm-trim = "0,sgmii"; + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy43: ethernet-phy@3 { + cavium,qlm-trim = "0,sgmii"; + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy44: ethernet-phy@4 { + cavium,qlm-trim = "0,sgmii"; + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + }; + + smi2: mdio@1180000003900 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00003900 0x0 0x40>; + + phy21: ethernet-phy@1 { + cavium,qlm-trim = "2,sgmii"; + reg = <1>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy22: ethernet-phy@2 { + cavium,qlm-trim = "2,sgmii"; + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy23: ethernet-phy@3 { + cavium,qlm-trim = "2,sgmii"; + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy24: ethernet-phy@4 { + cavium,qlm-trim = "2,sgmii"; + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + }; + + smi3: mdio@1180000003980 { + compatible = "cavium,octeon-3860-mdio"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0x00003980 0x0 0x40>; + + phy11: ethernet-phy@1 { + cavium,qlm-trim = "3,sgmii"; + reg = <1>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy12: ethernet-phy@2 { + cavium,qlm-trim = "3,sgmii"; + reg = <2>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy13: ethernet-phy@3 { + cavium,qlm-trim = "3,sgmii"; + reg = <3>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + phy14: ethernet-phy@4 { + cavium,qlm-trim = "3,sgmii"; + reg = <4>; + compatible = "marvell,88e1149r"; + marvell,reg-init = <3 0x10 0 0x5777>, + <3 0x11 0 0x00aa>, + <3 0x12 0 0x4105>, + <3 0x13 0 0x0a60>; + }; + }; + + mix0: ethernet@1070000100000 { + compatible = "cavium,octeon-5750-mix"; + reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */ + <0x11800 0xE0000000 0x0 0x300>, /* AGL */ + <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ + <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */ + cell-index = <0>; + interrupts = <6 40>, <6 32>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy0>; + }; + + pip: pip@11800a0000000 { + compatible = "cavium,octeon-3860-pip"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x11800 0xa0000000 0x0 0x2000>; + + interface@4 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy1>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy2>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy3>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy4>; + }; + }; + + interface@3 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy11>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy12>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy13>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy14>; + }; + }; + + interface@2 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy21>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy22>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy23>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy24>; + }; + }; + + interface@1 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + }; + + interface@0 { + compatible = "cavium,octeon-3860-pip-interface"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0>; /* interface */ + + ethernet@0 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x0>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy41>; + }; + ethernet@1 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x1>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy42>; + }; + ethernet@2 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x2>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy43>; + }; + ethernet@3 { + compatible = "cavium,octeon-3860-pip-port"; + reg = <0x3>; /* Port */ + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-handle = <&phy44>; + }; + }; + }; + + twsi0: i2c@1180000001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001000 0x0 0x200>; + interrupts = <3 32>; + clock-frequency = <100000>; + + rtc@68 { + compatible = "dallas,ds1337"; + reg = <0x68>; + }; + tmp@4c { + compatible = "ti,tmp421"; + reg = <0x4c>; + }; + }; + + twsi1: i2c@1180000001200 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "cavium,octeon-3860-twsi"; + reg = <0x11800 0x00001200 0x0 0x200>; + interrupts = <3 33>; + clock-frequency = <100000>; + }; + + uart0: serial@1180000000800 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000800 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <3 36>; + }; + + uart1: serial@1180000000c00 { + compatible = "cavium,octeon-3860-uart","ns16550"; + reg = <0x11800 0x00000c00 0x0 0x400>; + clock-frequency = <0>; + current-speed = <115200>; + reg-shift = <3>; + interrupts = <3 37>; + }; + + bootbus: bootbus@1180000000000 { + compatible = "cavium,octeon-3860-bootbus"; + reg = <0x11800 0x00000000 0x0 0x200>; + /* The chip select number and offset */ + #address-cells = <2>; + /* The size of the chip select region */ + #size-cells = <1>; + ranges = <0 0 0 0x1f400000 0xc00000>, + <1 0 0x10000 0x30000000 0>, + <2 0 0x10000 0x40000000 0>, + <3 0 0x10000 0x50000000 0>, + <4 0 0 0x1d020000 0x10000>, + <5 0 0 0x1d040000 0x10000>, + <6 0 0 0x1d050000 0x10000>, + <7 0 0x10000 0x90000000 0>; + + cavium,cs-config@0 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <0>; + cavium,t-adr = <10>; + cavium,t-ce = <50>; + cavium,t-oe = <50>; + cavium,t-we = <35>; + cavium,t-rd-hld = <25>; + cavium,t-wr-hld = <35>; + cavium,t-pause = <0>; + cavium,t-wait = <300>; + cavium,t-page = <25>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@4 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <4>; + cavium,t-adr = <320>; + cavium,t-ce = <320>; + cavium,t-oe = <320>; + cavium,t-we = <320>; + cavium,t-rd-hld = <320>; + cavium,t-wr-hld = <320>; + cavium,t-pause = <320>; + cavium,t-wait = <320>; + cavium,t-page = <320>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <8>; + }; + cavium,cs-config@5 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <5>; + cavium,t-adr = <0>; + cavium,t-ce = <300>; + cavium,t-oe = <125>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <300>; + cavium,t-pause = <0>; + cavium,t-wait = <300>; + cavium,t-page = <310>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,bus-width = <16>; + }; + cavium,cs-config@6 { + compatible = "cavium,octeon-3860-bootbus-config"; + cavium,cs-index = <6>; + cavium,t-adr = <0>; + cavium,t-ce = <30>; + cavium,t-oe = <125>; + cavium,t-we = <150>; + cavium,t-rd-hld = <100>; + cavium,t-wr-hld = <30>; + cavium,t-pause = <0>; + cavium,t-wait = <30>; + cavium,t-page = <310>; + cavium,t-rd-dly = <0>; + + cavium,pages = <0>; + cavium,wait-mode; + cavium,bus-width = <16>; + }; + + flash0: nor@0,0 { + compatible = "cfi-flash"; + reg = <0 0 0x800000>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0 0x200000>; + read-only; + }; + partition@200000 { + label = "kernel"; + reg = <0x200000 0x200000>; + }; + partition@400000 { + label = "cramfs"; + reg = <0x400000 0x3fe000>; + }; + partition@7fe000 { + label = "environment"; + reg = <0x7fe000 0x2000>; + read-only; + }; + }; + + led0: led-display@4,0 { + compatible = "avago,hdsp-253x"; + reg = <4 0x20 0x20>, <4 0 0x20>; + }; + + compact-flash@5,0 { + compatible = "cavium,ebt3000-compact-flash"; + reg = <5 0 0x10000>, <6 0 0x10000>; + cavium,bus-width = <16>; + cavium,true-ide; + cavium,dma-engine-handle = <&dma0>; + }; + }; + + dma0: dma-engine@1180000000100 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000100 0x0 0x8>; + interrupts = <0 63>; + }; + dma1: dma-engine@1180000000108 { + compatible = "cavium,octeon-5750-bootbus-dma"; + reg = <0x11800 0x00000108 0x0 0x8>; + interrupts = <0 63>; + }; + + uctl: uctl@118006f000000 { + compatible = "cavium,octeon-6335-uctl"; + reg = <0x11800 0x6f000000 0x0 0x100>; + ranges; /* Direct mapping */ + #address-cells = <2>; + #size-cells = <2>; + /* 12MHz, 24MHz and 48MHz allowed */ + refclk-frequency = <12000000>; + /* Either "crystal" or "external" */ + refclk-type = "crystal"; + + ehci@16f0000000000 { + compatible = "cavium,octeon-6335-ehci","usb-ehci"; + reg = <0x16f00 0x00000000 0x0 0x100>; + interrupts = <3 44>; + big-endian-regs; + }; + ohci@16f0000000400 { + compatible = "cavium,octeon-6335-ohci","usb-ohci"; + reg = <0x16f00 0x00000400 0x0 0x100>; + interrupts = <3 44>; + big-endian-regs; + }; + }; + }; + + aliases { + mix0 = &mix0; + pip = &pip; + smi0 = &smi0; + smi1 = &smi1; + smi2 = &smi2; + smi3 = &smi3; + twsi0 = &twsi0; + twsi1 = &twsi1; + uart0 = &uart0; + uart1 = &uart1; + uctl = &uctl; + led0 = &led0; + flash0 = &flash0; + }; + }; diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c index 057f0ae88c9..138b2216b4f 100644 --- a/arch/mips/cavium-octeon/serial.c +++ b/arch/mips/cavium-octeon/serial.c @@ -43,95 +43,67 @@ void octeon_serial_out(struct uart_port *up, int offset, int value) cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); } -/* - * Allocated in .bss, so it is all zeroed. - */ -#define OCTEON_MAX_UARTS 3 -static struct plat_serial8250_port octeon_uart8250_data[OCTEON_MAX_UARTS + 1]; -static struct platform_device octeon_uart8250_device = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = octeon_uart8250_data, - }, -}; - -static void __init octeon_uart_set_common(struct plat_serial8250_port *p) +static int __devinit octeon_serial_probe(struct platform_device *pdev) { - p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; - p->type = PORT_OCTEON; - p->iotype = UPIO_MEM; - p->regshift = 3; /* I/O addresses are every 8 bytes */ + int irq, res; + struct resource *res_mem; + struct uart_port port; + + /* All adaptors have an irq. */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + memset(&port, 0, sizeof(port)); + + port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; + port.type = PORT_OCTEON; + port.iotype = UPIO_MEM; + port.regshift = 3; + port.dev = &pdev->dev; + if (octeon_is_simulation()) /* Make simulator output fast*/ - p->uartclk = 115200 * 16; + port.uartclk = 115200 * 16; else - p->uartclk = octeon_get_io_clock_rate(); - p->serial_in = octeon_serial_in; - p->serial_out = octeon_serial_out; -} + port.uartclk = octeon_get_io_clock_rate(); -static int __init octeon_serial_init(void) -{ - int enable_uart0; - int enable_uart1; - int enable_uart2; - struct plat_serial8250_port *p; - -#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL - /* - * If we are configured to run as the second of two kernels, - * disable uart0 and enable uart1. Uart0 is owned by the first - * kernel - */ - enable_uart0 = 0; - enable_uart1 = 1; -#else - /* - * We are configured for the first kernel. We'll enable uart0 - * if the bootloader told us to use 0, otherwise will enable - * uart 1. - */ - enable_uart0 = (octeon_get_boot_uart() == 0); - enable_uart1 = (octeon_get_boot_uart() == 1); -#ifdef CONFIG_KGDB - enable_uart1 = 1; -#endif -#endif - - /* Right now CN52XX is the only chip with a third uart */ - enable_uart2 = OCTEON_IS_MODEL(OCTEON_CN52XX); - - p = octeon_uart8250_data; - if (enable_uart0) { - /* Add a ttyS device for hardware uart 0 */ - octeon_uart_set_common(p); - p->membase = (void *) CVMX_MIO_UARTX_RBR(0); - p->mapbase = CVMX_MIO_UARTX_RBR(0) & ((1ull << 49) - 1); - p->irq = OCTEON_IRQ_UART0; - p++; - } + port.serial_in = octeon_serial_in; + port.serial_out = octeon_serial_out; + port.irq = irq; - if (enable_uart1) { - /* Add a ttyS device for hardware uart 1 */ - octeon_uart_set_common(p); - p->membase = (void *) CVMX_MIO_UARTX_RBR(1); - p->mapbase = CVMX_MIO_UARTX_RBR(1) & ((1ull << 49) - 1); - p->irq = OCTEON_IRQ_UART1; - p++; - } - if (enable_uart2) { - /* Add a ttyS device for hardware uart 2 */ - octeon_uart_set_common(p); - p->membase = (void *) CVMX_MIO_UART2_RBR; - p->mapbase = CVMX_MIO_UART2_RBR & ((1ull << 49) - 1); - p->irq = OCTEON_IRQ_UART2; - p++; + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res_mem == NULL) { + dev_err(&pdev->dev, "found no memory resource\n"); + return -ENXIO; } + port.mapbase = res_mem->start; + port.membase = ioremap(res_mem->start, resource_size(res_mem)); - BUG_ON(p > &octeon_uart8250_data[OCTEON_MAX_UARTS]); + res = serial8250_register_port(&port); - return platform_device_register(&octeon_uart8250_device); + return res >= 0 ? 0 : res; } -device_initcall(octeon_serial_init); +static struct of_device_id octeon_serial_match[] = { + { + .compatible = "cavium,octeon-3860-uart", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, octeon_serial_match); + +static struct platform_driver octeon_serial_driver = { + .probe = octeon_serial_probe, + .driver = { + .owner = THIS_MODULE, + .name = "octeon_serial", + .of_match_table = octeon_serial_match, + }, +}; + +static int __init octeon_serial_init(void) +{ + return platform_driver_register(&octeon_serial_driver); +} +late_initcall(octeon_serial_init); diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 260dc247c05..919b0fb7bb1 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -21,6 +21,8 @@ #include <linux/platform_device.h> #include <linux/serial_core.h> #include <linux/serial_8250.h> +#include <linux/of_fdt.h> +#include <linux/libfdt.h> #include <asm/processor.h> #include <asm/reboot.h> @@ -775,3 +777,46 @@ void prom_free_prom_memory(void) } #endif } + +int octeon_prune_device_tree(void); + +extern const char __dtb_octeon_3xxx_begin; +extern const char __dtb_octeon_3xxx_end; +extern const char __dtb_octeon_68xx_begin; +extern const char __dtb_octeon_68xx_end; +void __init device_tree_init(void) +{ + int dt_size; + struct boot_param_header *fdt; + bool do_prune; + + if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { + fdt = phys_to_virt(octeon_bootinfo->fdt_addr); + if (fdt_check_header(fdt)) + panic("Corrupt Device Tree passed to kernel."); + dt_size = be32_to_cpu(fdt->totalsize); + do_prune = false; + } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { + fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin; + dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin; + do_prune = true; + } else { + fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin; + dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin; + do_prune = true; + } + + /* Copy the default tree from init memory. */ + initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8); + if (initial_boot_params == NULL) + panic("Could not allocate initial_boot_params\n"); + memcpy(initial_boot_params, fdt, dt_size); + + if (do_prune) { + octeon_prune_device_tree(); + pr_info("Using internal Device Tree.\n"); + } else { + pr_info("Using passed Device Tree.\n"); + } + unflatten_device_tree(); +} diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig new file mode 100644 index 00000000000..80cff8bea8e --- /dev/null +++ b/arch/mips/configs/ls1b_defconfig @@ -0,0 +1,109 @@ +CONFIG_MACH_LOONGSON1=y +CONFIG_PREEMPT=y +# CONFIG_SECCOMP is not set +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_NAMESPACES=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=m +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_DA=y +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_LEGACY_PTY_COUNT=8 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_USB_HID=m +CONFIG_HID_GENERIC=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_STORAGE=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_LOONGSON1=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_FTRACE is not set +# CONFIG_EARLY_PRINTK is not set diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig index d0b857d98c9..138f698d7c0 100644 --- a/arch/mips/configs/nlm_xlr_defconfig +++ b/arch/mips/configs/nlm_xlr_defconfig @@ -367,6 +367,10 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_TIMERIOMEM=m CONFIG_RAW_DRIVER=m +CONFIG_I2C=y +CONFIG_I2C_XLR=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1374=y # CONFIG_HWMON is not set # CONFIG_VGA_CONSOLE is not set # CONFIG_HID_SUPPORT is not set diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index e95ff3054ff..8c62316f22f 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -101,7 +101,7 @@ void __init prom_free_prom_memory(void) * the first page reserved for the exception handlers. */ -#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE) +#if IS_ENABLED(CONFIG_DECLANCE) /* * Leave 128 KB reserved for Lance memory for * IOASIC DECstations. diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 95e40c1e8ed..f21b7c04e95 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -197,6 +197,7 @@ #define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ #define PRID_REV_VR4130 0x0080 #define PRID_REV_34K_V1_0_2 0x0022 +#define PRID_REV_LOONGSON1B 0x0020 #define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2F 0x0003 @@ -261,7 +262,7 @@ enum cpu_type_enum { */ CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, - CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC, + CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, /* * MIPS64 class processors diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h index 5b8d15bb5fe..e104ddb694a 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_cpu.h @@ -9,6 +9,7 @@ * compile time if only one CPU support is enabled (idea stolen from * arm mach-types) */ +#define BCM6328_CPU_ID 0x6328 #define BCM6338_CPU_ID 0x6338 #define BCM6345_CPU_ID 0x6345 #define BCM6348_CPU_ID 0x6348 @@ -20,6 +21,19 @@ u16 __bcm63xx_get_cpu_id(void); u16 bcm63xx_get_cpu_rev(void); unsigned int bcm63xx_get_cpu_freq(void); +#ifdef CONFIG_BCM63XX_CPU_6328 +# ifdef bcm63xx_get_cpu_id +# undef bcm63xx_get_cpu_id +# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id() +# define BCMCPU_RUNTIME_DETECT +# else +# define bcm63xx_get_cpu_id() BCM6328_CPU_ID +# endif +# define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID) +#else +# define BCMCPU_IS_6328() (0) +#endif + #ifdef CONFIG_BCM63XX_CPU_6338 # ifdef bcm63xx_get_cpu_id # undef bcm63xx_get_cpu_id @@ -102,13 +116,13 @@ enum bcm63xx_regs_set { RSET_UART1, RSET_GPIO, RSET_SPI, - RSET_SPI2, RSET_UDC0, RSET_OHCI0, RSET_OHCI_PRIV, RSET_USBH_PRIV, RSET_MPI, RSET_PCMCIA, + RSET_PCIE, RSET_DSL, RSET_ENET0, RSET_ENET1, @@ -130,11 +144,17 @@ enum bcm63xx_regs_set { RSET_PCMDMA, RSET_PCMDMAC, RSET_PCMDMAS, + RSET_RNG, + RSET_MISC }; #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4) #define RSET_DSL_SIZE 4096 #define RSET_WDT_SIZE 12 +#define BCM_6338_RSET_SPI_SIZE 64 +#define BCM_6348_RSET_SPI_SIZE 64 +#define BCM_6358_RSET_SPI_SIZE 1804 +#define BCM_6368_RSET_SPI_SIZE 1804 #define RSET_ENET_SIZE 2048 #define RSET_ENETDMA_SIZE 2048 #define RSET_ENETSW_SIZE 65536 @@ -149,8 +169,53 @@ enum bcm63xx_regs_set { #define RSET_XTMDMA_SIZE 256 #define RSET_XTMDMAC_SIZE(chans) (16 * (chans)) #define RSET_XTMDMAS_SIZE(chans) (16 * (chans)) +#define RSET_RNG_SIZE 20 /* + * 6328 register sets base address + */ +#define BCM_6328_DSL_LMEM_BASE (0xdeadbeef) +#define BCM_6328_PERF_BASE (0xb0000000) +#define BCM_6328_TIMER_BASE (0xb0000040) +#define BCM_6328_WDT_BASE (0xb000005c) +#define BCM_6328_UART0_BASE (0xb0000100) +#define BCM_6328_UART1_BASE (0xb0000120) +#define BCM_6328_GPIO_BASE (0xb0000080) +#define BCM_6328_SPI_BASE (0xdeadbeef) +#define BCM_6328_UDC0_BASE (0xdeadbeef) +#define BCM_6328_USBDMA_BASE (0xdeadbeef) +#define BCM_6328_OHCI0_BASE (0xdeadbeef) +#define BCM_6328_OHCI_PRIV_BASE (0xdeadbeef) +#define BCM_6328_USBH_PRIV_BASE (0xdeadbeef) +#define BCM_6328_MPI_BASE (0xdeadbeef) +#define BCM_6328_PCMCIA_BASE (0xdeadbeef) +#define BCM_6328_PCIE_BASE (0xb0e40000) +#define BCM_6328_SDRAM_REGS_BASE (0xdeadbeef) +#define BCM_6328_DSL_BASE (0xb0001900) +#define BCM_6328_UBUS_BASE (0xdeadbeef) +#define BCM_6328_ENET0_BASE (0xdeadbeef) +#define BCM_6328_ENET1_BASE (0xdeadbeef) +#define BCM_6328_ENETDMA_BASE (0xb000d800) +#define BCM_6328_ENETDMAC_BASE (0xb000da00) +#define BCM_6328_ENETDMAS_BASE (0xb000dc00) +#define BCM_6328_ENETSW_BASE (0xb0e00000) +#define BCM_6328_EHCI0_BASE (0x10002500) +#define BCM_6328_SDRAM_BASE (0xdeadbeef) +#define BCM_6328_MEMC_BASE (0xdeadbeef) +#define BCM_6328_DDR_BASE (0xb0003000) +#define BCM_6328_M2M_BASE (0xdeadbeef) +#define BCM_6328_ATM_BASE (0xdeadbeef) +#define BCM_6328_XTM_BASE (0xdeadbeef) +#define BCM_6328_XTMDMA_BASE (0xb000b800) +#define BCM_6328_XTMDMAC_BASE (0xdeadbeef) +#define BCM_6328_XTMDMAS_BASE (0xdeadbeef) +#define BCM_6328_PCM_BASE (0xb000a800) +#define BCM_6328_PCMDMA_BASE (0xdeadbeef) +#define BCM_6328_PCMDMAC_BASE (0xdeadbeef) +#define BCM_6328_PCMDMAS_BASE (0xdeadbeef) +#define BCM_6328_RNG_BASE (0xdeadbeef) +#define BCM_6328_MISC_BASE (0xb0001800) +/* * 6338 register sets base address */ #define BCM_6338_DSL_LMEM_BASE (0xfff00000) @@ -162,7 +227,6 @@ enum bcm63xx_regs_set { #define BCM_6338_UART1_BASE (0xdeadbeef) #define BCM_6338_GPIO_BASE (0xfffe0400) #define BCM_6338_SPI_BASE (0xfffe0c00) -#define BCM_6338_SPI2_BASE (0xdeadbeef) #define BCM_6338_UDC0_BASE (0xdeadbeef) #define BCM_6338_USBDMA_BASE (0xfffe2400) #define BCM_6338_OHCI0_BASE (0xdeadbeef) @@ -170,6 +234,7 @@ enum bcm63xx_regs_set { #define BCM_6338_USBH_PRIV_BASE (0xdeadbeef) #define BCM_6338_MPI_BASE (0xfffe3160) #define BCM_6338_PCMCIA_BASE (0xdeadbeef) +#define BCM_6338_PCIE_BASE (0xdeadbeef) #define BCM_6338_SDRAM_REGS_BASE (0xfffe3100) #define BCM_6338_DSL_BASE (0xfffe1000) #define BCM_6338_UBUS_BASE (0xdeadbeef) @@ -193,6 +258,8 @@ enum bcm63xx_regs_set { #define BCM_6338_PCMDMA_BASE (0xdeadbeef) #define BCM_6338_PCMDMAC_BASE (0xdeadbeef) #define BCM_6338_PCMDMAS_BASE (0xdeadbeef) +#define BCM_6338_RNG_BASE (0xdeadbeef) +#define BCM_6338_MISC_BASE (0xdeadbeef) /* * 6345 register sets base address @@ -206,7 +273,6 @@ enum bcm63xx_regs_set { #define BCM_6345_UART1_BASE (0xdeadbeef) #define BCM_6345_GPIO_BASE (0xfffe0400) #define BCM_6345_SPI_BASE (0xdeadbeef) -#define BCM_6345_SPI2_BASE (0xdeadbeef) #define BCM_6345_UDC0_BASE (0xdeadbeef) #define BCM_6345_USBDMA_BASE (0xfffe2800) #define BCM_6345_ENET0_BASE (0xfffe1800) @@ -216,6 +282,7 @@ enum bcm63xx_regs_set { #define BCM_6345_ENETSW_BASE (0xdeadbeef) #define BCM_6345_PCMCIA_BASE (0xfffe2028) #define BCM_6345_MPI_BASE (0xfffe2000) +#define BCM_6345_PCIE_BASE (0xdeadbeef) #define BCM_6345_OHCI0_BASE (0xfffe2100) #define BCM_6345_OHCI_PRIV_BASE (0xfffe2200) #define BCM_6345_USBH_PRIV_BASE (0xdeadbeef) @@ -237,6 +304,8 @@ enum bcm63xx_regs_set { #define BCM_6345_PCMDMA_BASE (0xdeadbeef) #define BCM_6345_PCMDMAC_BASE (0xdeadbeef) #define BCM_6345_PCMDMAS_BASE (0xdeadbeef) +#define BCM_6345_RNG_BASE (0xdeadbeef) +#define BCM_6345_MISC_BASE (0xdeadbeef) /* * 6348 register sets base address @@ -249,13 +318,13 @@ enum bcm63xx_regs_set { #define BCM_6348_UART1_BASE (0xdeadbeef) #define BCM_6348_GPIO_BASE (0xfffe0400) #define BCM_6348_SPI_BASE (0xfffe0c00) -#define BCM_6348_SPI2_BASE (0xdeadbeef) #define BCM_6348_UDC0_BASE (0xfffe1000) #define BCM_6348_OHCI0_BASE (0xfffe1b00) #define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00) #define BCM_6348_USBH_PRIV_BASE (0xdeadbeef) #define BCM_6348_MPI_BASE (0xfffe2000) #define BCM_6348_PCMCIA_BASE (0xfffe2054) +#define BCM_6348_PCIE_BASE (0xdeadbeef) #define BCM_6348_SDRAM_REGS_BASE (0xfffe2300) #define BCM_6348_M2M_BASE (0xfffe2800) #define BCM_6348_DSL_BASE (0xfffe3000) @@ -278,6 +347,8 @@ enum bcm63xx_regs_set { #define BCM_6348_PCMDMA_BASE (0xdeadbeef) #define BCM_6348_PCMDMAC_BASE (0xdeadbeef) #define BCM_6348_PCMDMAS_BASE (0xdeadbeef) +#define BCM_6348_RNG_BASE (0xdeadbeef) +#define BCM_6348_MISC_BASE (0xdeadbeef) /* * 6358 register sets base address @@ -289,14 +360,14 @@ enum bcm63xx_regs_set { #define BCM_6358_UART0_BASE (0xfffe0100) #define BCM_6358_UART1_BASE (0xfffe0120) #define BCM_6358_GPIO_BASE (0xfffe0080) -#define BCM_6358_SPI_BASE (0xdeadbeef) -#define BCM_6358_SPI2_BASE (0xfffe0800) +#define BCM_6358_SPI_BASE (0xfffe0800) #define BCM_6358_UDC0_BASE (0xfffe0800) #define BCM_6358_OHCI0_BASE (0xfffe1400) #define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef) #define BCM_6358_USBH_PRIV_BASE (0xfffe1500) #define BCM_6358_MPI_BASE (0xfffe1000) #define BCM_6358_PCMCIA_BASE (0xfffe1054) +#define BCM_6358_PCIE_BASE (0xdeadbeef) #define BCM_6358_SDRAM_REGS_BASE (0xfffe2300) #define BCM_6358_M2M_BASE (0xdeadbeef) #define BCM_6358_DSL_BASE (0xfffe3000) @@ -319,6 +390,8 @@ enum bcm63xx_regs_set { #define BCM_6358_PCMDMA_BASE (0xfffe1800) #define BCM_6358_PCMDMAC_BASE (0xfffe1900) #define BCM_6358_PCMDMAS_BASE (0xfffe1a00) +#define BCM_6358_RNG_BASE (0xdeadbeef) +#define BCM_6358_MISC_BASE (0xdeadbeef) /* @@ -331,14 +404,14 @@ enum bcm63xx_regs_set { #define BCM_6368_UART0_BASE (0xb0000100) #define BCM_6368_UART1_BASE (0xb0000120) #define BCM_6368_GPIO_BASE (0xb0000080) -#define BCM_6368_SPI_BASE (0xdeadbeef) -#define BCM_6368_SPI2_BASE (0xb0000800) +#define BCM_6368_SPI_BASE (0xb0000800) #define BCM_6368_UDC0_BASE (0xdeadbeef) #define BCM_6368_OHCI0_BASE (0xb0001600) #define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef) #define BCM_6368_USBH_PRIV_BASE (0xb0001700) #define BCM_6368_MPI_BASE (0xb0001000) #define BCM_6368_PCMCIA_BASE (0xb0001054) +#define BCM_6368_PCIE_BASE (0xdeadbeef) #define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef) #define BCM_6368_M2M_BASE (0xdeadbeef) #define BCM_6368_DSL_BASE (0xdeadbeef) @@ -361,6 +434,8 @@ enum bcm63xx_regs_set { #define BCM_6368_PCMDMA_BASE (0xb0005800) #define BCM_6368_PCMDMAC_BASE (0xb0005a00) #define BCM_6368_PCMDMAS_BASE (0xb0005c00) +#define BCM_6368_RNG_BASE (0xb0004180) +#define BCM_6368_MISC_BASE (0xdeadbeef) extern const unsigned long *bcm63xx_regs_base; @@ -379,13 +454,13 @@ extern const unsigned long *bcm63xx_regs_base; __GEN_RSET_BASE(__cpu, UART1) \ __GEN_RSET_BASE(__cpu, GPIO) \ __GEN_RSET_BASE(__cpu, SPI) \ - __GEN_RSET_BASE(__cpu, SPI2) \ __GEN_RSET_BASE(__cpu, UDC0) \ __GEN_RSET_BASE(__cpu, OHCI0) \ __GEN_RSET_BASE(__cpu, OHCI_PRIV) \ __GEN_RSET_BASE(__cpu, USBH_PRIV) \ __GEN_RSET_BASE(__cpu, MPI) \ __GEN_RSET_BASE(__cpu, PCMCIA) \ + __GEN_RSET_BASE(__cpu, PCIE) \ __GEN_RSET_BASE(__cpu, DSL) \ __GEN_RSET_BASE(__cpu, ENET0) \ __GEN_RSET_BASE(__cpu, ENET1) \ @@ -407,6 +482,8 @@ extern const unsigned long *bcm63xx_regs_base; __GEN_RSET_BASE(__cpu, PCMDMA) \ __GEN_RSET_BASE(__cpu, PCMDMAC) \ __GEN_RSET_BASE(__cpu, PCMDMAS) \ + __GEN_RSET_BASE(__cpu, RNG) \ + __GEN_RSET_BASE(__cpu, MISC) \ } #define __GEN_CPU_REGS_TABLE(__cpu) \ @@ -418,13 +495,13 @@ extern const unsigned long *bcm63xx_regs_base; [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \ [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \ [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \ - [RSET_SPI2] = BCM_## __cpu ##_SPI2_BASE, \ [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \ [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \ [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \ [RSET_USBH_PRIV] = BCM_## __cpu ##_USBH_PRIV_BASE, \ [RSET_MPI] = BCM_## __cpu ##_MPI_BASE, \ [RSET_PCMCIA] = BCM_## __cpu ##_PCMCIA_BASE, \ + [RSET_PCIE] = BCM_## __cpu ##_PCIE_BASE, \ [RSET_DSL] = BCM_## __cpu ##_DSL_BASE, \ [RSET_ENET0] = BCM_## __cpu ##_ENET0_BASE, \ [RSET_ENET1] = BCM_## __cpu ##_ENET1_BASE, \ @@ -446,6 +523,8 @@ extern const unsigned long *bcm63xx_regs_base; [RSET_PCMDMA] = BCM_## __cpu ##_PCMDMA_BASE, \ [RSET_PCMDMAC] = BCM_## __cpu ##_PCMDMAC_BASE, \ [RSET_PCMDMAS] = BCM_## __cpu ##_PCMDMAS_BASE, \ + [RSET_RNG] = BCM_## __cpu ##_RNG_BASE, \ + [RSET_MISC] = BCM_## __cpu ##_MISC_BASE, \ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) @@ -453,6 +532,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) #ifdef BCMCPU_RUNTIME_DETECT return bcm63xx_regs_base[set]; #else +#ifdef CONFIG_BCM63XX_CPU_6328 + __GEN_RSET(6328) +#endif #ifdef CONFIG_BCM63XX_CPU_6338 __GEN_RSET(6338) #endif @@ -478,6 +560,7 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) */ enum bcm63xx_irq { IRQ_TIMER = 0, + IRQ_SPI, IRQ_UART0, IRQ_UART1, IRQ_DSL, @@ -506,9 +589,51 @@ enum bcm63xx_irq { }; /* + * 6328 irqs + */ +#define BCM_6328_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) + +#define BCM_6328_TIMER_IRQ (IRQ_INTERNAL_BASE + 31) +#define BCM_6328_SPI_IRQ 0 +#define BCM_6328_UART0_IRQ (IRQ_INTERNAL_BASE + 28) +#define BCM_6328_UART1_IRQ (BCM_6328_HIGH_IRQ_BASE + 7) +#define BCM_6328_DSL_IRQ (IRQ_INTERNAL_BASE + 4) +#define BCM_6328_UDC0_IRQ 0 +#define BCM_6328_ENET0_IRQ 0 +#define BCM_6328_ENET1_IRQ 0 +#define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12) +#define BCM_6328_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9) +#define BCM_6328_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10) +#define BCM_6328_PCMCIA_IRQ 0 +#define BCM_6328_ENET0_RXDMA_IRQ 0 +#define BCM_6328_ENET0_TXDMA_IRQ 0 +#define BCM_6328_ENET1_RXDMA_IRQ 0 +#define BCM_6328_ENET1_TXDMA_IRQ 0 +#define BCM_6328_PCI_IRQ (IRQ_INTERNAL_BASE + 23) +#define BCM_6328_ATM_IRQ 0 +#define BCM_6328_ENETSW_RXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 0) +#define BCM_6328_ENETSW_RXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 1) +#define BCM_6328_ENETSW_RXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 2) +#define BCM_6328_ENETSW_RXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 3) +#define BCM_6328_ENETSW_TXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 4) +#define BCM_6328_ENETSW_TXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 5) +#define BCM_6328_ENETSW_TXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 6) +#define BCM_6328_ENETSW_TXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 7) +#define BCM_6328_XTM_IRQ (BCM_6328_HIGH_IRQ_BASE + 31) +#define BCM_6328_XTM_DMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 11) + +#define BCM_6328_PCM_DMA0_IRQ (IRQ_INTERNAL_BASE + 2) +#define BCM_6328_PCM_DMA1_IRQ (IRQ_INTERNAL_BASE + 3) +#define BCM_6328_EXT_IRQ0 (IRQ_INTERNAL_BASE + 24) +#define BCM_6328_EXT_IRQ1 (IRQ_INTERNAL_BASE + 25) +#define BCM_6328_EXT_IRQ2 (IRQ_INTERNAL_BASE + 26) +#define BCM_6328_EXT_IRQ3 (IRQ_INTERNAL_BASE + 27) + +/* * 6338 irqs */ #define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6338_SPI_IRQ (IRQ_INTERNAL_BASE + 1) #define BCM_6338_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6338_UART1_IRQ 0 #define BCM_6338_DSL_IRQ (IRQ_INTERNAL_BASE + 5) @@ -539,6 +664,7 @@ enum bcm63xx_irq { * 6345 irqs */ #define BCM_6345_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6345_SPI_IRQ 0 #define BCM_6345_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6345_UART1_IRQ 0 #define BCM_6345_DSL_IRQ (IRQ_INTERNAL_BASE + 3) @@ -569,6 +695,7 @@ enum bcm63xx_irq { * 6348 irqs */ #define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6348_SPI_IRQ (IRQ_INTERNAL_BASE + 1) #define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6348_UART1_IRQ 0 #define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4) @@ -599,6 +726,7 @@ enum bcm63xx_irq { * 6358 irqs */ #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6358_SPI_IRQ (IRQ_INTERNAL_BASE + 1) #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3) #define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29) @@ -638,6 +766,7 @@ enum bcm63xx_irq { #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) #define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) +#define BCM_6368_SPI_IRQ (IRQ_INTERNAL_BASE + 1) #define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3) #define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4) @@ -677,6 +806,7 @@ extern const int *bcm63xx_irqs; #define __GEN_CPU_IRQ_TABLE(__cpu) \ [IRQ_TIMER] = BCM_## __cpu ##_TIMER_IRQ, \ + [IRQ_SPI] = BCM_## __cpu ##_SPI_IRQ, \ [IRQ_UART0] = BCM_## __cpu ##_UART0_IRQ, \ [IRQ_UART1] = BCM_## __cpu ##_UART1_IRQ, \ [IRQ_DSL] = BCM_## __cpu ##_DSL_IRQ, \ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h new file mode 100644 index 00000000000..354b8481ec4 --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_flash.h @@ -0,0 +1,12 @@ +#ifndef __BCM63XX_FLASH_H +#define __BCM63XX_FLASH_H + +enum { + BCM63XX_FLASH_TYPE_PARALLEL, + BCM63XX_FLASH_TYPE_SERIAL, + BCM63XX_FLASH_TYPE_NAND, +}; + +int __init bcm63xx_flash_register(void); + +#endif /* __BCM63XX_FLASH_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h new file mode 100644 index 00000000000..7d98dbe5d4b --- /dev/null +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h @@ -0,0 +1,89 @@ +#ifndef BCM63XX_DEV_SPI_H +#define BCM63XX_DEV_SPI_H + +#include <linux/types.h> +#include <bcm63xx_io.h> +#include <bcm63xx_regs.h> + +int __init bcm63xx_spi_register(void); + +struct bcm63xx_spi_pdata { + unsigned int fifo_size; + int bus_num; + int num_chipselect; + u32 speed_hz; +}; + +enum bcm63xx_regs_spi { + SPI_CMD, + SPI_INT_STATUS, + SPI_INT_MASK_ST, + SPI_INT_MASK, + SPI_ST, + SPI_CLK_CFG, + SPI_FILL_BYTE, + SPI_MSG_TAIL, + SPI_RX_TAIL, + SPI_MSG_CTL, + SPI_MSG_DATA, + SPI_RX_DATA, +}; + +#define __GEN_SPI_RSET_BASE(__cpu, __rset) \ + case SPI_## __rset: \ + return SPI_## __cpu ##_## __rset; + +#define __GEN_SPI_RSET(__cpu) \ + switch (reg) { \ + __GEN_SPI_RSET_BASE(__cpu, CMD) \ + __GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \ + __GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \ + __GEN_SPI_RSET_BASE(__cpu, INT_MASK) \ + __GEN_SPI_RSET_BASE(__cpu, ST) \ + __GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \ + __GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \ + __GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \ + __GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \ + __GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \ + __GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \ + __GEN_SPI_RSET_BASE(__cpu, RX_DATA) \ + } + +#define __GEN_SPI_REGS_TABLE(__cpu) \ + [SPI_CMD] = SPI_## __cpu ##_CMD, \ + [SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \ + [SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \ + [SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \ + [SPI_ST] = SPI_## __cpu ##_ST, \ + [SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \ + [SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \ + [SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \ + [SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \ + [SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \ + [SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \ + [SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA, + +static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg) +{ +#ifdef BCMCPU_RUNTIME_DETECT + extern const unsigned long *bcm63xx_regs_spi; + + return bcm63xx_regs_spi[reg]; +#else +#ifdef CONFIG_BCM63XX_CPU_6338 + __GEN_SPI_RSET(6338) +#endif +#ifdef CONFIG_BCM63XX_CPU_6348 + __GEN_SPI_RSET(6348) +#endif +#ifdef CONFIG_BCM63XX_CPU_6358 + __GEN_SPI_RSET(6358) +#endif +#ifdef CONFIG_BCM63XX_CPU_6368 + __GEN_SPI_RSET(6368) +#endif +#endif + return 0; +} + +#endif /* BCM63XX_DEV_SPI_H */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h index 1d7dd96aa46..0a9891f7580 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_gpio.h @@ -9,6 +9,8 @@ int __init bcm63xx_gpio_init(void); static inline unsigned long bcm63xx_gpio_count(void) { switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + return 32; case BCM6358_CPU_ID: return 40; case BCM6338_CPU_ID: diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h index 72477a6441d..9203d90e610 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h @@ -40,6 +40,10 @@ #define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \ BCM_CB_MEM_SIZE - 1) +#define BCM_PCIE_MEM_BASE_PA 0x10f00000 +#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024) +#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \ + BCM_PCIE_MEM_SIZE - 1) /* * Internal registers are accessed through KSEG3 @@ -85,11 +89,15 @@ #define bcm_mpi_writel(v, o) bcm_rset_writel(RSET_MPI, (v), (o)) #define bcm_pcmcia_readl(o) bcm_rset_readl(RSET_PCMCIA, (o)) #define bcm_pcmcia_writel(v, o) bcm_rset_writel(RSET_PCMCIA, (v), (o)) +#define bcm_pcie_readl(o) bcm_rset_readl(RSET_PCIE, (o)) +#define bcm_pcie_writel(v, o) bcm_rset_writel(RSET_PCIE, (v), (o)) #define bcm_sdram_readl(o) bcm_rset_readl(RSET_SDRAM, (o)) #define bcm_sdram_writel(v, o) bcm_rset_writel(RSET_SDRAM, (v), (o)) #define bcm_memc_readl(o) bcm_rset_readl(RSET_MEMC, (o)) #define bcm_memc_writel(v, o) bcm_rset_writel(RSET_MEMC, (v), (o)) #define bcm_ddr_readl(o) bcm_rset_readl(RSET_DDR, (o)) #define bcm_ddr_writel(v, o) bcm_rset_writel(RSET_DDR, (v), (o)) +#define bcm_misc_readl(o) bcm_rset_readl(RSET_MISC, (o)) +#define bcm_misc_writel(v, o) bcm_rset_writel(RSET_MISC, (v), (o)) #endif /* ! BCM63XX_IO_H_ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h index fdcd78ca1b0..4ccc2a748af 100644 --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h @@ -15,6 +15,30 @@ /* Clock Control register */ #define PERF_CKCTL_REG 0x4 +#define CKCTL_6328_PHYMIPS_EN (1 << 0) +#define CKCTL_6328_ADSL_QPROC_EN (1 << 1) +#define CKCTL_6328_ADSL_AFE_EN (1 << 2) +#define CKCTL_6328_ADSL_EN (1 << 3) +#define CKCTL_6328_MIPS_EN (1 << 4) +#define CKCTL_6328_SAR_EN (1 << 5) +#define CKCTL_6328_PCM_EN (1 << 6) +#define CKCTL_6328_USBD_EN (1 << 7) +#define CKCTL_6328_USBH_EN (1 << 8) +#define CKCTL_6328_HSSPI_EN (1 << 9) +#define CKCTL_6328_PCIE_EN (1 << 10) +#define CKCTL_6328_ROBOSW_EN (1 << 11) + +#define CKCTL_6328_ALL_SAFE_EN (CKCTL_6328_PHYMIPS_EN | \ + CKCTL_6328_ADSL_QPROC_EN | \ + CKCTL_6328_ADSL_AFE_EN | \ + CKCTL_6328_ADSL_EN | \ + CKCTL_6328_SAR_EN | \ + CKCTL_6328_PCM_EN | \ + CKCTL_6328_USBD_EN | \ + CKCTL_6328_USBH_EN | \ + CKCTL_6328_ROBOSW_EN | \ + CKCTL_6328_PCIE_EN) + #define CKCTL_6338_ADSLPHY_EN (1 << 0) #define CKCTL_6338_MPI_EN (1 << 1) #define CKCTL_6338_DRAM_EN (1 << 2) @@ -90,35 +114,36 @@ #define CKCTL_6368_PHYMIPS_EN (1 << 6) #define CKCTL_6368_SWPKT_USB_EN (1 << 7) #define CKCTL_6368_SWPKT_SAR_EN (1 << 8) -#define CKCTL_6368_SPI_CLK_EN (1 << 9) -#define CKCTL_6368_USBD_CLK_EN (1 << 10) -#define CKCTL_6368_SAR_CLK_EN (1 << 11) -#define CKCTL_6368_ROBOSW_CLK_EN (1 << 12) -#define CKCTL_6368_UTOPIA_CLK_EN (1 << 13) -#define CKCTL_6368_PCM_CLK_EN (1 << 14) -#define CKCTL_6368_USBH_CLK_EN (1 << 15) +#define CKCTL_6368_SPI_EN (1 << 9) +#define CKCTL_6368_USBD_EN (1 << 10) +#define CKCTL_6368_SAR_EN (1 << 11) +#define CKCTL_6368_ROBOSW_EN (1 << 12) +#define CKCTL_6368_UTOPIA_EN (1 << 13) +#define CKCTL_6368_PCM_EN (1 << 14) +#define CKCTL_6368_USBH_EN (1 << 15) #define CKCTL_6368_DISABLE_GLESS_EN (1 << 16) -#define CKCTL_6368_NAND_CLK_EN (1 << 17) -#define CKCTL_6368_IPSEC_CLK_EN (1 << 18) +#define CKCTL_6368_NAND_EN (1 << 17) +#define CKCTL_6368_IPSEC_EN (1 << 18) #define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \ CKCTL_6368_SWPKT_SAR_EN | \ - CKCTL_6368_SPI_CLK_EN | \ - CKCTL_6368_USBD_CLK_EN | \ - CKCTL_6368_SAR_CLK_EN | \ - CKCTL_6368_ROBOSW_CLK_EN | \ - CKCTL_6368_UTOPIA_CLK_EN | \ - CKCTL_6368_PCM_CLK_EN | \ - CKCTL_6368_USBH_CLK_EN | \ + CKCTL_6368_SPI_EN | \ + CKCTL_6368_USBD_EN | \ + CKCTL_6368_SAR_EN | \ + CKCTL_6368_ROBOSW_EN | \ + CKCTL_6368_UTOPIA_EN | \ + CKCTL_6368_PCM_EN | \ + CKCTL_6368_USBH_EN | \ CKCTL_6368_DISABLE_GLESS_EN | \ - CKCTL_6368_NAND_CLK_EN | \ - CKCTL_6368_IPSEC_CLK_EN) + CKCTL_6368_NAND_EN | \ + CKCTL_6368_IPSEC_EN) /* System PLL Control register */ #define PERF_SYS_PLL_CTL_REG 0x8 #define SYS_PLL_SOFT_RESET 0x1 /* Interrupt Mask register */ +#define PERF_IRQMASK_6328_REG 0x20 #define PERF_IRQMASK_6338_REG 0xc #define PERF_IRQMASK_6345_REG 0xc #define PERF_IRQMASK_6348_REG 0xc @@ -126,6 +151,7 @@ #define PERF_IRQMASK_6368_REG 0x20 /* Interrupt Status register */ +#define PERF_IRQSTAT_6328_REG 0x28 #define PERF_IRQSTAT_6338_REG 0x10 #define PERF_IRQSTAT_6345_REG 0x10 #define PERF_IRQSTAT_6348_REG 0x10 @@ -133,6 +159,7 @@ #define PERF_IRQSTAT_6368_REG 0x28 /* External Interrupt Configuration register */ +#define PERF_EXTIRQ_CFG_REG_6328 0x18 #define PERF_EXTIRQ_CFG_REG_6338 0x14 #define PERF_EXTIRQ_CFG_REG_6348 0x14 #define PERF_EXTIRQ_CFG_REG_6358 0x14 @@ -162,8 +189,21 @@ /* Soft Reset register */ #define PERF_SOFTRESET_REG 0x28 +#define PERF_SOFTRESET_6328_REG 0x10 #define PERF_SOFTRESET_6368_REG 0x10 +#define SOFTRESET_6328_SPI_MASK (1 << 0) +#define SOFTRESET_6328_EPHY_MASK (1 << 1) +#define SOFTRESET_6328_SAR_MASK (1 << 2) +#define SOFTRESET_6328_ENETSW_MASK (1 << 3) +#define SOFTRESET_6328_USBS_MASK (1 << 4) +#define SOFTRESET_6328_USBH_MASK (1 << 5) +#define SOFTRESET_6328_PCM_MASK (1 << 6) +#define SOFTRESET_6328_PCIE_CORE_MASK (1 << 7) +#define SOFTRESET_6328_PCIE_MASK (1 << 8) +#define SOFTRESET_6328_PCIE_EXT_MASK (1 << 9) +#define SOFTRESET_6328_PCIE_HARD_MASK (1 << 10) + #define SOFTRESET_6338_SPI_MASK (1 << 0) #define SOFTRESET_6338_ENET_MASK (1 << 2) #define SOFTRESET_6338_USBH_MASK (1 << 3) @@ -307,6 +347,8 @@ /* Watchdog reset length register */ #define WDT_RSTLEN_REG 0x8 +/* Watchdog soft reset register (BCM6328 only) */ +#define WDT_SOFTRESET_REG 0xc /************************************************************************* * _REG relative to RSET_UARTx @@ -507,6 +549,15 @@ #define GPIO_BASEMODE_6368_MASK 0x7 /* those bits must be kept as read in gpio basemode register*/ +#define GPIO_STRAPBUS_REG 0x40 +#define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1) +#define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1) +#define STRAPBUS_6368_BOOT_SEL_MASK 0x3 +#define STRAPBUS_6368_BOOT_SEL_NAND 0 +#define STRAPBUS_6368_BOOT_SEL_SERIAL 1 +#define STRAPBUS_6368_BOOT_SEL_PARALLEL 3 + + /************************************************************************* * _REG relative to RSET_ENET *************************************************************************/ @@ -924,6 +975,8 @@ * _REG relative to RSET_DDR *************************************************************************/ +#define DDR_CSEND_REG 0x8 + #define DDR_DMIPSPLLCFG_REG 0x18 #define DMIPSPLLCFG_M1_SHIFT 0 #define DMIPSPLLCFG_M1_MASK (0xff << DMIPSPLLCFG_M1_SHIFT) @@ -973,4 +1026,201 @@ #define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14) #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18) +/************************************************************************* + * _REG relative to RSET_RNG + *************************************************************************/ + +#define RNG_CTRL 0x00 +#define RNG_EN (1 << 0) + +#define RNG_STAT 0x04 +#define RNG_AVAIL_MASK (0xff000000) + +#define RNG_DATA 0x08 +#define RNG_THRES 0x0c +#define RNG_MASK 0x10 + +/************************************************************************* + * _REG relative to RSET_SPI + *************************************************************************/ + +/* BCM 6338 SPI core */ +#define SPI_6338_CMD 0x00 /* 16-bits register */ +#define SPI_6338_INT_STATUS 0x02 +#define SPI_6338_INT_MASK_ST 0x03 +#define SPI_6338_INT_MASK 0x04 +#define SPI_6338_ST 0x05 +#define SPI_6338_CLK_CFG 0x06 +#define SPI_6338_FILL_BYTE 0x07 +#define SPI_6338_MSG_TAIL 0x09 +#define SPI_6338_RX_TAIL 0x0b +#define SPI_6338_MSG_CTL 0x40 +#define SPI_6338_MSG_DATA 0x41 +#define SPI_6338_MSG_DATA_SIZE 0x3f +#define SPI_6338_RX_DATA 0x80 +#define SPI_6338_RX_DATA_SIZE 0x3f + +/* BCM 6348 SPI core */ +#define SPI_6348_CMD 0x00 /* 16-bits register */ +#define SPI_6348_INT_STATUS 0x02 +#define SPI_6348_INT_MASK_ST 0x03 +#define SPI_6348_INT_MASK 0x04 +#define SPI_6348_ST 0x05 +#define SPI_6348_CLK_CFG 0x06 +#define SPI_6348_FILL_BYTE 0x07 +#define SPI_6348_MSG_TAIL 0x09 +#define SPI_6348_RX_TAIL 0x0b +#define SPI_6348_MSG_CTL 0x40 +#define SPI_6348_MSG_DATA 0x41 +#define SPI_6348_MSG_DATA_SIZE 0x3f +#define SPI_6348_RX_DATA 0x80 +#define SPI_6348_RX_DATA_SIZE 0x3f + +/* BCM 6358 SPI core */ +#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */ +#define SPI_6358_MSG_DATA 0x02 +#define SPI_6358_MSG_DATA_SIZE 0x21e +#define SPI_6358_RX_DATA 0x400 +#define SPI_6358_RX_DATA_SIZE 0x220 +#define SPI_6358_CMD 0x700 /* 16-bits register */ +#define SPI_6358_INT_STATUS 0x702 +#define SPI_6358_INT_MASK_ST 0x703 +#define SPI_6358_INT_MASK 0x704 +#define SPI_6358_ST 0x705 +#define SPI_6358_CLK_CFG 0x706 +#define SPI_6358_FILL_BYTE 0x707 +#define SPI_6358_MSG_TAIL 0x709 +#define SPI_6358_RX_TAIL 0x70B + +/* BCM 6358 SPI core */ +#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */ +#define SPI_6368_MSG_DATA 0x02 +#define SPI_6368_MSG_DATA_SIZE 0x21e +#define SPI_6368_RX_DATA 0x400 +#define SPI_6368_RX_DATA_SIZE 0x220 +#define SPI_6368_CMD 0x700 /* 16-bits register */ +#define SPI_6368_INT_STATUS 0x702 +#define SPI_6368_INT_MASK_ST 0x703 +#define SPI_6368_INT_MASK 0x704 +#define SPI_6368_ST 0x705 +#define SPI_6368_CLK_CFG 0x706 +#define SPI_6368_FILL_BYTE 0x707 +#define SPI_6368_MSG_TAIL 0x709 +#define SPI_6368_RX_TAIL 0x70B + +/* Shared SPI definitions */ + +/* Message configuration */ +#define SPI_FD_RW 0x00 +#define SPI_HD_W 0x01 +#define SPI_HD_R 0x02 +#define SPI_BYTE_CNT_SHIFT 0 +#define SPI_MSG_TYPE_SHIFT 14 + +/* Command */ +#define SPI_CMD_NOOP 0x00 +#define SPI_CMD_SOFT_RESET 0x01 +#define SPI_CMD_HARD_RESET 0x02 +#define SPI_CMD_START_IMMEDIATE 0x03 +#define SPI_CMD_COMMAND_SHIFT 0 +#define SPI_CMD_COMMAND_MASK 0x000f +#define SPI_CMD_DEVICE_ID_SHIFT 4 +#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8 +#define SPI_CMD_ONE_BYTE_SHIFT 11 +#define SPI_CMD_ONE_WIRE_SHIFT 12 +#define SPI_DEV_ID_0 0 +#define SPI_DEV_ID_1 1 +#define SPI_DEV_ID_2 2 +#define SPI_DEV_ID_3 3 + +/* Interrupt mask */ +#define SPI_INTR_CMD_DONE 0x01 +#define SPI_INTR_RX_OVERFLOW 0x02 +#define SPI_INTR_TX_UNDERFLOW 0x04 +#define SPI_INTR_TX_OVERFLOW 0x08 +#define SPI_INTR_RX_UNDERFLOW 0x10 +#define SPI_INTR_CLEAR_ALL 0x1f + +/* Status */ +#define SPI_RX_EMPTY 0x02 +#define SPI_CMD_BUSY 0x04 +#define SPI_SERIAL_BUSY 0x08 + +/* Clock configuration */ +#define SPI_CLK_20MHZ 0x00 +#define SPI_CLK_0_391MHZ 0x01 +#define SPI_CLK_0_781MHZ 0x02 /* default */ +#define SPI_CLK_1_563MHZ 0x03 +#define SPI_CLK_3_125MHZ 0x04 +#define SPI_CLK_6_250MHZ 0x05 +#define SPI_CLK_12_50MHZ 0x06 +#define SPI_CLK_MASK 0x07 +#define SPI_SSOFFTIME_MASK 0x38 +#define SPI_SSOFFTIME_SHIFT 3 +#define SPI_BYTE_SWAP 0x80 + +/************************************************************************* + * _REG relative to RSET_MISC + *************************************************************************/ +#define MISC_SERDES_CTRL_REG 0x0 +#define SERDES_PCIE_EN (1 << 0) +#define SERDES_PCIE_EXD_EN (1 << 15) + +#define MISC_STRAPBUS_6328_REG 0x240 +#define STRAPBUS_6328_FCVO_SHIFT 7 +#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT) +#define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28) +#define STRAPBUS_6328_BOOT_SEL_NAND (0 << 28) + +/************************************************************************* + * _REG relative to RSET_PCIE + *************************************************************************/ + +#define PCIE_CONFIG2_REG 0x408 +#define CONFIG2_BAR1_SIZE_EN 1 +#define CONFIG2_BAR1_SIZE_MASK 0xf + +#define PCIE_IDVAL3_REG 0x43c +#define IDVAL3_CLASS_CODE_MASK 0xffffff +#define IDVAL3_SUBCLASS_SHIFT 8 +#define IDVAL3_CLASS_SHIFT 16 + +#define PCIE_DLSTATUS_REG 0x1048 +#define DLSTATUS_PHYLINKUP (1 << 13) + +#define PCIE_BRIDGE_OPT1_REG 0x2820 +#define OPT1_RD_BE_OPT_EN (1 << 7) +#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9) +#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11) +#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12) + +#define PCIE_BRIDGE_OPT2_REG 0x2824 +#define OPT2_UBUS_UR_DECODE_DIS (1 << 2) +#define OPT2_TX_CREDIT_CHK_EN (1 << 4) +#define OPT2_CFG_TYPE1_BD_SEL (1 << 7) +#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16 +#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT) + +#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828 +#define PCIE_BRIDGE_BAR1_BASEMASK_REG 0x2830 +#define BASEMASK_REMAP_EN (1 << 0) +#define BASEMASK_SWAP_EN (1 << 1) +#define BASEMASK_MASK_SHIFT 4 +#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT) +#define BASEMASK_BASE_SHIFT 20 +#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT) + +#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c +#define PCIE_BRIDGE_BAR1_REBASE_ADDR_REG 0x2834 +#define REBASE_ADDR_BASE_SHIFT 20 +#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT) + +#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854 +#define PCIE_RC_INT_A (1 << 0) +#define PCIE_RC_INT_B (1 << 1) +#define PCIE_RC_INT_C (1 << 2) +#define PCIE_RC_INT_D (1 << 3) + +#define PCIE_DEVICE_OFFSET 0x8000 + #endif /* BCM63XX_REGS_H_ */ diff --git a/arch/mips/include/asm/mach-bcm63xx/ioremap.h b/arch/mips/include/asm/mach-bcm63xx/ioremap.h index ef94ba73646..30931c42379 100644 --- a/arch/mips/include/asm/mach-bcm63xx/ioremap.h +++ b/arch/mips/include/asm/mach-bcm63xx/ioremap.h @@ -18,6 +18,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset) if (offset >= 0xfff00000) return 1; break; + case BCM6328_CPU_ID: case BCM6368_CPU_ID: if (offset >= 0xb0000000 && offset < 0xb1000000) return 1; diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index 5b05f186e39..418992042f6 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -41,61 +41,26 @@ enum octeon_irq { OCTEON_IRQ_TWSI, OCTEON_IRQ_TWSI2, OCTEON_IRQ_RML, - OCTEON_IRQ_TRACE0, - OCTEON_IRQ_GMX_DRP0 = OCTEON_IRQ_TRACE0 + 4, - OCTEON_IRQ_IPD_DRP = OCTEON_IRQ_GMX_DRP0 + 5, - OCTEON_IRQ_KEY_ZERO, OCTEON_IRQ_TIMER0, OCTEON_IRQ_TIMER1, OCTEON_IRQ_TIMER2, OCTEON_IRQ_TIMER3, OCTEON_IRQ_USB0, OCTEON_IRQ_USB1, - OCTEON_IRQ_PCM, - OCTEON_IRQ_MPI, - OCTEON_IRQ_POWIQ, - OCTEON_IRQ_IPDPPTHR, OCTEON_IRQ_MII0, OCTEON_IRQ_MII1, OCTEON_IRQ_BOOTDMA, - - OCTEON_IRQ_NAND, - OCTEON_IRQ_MIO, /* Summary of MIO_BOOT_ERR */ - OCTEON_IRQ_IOB, /* Summary of IOB_INT_SUM */ - OCTEON_IRQ_FPA, /* Summary of FPA_INT_SUM */ - OCTEON_IRQ_POW, /* Summary of POW_ECC_ERR */ - OCTEON_IRQ_L2C, /* Summary of L2C_INT_STAT */ - OCTEON_IRQ_IPD, /* Summary of IPD_INT_SUM */ - OCTEON_IRQ_PIP, /* Summary of PIP_INT_REG */ - OCTEON_IRQ_PKO, /* Summary of PKO_REG_ERROR */ - OCTEON_IRQ_ZIP, /* Summary of ZIP_ERROR */ - OCTEON_IRQ_TIM, /* Summary of TIM_REG_ERROR */ - OCTEON_IRQ_RAD, /* Summary of RAD_REG_ERROR */ - OCTEON_IRQ_KEY, /* Summary of KEY_INT_SUM */ - OCTEON_IRQ_DFA, /* Summary of DFA */ - OCTEON_IRQ_USBCTL, /* Summary of USBN0_INT_SUM */ - OCTEON_IRQ_SLI, /* Summary of SLI_INT_SUM */ - OCTEON_IRQ_DPI, /* Summary of DPI_INT_SUM */ - OCTEON_IRQ_AGX0, /* Summary of GMX0*+PCS0_INT*_REG */ - OCTEON_IRQ_AGL = OCTEON_IRQ_AGX0 + 5, - OCTEON_IRQ_PTP, - OCTEON_IRQ_PEM0, - OCTEON_IRQ_PEM1, - OCTEON_IRQ_SRIO0, - OCTEON_IRQ_SRIO1, - OCTEON_IRQ_LMC0, - OCTEON_IRQ_DFM = OCTEON_IRQ_LMC0 + 4, /* Summary of DFM */ - OCTEON_IRQ_RST, +#ifndef CONFIG_PCI_MSI + OCTEON_IRQ_LAST = 127 +#endif }; #ifdef CONFIG_PCI_MSI -/* 152 - 407 represent the MSI interrupts 0-255 */ -#define OCTEON_IRQ_MSI_BIT0 (OCTEON_IRQ_RST + 1) +/* 256 - 511 represent the MSI interrupts 0-255 */ +#define OCTEON_IRQ_MSI_BIT0 (256) #define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) #define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) -#else -#define OCTEON_IRQ_LAST (OCTEON_IRQ_RST + 1) #endif #endif diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h index bb5b9a4e29c..986982db7c3 100644 --- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h +++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h @@ -19,6 +19,8 @@ #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#define JZ_NAND_NUM_BANKS 4 + struct jz_nand_platform_data { int num_partitions; struct mtd_partition *partitions; @@ -27,6 +29,8 @@ struct jz_nand_platform_data { unsigned int busy_gpio; + unsigned char banks[JZ_NAND_NUM_BANKS]; + void (*ident_callback)(struct platform_device *, struct nand_chip *, struct mtd_partition **, int *num_partitions); }; diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h index 1e29b9dd1d7..06367c37e1b 100644 --- a/arch/mips/include/asm/mach-loongson/loongson.h +++ b/arch/mips/include/asm/mach-loongson/loongson.h @@ -14,6 +14,7 @@ #include <linux/io.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/kconfig.h> /* loongson internal northbridge initialization */ extern void bonito_irq_init(void); @@ -66,7 +67,7 @@ extern int mach_i8259_irq(void); #include <linux/interrupt.h> static inline void do_perfcnt_IRQ(void) { -#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) +#if IS_ENABLED(CONFIG_OPROFILE) do_IRQ(LOONGSON2_PERFCNT_IRQ); #endif } diff --git a/arch/mips/include/asm/mach-loongson1/irq.h b/arch/mips/include/asm/mach-loongson1/irq.h new file mode 100644 index 00000000000..da96ed42f73 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/irq.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> + * + * IRQ mappings for Loongson 1 + * + * 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 __ASM_MACH_LOONGSON1_IRQ_H +#define __ASM_MACH_LOONGSON1_IRQ_H + +/* + * CPU core Interrupt Numbers + */ +#define MIPS_CPU_IRQ_BASE 0 +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x)) + +#define SOFTINT0_IRQ MIPS_CPU_IRQ(0) +#define SOFTINT1_IRQ MIPS_CPU_IRQ(1) +#define INT0_IRQ MIPS_CPU_IRQ(2) +#define INT1_IRQ MIPS_CPU_IRQ(3) +#define INT2_IRQ MIPS_CPU_IRQ(4) +#define INT3_IRQ MIPS_CPU_IRQ(5) +#define INT4_IRQ MIPS_CPU_IRQ(6) +#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu timer */ + +#define MIPS_CPU_IRQS (MIPS_CPU_IRQ(7) + 1 - MIPS_CPU_IRQ_BASE) + +/* + * INT0~3 Interrupt Numbers + */ +#define LS1X_IRQ_BASE MIPS_CPU_IRQS +#define LS1X_IRQ(n, x) (LS1X_IRQ_BASE + (n << 5) + (x)) + +#define LS1X_UART0_IRQ LS1X_IRQ(0, 2) +#define LS1X_UART1_IRQ LS1X_IRQ(0, 3) +#define LS1X_UART2_IRQ LS1X_IRQ(0, 4) +#define LS1X_UART3_IRQ LS1X_IRQ(0, 5) +#define LS1X_CAN0_IRQ LS1X_IRQ(0, 6) +#define LS1X_CAN1_IRQ LS1X_IRQ(0, 7) +#define LS1X_SPI0_IRQ LS1X_IRQ(0, 8) +#define LS1X_SPI1_IRQ LS1X_IRQ(0, 9) +#define LS1X_AC97_IRQ LS1X_IRQ(0, 10) +#define LS1X_DMA0_IRQ LS1X_IRQ(0, 13) +#define LS1X_DMA1_IRQ LS1X_IRQ(0, 14) +#define LS1X_DMA2_IRQ LS1X_IRQ(0, 15) +#define LS1X_PWM0_IRQ LS1X_IRQ(0, 17) +#define LS1X_PWM1_IRQ LS1X_IRQ(0, 18) +#define LS1X_PWM2_IRQ LS1X_IRQ(0, 19) +#define LS1X_PWM3_IRQ LS1X_IRQ(0, 20) +#define LS1X_RTC_INT0_IRQ LS1X_IRQ(0, 21) +#define LS1X_RTC_INT1_IRQ LS1X_IRQ(0, 22) +#define LS1X_RTC_INT2_IRQ LS1X_IRQ(0, 23) +#define LS1X_TOY_INT0_IRQ LS1X_IRQ(0, 24) +#define LS1X_TOY_INT1_IRQ LS1X_IRQ(0, 25) +#define LS1X_TOY_INT2_IRQ LS1X_IRQ(0, 26) +#define LS1X_RTC_TICK_IRQ LS1X_IRQ(0, 27) +#define LS1X_TOY_TICK_IRQ LS1X_IRQ(0, 28) + +#define LS1X_EHCI_IRQ LS1X_IRQ(1, 0) +#define LS1X_OHCI_IRQ LS1X_IRQ(1, 1) +#define LS1X_GMAC0_IRQ LS1X_IRQ(1, 2) +#define LS1X_GMAC1_IRQ LS1X_IRQ(1, 3) + +#define LS1X_IRQS (LS1X_IRQ(4, 31) + 1 - LS1X_IRQ_BASE) + +#define NR_IRQS (MIPS_CPU_IRQS + LS1X_IRQS) + +#endif /* __ASM_MACH_LOONGSON1_IRQ_H */ diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson1/loongson1.h new file mode 100644 index 00000000000..4e18e88cebb --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/loongson1.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> + * + * Register mappings for Loongson 1 + * + * 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 __ASM_MACH_LOONGSON1_LOONGSON1_H +#define __ASM_MACH_LOONGSON1_LOONGSON1_H + +#define DEFAULT_MEMSIZE 256 /* If no memsize provided */ + +/* Loongson 1 Register Bases */ +#define LS1X_INTC_BASE 0x1fd01040 +#define LS1X_EHCI_BASE 0x1fe00000 +#define LS1X_OHCI_BASE 0x1fe08000 +#define LS1X_GMAC0_BASE 0x1fe10000 +#define LS1X_GMAC1_BASE 0x1fe20000 + +#define LS1X_UART0_BASE 0x1fe40000 +#define LS1X_UART1_BASE 0x1fe44000 +#define LS1X_UART2_BASE 0x1fe48000 +#define LS1X_UART3_BASE 0x1fe4c000 +#define LS1X_CAN0_BASE 0x1fe50000 +#define LS1X_CAN1_BASE 0x1fe54000 +#define LS1X_I2C0_BASE 0x1fe58000 +#define LS1X_I2C1_BASE 0x1fe68000 +#define LS1X_I2C2_BASE 0x1fe70000 +#define LS1X_PWM_BASE 0x1fe5c000 +#define LS1X_WDT_BASE 0x1fe5c060 +#define LS1X_RTC_BASE 0x1fe64000 +#define LS1X_AC97_BASE 0x1fe74000 +#define LS1X_NAND_BASE 0x1fe78000 +#define LS1X_CLK_BASE 0x1fe78030 + +#include <regs-clk.h> +#include <regs-wdt.h> + +#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */ diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h new file mode 100644 index 00000000000..2f171617bad --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/platform.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 __ASM_MACH_LOONGSON1_PLATFORM_H +#define __ASM_MACH_LOONGSON1_PLATFORM_H + +#include <linux/platform_device.h> + +extern struct platform_device ls1x_uart_device; +extern struct platform_device ls1x_eth0_device; +extern struct platform_device ls1x_ehci_device; +extern struct platform_device ls1x_rtc_device; + +void ls1x_serial_setup(void); + +#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */ diff --git a/arch/mips/include/asm/mach-loongson1/prom.h b/arch/mips/include/asm/mach-loongson1/prom.h new file mode 100644 index 00000000000..b871dc41b8d --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/prom.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 __ASM_MACH_LOONGSON1_PROM_H +#define __ASM_MACH_LOONGSON1_PROM_H + +#include <linux/io.h> +#include <linux/init.h> +#include <linux/irq.h> + +/* environment arguments from bootloader */ +extern unsigned long memsize, highmemsize; + +/* loongson-specific command line, env and memory initialization */ +extern char *prom_getenv(char *name); +extern void __init prom_init_cmdline(void); + +#endif /* __ASM_MACH_LOONGSON1_PROM_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h new file mode 100644 index 00000000000..8efa7fb9f73 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> + * + * Loongson 1 Clock Register Definitions. + * + * 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 __ASM_MACH_LOONGSON1_REGS_CLK_H +#define __ASM_MACH_LOONGSON1_REGS_CLK_H + +#define LS1X_CLK_REG(x) \ + ((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x))) + +#define LS1X_CLK_PLL_FREQ LS1X_CLK_REG(0x0) +#define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4) + +/* Clock PLL Divisor Register Bits */ +#define DIV_DC_EN (0x1 << 31) +#define DIV_DC (0x1f << 26) +#define DIV_CPU_EN (0x1 << 25) +#define DIV_CPU (0x1f << 20) +#define DIV_DDR_EN (0x1 << 19) +#define DIV_DDR (0x1f << 14) + +#define DIV_DC_SHIFT 26 +#define DIV_CPU_SHIFT 20 +#define DIV_DDR_SHIFT 14 + +#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */ diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson1/regs-wdt.h new file mode 100644 index 00000000000..f897de68c52 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> + * + * Loongson 1 watchdog register definitions. + * + * 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 __ASM_MACH_LOONGSON1_REGS_WDT_H +#define __ASM_MACH_LOONGSON1_REGS_WDT_H + +#define LS1X_WDT_REG(x) \ + ((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x))) + +#define LS1X_WDT_EN LS1X_WDT_REG(0x0) +#define LS1X_WDT_SET LS1X_WDT_REG(0x4) +#define LS1X_WDT_TIMER LS1X_WDT_REG(0x8) + +#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */ diff --git a/arch/mips/include/asm/mach-loongson1/war.h b/arch/mips/include/asm/mach-loongson1/war.h new file mode 100644 index 00000000000..e3680a8fb34 --- /dev/null +++ b/arch/mips/include/asm/mach-loongson1/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> + */ +#ifndef __ASM_MACH_LOONGSON1_WAR_H +#define __ASM_MACH_LOONGSON1_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MACH_LOONGSON1_WAR_H */ diff --git a/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h b/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h index d193fb68cf2..966db4be377 100644 --- a/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-netlogic/cpu-feature-overrides.h @@ -48,7 +48,6 @@ #define cpu_has_userlocal 1 #define cpu_has_mips32r2 1 #define cpu_has_mips64r2 1 -#define cpu_has_dc_aliases 1 #else #error "Unknown Netlogic CPU" #endif diff --git a/arch/mips/include/asm/mach-tx49xx/mangle-port.h b/arch/mips/include/asm/mach-tx49xx/mangle-port.h index 5e6912fdd0e..490867b03c8 100644 --- a/arch/mips/include/asm/mach-tx49xx/mangle-port.h +++ b/arch/mips/include/asm/mach-tx49xx/mangle-port.h @@ -9,7 +9,7 @@ #define ioswabb(a, x) (x) #define __mem_ioswabb(a, x) (x) #if defined(CONFIG_TOSHIBA_RBTX4939) && \ - (defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)) && \ + IS_ENABLED(CONFIG_SMC91X) && \ defined(__BIG_ENDIAN) #define NEEDS_TXX9_IOSWABW extern u16 (*ioswabw)(volatile u16 *a, u16 x); diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h index e71ff4c317f..5b3cb8553e9 100644 --- a/arch/mips/include/asm/mipsmtregs.h +++ b/arch/mips/include/asm/mipsmtregs.h @@ -28,6 +28,9 @@ #define read_c0_vpeconf0() __read_32bit_c0_register($1, 2) #define write_c0_vpeconf0(val) __write_32bit_c0_register($1, 2, val) +#define read_c0_vpeconf1() __read_32bit_c0_register($1, 3) +#define write_c0_vpeconf1(val) __write_32bit_c0_register($1, 3, val) + #define read_c0_tcstatus() __read_32bit_c0_register($2, 1) #define write_c0_tcstatus(val) __write_32bit_c0_register($2, 1, val) @@ -124,6 +127,14 @@ #define VPECONF0_XTC_SHIFT 21 #define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT) +/* VPEConf1 fields (per VPE) */ +#define VPECONF1_NCP1_SHIFT 0 +#define VPECONF1_NCP1 (_ULCAST_(0xff) << VPECONF1_NCP1_SHIFT) +#define VPECONF1_NCP2_SHIFT 10 +#define VPECONF1_NCP2 (_ULCAST_(0xff) << VPECONF1_NCP2_SHIFT) +#define VPECONF1_NCX_SHIFT 20 +#define VPECONF1_NCX (_ULCAST_(0xff) << VPECONF1_NCX_SHIFT) + /* TCStatus fields (per TC) */ #define TCSTATUS_TASID (_ULCAST_(0xff)) #define TCSTATUS_IXMT_SHIFT 10 @@ -350,6 +361,8 @@ do { \ #define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val) #define read_vpe_c0_vpeconf0() mftc0(1, 2) #define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val) +#define read_vpe_c0_vpeconf1() mftc0(1, 3) +#define write_vpe_c0_vpeconf1(val) mttc0(1, 3, val) #define read_vpe_c0_count() mftc0(9, 0) #define write_vpe_c0_count(val) mttc0(9, 0, val) #define read_vpe_c0_status() mftc0(12, 0) diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index 530008048c6..7531ecd654d 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -117,6 +117,8 @@ search_module_dbetables(unsigned long addr) #define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 #define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON1 +#define MODULE_PROC_FAMILY "LOONGSON1 " #elif defined CONFIG_CPU_LOONGSON2 #define MODULE_PROC_FAMILY "LOONGSON2 " #elif defined CONFIG_CPU_CAVIUM_OCTEON diff --git a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h index bf7d41deb9b..7b63a6b722a 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/cpucontrol.h @@ -47,7 +47,9 @@ #define CPU_BLOCKID_MAP 10 #define LSU_DEFEATURE 0x304 -#define LSU_CERRLOG_REGID 0x09 +#define LSU_DEBUG_ADDR 0x305 +#define LSU_DEBUG_DATA0 0x306 +#define LSU_CERRLOG_REGID 0x309 #define SCHED_DEFEATURE 0x700 /* Offsets of interest from the 'MAP' Block */ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h index 86cc3391e50..2c63f975464 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h @@ -36,6 +36,9 @@ #define __NLM_HAL_IOMAP_H__ #define XLP_DEFAULT_IO_BASE 0x18000000 +#define XLP_DEFAULT_PCI_ECFG_BASE XLP_DEFAULT_IO_BASE +#define XLP_DEFAULT_PCI_CFG_BASE 0x1c000000 + #define NMI_BASE 0xbfc00000 #define XLP_IO_CLK 133333333 @@ -129,7 +132,7 @@ #define PCI_DEVICE_ID_NLM_PIC 0x1003 #define PCI_DEVICE_ID_NLM_PCIE 0x1004 #define PCI_DEVICE_ID_NLM_EHCI 0x1007 -#define PCI_DEVICE_ID_NLM_ILK 0x1008 +#define PCI_DEVICE_ID_NLM_OHCI 0x1008 #define PCI_DEVICE_ID_NLM_NAE 0x1009 #define PCI_DEVICE_ID_NLM_POE 0x100A #define PCI_DEVICE_ID_NLM_FMN 0x100B diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h new file mode 100644 index 00000000000..66c323d1bd7 --- /dev/null +++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NLM_HAL_PCIBUS_H__ +#define __NLM_HAL_PCIBUS_H__ + +/* PCIE Memory and IO regions */ +#define PCIE_MEM_BASE 0xd0000000ULL +#define PCIE_MEM_LIMIT 0xdfffffffULL +#define PCIE_IO_BASE 0x14000000ULL +#define PCIE_IO_LIMIT 0x15ffffffULL + +#define PCIE_BRIDGE_CMD 0x1 +#define PCIE_BRIDGE_MSI_CAP 0x14 +#define PCIE_BRIDGE_MSI_ADDRL 0x15 +#define PCIE_BRIDGE_MSI_ADDRH 0x16 +#define PCIE_BRIDGE_MSI_DATA 0x17 + +/* XLP Global PCIE configuration space registers */ +#define PCIE_BYTE_SWAP_MEM_BASE 0x247 +#define PCIE_BYTE_SWAP_MEM_LIM 0x248 +#define PCIE_BYTE_SWAP_IO_BASE 0x249 +#define PCIE_BYTE_SWAP_IO_LIM 0x24A +#define PCIE_MSI_STATUS 0x25A +#define PCIE_MSI_EN 0x25B +#define PCIE_INT_EN0 0x261 + +/* PCIE_MSI_EN */ +#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF + +/* PCIE_INT_EN0 */ +#define PCIE_MSI_INT_EN (1 << 9) + +#ifndef __ASSEMBLY__ + +#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_get_pcie_base(node, inst) \ + nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst)) +#define nlm_get_pcie_regbase(node, inst) \ + (nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ) + +int xlp_pcie_link_irt(int link); +#endif +#endif /* __NLM_HAL_PCIBUS_H__ */ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index b6628f7ccf7..ad8b80233a6 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -201,7 +201,11 @@ #define PIC_NUM_USB_IRTS 6 #define PIC_IRT_USB_0_INDEX 115 #define PIC_IRT_EHCI_0_INDEX 115 +#define PIC_IRT_OHCI_0_INDEX 116 +#define PIC_IRT_OHCI_1_INDEX 117 #define PIC_IRT_EHCI_1_INDEX 118 +#define PIC_IRT_OHCI_2_INDEX 119 +#define PIC_IRT_OHCI_3_INDEX 120 #define PIC_IRT_USB_INDEX(num) ((num) + PIC_IRT_USB_0_INDEX) /* 115 to 120 */ #define PIC_IRT_GDX_INDEX 121 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/usb.h b/arch/mips/include/asm/netlogic/xlp-hal/usb.h new file mode 100644 index 00000000000..a9cd350dfb6 --- /dev/null +++ b/arch/mips/include/asm/netlogic/xlp-hal/usb.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NLM_HAL_USB_H__ +#define __NLM_HAL_USB_H__ + +#define USB_CTL_0 0x01 +#define USB_PHY_0 0x0A +#define USB_PHY_RESET 0x01 +#define USB_PHY_PORT_RESET_0 0x10 +#define USB_PHY_PORT_RESET_1 0x20 +#define USB_CONTROLLER_RESET 0x01 +#define USB_INT_STATUS 0x0E +#define USB_INT_EN 0x0F +#define USB_PHY_INTERRUPT_EN 0x01 +#define USB_OHCI_INTERRUPT_EN 0x02 +#define USB_OHCI_INTERRUPT1_EN 0x04 +#define USB_OHCI_INTERRUPT2_EN 0x08 +#define USB_CTRL_INTERRUPT_EN 0x10 + +#ifndef __ASSEMBLY__ + +#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_get_usb_pcibase(node, inst) \ + nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst)) +#define nlm_get_usb_hcd_base(node, inst) \ + nlm_xkphys_map_pcibar0(nlm_get_usb_pcibase(node, inst)) +#define nlm_get_usb_regbase(node, inst) \ + (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ) + +#endif +#endif /* __NLM_HAL_USB_H__ */ diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 1540588e396..7e47209327a 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -35,8 +35,21 @@ #ifndef _NLM_HAL_XLP_H #define _NLM_HAL_XLP_H -#define PIC_UART_0_IRQ 17 -#define PIC_UART_1_IRQ 18 +#define PIC_UART_0_IRQ 17 +#define PIC_UART_1_IRQ 18 +#define PIC_PCIE_LINK_0_IRQ 19 +#define PIC_PCIE_LINK_1_IRQ 20 +#define PIC_PCIE_LINK_2_IRQ 21 +#define PIC_PCIE_LINK_3_IRQ 22 +#define PIC_EHCI_0_IRQ 23 +#define PIC_EHCI_1_IRQ 24 +#define PIC_OHCI_0_IRQ 25 +#define PIC_OHCI_1_IRQ 26 +#define PIC_OHCI_2_IRQ 27 +#define PIC_OHCI_3_IRQ 28 +#define PIC_MMC_IRQ 29 +#define PIC_I2C_0_IRQ 30 +#define PIC_I2C_1_IRQ 31 #ifndef __ASSEMBLY__ diff --git a/arch/mips/include/asm/netlogic/xlr/bridge.h b/arch/mips/include/asm/netlogic/xlr/bridge.h new file mode 100644 index 00000000000..2d02428c4f1 --- /dev/null +++ b/arch/mips/include/asm/netlogic/xlr/bridge.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _ASM_NLM_BRIDGE_H_ +#define _ASM_NLM_BRIDGE_H_ + +#define BRIDGE_DRAM_0_BAR 0 +#define BRIDGE_DRAM_1_BAR 1 +#define BRIDGE_DRAM_2_BAR 2 +#define BRIDGE_DRAM_3_BAR 3 +#define BRIDGE_DRAM_4_BAR 4 +#define BRIDGE_DRAM_5_BAR 5 +#define BRIDGE_DRAM_6_BAR 6 +#define BRIDGE_DRAM_7_BAR 7 +#define BRIDGE_DRAM_CHN_0_MTR_0_BAR 8 +#define BRIDGE_DRAM_CHN_0_MTR_1_BAR 9 +#define BRIDGE_DRAM_CHN_0_MTR_2_BAR 10 +#define BRIDGE_DRAM_CHN_0_MTR_3_BAR 11 +#define BRIDGE_DRAM_CHN_0_MTR_4_BAR 12 +#define BRIDGE_DRAM_CHN_0_MTR_5_BAR 13 +#define BRIDGE_DRAM_CHN_0_MTR_6_BAR 14 +#define BRIDGE_DRAM_CHN_0_MTR_7_BAR 15 +#define BRIDGE_DRAM_CHN_1_MTR_0_BAR 16 +#define BRIDGE_DRAM_CHN_1_MTR_1_BAR 17 +#define BRIDGE_DRAM_CHN_1_MTR_2_BAR 18 +#define BRIDGE_DRAM_CHN_1_MTR_3_BAR 19 +#define BRIDGE_DRAM_CHN_1_MTR_4_BAR 20 +#define BRIDGE_DRAM_CHN_1_MTR_5_BAR 21 +#define BRIDGE_DRAM_CHN_1_MTR_6_BAR 22 +#define BRIDGE_DRAM_CHN_1_MTR_7_BAR 23 +#define BRIDGE_CFG_BAR 24 +#define BRIDGE_PHNX_IO_BAR 25 +#define BRIDGE_FLASH_BAR 26 +#define BRIDGE_SRAM_BAR 27 +#define BRIDGE_HTMEM_BAR 28 +#define BRIDGE_HTINT_BAR 29 +#define BRIDGE_HTPIC_BAR 30 +#define BRIDGE_HTSM_BAR 31 +#define BRIDGE_HTIO_BAR 32 +#define BRIDGE_HTCFG_BAR 33 +#define BRIDGE_PCIXCFG_BAR 34 +#define BRIDGE_PCIXMEM_BAR 35 +#define BRIDGE_PCIXIO_BAR 36 +#define BRIDGE_DEVICE_MASK 37 +#define BRIDGE_AERR_INTR_LOG1 38 +#define BRIDGE_AERR_INTR_LOG2 39 +#define BRIDGE_AERR_INTR_LOG3 40 +#define BRIDGE_AERR_DEV_STAT 41 +#define BRIDGE_AERR1_LOG1 42 +#define BRIDGE_AERR1_LOG2 43 +#define BRIDGE_AERR1_LOG3 44 +#define BRIDGE_AERR1_DEV_STAT 45 +#define BRIDGE_AERR_INTR_EN 46 +#define BRIDGE_AERR_UPG 47 +#define BRIDGE_AERR_CLEAR 48 +#define BRIDGE_AERR1_CLEAR 49 +#define BRIDGE_SBE_COUNTS 50 +#define BRIDGE_DBE_COUNTS 51 +#define BRIDGE_BITERR_INT_EN 52 + +#define BRIDGE_SYS2IO_CREDITS 53 +#define BRIDGE_EVNT_CNT_CTRL1 54 +#define BRIDGE_EVNT_COUNTER1 55 +#define BRIDGE_EVNT_CNT_CTRL2 56 +#define BRIDGE_EVNT_COUNTER2 57 +#define BRIDGE_RESERVED1 58 + +#define BRIDGE_DEFEATURE 59 +#define BRIDGE_SCRATCH0 60 +#define BRIDGE_SCRATCH1 61 +#define BRIDGE_SCRATCH2 62 +#define BRIDGE_SCRATCH3 63 + +#endif diff --git a/arch/mips/include/asm/netlogic/xlr/flash.h b/arch/mips/include/asm/netlogic/xlr/flash.h new file mode 100644 index 00000000000..f8aca5472b6 --- /dev/null +++ b/arch/mips/include/asm/netlogic/xlr/flash.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _ASM_NLM_FLASH_H_ +#define _ASM_NLM_FLASH_H_ + +#define FLASH_CSBASE_ADDR(cs) (cs) +#define FLASH_CSADDR_MASK(cs) (0x10 + (cs)) +#define FLASH_CSDEV_PARM(cs) (0x20 + (cs)) +#define FLASH_CSTIME_PARMA(cs) (0x30 + (cs)) +#define FLASH_CSTIME_PARMB(cs) (0x40 + (cs)) + +#define FLASH_INT_MASK 0x50 +#define FLASH_INT_STATUS 0x60 +#define FLASH_ERROR_STATUS 0x70 +#define FLASH_ERROR_ADDR 0x80 + +#define FLASH_NAND_CLE(cs) (0x90 + (cs)) +#define FLASH_NAND_ALE(cs) (0xa0 + (cs)) + +#define FLASH_NAND_CSDEV_PARAM 0x000041e6 +#define FLASH_NAND_CSTIME_PARAMA 0x4f400e22 +#define FLASH_NAND_CSTIME_PARAMB 0x000083cf + +#endif diff --git a/arch/mips/include/asm/netlogic/xlr/gpio.h b/arch/mips/include/asm/netlogic/xlr/gpio.h index 51f6ad4aeb1..8492e835b11 100644 --- a/arch/mips/include/asm/netlogic/xlr/gpio.h +++ b/arch/mips/include/asm/netlogic/xlr/gpio.h @@ -35,39 +35,40 @@ #ifndef _ASM_NLM_GPIO_H #define _ASM_NLM_GPIO_H -#define NETLOGIC_GPIO_INT_EN_REG 0 -#define NETLOGIC_GPIO_INPUT_INVERSION_REG 1 -#define NETLOGIC_GPIO_IO_DIR_REG 2 -#define NETLOGIC_GPIO_IO_DATA_WR_REG 3 -#define NETLOGIC_GPIO_IO_DATA_RD_REG 4 +#define GPIO_INT_EN_REG 0 +#define GPIO_INPUT_INVERSION_REG 1 +#define GPIO_IO_DIR_REG 2 +#define GPIO_IO_DATA_WR_REG 3 +#define GPIO_IO_DATA_RD_REG 4 -#define NETLOGIC_GPIO_SWRESET_REG 8 -#define NETLOGIC_GPIO_DRAM1_CNTRL_REG 9 -#define NETLOGIC_GPIO_DRAM1_RATIO_REG 10 -#define NETLOGIC_GPIO_DRAM1_RESET_REG 11 -#define NETLOGIC_GPIO_DRAM1_STATUS_REG 12 -#define NETLOGIC_GPIO_DRAM2_CNTRL_REG 13 -#define NETLOGIC_GPIO_DRAM2_RATIO_REG 14 -#define NETLOGIC_GPIO_DRAM2_RESET_REG 15 -#define NETLOGIC_GPIO_DRAM2_STATUS_REG 16 +#define GPIO_SWRESET_REG 8 +#define GPIO_DRAM1_CNTRL_REG 9 +#define GPIO_DRAM1_RATIO_REG 10 +#define GPIO_DRAM1_RESET_REG 11 +#define GPIO_DRAM1_STATUS_REG 12 +#define GPIO_DRAM2_CNTRL_REG 13 +#define GPIO_DRAM2_RATIO_REG 14 +#define GPIO_DRAM2_RESET_REG 15 +#define GPIO_DRAM2_STATUS_REG 16 -#define NETLOGIC_GPIO_PWRON_RESET_CFG_REG 21 -#define NETLOGIC_GPIO_BIST_ALL_GO_STATUS_REG 24 -#define NETLOGIC_GPIO_BIST_CPU_GO_STATUS_REG 25 -#define NETLOGIC_GPIO_BIST_DEV_GO_STATUS_REG 26 +#define GPIO_PWRON_RESET_CFG_REG 21 +#define GPIO_BIST_ALL_GO_STATUS_REG 24 +#define GPIO_BIST_CPU_GO_STATUS_REG 25 +#define GPIO_BIST_DEV_GO_STATUS_REG 26 -#define NETLOGIC_GPIO_FUSE_BANK_REG 35 -#define NETLOGIC_GPIO_CPU_RESET_REG 40 -#define NETLOGIC_GPIO_RNG_REG 43 +#define GPIO_FUSE_BANK_REG 35 +#define GPIO_CPU_RESET_REG 40 +#define GPIO_RNG_REG 43 -#define NETLOGIC_PWRON_RESET_PCMCIA_BOOT 17 -#define NETLOGIC_GPIO_LED_BITMAP 0x1700000 -#define NETLOGIC_GPIO_LED_0_SHIFT 20 -#define NETLOGIC_GPIO_LED_1_SHIFT 24 +#define PWRON_RESET_PCMCIA_BOOT 17 -#define NETLOGIC_GPIO_LED_OUTPUT_CODE_RESET 0x01 -#define NETLOGIC_GPIO_LED_OUTPUT_CODE_HARD_RESET 0x02 -#define NETLOGIC_GPIO_LED_OUTPUT_CODE_SOFT_RESET 0x03 -#define NETLOGIC_GPIO_LED_OUTPUT_CODE_MAIN 0x04 +#define GPIO_LED_BITMAP 0x1700000 +#define GPIO_LED_0_SHIFT 20 +#define GPIO_LED_1_SHIFT 24 + +#define GPIO_LED_OUTPUT_CODE_RESET 0x01 +#define GPIO_LED_OUTPUT_CODE_HARD_RESET 0x02 +#define GPIO_LED_OUTPUT_CODE_SOFT_RESET 0x03 +#define GPIO_LED_OUTPUT_CODE_MAIN 0x04 #endif diff --git a/arch/mips/include/asm/octeon/cvmx-helper-fpa.h b/arch/mips/include/asm/octeon/cvmx-helper-fpa.h deleted file mode 100644 index 5ff8c93198d..00000000000 --- a/arch/mips/include/asm/octeon/cvmx-helper-fpa.h +++ /dev/null @@ -1,64 +0,0 @@ -/***********************license start*************** - * Author: Cavium Networks - * - * Contact: support@caviumnetworks.com - * This file is part of the OCTEON SDK - * - * Copyright (c) 2003-2008 Cavium Networks - * - * This file 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 file is distributed in the hope that it will be useful, but - * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or - * NONINFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * or visit http://www.gnu.org/licenses/. - * - * This file may also be available under a different license from Cavium. - * Contact Cavium Networks for more information - ***********************license end**************************************/ - -/** - * @file - * - * Helper functions for FPA setup. - * - */ -#ifndef __CVMX_HELPER_H_FPA__ -#define __CVMX_HELPER_H_FPA__ - -/** - * Allocate memory and initialize the FPA pools using memory - * from cvmx-bootmem. Sizes of each element in the pools is - * controlled by the cvmx-config.h header file. Specifying - * zero for any parameter will cause that FPA pool to not be - * setup. This is useful if you aren't using some of the - * hardware and want to save memory. - * - * @packet_buffers: - * Number of packet buffers to allocate - * @work_queue_entries: - * Number of work queue entries - * @pko_buffers: - * PKO Command buffers. You should at minimum have two per - * each PKO queue. - * @tim_buffers: - * TIM ring buffer command queues. At least two per timer bucket - * is recommened. - * @dfa_buffers: - * DFA command buffer. A relatively small (32 for example) - * number should work. - * Returns Zero on success, non-zero if out of memory - */ -extern int cvmx_helper_initialize_fpa(int packet_buffers, - int work_queue_entries, int pko_buffers, - int tim_buffers, int dfa_buffers); - -#endif /* __CVMX_HELPER_H__ */ diff --git a/arch/mips/include/asm/octeon/cvmx-helper.h b/arch/mips/include/asm/octeon/cvmx-helper.h index 3169cd79f2a..0ac6b9f412b 100644 --- a/arch/mips/include/asm/octeon/cvmx-helper.h +++ b/arch/mips/include/asm/octeon/cvmx-helper.h @@ -61,8 +61,6 @@ typedef union { } s; } cvmx_helper_link_info_t; -#include "cvmx-helper-fpa.h" - #include <asm/octeon/cvmx-helper-errata.h> #include "cvmx-helper-loop.h" #include "cvmx-helper-npi.h" diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index f72f768cd3a..1e2486e2357 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -215,11 +215,6 @@ struct octeon_cf_data { int dma_engine; /* -1 for no DMA */ }; -struct octeon_i2c_data { - unsigned int sys_freq; - unsigned int i2c_freq; -}; - extern void octeon_write_lcd(const char *s); extern void octeon_check_cpu_bist(void); extern int octeon_get_boot_debug_flag(void); diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h index 7206d445bab..8808bf548b9 100644 --- a/arch/mips/include/asm/prom.h +++ b/arch/mips/include/asm/prom.h @@ -20,9 +20,6 @@ extern int early_init_dt_scan_memory_arch(unsigned long node, const char *uname, int depth, void *data); -extern int reserve_mem_mach(unsigned long addr, unsigned long size); -extern void free_mem_mach(unsigned long addr, unsigned long size); - extern void device_tree_init(void); static inline unsigned long pci_address_to_pio(phys_addr_t address) diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h index c9736fc0632..8935426a56a 100644 --- a/arch/mips/include/asm/smtc.h +++ b/arch/mips/include/asm/smtc.h @@ -33,6 +33,12 @@ typedef long asiduse; #endif #endif +/* + * VPE Management information + */ + +#define MAX_SMTC_VPES MAX_SMTC_TLBS /* FIXME: May not always be true. */ + extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; struct mm_struct; diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index 653a412c036..3b92efef56d 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -687,7 +687,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n); __MODULE_JAL(__copy_user) \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : \ - : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ DADDI_SCRATCH, "memory"); \ __cu_len_r; \ }) @@ -797,7 +797,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); ".set\treorder" \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : \ - : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ DADDI_SCRATCH, "memory"); \ __cu_len_r; \ }) @@ -820,7 +820,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); ".set\treorder" \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : \ - : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ + : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \ DADDI_SCRATCH, "memory"); \ __cu_len_r; \ }) diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 440a21dab57..3d9f75f7ffc 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -6,6 +6,7 @@ * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer * Copyright (C) 2005 Maciej W. Rozycki * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2012 MIPS Technologies, Inc. */ #include <linux/types.h> @@ -62,8 +63,10 @@ void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b) Ip_u2u1s3(_addiu); Ip_u3u1u2(_addu); -Ip_u2u1u3(_andi); Ip_u3u1u2(_and); +Ip_u2u1u3(_andi); +Ip_u1u2s3(_bbit0); +Ip_u1u2s3(_bbit1); Ip_u1u2s3(_beq); Ip_u1u2s3(_beql); Ip_u1s2(_bgez); @@ -72,55 +75,54 @@ Ip_u1s2(_bltz); Ip_u1s2(_bltzl); Ip_u1u2s3(_bne); Ip_u2s3u1(_cache); -Ip_u1u2u3(_dmfc0); -Ip_u1u2u3(_dmtc0); Ip_u2u1s3(_daddiu); Ip_u3u1u2(_daddu); +Ip_u2u1msbu3(_dins); +Ip_u2u1msbu3(_dinsm); +Ip_u1u2u3(_dmfc0); +Ip_u1u2u3(_dmtc0); +Ip_u2u1u3(_drotr); +Ip_u2u1u3(_drotr32); Ip_u2u1u3(_dsll); Ip_u2u1u3(_dsll32); Ip_u2u1u3(_dsra); Ip_u2u1u3(_dsrl); Ip_u2u1u3(_dsrl32); -Ip_u2u1u3(_drotr); -Ip_u2u1u3(_drotr32); Ip_u3u1u2(_dsubu); Ip_0(_eret); Ip_u1(_j); Ip_u1(_jal); Ip_u1(_jr); Ip_u2s3u1(_ld); +Ip_u3u1u2(_ldx); Ip_u2s3u1(_ll); Ip_u2s3u1(_lld); Ip_u1s2(_lui); Ip_u2s3u1(_lw); +Ip_u3u1u2(_lwx); Ip_u1u2u3(_mfc0); Ip_u1u2u3(_mtc0); -Ip_u2u1u3(_ori); Ip_u3u1u2(_or); +Ip_u2u1u3(_ori); Ip_u2s3u1(_pref); Ip_0(_rfe); +Ip_u2u1u3(_rotr); Ip_u2s3u1(_sc); Ip_u2s3u1(_scd); Ip_u2s3u1(_sd); Ip_u2u1u3(_sll); Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); -Ip_u2u1u3(_rotr); Ip_u3u1u2(_subu); Ip_u2s3u1(_sw); +Ip_u1(_syscall); Ip_0(_tlbp); Ip_0(_tlbr); Ip_0(_tlbwi); Ip_0(_tlbwr); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); -Ip_u2u1msbu3(_dins); -Ip_u2u1msbu3(_dinsm); -Ip_u1(_syscall); -Ip_u1u2s3(_bbit0); -Ip_u1u2s3(_bbit1); -Ip_u3u1u2(_lwx); -Ip_u3u1u2(_ldx); + /* Handle labels. */ struct uasm_label { @@ -145,37 +147,37 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ /* convenience macros for instructions */ #ifdef CONFIG_64BIT +# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val) +# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd) +# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) # define UASM_i_LW(buf, rs, rt, off) uasm_i_ld(buf, rs, rt, off) -# define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off) +# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd) +# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd) +# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd) +# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh) +# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off) # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh) # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh) # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh) # define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh) -# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh) -# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd) -# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd) -# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val) -# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd) # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd) -# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) -# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off) -# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd) +# define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off) #else +# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val) +# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd) +# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) # define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off) -# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) +# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd) +# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd) +# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd) +# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh) +# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off) # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh) # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh) # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh) # define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh) -# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh) -# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd) -# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd) -# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val) -# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd) # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd) -# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) -# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off) -# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd) +# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) #endif #define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off) @@ -183,19 +185,10 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ #define uasm_i_beqzl(buf, rs, off) uasm_i_beql(buf, rs, 0, off) #define uasm_i_bnez(buf, rs, off) uasm_i_bne(buf, rs, 0, off) #define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off) +#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3) #define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b) #define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0) #define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1) -#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3) - -static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, - unsigned int a2, unsigned int a3) -{ - if (a3 < 32) - uasm_i_dsrl(p, a1, a2, a3); - else - uasm_i_dsrl32(p, a1, a2, a3 - 32); -} static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, unsigned int a2, unsigned int a3) @@ -215,6 +208,15 @@ static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, uasm_i_dsll32(p, a1, a2, a3 - 32); } +static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1, + unsigned int a2, unsigned int a3) +{ + if (a3 < 32) + uasm_i_dsrl(p, a1, a2, a3); + else + uasm_i_dsrl32(p, a1, a2, a3 - 32); +} + /* Handle relocations. */ struct uasm_reloc { u32 *addr; @@ -234,16 +236,16 @@ void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr); /* Convenience functions for labeled branches. */ -void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid); +void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); +void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, + unsigned int bit, int lid); void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); +void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, unsigned int reg2, int lid); void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); -void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, - unsigned int bit, int lid); -void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, - unsigned int bit, int lid); diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c index 9a91fe9de69..9a3d9de4d04 100644 --- a/arch/mips/jz4740/board-qi_lb60.c +++ b/arch/mips/jz4740/board-qi_lb60.c @@ -140,6 +140,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev, static struct jz_nand_platform_data qi_lb60_nand_pdata = { .ident_callback = qi_lb60_nand_ident, .busy_gpio = 94, + .banks = { 1 }, }; /* Keyboard*/ diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c index 10929e2bc6d..e342ed4cbd4 100644 --- a/arch/mips/jz4740/platform.c +++ b/arch/mips/jz4740/platform.c @@ -157,11 +157,29 @@ static struct resource jz4740_nand_resources[] = { .flags = IORESOURCE_MEM, }, { - .name = "bank", + .name = "bank1", .start = 0x18000000, .end = 0x180C0000 - 1, .flags = IORESOURCE_MEM, }, + { + .name = "bank2", + .start = 0x14000000, + .end = 0x140C0000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "bank3", + .start = 0x0C000000, + .end = 0x0C0C0000 - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "bank4", + .start = 0x08000000, + .end = 0x080C0000 - 1, + .flags = IORESOURCE_MEM, + }, }; struct platform_device jz4740_nand_device = { diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c index 5f1fb95c0d0..6c0da5afcf1 100644 --- a/arch/mips/jz4740/reset.c +++ b/arch/mips/jz4740/reset.c @@ -21,6 +21,9 @@ #include <asm/mach-jz4740/base.h> #include <asm/mach-jz4740/timer.h> +#include "reset.h" +#include "clock.h" + static void jz4740_halt(void) { while (1) { @@ -53,21 +56,57 @@ static void jz4740_restart(char *command) jz4740_halt(); } -#define JZ_REG_RTC_CTRL 0x00 -#define JZ_REG_RTC_HIBERNATE 0x20 +#define JZ_REG_RTC_CTRL 0x00 +#define JZ_REG_RTC_HIBERNATE 0x20 +#define JZ_REG_RTC_WAKEUP_FILTER 0x24 +#define JZ_REG_RTC_RESET_COUNTER 0x28 -#define JZ_RTC_CTRL_WRDY BIT(7) +#define JZ_RTC_CTRL_WRDY BIT(7) +#define JZ_RTC_WAKEUP_FILTER_MASK 0x0000FFE0 +#define JZ_RTC_RESET_COUNTER_MASK 0x00000FE0 -static void jz4740_power_off(void) +static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base) { - void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x24); uint32_t ctrl; do { ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); } while (!(ctrl & JZ_RTC_CTRL_WRDY)); +} +static void jz4740_power_off(void) +{ + void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38); + unsigned long wakeup_filter_ticks; + unsigned long reset_counter_ticks; + + /* + * Set minimum wakeup pin assertion time: 100 ms. + * Range is 0 to 2 sec if RTC is clocked at 32 kHz. + */ + wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000; + if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) + wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; + else + wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK; + jz4740_rtc_wait_ready(rtc_base); + writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER); + + /* + * Set reset pin low-level assertion time after wakeup: 60 ms. + * Range is 0 to 125 ms if RTC is clocked at 32 kHz. + */ + reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000; + if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) + reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; + else + reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK; + jz4740_rtc_wait_ready(rtc_base); + writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER); + + jz4740_rtc_wait_ready(rtc_base); writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); + jz4740_halt(); } diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f4630e1082a..1b51046191e 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -190,6 +190,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: case CPU_JZRISC: + case CPU_LOONGSON1: case CPU_XLR: case CPU_XLP: cpu_wait = r4k_wait; @@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) #endif } +static char unknown_isa[] __cpuinitdata = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + +static inline unsigned int decode_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + int isa; + + config0 = read_c0_config(); + + if (((config0 & MIPS_CONF_MT) >> 7) == 1) + c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; + switch (isa) { + case 0: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } + break; + case 2: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } + break; + default: + goto unknown; + } + + return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); +} + +static inline unsigned int decode_config1(struct cpuinfo_mips *c) +{ + unsigned int config1; + + config1 = read_c0_config1(); + + if (config1 & MIPS_CONF1_MD) + c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_WR) + c->options |= MIPS_CPU_WATCH; + if (config1 & MIPS_CONF1_CA) + c->ases |= MIPS_ASE_MIPS16; + if (config1 & MIPS_CONF1_EP) + c->options |= MIPS_CPU_EJTAG; + if (config1 & MIPS_CONF1_FP) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + if (cpu_has_tlb) + c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; + + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + config2 = read_c0_config2(); + + if (config2 & MIPS_CONF2_SL) + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_config3(struct cpuinfo_mips *c) +{ + unsigned int config3; + + config3 = read_c0_config3(); + + if (config3 & MIPS_CONF3_SM) + c->ases |= MIPS_ASE_SMARTMIPS; + if (config3 & MIPS_CONF3_DSP) + c->ases |= MIPS_ASE_DSP; + if (config3 & MIPS_CONF3_VINT) + c->options |= MIPS_CPU_VINT; + if (config3 & MIPS_CONF3_VEIC) + c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_MT) + c->ases |= MIPS_ASE_MIPSMT; + if (config3 & MIPS_CONF3_ULRI) + c->options |= MIPS_CPU_ULRI; + + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + config4 = read_c0_config4(); + + if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT + && cpu_has_tlb) + c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + + c->kscratch_mask = (config4 >> 16) & 0xff; + + return config4 & MIPS_CONF_M; +} + +static void __cpuinit decode_configs(struct cpuinfo_mips *c) +{ + int ok; + + /* MIPS32 or MIPS64 compliant CPU. */ + c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + ok = decode_config0(c); /* Read Config registers. */ + BUG_ON(!ok); /* Arch spec violation! */ + if (ok) + ok = decode_config1(c); + if (ok) + ok = decode_config2(c); + if (ok) + ok = decode_config3(c); + if (ok) + ok = decode_config4(c); + + mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) MIPS_CPU_32FPR; c->tlbsize = 64; break; - } -} - -static char unknown_isa[] __cpuinitdata = KERN_ERR \ - "Unsupported ISA type, c0.config0: %d."; + case PRID_IMP_LOONGSON1: + decode_configs(c); -static inline unsigned int decode_config0(struct cpuinfo_mips *c) -{ - unsigned int config0; - int isa; + c->cputype = CPU_LOONGSON1; - config0 = read_c0_config(); - - if (((config0 & MIPS_CONF_MT) >> 7) == 1) - c->options |= MIPS_CPU_TLB; - isa = (config0 & MIPS_CONF_AT) >> 13; - switch (isa) { - case 0: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M32R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M32R2; + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON1B: + __cpu_name[cpu] = "Loongson 1B"; break; - default: - goto unknown; } - break; - case 2: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M64R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M64R2; - break; - default: - goto unknown; - } - break; - default: - goto unknown; - } - - return config0 & MIPS_CONF_M; - -unknown: - panic(unknown_isa, config0); -} -static inline unsigned int decode_config1(struct cpuinfo_mips *c) -{ - unsigned int config1; - - config1 = read_c0_config1(); - - if (config1 & MIPS_CONF1_MD) - c->ases |= MIPS_ASE_MDMX; - if (config1 & MIPS_CONF1_WR) - c->options |= MIPS_CPU_WATCH; - if (config1 & MIPS_CONF1_CA) - c->ases |= MIPS_ASE_MIPS16; - if (config1 & MIPS_CONF1_EP) - c->options |= MIPS_CPU_EJTAG; - if (config1 & MIPS_CONF1_FP) { - c->options |= MIPS_CPU_FPU; - c->options |= MIPS_CPU_32FPR; + break; } - if (cpu_has_tlb) - c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; - - return config1 & MIPS_CONF_M; -} - -static inline unsigned int decode_config2(struct cpuinfo_mips *c) -{ - unsigned int config2; - - config2 = read_c0_config2(); - - if (config2 & MIPS_CONF2_SL) - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; - - return config2 & MIPS_CONF_M; -} - -static inline unsigned int decode_config3(struct cpuinfo_mips *c) -{ - unsigned int config3; - - config3 = read_c0_config3(); - - if (config3 & MIPS_CONF3_SM) - c->ases |= MIPS_ASE_SMARTMIPS; - if (config3 & MIPS_CONF3_DSP) - c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_VINT) - c->options |= MIPS_CPU_VINT; - if (config3 & MIPS_CONF3_VEIC) - c->options |= MIPS_CPU_VEIC; - if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; - if (config3 & MIPS_CONF3_ULRI) - c->options |= MIPS_CPU_ULRI; - - return config3 & MIPS_CONF_M; -} - -static inline unsigned int decode_config4(struct cpuinfo_mips *c) -{ - unsigned int config4; - - config4 = read_c0_config4(); - - if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT - && cpu_has_tlb) - c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; - - c->kscratch_mask = (config4 >> 16) & 0xff; - - return config4 & MIPS_CONF_M; -} - -static void __cpuinit decode_configs(struct cpuinfo_mips *c) -{ - int ok; - - /* MIPS32 or MIPS64 compliant CPU. */ - c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; - - c->scache.flags = MIPS_CACHE_NOT_PRESENT; - - ok = decode_config0(c); /* Read Config registers. */ - BUG_ON(!ok); /* Arch spec violation! */ - if (ok) - ok = decode_config1(c); - if (ok) - ok = decode_config2(c); - if (ok) - ok = decode_config3(c); - if (ok) - ok = decode_config4(c); - - mips_probe_watch_registers(c); - - if (cpu_has_mips_r2) - c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c index eb5e394a465..2f28d3b5568 100644 --- a/arch/mips/kernel/perf_event_mipsxx.c +++ b/arch/mips/kernel/perf_event_mipsxx.c @@ -1559,6 +1559,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.cache_event_map = &mipsxxcore_cache_map; break; + case CPU_LOONGSON1: + mipspmu.name = "mips/loongson1"; + mipspmu.general_event_map = &mipsxxcore_event_map; + mipspmu.cache_event_map = &mipsxxcore_cache_map; + break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index f11b2bbb826..028f6f837ef 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -35,16 +35,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) return add_memory_region(base, size, BOOT_MEM_RAM); } -int __init reserve_mem_mach(unsigned long addr, unsigned long size) -{ - return reserve_bootmem(addr, size, BOOTMEM_DEFAULT); -} - -void __init free_mem_mach(unsigned long addr, unsigned long size) -{ - return free_bootmem(addr, size); -} - void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); @@ -77,25 +67,6 @@ void __init early_init_devtree(void *params) of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); } -void __init device_tree_init(void) -{ - unsigned long base, size; - - if (!initial_boot_params) - return; - - base = virt_to_phys((void *)initial_boot_params); - size = be32_to_cpu(initial_boot_params->totalsize); - - /* Before we do anything, lets reserve the dt blob */ - reserve_mem_mach(base, size); - - unflatten_device_tree(); - - /* free the space reserved for the dt blob */ - free_mem_mach(base, size); -} - void __init __dt_setup_arch(struct boot_param_header *bph) { if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 1268392f1d2..31637d8c873 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void) #ifdef CONFIG_MIPS_MT_SMTC /* Only do cpu_probe for first TC of CPU */ - if ((read_c0_tcbind() & TCBIND_CURTC) == 0) + if ((read_c0_tcbind() & TCBIND_CURTC) != 0) + __cpu_name[smp_processor_id()] = __cpu_name[0]; + else #endif /* CONFIG_MIPS_MT_SMTC */ cpu_probe(); cpu_report(); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 15b5f3cfd20..1d47843d3cc 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS]; static struct smtc_ipi_q freeIPIq; +/* + * Number of FPU contexts for each VPE + */ + +static int smtc_nconf1[MAX_SMTC_VPES]; + + /* Forward declarations */ void ipi_decode(struct smtc_ipi *); @@ -174,9 +181,9 @@ static int __init tintq(char *str) __setup("tintq=", tintq); -static int imstuckcount[2][8]; +static int imstuckcount[MAX_SMTC_VPES][8]; /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ -static int vpemask[2][8] = { +static int vpemask[MAX_SMTC_VPES][8] = { {0, 0, 1, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 1} }; @@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot) static void smtc_tc_setup(int vpe, int tc, int cpu) { + static int cp1contexts[MAX_SMTC_VPES]; + + /* + * Make a local copy of the available FPU contexts in order + * to keep track of TCs that can have one. + */ + if (tc == 1) + { + /* + * FIXME: Multi-core SMTC hasn't been tested and the + * maximum number of VPEs may change. + */ + cp1contexts[0] = smtc_nconf1[0] - 1; + cp1contexts[1] = smtc_nconf1[1]; + } + settc(tc); write_tc_c0_tchalt(TCHALT_H); mips_ihb(); @@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) * an active IPI queue. */ write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); - /* Bind tc to vpe */ + + /* Bind TC to VPE. */ write_tc_c0_tcbind(vpe); + /* In general, all TCs should have the same cpu_data indications. */ memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); - /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */ - if (cpu_data[0].cputype == CPU_34K || - cpu_data[0].cputype == CPU_1004K) + + /* Check to see if there is a FPU context available for this TC. */ + if (!cp1contexts[vpe]) cpu_data[cpu].options &= ~MIPS_CPU_FPU; + else + cp1contexts[vpe]--; + + /* Store the TC and VPE into the cpu_data structure. */ cpu_data[cpu].vpe_id = vpe; cpu_data[cpu].tc_id = tc; - /* Multi-core SMTC hasn't been tested, but be prepared */ + + /* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */ cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; } /* - * Tweak to get Count registes in as close a sync as possible. The + * Tweak to get Count registers synced as closely as possible. The * value seems good for 34K-class cores. */ @@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus) smtc_configure_tlb(); for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { + /* Get number of CP1 contexts for each VPE. */ + if (tc == 0) + { + /* + * Do not call settc() for TC0 or the FPU context + * value will be incorrect. Besides, we know that + * we are TC0 anyway. + */ + smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + if (nvpe == 2) + { + settc(1); + smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & + VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); + settc(0); + } + } if (tcpervpe[vpe] == 0) continue; if (vpe != 0) @@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus) */ if (tc != 0) { smtc_tc_setup(vpe, tc, cpu); + if (vpe != 0) { + /* + * Set MVP bit (possibly again). Do it + * here to catch CPUs that have no TCs + * bound to the VPE at reset. In that + * case, a TC must be bound to the VPE + * before we can set VPEControl[MVP] + */ + write_vpe_c0_vpeconf0( + read_vpe_c0_vpeconf0() | + VPECONF0_MVP); + } cpu++; } printk(" %d", tc); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c3c29354370..9be3df1fa8a 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void) case CPU_5KC: case CPU_5KE: + case CPU_LOONGSON1: write_c0_ecc(0x80000000); back_to_back_c0_hazard(); /* Set the PE bit (bit 31) in the c0_errctl register. */ diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 2a7c74fc15f..399a50a541d 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -2,7 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \ +lib-y += csum_partial.o delay.o memcpy.o memset.o \ strlen_user.o strncpy_user.o strnlen_user.o uncached.o obj-y += iomap.o diff --git a/arch/mips/lib/memcpy-inatomic.S b/arch/mips/lib/memcpy-inatomic.S deleted file mode 100644 index 68853a038d3..00000000000 --- a/arch/mips/lib/memcpy-inatomic.S +++ /dev/null @@ -1,451 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Unified implementation of memcpy, memmove and the __copy_user backend. - * - * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. - * Copyright (C) 2002 Broadcom, Inc. - * memcpy/copy_user author: Mark Vandevoorde - * Copyright (C) 2007 Maciej W. Rozycki - * - * Mnemonic names for arguments to memcpy/__copy_user - */ - -/* - * Hack to resolve longstanding prefetch issue - * - * Prefetching may be fatal on some systems if we're prefetching beyond the - * end of memory on some systems. It's also a seriously bad idea on non - * dma-coherent systems. - */ -#ifdef CONFIG_DMA_NONCOHERENT -#undef CONFIG_CPU_HAS_PREFETCH -#endif -#ifdef CONFIG_MIPS_MALTA -#undef CONFIG_CPU_HAS_PREFETCH -#endif - -#include <asm/asm.h> -#include <asm/asm-offsets.h> -#include <asm/regdef.h> - -#define dst a0 -#define src a1 -#define len a2 - -/* - * Spec - * - * memcpy copies len bytes from src to dst and sets v0 to dst. - * It assumes that - * - src and dst don't overlap - * - src is readable - * - dst is writable - * memcpy uses the standard calling convention - * - * __copy_user copies up to len bytes from src to dst and sets a2 (len) to - * the number of uncopied bytes due to an exception caused by a read or write. - * __copy_user assumes that src and dst don't overlap, and that the call is - * implementing one of the following: - * copy_to_user - * - src is readable (no exceptions when reading src) - * copy_from_user - * - dst is writable (no exceptions when writing dst) - * __copy_user uses a non-standard calling convention; see - * include/asm-mips/uaccess.h - * - * When an exception happens on a load, the handler must - # ensure that all of the destination buffer is overwritten to prevent - * leaking information to user mode programs. - */ - -/* - * Implementation - */ - -/* - * The exception handler for loads requires that: - * 1- AT contain the address of the byte just past the end of the source - * of the copy, - * 2- src_entry <= src < AT, and - * 3- (dst - src) == (dst_entry - src_entry), - * The _entry suffix denotes values when __copy_user was called. - * - * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user - * (2) is met by incrementing src by the number of bytes copied - * (3) is met by not doing loads between a pair of increments of dst and src - * - * The exception handlers for stores adjust len (if necessary) and return. - * These handlers do not need to overwrite any data. - * - * For __rmemcpy and memmove an exception is always a kernel bug, therefore - * they're not protected. - */ - -#define EXC(inst_reg,addr,handler) \ -9: inst_reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Only on the 64-bit kernel we can made use of 64-bit registers. - */ -#ifdef CONFIG_64BIT -#define USE_DOUBLE -#endif - -#ifdef USE_DOUBLE - -#define LOAD ld -#define LOADL ldl -#define LOADR ldr -#define STOREL sdl -#define STORER sdr -#define STORE sd -#define ADD daddu -#define SUB dsubu -#define SRL dsrl -#define SRA dsra -#define SLL dsll -#define SLLV dsllv -#define SRLV dsrlv -#define NBYTES 8 -#define LOG_NBYTES 3 - -/* - * As we are sharing code base with the mips32 tree (which use the o32 ABI - * register definitions). We need to redefine the register definitions from - * the n64 ABI register naming to the o32 ABI register naming. - */ -#undef t0 -#undef t1 -#undef t2 -#undef t3 -#define t0 $8 -#define t1 $9 -#define t2 $10 -#define t3 $11 -#define t4 $12 -#define t5 $13 -#define t6 $14 -#define t7 $15 - -#else - -#define LOAD lw -#define LOADL lwl -#define LOADR lwr -#define STOREL swl -#define STORER swr -#define STORE sw -#define ADD addu -#define SUB subu -#define SRL srl -#define SLL sll -#define SRA sra -#define SLLV sllv -#define SRLV srlv -#define NBYTES 4 -#define LOG_NBYTES 2 - -#endif /* USE_DOUBLE */ - -#ifdef CONFIG_CPU_LITTLE_ENDIAN -#define LDFIRST LOADR -#define LDREST LOADL -#define STFIRST STORER -#define STREST STOREL -#define SHIFT_DISCARD SLLV -#else -#define LDFIRST LOADL -#define LDREST LOADR -#define STFIRST STOREL -#define STREST STORER -#define SHIFT_DISCARD SRLV -#endif - -#define FIRST(unit) ((unit)*NBYTES) -#define REST(unit) (FIRST(unit)+NBYTES-1) -#define UNIT(unit) FIRST(unit) - -#define ADDRMASK (NBYTES-1) - - .text - .set noreorder -#ifndef CONFIG_CPU_DADDI_WORKAROUNDS - .set noat -#else - .set at=v1 -#endif - -/* - * A combined memcpy/__copy_user - * __copy_user sets len to 0 for success; else to an upper bound of - * the number of uncopied bytes. - * memcpy sets v0 to dst. - */ - .align 5 -LEAF(__copy_user_inatomic) - /* - * Note: dst & src may be unaligned, len may be 0 - * Temps - */ -#define rem t8 - - /* - * The "issue break"s below are very approximate. - * Issue delays for dcache fills will perturb the schedule, as will - * load queue full replay traps, etc. - * - * If len < NBYTES use byte operations. - */ - PREF( 0, 0(src) ) - PREF( 1, 0(dst) ) - sltu t2, len, NBYTES - and t1, dst, ADDRMASK - PREF( 0, 1*32(src) ) - PREF( 1, 1*32(dst) ) - bnez t2, .Lcopy_bytes_checklen - and t0, src, ADDRMASK - PREF( 0, 2*32(src) ) - PREF( 1, 2*32(dst) ) - bnez t1, .Ldst_unaligned - nop - bnez t0, .Lsrc_unaligned_dst_aligned - /* - * use delay slot for fall-through - * src and dst are aligned; need to compute rem - */ -.Lboth_aligned: - SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter - beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES - and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) - PREF( 0, 3*32(src) ) - PREF( 1, 3*32(dst) ) - .align 4 -1: -EXC( LOAD t0, UNIT(0)(src), .Ll_exc) -EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) -EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) -EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) - SUB len, len, 8*NBYTES -EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) -EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy) - STORE t0, UNIT(0)(dst) - STORE t1, UNIT(1)(dst) -EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy) -EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy) - ADD src, src, 8*NBYTES - ADD dst, dst, 8*NBYTES - STORE t2, UNIT(-6)(dst) - STORE t3, UNIT(-5)(dst) - STORE t4, UNIT(-4)(dst) - STORE t7, UNIT(-3)(dst) - STORE t0, UNIT(-2)(dst) - STORE t1, UNIT(-1)(dst) - PREF( 0, 8*32(src) ) - PREF( 1, 8*32(dst) ) - bne len, rem, 1b - nop - - /* - * len == rem == the number of bytes left to copy < 8*NBYTES - */ -.Lcleanup_both_aligned: - beqz len, .Ldone - sltu t0, len, 4*NBYTES - bnez t0, .Lless_than_4units - and rem, len, (NBYTES-1) # rem = len % NBYTES - /* - * len >= 4*NBYTES - */ -EXC( LOAD t0, UNIT(0)(src), .Ll_exc) -EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) -EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) -EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) - SUB len, len, 4*NBYTES - ADD src, src, 4*NBYTES - STORE t0, UNIT(0)(dst) - STORE t1, UNIT(1)(dst) - STORE t2, UNIT(2)(dst) - STORE t3, UNIT(3)(dst) - .set reorder /* DADDI_WAR */ - ADD dst, dst, 4*NBYTES - beqz len, .Ldone - .set noreorder -.Lless_than_4units: - /* - * rem = len % NBYTES - */ - beq rem, len, .Lcopy_bytes - nop -1: -EXC( LOAD t0, 0(src), .Ll_exc) - ADD src, src, NBYTES - SUB len, len, NBYTES - STORE t0, 0(dst) - .set reorder /* DADDI_WAR */ - ADD dst, dst, NBYTES - bne rem, len, 1b - .set noreorder - - /* - * src and dst are aligned, need to copy rem bytes (rem < NBYTES) - * A loop would do only a byte at a time with possible branch - * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE - * because can't assume read-access to dst. Instead, use - * STREST dst, which doesn't require read access to dst. - * - * This code should perform better than a simple loop on modern, - * wide-issue mips processors because the code has fewer branches and - * more instruction-level parallelism. - */ -#define bits t2 - beqz len, .Ldone - ADD t1, dst, len # t1 is just past last byte of dst - li bits, 8*NBYTES - SLL rem, len, 3 # rem = number of bits to keep -EXC( LOAD t0, 0(src), .Ll_exc) - SUB bits, bits, rem # bits = number of bits to discard - SHIFT_DISCARD t0, t0, bits - STREST t0, -1(t1) - jr ra - move len, zero -.Ldst_unaligned: - /* - * dst is unaligned - * t0 = src & ADDRMASK - * t1 = dst & ADDRMASK; T1 > 0 - * len >= NBYTES - * - * Copy enough bytes to align dst - * Set match = (src and dst have same alignment) - */ -#define match rem -EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) - ADD t2, zero, NBYTES -EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) - SUB t2, t2, t1 # t2 = number of bytes copied - xor match, t0, t1 - STFIRST t3, FIRST(0)(dst) - beq len, t2, .Ldone - SUB len, len, t2 - ADD dst, dst, t2 - beqz match, .Lboth_aligned - ADD src, src, t2 - -.Lsrc_unaligned_dst_aligned: - SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter - PREF( 0, 3*32(src) ) - beqz t0, .Lcleanup_src_unaligned - and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES - PREF( 1, 3*32(dst) ) -1: -/* - * Avoid consecutive LD*'s to the same register since some mips - * implementations can't issue them in the same cycle. - * It's OK to load FIRST(N+1) before REST(N) because the two addresses - * are to the same unit (unless src is aligned, but it's not). - */ -EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) -EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) - SUB len, len, 4*NBYTES -EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) -EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) -EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) -EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) -EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) -EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) - PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) - ADD src, src, 4*NBYTES -#ifdef CONFIG_CPU_SB1 - nop # improves slotting -#endif - STORE t0, UNIT(0)(dst) - STORE t1, UNIT(1)(dst) - STORE t2, UNIT(2)(dst) - STORE t3, UNIT(3)(dst) - PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) - .set reorder /* DADDI_WAR */ - ADD dst, dst, 4*NBYTES - bne len, rem, 1b - .set noreorder - -.Lcleanup_src_unaligned: - beqz len, .Ldone - and rem, len, NBYTES-1 # rem = len % NBYTES - beq rem, len, .Lcopy_bytes - nop -1: -EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) -EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) - ADD src, src, NBYTES - SUB len, len, NBYTES - STORE t0, 0(dst) - .set reorder /* DADDI_WAR */ - ADD dst, dst, NBYTES - bne len, rem, 1b - .set noreorder - -.Lcopy_bytes_checklen: - beqz len, .Ldone - nop -.Lcopy_bytes: - /* 0 < len < NBYTES */ -#define COPY_BYTE(N) \ -EXC( lb t0, N(src), .Ll_exc); \ - SUB len, len, 1; \ - beqz len, .Ldone; \ - sb t0, N(dst) - - COPY_BYTE(0) - COPY_BYTE(1) -#ifdef USE_DOUBLE - COPY_BYTE(2) - COPY_BYTE(3) - COPY_BYTE(4) - COPY_BYTE(5) -#endif -EXC( lb t0, NBYTES-2(src), .Ll_exc) - SUB len, len, 1 - jr ra - sb t0, NBYTES-2(dst) -.Ldone: - jr ra - nop - END(__copy_user_inatomic) - -.Ll_exc_copy: - /* - * Copy bytes from src until faulting load address (or until a - * lb faults) - * - * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28) - * may be more than a byte beyond the last address. - * Hence, the lb below may get an exception. - * - * Assumes src < THREAD_BUADDR($28) - */ - LOAD t0, TI_TASK($28) - nop - LOAD t0, THREAD_BUADDR(t0) -1: -EXC( lb t1, 0(src), .Ll_exc) - ADD src, src, 1 - sb t1, 0(dst) # can't fault -- we're copy_from_user - .set reorder /* DADDI_WAR */ - ADD dst, dst, 1 - bne src, t0, 1b - .set noreorder -.Ll_exc: - LOAD t0, TI_TASK($28) - nop - LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address - nop - SUB len, AT, t0 # len number of uncopied bytes - jr ra - nop diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index 56a1f85a1ce..65192c06781 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S @@ -183,6 +183,14 @@ #endif /* + * t6 is used as a flag to note inatomic mode. + */ +LEAF(__copy_user_inatomic) + b __copy_user_common + li t6, 1 + END(__copy_user_inatomic) + +/* * A combined memcpy/__copy_user * __copy_user sets len to 0 for success; else to an upper bound of * the number of uncopied bytes. @@ -193,6 +201,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ move v0, dst /* return value */ .L__memcpy: FEXPORT(__copy_user) + li t6, 0 /* not inatomic */ +__copy_user_common: /* * Note: dst & src may be unaligned, len may be 0 * Temps @@ -458,6 +468,7 @@ EXC( lb t1, 0(src), .Ll_exc) LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address nop SUB len, AT, t0 # len number of uncopied bytes + bnez t6, .Ldone /* Skip the zeroing part if inatomic */ /* * Here's where we rely on src and dst being incremented in tandem, * See (3) above. diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig new file mode 100644 index 00000000000..237fa214de9 --- /dev/null +++ b/arch/mips/loongson1/Kconfig @@ -0,0 +1,21 @@ +if MACH_LOONGSON1 + +choice + prompt "Machine Type" + +config LOONGSON1_LS1B + bool "Loongson LS1B board" + select CEVT_R4K + select CSRC_R4K + select SYS_HAS_CPU_LOONGSON1B + select DMA_NONCOHERENT + select BOOT_ELF32 + select IRQ_CPU + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_HIGHMEM + select SYS_HAS_EARLY_PRINTK + +endchoice + +endif # MACH_LOONGSON1 diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson1/Makefile new file mode 100644 index 00000000000..9719c75886f --- /dev/null +++ b/arch/mips/loongson1/Makefile @@ -0,0 +1,11 @@ +# +# Common code for all Loongson 1 based systems +# + +obj-$(CONFIG_MACH_LOONGSON1) += common/ + +# +# Loongson LS1B board +# + +obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/ diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson1/Platform new file mode 100644 index 00000000000..99bdefe627a --- /dev/null +++ b/arch/mips/loongson1/Platform @@ -0,0 +1,7 @@ +cflags-$(CONFIG_CPU_LOONGSON1) += \ + $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ + -Wa,-mips32r2 -Wa,--trap + +platform-$(CONFIG_MACH_LOONGSON1) += loongson1/ +cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1 +load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80100000 diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile new file mode 100644 index 00000000000..b2797709ef5 --- /dev/null +++ b/arch/mips/loongson1/common/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for common code of loongson1 based machines. +# + +obj-y += clock.o irq.o platform.o prom.o reset.o setup.o diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c new file mode 100644 index 00000000000..2d98fb03059 --- /dev/null +++ b/arch/mips/loongson1/common/clock.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/module.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <asm/clock.h> +#include <asm/time.h> + +#include <loongson1.h> + +static LIST_HEAD(clocks); +static DEFINE_MUTEX(clocks_mutex); + +struct clk *clk_get(struct device *dev, const char *name) +{ + struct clk *c; + struct clk *ret = NULL; + + mutex_lock(&clocks_mutex); + list_for_each_entry(c, &clocks, node) { + if (!strcmp(c->name, name)) { + ret = c; + break; + } + } + mutex_unlock(&clocks_mutex); + + return ret; +} +EXPORT_SYMBOL(clk_get); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +static void pll_clk_init(struct clk *clk) +{ + u32 pll; + + pll = __raw_readl(LS1X_CLK_PLL_FREQ); + clk->rate = (12 + (pll & 0x3f)) * 33 / 2 + + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2; + clk->rate *= 1000000; +} + +static void cpu_clk_init(struct clk *clk) +{ + u32 pll, ctrl; + + pll = clk_get_rate(clk->parent); + ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU; + clk->rate = pll / (ctrl >> DIV_CPU_SHIFT); +} + +static void ddr_clk_init(struct clk *clk) +{ + u32 pll, ctrl; + + pll = clk_get_rate(clk->parent); + ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR; + clk->rate = pll / (ctrl >> DIV_DDR_SHIFT); +} + +static void dc_clk_init(struct clk *clk) +{ + u32 pll, ctrl; + + pll = clk_get_rate(clk->parent); + ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC; + clk->rate = pll / (ctrl >> DIV_DC_SHIFT); +} + +static struct clk_ops pll_clk_ops = { + .init = pll_clk_init, +}; + +static struct clk_ops cpu_clk_ops = { + .init = cpu_clk_init, +}; + +static struct clk_ops ddr_clk_ops = { + .init = ddr_clk_init, +}; + +static struct clk_ops dc_clk_ops = { + .init = dc_clk_init, +}; + +static struct clk pll_clk = { + .name = "pll", + .ops = &pll_clk_ops, +}; + +static struct clk cpu_clk = { + .name = "cpu", + .parent = &pll_clk, + .ops = &cpu_clk_ops, +}; + +static struct clk ddr_clk = { + .name = "ddr", + .parent = &pll_clk, + .ops = &ddr_clk_ops, +}; + +static struct clk dc_clk = { + .name = "dc", + .parent = &pll_clk, + .ops = &dc_clk_ops, +}; + +int clk_register(struct clk *clk) +{ + mutex_lock(&clocks_mutex); + list_add(&clk->node, &clocks); + if (clk->ops->init) + clk->ops->init(clk); + mutex_unlock(&clocks_mutex); + + return 0; +} +EXPORT_SYMBOL(clk_register); + +static struct clk *ls1x_clks[] = { + &pll_clk, + &cpu_clk, + &ddr_clk, + &dc_clk, +}; + +int __init ls1x_clock_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++) + clk_register(ls1x_clks[i]); + + return 0; +} + +void __init plat_time_init(void) +{ + struct clk *clk; + + /* Initialize LS1X clocks */ + ls1x_clock_init(); + + /* setup mips r4k timer */ + clk = clk_get(NULL, "cpu"); + if (IS_ERR(clk)) + panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); + + mips_hpt_frequency = clk_get_rate(clk) / 2; +} diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson1/common/irq.c new file mode 100644 index 00000000000..41bc8ffe7bb --- /dev/null +++ b/arch/mips/loongson1/common/irq.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/interrupt.h> +#include <linux/irq.h> +#include <asm/irq_cpu.h> + +#include <loongson1.h> +#include <irq.h> + +#define LS1X_INTC_REG(n, x) \ + ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x))) + +#define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0) +#define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4) +#define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8) +#define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc) +#define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10) +#define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14) + +static void ls1x_irq_ack(struct irq_data *d) +{ + unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; + unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; + + __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) + | (1 << bit), LS1X_INTC_INTCLR(n)); +} + +static void ls1x_irq_mask(struct irq_data *d) +{ + unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; + unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; + + __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) + & ~(1 << bit), LS1X_INTC_INTIEN(n)); +} + +static void ls1x_irq_mask_ack(struct irq_data *d) +{ + unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; + unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; + + __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) + & ~(1 << bit), LS1X_INTC_INTIEN(n)); + __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) + | (1 << bit), LS1X_INTC_INTCLR(n)); +} + +static void ls1x_irq_unmask(struct irq_data *d) +{ + unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; + unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; + + __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) + | (1 << bit), LS1X_INTC_INTIEN(n)); +} + +static struct irq_chip ls1x_irq_chip = { + .name = "LS1X-INTC", + .irq_ack = ls1x_irq_ack, + .irq_mask = ls1x_irq_mask, + .irq_mask_ack = ls1x_irq_mask_ack, + .irq_unmask = ls1x_irq_unmask, +}; + +static void ls1x_irq_dispatch(int n) +{ + u32 int_status, irq; + + /* Get pending sources, masked by current enables */ + int_status = __raw_readl(LS1X_INTC_INTISR(n)) & + __raw_readl(LS1X_INTC_INTIEN(n)); + + if (int_status) { + irq = LS1X_IRQ(n, __ffs(int_status)); + do_IRQ(irq); + } +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending; + + pending = read_c0_cause() & read_c0_status() & ST0_IM; + + if (pending & CAUSEF_IP7) + do_IRQ(TIMER_IRQ); + else if (pending & CAUSEF_IP2) + ls1x_irq_dispatch(0); /* INT0 */ + else if (pending & CAUSEF_IP3) + ls1x_irq_dispatch(1); /* INT1 */ + else if (pending & CAUSEF_IP4) + ls1x_irq_dispatch(2); /* INT2 */ + else if (pending & CAUSEF_IP5) + ls1x_irq_dispatch(3); /* INT3 */ + else if (pending & CAUSEF_IP6) + ls1x_irq_dispatch(4); /* INT4 */ + else + spurious_interrupt(); + +} + +struct irqaction cascade_irqaction = { + .handler = no_action, + .name = "cascade", + .flags = IRQF_NO_THREAD, +}; + +static void __init ls1x_irq_init(int base) +{ + int n; + + /* Disable interrupts and clear pending, + * setup all IRQs as high level triggered + */ + for (n = 0; n < 4; n++) { + __raw_writel(0x0, LS1X_INTC_INTIEN(n)); + __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n)); + __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n)); + /* set DMA0, DMA1 and DMA2 to edge trigger */ + __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n)); + } + + + for (n = base; n < LS1X_IRQS; n++) { + irq_set_chip_and_handler(n, &ls1x_irq_chip, + handle_level_irq); + } + + setup_irq(INT0_IRQ, &cascade_irqaction); + setup_irq(INT1_IRQ, &cascade_irqaction); + setup_irq(INT2_IRQ, &cascade_irqaction); + setup_irq(INT3_IRQ, &cascade_irqaction); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + ls1x_irq_init(LS1X_IRQ_BASE); +} diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c new file mode 100644 index 00000000000..e92d59c4bd7 --- /dev/null +++ b/arch/mips/loongson1/common/platform.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/clk.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/phy.h> +#include <linux/serial_8250.h> +#include <linux/stmmac.h> +#include <asm-generic/sizes.h> + +#include <loongson1.h> + +#define LS1X_UART(_id) \ + { \ + .mapbase = LS1X_UART ## _id ## _BASE, \ + .irq = LS1X_UART ## _id ## _IRQ, \ + .iotype = UPIO_MEM, \ + .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \ + .type = PORT_16550A, \ + } + +static struct plat_serial8250_port ls1x_serial8250_port[] = { + LS1X_UART(0), + LS1X_UART(1), + LS1X_UART(2), + LS1X_UART(3), + {}, +}; + +struct platform_device ls1x_uart_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = ls1x_serial8250_port, + }, +}; + +void __init ls1x_serial_setup(void) +{ + struct clk *clk; + struct plat_serial8250_port *p; + + clk = clk_get(NULL, "dc"); + if (IS_ERR(clk)) + panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); + + for (p = ls1x_serial8250_port; p->flags != 0; ++p) + p->uartclk = clk_get_rate(clk); +} + +/* Synopsys Ethernet GMAC */ +static struct resource ls1x_eth0_resources[] = { + [0] = { + .start = LS1X_GMAC0_BASE, + .end = LS1X_GMAC0_BASE + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "macirq", + .start = LS1X_GMAC0_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { + .bus_id = 0, + .phy_mask = 0, +}; + +static struct plat_stmmacenet_data ls1x_eth_data = { + .bus_id = 0, + .phy_addr = -1, + .mdio_bus_data = &ls1x_mdio_bus_data, + .has_gmac = 1, + .tx_coe = 1, +}; + +struct platform_device ls1x_eth0_device = { + .name = "stmmaceth", + .id = 0, + .num_resources = ARRAY_SIZE(ls1x_eth0_resources), + .resource = ls1x_eth0_resources, + .dev = { + .platform_data = &ls1x_eth_data, + }, +}; + +/* USB EHCI */ +static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); + +static struct resource ls1x_ehci_resources[] = { + [0] = { + .start = LS1X_EHCI_BASE, + .end = LS1X_EHCI_BASE + SZ_32K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = LS1X_EHCI_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device ls1x_ehci_device = { + .name = "ls1x-ehci", + .id = -1, + .num_resources = ARRAY_SIZE(ls1x_ehci_resources), + .resource = ls1x_ehci_resources, + .dev = { + .dma_mask = &ls1x_ehci_dmamask, + }, +}; + +/* Real Time Clock */ +struct platform_device ls1x_rtc_device = { + .name = "ls1x-rtc", + .id = -1, +}; diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c new file mode 100644 index 00000000000..1f8e49f9886 --- /dev/null +++ b/arch/mips/loongson1/common/prom.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> + * + * Modified from arch/mips/pnx833x/common/prom.c. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/serial_reg.h> +#include <asm/bootinfo.h> + +#include <loongson1.h> +#include <prom.h> + +int prom_argc; +char **prom_argv, **prom_envp; +unsigned long memsize, highmemsize; + +char *prom_getenv(char *envname) +{ + char **env = prom_envp; + int i; + + i = strlen(envname); + + while (*env) { + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') + return *env + i + 1; + env++; + } + + return 0; +} + +static inline unsigned long env_or_default(char *env, unsigned long dfl) +{ + char *str = prom_getenv(env); + return str ? simple_strtol(str, 0, 0) : dfl; +} + +void __init prom_init_cmdline(void) +{ + char *c = &(arcs_cmdline[0]); + int i; + + for (i = 1; i < prom_argc; i++) { + strcpy(c, prom_argv[i]); + c += strlen(prom_argv[i]); + if (i < prom_argc-1) + *c++ = ' '; + } + *c = 0; +} + +void __init prom_init(void) +{ + prom_argc = fw_arg0; + prom_argv = (char **)fw_arg1; + prom_envp = (char **)fw_arg2; + + prom_init_cmdline(); + + memsize = env_or_default("memsize", DEFAULT_MEMSIZE); + highmemsize = env_or_default("highmemsize", 0x0); +} + +void __init prom_free_prom_memory(void) +{ +} + +#define PORT(offset) (u8 *)(KSEG1ADDR(LS1X_UART0_BASE + offset)) + +void __init prom_putchar(char c) +{ + int timeout; + + timeout = 1024; + + while (((readb(PORT(UART_LSR)) & UART_LSR_THRE) == 0) + && (timeout-- > 0)) + ; + + writeb(c, PORT(UART_TX)); +} diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c new file mode 100644 index 00000000000..fb979a784ec --- /dev/null +++ b/arch/mips/loongson1/common/reset.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/io.h> +#include <linux/pm.h> +#include <asm/reboot.h> + +#include <loongson1.h> + +static void ls1x_restart(char *command) +{ + __raw_writel(0x1, LS1X_WDT_EN); + __raw_writel(0x5000000, LS1X_WDT_TIMER); + __raw_writel(0x1, LS1X_WDT_SET); +} + +static void ls1x_halt(void) +{ + while (1) { + if (cpu_wait) + cpu_wait(); + } +} + +static void ls1x_power_off(void) +{ + ls1x_halt(); +} + +static int __init ls1x_reboot_setup(void) +{ + _machine_restart = ls1x_restart; + _machine_halt = ls1x_halt; + pm_power_off = ls1x_power_off; + + return 0; +} + +arch_initcall(ls1x_reboot_setup); diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson1/common/setup.c new file mode 100644 index 00000000000..62128cc27e6 --- /dev/null +++ b/arch/mips/loongson1/common/setup.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 <asm/bootinfo.h> + +#include <prom.h> + +void __init plat_mem_setup(void) +{ + add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); +} + +const char *get_system_type(void) +{ + unsigned int processor_id = (¤t_cpu_data)->processor_id; + + switch (processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON1B: + return "LOONGSON LS1B"; + default: + return "LOONGSON (unknown)"; + } +} diff --git a/arch/mips/loongson1/ls1b/Makefile b/arch/mips/loongson1/ls1b/Makefile new file mode 100644 index 00000000000..891eac482b8 --- /dev/null +++ b/arch/mips/loongson1/ls1b/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for loongson1B based machines. +# + +obj-y += board.o diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c new file mode 100644 index 00000000000..295b1be893e --- /dev/null +++ b/arch/mips/loongson1/ls1b/board.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 <platform.h> + +#include <linux/serial_8250.h> +#include <loongson1.h> + +static struct platform_device *ls1b_platform_devices[] __initdata = { + &ls1x_uart_device, + &ls1x_eth0_device, + &ls1x_ehci_device, + &ls1x_rtc_device, +}; + +static int __init ls1b_platform_init(void) +{ + int err; + + ls1x_serial_setup(); + + err = platform_add_devices(ls1b_platform_devices, + ARRAY_SIZE(ls1b_platform_devices)); + return err; +} + +arch_initcall(ls1b_platform_init); diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 5fa185151fc..64a28e81906 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -58,18 +58,16 @@ enum fields { enum opcode { insn_invalid, - insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, - insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, - insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, - insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, - insn_dsrl32, insn_drotr, insn_drotr32, insn_dsubu, insn_eret, - insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, - insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_or, insn_ori, - insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, - insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, + insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1, + insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, + insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, + insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, + insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, + insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, + insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, + insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, + insn_sra, insn_srl, insn_subu, insn_sw, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, - insn_dins, insn_dinsm, insn_syscall, insn_bbit0, insn_bbit1, - insn_lwx, insn_ldx }; struct insn { @@ -90,65 +88,65 @@ struct insn { static struct insn insn_table[] __uasminitdata = { { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, - { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, - { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, + { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, + { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM }, + { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM }, - { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, + { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM }, { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM }, + { insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, + { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, + { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE }, + { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, + { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE }, + { insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE }, { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, - { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, - { insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, - { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, + { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, - { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, + { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, - { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, - { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, + { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, - { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE }, { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, - { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE }, { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, - { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, - { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, - { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, - { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, - { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, - { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, - { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, + { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_invalid, 0, 0 } }; diff --git a/arch/mips/netlogic/common/earlycons.c b/arch/mips/netlogic/common/earlycons.c index f193f7b3bd8..1902fa22d27 100644 --- a/arch/mips/netlogic/common/earlycons.c +++ b/arch/mips/netlogic/common/earlycons.c @@ -54,7 +54,7 @@ void prom_putchar(char c) #elif defined(CONFIG_CPU_XLR) uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); #endif - while (nlm_read_reg(uartbase, UART_LSR) == 0) + while ((nlm_read_reg(uartbase, UART_LSR) & UART_LSR_THRE) == 0) ; nlm_write_reg(uartbase, UART_TX, c); } diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index c138b1a6dec..a13355cc97e 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -54,28 +54,68 @@ XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ SYS_CPU_NONCOHERENT_MODE * 4 -.macro __config_lsu - li t0, LSU_DEFEATURE - mfcr t1, t0 +#define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */ - lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ - or t1, t1, t2 - li t2, ~0xe /* S1RCM */ +/* Enable XLP features and workarounds in the LSU */ +.macro xlp_config_lsu + li t0, LSU_DEFEATURE + mfcr t1, t0 + + lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ + or t1, t1, t2 +#ifdef XLP_AX_WORKAROUND + li t2, ~0xe /* S1RCM */ and t1, t1, t2 - mtcr t1, t0 +#endif + mtcr t1, t0 - li t0, SCHED_DEFEATURE - lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */ - mtcr t1, t0 +#ifdef XLP_AX_WORKAROUND + li t0, SCHED_DEFEATURE + lui t1, 0x0100 /* Disable BRU accepting ALU ops */ + mtcr t1, t0 +#endif +.endm + +/* + * This is the code that will be copied to the reset entry point for + * XLR and XLP. The XLP cores start here when they are woken up. This + * is also the NMI entry point. + */ +.macro xlp_flush_l1_dcache + li t0, LSU_DEBUG_DATA0 + li t1, LSU_DEBUG_ADDR + li t2, 0 /* index */ + li t3, 0x1000 /* loop count */ +1: + sll v0, t2, 5 + mtcr zero, t0 + ori v1, v0, 0x3 /* way0 | write_enable | write_active */ + mtcr v1, t1 +2: + mfcr v1, t1 + andi v1, 0x1 /* wait for write_active == 0 */ + bnez v1, 2b + nop + mtcr zero, t0 + ori v1, v0, 0x7 /* way1 | write_enable | write_active */ + mtcr v1, t1 +3: + mfcr v1, t1 + andi v1, 0x1 /* wait for write_active == 0 */ + bnez v1, 3b + nop + addi t2, 1 + bne t3, t2, 1b + nop .endm /* * The cores can come start when they are woken up. This is also the NMI * entry, so check that first. * - * The data corresponding to reset is stored at RESET_DATA_PHYS location, - * this will have the thread mask (used when core is woken up) and the - * current NMI handler in case we reached here for an NMI. + * The data corresponding to reset/NMI is stored at RESET_DATA_PHYS + * location, this will have the thread mask (used when core is woken up) + * and the current NMI handler in case we reached here for an NMI. * * When a core or thread is newly woken up, it loops in a 'wait'. When * the CPU really needs waking up, we send an NMI to it, with the NMI @@ -89,12 +129,12 @@ FEXPORT(nlm_reset_entry) dmtc0 k0, $22, 6 dmtc0 k1, $22, 7 - mfc0 k0, CP0_STATUS - li k1, 0x80000 - and k1, k0, k1 - beqz k1, 1f /* go to real reset entry */ + mfc0 k0, CP0_STATUS + li k1, 0x80000 + and k1, k0, k1 + beqz k1, 1f /* go to real reset entry */ nop - li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ + li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ ld k0, BOOT_NMI_HANDLER(k1) jr k0 nop @@ -114,21 +154,25 @@ FEXPORT(nlm_reset_entry) li t2, SYS_CPU_COHERENT_BASE(0) add t2, t2, t3 /* t2 <- SYS offset for node */ lw t1, 0(t2) - and t1, t1, t0 - sw t1, 0(t2) + and t1, t1, t0 + sw t1, 0(t2) /* read back to ensure complete */ - lw t1, 0(t2) + lw t1, 0(t2) sync /* Configure LSU on Non-0 Cores. */ - __config_lsu + xlp_config_lsu + /* FALL THROUGH */ /* * Wake up sibling threads from the initial thread in * a core. */ EXPORT(nlm_boot_siblings) + /* core L1D flush before enable threads */ + xlp_flush_l1_dcache + /* Enable hw threads by writing to MAP_THREADMODE of the core */ li t0, CKSEG1ADDR(RESET_DATA_PHYS) lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) @@ -139,31 +183,28 @@ EXPORT(nlm_boot_siblings) /* * The new hardware thread starts at the next instruction * For all the cases other than core 0 thread 0, we will - * jump to the secondary wait function. - */ + * jump to the secondary wait function. + */ mfc0 v0, CP0_EBASE, 1 andi v0, 0x7f /* v0 <- node/core */ -#if 1 - /* A0 errata - Write MMU_SETUP after changing thread mode register. */ + /* Init MMU in the first thread after changing THREAD_MODE + * register (Ax Errata?) + */ andi v1, v0, 0x3 /* v1 <- thread id */ bnez v1, 2f nop - li t0, MMU_SETUP - li t1, 0 - mtcr t1, t0 - ehb -#endif + li t0, MMU_SETUP + li t1, 0 + mtcr t1, t0 + _ehb -2: beqz v0, 4f +2: beqz v0, 4f /* boot cpu (cpuid == 0)? */ nop /* setup status reg */ - mfc0 t1, CP0_STATUS - li t0, ST0_BEV - or t1, t0 - xor t1, t0 + move t1, zero #ifdef CONFIG_64BIT ori t1, ST0_KX #endif @@ -183,9 +224,9 @@ EXPORT(nlm_boot_siblings) * For the boot CPU, we have to restore registers and * return */ -4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ +4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ li t1, 0xfadebeef - dmtc0 t1, $4, 2 /* restore SP from UserLocal */ + dmtc0 t1, $4, 2 /* restore SP from UserLocal */ PTR_SUBU sp, t0, PT_SIZE RESTORE_ALL jr ra @@ -193,7 +234,7 @@ EXPORT(nlm_boot_siblings) EXPORT(nlm_reset_entry_end) FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ - __config_lsu + xlp_config_lsu dmtc0 sp, $4, 2 /* SP saved in UserLocal */ SAVE_ALL sync @@ -210,6 +251,12 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ __CPUINIT NESTED(nlm_boot_secondary_cpus, 16, sp) + /* Initialize CP0 Status */ + move t1, zero +#ifdef CONFIG_64BIT + ori t1, ST0_KX +#endif + mtc0 t1, CP0_STATUS PTR_LA t1, nlm_next_sp PTR_L sp, 0(t1) PTR_LA t1, nlm_next_gp @@ -234,36 +281,36 @@ END(nlm_boot_secondary_cpus) */ __CPUINIT NESTED(nlm_rmiboot_preboot, 16, sp) - mfc0 t0, $15, 1 # read ebase - andi t0, 0x1f # t0 has the processor_id() - andi t2, t0, 0x3 # thread no - sll t0, 2 # offset in cpu array + mfc0 t0, $15, 1 /* read ebase */ + andi t0, 0x1f /* t0 has the processor_id() */ + andi t2, t0, 0x3 /* thread num */ + sll t0, 2 /* offset in cpu array */ - PTR_LA t1, nlm_cpu_ready # mark CPU ready + PTR_LA t1, nlm_cpu_ready /* mark CPU ready */ PTR_ADDU t1, t0 li t3, 1 sw t3, 0(t1) - bnez t2, 1f # skip thread programming - nop # for non zero hw threads + bnez t2, 1f /* skip thread programming */ + nop /* for thread id != 0 */ /* - * MMU setup only for first thread in core + * XLR MMU setup only for first thread in core */ li t0, 0x400 mfcr t1, t0 - li t2, 6 # XLR thread mode mask + li t2, 6 /* XLR thread mode mask */ nor t3, t2, zero - and t2, t1, t2 # t2 - current thread mode + and t2, t1, t2 /* t2 - current thread mode */ li v0, CKSEG1ADDR(RESET_DATA_PHYS) - lw v1, BOOT_THREAD_MODE(v0) # v1 - new thread mode + lw v1, BOOT_THREAD_MODE(v0) /* v1 - new thread mode */ sll v1, 1 - beq v1, t2, 1f # same as request value - nop # nothing to do */ + beq v1, t2, 1f /* same as request value */ + nop /* nothing to do */ - and t2, t1, t3 # mask out old thread mode - or t1, t2, v1 # put in new value - mtcr t1, t0 # update core control + and t2, t1, t3 /* mask out old thread mode */ + or t1, t2, v1 /* put in new value */ + mtcr t1, t0 /* update core control */ 1: wait j 1b diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index b93ed83474e..6b4b972218f 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -1,2 +1,4 @@ obj-y += setup.o platform.o nlm_hal.o +obj-$(CONFIG_OF) += of.o obj-$(CONFIG_SMP) += wakeup.o +obj-$(CONFIG_USB) += usb-init.o diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 9428e7125fe..6c65ac70191 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -69,6 +69,32 @@ int nlm_irq_to_irt(int irq) return PIC_IRT_UART_0_INDEX; case PIC_UART_1_IRQ: return PIC_IRT_UART_1_INDEX; + case PIC_PCIE_LINK_0_IRQ: + return PIC_IRT_PCIE_LINK_0_INDEX; + case PIC_PCIE_LINK_1_IRQ: + return PIC_IRT_PCIE_LINK_1_INDEX; + case PIC_PCIE_LINK_2_IRQ: + return PIC_IRT_PCIE_LINK_2_INDEX; + case PIC_PCIE_LINK_3_IRQ: + return PIC_IRT_PCIE_LINK_3_INDEX; + case PIC_EHCI_0_IRQ: + return PIC_IRT_EHCI_0_INDEX; + case PIC_EHCI_1_IRQ: + return PIC_IRT_EHCI_1_INDEX; + case PIC_OHCI_0_IRQ: + return PIC_IRT_OHCI_0_INDEX; + case PIC_OHCI_1_IRQ: + return PIC_IRT_OHCI_1_INDEX; + case PIC_OHCI_2_IRQ: + return PIC_IRT_OHCI_2_INDEX; + case PIC_OHCI_3_IRQ: + return PIC_IRT_OHCI_3_INDEX; + case PIC_MMC_IRQ: + return PIC_IRT_MMC_INDEX; + case PIC_I2C_0_IRQ: + return PIC_IRT_I2C_0_INDEX; + case PIC_I2C_1_IRQ: + return PIC_IRT_I2C_1_INDEX; default: return -1; } @@ -81,6 +107,32 @@ int nlm_irt_to_irq(int irt) return PIC_UART_0_IRQ; case PIC_IRT_UART_1_INDEX: return PIC_UART_1_IRQ; + case PIC_IRT_PCIE_LINK_0_INDEX: + return PIC_PCIE_LINK_0_IRQ; + case PIC_IRT_PCIE_LINK_1_INDEX: + return PIC_PCIE_LINK_1_IRQ; + case PIC_IRT_PCIE_LINK_2_INDEX: + return PIC_PCIE_LINK_2_IRQ; + case PIC_IRT_PCIE_LINK_3_INDEX: + return PIC_PCIE_LINK_3_IRQ; + case PIC_IRT_EHCI_0_INDEX: + return PIC_EHCI_0_IRQ; + case PIC_IRT_EHCI_1_INDEX: + return PIC_EHCI_1_IRQ; + case PIC_IRT_OHCI_0_INDEX: + return PIC_OHCI_0_IRQ; + case PIC_IRT_OHCI_1_INDEX: + return PIC_OHCI_1_IRQ; + case PIC_IRT_OHCI_2_INDEX: + return PIC_OHCI_2_IRQ; + case PIC_IRT_OHCI_3_INDEX: + return PIC_OHCI_3_IRQ; + case PIC_IRT_MMC_INDEX: + return PIC_MMC_IRQ; + case PIC_IRT_I2C_0_INDEX: + return PIC_I2C_0_IRQ; + case PIC_IRT_I2C_1_INDEX: + return PIC_I2C_1_IRQ; default: return -1; } diff --git a/arch/mips/netlogic/xlp/of.c b/arch/mips/netlogic/xlp/of.c new file mode 100644 index 00000000000..8e3921c0c20 --- /dev/null +++ b/arch/mips/netlogic/xlp/of.c @@ -0,0 +1,34 @@ +#include <linux/bootmem.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/of_fdt.h> +#include <asm/byteorder.h> + +static int __init reserve_mem_mach(unsigned long addr, unsigned long size) +{ + return reserve_bootmem(addr, size, BOOTMEM_DEFAULT); +} + +void __init free_mem_mach(unsigned long addr, unsigned long size) +{ + return free_bootmem(addr, size); +} + +void __init device_tree_init(void) +{ + unsigned long base, size; + + if (!initial_boot_params) + return; + + base = virt_to_phys((void *)initial_boot_params); + size = be32_to_cpu(initial_boot_params->totalsize); + + /* Before we do anything, lets reserve the dt blob */ + reserve_mem_mach(base, size); + + unflatten_device_tree(); + + /* free the space reserved for the dt blob */ + free_mem_mach(base, size); +} diff --git a/arch/mips/netlogic/xlp/platform.c b/arch/mips/netlogic/xlp/platform.c index 1f5e4cba891..2c510d58544 100644 --- a/arch/mips/netlogic/xlp/platform.c +++ b/arch/mips/netlogic/xlp/platform.c @@ -53,7 +53,7 @@ static unsigned int nlm_xlp_uart_in(struct uart_port *p, int offset) { - return nlm_read_reg(p->iobase, offset); + return nlm_read_reg(p->iobase, offset); } static void nlm_xlp_uart_out(struct uart_port *p, int offset, int value) diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index b3df7c2aad1..3dec9f28b65 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -41,6 +41,8 @@ #include <asm/bootinfo.h> #include <linux/of_fdt.h> +#include <linux/of_platform.h> +#include <linux/of_device.h> #include <asm/netlogic/haldefs.h> #include <asm/netlogic/common.h> @@ -109,3 +111,17 @@ void __init prom_init(void) register_smp_ops(&nlm_smp_ops); #endif } + +static struct of_device_id __initdata xlp_ids[] = { + { .compatible = "simple-bus", }, + {}, +}; + +int __init xlp8xx_ds_publish_devices(void) +{ + if (!of_have_populated_dt()) + return 0; + return of_platform_bus_probe(NULL, xlp_ids, NULL); +} + +device_initcall(xlp8xx_ds_publish_devices); diff --git a/arch/mips/netlogic/xlp/usb-init.c b/arch/mips/netlogic/xlp/usb-init.c new file mode 100644 index 00000000000..dbe083a9353 --- /dev/null +++ b/arch/mips/netlogic/xlp/usb-init.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/usb.h> + +static void nlm_usb_intr_en(int node, int port) +{ + uint32_t val; + uint64_t port_addr; + + port_addr = nlm_get_usb_regbase(node, port); + val = nlm_read_usb_reg(port_addr, USB_INT_EN); + val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN | + USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN | + USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN; + nlm_write_usb_reg(port_addr, USB_INT_EN, val); +} + +static void nlm_usb_hw_reset(int node, int port) +{ + uint64_t port_addr; + uint32_t val; + + /* reset USB phy */ + port_addr = nlm_get_usb_regbase(node, port); + val = nlm_read_usb_reg(port_addr, USB_PHY_0); + val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1); + nlm_write_usb_reg(port_addr, USB_PHY_0, val); + + mdelay(100); + val = nlm_read_usb_reg(port_addr, USB_CTL_0); + val &= ~(USB_CONTROLLER_RESET); + val |= 0x4; + nlm_write_usb_reg(port_addr, USB_CTL_0, val); +} + +static int __init nlm_platform_usb_init(void) +{ + pr_info("Initializing USB Interface\n"); + nlm_usb_hw_reset(0, 0); + nlm_usb_hw_reset(0, 3); + + /* Enable PHY interrupts */ + nlm_usb_intr_en(0, 0); + nlm_usb_intr_en(0, 3); + + return 0; +} + +arch_initcall(nlm_platform_usb_init); + +static u64 xlp_usb_dmamask = ~(u32)0; + +/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */ +static void nlm_usb_fixup_final(struct pci_dev *dev) +{ + dev->dev.dma_mask = &xlp_usb_dmamask; + dev->dev.coherent_dma_mask = DMA_BIT_MASK(64); + switch (dev->devfn) { + case 0x10: + dev->irq = PIC_EHCI_0_IRQ; + break; + case 0x11: + dev->irq = PIC_OHCI_0_IRQ; + break; + case 0x12: + dev->irq = PIC_OHCI_1_IRQ; + break; + case 0x13: + dev->irq = PIC_EHCI_1_IRQ; + break; + case 0x14: + dev->irq = PIC_OHCI_2_IRQ; + break; + case 0x15: + dev->irq = PIC_OHCI_3_IRQ; + break; + } +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI, + nlm_usb_fixup_final); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI, + nlm_usb_fixup_final); diff --git a/arch/mips/netlogic/xlr/Makefile b/arch/mips/netlogic/xlr/Makefile index f01e4d7a060..c287dea8757 100644 --- a/arch/mips/netlogic/xlr/Makefile +++ b/arch/mips/netlogic/xlr/Makefile @@ -1,2 +1,2 @@ -obj-y += setup.o platform.o +obj-y += setup.o platform.o platform-flash.o obj-$(CONFIG_SMP) += wakeup.o diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c new file mode 100644 index 00000000000..340ab1601c4 --- /dev/null +++ b/arch/mips/netlogic/xlr/platform-flash.c @@ -0,0 +1,220 @@ +/* + * Copyright 2011, Netlogic Microsystems. + * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/resource.h> +#include <linux/spi/flash.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/physmap.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/xlr/iomap.h> +#include <asm/netlogic/xlr/flash.h> +#include <asm/netlogic/xlr/bridge.h> +#include <asm/netlogic/xlr/gpio.h> +#include <asm/netlogic/xlr/xlr.h> + +/* + * Default NOR partition layout + */ +static struct mtd_partition xlr_nor_parts[] = { + { + .name = "User FS", + .offset = 0x800000, + .size = MTDPART_SIZ_FULL, + } +}; + +/* + * Default NAND partition layout + */ +static struct mtd_partition xlr_nand_parts[] = { + { + .name = "Root Filesystem", + .offset = 64 * 64 * 2048, + .size = 432 * 64 * 2048, + }, + { + .name = "Home Filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +/* Use PHYSMAP flash for NOR */ +struct physmap_flash_data xlr_nor_data = { + .width = 2, + .parts = xlr_nor_parts, + .nr_parts = ARRAY_SIZE(xlr_nor_parts), +}; + +static struct resource xlr_nor_res[] = { + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device xlr_nor_dev = { + .name = "physmap-flash", + .dev = { + .platform_data = &xlr_nor_data, + }, + .num_resources = ARRAY_SIZE(xlr_nor_res), + .resource = xlr_nor_res, +}; + +const char *xlr_part_probes[] = { "cmdlinepart", NULL }; + +/* + * Use "gen_nand" driver for NAND flash + * + * There seems to be no way to store a private pointer containing + * platform specific info in gen_nand drivier. We will use a global + * struct for now, since we currently have only one NAND chip per board. + */ +struct xlr_nand_flash_priv { + int cs; + uint64_t flash_mmio; +}; + +static struct xlr_nand_flash_priv nand_priv; + +static void xlr_nand_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + if (ctrl & NAND_CLE) + nlm_write_reg(nand_priv.flash_mmio, + FLASH_NAND_CLE(nand_priv.cs), cmd); + else if (ctrl & NAND_ALE) + nlm_write_reg(nand_priv.flash_mmio, + FLASH_NAND_ALE(nand_priv.cs), cmd); +} + +struct platform_nand_data xlr_nand_data = { + .chip = { + .nr_chips = 1, + .nr_partitions = ARRAY_SIZE(xlr_nand_parts), + .chip_delay = 50, + .partitions = xlr_nand_parts, + .part_probe_types = xlr_part_probes, + }, + .ctrl = { + .cmd_ctrl = xlr_nand_ctrl, + }, +}; + +static struct resource xlr_nand_res[] = { + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device xlr_nand_dev = { + .name = "gen_nand", + .id = -1, + .num_resources = ARRAY_SIZE(xlr_nand_res), + .resource = xlr_nand_res, + .dev = { + .platform_data = &xlr_nand_data, + } +}; + +/* + * XLR/XLS supports upto 8 devices on its FLASH interface. The value in + * FLASH_BAR (on the MEM/IO bridge) gives the base for mapping all the + * flash devices. + * Under this, each flash device has an offset and size given by the + * CSBASE_ADDR and CSBASE_MASK registers for the device. + * + * The CSBASE_ registers are expected to be setup by the bootloader. + */ +static void setup_flash_resource(uint64_t flash_mmio, + uint64_t flash_map_base, int cs, struct resource *res) +{ + u32 base, mask; + + base = nlm_read_reg(flash_mmio, FLASH_CSBASE_ADDR(cs)); + mask = nlm_read_reg(flash_mmio, FLASH_CSADDR_MASK(cs)); + + res->start = flash_map_base + ((unsigned long)base << 16); + res->end = res->start + (mask + 1) * 64 * 1024; +} + +static int __init xlr_flash_init(void) +{ + uint64_t gpio_mmio, flash_mmio, flash_map_base; + u32 gpio_resetcfg, flash_bar; + int cs, boot_nand, boot_nor; + + /* Flash address bits 39:24 is in bridge flash BAR */ + flash_bar = nlm_read_reg(nlm_io_base, BRIDGE_FLASH_BAR); + flash_map_base = (flash_bar & 0xffff0000) << 8; + + gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); + flash_mmio = nlm_mmio_base(NETLOGIC_IO_FLASH_OFFSET); + + /* Get the chip reset config */ + gpio_resetcfg = nlm_read_reg(gpio_mmio, GPIO_PWRON_RESET_CFG_REG); + + /* Check for boot flash type */ + boot_nor = boot_nand = 0; + if (nlm_chip_is_xls()) { + /* On XLS, check boot from NAND bit (GPIO reset reg bit 16) */ + if (gpio_resetcfg & (1 << 16)) + boot_nand = 1; + + /* check boot from PCMCIA, (GPIO reset reg bit 15 */ + if ((gpio_resetcfg & (1 << 15)) == 0) + boot_nor = 1; /* not set, booted from NOR */ + } else { /* XLR */ + /* check boot from PCMCIA (bit 16 in GPIO reset on XLR) */ + if ((gpio_resetcfg & (1 << 16)) == 0) + boot_nor = 1; /* not set, booted from NOR */ + } + + /* boot flash at chip select 0 */ + cs = 0; + + if (boot_nand) { + nand_priv.cs = cs; + nand_priv.flash_mmio = flash_mmio; + setup_flash_resource(flash_mmio, flash_map_base, cs, + xlr_nand_res); + + /* Initialize NAND flash at CS 0 */ + nlm_write_reg(flash_mmio, FLASH_CSDEV_PARM(cs), + FLASH_NAND_CSDEV_PARAM); + nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMA(cs), + FLASH_NAND_CSTIME_PARAMA); + nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMB(cs), + FLASH_NAND_CSTIME_PARAMB); + + pr_info("ChipSelect %d: NAND Flash %pR\n", cs, xlr_nand_res); + return platform_device_register(&xlr_nand_dev); + } + + if (boot_nor) { + setup_flash_resource(flash_mmio, flash_map_base, cs, + xlr_nor_res); + pr_info("ChipSelect %d: NOR Flash %pR\n", cs, xlr_nor_res); + return platform_device_register(&xlr_nor_dev); + } + return 0; +} + +arch_initcall(xlr_flash_init); diff --git a/arch/mips/netlogic/xlr/platform.c b/arch/mips/netlogic/xlr/platform.c index eab64b45dff..71b44d82621 100644 --- a/arch/mips/netlogic/xlr/platform.c +++ b/arch/mips/netlogic/xlr/platform.c @@ -14,6 +14,7 @@ #include <linux/resource.h> #include <linux/serial_8250.h> #include <linux/serial_reg.h> +#include <linux/i2c.h> #include <asm/netlogic/haldefs.h> #include <asm/netlogic/xlr/iomap.h> @@ -97,3 +98,142 @@ static int __init nlm_uart_init(void) } arch_initcall(nlm_uart_init); + +#ifdef CONFIG_USB +/* Platform USB devices, only on XLS chips */ +static u64 xls_usb_dmamask = ~(u32)0; +#define USB_PLATFORM_DEV(n, i, irq) \ + { \ + .name = n, \ + .id = i, \ + .num_resources = 2, \ + .dev = { \ + .dma_mask = &xls_usb_dmamask, \ + .coherent_dma_mask = 0xffffffff, \ + }, \ + .resource = (struct resource[]) { \ + { \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = irq, \ + .end = irq, \ + .flags = IORESOURCE_IRQ, \ + }, \ + }, \ + } + +static struct platform_device xls_usb_ehci_device = + USB_PLATFORM_DEV("ehci-xls", 0, PIC_USB_IRQ); +static struct platform_device xls_usb_ohci_device_0 = + USB_PLATFORM_DEV("ohci-xls-0", 1, PIC_USB_IRQ); +static struct platform_device xls_usb_ohci_device_1 = + USB_PLATFORM_DEV("ohci-xls-1", 2, PIC_USB_IRQ); + +static struct platform_device *xls_platform_devices[] = { + &xls_usb_ehci_device, + &xls_usb_ohci_device_0, + &xls_usb_ohci_device_1, +}; + +int xls_platform_usb_init(void) +{ + uint64_t usb_mmio, gpio_mmio; + unsigned long memres; + uint32_t val; + + if (!nlm_chip_is_xls()) + return 0; + + gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); + usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET); + + /* Clear Rogue Phy INTs */ + nlm_write_reg(usb_mmio, 49, 0x10000000); + /* Enable all interrupts */ + nlm_write_reg(usb_mmio, 50, 0x1f000000); + + /* Enable ports */ + nlm_write_reg(usb_mmio, 1, 0x07000500); + + val = nlm_read_reg(gpio_mmio, 21); + if (((val >> 22) & 0x01) == 0) { + pr_info("Detected USB Device mode - Not supported!\n"); + nlm_write_reg(usb_mmio, 0, 0x01000000); + return 0; + } + + pr_info("Detected USB Host mode - Adding XLS USB devices.\n"); + /* Clear reset, host mode */ + nlm_write_reg(usb_mmio, 0, 0x02000000); + + /* Memory resource for various XLS usb ports */ + usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET); + memres = CPHYSADDR((unsigned long)usb_mmio); + xls_usb_ehci_device.resource[0].start = memres; + xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1; + + memres += 0x400; + xls_usb_ohci_device_0.resource[0].start = memres; + xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1; + + memres += 0x400; + xls_usb_ohci_device_1.resource[0].start = memres; + xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1; + + return platform_add_devices(xls_platform_devices, + ARRAY_SIZE(xls_platform_devices)); +} + +arch_initcall(xls_platform_usb_init); +#endif + +#ifdef CONFIG_I2C +static struct i2c_board_info nlm_i2c_board_info1[] __initdata = { + /* All XLR boards have this RTC and Max6657 Temp Chip */ + [0] = { + .type = "ds1374", + .addr = 0x68 + }, + [1] = { + .type = "lm90", + .addr = 0x4c + }, +}; + +static struct resource i2c_resources[] = { + [0] = { + .start = 0, /* filled at init */ + .end = 0, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device nlm_xlr_i2c_1 = { + .name = "xlr-i2cbus", + .id = 1, + .num_resources = 1, + .resource = i2c_resources, +}; + +static int __init nlm_i2c_init(void) +{ + int err = 0; + unsigned int offset; + + /* I2C bus 0 does not have any useful devices, configure only bus 1 */ + offset = NETLOGIC_IO_I2C_1_OFFSET; + nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset)); + nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff; + + platform_device_register(&nlm_xlr_i2c_1); + + err = i2c_register_board_info(1, nlm_i2c_board_info1, + ARRAY_SIZE(nlm_i2c_board_info1)); + if (err < 0) + pr_err("nlm-i2c: cannot register board I2C devices\n"); + return err; +} + +arch_initcall(nlm_i2c_init); +#endif diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c index c9d066dedc4..81b1d311834 100644 --- a/arch/mips/netlogic/xlr/setup.c +++ b/arch/mips/netlogic/xlr/setup.c @@ -85,7 +85,7 @@ static void nlm_linux_exit(void) gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */ - nlm_write_reg(gpiobase, NETLOGIC_GPIO_SWRESET_REG, 1); + nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1); for ( ; ; ) cpu_wait(); } diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c index b6e378211a2..f80480a5a03 100644 --- a/arch/mips/oprofile/common.c +++ b/arch/mips/oprofile/common.c @@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_34K: case CPU_1004K: case CPU_74K: + case CPU_LOONGSON1: case CPU_SB1: case CPU_SB1A: case CPU_R10000: diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index 4d80a856048..28ea1a4cc57 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c @@ -339,12 +339,6 @@ static int __init mipsxx_init(void) break; case CPU_1004K: -#if 0 - /* FIXME: report as 34K for now */ - op_model_mipsxx_ops.cpu_type = "mips/1004K"; - break; -#endif - case CPU_34K: op_model_mipsxx_ops.cpu_type = "mips/34K"; break; @@ -374,6 +368,10 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/sb1"; break; + case CPU_LOONGSON1: + op_model_mipsxx_ops.cpu_type = "mips/loongson1"; + break; + default: printk(KERN_ERR "Profiling unsupported for this CPU\n"); diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c703f43a991..e13a71cbc3c 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o obj-$(CONFIG_CPU_XLR) += pci-xlr.o +obj-$(CONFIG_CPU_XLP) += pci-xlp.o ifdef CONFIG_PCI_MSI obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index 9553b14002d..3e7ce65d776 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -37,7 +37,7 @@ #define VIA_COBALT_BRD_ID_REG 0x94 #define VIA_COBALT_BRD_REG_to_ID(reg) ((unsigned char)(reg) >> 4) -static void qube_raq_galileo_early_fixup(struct pci_dev *dev) +static void __devinit qube_raq_galileo_early_fixup(struct pci_dev *dev) { if (dev->devfn == PCI_DEVFN(0, 0) && (dev->class >> 8) == PCI_CLASS_MEMORY_OTHER) { @@ -51,7 +51,7 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev) DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, qube_raq_galileo_early_fixup); -static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) +static void __devinit qube_raq_via_bmIDE_fixup(struct pci_dev *dev) { unsigned short cfgword; unsigned char lt; @@ -74,7 +74,7 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, qube_raq_via_bmIDE_fixup); -static void qube_raq_galileo_fixup(struct pci_dev *dev) +static void __devinit qube_raq_galileo_fixup(struct pci_dev *dev) { if (dev->devfn != PCI_DEVFN(0, 0)) return; @@ -129,7 +129,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, int cobalt_board_id; -static void qube_raq_via_board_id_fixup(struct pci_dev *dev) +static void __devinit qube_raq_via_board_id_fixup(struct pci_dev *dev) { u8 id; int retval; diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c index 70073c98ed3..819622f93e9 100644 --- a/arch/mips/pci/fixup-malta.c +++ b/arch/mips/pci/fixup-malta.c @@ -101,3 +101,17 @@ static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, malta_piix_func1_fixup); + +/* Enable PCI 2.1 compatibility in PIIX4 */ +static void __devinit quirk_dlcsetup(struct pci_dev *dev) +{ + u8 odlc, ndlc; + + (void) pci_read_config_byte(dev, 0x82, &odlc); + /* Enable passive releases and delayed transaction */ + ndlc = odlc | 7; + (void) pci_write_config_byte(dev, 0x82, ndlc); +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, + quirk_dlcsetup); diff --git a/arch/mips/pci/fixup-rc32434.c b/arch/mips/pci/fixup-rc32434.c index 3d86823d03a..76bb1be99d4 100644 --- a/arch/mips/pci/fixup-rc32434.c +++ b/arch/mips/pci/fixup-rc32434.c @@ -47,7 +47,7 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) return irq + GROUP4_IRQ_BASE + 4; } -static void rc32434_pci_early_fixup(struct pci_dev *dev) +static void __devinit rc32434_pci_early_fixup(struct pci_dev *dev) { if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) { /* disable prefetched memory range */ diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c index 822ae179bc5..65c7bd10048 100644 --- a/arch/mips/pci/ops-bcm63xx.c +++ b/arch/mips/pci/ops-bcm63xx.c @@ -411,7 +411,7 @@ struct pci_ops bcm63xx_cb_ops = { * only one IO window, so it cannot be shared by PCI and cardbus, use * fixup to choose and detect unhandled configuration */ -static void bcm63xx_fixup(struct pci_dev *dev) +static void __devinit bcm63xx_fixup(struct pci_dev *dev) { static int io_window = -1; int i, found, new_io_window; @@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev *dev) DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup); #endif + +static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn) +{ + switch (bus->number) { + case PCIE_BUS_BRIDGE: + return (PCI_SLOT(devfn) == 0); + case PCIE_BUS_DEVICE: + if (PCI_SLOT(devfn) == 0) + return bcm_pcie_readl(PCIE_DLSTATUS_REG) + & DLSTATUS_PHYLINKUP; + default: + return false; + } +} + +static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + u32 data; + u32 reg = where & ~3; + + if (!bcm63xx_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + data = bcm_pcie_readl(reg); + + *val = postprocess_read(data, where, size); + + return PCIBIOS_SUCCESSFUL; + +} + +static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data; + u32 reg = where & ~3; + + if (!bcm63xx_pcie_can_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (bus->number == PCIE_BUS_DEVICE) + reg += PCIE_DEVICE_OFFSET; + + + data = bcm_pcie_readl(reg); + + data = preprocess_write(data, val, where, size); + bcm_pcie_writel(data, reg); + + return PCIBIOS_SUCCESSFUL; +} + + +struct pci_ops bcm63xx_pcie_ops = { + .read = bcm63xx_pcie_read, + .write = bcm63xx_pcie_write +}; diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index 39eb7c417e2..8a48139d219 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -10,6 +10,7 @@ #include <linux/pci.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/delay.h> #include <asm/bootinfo.h> #include "pci-bcm63xx.h" @@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_controller = { }; #endif +static struct resource bcm_pcie_mem_resource = { + .name = "bcm63xx PCIe memory space", + .start = BCM_PCIE_MEM_BASE_PA, + .end = BCM_PCIE_MEM_END_PA, + .flags = IORESOURCE_MEM, +}; + +static struct resource bcm_pcie_io_resource = { + .name = "bcm63xx PCIe IO space", + .start = 0, + .end = 0, + .flags = 0, +}; + +struct pci_controller bcm63xx_pcie_controller = { + .pci_ops = &bcm63xx_pcie_ops, + .io_resource = &bcm_pcie_io_resource, + .mem_resource = &bcm_pcie_mem_resource, +}; + static u32 bcm63xx_int_cfg_readl(u32 reg) { u32 tmp; @@ -94,17 +115,99 @@ static void bcm63xx_int_cfg_writel(u32 val, u32 reg) void __iomem *pci_iospace_start; -static int __init bcm63xx_pci_init(void) +static void __init bcm63xx_reset_pcie(void) { - unsigned int mem_size; u32 val; - if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368()) - return -ENODEV; + /* enable clock */ + val = bcm_perf_readl(PERF_CKCTL_REG); + val |= CKCTL_6328_PCIE_EN; + bcm_perf_writel(val, PERF_CKCTL_REG); + + /* enable SERDES */ + val = bcm_misc_readl(MISC_SERDES_CTRL_REG); + val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN; + bcm_misc_writel(val, MISC_SERDES_CTRL_REG); + + /* reset the PCIe core */ + val = bcm_perf_readl(PERF_SOFTRESET_6328_REG); + + val &= ~SOFTRESET_6328_PCIE_MASK; + val &= ~SOFTRESET_6328_PCIE_CORE_MASK; + val &= ~SOFTRESET_6328_PCIE_HARD_MASK; + val &= ~SOFTRESET_6328_PCIE_EXT_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG); + mdelay(10); + + val |= SOFTRESET_6328_PCIE_MASK; + val |= SOFTRESET_6328_PCIE_CORE_MASK; + val |= SOFTRESET_6328_PCIE_HARD_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG); + mdelay(10); + + val |= SOFTRESET_6328_PCIE_EXT_MASK; + bcm_perf_writel(val, PERF_SOFTRESET_6328_REG); + mdelay(200); +} - if (!bcm63xx_pci_enabled) - return -ENODEV; +static int __init bcm63xx_register_pcie(void) +{ + u32 val; + bcm63xx_reset_pcie(); + + /* configure the PCIe bridge */ + val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG); + val |= OPT1_RD_BE_OPT_EN; + val |= OPT1_RD_REPLY_BE_FIX_EN; + val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN; + val |= OPT1_L1_INT_STATUS_MASK_POL; + bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG); + + /* setup the interrupts */ + val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG); + val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D; + bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG); + + val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG); + /* enable credit checking and error checking */ + val |= OPT2_TX_CREDIT_CHK_EN; + val |= OPT2_UBUS_UR_DECODE_DIS; + + /* set device bus/func for the pcie device */ + val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT); + val |= OPT2_CFG_TYPE1_BD_SEL; + bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG); + + /* setup class code as bridge */ + val = bcm_pcie_readl(PCIE_IDVAL3_REG); + val &= ~IDVAL3_CLASS_CODE_MASK; + val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT); + bcm_pcie_writel(val, PCIE_IDVAL3_REG); + + /* disable bar1 size */ + val = bcm_pcie_readl(PCIE_CONFIG2_REG); + val &= ~CONFIG2_BAR1_SIZE_MASK; + bcm_pcie_writel(val, PCIE_CONFIG2_REG); + + /* set bar0 to little endian */ + val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT; + val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT; + val |= BASEMASK_REMAP_EN; + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG); + + val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT; + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG); + + register_pci_controller(&bcm63xx_pcie_controller); + + return 0; +} + +static int __init bcm63xx_register_pci(void) +{ + unsigned int mem_size; + u32 val; /* * configuration access are done through IO space, remap 4 * first bytes to access it from CPU. @@ -221,4 +324,22 @@ static int __init bcm63xx_pci_init(void) return 0; } + +static int __init bcm63xx_pci_init(void) +{ + if (!bcm63xx_pci_enabled) + return -ENODEV; + + switch (bcm63xx_get_cpu_id()) { + case BCM6328_CPU_ID: + return bcm63xx_register_pcie(); + case BCM6348_CPU_ID: + case BCM6358_CPU_ID: + case BCM6368_CPU_ID: + return bcm63xx_register_pci(); + default: + return -ENODEV; + } +} + arch_initcall(bcm63xx_pci_init); diff --git a/arch/mips/pci/pci-bcm63xx.h b/arch/mips/pci/pci-bcm63xx.h index a6e594ef3d6..e6736d558ac 100644 --- a/arch/mips/pci/pci-bcm63xx.h +++ b/arch/mips/pci/pci-bcm63xx.h @@ -13,11 +13,16 @@ */ #define CARDBUS_PCI_IDSEL 0x8 + +#define PCIE_BUS_BRIDGE 0 +#define PCIE_BUS_DEVICE 1 + /* * defined in ops-bcm63xx.c */ extern struct pci_ops bcm63xx_pci_ops; extern struct pci_ops bcm63xx_cb_ops; +extern struct pci_ops bcm63xx_pcie_ops; /* * defined in pci-bcm63xx.c diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c new file mode 100644 index 00000000000..140557a2048 --- /dev/null +++ b/arch/mips/pci/pci-xlp.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/msi.h> +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/irqdesc.h> +#include <linux/console.h> + +#include <asm/io.h> + +#include <asm/netlogic/interrupt.h> +#include <asm/netlogic/haldefs.h> + +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/pic.h> +#include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pcibus.h> +#include <asm/netlogic/xlp-hal/bridge.h> + +static void *pci_config_base; + +#define pci_cfg_addr(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) + +/* PCI ops */ +static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn, + int where) +{ + u32 data; + u32 *cfgaddr; + + cfgaddr = (u32 *)(pci_config_base + + pci_cfg_addr(bus->number, devfn, where & ~3)); + data = *cfgaddr; + return data; +} + +static inline void pci_cfg_write_32bit(struct pci_bus *bus, unsigned int devfn, + int where, u32 data) +{ + u32 *cfgaddr; + + cfgaddr = (u32 *)(pci_config_base + + pci_cfg_addr(bus->number, devfn, where & ~3)); + *cfgaddr = data; +} + +static int nlm_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + u32 data; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + data = pci_cfg_read_32bit(bus, devfn, where); + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + + +static int nlm_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + data = pci_cfg_read_32bit(bus, devfn, where); + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else + data = val; + + pci_cfg_write_32bit(bus, devfn, where, data); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops nlm_pci_ops = { + .read = nlm_pcibios_read, + .write = nlm_pcibios_write +}; + +static struct resource nlm_pci_mem_resource = { + .name = "XLP PCI MEM", + .start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */ + .end = 0xdfffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource nlm_pci_io_resource = { + .name = "XLP IO MEM", + .start = 0x14000000UL, /* 64MB PCI IO @ 0x1000_0000 */ + .end = 0x17ffffffUL, + .flags = IORESOURCE_IO, +}; + +struct pci_controller nlm_pci_controller = { + .index = 0, + .pci_ops = &nlm_pci_ops, + .mem_resource = &nlm_pci_mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &nlm_pci_io_resource, + .io_offset = 0x00000000UL, +}; + +static int get_irq_vector(const struct pci_dev *dev) +{ + /* + * For XLP PCIe, there is an IRQ per Link, find out which + * link the device is on to assign interrupts + */ + if (dev->bus->self == NULL) + return 0; + + switch (dev->bus->self->devfn) { + case 0x8: + return PIC_PCIE_LINK_0_IRQ; + case 0x9: + return PIC_PCIE_LINK_1_IRQ; + case 0xa: + return PIC_PCIE_LINK_2_IRQ; + case 0xb: + return PIC_PCIE_LINK_3_IRQ; + } + WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn); + return 0; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return get_irq_vector(dev); +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +static int xlp_enable_pci_bswap(void) +{ + uint64_t pciebase, sysbase; + int node, i; + u32 reg; + + /* Chip-0 so node set to 0 */ + node = 0; + sysbase = nlm_get_bridge_regbase(node); + /* + * Enable byte swap in hardware. Program each link's PCIe SWAP regions + * from the link's address ranges. + */ + for (i = 0; i < 4; i++) { + pciebase = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, i)); + if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) + continue; + + reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_BASE0 + i); + nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_BASE, reg); + + reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_LIMIT0 + i); + nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_LIM, + reg | 0xfff); + + reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_BASE0 + i); + nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_BASE, reg); + + reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_LIMIT0 + i); + nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); + } + return 0; +} + +static int __init pcibios_init(void) +{ + /* Firmware assigns PCI resources */ + pci_set_flags(PCI_PROBE_ONLY); + pci_config_base = ioremap(XLP_DEFAULT_PCI_ECFG_BASE, 64 << 20); + + /* Extend IO port for memory mapped io */ + ioport_resource.start = 0; + ioport_resource.end = ~0; + + xlp_enable_pci_bswap(); + set_io_port_base(CKSEG1); + nlm_pci_controller.io_map_base = CKSEG1; + + register_pci_controller(&nlm_pci_controller); + pr_info("XLP PCIe Controller %pR%pR.\n", &nlm_pci_io_resource, + &nlm_pci_mem_resource); + + return 0; +} +arch_initcall(pcibios_init); diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 172af1cd586..18af021d289 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -375,7 +375,3 @@ static int __init pcibios_init(void) } arch_initcall(pcibios_init); - -struct pci_fixup pcibios_fixups[] = { - {0} -}; diff --git a/arch/mips/pnx833x/stb22x/board.c b/arch/mips/pnx833x/stb22x/board.c index 644eb7c3210..4b328ac4305 100644 --- a/arch/mips/pnx833x/stb22x/board.c +++ b/arch/mips/pnx833x/stb22x/board.c @@ -91,7 +91,7 @@ void __init pnx833x_board_setup(void) pnx833x_gpio_select_function_alt(32); pnx833x_gpio_select_function_alt(33); -#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) +#if IS_ENABLED(CONFIG_MTD_NAND_PLATFORM) /* Setup MIU for NAND access on CS0... * * (it seems that we must also configure CS1 for reliable operation, @@ -117,7 +117,7 @@ void __init pnx833x_board_setup(void) pnx833x_gpio_select_output(5); pnx833x_gpio_write(1, 5); -#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) +#elif IS_ENABLED(CONFIG_MTD_CFI) /* Set up MIU for 16-bit NOR access on CS0 and CS1... */ diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index 125db323ab1..4efd9185f29 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -304,7 +304,7 @@ static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev) smsc_fdc37m81x_config_end(); } -static void quirk_slc90e66_ide(struct pci_dev *dev) +static void __devinit quirk_slc90e66_ide(struct pci_dev *dev) { unsigned char dat; int regs[2] = {0x41, 0x43}; @@ -339,7 +339,7 @@ static void quirk_slc90e66_ide(struct pci_dev *dev) } #endif /* CONFIG_TOSHIBA_FPCIB0 */ -static void tc35815_fixup(struct pci_dev *dev) +static void __devinit tc35815_fixup(struct pci_dev *dev) { /* This device may have PM registers but not they are not suported. */ if (dev->pm_cap) { @@ -348,7 +348,7 @@ static void tc35815_fixup(struct pci_dev *dev) } } -static void final_fixup(struct pci_dev *dev) +static void __devinit final_fixup(struct pci_dev *dev) { unsigned char bist; diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index ae77a7916c0..560fe899175 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -632,7 +632,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, unsigned long size, const struct physmap_flash_data *pdata) { -#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +#if IS_ENABLED(CONFIG_MTD_PHYSMAP) struct resource res = { .start = addr, .end = addr + size - 1, @@ -670,8 +670,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, void __init txx9_ndfmc_init(unsigned long baseaddr, const struct txx9ndfmc_platform_data *pdata) { -#if defined(CONFIG_MTD_NAND_TXX9NDFMC) || \ - defined(CONFIG_MTD_NAND_TXX9NDFMC_MODULE) +#if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC) struct resource res = { .start = baseaddr, .end = baseaddr + 0x1000 - 1, @@ -687,7 +686,7 @@ void __init txx9_ndfmc_init(unsigned long baseaddr, #endif } -#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +#if IS_ENABLED(CONFIG_LEDS_GPIO) static DEFINE_SPINLOCK(txx9_iocled_lock); #define TXX9_IOCLED_MAXLEDS 8 @@ -810,7 +809,7 @@ void __init txx9_iocled_init(unsigned long baseaddr, void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq, const struct txx9dmac_platform_data *pdata) { -#if defined(CONFIG_TXX9_DMAC) || defined(CONFIG_TXX9_DMAC_MODULE) +#if IS_ENABLED(CONFIG_TXX9_DMAC) struct resource res[] = { { .start = baseaddr, @@ -866,8 +865,7 @@ void __init txx9_aclc_init(unsigned long baseaddr, int irq, unsigned int dma_chan_out, unsigned int dma_chan_in) { -#if defined(CONFIG_SND_SOC_TXX9ACLC) || \ - defined(CONFIG_SND_SOC_TXX9ACLC_MODULE) +#if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC) unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS; struct resource res[] = { { diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c index 6567895d1f5..5ff7a9584da 100644 --- a/arch/mips/txx9/generic/setup_tx4939.c +++ b/arch/mips/txx9/generic/setup_tx4939.c @@ -317,7 +317,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) } } -#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) +#if IS_ENABLED(CONFIG_TC35815) static u32 tx4939_get_eth_speed(struct net_device *dev) { struct ethtool_cmd cmd; diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c index 2ad8973ba13..e15641d9309 100644 --- a/arch/mips/txx9/rbtx4939/setup.c +++ b/arch/mips/txx9/rbtx4939/setup.c @@ -40,8 +40,7 @@ static void __init rbtx4939_time_init(void) tx4939_time_init(0); } -#if defined(__BIG_ENDIAN) && \ - (defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)) +#if defined(__BIG_ENDIAN) && IS_ENABLED(CONFIG_SMC91X) #define HAVE_RBTX4939_IOSWAB #define IS_CE1_ADDR(addr) \ ((((unsigned long)(addr) - IO_BASE) & 0xfff00000) == TXX9_CE(1)) @@ -187,7 +186,7 @@ static void __init rbtx4939_update_ioc_pen(void) #define RBTX4939_MAX_7SEGLEDS 8 -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#if IS_ENABLED(CONFIG_LEDS_CLASS) static u8 led_val[RBTX4939_MAX_7SEGLEDS]; struct rbtx4939_led_data { struct led_classdev cdev; @@ -263,7 +262,7 @@ static inline void rbtx4939_led_setup(void) static void __rbtx4939_7segled_putc(unsigned int pos, unsigned char val) { -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#if IS_ENABLED(CONFIG_LEDS_CLASS) unsigned long flags; local_irq_save(flags); /* bit7: reserved for LED class */ @@ -287,7 +286,7 @@ static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val) __rbtx4939_7segled_putc(pos, val); } -#if defined(CONFIG_MTD_RBTX4939) || defined(CONFIG_MTD_RBTX4939_MODULE) +#if IS_ENABLED(CONFIG_MTD_RBTX4939) /* special mapping for boot rom */ static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs) { @@ -463,7 +462,7 @@ static void __init rbtx4939_device_init(void) .flags = SMC91X_USE_16BIT, }; struct platform_device *pdev; -#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) +#if IS_ENABLED(CONFIG_TC35815) int i, j; unsigned char ethaddr[2][6]; u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; diff --git a/arch/mn10300/include/asm/ipc.h b/arch/mn10300/include/asm/ipc.h deleted file mode 100644 index a46e3d9c2a3..00000000000 --- a/arch/mn10300/include/asm/ipc.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ipc.h> diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild index 3f35c38d7b6..0922959663a 100644 --- a/arch/openrisc/include/asm/Kbuild +++ b/arch/openrisc/include/asm/Kbuild @@ -13,7 +13,6 @@ generic-y += cacheflush.h generic-y += checksum.h generic-y += cmpxchg.h generic-y += cmpxchg-local.h -generic-y += cpumask.h generic-y += cputime.h generic-y += current.h generic-y += device.h @@ -43,7 +42,6 @@ generic-y += percpu.h generic-y += poll.h generic-y += posix_types.h generic-y += resource.h -generic-y += rmap.h generic-y += scatterlist.h generic-y += sections.h generic-y += segment.h diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 62678e365ca..78160874809 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h @@ -27,7 +27,10 @@ extern void *dma_direct_alloc_coherent(struct device *dev, size_t size, extern void dma_direct_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs); - +extern int dma_direct_mmap_coherent(struct device *dev, + struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t handle, + size_t size, struct dma_attrs *attrs); #ifdef CONFIG_NOT_COHERENT_CACHE /* @@ -207,11 +210,8 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr) #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -extern int dma_mmap_coherent(struct device *, struct vm_area_struct *, - void *, dma_addr_t, size_t); #define ARCH_HAS_DMA_MMAP_COHERENT - static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index bcfdcd22c76..2d7bb8ced13 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c @@ -109,6 +109,7 @@ static u64 dma_iommu_get_required_mask(struct device *dev) struct dma_map_ops dma_iommu_ops = { .alloc = dma_iommu_alloc_coherent, .free = dma_iommu_free_coherent, + .mmap = dma_direct_mmap_coherent, .map_sg = dma_iommu_map_sg, .unmap_sg = dma_iommu_unmap_sg, .dma_supported = dma_iommu_dma_supported, diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index 4ab88dafb23..46943651da2 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -49,6 +49,7 @@ static u64 swiotlb_powerpc_get_required(struct device *dev) struct dma_map_ops swiotlb_dma_ops = { .alloc = dma_direct_alloc_coherent, .free = dma_direct_free_coherent, + .mmap = dma_direct_mmap_coherent, .map_sg = swiotlb_map_sg_attrs, .unmap_sg = swiotlb_unmap_sg_attrs, .dma_supported = swiotlb_dma_supported, diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 289be751cd7..355b9d84b0f 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c @@ -67,6 +67,24 @@ void dma_direct_free_coherent(struct device *dev, size_t size, #endif } +int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t handle, size_t size, + struct dma_attrs *attrs) +{ + unsigned long pfn; + +#ifdef CONFIG_NOT_COHERENT_CACHE + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr); +#else + pfn = page_to_pfn(virt_to_page(cpu_addr)); +#endif + return remap_pfn_range(vma, vma->vm_start, + pfn + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents, enum dma_data_direction direction, struct dma_attrs *attrs) @@ -156,6 +174,7 @@ static inline void dma_direct_sync_single(struct device *dev, struct dma_map_ops dma_direct_ops = { .alloc = dma_direct_alloc_coherent, .free = dma_direct_free_coherent, + .mmap = dma_direct_mmap_coherent, .map_sg = dma_direct_map_sg, .unmap_sg = dma_direct_unmap_sg, .dma_supported = dma_direct_dma_supported, @@ -219,20 +238,3 @@ static int __init dma_init(void) } fs_initcall(dma_init); -int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t handle, size_t size) -{ - unsigned long pfn; - -#ifdef CONFIG_NOT_COHERENT_CACHE - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr); -#else - pfn = page_to_pfn(virt_to_page(cpu_addr)); -#endif - return remap_pfn_range(vma, vma->vm_start, - pfn + vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); -} -EXPORT_SYMBOL_GPL(dma_mmap_coherent); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 3052a931f2b..02b32216bbc 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -611,6 +611,7 @@ static u64 vio_dma_get_required_mask(struct device *dev) struct dma_map_ops vio_dma_mapping_ops = { .alloc = vio_dma_iommu_alloc_coherent, .free = vio_dma_iommu_free_coherent, + .mmap = dma_direct_mmap_coherent, .map_sg = vio_dma_iommu_map_sg, .unmap_sg = vio_dma_iommu_unmap_sg, .map_page = vio_dma_iommu_map_page, diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index fb7c65ae8de..5bd71994452 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -16,7 +16,6 @@ generic-y += fb.h generic-y += fcntl.h generic-y += ioctl.h generic-y += ioctls.h -generic-y += ipc.h generic-y += ipcbuf.h generic-y += irq_regs.h generic-y += kdebug.h diff --git a/arch/xtensa/include/asm/cpumask.h b/arch/xtensa/include/asm/cpumask.h deleted file mode 100644 index ebeede397db..00000000000 --- a/arch/xtensa/include/asm/cpumask.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/cpumask.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_CPUMASK_H -#define _XTENSA_CPUMASK_H - -#include <asm-generic/cpumask.h> - -#endif /* _XTENSA_CPUMASK_H */ diff --git a/arch/xtensa/include/asm/rmap.h b/arch/xtensa/include/asm/rmap.h deleted file mode 100644 index 649588b7e9a..00000000000 --- a/arch/xtensa/include/asm/rmap.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/rmap.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_RMAP_H -#define _XTENSA_RMAP_H - -#include <asm-generic/rmap.h> - -#endif diff --git a/drivers/Kconfig b/drivers/Kconfig index bfc918633fd..805c432c943 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -148,4 +148,6 @@ source "drivers/iio/Kconfig" source "drivers/vme/Kconfig" +source "drivers/pwm/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 2ba29ffef2c..bd36f09f224 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -8,6 +8,7 @@ # GPIO must come after pinctrl as gpios may need to mux pins etc obj-y += pinctrl/ obj-y += gpio/ +obj-y += pwm/ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 45d8097ef4c..b728880ef10 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -132,6 +132,33 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } +/* Force to use vendor driver when the ACPI device is known to be + * buggy */ +static int video_detect_force_vendor(const struct dmi_system_id *d) +{ + acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; + return 0; +} + +static struct dmi_system_id video_detect_dmi_table[] = { + /* On Samsung X360, the BIOS will set a flag (VDRV) if generic + * ACPI backlight device is used. This flag will definitively break + * the backlight interface (even the vendor interface) untill next + * reboot. It's why we should prevent video.ko from being used here + * and we can't rely on a later call to acpi_video_unregister(). + */ + { + .callback = video_detect_force_vendor, + .ident = "X360", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "X360"), + DMI_MATCH(DMI_BOARD_NAME, "X360"), + }, + }, + { }, +}; + /* * Returns the video capabilities of a specific ACPI graphics device * @@ -164,6 +191,8 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle) * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; *} */ + + dmi_check_system(video_detect_dmi_table); } else { status = acpi_bus_get_device(graphics_handle, &tmp_dev); if (ACPI_FAILURE(status)) { @@ -182,8 +211,7 @@ long acpi_video_get_capabilities(acpi_handle graphics_handle) } EXPORT_SYMBOL(acpi_video_get_capabilities); -/* Returns true if video.ko can do backlight switching */ -int acpi_video_backlight_support(void) +static void acpi_video_caps_check(void) { /* * We must check whether the ACPI graphics device is physically plugged @@ -191,6 +219,34 @@ int acpi_video_backlight_support(void) */ if (!acpi_video_caps_checked) acpi_video_get_capabilities(NULL); +} + +/* Promote the vendor interface instead of the generic video module. + * This function allow DMI blacklists to be implemented by externals + * platform drivers instead of putting a big blacklist in video_detect.c + * After calling this function you will probably want to call + * acpi_video_unregister() to make sure the video module is not loaded + */ +void acpi_video_dmi_promote_vendor(void) +{ + acpi_video_caps_check(); + acpi_video_support |= ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; +} +EXPORT_SYMBOL(acpi_video_dmi_promote_vendor); + +/* To be called when a driver who previously promoted the vendor + * interface */ +void acpi_video_dmi_demote_vendor(void) +{ + acpi_video_caps_check(); + acpi_video_support &= ~ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; +} +EXPORT_SYMBOL(acpi_video_dmi_demote_vendor); + +/* Returns true if video.ko can do backlight switching */ +int acpi_video_backlight_support(void) +{ + acpi_video_caps_check(); /* First check for boot param -> highest prio */ if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index 6f3676f1559..3fbedc75e7c 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -10,6 +10,7 @@ #include <linux/dma-mapping.h> #include <linux/export.h> #include <linux/gfp.h> +#include <asm-generic/dma-coherent.h> /* * Managed DMA API @@ -217,4 +218,52 @@ void dmam_release_declared_memory(struct device *dev) } EXPORT_SYMBOL(dmam_release_declared_memory); +/* + * Create scatter-list for the already allocated DMA buffer. + */ +int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t handle, size_t size) +{ + struct page *page = virt_to_page(cpu_addr); + int ret; + + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + if (unlikely(ret)) + return ret; + + sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); + return 0; +} +EXPORT_SYMBOL(dma_common_get_sgtable); + #endif + +/* + * Create userspace mapping for the DMA-coherent memory. + */ +int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + int ret = -ENXIO; +#ifdef CONFIG_MMU + unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; + unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr)); + unsigned long off = vma->vm_pgoff; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) + return ret; + + if (off < count && user_count <= (count - off)) { + ret = remap_pfn_range(vma, vma->vm_start, + pfn + off, + user_count << PAGE_SHIFT, + vma->vm_page_prot); + } +#endif /* CONFIG_MMU */ + + return ret; +} +EXPORT_SYMBOL(dma_common_mmap); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 693187df760..c0bbeb47075 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -21,8 +21,6 @@ struct workqueue_struct *virtblk_wq; struct virtio_blk { - spinlock_t lock; - struct virtio_device *vdev; struct virtqueue *vq; @@ -65,7 +63,7 @@ static void blk_done(struct virtqueue *vq) unsigned int len; unsigned long flags; - spin_lock_irqsave(&vblk->lock, flags); + spin_lock_irqsave(vblk->disk->queue->queue_lock, flags); while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { int error; @@ -99,7 +97,7 @@ static void blk_done(struct virtqueue *vq) } /* In case queue is stopped waiting for more buffers. */ blk_start_queue(vblk->disk->queue); - spin_unlock_irqrestore(&vblk->lock, flags); + spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags); } static bool do_req(struct request_queue *q, struct virtio_blk *vblk, @@ -397,6 +395,83 @@ static int virtblk_name_format(char *prefix, int index, char *buf, int buflen) return 0; } +static int virtblk_get_cache_mode(struct virtio_device *vdev) +{ + u8 writeback; + int err; + + err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE, + offsetof(struct virtio_blk_config, wce), + &writeback); + if (err) + writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); + + return writeback; +} + +static void virtblk_update_cache_mode(struct virtio_device *vdev) +{ + u8 writeback = virtblk_get_cache_mode(vdev); + struct virtio_blk *vblk = vdev->priv; + + if (writeback) + blk_queue_flush(vblk->disk->queue, REQ_FLUSH); + else + blk_queue_flush(vblk->disk->queue, 0); + + revalidate_disk(vblk->disk); +} + +static const char *const virtblk_cache_types[] = { + "write through", "write back" +}; + +static ssize_t +virtblk_cache_type_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gendisk *disk = dev_to_disk(dev); + struct virtio_blk *vblk = disk->private_data; + struct virtio_device *vdev = vblk->vdev; + int i; + u8 writeback; + + BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE)); + for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; ) + if (sysfs_streq(buf, virtblk_cache_types[i])) + break; + + if (i < 0) + return -EINVAL; + + writeback = i; + vdev->config->set(vdev, + offsetof(struct virtio_blk_config, wce), + &writeback, sizeof(writeback)); + + virtblk_update_cache_mode(vdev); + return count; +} + +static ssize_t +virtblk_cache_type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gendisk *disk = dev_to_disk(dev); + struct virtio_blk *vblk = disk->private_data; + u8 writeback = virtblk_get_cache_mode(vblk->vdev); + + BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types)); + return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]); +} + +static const struct device_attribute dev_attr_cache_type_ro = + __ATTR(cache_type, S_IRUGO, + virtblk_cache_type_show, NULL); +static const struct device_attribute dev_attr_cache_type_rw = + __ATTR(cache_type, S_IRUGO|S_IWUSR, + virtblk_cache_type_show, virtblk_cache_type_store); + static int __devinit virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; @@ -431,7 +506,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) goto out_free_index; } - spin_lock_init(&vblk->lock); vblk->vdev = vdev; vblk->sg_elems = sg_elems; sg_init_table(vblk->sg, vblk->sg_elems); @@ -456,7 +530,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) goto out_mempool; } - q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); + q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL); if (!q) { err = -ENOMEM; goto out_put_disk; @@ -474,8 +548,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) vblk->index = index; /* configure queue flush support */ - if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) - blk_queue_flush(q, REQ_FLUSH); + virtblk_update_cache_mode(vdev); /* If disk is read-only in the host, the guest should obey */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) @@ -553,6 +626,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) if (err) goto out_del_disk; + if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE)) + err = device_create_file(disk_to_dev(vblk->disk), + &dev_attr_cache_type_rw); + else + err = device_create_file(disk_to_dev(vblk->disk), + &dev_attr_cache_type_ro); + if (err) + goto out_del_disk; return 0; out_del_disk: @@ -576,30 +657,20 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; int index = vblk->index; - struct virtblk_req *vbr; - unsigned long flags; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); vblk->config_enable = false; mutex_unlock(&vblk->config_lock); + del_gendisk(vblk->disk); + blk_cleanup_queue(vblk->disk->queue); + /* Stop all the virtqueues. */ vdev->config->reset(vdev); flush_work(&vblk->config_work); - del_gendisk(vblk->disk); - - /* Abort requests dispatched to driver. */ - spin_lock_irqsave(&vblk->lock, flags); - while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) { - __blk_end_request_all(vbr->req, -EIO); - mempool_free(vbr, vblk->pool); - } - spin_unlock_irqrestore(&vblk->lock, flags); - - blk_cleanup_queue(vblk->disk->queue); put_disk(vblk->disk); mempool_destroy(vblk->pool); vdev->config->del_vqs(vdev); @@ -655,7 +726,7 @@ static const struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI, - VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY + VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE }; /* diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index b01d6732824..7c0d391996b 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -73,6 +73,20 @@ config HW_RANDOM_ATMEL If unsure, say Y. +config HW_RANDOM_BCM63XX + tristate "Broadcom BCM63xx Random Number Generator support" + depends on HW_RANDOM && BCM63XX + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on the Broadcom BCM63xx SoCs. + + To compile this driver as a module, choose M here: the + module will be called bcm63xx-rng + + If unusure, say Y. + + config HW_RANDOM_GEODE tristate "AMD Geode HW Random Number Generator support" depends on HW_RANDOM && X86_32 && PCI diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 8d6d173b65e..39a757ca15b 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o +obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o n2-rng-y := n2-drv.o n2-asm.o diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c new file mode 100644 index 00000000000..aec6a4277ca --- /dev/null +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -0,0 +1,175 @@ +/* + * Broadcom BCM63xx Random Number Generator support + * + * Copyright (C) 2011, Florian Fainelli <florian@openwrt.org> + * Copyright (C) 2009, Broadcom Corporation + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> + +#include <bcm63xx_io.h> +#include <bcm63xx_regs.h> + +struct bcm63xx_rng_priv { + struct clk *clk; + void __iomem *regs; +}; + +#define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv) + +static int bcm63xx_rng_init(struct hwrng *rng) +{ + struct bcm63xx_rng_priv *priv = to_rng_priv(rng); + u32 val; + + val = bcm_readl(priv->regs + RNG_CTRL); + val |= RNG_EN; + bcm_writel(val, priv->regs + RNG_CTRL); + + return 0; +} + +static void bcm63xx_rng_cleanup(struct hwrng *rng) +{ + struct bcm63xx_rng_priv *priv = to_rng_priv(rng); + u32 val; + + val = bcm_readl(priv->regs + RNG_CTRL); + val &= ~RNG_EN; + bcm_writel(val, priv->regs + RNG_CTRL); +} + +static int bcm63xx_rng_data_present(struct hwrng *rng, int wait) +{ + struct bcm63xx_rng_priv *priv = to_rng_priv(rng); + + return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK; +} + +static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) +{ + struct bcm63xx_rng_priv *priv = to_rng_priv(rng); + + *data = bcm_readl(priv->regs + RNG_DATA); + + return 4; +} + +static int __devinit bcm63xx_rng_probe(struct platform_device *pdev) +{ + struct resource *r; + struct clk *clk; + int ret; + struct bcm63xx_rng_priv *priv; + struct hwrng *rng; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no iomem resource\n"); + ret = -ENXIO; + goto out; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(&pdev->dev, "no memory for private structure\n"); + ret = -ENOMEM; + goto out; + } + + rng = kzalloc(sizeof(*rng), GFP_KERNEL); + if (!rng) { + dev_err(&pdev->dev, "no memory for rng structure\n"); + ret = -ENOMEM; + goto out_free_priv; + } + + platform_set_drvdata(pdev, rng); + rng->priv = (unsigned long)priv; + rng->name = pdev->name; + rng->init = bcm63xx_rng_init; + rng->cleanup = bcm63xx_rng_cleanup; + rng->data_present = bcm63xx_rng_data_present; + rng->data_read = bcm63xx_rng_data_read; + + clk = clk_get(&pdev->dev, "ipsec"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "no clock for device\n"); + ret = PTR_ERR(clk); + goto out_free_rng; + } + + priv->clk = clk; + + if (!devm_request_mem_region(&pdev->dev, r->start, + resource_size(r), pdev->name)) { + dev_err(&pdev->dev, "request mem failed"); + ret = -ENOMEM; + goto out_free_rng; + } + + priv->regs = devm_ioremap_nocache(&pdev->dev, r->start, + resource_size(r)); + if (!priv->regs) { + dev_err(&pdev->dev, "ioremap failed"); + ret = -ENOMEM; + goto out_free_rng; + } + + clk_enable(clk); + + ret = hwrng_register(rng); + if (ret) { + dev_err(&pdev->dev, "failed to register rng device\n"); + goto out_clk_disable; + } + + dev_info(&pdev->dev, "registered RNG driver\n"); + + return 0; + +out_clk_disable: + clk_disable(clk); +out_free_rng: + platform_set_drvdata(pdev, NULL); + kfree(rng); +out_free_priv: + kfree(priv); +out: + return ret; +} + +static int __devexit bcm63xx_rng_remove(struct platform_device *pdev) +{ + struct hwrng *rng = platform_get_drvdata(pdev); + struct bcm63xx_rng_priv *priv = to_rng_priv(rng); + + hwrng_unregister(rng); + clk_disable(priv->clk); + kfree(priv); + kfree(rng); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver bcm63xx_rng_driver = { + .probe = bcm63xx_rng_probe, + .remove = __devexit_p(bcm63xx_rng_remove), + .driver = { + .name = "bcm63xx-rng", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(bcm63xx_rng_driver); + +MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); +MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 723725bbb96..5708299507d 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -55,6 +55,7 @@ static void register_buffer(u8 *buf, size_t size) static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) { + int ret; if (!busy) { busy = true; @@ -65,7 +66,9 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) if (!wait) return 0; - wait_for_completion(&have_data); + ret = wait_for_completion_killable(&have_data); + if (ret < 0) + return ret; busy = false; @@ -85,7 +88,7 @@ static struct hwrng virtio_hwrng = { .read = virtio_read, }; -static int virtrng_probe(struct virtio_device *vdev) +static int probe_common(struct virtio_device *vdev) { int err; @@ -103,13 +106,37 @@ static int virtrng_probe(struct virtio_device *vdev) return 0; } -static void __devexit virtrng_remove(struct virtio_device *vdev) +static void remove_common(struct virtio_device *vdev) { vdev->config->reset(vdev); + busy = false; hwrng_unregister(&virtio_hwrng); vdev->config->del_vqs(vdev); } +static int virtrng_probe(struct virtio_device *vdev) +{ + return probe_common(vdev); +} + +static void __devexit virtrng_remove(struct virtio_device *vdev) +{ + remove_common(vdev); +} + +#ifdef CONFIG_PM +static int virtrng_freeze(struct virtio_device *vdev) +{ + remove_common(vdev); + return 0; +} + +static int virtrng_restore(struct virtio_device *vdev) +{ + return probe_common(vdev); +} +#endif + static struct virtio_device_id id_table[] = { { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, { 0 }, @@ -121,6 +148,10 @@ static struct virtio_driver virtio_rng_driver = { .id_table = id_table, .probe = virtrng_probe, .remove = __devexit_p(virtrng_remove), +#ifdef CONFIG_PM + .freeze = virtrng_freeze, + .restore = virtrng_restore, +#endif }; static int __init init(void) diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 8b78750f1ef..845f97fd183 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, vdata->flags = flags; vdata->type = type; spin_lock_init(&vdata->lock); - vdata->refcnt = ATOMIC_INIT(1); + atomic_set(&vdata->refcnt, 1); vma->vm_private_data = vdata; vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); diff --git a/drivers/cpufreq/exynos5250-cpufreq.c b/drivers/cpufreq/exynos5250-cpufreq.c index a88331644eb..e64c253cb16 100644 --- a/drivers/cpufreq/exynos5250-cpufreq.c +++ b/drivers/cpufreq/exynos5250-cpufreq.c @@ -65,20 +65,20 @@ static unsigned int clkdiv_cpu0_5250[CPUFREQ_LEVEL_END][8] = { * Clock divider value for following * { ARM, CPUD, ACP, PERIPH, ATB, PCLK_DBG, APLL, ARM2 } */ - { 0, 3, 7, 7, 6, 1, 3, 0 }, /* 1700 MHz - N/A */ - { 0, 3, 7, 7, 6, 1, 3, 0 }, /* 1600 MHz - N/A */ - { 0, 3, 7, 7, 5, 1, 3, 0 }, /* 1500 MHz - N/A */ - { 0, 3, 7, 7, 6, 1, 3, 0 }, /* 1400 MHz */ - { 0, 3, 7, 7, 6, 1, 3, 0 }, /* 1300 MHz */ - { 0, 3, 7, 7, 5, 1, 3, 0 }, /* 1200 MHz */ - { 0, 2, 7, 7, 5, 1, 2, 0 }, /* 1100 MHz */ - { 0, 2, 7, 7, 4, 1, 2, 0 }, /* 1000 MHz */ - { 0, 2, 7, 7, 4, 1, 2, 0 }, /* 900 MHz */ - { 0, 2, 7, 7, 3, 1, 1, 0 }, /* 800 MHz */ + { 0, 3, 7, 7, 7, 3, 5, 0 }, /* 1700 MHz */ + { 0, 3, 7, 7, 7, 1, 4, 0 }, /* 1600 MHz */ + { 0, 2, 7, 7, 7, 1, 4, 0 }, /* 1500 MHz */ + { 0, 2, 7, 7, 6, 1, 4, 0 }, /* 1400 MHz */ + { 0, 2, 7, 7, 6, 1, 3, 0 }, /* 1300 MHz */ + { 0, 2, 7, 7, 5, 1, 3, 0 }, /* 1200 MHz */ + { 0, 3, 7, 7, 5, 1, 3, 0 }, /* 1100 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 1000 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 900 MHz */ + { 0, 1, 7, 7, 4, 1, 2, 0 }, /* 800 MHz */ { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 700 MHz */ - { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 600 MHz */ + { 0, 1, 7, 7, 3, 1, 1, 0 }, /* 600 MHz */ { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 500 MHz */ - { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 400 MHz */ + { 0, 1, 7, 7, 2, 1, 1, 0 }, /* 400 MHz */ { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 300 MHz */ { 0, 1, 7, 7, 1, 1, 1, 0 }, /* 200 MHz */ }; @@ -87,9 +87,9 @@ static unsigned int clkdiv_cpu1_5250[CPUFREQ_LEVEL_END][2] = { /* Clock divider value for following * { COPY, HPM } */ - { 0, 2 }, /* 1700 MHz - N/A */ - { 0, 2 }, /* 1600 MHz - N/A */ - { 0, 2 }, /* 1500 MHz - N/A */ + { 0, 2 }, /* 1700 MHz */ + { 0, 2 }, /* 1600 MHz */ + { 0, 2 }, /* 1500 MHz */ { 0, 2 }, /* 1400 MHz */ { 0, 2 }, /* 1300 MHz */ { 0, 2 }, /* 1200 MHz */ @@ -106,10 +106,10 @@ static unsigned int clkdiv_cpu1_5250[CPUFREQ_LEVEL_END][2] = { }; static unsigned int exynos5_apll_pms_table[CPUFREQ_LEVEL_END] = { - (0), /* 1700 MHz - N/A */ - (0), /* 1600 MHz - N/A */ - (0), /* 1500 MHz - N/A */ - (0), /* 1400 MHz */ + ((425 << 16) | (6 << 8) | 0), /* 1700 MHz */ + ((200 << 16) | (3 << 8) | 0), /* 1600 MHz */ + ((250 << 16) | (4 << 8) | 0), /* 1500 MHz */ + ((175 << 16) | (3 << 8) | 0), /* 1400 MHz */ ((325 << 16) | (6 << 8) | 0), /* 1300 MHz */ ((200 << 16) | (4 << 8) | 0), /* 1200 MHz */ ((275 << 16) | (6 << 8) | 0), /* 1100 MHz */ @@ -126,9 +126,10 @@ static unsigned int exynos5_apll_pms_table[CPUFREQ_LEVEL_END] = { /* ASV group voltage table */ static const unsigned int asv_voltage_5250[CPUFREQ_LEVEL_END] = { - 0, 0, 0, 0, 0, 0, 0, /* 1700 MHz ~ 1100 MHz Not supported */ - 1175000, 1125000, 1075000, 1050000, 1000000, - 950000, 925000, 925000, 900000 + 1300000, 1250000, 1225000, 1200000, 1150000, + 1125000, 1100000, 1075000, 1050000, 1025000, + 1012500, 1000000, 975000, 950000, 937500, + 925000 }; static void set_clkdiv(unsigned int div_index) @@ -248,15 +249,7 @@ static void __init set_volt_table(void) { unsigned int i; - exynos5250_freq_table[L0].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L1].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L2].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L3].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L4].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L5].frequency = CPUFREQ_ENTRY_INVALID; - exynos5250_freq_table[L6].frequency = CPUFREQ_ENTRY_INVALID; - - max_support_idx = L7; + max_support_idx = L0; for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++) exynos5250_volt_table[i] = asv_voltage_5250[i]; diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index fdffa1beca1..409b92b8d34 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -7,7 +7,7 @@ menuconfig EDAC bool "EDAC (Error Detection And Correction) reporting" depends on HAS_IOMEM - depends on X86 || PPC || TILE + depends on X86 || PPC || TILE || ARM help EDAC is designed to report errors in the core system. These are low-level errors that are reported in the CPU or @@ -31,6 +31,14 @@ if EDAC comment "Reporting subsystems" +config EDAC_LEGACY_SYSFS + bool "EDAC legacy sysfs" + default y + help + Enable the compatibility sysfs nodes. + Use 'Y' if your edac utilities aren't ported to work with the newer + structures. + config EDAC_DEBUG bool "Debugging" help @@ -294,4 +302,18 @@ config EDAC_TILE Support for error detection and correction on the Tilera memory controller. +config EDAC_HIGHBANK_MC + tristate "Highbank Memory Controller" + depends on EDAC_MM_EDAC && ARCH_HIGHBANK + help + Support for error detection and correction on the + Calxeda Highbank memory controller. + +config EDAC_HIGHBANK_L2 + tristate "Highbank L2 Cache" + depends on EDAC_MM_EDAC && ARCH_HIGHBANK + help + Support for error detection and correction on the + Calxeda Highbank memory controller. + endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 196a63dd37c..7e5129a733f 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -55,3 +55,6 @@ obj-$(CONFIG_EDAC_AMD8111) += amd8111_edac.o obj-$(CONFIG_EDAC_AMD8131) += amd8131_edac.o obj-$(CONFIG_EDAC_TILE) += tile_edac.o + +obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o +obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7be9b7288e9..5a297a26211 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -321,8 +321,8 @@ found: return edac_mc_find((int)node_id); err_no_match: - debugf2("sys_addr 0x%lx doesn't match any node\n", - (unsigned long)sys_addr); + edac_dbg(2, "sys_addr 0x%lx doesn't match any node\n", + (unsigned long)sys_addr); return NULL; } @@ -393,15 +393,15 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) mask = ~mask; if ((input_addr & mask) == (base & mask)) { - debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n", - (unsigned long)input_addr, csrow, - pvt->mc_node_id); + edac_dbg(2, "InputAddr 0x%lx matches csrow %d (node %d)\n", + (unsigned long)input_addr, csrow, + pvt->mc_node_id); return csrow; } } - debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n", - (unsigned long)input_addr, pvt->mc_node_id); + edac_dbg(2, "no matching csrow for InputAddr 0x%lx (MC node %d)\n", + (unsigned long)input_addr, pvt->mc_node_id); return -1; } @@ -430,20 +430,20 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, /* only revE and later have the DRAM Hole Address Register */ if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_E) { - debugf1(" revision %d for node %d does not support DHAR\n", - pvt->ext_model, pvt->mc_node_id); + edac_dbg(1, " revision %d for node %d does not support DHAR\n", + pvt->ext_model, pvt->mc_node_id); return 1; } /* valid for Fam10h and above */ if (boot_cpu_data.x86 >= 0x10 && !dhar_mem_hoist_valid(pvt)) { - debugf1(" Dram Memory Hoisting is DISABLED on this system\n"); + edac_dbg(1, " Dram Memory Hoisting is DISABLED on this system\n"); return 1; } if (!dhar_valid(pvt)) { - debugf1(" Dram Memory Hoisting is DISABLED on this node %d\n", - pvt->mc_node_id); + edac_dbg(1, " Dram Memory Hoisting is DISABLED on this node %d\n", + pvt->mc_node_id); return 1; } @@ -475,9 +475,9 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, else *hole_offset = k8_dhar_offset(pvt); - debugf1(" DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n", - pvt->mc_node_id, (unsigned long)*hole_base, - (unsigned long)*hole_offset, (unsigned long)*hole_size); + edac_dbg(1, " DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n", + pvt->mc_node_id, (unsigned long)*hole_base, + (unsigned long)*hole_offset, (unsigned long)*hole_size); return 0; } @@ -528,10 +528,9 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) /* use DHAR to translate SysAddr to DramAddr */ dram_addr = sys_addr - hole_offset; - debugf2("using DHAR to translate SysAddr 0x%lx to " - "DramAddr 0x%lx\n", - (unsigned long)sys_addr, - (unsigned long)dram_addr); + edac_dbg(2, "using DHAR to translate SysAddr 0x%lx to DramAddr 0x%lx\n", + (unsigned long)sys_addr, + (unsigned long)dram_addr); return dram_addr; } @@ -548,9 +547,8 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) */ dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base; - debugf2("using DRAM Base register to translate SysAddr 0x%lx to " - "DramAddr 0x%lx\n", (unsigned long)sys_addr, - (unsigned long)dram_addr); + edac_dbg(2, "using DRAM Base register to translate SysAddr 0x%lx to DramAddr 0x%lx\n", + (unsigned long)sys_addr, (unsigned long)dram_addr); return dram_addr; } @@ -586,9 +584,9 @@ static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr) input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) + (dram_addr & 0xfff); - debugf2(" Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n", - intlv_shift, (unsigned long)dram_addr, - (unsigned long)input_addr); + edac_dbg(2, " Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n", + intlv_shift, (unsigned long)dram_addr, + (unsigned long)input_addr); return input_addr; } @@ -604,8 +602,8 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) input_addr = dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr)); - debugf2("SysAdddr 0x%lx translates to InputAddr 0x%lx\n", - (unsigned long)sys_addr, (unsigned long)input_addr); + edac_dbg(2, "SysAdddr 0x%lx translates to InputAddr 0x%lx\n", + (unsigned long)sys_addr, (unsigned long)input_addr); return input_addr; } @@ -637,8 +635,8 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0)); if (intlv_shift == 0) { - debugf1(" InputAddr 0x%lx translates to DramAddr of " - "same value\n", (unsigned long)input_addr); + edac_dbg(1, " InputAddr 0x%lx translates to DramAddr of same value\n", + (unsigned long)input_addr); return input_addr; } @@ -649,9 +647,9 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1); dram_addr = bits + (intlv_sel << 12); - debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " - "(%d node interleave bits)\n", (unsigned long)input_addr, - (unsigned long)dram_addr, intlv_shift); + edac_dbg(1, "InputAddr 0x%lx translates to DramAddr 0x%lx (%d node interleave bits)\n", + (unsigned long)input_addr, + (unsigned long)dram_addr, intlv_shift); return dram_addr; } @@ -673,9 +671,9 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) (dram_addr < (hole_base + hole_size))) { sys_addr = dram_addr + hole_offset; - debugf1("using DHAR to translate DramAddr 0x%lx to " - "SysAddr 0x%lx\n", (unsigned long)dram_addr, - (unsigned long)sys_addr); + edac_dbg(1, "using DHAR to translate DramAddr 0x%lx to SysAddr 0x%lx\n", + (unsigned long)dram_addr, + (unsigned long)sys_addr); return sys_addr; } @@ -697,9 +695,9 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) */ sys_addr |= ~((sys_addr & (1ull << 39)) - 1); - debugf1(" Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", - pvt->mc_node_id, (unsigned long)dram_addr, - (unsigned long)sys_addr); + edac_dbg(1, " Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", + pvt->mc_node_id, (unsigned long)dram_addr, + (unsigned long)sys_addr); return sys_addr; } @@ -768,49 +766,48 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8); static void amd64_dump_dramcfg_low(u32 dclr, int chan) { - debugf1("F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); + edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); - debugf1(" DIMM type: %sbuffered; all DIMMs support ECC: %s\n", - (dclr & BIT(16)) ? "un" : "", - (dclr & BIT(19)) ? "yes" : "no"); + edac_dbg(1, " DIMM type: %sbuffered; all DIMMs support ECC: %s\n", + (dclr & BIT(16)) ? "un" : "", + (dclr & BIT(19)) ? "yes" : "no"); - debugf1(" PAR/ERR parity: %s\n", - (dclr & BIT(8)) ? "enabled" : "disabled"); + edac_dbg(1, " PAR/ERR parity: %s\n", + (dclr & BIT(8)) ? "enabled" : "disabled"); if (boot_cpu_data.x86 == 0x10) - debugf1(" DCT 128bit mode width: %s\n", - (dclr & BIT(11)) ? "128b" : "64b"); + edac_dbg(1, " DCT 128bit mode width: %s\n", + (dclr & BIT(11)) ? "128b" : "64b"); - debugf1(" x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n", - (dclr & BIT(12)) ? "yes" : "no", - (dclr & BIT(13)) ? "yes" : "no", - (dclr & BIT(14)) ? "yes" : "no", - (dclr & BIT(15)) ? "yes" : "no"); + edac_dbg(1, " x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n", + (dclr & BIT(12)) ? "yes" : "no", + (dclr & BIT(13)) ? "yes" : "no", + (dclr & BIT(14)) ? "yes" : "no", + (dclr & BIT(15)) ? "yes" : "no"); } /* Display and decode various NB registers for debug purposes. */ static void dump_misc_regs(struct amd64_pvt *pvt) { - debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap); + edac_dbg(1, "F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap); - debugf1(" NB two channel DRAM capable: %s\n", - (pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no"); + edac_dbg(1, " NB two channel DRAM capable: %s\n", + (pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no"); - debugf1(" ECC capable: %s, ChipKill ECC capable: %s\n", - (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", - (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); + edac_dbg(1, " ECC capable: %s, ChipKill ECC capable: %s\n", + (pvt->nbcap & NBCAP_SECDED) ? "yes" : "no", + (pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no"); amd64_dump_dramcfg_low(pvt->dclr0, 0); - debugf1("F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); + edac_dbg(1, "F3xB0 (Online Spare): 0x%08x\n", pvt->online_spare); - debugf1("F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, " - "offset: 0x%08x\n", - pvt->dhar, dhar_base(pvt), - (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) - : f10_dhar_offset(pvt)); + edac_dbg(1, "F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, offset: 0x%08x\n", + pvt->dhar, dhar_base(pvt), + (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) + : f10_dhar_offset(pvt)); - debugf1(" DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); + edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); amd64_debug_display_dimm_sizes(pvt, 0); @@ -857,15 +854,15 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *base1 = &pvt->csels[1].csbases[cs]; if (!amd64_read_dct_pci_cfg(pvt, reg0, base0)) - debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", - cs, *base0, reg0); + edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", + cs, *base0, reg0); if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt)) continue; if (!amd64_read_dct_pci_cfg(pvt, reg1, base1)) - debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", - cs, *base1, reg1); + edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", + cs, *base1, reg1); } for_each_chip_select_mask(cs, 0, pvt) { @@ -875,15 +872,15 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) u32 *mask1 = &pvt->csels[1].csmasks[cs]; if (!amd64_read_dct_pci_cfg(pvt, reg0, mask0)) - debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", - cs, *mask0, reg0); + edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", + cs, *mask0, reg0); if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt)) continue; if (!amd64_read_dct_pci_cfg(pvt, reg1, mask1)) - debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", - cs, *mask1, reg1); + edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", + cs, *mask1, reg1); } } @@ -1049,24 +1046,22 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, if (!src_mci) { amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a node", - NULL); + ""); return; } /* Now map the sys_addr to a CSROW */ csrow = sys_addr_to_csrow(src_mci, sys_addr); if (csrow < 0) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a csrow", - NULL); + ""); return; } @@ -1082,12 +1077,11 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, amd64_mc_warn(src_mci, "unknown syndrome 0x%04x - " "possible error reporting race\n", syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, csrow, -1, -1, - EDAC_MOD_STR, "unknown syndrome - possible error reporting race", - NULL); + ""); return; } } else { @@ -1102,10 +1096,10 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, channel = ((sys_addr & BIT(3)) != 0); } - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, src_mci, 1, page, offset, syndrome, csrow, channel, -1, - EDAC_MOD_STR, "", NULL); + "", ""); } static int ddr2_cs_size(unsigned i, bool dct_width) @@ -1193,7 +1187,7 @@ static int f1x_early_channel_count(struct amd64_pvt *pvt) * Need to check DCT0[0] and DCT1[0] to see if only one of them has * their CSEnable bit on. If so, then SINGLE DIMM case. */ - debugf0("Data width is not 128 bits - need more decoding\n"); + edac_dbg(0, "Data width is not 128 bits - need more decoding\n"); /* * Check DRAM Bank Address Mapping values for each DIMM to see if there @@ -1272,25 +1266,24 @@ static void read_dram_ctl_register(struct amd64_pvt *pvt) return; if (!amd64_read_dct_pci_cfg(pvt, DCT_SEL_LO, &pvt->dct_sel_lo)) { - debugf0("F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n", - pvt->dct_sel_lo, dct_sel_baseaddr(pvt)); + edac_dbg(0, "F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n", + pvt->dct_sel_lo, dct_sel_baseaddr(pvt)); - debugf0(" DCTs operate in %s mode.\n", - (dct_ganging_enabled(pvt) ? "ganged" : "unganged")); + edac_dbg(0, " DCTs operate in %s mode\n", + (dct_ganging_enabled(pvt) ? "ganged" : "unganged")); if (!dct_ganging_enabled(pvt)) - debugf0(" Address range split per DCT: %s\n", - (dct_high_range_enabled(pvt) ? "yes" : "no")); + edac_dbg(0, " Address range split per DCT: %s\n", + (dct_high_range_enabled(pvt) ? "yes" : "no")); - debugf0(" data interleave for ECC: %s, " - "DRAM cleared since last warm reset: %s\n", - (dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"), - (dct_memory_cleared(pvt) ? "yes" : "no")); + edac_dbg(0, " data interleave for ECC: %s, DRAM cleared since last warm reset: %s\n", + (dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"), + (dct_memory_cleared(pvt) ? "yes" : "no")); - debugf0(" channel interleave: %s, " - "interleave bits selector: 0x%x\n", - (dct_interleave_enabled(pvt) ? "enabled" : "disabled"), - dct_sel_interleave_addr(pvt)); + edac_dbg(0, " channel interleave: %s, " + "interleave bits selector: 0x%x\n", + (dct_interleave_enabled(pvt) ? "enabled" : "disabled"), + dct_sel_interleave_addr(pvt)); } amd64_read_dct_pci_cfg(pvt, DCT_SEL_HI, &pvt->dct_sel_hi); @@ -1428,7 +1421,7 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) pvt = mci->pvt_info; - debugf1("input addr: 0x%llx, DCT: %d\n", in_addr, dct); + edac_dbg(1, "input addr: 0x%llx, DCT: %d\n", in_addr, dct); for_each_chip_select(csrow, dct, pvt) { if (!csrow_enabled(csrow, dct, pvt)) @@ -1436,19 +1429,18 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) get_cs_base_and_mask(pvt, csrow, dct, &cs_base, &cs_mask); - debugf1(" CSROW=%d CSBase=0x%llx CSMask=0x%llx\n", - csrow, cs_base, cs_mask); + edac_dbg(1, " CSROW=%d CSBase=0x%llx CSMask=0x%llx\n", + csrow, cs_base, cs_mask); cs_mask = ~cs_mask; - debugf1(" (InputAddr & ~CSMask)=0x%llx " - "(CSBase & ~CSMask)=0x%llx\n", - (in_addr & cs_mask), (cs_base & cs_mask)); + edac_dbg(1, " (InputAddr & ~CSMask)=0x%llx (CSBase & ~CSMask)=0x%llx\n", + (in_addr & cs_mask), (cs_base & cs_mask)); if ((in_addr & cs_mask) == (cs_base & cs_mask)) { cs_found = f10_process_possible_spare(pvt, dct, csrow); - debugf1(" MATCH csrow=%d\n", cs_found); + edac_dbg(1, " MATCH csrow=%d\n", cs_found); break; } } @@ -1505,8 +1497,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, u8 intlv_en = dram_intlv_en(pvt, range); u32 intlv_sel = dram_intlv_sel(pvt, range); - debugf1("(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", - range, sys_addr, get_dram_limit(pvt, range)); + edac_dbg(1, "(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", + range, sys_addr, get_dram_limit(pvt, range)); if (dhar_valid(pvt) && dhar_base(pvt) <= sys_addr && @@ -1562,7 +1554,7 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, (chan_addr & 0xfff); } - debugf1(" Normalized DCT addr: 0x%llx\n", chan_addr); + edac_dbg(1, " Normalized DCT addr: 0x%llx\n", chan_addr); cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel); @@ -1616,12 +1608,11 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); if (csrow < 0) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, -1, -1, -1, - EDAC_MOD_STR, "failed to map error addr to a csrow", - NULL); + ""); return; } @@ -1633,10 +1624,10 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, if (dct_ganging_enabled(pvt)) chan = get_channel_from_ecc_syndrome(mci, syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset, syndrome, csrow, chan, -1, - EDAC_MOD_STR, "", NULL); + "", ""); } /* @@ -1664,7 +1655,8 @@ static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->csels[1].csbases : pvt->csels[0].csbases; - debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam); + edac_dbg(1, "F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", + ctrl, dbam); edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl); @@ -1840,7 +1832,7 @@ static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs, } } - debugf0("syndrome(%x) not found\n", syndrome); + edac_dbg(0, "syndrome(%x) not found\n", syndrome); return -1; } @@ -1917,12 +1909,11 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m) /* Ensure that the Error Address is VALID */ if (!(m->status & MCI_STATUS_ADDRV)) { amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - EDAC_MOD_STR, "HW has no ERROR_ADDRESS available", - NULL); + ""); return; } @@ -1946,12 +1937,11 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (!(m->status & MCI_STATUS_ADDRV)) { amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - EDAC_MOD_STR, "HW has no ERROR_ADDRESS available", - NULL); + ""); return; } @@ -1966,11 +1956,11 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (!src_mci) { amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, -1, -1, -1, - EDAC_MOD_STR, - "ERROR ADDRESS NOT mapped to a MC", NULL); + "ERROR ADDRESS NOT mapped to a MC", + ""); return; } @@ -1980,17 +1970,16 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) if (csrow < 0) { amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n", (unsigned long)sys_addr); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, -1, -1, -1, - EDAC_MOD_STR, "ERROR ADDRESS NOT mapped to CS", - NULL); + ""); } else { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, csrow, -1, -1, - EDAC_MOD_STR, "", NULL); + "", ""); } } @@ -2047,9 +2036,9 @@ static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id) return -ENODEV; } - debugf1("F1: %s\n", pci_name(pvt->F1)); - debugf1("F2: %s\n", pci_name(pvt->F2)); - debugf1("F3: %s\n", pci_name(pvt->F3)); + edac_dbg(1, "F1: %s\n", pci_name(pvt->F1)); + edac_dbg(1, "F2: %s\n", pci_name(pvt->F2)); + edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); return 0; } @@ -2076,15 +2065,15 @@ static void read_mc_regs(struct amd64_pvt *pvt) * those are Read-As-Zero */ rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem); - debugf0(" TOP_MEM: 0x%016llx\n", pvt->top_mem); + edac_dbg(0, " TOP_MEM: 0x%016llx\n", pvt->top_mem); /* check first whether TOP_MEM2 is enabled */ rdmsrl(MSR_K8_SYSCFG, msr_val); if (msr_val & (1U << 21)) { rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2); - debugf0(" TOP_MEM2: 0x%016llx\n", pvt->top_mem2); + edac_dbg(0, " TOP_MEM2: 0x%016llx\n", pvt->top_mem2); } else - debugf0(" TOP_MEM2 disabled.\n"); + edac_dbg(0, " TOP_MEM2 disabled\n"); amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap); @@ -2100,17 +2089,17 @@ static void read_mc_regs(struct amd64_pvt *pvt) if (!rw) continue; - debugf1(" DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n", - range, - get_dram_base(pvt, range), - get_dram_limit(pvt, range)); + edac_dbg(1, " DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n", + range, + get_dram_base(pvt, range), + get_dram_limit(pvt, range)); - debugf1(" IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n", - dram_intlv_en(pvt, range) ? "Enabled" : "Disabled", - (rw & 0x1) ? "R" : "-", - (rw & 0x2) ? "W" : "-", - dram_intlv_sel(pvt, range), - dram_dst_node(pvt, range)); + edac_dbg(1, " IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n", + dram_intlv_en(pvt, range) ? "Enabled" : "Disabled", + (rw & 0x1) ? "R" : "-", + (rw & 0x2) ? "W" : "-", + dram_intlv_sel(pvt, range), + dram_dst_node(pvt, range)); } read_dct_base_mask(pvt); @@ -2191,9 +2180,9 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT); - debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); - debugf0(" nr_pages/channel= %u channel-count = %d\n", - nr_pages, pvt->channel_count); + edac_dbg(0, " (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode); + edac_dbg(0, " nr_pages/channel= %u channel-count = %d\n", + nr_pages, pvt->channel_count); return nr_pages; } @@ -2205,6 +2194,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) static int init_csrows(struct mem_ctl_info *mci) { struct csrow_info *csrow; + struct dimm_info *dimm; struct amd64_pvt *pvt = mci->pvt_info; u64 base, mask; u32 val; @@ -2217,22 +2207,19 @@ static int init_csrows(struct mem_ctl_info *mci) pvt->nbcfg = val; - debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", - pvt->mc_node_id, val, - !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); + edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", + pvt->mc_node_id, val, + !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); for_each_chip_select(i, 0, pvt) { - csrow = &mci->csrows[i]; + csrow = mci->csrows[i]; if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) { - debugf1("----CSROW %d EMPTY for node %d\n", i, - pvt->mc_node_id); + edac_dbg(1, "----CSROW %d VALID for MC node %d\n", + i, pvt->mc_node_id); continue; } - debugf1("----CSROW %d VALID for MC node %d\n", - i, pvt->mc_node_id); - empty = 0; if (csrow_enabled(i, 0, pvt)) nr_pages = amd64_csrow_nr_pages(pvt, 0, i); @@ -2244,8 +2231,9 @@ static int init_csrows(struct mem_ctl_info *mci) mtype = amd64_determine_memory_type(pvt, i); - debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); - debugf1(" nr_pages: %u\n", nr_pages * pvt->channel_count); + edac_dbg(1, " for MC node %d csrow %d:\n", pvt->mc_node_id, i); + edac_dbg(1, " nr_pages: %u\n", + nr_pages * pvt->channel_count); /* * determine whether CHIPKILL or JUST ECC or NO ECC is operating @@ -2257,9 +2245,10 @@ static int init_csrows(struct mem_ctl_info *mci) edac_mode = EDAC_NONE; for (j = 0; j < pvt->channel_count; j++) { - csrow->channels[j].dimm->mtype = mtype; - csrow->channels[j].dimm->edac_mode = edac_mode; - csrow->channels[j].dimm->nr_pages = nr_pages; + dimm = csrow->channels[j]->dimm; + dimm->mtype = mtype; + dimm->edac_mode = edac_mode; + dimm->nr_pages = nr_pages; } } @@ -2296,9 +2285,9 @@ static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid) struct msr *reg = per_cpu_ptr(msrs, cpu); nbe = reg->l & MSR_MCGCTL_NBE; - debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", - cpu, reg->q, - (nbe ? "enabled" : "disabled")); + edac_dbg(0, "core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", + cpu, reg->q, + (nbe ? "enabled" : "disabled")); if (!nbe) goto out; @@ -2369,8 +2358,8 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, amd64_read_pci_cfg(F3, NBCFG, &value); - debugf0("1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", - nid, value, !!(value & NBCFG_ECC_ENABLE)); + edac_dbg(0, "1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", + nid, value, !!(value & NBCFG_ECC_ENABLE)); if (!(value & NBCFG_ECC_ENABLE)) { amd64_warn("DRAM ECC disabled on this node, enabling...\n"); @@ -2394,8 +2383,8 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, s->flags.nb_ecc_prev = 1; } - debugf0("2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", - nid, value, !!(value & NBCFG_ECC_ENABLE)); + edac_dbg(0, "2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n", + nid, value, !!(value & NBCFG_ECC_ENABLE)); return ret; } @@ -2463,26 +2452,29 @@ static bool ecc_enabled(struct pci_dev *F3, u8 nid) return true; } -struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + - ARRAY_SIZE(amd64_inj_attrs) + - 1]; - -struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; - -static void set_mc_sysfs_attrs(struct mem_ctl_info *mci) +static int set_mc_sysfs_attrs(struct mem_ctl_info *mci) { - unsigned int i = 0, j = 0; + int rc; - for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) - sysfs_attrs[i] = amd64_dbg_attrs[i]; + rc = amd64_create_sysfs_dbg_files(mci); + if (rc < 0) + return rc; - if (boot_cpu_data.x86 >= 0x10) - for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) - sysfs_attrs[i] = amd64_inj_attrs[j]; + if (boot_cpu_data.x86 >= 0x10) { + rc = amd64_create_sysfs_inject_files(mci); + if (rc < 0) + return rc; + } + + return 0; +} - sysfs_attrs[i] = terminator; +static void del_mc_sysfs_attrs(struct mem_ctl_info *mci) +{ + amd64_remove_sysfs_dbg_files(mci); - mci->mc_driver_sysfs_attributes = sysfs_attrs; + if (boot_cpu_data.x86 >= 0x10) + amd64_remove_sysfs_inject_files(mci); } static void setup_mci_misc_attrs(struct mem_ctl_info *mci, @@ -2601,20 +2593,22 @@ static int amd64_init_one_instance(struct pci_dev *F2) goto err_siblings; mci->pvt_info = pvt; - mci->dev = &pvt->F2->dev; + mci->pdev = &pvt->F2->dev; setup_mci_misc_attrs(mci, fam_type); if (init_csrows(mci)) mci->edac_cap = EDAC_FLAG_NONE; - set_mc_sysfs_attrs(mci); - ret = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf1("failed edac_mc_add_mc()\n"); + edac_dbg(1, "failed edac_mc_add_mc()\n"); goto err_add_mc; } + if (set_mc_sysfs_attrs(mci)) { + edac_dbg(1, "failed edac_mc_add_mc()\n"); + goto err_add_sysfs; + } /* register stuff with EDAC MCE */ if (report_gart_errors) @@ -2628,6 +2622,8 @@ static int amd64_init_one_instance(struct pci_dev *F2) return 0; +err_add_sysfs: + edac_mc_del_mc(mci->pdev); err_add_mc: edac_mc_free(mci); @@ -2651,7 +2647,7 @@ static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret < 0) { - debugf0("ret=%d\n", ret); + edac_dbg(0, "ret=%d\n", ret); return -EIO; } @@ -2698,6 +2694,8 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) struct pci_dev *F3 = node_to_amd_nb(nid)->misc; struct ecc_settings *s = ecc_stngs[nid]; + mci = find_mci_by_dev(&pdev->dev); + del_mc_sysfs_attrs(mci); /* Remove from EDAC CORE tracking list */ mci = edac_mc_del_mc(&pdev->dev); if (!mci) diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 9a666cb985b..8d4804732ba 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -413,20 +413,33 @@ struct ecc_settings { }; #ifdef CONFIG_EDAC_DEBUG -#define NUM_DBG_ATTRS 5 +int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci); +void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci); + #else -#define NUM_DBG_ATTRS 0 +static inline int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + return 0; +} +static void inline amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci) +{ +} #endif #ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION -#define NUM_INJ_ATTRS 5 +int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci); +void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci); + #else -#define NUM_INJ_ATTRS 0 +static inline int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci) +{ + return 0; +} +static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci) +{ +} #endif -extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS], - amd64_inj_attrs[NUM_INJ_ATTRS]; - /* * Each of the PCI Device IDs types have their own set of hardware accessor * functions and per device encoding/decoding logic. @@ -460,3 +473,5 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, u64 *hole_offset, u64 *hole_size); + +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c index e3562288f4c..2c1bbf74060 100644 --- a/drivers/edac/amd64_edac_dbg.c +++ b/drivers/edac/amd64_edac_dbg.c @@ -1,8 +1,11 @@ #include "amd64_edac.h" #define EDAC_DCT_ATTR_SHOW(reg) \ -static ssize_t amd64_##reg##_show(struct mem_ctl_info *mci, char *data) \ +static ssize_t amd64_##reg##_show(struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct amd64_pvt *pvt = mci->pvt_info; \ return sprintf(data, "0x%016llx\n", (u64)pvt->reg); \ } @@ -12,8 +15,12 @@ EDAC_DCT_ATTR_SHOW(dbam0); EDAC_DCT_ATTR_SHOW(top_mem); EDAC_DCT_ATTR_SHOW(top_mem2); -static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) +static ssize_t amd64_hole_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + u64 hole_base = 0; u64 hole_offset = 0; u64 hole_size = 0; @@ -27,46 +34,40 @@ static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) /* * update NUM_DBG_ATTRS in case you add new members */ -struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { +static DEVICE_ATTR(dhar, S_IRUGO, amd64_dhar_show, NULL); +static DEVICE_ATTR(dbam, S_IRUGO, amd64_dbam0_show, NULL); +static DEVICE_ATTR(topmem, S_IRUGO, amd64_top_mem_show, NULL); +static DEVICE_ATTR(topmem2, S_IRUGO, amd64_top_mem2_show, NULL); +static DEVICE_ATTR(dram_hole, S_IRUGO, amd64_hole_show, NULL); + +int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_dhar); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_dbam); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_topmem); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_topmem2); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_dram_hole); + if (rc < 0) + return rc; - { - .attr = { - .name = "dhar", - .mode = (S_IRUGO) - }, - .show = amd64_dhar_show, - .store = NULL, - }, - { - .attr = { - .name = "dbam", - .mode = (S_IRUGO) - }, - .show = amd64_dbam0_show, - .store = NULL, - }, - { - .attr = { - .name = "topmem", - .mode = (S_IRUGO) - }, - .show = amd64_top_mem_show, - .store = NULL, - }, - { - .attr = { - .name = "topmem2", - .mode = (S_IRUGO) - }, - .show = amd64_top_mem2_show, - .store = NULL, - }, - { - .attr = { - .name = "dram_hole", - .mode = (S_IRUGO) - }, - .show = amd64_hole_show, - .store = NULL, - }, -}; + return 0; +} + +void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci) +{ + device_remove_file(&mci->dev, &dev_attr_dhar); + device_remove_file(&mci->dev, &dev_attr_dbam); + device_remove_file(&mci->dev, &dev_attr_topmem); + device_remove_file(&mci->dev, &dev_attr_topmem2); + device_remove_file(&mci->dev, &dev_attr_dram_hole); +} diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index 303f10e03dd..53d972e00df 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c @@ -1,7 +1,10 @@ #include "amd64_edac.h" -static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_section_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.section); } @@ -12,9 +15,11 @@ static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) * * range: 0..3 */ -static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, +static ssize_t amd64_inject_section_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -33,8 +38,11 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, return ret; } -static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_word_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.word); } @@ -45,9 +53,11 @@ static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) * * range: 0..8 */ -static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_word_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -66,8 +76,11 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, return ret; } -static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) +static ssize_t amd64_inject_ecc_vector_show(struct device *dev, + struct device_attribute *mattr, + char *buf) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; return sprintf(buf, "0x%x\n", pvt->injection.bit_map); } @@ -77,9 +90,11 @@ static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) * corresponding bit within the error injection word above. When used during a * DRAM ECC read, it holds the contents of the of the DRAM ECC bits. */ -static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_ecc_vector_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; int ret = 0; @@ -103,9 +118,11 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, * Do a DRAM ECC read. Assemble staged values in the pvt area, format into * fields needed by the injection registers and read the NB Array Data Port. */ -static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t amd64_inject_read_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; u32 section, word_bits; @@ -125,7 +142,8 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, /* Issue 'word' and 'bit' along with the READ request */ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); - debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); + edac_dbg(0, "section=0x%x word_bits=0x%x\n", + section, word_bits); return count; } @@ -136,9 +154,11 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, * Do a DRAM ECC write. Assemble staged values in the pvt area and format into * fields needed by the injection registers. */ -static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, +static ssize_t amd64_inject_write_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct amd64_pvt *pvt = mci->pvt_info; unsigned long value; u32 section, word_bits; @@ -158,7 +178,8 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, /* Issue 'word' and 'bit' along with the READ request */ amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits); - debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); + edac_dbg(0, "section=0x%x word_bits=0x%x\n", + section, word_bits); return count; } @@ -168,46 +189,47 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, /* * update NUM_INJ_ATTRS in case you add new members */ -struct mcidev_sysfs_attribute amd64_inj_attrs[] = { - - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_section_show, - .store = amd64_inject_section_store, - }, - { - .attr = { - .name = "inject_word", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_word_show, - .store = amd64_inject_word_store, - }, - { - .attr = { - .name = "inject_ecc_vector", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = amd64_inject_ecc_vector_show, - .store = amd64_inject_ecc_vector_store, - }, - { - .attr = { - .name = "inject_write", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = NULL, - .store = amd64_inject_write_store, - }, - { - .attr = { - .name = "inject_read", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = NULL, - .store = amd64_inject_read_store, - }, -}; + +static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, + amd64_inject_section_show, amd64_inject_section_store); +static DEVICE_ATTR(inject_word, S_IRUGO | S_IWUSR, + amd64_inject_word_show, amd64_inject_word_store); +static DEVICE_ATTR(inject_ecc_vector, S_IRUGO | S_IWUSR, + amd64_inject_ecc_vector_show, amd64_inject_ecc_vector_store); +static DEVICE_ATTR(inject_write, S_IRUGO | S_IWUSR, + NULL, amd64_inject_write_store); +static DEVICE_ATTR(inject_read, S_IRUGO | S_IWUSR, + NULL, amd64_inject_read_store); + + +int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_section); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_word); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_ecc_vector); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_write); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_read); + if (rc < 0) + return rc; + + return 0; +} + +void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci) +{ + device_remove_file(&mci->dev, &dev_attr_inject_section); + device_remove_file(&mci->dev, &dev_attr_inject_word); + device_remove_file(&mci->dev, &dev_attr_inject_ecc_vector); + device_remove_file(&mci->dev, &dev_attr_inject_write); + device_remove_file(&mci->dev, &dev_attr_inject_read); +} diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 9774d443fa5..29eeb68a200 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c @@ -105,7 +105,7 @@ static void amd76x_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &info->ecc_mode_status); @@ -145,10 +145,10 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = (info->ecc_mode_status >> 4) & 0xf; - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - mci->csrows[row].first_page, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + mci->csrows[row]->first_page, 0, 0, row, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } @@ -160,10 +160,10 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, if (handle_errors) { row = info->ecc_mode_status & 0xf; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - mci->csrows[row].first_page, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + mci->csrows[row]->first_page, 0, 0, row, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } @@ -180,7 +180,7 @@ static int amd76x_process_error_info(struct mem_ctl_info *mci, static void amd76x_check(struct mem_ctl_info *mci) { struct amd76x_error_info info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); amd76x_get_error_info(mci, &info); amd76x_process_error_info(mci, &info, 1); } @@ -194,8 +194,8 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, int index; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; /* find the DRAM Chip Select Base address and mask */ pci_read_config_dword(pdev, @@ -241,7 +241,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) u32 ems_mode; struct amd76x_error_info discard; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems); ems_mode = (ems >> 10) & 0x3; @@ -256,8 +256,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("%s(): mci = %p\n", __func__, mci); - mci->dev = &pdev->dev; + edac_dbg(0, "mci = %p\n", mci); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = ems_mode ? @@ -276,7 +276,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -292,7 +292,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail: @@ -304,7 +304,7 @@ fail: static int __devinit amd76x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* don't need to call pci_enable_device() */ return amd76x_probe1(pdev, ent->driver_data); @@ -322,7 +322,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (amd76x_pci) edac_pci_release_generic_ctl(amd76x_pci); diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 69ee6aab5c7..a1bbd8edd25 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -33,10 +33,10 @@ struct cell_edac_priv static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) { struct cell_edac_priv *priv = mci->pvt_info; - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; unsigned long address, pfn, offset, syndrome; - dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", + dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", priv->node, chan, ar); /* Address decoding is likely a bit bogus, to dbl check */ @@ -48,18 +48,18 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) syndrome = (ar & 0x000000001fe00000ul) >> 21; /* TODO: Decoding of the error address */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, csrow->first_page + pfn, offset, syndrome, - 0, chan, -1, "", "", NULL); + 0, chan, -1, "", ""); } static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) { struct cell_edac_priv *priv = mci->pvt_info; - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; unsigned long address, pfn, offset; - dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", + dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", priv->node, chan, ar); /* Address decoding is likely a bit bogus, to dbl check */ @@ -70,9 +70,9 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) offset = address & ~PAGE_MASK; /* TODO: Decoding of the error address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, csrow->first_page + pfn, offset, 0, - 0, chan, -1, "", "", NULL); + 0, chan, -1, "", ""); } static void cell_edac_check(struct mem_ctl_info *mci) @@ -83,7 +83,7 @@ static void cell_edac_check(struct mem_ctl_info *mci) fir = in_be64(&priv->regs->mic_fir); #ifdef DEBUG if (fir != priv->prev_fir) { - dev_dbg(mci->dev, "fir change : 0x%016lx\n", fir); + dev_dbg(mci->pdev, "fir change : 0x%016lx\n", fir); priv->prev_fir = fir; } #endif @@ -119,14 +119,14 @@ static void cell_edac_check(struct mem_ctl_info *mci) mb(); /* sync up */ #ifdef DEBUG fir = in_be64(&priv->regs->mic_fir); - dev_dbg(mci->dev, "fir clear : 0x%016lx\n", fir); + dev_dbg(mci->pdev, "fir clear : 0x%016lx\n", fir); #endif } } static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) { - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; struct dimm_info *dimm; struct cell_edac_priv *priv = mci->pvt_info; struct device_node *np; @@ -150,12 +150,12 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) csrow->last_page = csrow->first_page + nr_pages - 1; for (j = 0; j < csrow->nr_channels; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->mtype = MEM_XDR; dimm->edac_mode = EDAC_SECDED; dimm->nr_pages = nr_pages / csrow->nr_channels; } - dev_dbg(mci->dev, + dev_dbg(mci->pdev, "Initialized on node %d, chanmask=0x%x," " first_page=0x%lx, nr_pages=0x%x\n", priv->node, priv->chanmask, @@ -212,7 +212,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) priv->regs = regs; priv->node = pdev->id; priv->chanmask = chanmask; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_XDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index e22030a9de6..c2ef1349587 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c @@ -316,13 +316,12 @@ static void get_total_mem(struct cpc925_mc_pdata *pdata) reg += aw; size = of_read_number(reg, sw); reg += sw; - debugf1("%s: start 0x%lx, size 0x%lx\n", __func__, - start, size); + edac_dbg(1, "start 0x%lx, size 0x%lx\n", start, size); pdata->total_mem += size; } while (reg < reg_end); of_node_put(np); - debugf0("%s: total_mem 0x%lx\n", __func__, pdata->total_mem); + edac_dbg(0, "total_mem 0x%lx\n", pdata->total_mem); } static void cpc925_init_csrows(struct mem_ctl_info *mci) @@ -330,8 +329,9 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) struct cpc925_mc_pdata *pdata = mci->pvt_info; struct csrow_info *csrow; struct dimm_info *dimm; + enum dev_type dtype; int index, j; - u32 mbmr, mbbar, bba; + u32 mbmr, mbbar, bba, grain; unsigned long row_size, nr_pages, last_nr_pages = 0; get_total_mem(pdata); @@ -347,7 +347,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) if (bba == 0) continue; /* not populated */ - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; row_size = bba * (1UL << 28); /* 256M */ csrow->first_page = last_nr_pages; @@ -355,37 +355,36 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci) csrow->last_page = csrow->first_page + nr_pages - 1; last_nr_pages = csrow->last_page + 1; + switch (csrow->nr_channels) { + case 1: /* Single channel */ + grain = 32; /* four-beat burst of 32 bytes */ + break; + case 2: /* Dual channel */ + default: + grain = 64; /* four-beat burst of 64 bytes */ + break; + } + switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { + case 6: /* 0110, no way to differentiate X8 VS X16 */ + case 5: /* 0101 */ + case 8: /* 1000 */ + dtype = DEV_X16; + break; + case 7: /* 0111 */ + case 9: /* 1001 */ + dtype = DEV_X8; + break; + default: + dtype = DEV_UNKNOWN; + break; + } for (j = 0; j < csrow->nr_channels; j++) { - dimm = csrow->channels[j].dimm; - + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->mtype = MEM_RDDR; dimm->edac_mode = EDAC_SECDED; - - switch (csrow->nr_channels) { - case 1: /* Single channel */ - dimm->grain = 32; /* four-beat burst of 32 bytes */ - break; - case 2: /* Dual channel */ - default: - dimm->grain = 64; /* four-beat burst of 64 bytes */ - break; - } - - switch ((mbmr & MBMR_MODE_MASK) >> MBMR_MODE_SHIFT) { - case 6: /* 0110, no way to differentiate X8 VS X16 */ - case 5: /* 0101 */ - case 8: /* 1000 */ - dimm->dtype = DEV_X16; - break; - case 7: /* 0111 */ - case 9: /* 1001 */ - dimm->dtype = DEV_X8; - break; - default: - dimm->dtype = DEV_UNKNOWN; - break; - } + dimm->grain = grain; + dimm->dtype = dtype; } } } @@ -463,7 +462,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, *csrow = rank; #ifdef CONFIG_EDAC_DEBUG - if (mci->csrows[rank].first_page == 0) { + if (mci->csrows[rank]->first_page == 0) { cpc925_mc_printk(mci, KERN_ERR, "ECC occurs in a " "non-populated csrow, broken hardware?\n"); return; @@ -471,7 +470,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, #endif /* Revert csrow number */ - pa = mci->csrows[rank].first_page << PAGE_SHIFT; + pa = mci->csrows[rank]->first_page << PAGE_SHIFT; /* Revert column address */ col += bcnt; @@ -512,7 +511,7 @@ static void cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, *offset = pa & (PAGE_SIZE - 1); *pfn = pa >> PAGE_SHIFT; - debugf0("%s: ECC physical address 0x%lx\n", __func__, pa); + edac_dbg(0, "ECC physical address 0x%lx\n", pa); } static int cpc925_mc_find_channel(struct mem_ctl_info *mci, u16 syndrome) @@ -555,18 +554,18 @@ static void cpc925_mc_check(struct mem_ctl_info *mci) if (apiexcp & CECC_EXCP_DETECTED) { cpc925_mc_printk(mci, KERN_INFO, "DRAM CECC Fault\n"); channel = cpc925_mc_find_channel(mci, syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, syndrome, csrow, channel, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } if (apiexcp & UECC_EXCP_DETECTED) { cpc925_mc_printk(mci, KERN_INFO, "DRAM UECC Fault\n"); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, 0, csrow, -1, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } cpc925_mc_printk(mci, KERN_INFO, "Dump registers:\n"); @@ -852,8 +851,8 @@ static void cpc925_add_edac_devices(void __iomem *vbase) goto err2; } - debugf0("%s: Successfully added edac device for %s\n", - __func__, dev_info->ctl_name); + edac_dbg(0, "Successfully added edac device for %s\n", + dev_info->ctl_name); continue; @@ -884,8 +883,8 @@ static void cpc925_del_edac_devices(void) if (dev_info->exit) dev_info->exit(dev_info); - debugf0("%s: Successfully deleted edac device for %s\n", - __func__, dev_info->ctl_name); + edac_dbg(0, "Successfully deleted edac device for %s\n", + dev_info->ctl_name); } } @@ -900,7 +899,7 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) mscr = __raw_readl(pdata->vbase + REG_MSCR_OFFSET); si = (mscr & MSCR_SI_MASK) >> MSCR_SI_SHIFT; - debugf0("%s, Mem Scrub Ctrl Register 0x%x\n", __func__, mscr); + edac_dbg(0, "Mem Scrub Ctrl Register 0x%x\n", mscr); if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || (si == 0)) { @@ -928,8 +927,7 @@ static int cpc925_mc_get_channels(void __iomem *vbase) ((mbcr & MBCR_64BITBUS_MASK) == 0)) dual = 1; - debugf0("%s: %s channel\n", __func__, - (dual > 0) ? "Dual" : "Single"); + edac_dbg(0, "%s channel\n", (dual > 0) ? "Dual" : "Single"); return dual; } @@ -944,7 +942,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) struct resource *r; int res = 0, nr_channels; - debugf0("%s: %s platform device found!\n", __func__, pdev->name); + edac_dbg(0, "%s platform device found!\n", pdev->name); if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) { res = -ENOMEM; @@ -995,7 +993,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) pdata->edac_idx = edac_mc_idx++; pdata->name = pdev->name; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; platform_set_drvdata(pdev, mci); mci->dev_name = dev_name(&pdev->dev); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; @@ -1026,7 +1024,7 @@ static int __devinit cpc925_probe(struct platform_device *pdev) cpc925_add_edac_devices(vbase); /* get this far and it's successful */ - debugf0("%s: success\n", __func__); + edac_dbg(0, "success\n"); res = 0; goto out; diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 3186512c973..a5ed6b795fd 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c @@ -309,7 +309,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); if (page < pvt->tolm) return page; @@ -335,7 +335,7 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, int i; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* convert the addr to 4k page */ page = sec1_add >> (PAGE_SHIFT - 4); @@ -371,10 +371,10 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one, channel = !(error_one & 1); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offset_in_page(sec1_add << 4), sec1_syndrome, row, channel, -1, - "e752x CE", "", NULL); + "e752x CE", ""); } static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, @@ -394,7 +394,7 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, int row; struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); if (error_one & 0x0202) { error_2b = ded_add; @@ -408,11 +408,11 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, edac_mc_find_csrow_by_page(mci, block_page); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, - "e752x UE from Read", "", NULL); + "e752x UE from Read", ""); } if (error_one & 0x0404) { @@ -427,11 +427,11 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, edac_mc_find_csrow_by_page(mci, block_page); /* e752x mc reads 34:6 of the DRAM linear address */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, offset_in_page(error_2b << 4), 0, row, -1, -1, - "e752x UE from Scruber", "", NULL); + "e752x UE from Scruber", ""); } } @@ -453,10 +453,10 @@ static inline void process_ue_no_info_wr(struct mem_ctl_info *mci, if (!handle_error) return; - debugf3("%s()\n", __func__); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_dbg(3, "\n"); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - "e752x UE log memory write", "", NULL); + "e752x UE log memory write", ""); } static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error, @@ -982,7 +982,7 @@ static void e752x_check(struct mem_ctl_info *mci) { struct e752x_error_info info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); e752x_get_error_info(mci, &info); e752x_process_error_info(mci, &info, 1); } @@ -1069,6 +1069,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, u16 ddrcsr) { struct csrow_info *csrow; + enum edac_type edac_mode; unsigned long last_cumul_size; int index, mem_dev, drc_chan; int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */ @@ -1095,14 +1096,13 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { /* mem_dev 0=x8, 1=x4 */ mem_dev = (dra >> (index * 4 + 2)) & 0x3; - csrow = &mci->csrows[remap_csrow_index(mci, index)]; + csrow = mci->csrows[remap_csrow_index(mci, index)]; mem_dev = (mem_dev == 2); pci_read_config_byte(pdev, E752X_DRB + index, &value); /* convert a 128 or 64 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -1111,29 +1111,29 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + edac_mode = EDAC_NONE; for (i = 0; i < csrow->nr_channels; i++) { - struct dimm_info *dimm = csrow->channels[i].dimm; + struct dimm_info *dimm = csrow->channels[i]->dimm; - debugf3("Initializing rank at (%i,%i)\n", index, i); + edac_dbg(3, "Initializing rank at (%i,%i)\n", index, i); dimm->nr_pages = nr_pages / csrow->nr_channels; dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; - - /* - * if single channel or x8 devices then SECDED - * if dual channel and x4 then S4ECD4ED - */ - if (drc_ddim) { - if (drc_chan && mem_dev) { - dimm->edac_mode = EDAC_S4ECD4ED; - mci->edac_cap |= EDAC_FLAG_S4ECD4ED; - } else { - dimm->edac_mode = EDAC_SECDED; - mci->edac_cap |= EDAC_FLAG_SECDED; - } - } else - dimm->edac_mode = EDAC_NONE; + dimm->edac_mode = edac_mode; } } } @@ -1269,8 +1269,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; /* Number of channels 0=1chan,1=2chan */ struct e752x_error_info discard; - debugf0("%s(): mci\n", __func__); - debugf0("Starting Probe1\n"); + edac_dbg(0, "mci\n"); + edac_dbg(0, "Starting Probe1\n"); /* check to see if device 0 function 1 is enabled; if it isn't, we * assume the BIOS has reserved it for a reason and is expecting @@ -1300,7 +1300,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; /* 3100 IMCH supports SECDEC only */ mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED : @@ -1308,9 +1308,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E752X_REVISION; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; - debugf3("%s(): init pvt\n", __func__); + edac_dbg(3, "init pvt\n"); pvt = (struct e752x_pvt *)mci->pvt_info; pvt->dev_info = &e752x_devs[dev_idx]; pvt->mc_symmetric = ((ddrcsr & 0x10) != 0); @@ -1320,7 +1320,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) return -ENODEV; } - debugf3("%s(): more mci init\n", __func__); + edac_dbg(3, "more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e752x_check; @@ -1342,7 +1342,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */ else mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + edac_dbg(3, "tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E752X_TOLM, &pci_data); @@ -1359,7 +1359,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -1377,7 +1377,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail: @@ -1393,7 +1393,7 @@ fail: static int __devinit e752x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* wake up and enable device */ if (pci_enable_device(pdev) < 0) @@ -1407,7 +1407,7 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e752x_pvt *pvt; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (e752x_pci) edac_pci_release_generic_ctl(e752x_pci); @@ -1453,7 +1453,7 @@ static int __init e752x_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1464,7 +1464,7 @@ static int __init e752x_init(void) static void __exit e752x_exit(void) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); pci_unregister_driver(&e752x_driver); } diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 9a9c1a54679..9ff57f361a4 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c @@ -166,7 +166,7 @@ static const struct e7xxx_dev_info e7xxx_devs[] = { /* FIXME - is this valid for both SECDED and S4ECD4ED? */ static inline int e7xxx_find_channel(u16 syndrome) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); if ((syndrome & 0xff00) == 0) return 0; @@ -186,7 +186,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, u32 remap; struct e7xxx_pvt *pvt = (struct e7xxx_pvt *)mci->pvt_info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); if ((page < pvt->tolm) || ((page >= 0x100000) && (page < pvt->remapbase))) @@ -208,7 +208,7 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) int row; int channel; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* read the error address */ error_1b = info->dram_celog_add; /* FIXME - should use PAGE_SHIFT */ @@ -219,15 +219,15 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) row = edac_mc_find_csrow_by_page(mci, page); /* convert syndrome to channel */ channel = e7xxx_find_channel(syndrome); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, page, 0, syndrome, - row, channel, -1, "e7xxx CE", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, 0, syndrome, + row, channel, -1, "e7xxx CE", ""); } static void process_ce_no_info(struct mem_ctl_info *mci) { - debugf3("%s()\n", __func__); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "e7xxx CE log register overflow", "", NULL); + edac_dbg(3, "\n"); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, + "e7xxx CE log register overflow", ""); } static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) @@ -235,23 +235,23 @@ static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) u32 error_2b, block_page; int row; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* read the error address */ error_2b = info->dram_uelog_add; /* FIXME - should use PAGE_SHIFT */ block_page = error_2b >> 6; /* convert to 4k address */ row = edac_mc_find_csrow_by_page(mci, block_page); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, block_page, 0, 0, - row, -1, -1, "e7xxx UE", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, block_page, 0, 0, + row, -1, -1, "e7xxx UE", ""); } static void process_ue_no_info(struct mem_ctl_info *mci) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, -1, -1, -1, - "e7xxx UE log register overflow", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, + "e7xxx UE log register overflow", ""); } static void e7xxx_get_error_info(struct mem_ctl_info *mci, @@ -334,7 +334,7 @@ static void e7xxx_check(struct mem_ctl_info *mci) { struct e7xxx_error_info info; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); e7xxx_get_error_info(mci, &info); e7xxx_process_error_info(mci, &info, 1); } @@ -362,6 +362,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, int drc_chan, drc_drbg, drc_ddim, mem_dev; struct csrow_info *csrow; struct dimm_info *dimm; + enum edac_type edac_mode; pci_read_config_dword(pdev, E7XXX_DRA, &dra); drc_chan = dual_channel_active(drc, dev_idx); @@ -377,13 +378,12 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, for (index = 0; index < mci->nr_csrows; index++) { /* mem_dev 0=x8, 1=x4 */ mem_dev = (dra >> (index * 4 + 3)) & 0x1; - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; pci_read_config_byte(pdev, E7XXX_DRB + index, &value); /* convert a 64 or 32 MiB DRB to a page size. */ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -392,28 +392,29 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; + /* + * if single channel or x8 devices then SECDED + * if dual channel and x4 then S4ECD4ED + */ + if (drc_ddim) { + if (drc_chan && mem_dev) { + edac_mode = EDAC_S4ECD4ED; + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } else { + edac_mode = EDAC_SECDED; + mci->edac_cap |= EDAC_FLAG_SECDED; + } + } else + edac_mode = EDAC_NONE; + for (j = 0; j < drc_chan + 1; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / (drc_chan + 1); dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ dimm->mtype = MEM_RDDR; /* only one type supported */ dimm->dtype = mem_dev ? DEV_X4 : DEV_X8; - - /* - * if single channel or x8 devices then SECDED - * if dual channel and x4 then S4ECD4ED - */ - if (drc_ddim) { - if (drc_chan && mem_dev) { - dimm->edac_mode = EDAC_S4ECD4ED; - mci->edac_cap |= EDAC_FLAG_S4ECD4ED; - } else { - dimm->edac_mode = EDAC_SECDED; - mci->edac_cap |= EDAC_FLAG_SECDED; - } - } else - dimm->edac_mode = EDAC_NONE; + dimm->edac_mode = edac_mode; } } } @@ -428,7 +429,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) int drc_chan; struct e7xxx_error_info discard; - debugf0("%s(): mci\n", __func__); + edac_dbg(0, "mci\n"); pci_read_config_dword(pdev, E7XXX_DRC, &drc); @@ -451,15 +452,15 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED; /* FIXME - what if different memory types are in different csrows? */ mci->mod_name = EDAC_MOD_STR; mci->mod_ver = E7XXX_REVISION; - mci->dev = &pdev->dev; - debugf3("%s(): init pvt\n", __func__); + mci->pdev = &pdev->dev; + edac_dbg(3, "init pvt\n"); pvt = (struct e7xxx_pvt *)mci->pvt_info; pvt->dev_info = &e7xxx_devs[dev_idx]; pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -472,14 +473,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - debugf3("%s(): more mci init\n", __func__); + edac_dbg(3, "more mci init\n"); mci->ctl_name = pvt->dev_info->ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = e7xxx_check; mci->ctl_page_to_phys = ctl_page_to_phys; e7xxx_init_csrows(mci, pdev, dev_idx, drc); mci->edac_cap |= EDAC_FLAG_NONE; - debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); + edac_dbg(3, "tolm, remapbase, remaplimit\n"); /* load the top of low memory, remap base, and remap limit vars */ pci_read_config_word(pdev, E7XXX_TOLM, &pci_data); pvt->tolm = ((u32) pci_data) << 4; @@ -498,7 +499,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail1; } @@ -514,7 +515,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail1: @@ -530,7 +531,7 @@ fail0: static int __devinit e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* wake up and enable device */ return pci_enable_device(pdev) ? @@ -542,7 +543,7 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct e7xxx_pvt *pvt; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (e7xxx_pci) edac_pci_release_generic_ctl(e7xxx_pci); diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 117490d4f83..23bb99fa44f 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -71,26 +71,21 @@ extern const char *edac_mem_types[]; #ifdef CONFIG_EDAC_DEBUG extern int edac_debug_level; -#define edac_debug_printk(level, fmt, arg...) \ - do { \ - if (level <= edac_debug_level) \ - edac_printk(KERN_DEBUG, EDAC_DEBUG, \ - "%s: " fmt, __func__, ##arg); \ - } while (0) - -#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ ) -#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ ) -#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ ) -#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ ) -#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ ) +#define edac_dbg(level, fmt, ...) \ +do { \ + if (level <= edac_debug_level) \ + edac_printk(KERN_DEBUG, EDAC_DEBUG, \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) #else /* !CONFIG_EDAC_DEBUG */ -#define debugf0( ... ) -#define debugf1( ... ) -#define debugf2( ... ) -#define debugf3( ... ) -#define debugf4( ... ) +#define edac_dbg(level, fmt, ...) \ +do { \ + if (0) \ + edac_printk(KERN_DEBUG, EDAC_DEBUG, \ + "%s: " fmt, __func__, ##__VA_ARGS__); \ +} while (0) #endif /* !CONFIG_EDAC_DEBUG */ @@ -460,15 +455,15 @@ extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page); void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, + const u16 error_count, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, - const int layer0, - const int layer1, - const int layer2, + const int top_layer, + const int mid_layer, + const int low_layer, const char *msg, - const char *other_detail, - const void *mcelog); + const char *other_detail); /* * edac_device APIs diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index ee3f1f810c1..211021dfec7 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -40,12 +40,13 @@ static LIST_HEAD(edac_device_list); #ifdef CONFIG_EDAC_DEBUG static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev) { - debugf3("\tedac_dev = %p dev_idx=%d \n", edac_dev, edac_dev->dev_idx); - debugf4("\tedac_dev->edac_check = %p\n", edac_dev->edac_check); - debugf3("\tdev = %p\n", edac_dev->dev); - debugf3("\tmod_name:ctl_name = %s:%s\n", - edac_dev->mod_name, edac_dev->ctl_name); - debugf3("\tpvt_info = %p\n\n", edac_dev->pvt_info); + edac_dbg(3, "\tedac_dev = %p dev_idx=%d\n", + edac_dev, edac_dev->dev_idx); + edac_dbg(4, "\tedac_dev->edac_check = %p\n", edac_dev->edac_check); + edac_dbg(3, "\tdev = %p\n", edac_dev->dev); + edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n", + edac_dev->mod_name, edac_dev->ctl_name); + edac_dbg(3, "\tpvt_info = %p\n\n", edac_dev->pvt_info); } #endif /* CONFIG_EDAC_DEBUG */ @@ -82,8 +83,7 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( void *pvt, *p; int err; - debugf4("%s() instances=%d blocks=%d\n", - __func__, nr_instances, nr_blocks); + edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks); /* Calculate the size of memory we need to allocate AND * determine the offsets of the various item arrays @@ -156,8 +156,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( /* Name of this edac device */ snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); - debugf4("%s() edac_dev=%p next after end=%p\n", - __func__, dev_ctl, pvt + sz_private ); + edac_dbg(4, "edac_dev=%p next after end=%p\n", + dev_ctl, pvt + sz_private); /* Initialize every Instance */ for (instance = 0; instance < nr_instances; instance++) { @@ -178,10 +178,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( snprintf(blk->name, sizeof(blk->name), "%s%d", edac_block_name, block+offset_value); - debugf4("%s() instance=%d inst_p=%p block=#%d " - "block_p=%p name='%s'\n", - __func__, instance, inst, block, - blk, blk->name); + edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n", + instance, inst, block, blk, blk->name); /* if there are NO attributes OR no attribute pointer * then continue on to next block iteration @@ -194,8 +192,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib_p = &dev_attrib[block*nr_instances*nr_attrib]; blk->block_attributes = attrib_p; - debugf4("%s() THIS BLOCK_ATTRIB=%p\n", - __func__, blk->block_attributes); + edac_dbg(4, "THIS BLOCK_ATTRIB=%p\n", + blk->block_attributes); /* Initialize every user specified attribute in this * block with the data the caller passed in @@ -214,11 +212,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( attrib->block = blk; /* up link */ - debugf4("%s() alloc-attrib=%p attrib_name='%s' " - "attrib-spec=%p spec-name=%s\n", - __func__, attrib, attrib->attr.name, - &attrib_spec[attr], - attrib_spec[attr].attr.name + edac_dbg(4, "alloc-attrib=%p attrib_name='%s' attrib-spec=%p spec-name=%s\n", + attrib, attrib->attr.name, + &attrib_spec[attr], + attrib_spec[attr].attr.name ); } } @@ -273,7 +270,7 @@ static struct edac_device_ctl_info *find_edac_device_by_dev(struct device *dev) struct edac_device_ctl_info *edac_dev; struct list_head *item; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); list_for_each(item, &edac_device_list) { edac_dev = list_entry(item, struct edac_device_ctl_info, link); @@ -408,7 +405,7 @@ static void edac_device_workq_function(struct work_struct *work_req) void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, unsigned msec) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* take the arg 'msec' and set it into the control structure * to used in the time period calculation @@ -496,7 +493,7 @@ EXPORT_SYMBOL_GPL(edac_device_alloc_index); */ int edac_device_add_device(struct edac_device_ctl_info *edac_dev) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -570,7 +567,7 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev) { struct edac_device_ctl_info *edac_dev; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mutex_lock(&device_ctls_mutex); diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index b4ea185cceb..fb68a06ad68 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -202,7 +202,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj) { struct edac_device_ctl_info *edac_dev = to_edacdev(kobj); - debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx); + edac_dbg(4, "control index=%d\n", edac_dev->dev_idx); /* decrement the EDAC CORE module ref count */ module_put(edac_dev->owner); @@ -233,12 +233,12 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) struct bus_type *edac_subsys; int err; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); /* get the /sys/devices/system/edac reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys error\n", __func__); + edac_dbg(1, "no edac_subsys error\n"); err = -ENODEV; goto err_out; } @@ -264,8 +264,8 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) &edac_subsys->dev_root->kobj, "%s", edac_dev->name); if (err) { - debugf1("%s()Failed to register '.../edac/%s'\n", - __func__, edac_dev->name); + edac_dbg(1, "Failed to register '.../edac/%s'\n", + edac_dev->name); goto err_kobj_reg; } kobject_uevent(&edac_dev->kobj, KOBJ_ADD); @@ -274,8 +274,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) * edac_device_unregister_sysfs_main_kobj() must be used */ - debugf4("%s() Registered '.../edac/%s' kobject\n", - __func__, edac_dev->name); + edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name); return 0; @@ -296,9 +295,8 @@ err_out: */ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) { - debugf0("%s()\n", __func__); - debugf4("%s() name of kobject is: %s\n", - __func__, kobject_name(&dev->kobj)); + edac_dbg(0, "\n"); + edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj)); /* * Unregister the edac device's kobject and @@ -336,7 +334,7 @@ static void edac_device_ctrl_instance_release(struct kobject *kobj) { struct edac_device_instance *instance; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); /* map from this kobj to the main control struct * and then dec the main kobj count @@ -442,7 +440,7 @@ static void edac_device_ctrl_block_release(struct kobject *kobj) { struct edac_device_block *block; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); /* get the container of the kobj */ block = to_block(kobj); @@ -524,10 +522,10 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; - debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n", - __func__, instance->name, instance, block->name, block); - debugf4("%s() block kobj=%p block kobj->parent=%p\n", - __func__, &block->kobj, &block->kobj.parent); + edac_dbg(4, "Instance '%s' inst_p=%p block '%s' block_p=%p\n", + instance->name, instance, block->name, block); + edac_dbg(4, "block kobj=%p block kobj->parent=%p\n", + &block->kobj, &block->kobj.parent); /* init this block's kobject */ memset(&block->kobj, 0, sizeof(struct kobject)); @@ -546,8 +544,7 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, &instance->kobj, "%s", block->name); if (err) { - debugf1("%s() Failed to register instance '%s'\n", - __func__, block->name); + edac_dbg(1, "Failed to register instance '%s'\n", block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; @@ -560,11 +557,9 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { - debugf4("%s() creating block attrib='%s' " - "attrib->%p to kobj=%p\n", - __func__, - sysfs_attrib->attr.name, - sysfs_attrib, &block->kobj); + edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n", + sysfs_attrib->attr.name, + sysfs_attrib, &block->kobj); /* Create each block_attribute file */ err = sysfs_create_file(&block->kobj, @@ -647,14 +642,14 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl, &edac_dev->kobj, "%s", instance->name); if (err != 0) { - debugf2("%s() Failed to register instance '%s'\n", - __func__, instance->name); + edac_dbg(2, "Failed to register instance '%s'\n", + instance->name); kobject_put(main_kobj); goto err_out; } - debugf4("%s() now register '%d' blocks for instance %d\n", - __func__, instance->nr_blocks, idx); + edac_dbg(4, "now register '%d' blocks for instance %d\n", + instance->nr_blocks, idx); /* register all blocks of this instance */ for (i = 0; i < instance->nr_blocks; i++) { @@ -670,8 +665,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, } kobject_uevent(&instance->kobj, KOBJ_ADD); - debugf4("%s() Registered instance %d '%s' kobject\n", - __func__, idx, instance->name); + edac_dbg(4, "Registered instance %d '%s' kobject\n", + idx, instance->name); return 0; @@ -715,7 +710,7 @@ static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev) int i, j; int err; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) { @@ -817,12 +812,12 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) int err; struct kobject *edac_kobj = &edac_dev->kobj; - debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx); + edac_dbg(0, "idx=%d\n", edac_dev->dev_idx); /* go create any main attributes callers wants */ err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { - debugf0("%s() failed to add sysfs attribs\n", __func__); + edac_dbg(0, "failed to add sysfs attribs\n"); goto err_out; } @@ -832,8 +827,7 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { - debugf0("%s() sysfs_create_link() returned err= %d\n", - __func__, err); + edac_dbg(0, "sysfs_create_link() returned err= %d\n", err); goto err_remove_main_attribs; } @@ -843,14 +837,13 @@ int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev) */ err = edac_device_create_instances(edac_dev); if (err) { - debugf0("%s() edac_device_create_instances() " - "returned err= %d\n", __func__, err); + edac_dbg(0, "edac_device_create_instances() returned err= %d\n", + err); goto err_remove_link; } - debugf4("%s() create-instances done, idx=%d\n", - __func__, edac_dev->dev_idx); + edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx); return 0; @@ -873,7 +866,7 @@ err_out: */ void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* remove any main attributes for this device */ edac_device_remove_main_sysfs_attributes(edac_dev); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index de5ba86e8b8..616d90bcb3a 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -27,70 +27,95 @@ #include <linux/list.h> #include <linux/ctype.h> #include <linux/edac.h> +#include <linux/bitops.h> #include <asm/uaccess.h> #include <asm/page.h> #include <asm/edac.h> #include "edac_core.h" #include "edac_module.h" +#define CREATE_TRACE_POINTS +#define TRACE_INCLUDE_PATH ../../include/ras +#include <ras/ras_event.h> + /* lock to memory controller's control array */ static DEFINE_MUTEX(mem_ctls_mutex); static LIST_HEAD(mc_devices); +unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf, + unsigned len) +{ + struct mem_ctl_info *mci = dimm->mci; + int i, n, count = 0; + char *p = buf; + + for (i = 0; i < mci->n_layers; i++) { + n = snprintf(p, len, "%s %d ", + edac_layer_name[mci->layers[i].type], + dimm->location[i]); + p += n; + len -= n; + count += n; + if (!len) + break; + } + + return count; +} + #ifdef CONFIG_EDAC_DEBUG static void edac_mc_dump_channel(struct rank_info *chan) { - debugf4("\tchannel = %p\n", chan); - debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx); - debugf4("\tchannel->csrow = %p\n\n", chan->csrow); - debugf4("\tchannel->dimm = %p\n", chan->dimm); + edac_dbg(4, " channel->chan_idx = %d\n", chan->chan_idx); + edac_dbg(4, " channel = %p\n", chan); + edac_dbg(4, " channel->csrow = %p\n", chan->csrow); + edac_dbg(4, " channel->dimm = %p\n", chan->dimm); } -static void edac_mc_dump_dimm(struct dimm_info *dimm) +static void edac_mc_dump_dimm(struct dimm_info *dimm, int number) { - int i; - - debugf4("\tdimm = %p\n", dimm); - debugf4("\tdimm->label = '%s'\n", dimm->label); - debugf4("\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); - debugf4("\tdimm location "); - for (i = 0; i < dimm->mci->n_layers; i++) { - printk(KERN_CONT "%d", dimm->location[i]); - if (i < dimm->mci->n_layers - 1) - printk(KERN_CONT "."); - } - printk(KERN_CONT "\n"); - debugf4("\tdimm->grain = %d\n", dimm->grain); - debugf4("\tdimm->nr_pages = 0x%x\n", dimm->nr_pages); + char location[80]; + + edac_dimm_info_location(dimm, location, sizeof(location)); + + edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", + dimm->mci->mem_is_per_rank ? "rank" : "dimm", + number, location, dimm->csrow, dimm->cschannel); + edac_dbg(4, " dimm = %p\n", dimm); + edac_dbg(4, " dimm->label = '%s'\n", dimm->label); + edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages); + edac_dbg(4, " dimm->grain = %d\n", dimm->grain); + edac_dbg(4, " dimm->nr_pages = 0x%x\n", dimm->nr_pages); } static void edac_mc_dump_csrow(struct csrow_info *csrow) { - debugf4("\tcsrow = %p\n", csrow); - debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); - debugf4("\tcsrow->first_page = 0x%lx\n", csrow->first_page); - debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); - debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); - debugf4("\tcsrow->nr_channels = %d\n", csrow->nr_channels); - debugf4("\tcsrow->channels = %p\n", csrow->channels); - debugf4("\tcsrow->mci = %p\n\n", csrow->mci); + edac_dbg(4, "csrow->csrow_idx = %d\n", csrow->csrow_idx); + edac_dbg(4, " csrow = %p\n", csrow); + edac_dbg(4, " csrow->first_page = 0x%lx\n", csrow->first_page); + edac_dbg(4, " csrow->last_page = 0x%lx\n", csrow->last_page); + edac_dbg(4, " csrow->page_mask = 0x%lx\n", csrow->page_mask); + edac_dbg(4, " csrow->nr_channels = %d\n", csrow->nr_channels); + edac_dbg(4, " csrow->channels = %p\n", csrow->channels); + edac_dbg(4, " csrow->mci = %p\n", csrow->mci); } static void edac_mc_dump_mci(struct mem_ctl_info *mci) { - debugf3("\tmci = %p\n", mci); - debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap); - debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap); - debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap); - debugf4("\tmci->edac_check = %p\n", mci->edac_check); - debugf3("\tmci->nr_csrows = %d, csrows = %p\n", - mci->nr_csrows, mci->csrows); - debugf3("\tmci->nr_dimms = %d, dimms = %p\n", - mci->tot_dimms, mci->dimms); - debugf3("\tdev = %p\n", mci->dev); - debugf3("\tmod_name:ctl_name = %s:%s\n", mci->mod_name, mci->ctl_name); - debugf3("\tpvt_info = %p\n\n", mci->pvt_info); + edac_dbg(3, "\tmci = %p\n", mci); + edac_dbg(3, "\tmci->mtype_cap = %lx\n", mci->mtype_cap); + edac_dbg(3, "\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap); + edac_dbg(3, "\tmci->edac_cap = %lx\n", mci->edac_cap); + edac_dbg(4, "\tmci->edac_check = %p\n", mci->edac_check); + edac_dbg(3, "\tmci->nr_csrows = %d, csrows = %p\n", + mci->nr_csrows, mci->csrows); + edac_dbg(3, "\tmci->nr_dimms = %d, dimms = %p\n", + mci->tot_dimms, mci->dimms); + edac_dbg(3, "\tdev = %p\n", mci->pdev); + edac_dbg(3, "\tmod_name:ctl_name = %s:%s\n", + mci->mod_name, mci->ctl_name); + edac_dbg(3, "\tpvt_info = %p\n\n", mci->pvt_info); } #endif /* CONFIG_EDAC_DEBUG */ @@ -205,15 +230,15 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, { struct mem_ctl_info *mci; struct edac_mc_layer *layer; - struct csrow_info *csi, *csr; - struct rank_info *chi, *chp, *chan; + struct csrow_info *csr; + struct rank_info *chan; struct dimm_info *dimm; u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS]; unsigned pos[EDAC_MAX_LAYERS]; unsigned size, tot_dimms = 1, count = 1; unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0; void *pvt, *p, *ptr = NULL; - int i, j, err, row, chn, n, len; + int i, j, row, chn, n, len, off; bool per_rank = false; BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0); @@ -239,26 +264,24 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, */ mci = edac_align_ptr(&ptr, sizeof(*mci), 1); layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers); - csi = edac_align_ptr(&ptr, sizeof(*csi), tot_csrows); - chi = edac_align_ptr(&ptr, sizeof(*chi), tot_csrows * tot_channels); - dimm = edac_align_ptr(&ptr, sizeof(*dimm), tot_dimms); for (i = 0; i < n_layers; i++) { count *= layers[i].size; - debugf4("%s: errcount layer %d size %d\n", __func__, i, count); + edac_dbg(4, "errcount layer %d size %d\n", i, count); ce_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); ue_per_layer[i] = edac_align_ptr(&ptr, sizeof(u32), count); tot_errcount += 2 * count; } - debugf4("%s: allocating %d error counters\n", __func__, tot_errcount); + edac_dbg(4, "allocating %d error counters\n", tot_errcount); pvt = edac_align_ptr(&ptr, sz_pvt, 1); size = ((unsigned long)pvt) + sz_pvt; - debugf1("%s(): allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", - __func__, size, - tot_dimms, - per_rank ? "ranks" : "dimms", - tot_csrows * tot_channels); + edac_dbg(1, "allocating %u bytes for mci data (%d %s, %d csrows/channels)\n", + size, + tot_dimms, + per_rank ? "ranks" : "dimms", + tot_csrows * tot_channels); + mci = kzalloc(size, GFP_KERNEL); if (mci == NULL) return NULL; @@ -267,9 +290,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, * rather than an imaginary chunk of memory located at address 0. */ layer = (struct edac_mc_layer *)(((char *)mci) + ((unsigned long)layer)); - csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi)); - chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi)); - dimm = (struct dimm_info *)(((char *)mci) + ((unsigned long)dimm)); for (i = 0; i < n_layers; i++) { mci->ce_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ce_per_layer[i])); mci->ue_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ue_per_layer[i])); @@ -278,8 +298,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, /* setup index and various internal pointers */ mci->mc_idx = mc_num; - mci->csrows = csi; - mci->dimms = dimm; mci->tot_dimms = tot_dimms; mci->pvt_info = pvt; mci->n_layers = n_layers; @@ -290,40 +308,57 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, mci->mem_is_per_rank = per_rank; /* - * Fill the csrow struct + * Alocate and fill the csrow/channels structs */ + mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); + if (!mci->csrows) + goto error; for (row = 0; row < tot_csrows; row++) { - csr = &csi[row]; + csr = kzalloc(sizeof(**mci->csrows), GFP_KERNEL); + if (!csr) + goto error; + mci->csrows[row] = csr; csr->csrow_idx = row; csr->mci = mci; csr->nr_channels = tot_channels; - chp = &chi[row * tot_channels]; - csr->channels = chp; + csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, + GFP_KERNEL); + if (!csr->channels) + goto error; for (chn = 0; chn < tot_channels; chn++) { - chan = &chp[chn]; + chan = kzalloc(sizeof(**csr->channels), GFP_KERNEL); + if (!chan) + goto error; + csr->channels[chn] = chan; chan->chan_idx = chn; chan->csrow = csr; } } /* - * Fill the dimm struct + * Allocate and fill the dimm structs */ + mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); + if (!mci->dimms) + goto error; + memset(&pos, 0, sizeof(pos)); row = 0; chn = 0; - debugf4("%s: initializing %d %s\n", __func__, tot_dimms, - per_rank ? "ranks" : "dimms"); for (i = 0; i < tot_dimms; i++) { - chan = &csi[row].channels[chn]; - dimm = EDAC_DIMM_PTR(layer, mci->dimms, n_layers, - pos[0], pos[1], pos[2]); - dimm->mci = mci; + chan = mci->csrows[row]->channels[chn]; + off = EDAC_DIMM_OFF(layer, n_layers, pos[0], pos[1], pos[2]); + if (off < 0 || off >= tot_dimms) { + edac_mc_printk(mci, KERN_ERR, "EDAC core bug: EDAC_DIMM_OFF is trying to do an illegal data access\n"); + goto error; + } - debugf2("%s: %d: %s%zd (%d:%d:%d): row %d, chan %d\n", __func__, - i, per_rank ? "rank" : "dimm", (dimm - mci->dimms), - pos[0], pos[1], pos[2], row, chn); + dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL); + if (!dimm) + goto error; + mci->dimms[off] = dimm; + dimm->mci = mci; /* * Copy DIMM location and initialize it. @@ -367,16 +402,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, } mci->op_state = OP_ALLOC; - INIT_LIST_HEAD(&mci->grp_kobj_list); - - /* - * Initialize the 'root' kobj for the edac_mc controller - */ - err = edac_mc_register_sysfs_main_kobj(mci); - if (err) { - kfree(mci); - return NULL; - } /* at this point, the root kobj is valid, and in order to * 'free' the object, then the function: @@ -384,7 +409,30 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, * which will perform kobj unregistration and the actual free * will occur during the kobject callback operation */ + return mci; + +error: + if (mci->dimms) { + for (i = 0; i < tot_dimms; i++) + kfree(mci->dimms[i]); + kfree(mci->dimms); + } + if (mci->csrows) { + for (chn = 0; chn < tot_channels; chn++) { + csr = mci->csrows[chn]; + if (csr) { + for (chn = 0; chn < tot_channels; chn++) + kfree(csr->channels[chn]); + kfree(csr); + } + kfree(mci->csrows[i]); + } + kfree(mci->csrows); + } + kfree(mci); + + return NULL; } EXPORT_SYMBOL_GPL(edac_mc_alloc); @@ -395,12 +443,10 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc); */ void edac_mc_free(struct mem_ctl_info *mci) { - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); - edac_mc_unregister_sysfs_main_kobj(mci); - - /* free the mci instance memory here */ - kfree(mci); + /* the mci instance is freed here, when the sysfs object is dropped */ + edac_unregister_sysfs(mci); } EXPORT_SYMBOL_GPL(edac_mc_free); @@ -417,12 +463,12 @@ struct mem_ctl_info *find_mci_by_dev(struct device *dev) struct mem_ctl_info *mci; struct list_head *item; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); list_for_each(item, &mc_devices) { mci = list_entry(item, struct mem_ctl_info, link); - if (mci->dev == dev) + if (mci->pdev == dev) return mci; } @@ -485,7 +531,7 @@ static void edac_mc_workq_function(struct work_struct *work_req) */ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* if this instance is not in the POLL state, then simply return */ if (mci->op_state != OP_RUNNING_POLL) @@ -512,8 +558,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) status = cancel_delayed_work(&mci->work); if (status == 0) { - debugf0("%s() not canceled, flush the queue\n", - __func__); + edac_dbg(0, "not canceled, flush the queue\n"); /* workq instance might be running, wait for it */ flush_workqueue(edac_workqueue); @@ -574,7 +619,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) insert_before = &mc_devices; - p = find_mci_by_dev(mci->dev); + p = find_mci_by_dev(mci->pdev); if (unlikely(p != NULL)) goto fail0; @@ -596,7 +641,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci) fail0: edac_printk(KERN_WARNING, EDAC_MC, - "%s (%s) %s %s already assigned %d\n", dev_name(p->dev), + "%s (%s) %s %s already assigned %d\n", dev_name(p->pdev), edac_dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx); return 1; @@ -660,7 +705,7 @@ EXPORT_SYMBOL(edac_mc_find); /* FIXME - should a warning be printed if no error detection? correction? */ int edac_mc_add_mc(struct mem_ctl_info *mci) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); #ifdef CONFIG_EDAC_DEBUG if (edac_debug_level >= 3) @@ -670,15 +715,22 @@ int edac_mc_add_mc(struct mem_ctl_info *mci) int i; for (i = 0; i < mci->nr_csrows; i++) { + struct csrow_info *csrow = mci->csrows[i]; + u32 nr_pages = 0; int j; - edac_mc_dump_csrow(&mci->csrows[i]); - for (j = 0; j < mci->csrows[i].nr_channels; j++) - edac_mc_dump_channel(&mci->csrows[i]. - channels[j]); + for (j = 0; j < csrow->nr_channels; j++) + nr_pages += csrow->channels[j]->dimm->nr_pages; + if (!nr_pages) + continue; + edac_mc_dump_csrow(csrow); + for (j = 0; j < csrow->nr_channels; j++) + if (csrow->channels[j]->dimm->nr_pages) + edac_mc_dump_channel(csrow->channels[j]); } for (i = 0; i < mci->tot_dimms; i++) - edac_mc_dump_dimm(&mci->dimms[i]); + if (mci->dimms[i]->nr_pages) + edac_mc_dump_dimm(mci->dimms[i], i); } #endif mutex_lock(&mem_ctls_mutex); @@ -732,7 +784,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mutex_lock(&mem_ctls_mutex); @@ -770,7 +822,7 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, void *virt_addr; unsigned long flags = 0; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* ECC error page was not in our memory. Ignore it. */ if (!pfn_valid(page)) @@ -797,26 +849,26 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, /* FIXME - should return -1 */ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) { - struct csrow_info *csrows = mci->csrows; + struct csrow_info **csrows = mci->csrows; int row, i, j, n; - debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); + edac_dbg(1, "MC%d: 0x%lx\n", mci->mc_idx, page); row = -1; for (i = 0; i < mci->nr_csrows; i++) { - struct csrow_info *csrow = &csrows[i]; + struct csrow_info *csrow = csrows[i]; n = 0; for (j = 0; j < csrow->nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; n += dimm->nr_pages; } if (n == 0) continue; - debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) " - "mask(0x%lx)\n", mci->mc_idx, __func__, - csrow->first_page, page, csrow->last_page, - csrow->page_mask); + edac_dbg(3, "MC%d: first(0x%lx) page(0x%lx) last(0x%lx) mask(0x%lx)\n", + mci->mc_idx, + csrow->first_page, page, csrow->last_page, + csrow->page_mask); if ((page >= csrow->first_page) && (page <= csrow->last_page) && @@ -845,15 +897,16 @@ const char *edac_layer_name[] = { EXPORT_SYMBOL_GPL(edac_layer_name); static void edac_inc_ce_error(struct mem_ctl_info *mci, - bool enable_per_layer_report, - const int pos[EDAC_MAX_LAYERS]) + bool enable_per_layer_report, + const int pos[EDAC_MAX_LAYERS], + const u16 count) { int i, index = 0; - mci->ce_mc++; + mci->ce_mc += count; if (!enable_per_layer_report) { - mci->ce_noinfo_count++; + mci->ce_noinfo_count += count; return; } @@ -861,7 +914,7 @@ static void edac_inc_ce_error(struct mem_ctl_info *mci, if (pos[i] < 0) break; index += pos[i]; - mci->ce_per_layer[i][index]++; + mci->ce_per_layer[i][index] += count; if (i < mci->n_layers - 1) index *= mci->layers[i + 1].size; @@ -870,14 +923,15 @@ static void edac_inc_ce_error(struct mem_ctl_info *mci, static void edac_inc_ue_error(struct mem_ctl_info *mci, bool enable_per_layer_report, - const int pos[EDAC_MAX_LAYERS]) + const int pos[EDAC_MAX_LAYERS], + const u16 count) { int i, index = 0; - mci->ue_mc++; + mci->ue_mc += count; if (!enable_per_layer_report) { - mci->ce_noinfo_count++; + mci->ce_noinfo_count += count; return; } @@ -885,7 +939,7 @@ static void edac_inc_ue_error(struct mem_ctl_info *mci, if (pos[i] < 0) break; index += pos[i]; - mci->ue_per_layer[i][index]++; + mci->ue_per_layer[i][index] += count; if (i < mci->n_layers - 1) index *= mci->layers[i + 1].size; @@ -893,6 +947,7 @@ static void edac_inc_ue_error(struct mem_ctl_info *mci, } static void edac_ce_error(struct mem_ctl_info *mci, + const u16 error_count, const int pos[EDAC_MAX_LAYERS], const char *msg, const char *location, @@ -902,23 +957,25 @@ static void edac_ce_error(struct mem_ctl_info *mci, const bool enable_per_layer_report, const unsigned long page_frame_number, const unsigned long offset_in_page, - u32 grain) + long grain) { unsigned long remapped_page; if (edac_mc_get_log_ce()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s%s - %s)\n", + "%d CE %s on %s (%s %s - %s)\n", + error_count, msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "CE %s on %s (%s%s)\n", + "%d CE %s on %s (%s %s)\n", + error_count, msg, label, location, detail); } - edac_inc_ce_error(mci, enable_per_layer_report, pos); + edac_inc_ce_error(mci, enable_per_layer_report, pos, error_count); if (mci->scrub_mode & SCRUB_SW_SRC) { /* @@ -942,6 +999,7 @@ static void edac_ce_error(struct mem_ctl_info *mci, } static void edac_ue_error(struct mem_ctl_info *mci, + const u16 error_count, const int pos[EDAC_MAX_LAYERS], const char *msg, const char *location, @@ -953,12 +1011,14 @@ static void edac_ue_error(struct mem_ctl_info *mci, if (edac_mc_get_log_ue()) { if (other_detail && *other_detail) edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s%s - %s)\n", + "%d UE %s on %s (%s %s - %s)\n", + error_count, msg, label, location, detail, other_detail); else edac_mc_printk(mci, KERN_WARNING, - "UE %s on %s (%s%s)\n", + "%d UE %s on %s (%s %s)\n", + error_count, msg, label, location, detail); } @@ -971,33 +1031,53 @@ static void edac_ue_error(struct mem_ctl_info *mci, msg, label, location, detail); } - edac_inc_ue_error(mci, enable_per_layer_report, pos); + edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count); } #define OTHER_LABEL " or " + +/** + * edac_mc_handle_error - reports a memory event to userspace + * + * @type: severity of the error (CE/UE/Fatal) + * @mci: a struct mem_ctl_info pointer + * @error_count: Number of errors of the same type + * @page_frame_number: mem page where the error occurred + * @offset_in_page: offset of the error inside the page + * @syndrome: ECC syndrome + * @top_layer: Memory layer[0] position + * @mid_layer: Memory layer[1] position + * @low_layer: Memory layer[2] position + * @msg: Message meaningful to the end users that + * explains the event + * @other_detail: Technical details about the event that + * may help hardware manufacturers and + * EDAC developers to analyse the event + */ void edac_mc_handle_error(const enum hw_event_mc_err_type type, struct mem_ctl_info *mci, + const u16 error_count, const unsigned long page_frame_number, const unsigned long offset_in_page, const unsigned long syndrome, - const int layer0, - const int layer1, - const int layer2, + const int top_layer, + const int mid_layer, + const int low_layer, const char *msg, - const char *other_detail, - const void *mcelog) + const char *other_detail) { /* FIXME: too much for stack: move it to some pre-alocated area */ char detail[80], location[80]; char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * mci->tot_dimms]; char *p; int row = -1, chan = -1; - int pos[EDAC_MAX_LAYERS] = { layer0, layer1, layer2 }; + int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer }; int i; - u32 grain; + long grain; bool enable_per_layer_report = false; + u8 grain_bits; - debugf3("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(3, "MC%d\n", mci->mc_idx); /* * Check if the event report is consistent and if the memory @@ -1043,13 +1123,13 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, p = label; *p = '\0'; for (i = 0; i < mci->tot_dimms; i++) { - struct dimm_info *dimm = &mci->dimms[i]; + struct dimm_info *dimm = mci->dimms[i]; - if (layer0 >= 0 && layer0 != dimm->location[0]) + if (top_layer >= 0 && top_layer != dimm->location[0]) continue; - if (layer1 >= 0 && layer1 != dimm->location[1]) + if (mid_layer >= 0 && mid_layer != dimm->location[1]) continue; - if (layer2 >= 0 && layer2 != dimm->location[2]) + if (low_layer >= 0 && low_layer != dimm->location[2]) continue; /* get the max grain, over the error match range */ @@ -1075,11 +1155,9 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, * get csrow/channel of the DIMM, in order to allow * incrementing the compat API counters */ - debugf4("%s: %s csrows map: (%d,%d)\n", - __func__, - mci->mem_is_per_rank ? "rank" : "dimm", - dimm->csrow, dimm->cschannel); - + edac_dbg(4, "%s csrows map: (%d,%d)\n", + mci->mem_is_per_rank ? "rank" : "dimm", + dimm->csrow, dimm->cschannel); if (row == -1) row = dimm->csrow; else if (row >= 0 && row != dimm->csrow) @@ -1095,19 +1173,18 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, if (!enable_per_layer_report) { strcpy(label, "any memory"); } else { - debugf4("%s: csrow/channel to increment: (%d,%d)\n", - __func__, row, chan); + edac_dbg(4, "csrow/channel to increment: (%d,%d)\n", row, chan); if (p == label) strcpy(label, "unknown memory"); if (type == HW_EVENT_ERR_CORRECTED) { if (row >= 0) { - mci->csrows[row].ce_count++; + mci->csrows[row]->ce_count += error_count; if (chan >= 0) - mci->csrows[row].channels[chan].ce_count++; + mci->csrows[row]->channels[chan]->ce_count += error_count; } } else if (row >= 0) - mci->csrows[row].ue_count++; + mci->csrows[row]->ue_count += error_count; } /* Fill the RAM location data */ @@ -1120,23 +1197,33 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, edac_layer_name[mci->layers[i].type], pos[i]); } + if (p > location) + *(p - 1) = '\0'; + + /* Report the error via the trace interface */ + + grain_bits = fls_long(grain) + 1; + trace_mc_event(type, msg, label, error_count, + mci->mc_idx, top_layer, mid_layer, low_layer, + PAGES_TO_MiB(page_frame_number) | offset_in_page, + grain_bits, syndrome, other_detail); /* Memory type dependent details about the error */ if (type == HW_EVENT_ERR_CORRECTED) { snprintf(detail, sizeof(detail), - "page:0x%lx offset:0x%lx grain:%d syndrome:0x%lx", + "page:0x%lx offset:0x%lx grain:%ld syndrome:0x%lx", page_frame_number, offset_in_page, grain, syndrome); - edac_ce_error(mci, pos, msg, location, label, detail, - other_detail, enable_per_layer_report, + edac_ce_error(mci, error_count, pos, msg, location, label, + detail, other_detail, enable_per_layer_report, page_frame_number, offset_in_page, grain); } else { snprintf(detail, sizeof(detail), - "page:0x%lx offset:0x%lx grain:%d", + "page:0x%lx offset:0x%lx grain:%ld", page_frame_number, offset_in_page, grain); - edac_ue_error(mci, pos, msg, location, label, detail, - other_detail, enable_per_layer_report); + edac_ue_error(mci, error_count, pos, msg, location, label, + detail, other_detail, enable_per_layer_report); } } EXPORT_SYMBOL_GPL(edac_mc_handle_error); diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index f6a29b0eedc..ed0bc07b850 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -7,17 +7,21 @@ * * Written Doug Thompson <norsk5@xmission.com> www.softwarebitmaker.com * + * (c) 2012 - Mauro Carvalho Chehab <mchehab@redhat.com> + * The entire API were re-written, and ported to use struct device + * */ #include <linux/ctype.h> #include <linux/slab.h> #include <linux/edac.h> #include <linux/bug.h> +#include <linux/pm_runtime.h> +#include <linux/uaccess.h> #include "edac_core.h" #include "edac_module.h" - /* MC EDAC Controls, setable by module parameter, and sysfs */ static int edac_mc_log_ue = 1; static int edac_mc_log_ce = 1; @@ -78,6 +82,8 @@ module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int, &edac_mc_poll_msec, 0644); MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); +static struct device *mci_pdev; + /* * various constants for Memory Controllers */ @@ -125,317 +131,526 @@ static const char *edac_caps[] = { [EDAC_S16ECD16ED] = "S16ECD16ED" }; -/* EDAC sysfs CSROW data structures and methods +#ifdef CONFIG_EDAC_LEGACY_SYSFS +/* + * EDAC sysfs CSROW data structures and methods + */ + +#define to_csrow(k) container_of(k, struct csrow_info, dev) + +/* + * We need it to avoid namespace conflicts between the legacy API + * and the per-dimm/per-rank one */ +#define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \ + struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store) + +struct dev_ch_attribute { + struct device_attribute attr; + int channel; +}; + +#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \ + struct dev_ch_attribute dev_attr_legacy_##_name = \ + { __ATTR(_name, _mode, _show, _store), (_var) } + +#define to_channel(k) (container_of(k, struct dev_ch_attribute, attr)->channel) /* Set of more default csrow<id> attribute show/store functions */ -static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_ue_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%u\n", csrow->ue_count); } -static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_ce_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); + return sprintf(data, "%u\n", csrow->ce_count); } -static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_size_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct csrow_info *csrow = to_csrow(dev); int i; u32 nr_pages = 0; for (i = 0; i < csrow->nr_channels; i++) - nr_pages += csrow->channels[i].dimm->nr_pages; - + nr_pages += csrow->channels[i]->dimm->nr_pages; return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); } -static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_mem_type_show(struct device *dev, + struct device_attribute *mattr, char *data) { - return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]); + struct csrow_info *csrow = to_csrow(dev); + + return sprintf(data, "%s\n", mem_types[csrow->channels[0]->dimm->mtype]); } -static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_dev_type_show(struct device *dev, + struct device_attribute *mattr, char *data) { - return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]); + struct csrow_info *csrow = to_csrow(dev); + + return sprintf(data, "%s\n", dev_types[csrow->channels[0]->dimm->dtype]); } -static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, - int private) +static ssize_t csrow_edac_mode_show(struct device *dev, + struct device_attribute *mattr, + char *data) { - return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]); + struct csrow_info *csrow = to_csrow(dev); + + return sprintf(data, "%s\n", edac_caps[csrow->channels[0]->dimm->edac_mode]); } /* show/store functions for DIMM Label attributes */ -static ssize_t channel_dimm_label_show(struct csrow_info *csrow, - char *data, int channel) +static ssize_t channel_dimm_label_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = csrow->channels[chan]; + /* if field has not been initialized, there is nothing to send */ - if (!csrow->channels[channel].dimm->label[0]) + if (!rank->dimm->label[0]) return 0; return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", - csrow->channels[channel].dimm->label); + rank->dimm->label); } -static ssize_t channel_dimm_label_store(struct csrow_info *csrow, - const char *data, - size_t count, int channel) +static ssize_t channel_dimm_label_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = csrow->channels[chan]; + ssize_t max_size = 0; max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1); - strncpy(csrow->channels[channel].dimm->label, data, max_size); - csrow->channels[channel].dimm->label[max_size] = '\0'; + strncpy(rank->dimm->label, data, max_size); + rank->dimm->label[max_size] = '\0'; return max_size; } /* show function for dynamic chX_ce_count attribute */ -static ssize_t channel_ce_count_show(struct csrow_info *csrow, - char *data, int channel) +static ssize_t channel_ce_count_show(struct device *dev, + struct device_attribute *mattr, char *data) { - return sprintf(data, "%u\n", csrow->channels[channel].ce_count); + struct csrow_info *csrow = to_csrow(dev); + unsigned chan = to_channel(mattr); + struct rank_info *rank = csrow->channels[chan]; + + return sprintf(data, "%u\n", rank->ce_count); } -/* csrow specific attribute structure */ -struct csrowdev_attribute { - struct attribute attr; - ssize_t(*show) (struct csrow_info *, char *, int); - ssize_t(*store) (struct csrow_info *, const char *, size_t, int); - int private; -}; +/* cwrow<id>/attribute files */ +DEVICE_ATTR_LEGACY(size_mb, S_IRUGO, csrow_size_show, NULL); +DEVICE_ATTR_LEGACY(dev_type, S_IRUGO, csrow_dev_type_show, NULL); +DEVICE_ATTR_LEGACY(mem_type, S_IRUGO, csrow_mem_type_show, NULL); +DEVICE_ATTR_LEGACY(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL); +DEVICE_ATTR_LEGACY(ue_count, S_IRUGO, csrow_ue_count_show, NULL); +DEVICE_ATTR_LEGACY(ce_count, S_IRUGO, csrow_ce_count_show, NULL); -#define to_csrow(k) container_of(k, struct csrow_info, kobj) -#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr) +/* default attributes of the CSROW<id> object */ +static struct attribute *csrow_attrs[] = { + &dev_attr_legacy_dev_type.attr, + &dev_attr_legacy_mem_type.attr, + &dev_attr_legacy_edac_mode.attr, + &dev_attr_legacy_size_mb.attr, + &dev_attr_legacy_ue_count.attr, + &dev_attr_legacy_ce_count.attr, + NULL, +}; -/* Set of show/store higher level functions for default csrow attributes */ -static ssize_t csrowdev_show(struct kobject *kobj, - struct attribute *attr, char *buffer) -{ - struct csrow_info *csrow = to_csrow(kobj); - struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); +static struct attribute_group csrow_attr_grp = { + .attrs = csrow_attrs, +}; - if (csrowdev_attr->show) - return csrowdev_attr->show(csrow, - buffer, csrowdev_attr->private); - return -EIO; -} +static const struct attribute_group *csrow_attr_groups[] = { + &csrow_attr_grp, + NULL +}; -static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +static void csrow_attr_release(struct device *dev) { - struct csrow_info *csrow = to_csrow(kobj); - struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); - - if (csrowdev_attr->store) - return csrowdev_attr->store(csrow, - buffer, - count, csrowdev_attr->private); - return -EIO; -} + struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); -static const struct sysfs_ops csrowfs_ops = { - .show = csrowdev_show, - .store = csrowdev_store -}; + edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); + kfree(csrow); +} -#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private) \ -static struct csrowdev_attribute attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ - .private = _private, \ +static struct device_type csrow_attr_type = { + .groups = csrow_attr_groups, + .release = csrow_attr_release, }; -/* default cwrow<id>/attribute files */ -CSROWDEV_ATTR(size_mb, S_IRUGO, csrow_size_show, NULL, 0); -CSROWDEV_ATTR(dev_type, S_IRUGO, csrow_dev_type_show, NULL, 0); -CSROWDEV_ATTR(mem_type, S_IRUGO, csrow_mem_type_show, NULL, 0); -CSROWDEV_ATTR(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL, 0); -CSROWDEV_ATTR(ue_count, S_IRUGO, csrow_ue_count_show, NULL, 0); -CSROWDEV_ATTR(ce_count, S_IRUGO, csrow_ce_count_show, NULL, 0); +/* + * possible dynamic channel DIMM Label attribute files + * + */ -/* default attributes of the CSROW<id> object */ -static struct csrowdev_attribute *default_csrow_attr[] = { - &attr_dev_type, - &attr_mem_type, - &attr_edac_mode, - &attr_size_mb, - &attr_ue_count, - &attr_ce_count, - NULL, -}; +#define EDAC_NR_CHANNELS 6 -/* possible dynamic channel DIMM Label attribute files */ -CSROWDEV_ATTR(ch0_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 0); -CSROWDEV_ATTR(ch1_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 1); -CSROWDEV_ATTR(ch2_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch2_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 2); -CSROWDEV_ATTR(ch3_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch3_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 3); -CSROWDEV_ATTR(ch4_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch4_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 4); -CSROWDEV_ATTR(ch5_dimm_label, S_IRUGO | S_IWUSR, +DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR, channel_dimm_label_show, channel_dimm_label_store, 5); /* Total possible dynamic DIMM Label attribute file table */ -static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = { - &attr_ch0_dimm_label, - &attr_ch1_dimm_label, - &attr_ch2_dimm_label, - &attr_ch3_dimm_label, - &attr_ch4_dimm_label, - &attr_ch5_dimm_label +static struct device_attribute *dynamic_csrow_dimm_attr[] = { + &dev_attr_legacy_ch0_dimm_label.attr, + &dev_attr_legacy_ch1_dimm_label.attr, + &dev_attr_legacy_ch2_dimm_label.attr, + &dev_attr_legacy_ch3_dimm_label.attr, + &dev_attr_legacy_ch4_dimm_label.attr, + &dev_attr_legacy_ch5_dimm_label.attr }; /* possible dynamic channel ce_count attribute files */ -CSROWDEV_ATTR(ch0_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 0); -CSROWDEV_ATTR(ch1_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 1); -CSROWDEV_ATTR(ch2_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 2); -CSROWDEV_ATTR(ch3_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 3); -CSROWDEV_ATTR(ch4_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 4); -CSROWDEV_ATTR(ch5_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 5); +DEVICE_CHANNEL(ch0_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 0); +DEVICE_CHANNEL(ch1_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 1); +DEVICE_CHANNEL(ch2_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 2); +DEVICE_CHANNEL(ch3_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 3); +DEVICE_CHANNEL(ch4_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 4); +DEVICE_CHANNEL(ch5_ce_count, S_IRUGO | S_IWUSR, + channel_ce_count_show, NULL, 5); /* Total possible dynamic ce_count attribute file table */ -static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = { - &attr_ch0_ce_count, - &attr_ch1_ce_count, - &attr_ch2_ce_count, - &attr_ch3_ce_count, - &attr_ch4_ce_count, - &attr_ch5_ce_count +static struct device_attribute *dynamic_csrow_ce_count_attr[] = { + &dev_attr_legacy_ch0_ce_count.attr, + &dev_attr_legacy_ch1_ce_count.attr, + &dev_attr_legacy_ch2_ce_count.attr, + &dev_attr_legacy_ch3_ce_count.attr, + &dev_attr_legacy_ch4_ce_count.attr, + &dev_attr_legacy_ch5_ce_count.attr }; -#define EDAC_NR_CHANNELS 6 +static inline int nr_pages_per_csrow(struct csrow_info *csrow) +{ + int chan, nr_pages = 0; + + for (chan = 0; chan < csrow->nr_channels; chan++) + nr_pages += csrow->channels[chan]->dimm->nr_pages; + + return nr_pages; +} -/* Create dynamic CHANNEL files, indexed by 'chan', under specifed CSROW */ -static int edac_create_channel_files(struct kobject *kobj, int chan) +/* Create a CSROW object under specifed edac_mc_device */ +static int edac_create_csrow_object(struct mem_ctl_info *mci, + struct csrow_info *csrow, int index) { - int err = -ENODEV; + int err, chan; + + if (csrow->nr_channels >= EDAC_NR_CHANNELS) + return -ENODEV; + + csrow->dev.type = &csrow_attr_type; + csrow->dev.bus = &mci->bus; + device_initialize(&csrow->dev); + csrow->dev.parent = &mci->dev; + dev_set_name(&csrow->dev, "csrow%d", index); + dev_set_drvdata(&csrow->dev, csrow); - if (chan >= EDAC_NR_CHANNELS) + edac_dbg(0, "creating (virtual) csrow node %s\n", + dev_name(&csrow->dev)); + + err = device_add(&csrow->dev); + if (err < 0) return err; - /* create the DIMM label attribute file */ - err = sysfs_create_file(kobj, - (struct attribute *) - dynamic_csrow_dimm_attr[chan]); - - if (!err) { - /* create the CE Count attribute file */ - err = sysfs_create_file(kobj, - (struct attribute *) - dynamic_csrow_ce_count_attr[chan]); - } else { - debugf1("%s() dimm labels and ce_count files created", - __func__); + for (chan = 0; chan < csrow->nr_channels; chan++) { + /* Only expose populated DIMMs */ + if (!csrow->channels[chan]->dimm->nr_pages) + continue; + err = device_create_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + if (err < 0) + goto error; + err = device_create_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + if (err < 0) { + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + goto error; + } + } + + return 0; + +error: + for (--chan; chan >= 0; chan--) { + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); } + put_device(&csrow->dev); return err; } -/* No memory to release for this kobj */ -static void edac_csrow_instance_release(struct kobject *kobj) +/* Create a CSROW object under specifed edac_mc_device */ +static int edac_create_csrow_objects(struct mem_ctl_info *mci) { - struct mem_ctl_info *mci; - struct csrow_info *cs; + int err, i, chan; + struct csrow_info *csrow; + + for (i = 0; i < mci->nr_csrows; i++) { + csrow = mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; + err = edac_create_csrow_object(mci, mci->csrows[i], i); + if (err < 0) + goto error; + } + return 0; - debugf1("%s()\n", __func__); +error: + for (--i; i >= 0; i--) { + csrow = mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; + for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + if (!csrow->channels[chan]->dimm->nr_pages) + continue; + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + } + put_device(&mci->csrows[i]->dev); + } - cs = container_of(kobj, struct csrow_info, kobj); - mci = cs->mci; + return err; +} - kobject_put(&mci->edac_mci_kobj); +static void edac_delete_csrow_objects(struct mem_ctl_info *mci) +{ + int i, chan; + struct csrow_info *csrow; + + for (i = mci->nr_csrows - 1; i >= 0; i--) { + csrow = mci->csrows[i]; + if (!nr_pages_per_csrow(csrow)) + continue; + for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { + if (!csrow->channels[chan]->dimm->nr_pages) + continue; + edac_dbg(1, "Removing csrow %d channel %d sysfs nodes\n", + i, chan); + device_remove_file(&csrow->dev, + dynamic_csrow_dimm_attr[chan]); + device_remove_file(&csrow->dev, + dynamic_csrow_ce_count_attr[chan]); + } + put_device(&mci->csrows[i]->dev); + device_del(&mci->csrows[i]->dev); + } } +#endif -/* the kobj_type instance for a CSROW */ -static struct kobj_type ktype_csrow = { - .release = edac_csrow_instance_release, - .sysfs_ops = &csrowfs_ops, - .default_attrs = (struct attribute **)default_csrow_attr, +/* + * Per-dimm (or per-rank) devices + */ + +#define to_dimm(k) container_of(k, struct dimm_info, dev) + +/* show/store functions for DIMM Label attributes */ +static ssize_t dimmdev_location_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return edac_dimm_info_location(dimm, data, PAGE_SIZE); +} + +static ssize_t dimmdev_label_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + /* if field has not been initialized, there is nothing to send */ + if (!dimm->label[0]) + return 0; + + return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", dimm->label); +} + +static ssize_t dimmdev_label_store(struct device *dev, + struct device_attribute *mattr, + const char *data, + size_t count) +{ + struct dimm_info *dimm = to_dimm(dev); + + ssize_t max_size = 0; + + max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1); + strncpy(dimm->label, data, max_size); + dimm->label[max_size] = '\0'; + + return max_size; +} + +static ssize_t dimmdev_size_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%u\n", PAGES_TO_MiB(dimm->nr_pages)); +} + +static ssize_t dimmdev_mem_type_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", mem_types[dimm->mtype]); +} + +static ssize_t dimmdev_dev_type_show(struct device *dev, + struct device_attribute *mattr, char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", dev_types[dimm->dtype]); +} + +static ssize_t dimmdev_edac_mode_show(struct device *dev, + struct device_attribute *mattr, + char *data) +{ + struct dimm_info *dimm = to_dimm(dev); + + return sprintf(data, "%s\n", edac_caps[dimm->edac_mode]); +} + +/* dimm/rank attribute files */ +static DEVICE_ATTR(dimm_label, S_IRUGO | S_IWUSR, + dimmdev_label_show, dimmdev_label_store); +static DEVICE_ATTR(dimm_location, S_IRUGO, dimmdev_location_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, dimmdev_size_show, NULL); +static DEVICE_ATTR(dimm_mem_type, S_IRUGO, dimmdev_mem_type_show, NULL); +static DEVICE_ATTR(dimm_dev_type, S_IRUGO, dimmdev_dev_type_show, NULL); +static DEVICE_ATTR(dimm_edac_mode, S_IRUGO, dimmdev_edac_mode_show, NULL); + +/* attributes of the dimm<id>/rank<id> object */ +static struct attribute *dimm_attrs[] = { + &dev_attr_dimm_label.attr, + &dev_attr_dimm_location.attr, + &dev_attr_size.attr, + &dev_attr_dimm_mem_type.attr, + &dev_attr_dimm_dev_type.attr, + &dev_attr_dimm_edac_mode.attr, + NULL, }; -/* Create a CSROW object under specifed edac_mc_device */ -static int edac_create_csrow_object(struct mem_ctl_info *mci, - struct csrow_info *csrow, int index) +static struct attribute_group dimm_attr_grp = { + .attrs = dimm_attrs, +}; + +static const struct attribute_group *dimm_attr_groups[] = { + &dimm_attr_grp, + NULL +}; + +static void dimm_attr_release(struct device *dev) { - struct kobject *kobj_mci = &mci->edac_mci_kobj; - struct kobject *kobj; - int chan; - int err; + struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); - /* generate ..../edac/mc/mc<id>/csrow<index> */ - memset(&csrow->kobj, 0, sizeof(csrow->kobj)); - csrow->mci = mci; /* include container up link */ + edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev)); + kfree(dimm); +} - /* bump the mci instance's kobject's ref count */ - kobj = kobject_get(&mci->edac_mci_kobj); - if (!kobj) { - err = -ENODEV; - goto err_out; - } +static struct device_type dimm_attr_type = { + .groups = dimm_attr_groups, + .release = dimm_attr_release, +}; + +/* Create a DIMM object under specifed memory controller device */ +static int edac_create_dimm_object(struct mem_ctl_info *mci, + struct dimm_info *dimm, + int index) +{ + int err; + dimm->mci = mci; - /* Instanstiate the csrow object */ - err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci, - "csrow%d", index); - if (err) - goto err_release_top_kobj; + dimm->dev.type = &dimm_attr_type; + dimm->dev.bus = &mci->bus; + device_initialize(&dimm->dev); - /* At this point, to release a csrow kobj, one must - * call the kobject_put and allow that tear down - * to work the releasing - */ + dimm->dev.parent = &mci->dev; + if (mci->mem_is_per_rank) + dev_set_name(&dimm->dev, "rank%d", index); + else + dev_set_name(&dimm->dev, "dimm%d", index); + dev_set_drvdata(&dimm->dev, dimm); + pm_runtime_forbid(&mci->dev); - /* Create the dyanmic attribute files on this csrow, - * namely, the DIMM labels and the channel ce_count - */ - for (chan = 0; chan < csrow->nr_channels; chan++) { - err = edac_create_channel_files(&csrow->kobj, chan); - if (err) { - /* special case the unregister here */ - kobject_put(&csrow->kobj); - goto err_out; - } - } - kobject_uevent(&csrow->kobj, KOBJ_ADD); - return 0; + err = device_add(&dimm->dev); - /* error unwind stack */ -err_release_top_kobj: - kobject_put(&mci->edac_mci_kobj); + edac_dbg(0, "creating rank/dimm device %s\n", dev_name(&dimm->dev)); -err_out: return err; } -/* default sysfs methods and data structures for the main MCI kobject */ +/* + * Memory controller device + */ + +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) -static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, +static ssize_t mci_reset_counters_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { - int row, chan; - - mci->ue_noinfo_count = 0; - mci->ce_noinfo_count = 0; + struct mem_ctl_info *mci = to_mci(dev); + int cnt, row, chan, i; mci->ue_mc = 0; mci->ce_mc = 0; + mci->ue_noinfo_count = 0; + mci->ce_noinfo_count = 0; for (row = 0; row < mci->nr_csrows; row++) { - struct csrow_info *ri = &mci->csrows[row]; + struct csrow_info *ri = mci->csrows[row]; ri->ue_count = 0; ri->ce_count = 0; for (chan = 0; chan < ri->nr_channels; chan++) - ri->channels[chan].ce_count = 0; + ri->channels[chan]->ce_count = 0; + } + + cnt = 1; + for (i = 0; i < mci->n_layers; i++) { + cnt *= mci->layers[i].size; + memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32)); + memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32)); } mci->start_time = jiffies; @@ -451,9 +666,11 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, * Negative value still means that an error has occurred while setting * the scrub rate. */ -static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, +static ssize_t mci_sdram_scrub_rate_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); unsigned long bandwidth = 0; int new_bw = 0; @@ -476,8 +693,11 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, /* * ->get_sdram_scrub_rate() return value semantics same as above. */ -static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_sdram_scrub_rate_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); int bandwidth = 0; if (!mci->get_sdram_scrub_rate) @@ -493,45 +713,72 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) } /* default attribute files for the MCI object */ -static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ue_count_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ue_mc); } -static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ce_count_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ce_mc); } -static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ce_noinfo_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ce_noinfo_count); } -static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ue_noinfo_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%d\n", mci->ue_noinfo_count); } -static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_seconds_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ); } -static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_ctl_name_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); + return sprintf(data, "%s\n", mci->ctl_name); } -static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) +static ssize_t mci_size_mb_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); int total_pages = 0, csrow_idx, j; for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { - struct csrow_info *csrow = &mci->csrows[csrow_idx]; + struct csrow_info *csrow = mci->csrows[csrow_idx]; for (j = 0; j < csrow->nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; total_pages += dimm->nr_pages; } @@ -540,361 +787,187 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); } -#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj) -#define to_mcidev_attr(a) container_of(a,struct mcidev_sysfs_attribute,attr) - -/* MCI show/store functions for top most object */ -static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, - char *buffer) +static ssize_t mci_max_location_show(struct device *dev, + struct device_attribute *mattr, + char *data) { - struct mem_ctl_info *mem_ctl_info = to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); + struct mem_ctl_info *mci = to_mci(dev); + int i; + char *p = data; - if (mcidev_attr->show) - return mcidev_attr->show(mem_ctl_info, buffer); + for (i = 0; i < mci->n_layers; i++) { + p += sprintf(p, "%s %d ", + edac_layer_name[mci->layers[i].type], + mci->layers[i].size - 1); + } - return -EIO; + return p - data; } -static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +#ifdef CONFIG_EDAC_DEBUG +static ssize_t edac_fake_inject_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) { - struct mem_ctl_info *mem_ctl_info = to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->store) - return mcidev_attr->store(mem_ctl_info, buffer, count); + struct device *dev = file->private_data; + struct mem_ctl_info *mci = to_mci(dev); + static enum hw_event_mc_err_type type; + u16 errcount = mci->fake_inject_count; + + if (!errcount) + errcount = 1; + + type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED + : HW_EVENT_ERR_CORRECTED; + + printk(KERN_DEBUG + "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n", + errcount, + (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE", + errcount > 1 ? "s" : "", + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2] + ); + edac_mc_handle_error(type, mci, errcount, 0, 0, 0, + mci->fake_inject_layer[0], + mci->fake_inject_layer[1], + mci->fake_inject_layer[2], + "FAKE ERROR", "for EDAC testing only"); - return -EIO; + return count; } -/* Intermediate show/store table */ -static const struct sysfs_ops mci_ops = { - .show = mcidev_show, - .store = mcidev_store -}; +static int debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} -#define MCIDEV_ATTR(_name,_mode,_show,_store) \ -static struct mcidev_sysfs_attribute mci_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ +static const struct file_operations debug_fake_inject_fops = { + .open = debugfs_open, + .write = edac_fake_inject_write, + .llseek = generic_file_llseek, }; +#endif /* default Control file */ -MCIDEV_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); +DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store); /* default Attribute files */ -MCIDEV_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL); -MCIDEV_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL); -MCIDEV_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL); -MCIDEV_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); -MCIDEV_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); -MCIDEV_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); -MCIDEV_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); +DEVICE_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL); +DEVICE_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL); +DEVICE_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL); +DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL); +DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL); +DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL); +DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL); +DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL); /* memory scrubber attribute file */ -MCIDEV_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, +DEVICE_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show, mci_sdram_scrub_rate_store); -static struct mcidev_sysfs_attribute *mci_attr[] = { - &mci_attr_reset_counters, - &mci_attr_mc_name, - &mci_attr_size_mb, - &mci_attr_seconds_since_reset, - &mci_attr_ue_noinfo_count, - &mci_attr_ce_noinfo_count, - &mci_attr_ue_count, - &mci_attr_ce_count, - &mci_attr_sdram_scrub_rate, +static struct attribute *mci_attrs[] = { + &dev_attr_reset_counters.attr, + &dev_attr_mc_name.attr, + &dev_attr_size_mb.attr, + &dev_attr_seconds_since_reset.attr, + &dev_attr_ue_noinfo_count.attr, + &dev_attr_ce_noinfo_count.attr, + &dev_attr_ue_count.attr, + &dev_attr_ce_count.attr, + &dev_attr_sdram_scrub_rate.attr, + &dev_attr_max_location.attr, NULL }; +static struct attribute_group mci_attr_grp = { + .attrs = mci_attrs, +}; -/* - * Release of a MC controlling instance - * - * each MC control instance has the following resources upon entry: - * a) a ref count on the top memctl kobj - * b) a ref count on this module - * - * this function must decrement those ref counts and then - * issue a free on the instance's memory - */ -static void edac_mci_control_release(struct kobject *kobj) -{ - struct mem_ctl_info *mci; - - mci = to_mci(kobj); +static const struct attribute_group *mci_attr_groups[] = { + &mci_attr_grp, + NULL +}; - debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx); +static void mci_attr_release(struct device *dev) +{ + struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); - /* decrement the module ref count */ - module_put(mci->owner); + edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); + kfree(mci); } -static struct kobj_type ktype_mci = { - .release = edac_mci_control_release, - .sysfs_ops = &mci_ops, - .default_attrs = (struct attribute **)mci_attr, +static struct device_type mci_attr_type = { + .groups = mci_attr_groups, + .release = mci_attr_release, }; -/* EDAC memory controller sysfs kset: - * /sys/devices/system/edac/mc - */ -static struct kset *mc_kset; +#ifdef CONFIG_EDAC_DEBUG +static struct dentry *edac_debugfs; -/* - * edac_mc_register_sysfs_main_kobj - * - * setups and registers the main kobject for each mci - */ -int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci) +int __init edac_debugfs_init(void) { - struct kobject *kobj_mci; - int err; - - debugf1("%s()\n", __func__); - - kobj_mci = &mci->edac_mci_kobj; - - /* Init the mci's kobject */ - memset(kobj_mci, 0, sizeof(*kobj_mci)); - - /* Record which module 'owns' this control structure - * and bump the ref count of the module - */ - mci->owner = THIS_MODULE; - - /* bump ref count on this module */ - if (!try_module_get(mci->owner)) { - err = -ENODEV; - goto fail_out; - } - - /* this instance become part of the mc_kset */ - kobj_mci->kset = mc_kset; - - /* register the mc<id> kobject to the mc_kset */ - err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL, - "mc%d", mci->mc_idx); - if (err) { - debugf1("%s()Failed to register '.../edac/mc%d'\n", - __func__, mci->mc_idx); - goto kobj_reg_fail; + edac_debugfs = debugfs_create_dir("edac", NULL); + if (IS_ERR(edac_debugfs)) { + edac_debugfs = NULL; + return -ENOMEM; } - kobject_uevent(kobj_mci, KOBJ_ADD); - - /* At this point, to 'free' the control struct, - * edac_mc_unregister_sysfs_main_kobj() must be used - */ - - debugf1("%s() Registered '.../edac/mc%d' kobject\n", - __func__, mci->mc_idx); - return 0; - - /* Error exit stack */ - -kobj_reg_fail: - module_put(mci->owner); - -fail_out: - return err; -} - -/* - * edac_mc_register_sysfs_main_kobj - * - * tears down and the main mci kobject from the mc_kset - */ -void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci) -{ - debugf1("%s()\n", __func__); - - /* delete the kobj from the mc_kset */ - kobject_put(&mci->edac_mci_kobj); -} - -#define EDAC_DEVICE_SYMLINK "device" - -#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci) - -/* MCI show/store functions for top most object */ -static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr, - char *buffer) -{ - struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->show) - return mcidev_attr->show(mem_ctl_info, buffer); - - return -EIO; } -static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr, - const char *buffer, size_t count) +void __exit edac_debugfs_exit(void) { - struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj); - struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr); - - debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info); - - if (mcidev_attr->store) - return mcidev_attr->store(mem_ctl_info, buffer, count); - - return -EIO; + debugfs_remove(edac_debugfs); } -/* No memory to release for this kobj */ -static void edac_inst_grp_release(struct kobject *kobj) +int edac_create_debug_nodes(struct mem_ctl_info *mci) { - struct mcidev_sysfs_group_kobj *grp; - struct mem_ctl_info *mci; - - debugf1("%s()\n", __func__); - - grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj); - mci = grp->mci; -} - -/* Intermediate show/store table */ -static struct sysfs_ops inst_grp_ops = { - .show = inst_grp_show, - .store = inst_grp_store -}; - -/* the kobj_type instance for a instance group */ -static struct kobj_type ktype_inst_grp = { - .release = edac_inst_grp_release, - .sysfs_ops = &inst_grp_ops, -}; - + struct dentry *d, *parent; + char name[80]; + int i; -/* - * edac_create_mci_instance_attributes - * create MC driver specific attributes bellow an specified kobj - * This routine calls itself recursively, in order to create an entire - * object tree. - */ -static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci, - const struct mcidev_sysfs_attribute *sysfs_attrib, - struct kobject *kobj) -{ - int err; + if (!edac_debugfs) + return -ENODEV; - debugf4("%s()\n", __func__); - - while (sysfs_attrib) { - debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib); - if (sysfs_attrib->grp) { - struct mcidev_sysfs_group_kobj *grp_kobj; - - grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL); - if (!grp_kobj) - return -ENOMEM; - - grp_kobj->grp = sysfs_attrib->grp; - grp_kobj->mci = mci; - list_add_tail(&grp_kobj->list, &mci->grp_kobj_list); - - debugf0("%s() grp %s, mci %p\n", __func__, - sysfs_attrib->grp->name, mci); - - err = kobject_init_and_add(&grp_kobj->kobj, - &ktype_inst_grp, - &mci->edac_mci_kobj, - sysfs_attrib->grp->name); - if (err < 0) { - printk(KERN_ERR "kobject_init_and_add failed: %d\n", err); - return err; - } - err = edac_create_mci_instance_attributes(mci, - grp_kobj->grp->mcidev_attr, - &grp_kobj->kobj); - - if (err < 0) - return err; - } else if (sysfs_attrib->attr.name) { - debugf4("%s() file %s\n", __func__, - sysfs_attrib->attr.name); - - err = sysfs_create_file(kobj, &sysfs_attrib->attr); - if (err < 0) { - printk(KERN_ERR "sysfs_create_file failed: %d\n", err); - return err; - } - } else - break; - - sysfs_attrib++; + d = debugfs_create_dir(mci->dev.kobj.name, edac_debugfs); + if (!d) + return -ENOMEM; + parent = d; + + for (i = 0; i < mci->n_layers; i++) { + sprintf(name, "fake_inject_%s", + edac_layer_name[mci->layers[i].type]); + d = debugfs_create_u8(name, S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_layer[i]); + if (!d) + goto nomem; } - return 0; -} + d = debugfs_create_bool("fake_inject_ue", S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_ue); + if (!d) + goto nomem; -/* - * edac_remove_mci_instance_attributes - * remove MC driver specific attributes at the topmost level - * directory of this mci instance. - */ -static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, - const struct mcidev_sysfs_attribute *sysfs_attrib, - struct kobject *kobj, int count) -{ - struct mcidev_sysfs_group_kobj *grp_kobj, *tmp; + d = debugfs_create_u16("fake_inject_count", S_IRUGO | S_IWUSR, parent, + &mci->fake_inject_count); + if (!d) + goto nomem; - debugf1("%s()\n", __func__); - - /* - * loop if there are attributes and until we hit a NULL entry - * Remove first all the attributes - */ - while (sysfs_attrib) { - debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib); - if (sysfs_attrib->grp) { - debugf4("%s() seeking for group %s\n", - __func__, sysfs_attrib->grp->name); - list_for_each_entry(grp_kobj, - &mci->grp_kobj_list, list) { - debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp); - if (grp_kobj->grp == sysfs_attrib->grp) { - edac_remove_mci_instance_attributes(mci, - grp_kobj->grp->mcidev_attr, - &grp_kobj->kobj, count + 1); - debugf4("%s() group %s\n", __func__, - sysfs_attrib->grp->name); - kobject_put(&grp_kobj->kobj); - } - } - debugf4("%s() end of seeking for group %s\n", - __func__, sysfs_attrib->grp->name); - } else if (sysfs_attrib->attr.name) { - debugf4("%s() file %s\n", __func__, - sysfs_attrib->attr.name); - sysfs_remove_file(kobj, &sysfs_attrib->attr); - } else - break; - sysfs_attrib++; - } + d = debugfs_create_file("fake_inject", S_IWUSR, parent, + &mci->dev, + &debug_fake_inject_fops); + if (!d) + goto nomem; - /* Remove the group objects */ - if (count) - return; - list_for_each_entry_safe(grp_kobj, tmp, - &mci->grp_kobj_list, list) { - list_del(&grp_kobj->list); - kfree(grp_kobj); - } + mci->debugfs = parent; + return 0; +nomem: + debugfs_remove(mci->debugfs); + return -ENOMEM; } - +#endif /* * Create a new Memory Controller kobject instance, @@ -906,77 +979,87 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci, */ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) { - int i, j; - int err; - struct csrow_info *csrow; - struct kobject *kobj_mci = &mci->edac_mci_kobj; + int i, err; - debugf0("%s() idx=%d\n", __func__, mci->mc_idx); - - INIT_LIST_HEAD(&mci->grp_kobj_list); + /* + * The memory controller needs its own bus, in order to avoid + * namespace conflicts at /sys/bus/edac. + */ + mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); + if (!mci->bus.name) + return -ENOMEM; + edac_dbg(0, "creating bus %s\n", mci->bus.name); + err = bus_register(&mci->bus); + if (err < 0) + return err; - /* create a symlink for the device */ - err = sysfs_create_link(kobj_mci, &mci->dev->kobj, - EDAC_DEVICE_SYMLINK); - if (err) { - debugf1("%s() failure to create symlink\n", __func__); - goto fail0; + /* get the /sys/devices/system/edac subsys reference */ + mci->dev.type = &mci_attr_type; + device_initialize(&mci->dev); + + mci->dev.parent = mci_pdev; + mci->dev.bus = &mci->bus; + dev_set_name(&mci->dev, "mc%d", mci->mc_idx); + dev_set_drvdata(&mci->dev, mci); + pm_runtime_forbid(&mci->dev); + + edac_dbg(0, "creating device %s\n", dev_name(&mci->dev)); + err = device_add(&mci->dev); + if (err < 0) { + bus_unregister(&mci->bus); + kfree(mci->bus.name); + return err; } - /* If the low level driver desires some attributes, - * then create them now for the driver. + /* + * Create the dimm/rank devices */ - if (mci->mc_driver_sysfs_attributes) { - err = edac_create_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, - &mci->edac_mci_kobj); + for (i = 0; i < mci->tot_dimms; i++) { + struct dimm_info *dimm = mci->dimms[i]; + /* Only expose populated DIMMs */ + if (dimm->nr_pages == 0) + continue; +#ifdef CONFIG_EDAC_DEBUG + edac_dbg(1, "creating dimm%d, located at ", i); + if (edac_debug_level >= 1) { + int lay; + for (lay = 0; lay < mci->n_layers; lay++) + printk(KERN_CONT "%s %d ", + edac_layer_name[mci->layers[lay].type], + dimm->location[lay]); + printk(KERN_CONT "\n"); + } +#endif + err = edac_create_dimm_object(mci, dimm, i); if (err) { - debugf1("%s() failure to create mci attributes\n", - __func__); - goto fail0; + edac_dbg(1, "failure: create dimm %d obj\n", i); + goto fail; } } - /* Make directories for each CSROW object under the mc<id> kobject - */ - for (i = 0; i < mci->nr_csrows; i++) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - - if (nr_pages > 0) { - err = edac_create_csrow_object(mci, csrow, i); - if (err) { - debugf1("%s() failure: create csrow %d obj\n", - __func__, i); - goto fail1; - } - } - } +#ifdef CONFIG_EDAC_LEGACY_SYSFS + err = edac_create_csrow_objects(mci); + if (err < 0) + goto fail; +#endif +#ifdef CONFIG_EDAC_DEBUG + edac_create_debug_nodes(mci); +#endif return 0; -fail1: +fail: for (i--; i >= 0; i--) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - if (nr_pages > 0) - kobject_put(&mci->csrows[i].kobj); + struct dimm_info *dimm = mci->dimms[i]; + if (dimm->nr_pages == 0) + continue; + put_device(&dimm->dev); + device_del(&dimm->dev); } - - /* remove the mci instance's attributes, if any */ - edac_remove_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0); - - /* remove the symlink */ - sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK); - -fail0: + put_device(&mci->dev); + device_del(&mci->dev); + bus_unregister(&mci->bus); + kfree(mci->bus.name); return err; } @@ -985,98 +1068,84 @@ fail0: */ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { - struct csrow_info *csrow; - int i, j; - - debugf0("%s()\n", __func__); - - /* remove all csrow kobjects */ - debugf4("%s() unregister this mci kobj\n", __func__); - for (i = 0; i < mci->nr_csrows; i++) { - int nr_pages = 0; - - csrow = &mci->csrows[i]; - for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j].dimm->nr_pages; - if (nr_pages > 0) { - debugf0("%s() unreg csrow-%d\n", __func__, i); - kobject_put(&mci->csrows[i].kobj); - } - } + int i; - /* remove this mci instance's attribtes */ - if (mci->mc_driver_sysfs_attributes) { - debugf4("%s() unregister mci private attributes\n", __func__); - edac_remove_mci_instance_attributes(mci, - mci->mc_driver_sysfs_attributes, - &mci->edac_mci_kobj, 0); + edac_dbg(0, "\n"); + +#ifdef CONFIG_EDAC_DEBUG + debugfs_remove(mci->debugfs); +#endif +#ifdef CONFIG_EDAC_LEGACY_SYSFS + edac_delete_csrow_objects(mci); +#endif + + for (i = 0; i < mci->tot_dimms; i++) { + struct dimm_info *dimm = mci->dimms[i]; + if (dimm->nr_pages == 0) + continue; + edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev)); + put_device(&dimm->dev); + device_del(&dimm->dev); } - - /* remove the symlink */ - debugf4("%s() remove_link\n", __func__); - sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); - - /* unregister this instance's kobject */ - debugf4("%s() remove_mci_instance\n", __func__); - kobject_put(&mci->edac_mci_kobj); } +void edac_unregister_sysfs(struct mem_ctl_info *mci) +{ + edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); + put_device(&mci->dev); + device_del(&mci->dev); + bus_unregister(&mci->bus); + kfree(mci->bus.name); +} +static void mc_attr_release(struct device *dev) +{ + /* + * There's no container structure here, as this is just the mci + * parent device, used to create the /sys/devices/mc sysfs node. + * So, there are no attributes on it. + */ + edac_dbg(1, "Releasing device %s\n", dev_name(dev)); + kfree(dev); +} - +static struct device_type mc_attr_type = { + .release = mc_attr_release, +}; /* - * edac_setup_sysfs_mc_kset(void) - * - * Initialize the mc_kset for the 'mc' entry - * This requires creating the top 'mc' directory with a kset - * and its controls/attributes. - * - * To this 'mc' kset, instance 'mci' will be grouped as children. - * - * Return: 0 SUCCESS - * !0 FAILURE error code + * Init/exit code for the module. Basically, creates/removes /sys/class/rc */ -int edac_sysfs_setup_mc_kset(void) +int __init edac_mc_sysfs_init(void) { - int err = -EINVAL; struct bus_type *edac_subsys; - - debugf1("%s()\n", __func__); + int err; /* get the /sys/devices/system/edac subsys reference */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys error=%d\n", __func__, err); - goto fail_out; + edac_dbg(1, "no edac_subsys\n"); + return -EINVAL; } - /* Init the MC's kobject */ - mc_kset = kset_create_and_add("mc", NULL, &edac_subsys->dev_root->kobj); - if (!mc_kset) { - err = -ENOMEM; - debugf1("%s() Failed to register '.../edac/mc'\n", __func__); - goto fail_kset; - } + mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL); - debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); + mci_pdev->bus = edac_subsys; + mci_pdev->type = &mc_attr_type; + device_initialize(mci_pdev); + dev_set_name(mci_pdev, "mc"); - return 0; + err = device_add(mci_pdev); + if (err < 0) + return err; -fail_kset: - edac_put_sysfs_subsys(); + edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); -fail_out: - return err; + return 0; } -/* - * edac_sysfs_teardown_mc_kset - * - * deconstruct the mc_ket for memory controllers - */ -void edac_sysfs_teardown_mc_kset(void) +void __exit edac_mc_sysfs_exit(void) { - kset_unregister(mc_kset); + put_device(mci_pdev); + device_del(mci_pdev); edac_put_sysfs_subsys(); } - diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c index 5ddaa86d6a6..58a28d838f3 100644 --- a/drivers/edac/edac_module.c +++ b/drivers/edac/edac_module.c @@ -15,7 +15,7 @@ #include "edac_core.h" #include "edac_module.h" -#define EDAC_VERSION "Ver: 2.1.0" +#define EDAC_VERSION "Ver: 3.0.0" #ifdef CONFIG_EDAC_DEBUG /* Values of 0 to 4 will generate output */ @@ -90,26 +90,21 @@ static int __init edac_init(void) */ edac_pci_clear_parity_errors(); - /* - * now set up the mc_kset under the edac class object - */ - err = edac_sysfs_setup_mc_kset(); + err = edac_mc_sysfs_init(); if (err) goto error; + edac_debugfs_init(); + /* Setup/Initialize the workq for this core */ err = edac_workqueue_setup(); if (err) { edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n"); - goto workq_fail; + goto error; } return 0; - /* Error teardown stack */ -workq_fail: - edac_sysfs_teardown_mc_kset(); - error: return err; } @@ -120,11 +115,12 @@ error: */ static void __exit edac_exit(void) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* tear down the various subsystems */ edac_workqueue_teardown(); - edac_sysfs_teardown_mc_kset(); + edac_mc_sysfs_exit(); + edac_debugfs_exit(); } /* diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index 0ea7d14cb93..3d139c6e7fe 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -19,12 +19,12 @@ * * edac_mc objects */ -extern int edac_sysfs_setup_mc_kset(void); -extern void edac_sysfs_teardown_mc_kset(void); -extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci); -extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci); + /* on edac_mc_sysfs.c */ +int edac_mc_sysfs_init(void); +void edac_mc_sysfs_exit(void); extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci); extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci); +void edac_unregister_sysfs(struct mem_ctl_info *mci); extern int edac_get_log_ue(void); extern int edac_get_log_ce(void); extern int edac_get_panic_on_ue(void); @@ -34,6 +34,10 @@ extern int edac_mc_get_panic_on_ue(void); extern int edac_get_poll_msec(void); extern int edac_mc_get_poll_msec(void); +unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf, + unsigned len); + + /* on edac_device.c */ extern int edac_device_register_sysfs_main_kobj( struct edac_device_ctl_info *edac_dev); extern void edac_device_unregister_sysfs_main_kobj( @@ -53,6 +57,20 @@ extern void edac_mc_reset_delay_period(int value); extern void *edac_align_ptr(void **p, unsigned size, int n_elems); /* + * EDAC debugfs functions + */ +#ifdef CONFIG_EDAC_DEBUG +int edac_debugfs_init(void); +void edac_debugfs_exit(void); +#else +static inline int edac_debugfs_init(void) +{ + return -ENODEV; +} +static inline void edac_debugfs_exit(void) {} +#endif + +/* * EDAC PCI functions */ #ifdef CONFIG_PCI diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index f1ac8664988..ee87ef972ea 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -45,7 +45,7 @@ struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt, void *p = NULL, *pvt; unsigned int size; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); pci = edac_align_ptr(&p, sizeof(*pci), 1); pvt = edac_align_ptr(&p, 1, sz_pvt); @@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info); */ void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci) { - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); edac_pci_remove_sysfs(pci); } @@ -97,7 +97,7 @@ static struct edac_pci_ctl_info *find_edac_pci_by_dev(struct device *dev) struct edac_pci_ctl_info *pci; struct list_head *item; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); list_for_each(item, &edac_pci_list) { pci = list_entry(item, struct edac_pci_ctl_info, link); @@ -122,7 +122,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci) struct list_head *item, *insert_before; struct edac_pci_ctl_info *rover; - debugf1("%s()\n", __func__); + edac_dbg(1, "\n"); insert_before = &edac_pci_list; @@ -226,7 +226,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) int msec; unsigned long delay; - debugf3("%s() checking\n", __func__); + edac_dbg(3, "checking\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -261,7 +261,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, unsigned int msec) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); queue_delayed_work(edac_workqueue, &pci->work, @@ -276,7 +276,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { int status; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); status = cancel_delayed_work(&pci->work); if (status == 0) @@ -293,7 +293,7 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci, unsigned long value) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_pci_workq_teardown(pci); @@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_index); */ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); pci->pci_idx = edac_idx; pci->start_time = jiffies; @@ -393,7 +393,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) { struct edac_pci_ctl_info *pci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mutex_lock(&edac_pci_ctls_mutex); @@ -430,7 +430,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device); */ static void edac_pci_generic_check(struct edac_pci_ctl_info *pci) { - debugf4("%s()\n", __func__); + edac_dbg(4, "\n"); edac_pci_do_parity_check(); } @@ -475,7 +475,7 @@ struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev, pdata->edac_idx = edac_pci_idx++; if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + edac_dbg(3, "failed edac_pci_add_device()\n"); edac_pci_free_ctl_info(pci); return NULL; } @@ -491,7 +491,7 @@ EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl); */ void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci) { - debugf0("%s() pci mod=%s\n", __func__, pci->mod_name); + edac_dbg(0, "pci mod=%s\n", pci->mod_name); edac_pci_del_device(pci->dev); edac_pci_free_ctl_info(pci); diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 97f5064e399..e164c555a33 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -78,7 +78,7 @@ static void edac_pci_instance_release(struct kobject *kobj) { struct edac_pci_ctl_info *pci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* Form pointer to containing struct, the pci control struct */ pci = to_instance(kobj); @@ -161,7 +161,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) struct kobject *main_kobj; int err; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* First bump the ref count on the top main kobj, which will * track the number of PCI instances we have, and thus nest @@ -177,14 +177,13 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx) err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance, edac_pci_top_main_kobj, "pci%d", idx); if (err != 0) { - debugf2("%s() failed to register instance pci%d\n", - __func__, idx); + edac_dbg(2, "failed to register instance pci%d\n", idx); kobject_put(edac_pci_top_main_kobj); goto error_out; } kobject_uevent(&pci->kobj, KOBJ_ADD); - debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx); + edac_dbg(1, "Register instance 'pci%d' kobject\n", idx); return 0; @@ -201,7 +200,7 @@ error_out: static void edac_pci_unregister_sysfs_instance_kobj( struct edac_pci_ctl_info *pci) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* Unregister the instance kobject and allow its release * function release the main reference count and then @@ -317,7 +316,7 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { */ static void edac_pci_release_main_kobj(struct kobject *kobj) { - debugf0("%s() here to module_put(THIS_MODULE)\n", __func__); + edac_dbg(0, "here to module_put(THIS_MODULE)\n"); kfree(kobj); @@ -345,7 +344,7 @@ static int edac_pci_main_kobj_setup(void) int err; struct bus_type *edac_subsys; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* check and count if we have already created the main kobject */ if (atomic_inc_return(&edac_pci_sysfs_refcount) != 1) @@ -356,7 +355,7 @@ static int edac_pci_main_kobj_setup(void) */ edac_subsys = edac_get_sysfs_subsys(); if (edac_subsys == NULL) { - debugf1("%s() no edac_subsys\n", __func__); + edac_dbg(1, "no edac_subsys\n"); err = -ENODEV; goto decrement_count_fail; } @@ -366,14 +365,14 @@ static int edac_pci_main_kobj_setup(void) * level main kobj for EDAC PCI */ if (!try_module_get(THIS_MODULE)) { - debugf1("%s() try_module_get() failed\n", __func__); + edac_dbg(1, "try_module_get() failed\n"); err = -ENODEV; goto mod_get_fail; } edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); if (!edac_pci_top_main_kobj) { - debugf1("Failed to allocate\n"); + edac_dbg(1, "Failed to allocate\n"); err = -ENOMEM; goto kzalloc_fail; } @@ -383,7 +382,7 @@ static int edac_pci_main_kobj_setup(void) &ktype_edac_pci_main_kobj, &edac_subsys->dev_root->kobj, "pci"); if (err) { - debugf1("Failed to register '.../edac/pci'\n"); + edac_dbg(1, "Failed to register '.../edac/pci'\n"); goto kobject_init_and_add_fail; } @@ -392,7 +391,7 @@ static int edac_pci_main_kobj_setup(void) * must be used, for resources to be cleaned up properly */ kobject_uevent(edac_pci_top_main_kobj, KOBJ_ADD); - debugf1("Registered '.../edac/pci' kobject\n"); + edac_dbg(1, "Registered '.../edac/pci' kobject\n"); return 0; @@ -421,15 +420,14 @@ decrement_count_fail: */ static void edac_pci_main_kobj_teardown(void) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* Decrement the count and only if no more controller instances * are connected perform the unregisteration of the top level * main kobj */ if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) { - debugf0("%s() called kobject_put on main kobj\n", - __func__); + edac_dbg(0, "called kobject_put on main kobj\n"); kobject_put(edac_pci_top_main_kobj); } edac_put_sysfs_subsys(); @@ -446,7 +444,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) int err; struct kobject *edac_kobj = &pci->kobj; - debugf0("%s() idx=%d\n", __func__, pci->pci_idx); + edac_dbg(0, "idx=%d\n", pci->pci_idx); /* create the top main EDAC PCI kobject, IF needed */ err = edac_pci_main_kobj_setup(); @@ -460,8 +458,7 @@ int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci) err = sysfs_create_link(edac_kobj, &pci->dev->kobj, EDAC_PCI_SYMLINK); if (err) { - debugf0("%s() sysfs_create_link() returned err= %d\n", - __func__, err); + edac_dbg(0, "sysfs_create_link() returned err= %d\n", err); goto symlink_fail; } @@ -484,7 +481,7 @@ unregister_cleanup: */ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) { - debugf0("%s() index=%d\n", __func__, pci->pci_idx); + edac_dbg(0, "index=%d\n", pci->pci_idx); /* Remove the symlink */ sysfs_remove_link(&pci->kobj, EDAC_PCI_SYMLINK); @@ -496,7 +493,7 @@ void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci) * if this 'pci' is the last instance. * If it is, the main kobject will be unregistered as a result */ - debugf0("%s() calling edac_pci_main_kobj_teardown()\n", __func__); + edac_dbg(0, "calling edac_pci_main_kobj_teardown()\n"); edac_pci_main_kobj_teardown(); } @@ -572,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) local_irq_restore(flags); - debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); + edac_dbg(4, "PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); /* check the status reg for errors on boards NOT marked as broken * if broken, we cannot trust any of the status bits @@ -603,13 +600,15 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) } - debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev)); + edac_dbg(4, "PCI HEADER TYPE= 0x%02x %s\n", + header_type, dev_name(&dev->dev)); if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* On bridges, need to examine secondary status register */ status = get_pci_parity_status(dev, 1); - debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev)); + edac_dbg(4, "PCI SEC_STATUS= 0x%04x %s\n", + status, dev_name(&dev->dev)); /* check the secondary status reg for errors, * on NOT broken boards @@ -671,7 +670,7 @@ void edac_pci_do_parity_check(void) { int before_count; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* if policy has PCI check off, leave now */ if (!check_pci_errors) diff --git a/drivers/edac/highbank_l2_edac.c b/drivers/edac/highbank_l2_edac.c new file mode 100644 index 00000000000..e599b00c05a --- /dev/null +++ b/drivers/edac/highbank_l2_edac.c @@ -0,0 +1,149 @@ +/* + * Copyright 2011-2012 Calxeda, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/ctype.h> +#include <linux/edac.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/of_platform.h> + +#include "edac_core.h" +#include "edac_module.h" + +#define SR_CLR_SB_ECC_INTR 0x0 +#define SR_CLR_DB_ECC_INTR 0x4 + +struct hb_l2_drvdata { + void __iomem *base; + int sb_irq; + int db_irq; +}; + +static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id) +{ + struct edac_device_ctl_info *dci = dev_id; + struct hb_l2_drvdata *drvdata = dci->pvt_info; + + if (irq == drvdata->sb_irq) { + writel(1, drvdata->base + SR_CLR_SB_ECC_INTR); + edac_device_handle_ce(dci, 0, 0, dci->ctl_name); + } + if (irq == drvdata->db_irq) { + writel(1, drvdata->base + SR_CLR_DB_ECC_INTR); + edac_device_handle_ue(dci, 0, 0, dci->ctl_name); + } + + return IRQ_HANDLED; +} + +static int __devinit highbank_l2_err_probe(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci; + struct hb_l2_drvdata *drvdata; + struct resource *r; + int res = 0; + + dci = edac_device_alloc_ctl_info(sizeof(*drvdata), "cpu", + 1, "L", 1, 2, NULL, 0, 0); + if (!dci) + return -ENOMEM; + + drvdata = dci->pvt_info; + dci->dev = &pdev->dev; + platform_set_drvdata(pdev, dci); + + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) + return -ENOMEM; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + res = -ENODEV; + goto err; + } + + if (!devm_request_mem_region(&pdev->dev, r->start, + resource_size(r), dev_name(&pdev->dev))) { + dev_err(&pdev->dev, "Error while requesting mem region\n"); + res = -EBUSY; + goto err; + } + + drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!drvdata->base) { + dev_err(&pdev->dev, "Unable to map regs\n"); + res = -ENOMEM; + goto err; + } + + drvdata->db_irq = platform_get_irq(pdev, 0); + res = devm_request_irq(&pdev->dev, drvdata->db_irq, + highbank_l2_err_handler, + 0, dev_name(&pdev->dev), dci); + if (res < 0) + goto err; + + drvdata->sb_irq = platform_get_irq(pdev, 1); + res = devm_request_irq(&pdev->dev, drvdata->sb_irq, + highbank_l2_err_handler, + 0, dev_name(&pdev->dev), dci); + if (res < 0) + goto err; + + dci->mod_name = dev_name(&pdev->dev); + dci->dev_name = dev_name(&pdev->dev); + + if (edac_device_add_device(dci)) + goto err; + + devres_close_group(&pdev->dev, NULL); + return 0; +err: + devres_release_group(&pdev->dev, NULL); + edac_device_free_ctl_info(dci); + return res; +} + +static int highbank_l2_err_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); + + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(dci); + return 0; +} + +static const struct of_device_id hb_l2_err_of_match[] = { + { .compatible = "calxeda,hb-sregs-l2-ecc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, hb_l2_err_of_match); + +static struct platform_driver highbank_l2_edac_driver = { + .probe = highbank_l2_err_probe, + .remove = highbank_l2_err_remove, + .driver = { + .name = "hb_l2_edac", + .of_match_table = hb_l2_err_of_match, + }, +}; + +module_platform_driver(highbank_l2_edac_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Calxeda, Inc."); +MODULE_DESCRIPTION("EDAC Driver for Calxeda Highbank L2 Cache"); diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c new file mode 100644 index 00000000000..c769f477fd2 --- /dev/null +++ b/drivers/edac/highbank_mc_edac.c @@ -0,0 +1,264 @@ +/* + * Copyright 2011-2012 Calxeda, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/ctype.h> +#include <linux/edac.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/of_platform.h> +#include <linux/uaccess.h> + +#include "edac_core.h" +#include "edac_module.h" + +/* DDR Ctrlr Error Registers */ +#define HB_DDR_ECC_OPT 0x128 +#define HB_DDR_ECC_U_ERR_ADDR 0x130 +#define HB_DDR_ECC_U_ERR_STAT 0x134 +#define HB_DDR_ECC_U_ERR_DATAL 0x138 +#define HB_DDR_ECC_U_ERR_DATAH 0x13c +#define HB_DDR_ECC_C_ERR_ADDR 0x140 +#define HB_DDR_ECC_C_ERR_STAT 0x144 +#define HB_DDR_ECC_C_ERR_DATAL 0x148 +#define HB_DDR_ECC_C_ERR_DATAH 0x14c +#define HB_DDR_ECC_INT_STATUS 0x180 +#define HB_DDR_ECC_INT_ACK 0x184 +#define HB_DDR_ECC_U_ERR_ID 0x424 +#define HB_DDR_ECC_C_ERR_ID 0x428 + +#define HB_DDR_ECC_INT_STAT_CE 0x8 +#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10 +#define HB_DDR_ECC_INT_STAT_UE 0x20 +#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40 + +#define HB_DDR_ECC_OPT_MODE_MASK 0x3 +#define HB_DDR_ECC_OPT_FWC 0x100 +#define HB_DDR_ECC_OPT_XOR_SHIFT 16 + +struct hb_mc_drvdata { + void __iomem *mc_vbase; +}; + +static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) +{ + struct mem_ctl_info *mci = dev_id; + struct hb_mc_drvdata *drvdata = mci->pvt_info; + u32 status, err_addr; + + /* Read the interrupt status register */ + status = readl(drvdata->mc_vbase + HB_DDR_ECC_INT_STATUS); + + if (status & HB_DDR_ECC_INT_STAT_UE) { + err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_U_ERR_ADDR); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + err_addr >> PAGE_SHIFT, + err_addr & ~PAGE_MASK, 0, + 0, 0, -1, + mci->ctl_name, ""); + } + if (status & HB_DDR_ECC_INT_STAT_CE) { + u32 syndrome = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_STAT); + syndrome = (syndrome >> 8) & 0xff; + err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_ADDR); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + err_addr >> PAGE_SHIFT, + err_addr & ~PAGE_MASK, syndrome, + 0, 0, -1, + mci->ctl_name, ""); + } + + /* clear the error, clears the interrupt */ + writel(status, drvdata->mc_vbase + HB_DDR_ECC_INT_ACK); + return IRQ_HANDLED; +} + +#ifdef CONFIG_EDAC_DEBUG +static ssize_t highbank_mc_err_inject_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct mem_ctl_info *mci = file->private_data; + struct hb_mc_drvdata *pdata = mci->pvt_info; + char buf[32]; + size_t buf_size; + u32 reg; + u8 synd; + + buf_size = min(count, (sizeof(buf)-1)); + if (copy_from_user(buf, data, buf_size)) + return -EFAULT; + buf[buf_size] = 0; + + if (!kstrtou8(buf, 16, &synd)) { + reg = readl(pdata->mc_vbase + HB_DDR_ECC_OPT); + reg &= HB_DDR_ECC_OPT_MODE_MASK; + reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC; + writel(reg, pdata->mc_vbase + HB_DDR_ECC_OPT); + } + + return count; +} + +static int debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static const struct file_operations highbank_mc_debug_inject_fops = { + .open = debugfs_open, + .write = highbank_mc_err_inject_write, + .llseek = generic_file_llseek, +}; + +static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) +{ + if (mci->debugfs) + debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci, + &highbank_mc_debug_inject_fops); +; +} +#else +static void __devinit highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) +{} +#endif + +static int __devinit highbank_mc_probe(struct platform_device *pdev) +{ + struct edac_mc_layer layers[2]; + struct mem_ctl_info *mci; + struct hb_mc_drvdata *drvdata; + struct dimm_info *dimm; + struct resource *r; + u32 control; + int irq; + int res = 0; + + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = 1; + layers[0].is_virt_csrow = true; + layers[1].type = EDAC_MC_LAYER_CHANNEL; + layers[1].size = 1; + layers[1].is_virt_csrow = false; + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, + sizeof(struct hb_mc_drvdata)); + if (!mci) + return -ENOMEM; + + mci->pdev = &pdev->dev; + drvdata = mci->pvt_info; + platform_set_drvdata(pdev, mci); + + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) + return -ENOMEM; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + res = -ENODEV; + goto err; + } + + if (!devm_request_mem_region(&pdev->dev, r->start, + resource_size(r), dev_name(&pdev->dev))) { + dev_err(&pdev->dev, "Error while requesting mem region\n"); + res = -EBUSY; + goto err; + } + + drvdata->mc_vbase = devm_ioremap(&pdev->dev, + r->start, resource_size(r)); + if (!drvdata->mc_vbase) { + dev_err(&pdev->dev, "Unable to map regs\n"); + res = -ENOMEM; + goto err; + } + + control = readl(drvdata->mc_vbase + HB_DDR_ECC_OPT) & 0x3; + if (!control || (control == 0x2)) { + dev_err(&pdev->dev, "No ECC present, or ECC disabled\n"); + res = -ENODEV; + goto err; + } + + irq = platform_get_irq(pdev, 0); + res = devm_request_irq(&pdev->dev, irq, highbank_mc_err_handler, + 0, dev_name(&pdev->dev), mci); + if (res < 0) { + dev_err(&pdev->dev, "Unable to request irq %d\n", irq); + goto err; + } + + mci->mtype_cap = MEM_FLAG_DDR3; + mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = dev_name(&pdev->dev); + mci->mod_ver = "1"; + mci->ctl_name = dev_name(&pdev->dev); + mci->scrub_mode = SCRUB_SW_SRC; + + /* Only a single 4GB DIMM is supported */ + dimm = *mci->dimms; + dimm->nr_pages = (~0UL >> PAGE_SHIFT) + 1; + dimm->grain = 8; + dimm->dtype = DEV_X8; + dimm->mtype = MEM_DDR3; + dimm->edac_mode = EDAC_SECDED; + + res = edac_mc_add_mc(mci); + if (res < 0) + goto err; + + highbank_mc_create_debugfs_nodes(mci); + + devres_close_group(&pdev->dev, NULL); + return 0; +err: + devres_release_group(&pdev->dev, NULL); + edac_mc_free(mci); + return res; +} + +static int highbank_mc_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + return 0; +} + +static const struct of_device_id hb_ddr_ctrl_of_match[] = { + { .compatible = "calxeda,hb-ddr-ctrl", }, + {}, +}; +MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match); + +static struct platform_driver highbank_mc_edac_driver = { + .probe = highbank_mc_probe, + .remove = highbank_mc_remove, + .driver = { + .name = "hb_mc_edac", + .of_match_table = hb_ddr_ctrl_of_match, + }, +}; + +module_platform_driver(highbank_mc_edac_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Calxeda, Inc."); +MODULE_DESCRIPTION("EDAC Driver for Calxeda Highbank"); diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index 8ad1744faac..d3d19cc4e9a 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -194,7 +194,7 @@ static void i3000_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -236,7 +236,7 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, int row, multi_chan, channel; unsigned long pfn, offset; - multi_chan = mci->csrows[0].nr_channels - 1; + multi_chan = mci->csrows[0]->nr_channels - 1; if (!(info->errsts & I3000_ERRSTS_BITS)) return 0; @@ -245,9 +245,9 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -258,15 +258,15 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, row = edac_mc_find_csrow_by_page(mci, pfn); if (info->errsts & I3000_ERRSTS_UE) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, pfn, offset, 0, row, -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, offset, info->derrsyn, row, multi_chan ? channel : 0, -1, - "i3000 CE", "", NULL); + "i3000 CE", ""); return 1; } @@ -275,7 +275,7 @@ static void i3000_check(struct mem_ctl_info *mci) { struct i3000_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i3000_get_error_info(mci, &info); i3000_process_error_info(mci, &info, 1); } @@ -322,7 +322,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) unsigned long mchbar; void __iomem *window; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar); mchbar &= I3000_MCHBAR_MASK; @@ -366,9 +366,9 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + edac_dbg(3, "MC: init mci\n"); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; @@ -393,14 +393,13 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) { u8 value; u32 cumul_size; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; value = drb[i]; cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); if (interleaved) cumul_size <<= 1; - debugf3("MC: %s(): (%d) cumul_size 0x%x\n", - __func__, i, cumul_size); + edac_dbg(3, "MC: (%d) cumul_size 0x%x\n", i, cumul_size); if (cumul_size == last_cumul_size) continue; @@ -410,7 +409,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) last_cumul_size = cumul_size; for (j = 0; j < nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_channels; dimm->grain = I3000_DEAP_GRAIN; @@ -429,7 +428,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } @@ -445,7 +444,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -461,7 +460,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -477,7 +476,7 @@ static void __devexit i3000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (i3000_pci) edac_pci_release_generic_ctl(i3000_pci); @@ -511,7 +510,7 @@ static int __init i3000_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -525,14 +524,14 @@ static int __init i3000_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_3000_HB, NULL); if (!mci_pdev) { - debugf0("i3000 pci_get_device fail\n"); + edac_dbg(0, "i3000 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = i3000_init_one(mci_pdev, i3000_pci_tbl); if (pci_rc < 0) { - debugf0("i3000 init fail\n"); + edac_dbg(0, "i3000 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -552,7 +551,7 @@ fail0: static void __exit i3000_exit(void) { - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&i3000_driver); if (!i3000_registered) { diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index bbe43ef7182..47180a08eda 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -110,10 +110,10 @@ static int how_many_channels(struct pci_dev *pdev) pci_read_config_byte(pdev, I3200_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ - debugf0("In single channel mode.\n"); + edac_dbg(0, "In single channel mode\n"); return 1; } else { - debugf0("In dual channel mode.\n"); + edac_dbg(0, "In dual channel mode\n"); return 2; } } @@ -159,7 +159,7 @@ static void i3200_clear_error_info(struct mem_ctl_info *mci) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * Clear any error bits. @@ -176,7 +176,7 @@ static void i3200_get_and_clear_error_info(struct mem_ctl_info *mci, struct i3200_priv *priv = mci->pvt_info; void __iomem *window = priv->window; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -218,25 +218,25 @@ static void i3200_process_error_info(struct mem_ctl_info *mci, return; if ((info->errsts ^ info->errsts2) & I3200_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } for (channel = 0; channel < nr_channels; channel++) { log = info->eccerrlog[channel]; if (log & I3200_ECCERRLOG_UE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); } else if (log & I3200_ECCERRLOG_CE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, - "i3000 UE", "", NULL); + "i3000 UE", ""); } } } @@ -245,7 +245,7 @@ static void i3200_check(struct mem_ctl_info *mci) { struct i3200_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i3200_get_and_clear_error_info(mci, &info); i3200_process_error_info(mci, &info); } @@ -332,7 +332,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) void __iomem *window; struct i3200_priv *priv; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); window = i3200_map_mchbar(pdev); if (!window) @@ -352,9 +352,9 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + edac_dbg(3, "MC: init mci\n"); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; @@ -379,7 +379,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) */ for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; nr_pages = drb_to_nr_pages(drbs, stacked, i / I3200_RANKS_PER_CHANNEL, @@ -389,7 +389,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) continue; for (j = 0; j < nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_channels; dimm->grain = nr_pages << PAGE_SHIFT; @@ -403,12 +403,12 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -424,7 +424,7 @@ static int __devinit i3200_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -441,7 +441,7 @@ static void __devexit i3200_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i3200_priv *priv; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -475,7 +475,7 @@ static int __init i3200_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -489,14 +489,14 @@ static int __init i3200_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_3200_HB, NULL); if (!mci_pdev) { - debugf0("i3200 pci_get_device fail\n"); + edac_dbg(0, "i3200 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = i3200_init_one(mci_pdev, i3200_pci_tbl); if (pci_rc < 0) { - debugf0("i3200 init fail\n"); + edac_dbg(0, "i3200 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -516,7 +516,7 @@ fail0: static void __exit i3200_exit(void) { - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&i3200_driver); if (!i3200_registered) { diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 11ea835f155..39c63757c2a 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -273,7 +273,7 @@ #define CHANNELS_PER_BRANCH 2 #define MAX_BRANCHES 2 -/* Defines to extract the vaious fields from the +/* Defines to extract the various fields from the * MTRx - Memory Technology Registers */ #define MTR_DIMMS_PRESENT(mtr) ((mtr) & (0x1 << 8)) @@ -287,22 +287,6 @@ #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) -#ifdef CONFIG_EDAC_DEBUG -static char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "reserved" -}; - -static char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /* enables the report of miscellaneous messages as CE errors - default off */ static int misc_messages; @@ -344,7 +328,13 @@ struct i5000_pvt { struct pci_dev *branch_1; /* 22.0 */ u16 tolm; /* top of low memory */ - u64 ambase; /* AMB BAR */ + union { + u64 ambase; /* AMB BAR */ + struct { + u32 ambase_bottom; + u32 ambase_top; + } u __packed; + }; u16 mir0, mir1, mir2; @@ -494,10 +484,9 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, ras = NREC_RAS(info->nrecmemb); cas = NREC_CAS(info->nrecmemb); - debugf0("\t\tCSROW= %d Channel= %d " - "(DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channel= %d (DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, bank, + rdwr ? "Write" : "Read", ras, cas); /* Only 1 bit will be on */ switch (allErrors) { @@ -536,10 +525,10 @@ static void i5000_process_fatal_error_info(struct mem_ctl_info *mci, bank, ras, cas, allErrors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0, channel >> 1, channel & 1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* @@ -574,7 +563,7 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, /* ONLY ONE of the possible error bits will be set, as per the docs */ ue_errors = allErrors & FERR_NF_UNCORRECTABLE; if (ue_errors) { - debugf0("\tUncorrected bits= 0x%x\n", ue_errors); + edac_dbg(0, "\tUncorrected bits= 0x%x\n", ue_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); @@ -590,11 +579,9 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, ras = NREC_RAS(info->nrecmemb); cas = NREC_CAS(info->nrecmemb); - debugf0 - ("\t\tCSROW= %d Channels= %d,%d (Branch= %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, channel + 1, branch >> 1, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channels= %d,%d (Branch= %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, channel + 1, branch >> 1, bank, + rdwr ? "Write" : "Read", ras, cas); switch (ue_errors) { case FERR_NF_M12ERR: @@ -637,16 +624,16 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, rank, bank, ras, cas, ue_errors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, channel >> 1, -1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* Check correctable errors */ ce_errors = allErrors & FERR_NF_CORRECTABLE; if (ce_errors) { - debugf0("\tCorrected bits= 0x%x\n", ce_errors); + edac_dbg(0, "\tCorrected bits= 0x%x\n", ce_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); @@ -664,10 +651,9 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, ras = REC_RAS(info->recmemb); cas = REC_CAS(info->recmemb); - debugf0("\t\tCSROW= %d Channel= %d (Branch %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, branch >> 1, bank, - rdwr ? "Write" : "Read", ras, cas); + edac_dbg(0, "\t\tCSROW= %d Channel= %d (Branch %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, branch >> 1, bank, + rdwr ? "Write" : "Read", ras, cas); switch (ce_errors) { case FERR_NF_M17ERR: @@ -692,10 +678,10 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, channel >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } if (!misc_messages) @@ -738,9 +724,9 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, "Err=%#x (%s)", misc_errors, specific); /* Call the helper to output message */ - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, branch >> 1, -1, -1, - "Misc error", msg, NULL); + "Misc error", msg); } } @@ -779,7 +765,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci) static void i5000_check_error(struct mem_ctl_info *mci) { struct i5000_error_info info; - debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + edac_dbg(4, "MC%d\n", mci->mc_idx); i5000_get_error_info(mci, &info); i5000_process_error_info(mci, &info, 1); } @@ -850,15 +836,16 @@ static int i5000_get_devices(struct mem_ctl_info *mci, int dev_idx) pvt->fsb_error_regs = pdev; - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->system_address), - pvt->system_address->vendor, pvt->system_address->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->branchmap_werrors), - pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->fsb_error_regs), - pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->system_address), + pvt->system_address->vendor, pvt->system_address->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->branchmap_werrors), + pvt->branchmap_werrors->vendor, + pvt->branchmap_werrors->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->fsb_error_regs), + pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); pdev = NULL; pdev = pci_get_device(PCI_VENDOR_ID_INTEL, @@ -981,16 +968,25 @@ static void decode_mtr(int slot_row, u16 mtr) ans = MTR_DIMMS_PRESENT(mtr); - debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d=0x%x: DIMMs are %sPresent\n", + slot_row, mtr, ans ? "" : "NOT "); if (!ans) return; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANK(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "reserved"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5000_pvt *pvt, int slot, int channel, @@ -1061,7 +1057,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) "--------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1082,7 +1078,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) } p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1092,7 +1088,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) "--------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1105,7 +1101,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1118,7 +1114,7 @@ static void calculate_dimm_size(struct i5000_pvt *pvt) } /* output the last message and free buffer */ - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); kfree(mem_buffer); } @@ -1141,24 +1137,25 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pvt = mci->pvt_info; pci_read_config_dword(pvt->system_address, AMBASE, - (u32 *) & pvt->ambase); + &pvt->u.ambase_bottom); pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32), - ((u32 *) & pvt->ambase) + sizeof(u32)); + &pvt->u.ambase_top); maxdimmperch = pvt->maxdimmperch; maxch = pvt->maxch; - debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", - (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); + edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", + (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); /* Get the Branch Map regs */ pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = pvt->tolm << 28; - debugf2("Actual TOLM byte addr=%u (0x%x)\n", actual_tolm, actual_tolm); + edac_dbg(2, "Actual TOLM byte addr=%u (0x%x)\n", + actual_tolm, actual_tolm); pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0); pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1); @@ -1168,15 +1165,18 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) limit = (pvt->mir0 >> 4) & 0x0FFF; way0 = pvt->mir0 & 0x1; way1 = pvt->mir0 & 0x2; - debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir1 >> 4) & 0x0FFF; way0 = pvt->mir1 & 0x1; way1 = pvt->mir1 & 0x2; - debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir2 >> 4) & 0x0FFF; way0 = pvt->mir2 & 0x1; way1 = pvt->mir2 & 0x2; - debugf2("MIR2: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR2: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); /* Get the MTR[0-3] regs */ for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { @@ -1185,31 +1185,31 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_word(pvt->branch_0, where, &pvt->b0_mtr[slot_row]); - debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where, - pvt->b0_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B0 value=0x%x\n", + slot_row, where, pvt->b0_mtr[slot_row]); if (pvt->maxch >= CHANNELS_PER_BRANCH) { pci_read_config_word(pvt->branch_1, where, &pvt->b1_mtr[slot_row]); - debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, - where, pvt->b1_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B1 value=0x%x\n", + slot_row, where, pvt->b1_mtr[slot_row]); } else { pvt->b1_mtr[slot_row] = 0; } } /* Read and dump branch 0's MTRs */ - debugf2("\nMemory Technology Registers:\n"); - debugf2(" Branch 0:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); + edac_dbg(2, " Branch 0:\n"); for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { decode_mtr(slot_row, pvt->b0_mtr[slot_row]); } pci_read_config_word(pvt->branch_0, AMB_PRESENT_0, &pvt->b0_ambpresent0); - debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); pci_read_config_word(pvt->branch_0, AMB_PRESENT_1, &pvt->b0_ambpresent1); - debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); /* Only if we have 2 branchs (4 channels) */ if (pvt->maxch < CHANNELS_PER_BRANCH) { @@ -1217,18 +1217,18 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) pvt->b1_ambpresent1 = 0; } else { /* Read and dump branch 1's MTRs */ - debugf2(" Branch 1:\n"); + edac_dbg(2, " Branch 1:\n"); for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) { decode_mtr(slot_row, pvt->b1_mtr[slot_row]); } pci_read_config_word(pvt->branch_1, AMB_PRESENT_0, &pvt->b1_ambpresent0); - debugf2("\t\tAMB-Branch 1-present0 0x%x:\n", - pvt->b1_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 1-present0 0x%x:\n", + pvt->b1_ambpresent0); pci_read_config_word(pvt->branch_1, AMB_PRESENT_1, &pvt->b1_ambpresent1); - debugf2("\t\tAMB-Branch 1-present1 0x%x:\n", - pvt->b1_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 1-present1 0x%x:\n", + pvt->b1_ambpresent1); } /* Go and determine the size of each DIMM and place in an @@ -1363,10 +1363,9 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) int num_channels; int num_dimms_per_channel; - debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, __func__, - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1388,8 +1387,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, &num_channels); - debugf0("MC: %s(): Number of Branches=2 Channels= %d DIMMS= %d\n", - __func__, num_channels, num_dimms_per_channel); + edac_dbg(0, "MC: Number of Branches=2 Channels= %d DIMMS= %d\n", + num_channels, num_dimms_per_channel); /* allocate a new MC control structure */ @@ -1406,10 +1405,9 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - kobject_get(&mci->edac_mci_kobj); - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->system_address = pdev; /* Record this device in our private */ @@ -1439,19 +1437,16 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) /* initialize the MC control structure 'csrows' table * with the mapping and control information */ if (i5000_init_csrows(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i5000_init_csrows() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i5000_init_csrows() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i5000_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", - __FILE__, __func__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1479,7 +1474,6 @@ fail1: i5000_put_devices(mci); fail0: - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); return -ENODEV; } @@ -1496,7 +1490,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(0, "MC:\n"); /* wake up device */ rc = pci_enable_device(pdev); @@ -1515,7 +1509,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + edac_dbg(0, "\n"); if (i5000_pci) edac_pci_release_generic_ctl(i5000_pci); @@ -1525,7 +1519,6 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) /* retrieve references to resources, and free those resources */ i5000_put_devices(mci); - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); } @@ -1562,7 +1555,7 @@ static int __init i5000_init(void) { int pci_rc; - debugf2("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(2, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1578,7 +1571,7 @@ static int __init i5000_init(void) */ static void __exit i5000_exit(void) { - debugf2("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(2, "MC:\n"); pci_unregister_driver(&i5000_driver); } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index e9e7c2a29dc..c4b5e5f868e 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -431,10 +431,10 @@ static void i5100_handle_ce(struct mem_ctl_info *mci, "bank %u, cas %u, ras %u\n", bank, cas, ras); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, syndrome, chan, rank, -1, - msg, detail, NULL); + msg, detail); } static void i5100_handle_ue(struct mem_ctl_info *mci, @@ -453,10 +453,10 @@ static void i5100_handle_ue(struct mem_ctl_info *mci, "bank %u, cas %u, ras %u\n", bank, cas, ras); - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, syndrome, chan, rank, -1, - msg, detail, NULL); + msg, detail); } static void i5100_read_log(struct mem_ctl_info *mci, int chan, @@ -859,8 +859,8 @@ static void __devinit i5100_init_csrows(struct mem_ctl_info *mci) i5100_rank_to_slot(mci, chan, rank)); } - debugf2("dimm channel %d, rank %d, size %ld\n", - chan, rank, (long)PAGES_TO_MiB(npages)); + edac_dbg(2, "dimm channel %d, rank %d, size %ld\n", + chan, rank, (long)PAGES_TO_MiB(npages)); } } @@ -943,7 +943,7 @@ static int __devinit i5100_init_one(struct pci_dev *pdev, goto bail_disable_ch1; } - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; priv = mci->pvt_info; priv->ranksperchan = ranksperch; diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 6640c29e188..277246998b8 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c @@ -300,24 +300,6 @@ static inline int extract_fbdchan_indx(u32 x) return (x>>28) & 0x3; } -#ifdef CONFIG_EDAC_DEBUG -/* MTR NUMROW */ -static const char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "65,536 - 16 rows" -}; - -/* MTR NUMCOL */ -static const char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /* Device name and register DID (Device ID) */ struct i5400_dev_info { const char *ctl_name; /* name for this device */ @@ -345,7 +327,13 @@ struct i5400_pvt { struct pci_dev *branch_1; /* 22.0 */ u16 tolm; /* top of low memory */ - u64 ambase; /* AMB BAR */ + union { + u64 ambase; /* AMB BAR */ + struct { + u32 ambase_bottom; + u32 ambase_top; + } u __packed; + }; u16 mir0, mir1; @@ -560,10 +548,9 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, ras = nrec_ras(info); cas = nrec_cas(info); - debugf0("\t\tDIMM= %d Channels= %d,%d (Branch= %d " - "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, channel + 1, branch >> 1, bank, - buf_id, rdwr_str(rdwr), ras, cas); + edac_dbg(0, "\t\tDIMM= %d Channels= %d,%d (Branch= %d DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, channel + 1, branch >> 1, bank, + buf_id, rdwr_str(rdwr), ras, cas); /* Only 1 bit will be on */ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); @@ -573,10 +560,10 @@ static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci, "Bank=%d Buffer ID = %d RAS=%d CAS=%d Err=0x%lx (%s)", bank, buf_id, ras, cas, allErrors, error_name[errnum]); - edac_mc_handle_error(tp_event, mci, 0, 0, 0, + edac_mc_handle_error(tp_event, mci, 1, 0, 0, 0, branch >> 1, -1, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); } /* @@ -613,7 +600,7 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Correctable errors */ if (allErrors & ERROR_NF_CORRECTABLE) { - debugf0("\tCorrected bits= 0x%lx\n", allErrors); + edac_dbg(0, "\tCorrected bits= 0x%lx\n", allErrors); branch = extract_fbdchan_indx(info->ferr_nf_fbd); @@ -634,10 +621,9 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, /* Only 1 bit will be on */ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name)); - debugf0("\t\tDIMM= %d Channel= %d (Branch %d " - "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", - rank, channel, branch >> 1, bank, - rdwr_str(rdwr), ras, cas); + edac_dbg(0, "\t\tDIMM= %d Channel= %d (Branch %d DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n", + rank, channel, branch >> 1, bank, + rdwr_str(rdwr), ras, cas); /* Form out message */ snprintf(msg, sizeof(msg), @@ -646,10 +632,10 @@ static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci, branch >> 1, bank, rdwr_str(rdwr), ras, cas, allErrors, error_name[errnum]); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, branch >> 1, channel % 2, rank, rdwr ? "Write error" : "Read error", - msg, NULL); + msg); return; } @@ -700,7 +686,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci) static void i5400_check_error(struct mem_ctl_info *mci) { struct i5400_error_info info; - debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + edac_dbg(4, "MC%d\n", mci->mc_idx); i5400_get_error_info(mci, &info); i5400_process_error_info(mci, &info); } @@ -786,15 +772,16 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) } pvt->fsb_error_regs = pdev; - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->system_address), - pvt->system_address->vendor, pvt->system_address->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->branchmap_werrors), - pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->fsb_error_regs), - pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->system_address), + pvt->system_address->vendor, pvt->system_address->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->branchmap_werrors), + pvt->branchmap_werrors->vendor, + pvt->branchmap_werrors->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->fsb_error_regs), + pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device); pvt->branch_0 = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0, NULL); @@ -882,8 +869,8 @@ static int determine_mtr(struct i5400_pvt *pvt, int dimm, int channel) n = dimm; if (n >= DIMMS_PER_CHANNEL) { - debugf0("ERROR: trying to access an invalid dimm: %d\n", - dimm); + edac_dbg(0, "ERROR: trying to access an invalid dimm: %d\n", + dimm); return 0; } @@ -903,20 +890,29 @@ static void decode_mtr(int slot_row, u16 mtr) ans = MTR_DIMMS_PRESENT(mtr); - debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d=0x%x: DIMMs are %sPresent\n", + slot_row, mtr, ans ? "" : "NOT "); if (!ans) return; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - - debugf2("\t\tELECTRICAL THROTTLING is %s\n", - MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); - - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + + edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n", + MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); + + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANK(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); } static void handle_channel(struct i5400_pvt *pvt, int dimm, int channel, @@ -989,7 +985,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) "-------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1004,7 +1000,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; } @@ -1014,7 +1010,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) "-------------------------------"); p += n; space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1029,7 +1025,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) } space -= n; - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); p = mem_buffer; space = PAGE_SIZE; @@ -1042,7 +1038,7 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) } /* output the last message and free buffer */ - debugf2("%s\n", mem_buffer); + edac_dbg(2, "%s\n", mem_buffer); kfree(mem_buffer); } @@ -1065,25 +1061,25 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) pvt = mci->pvt_info; pci_read_config_dword(pvt->system_address, AMBASE, - (u32 *) &pvt->ambase); + &pvt->u.ambase_bottom); pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32), - ((u32 *) &pvt->ambase) + sizeof(u32)); + &pvt->u.ambase_top); maxdimmperch = pvt->maxdimmperch; maxch = pvt->maxch; - debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", - (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); + edac_dbg(2, "AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n", + (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch); /* Get the Branch Map regs */ pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "\nTOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); - debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", - actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n", + actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0); pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1); @@ -1092,11 +1088,13 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) limit = (pvt->mir0 >> 4) & 0x0fff; way0 = pvt->mir0 & 0x1; way1 = pvt->mir0 & 0x2; - debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); limit = (pvt->mir1 >> 4) & 0xfff; way0 = pvt->mir1 & 0x1; way1 = pvt->mir1 & 0x2; - debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0); + edac_dbg(2, "MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", + limit, way1, way0); /* Get the set of MTR[0-3] regs by each branch */ for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) { @@ -1106,8 +1104,8 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_word(pvt->branch_0, where, &pvt->b0_mtr[slot_row]); - debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where, - pvt->b0_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B0 value=0x%x\n", + slot_row, where, pvt->b0_mtr[slot_row]); if (pvt->maxch < CHANNELS_PER_BRANCH) { pvt->b1_mtr[slot_row] = 0; @@ -1117,22 +1115,22 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) /* Branch 1 set of MTR registers */ pci_read_config_word(pvt->branch_1, where, &pvt->b1_mtr[slot_row]); - debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, where, - pvt->b1_mtr[slot_row]); + edac_dbg(2, "MTR%d where=0x%x B1 value=0x%x\n", + slot_row, where, pvt->b1_mtr[slot_row]); } /* Read and dump branch 0's MTRs */ - debugf2("\nMemory Technology Registers:\n"); - debugf2(" Branch 0:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); + edac_dbg(2, " Branch 0:\n"); for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) decode_mtr(slot_row, pvt->b0_mtr[slot_row]); pci_read_config_word(pvt->branch_0, AMBPRESENT_0, &pvt->b0_ambpresent0); - debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0); pci_read_config_word(pvt->branch_0, AMBPRESENT_1, &pvt->b0_ambpresent1); - debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1); /* Only if we have 2 branchs (4 channels) */ if (pvt->maxch < CHANNELS_PER_BRANCH) { @@ -1140,18 +1138,18 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) pvt->b1_ambpresent1 = 0; } else { /* Read and dump branch 1's MTRs */ - debugf2(" Branch 1:\n"); + edac_dbg(2, " Branch 1:\n"); for (slot_row = 0; slot_row < DIMMS_PER_CHANNEL; slot_row++) decode_mtr(slot_row, pvt->b1_mtr[slot_row]); pci_read_config_word(pvt->branch_1, AMBPRESENT_0, &pvt->b1_ambpresent0); - debugf2("\t\tAMB-Branch 1-present0 0x%x:\n", - pvt->b1_ambpresent0); + edac_dbg(2, "\t\tAMB-Branch 1-present0 0x%x:\n", + pvt->b1_ambpresent0); pci_read_config_word(pvt->branch_1, AMBPRESENT_1, &pvt->b1_ambpresent1); - debugf2("\t\tAMB-Branch 1-present1 0x%x:\n", - pvt->b1_ambpresent1); + edac_dbg(2, "\t\tAMB-Branch 1-present1 0x%x:\n", + pvt->b1_ambpresent1); } /* Go and determine the size of each DIMM and place in an @@ -1203,10 +1201,9 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) size_mb = pvt->dimm_info[slot][channel].megabytes; - debugf2("%s: dimm%zd (branch %d channel %d slot %d): %d.%03d GB\n", - __func__, dimm - mci->dimms, - channel / 2, channel % 2, slot, - size_mb / 1000, size_mb % 1000); + edac_dbg(2, "dimm (branch %d channel %d slot %d): %d.%03d GB\n", + channel / 2, channel % 2, slot, + size_mb / 1000, size_mb % 1000); dimm->nr_pages = size_mb << 8; dimm->grain = 8; @@ -1227,7 +1224,7 @@ static int i5400_init_dimms(struct mem_ctl_info *mci) * With such single-DIMM mode, the SDCC algorithm degrades to SECDEC+. */ if (ndimms == 1) - mci->dimms[0].edac_mode = EDAC_SECDED; + mci->dimms[0]->edac_mode = EDAC_SECDED; return (ndimms == 0); } @@ -1270,10 +1267,9 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (dev_idx >= ARRAY_SIZE(i5400_devs)) return -EINVAL; - debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __FILE__, __func__, - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1297,9 +1293,9 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->system_address = pdev; /* Record this device in our private */ @@ -1329,19 +1325,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) /* initialize the MC control structure 'dimms' table * with the mapping and control information */ if (i5400_init_dimms(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i5400_init_dimms() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i5400_init_dimms() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no dimms found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i5400_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", - __FILE__, __func__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1385,7 +1378,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(0, "MC:\n"); /* wake up device */ rc = pci_enable_device(pdev); @@ -1404,7 +1397,7 @@ static void __devexit i5400_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + edac_dbg(0, "\n"); if (i5400_pci) edac_pci_release_generic_ctl(i5400_pci); @@ -1450,7 +1443,7 @@ static int __init i5400_init(void) { int pci_rc; - debugf2("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(2, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1466,7 +1459,7 @@ static int __init i5400_init(void) */ static void __exit i5400_exit(void) { - debugf2("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(2, "MC:\n"); pci_unregister_driver(&i5400_driver); } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 97c22fd650e..a09d0667f72 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -182,24 +182,6 @@ static const u16 mtr_regs[MAX_SLOTS] = { #define MTR_DIMM_COLS(mtr) ((mtr) & 0x3) #define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10) -#ifdef CONFIG_EDAC_DEBUG -/* MTR NUMROW */ -static const char *numrow_toString[] = { - "8,192 - 13 rows", - "16,384 - 14 rows", - "32,768 - 15 rows", - "65,536 - 16 rows" -}; - -/* MTR NUMCOL */ -static const char *numcol_toString[] = { - "1,024 - 10 columns", - "2,048 - 11 columns", - "4,096 - 12 columns", - "reserved" -}; -#endif - /************************************************ * i7300 Register definitions for error detection ************************************************/ @@ -467,10 +449,10 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) "Bank=%d RAS=%d CAS=%d Err=0x%lx (%s))", bank, ras, cas, errors, specific); - edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, 1, 0, 0, 0, branch, -1, rank, is_wr ? "Write error" : "Read error", - pvt->tmp_prt_buffer, NULL); + pvt->tmp_prt_buffer); } @@ -513,11 +495,11 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) "DRAM-Bank=%d RAS=%d CAS=%d, Err=0x%lx (%s))", bank, ras, cas, errors, specific); - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, syndrome, branch >> 1, channel % 2, rank, is_wr ? "Write error" : "Read error", - pvt->tmp_prt_buffer, NULL); + pvt->tmp_prt_buffer); } return; } @@ -614,9 +596,8 @@ static int decode_mtr(struct i7300_pvt *pvt, mtr = pvt->mtr[slot][branch]; ans = MTR_DIMMS_PRESENT(mtr) ? 1 : 0; - debugf2("\tMTR%d CH%d: DIMMs are %s (mtr)\n", - slot, channel, - ans ? "Present" : "NOT Present"); + edac_dbg(2, "\tMTR%d CH%d: DIMMs are %sPresent (mtr)\n", + slot, channel, ans ? "" : "NOT "); /* Determine if there is a DIMM present in this DIMM slot */ if (!ans) @@ -638,16 +619,25 @@ static int decode_mtr(struct i7300_pvt *pvt, dinfo->megabytes = 1 << addrBits; - debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); - - debugf2("\t\tELECTRICAL THROTTLING is %s\n", - MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); - - debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); - debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANKS(mtr) ? "double" : "single"); - debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]); - debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]); - debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes); + edac_dbg(2, "\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr)); + + edac_dbg(2, "\t\tELECTRICAL THROTTLING is %s\n", + MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled"); + + edac_dbg(2, "\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr)); + edac_dbg(2, "\t\tNUMRANK: %s\n", + MTR_DIMM_RANKS(mtr) ? "double" : "single"); + edac_dbg(2, "\t\tNUMROW: %s\n", + MTR_DIMM_ROWS(mtr) == 0 ? "8,192 - 13 rows" : + MTR_DIMM_ROWS(mtr) == 1 ? "16,384 - 14 rows" : + MTR_DIMM_ROWS(mtr) == 2 ? "32,768 - 15 rows" : + "65,536 - 16 rows"); + edac_dbg(2, "\t\tNUMCOL: %s\n", + MTR_DIMM_COLS(mtr) == 0 ? "1,024 - 10 columns" : + MTR_DIMM_COLS(mtr) == 1 ? "2,048 - 11 columns" : + MTR_DIMM_COLS(mtr) == 2 ? "4,096 - 12 columns" : + "reserved"); + edac_dbg(2, "\t\tSIZE: %d MB\n", dinfo->megabytes); /* * The type of error detection actually depends of the @@ -663,9 +653,9 @@ static int decode_mtr(struct i7300_pvt *pvt, dimm->mtype = MEM_FB_DDR2; if (IS_SINGLE_MODE(pvt->mc_settings_a)) { dimm->edac_mode = EDAC_SECDED; - debugf2("\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); + edac_dbg(2, "\t\tECC code is 8-byte-over-32-byte SECDED+ code\n"); } else { - debugf2("\t\tECC code is on Lockstep mode\n"); + edac_dbg(2, "\t\tECC code is on Lockstep mode\n"); if (MTR_DRAM_WIDTH(mtr) == 8) dimm->edac_mode = EDAC_S8ECD8ED; else @@ -674,9 +664,9 @@ static int decode_mtr(struct i7300_pvt *pvt, /* ask what device type on this row */ if (MTR_DRAM_WIDTH(mtr) == 8) { - debugf2("\t\tScrub algorithm for x8 is on %s mode\n", - IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? - "enhanced" : "normal"); + edac_dbg(2, "\t\tScrub algorithm for x8 is on %s mode\n", + IS_SCRBALGO_ENHANCED(pvt->mc_settings) ? + "enhanced" : "normal"); dimm->dtype = DEV_X8; } else @@ -710,14 +700,14 @@ static void print_dimm_size(struct i7300_pvt *pvt) p += n; space -= n; } - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; n = snprintf(p, space, "-------------------------------" "------------------------------"); p += n; space -= n; - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; @@ -733,7 +723,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) space -= n; } - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; } @@ -742,7 +732,7 @@ static void print_dimm_size(struct i7300_pvt *pvt) "------------------------------"); p += n; space -= n; - debugf2("%s\n", pvt->tmp_prt_buffer); + edac_dbg(2, "%s\n", pvt->tmp_prt_buffer); p = pvt->tmp_prt_buffer; space = PAGE_SIZE; #endif @@ -765,7 +755,7 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) pvt = mci->pvt_info; - debugf2("Memory Technology Registers:\n"); + edac_dbg(2, "Memory Technology Registers:\n"); /* Get the AMB present registers for the four channels */ for (branch = 0; branch < MAX_BRANCHES; branch++) { @@ -774,15 +764,15 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_0, &pvt->ambpresent[channel]); - debugf2("\t\tAMB-present CH%d = 0x%x:\n", - channel, pvt->ambpresent[channel]); + edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); channel = to_channel(1, branch); pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1, &pvt->ambpresent[channel]); - debugf2("\t\tAMB-present CH%d = 0x%x:\n", - channel, pvt->ambpresent[channel]); + edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", + channel, pvt->ambpresent[channel]); } /* Get the set of MTR[0-7] regs by each branch */ @@ -824,12 +814,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) static void decode_mir(int mir_no, u16 mir[MAX_MIR]) { if (mir[mir_no] & 3) - debugf2("MIR%d: limit= 0x%x Branch(es) that participate:" - " %s %s\n", - mir_no, - (mir[mir_no] >> 4) & 0xfff, - (mir[mir_no] & 1) ? "B0" : "", - (mir[mir_no] & 2) ? "B1" : ""); + edac_dbg(2, "MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n", + mir_no, + (mir[mir_no] >> 4) & 0xfff, + (mir[mir_no] & 1) ? "B0" : "", + (mir[mir_no] & 2) ? "B1" : ""); } /** @@ -849,17 +838,17 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_dev_16_0_fsb_ctlr, AMBASE, (u32 *) &pvt->ambase); - debugf2("AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); + edac_dbg(2, "AMBASE= 0x%lx\n", (long unsigned int)pvt->ambase); /* Get the Branch Map regs */ pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, TOLM, &pvt->tolm); pvt->tolm >>= 12; - debugf2("TOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm, - pvt->tolm); + edac_dbg(2, "TOLM (number of 256M regions) =%u (0x%x)\n", + pvt->tolm, pvt->tolm); actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28)); - debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n", - actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); + edac_dbg(2, "Actual TOLM byte addr=%u.%03u GB (0x%x)\n", + actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28); /* Get memory controller settings */ pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, MC_SETTINGS, @@ -868,15 +857,15 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci) &pvt->mc_settings_a); if (IS_SINGLE_MODE(pvt->mc_settings_a)) - debugf0("Memory controller operating on single mode\n"); + edac_dbg(0, "Memory controller operating on single mode\n"); else - debugf0("Memory controller operating on %s mode\n", - IS_MIRRORED(pvt->mc_settings) ? "mirrored" : "non-mirrored"); + edac_dbg(0, "Memory controller operating on %smirrored mode\n", + IS_MIRRORED(pvt->mc_settings) ? "" : "non-"); - debugf0("Error detection is %s\n", - IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); - debugf0("Retry is %s\n", - IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); + edac_dbg(0, "Error detection is %s\n", + IS_ECC_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); + edac_dbg(0, "Retry is %s\n", + IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled"); /* Get Memory Interleave Range registers */ pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, @@ -970,18 +959,18 @@ static int __devinit i7300_get_devices(struct mem_ctl_info *mci) } } - debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_0_fsb_ctlr), - pvt->pci_dev_16_0_fsb_ctlr->vendor, - pvt->pci_dev_16_0_fsb_ctlr->device); - debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_1_fsb_addr_map), - pvt->pci_dev_16_1_fsb_addr_map->vendor, - pvt->pci_dev_16_1_fsb_addr_map->device); - debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n", - pci_name(pvt->pci_dev_16_2_fsb_err_regs), - pvt->pci_dev_16_2_fsb_err_regs->vendor, - pvt->pci_dev_16_2_fsb_err_regs->device); + edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_0_fsb_ctlr), + pvt->pci_dev_16_0_fsb_ctlr->vendor, + pvt->pci_dev_16_0_fsb_ctlr->device); + edac_dbg(1, "Branchmap, control and errors - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_1_fsb_addr_map), + pvt->pci_dev_16_1_fsb_addr_map->vendor, + pvt->pci_dev_16_1_fsb_addr_map->device); + edac_dbg(1, "FSB Error Regs - PCI Bus ID: %s %x:%x\n", + pci_name(pvt->pci_dev_16_2_fsb_err_regs), + pvt->pci_dev_16_2_fsb_err_regs->vendor, + pvt->pci_dev_16_2_fsb_err_regs->device); pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_FB0, @@ -1032,10 +1021,9 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (rc == -EIO) return rc; - debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", - __func__, - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "MC: pdev bus %u dev=0x%x fn=0x%x\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); /* We only are looking for func 0 of the set */ if (PCI_FUNC(pdev->devfn) != 0) @@ -1055,9 +1043,9 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, if (mci == NULL) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); + edac_dbg(0, "MC: mci = %p\n", mci); - mci->dev = &pdev->dev; /* record ptr to the generic device */ + mci->pdev = &pdev->dev; /* record ptr to the generic device */ pvt = mci->pvt_info; pvt->pci_dev_16_0_fsb_ctlr = pdev; /* Record this device in our private */ @@ -1088,19 +1076,16 @@ static int __devinit i7300_init_one(struct pci_dev *pdev, /* initialize the MC control structure 'csrows' table * with the mapping and control information */ if (i7300_get_mc_regs(mci)) { - debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n" - " because i7300_init_csrows() returned nonzero " - "value\n"); + edac_dbg(0, "MC: Setting mci->edac_cap to EDAC_FLAG_NONE because i7300_init_csrows() returned nonzero value\n"); mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ } else { - debugf1("MC: Enable error reporting now\n"); + edac_dbg(1, "MC: Enable error reporting now\n"); i7300_enable_error_reporting(mci); } /* add this new MC control structure to EDAC's list of MCs */ if (edac_mc_add_mc(mci)) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -1142,7 +1127,7 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; char *tmp; - debugf0(__FILE__ ": %s()\n", __func__); + edac_dbg(0, "\n"); if (i7300_pci) edac_pci_release_generic_ctl(i7300_pci); @@ -1189,7 +1174,7 @@ static int __init i7300_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1204,7 +1189,7 @@ static int __init i7300_init(void) */ static void __exit i7300_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); pci_unregister_driver(&i7300_driver); } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index a499c7ed820..3672101023b 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -248,6 +248,8 @@ struct i7core_dev { }; struct i7core_pvt { + struct device *addrmatch_dev, *chancounts_dev; + struct pci_dev *pci_noncore; struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; @@ -514,29 +516,28 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod); pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map); - debugf0("QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n", - pvt->i7core_dev->socket, pvt->info.mc_control, pvt->info.mc_status, - pvt->info.max_dod, pvt->info.ch_map); + edac_dbg(0, "QPI %d control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n", + pvt->i7core_dev->socket, pvt->info.mc_control, + pvt->info.mc_status, pvt->info.max_dod, pvt->info.ch_map); if (ECC_ENABLED(pvt)) { - debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4); + edac_dbg(0, "ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4); if (ECCx8(pvt)) mode = EDAC_S8ECD8ED; else mode = EDAC_S4ECD4ED; } else { - debugf0("ECC disabled\n"); + edac_dbg(0, "ECC disabled\n"); mode = EDAC_NONE; } /* FIXME: need to handle the error codes */ - debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked " - "x%x x 0x%x\n", - numdimms(pvt->info.max_dod), - numrank(pvt->info.max_dod >> 2), - numbank(pvt->info.max_dod >> 4), - numrow(pvt->info.max_dod >> 6), - numcol(pvt->info.max_dod >> 9)); + edac_dbg(0, "DOD Max limits: DIMMS: %d, %d-ranked, %d-banked x%x x 0x%x\n", + numdimms(pvt->info.max_dod), + numrank(pvt->info.max_dod >> 2), + numbank(pvt->info.max_dod >> 4), + numrow(pvt->info.max_dod >> 6), + numcol(pvt->info.max_dod >> 9)); for (i = 0; i < NUM_CHANS; i++) { u32 data, dimm_dod[3], value[8]; @@ -545,11 +546,11 @@ static int get_dimm_config(struct mem_ctl_info *mci) continue; if (!CH_ACTIVE(pvt, i)) { - debugf0("Channel %i is not active\n", i); + edac_dbg(0, "Channel %i is not active\n", i); continue; } if (CH_DISABLED(pvt, i)) { - debugf0("Channel %i is disabled\n", i); + edac_dbg(0, "Channel %i is disabled\n", i); continue; } @@ -580,15 +581,14 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_ch[i][1], MC_DOD_CH_DIMM2, &dimm_dod[2]); - debugf0("Ch%d phy rd%d, wr%d (0x%08x): " - "%s%s%s%cDIMMs\n", - i, - RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), - data, - pvt->channel[i].is_3dimms_present ? "3DIMMS " : "", - pvt->channel[i].is_3dimms_present ? "SINGLE_4R " : "", - pvt->channel[i].has_4rank ? "HAS_4R " : "", - (data & REGISTERED_DIMM) ? 'R' : 'U'); + edac_dbg(0, "Ch%d phy rd%d, wr%d (0x%08x): %s%s%s%cDIMMs\n", + i, + RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), + data, + pvt->channel[i].is_3dimms_present ? "3DIMMS " : "", + pvt->channel[i].is_3dimms_present ? "SINGLE_4R " : "", + pvt->channel[i].has_4rank ? "HAS_4R " : "", + (data & REGISTERED_DIMM) ? 'R' : 'U'); for (j = 0; j < 3; j++) { u32 banks, ranks, rows, cols; @@ -607,11 +607,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) /* DDR3 has 8 I/O banks */ size = (rows * cols * banks * ranks) >> (20 - 3); - debugf0("\tdimm %d %d Mb offset: %x, " - "bank: %d, rank: %d, row: %#x, col: %#x\n", - j, size, - RANKOFFSET(dimm_dod[j]), - banks, ranks, rows, cols); + edac_dbg(0, "\tdimm %d %d Mb offset: %x, bank: %d, rank: %d, row: %#x, col: %#x\n", + j, size, + RANKOFFSET(dimm_dod[j]), + banks, ranks, rows, cols); npages = MiB_TO_PAGES(size); @@ -647,12 +646,12 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]); pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]); pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]); - debugf1("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i); + edac_dbg(1, "\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i); for (j = 0; j < 8; j++) - debugf1("\t\t%#x\t%#x\t%#x\n", - (value[j] >> 27) & 0x1, - (value[j] >> 24) & 0x7, - (value[j] & ((1 << 24) - 1))); + edac_dbg(1, "\t\t%#x\t%#x\t%#x\n", + (value[j] >> 27) & 0x1, + (value[j] >> 24) & 0x7, + (value[j] & ((1 << 24) - 1))); } return 0; @@ -662,6 +661,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) Error insertion routines ****************************************************************************/ +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + /* The i7core has independent error injection features per channel. However, to have a simpler code, we don't allow enabling error injection on more than one channel. @@ -691,9 +692,11 @@ static int disable_inject(const struct mem_ctl_info *mci) * bit 0 - refers to the lower 32-byte half cacheline * bit 1 - refers to the upper 32-byte half cacheline */ -static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, +static ssize_t i7core_inject_section_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -709,9 +712,11 @@ static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_section_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; return sprintf(data, "0x%08x\n", pvt->inject.section); } @@ -724,10 +729,12 @@ static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci, * bit 1 - inject ECC error * bit 2 - inject parity error */ -static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, +static ssize_t i7core_inject_type_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { - struct i7core_pvt *pvt = mci->pvt_info; + struct mem_ctl_info *mci = to_mci(dev); +struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -742,10 +749,13 @@ static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_type_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; + return sprintf(data, "0x%08x\n", pvt->inject.type); } @@ -759,9 +769,11 @@ static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci, * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an * uncorrectable error to be injected. */ -static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t i7core_inject_eccmask_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; unsigned long value; int rc; @@ -777,10 +789,13 @@ static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci, return count; } -static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_eccmask_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; + return sprintf(data, "0x%08x\n", pvt->inject.eccmask); } @@ -797,14 +812,16 @@ static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci, #define DECLARE_ADDR_MATCH(param, limit) \ static ssize_t i7core_inject_store_##param( \ - struct mem_ctl_info *mci, \ - const char *data, size_t count) \ + struct device *dev, \ + struct device_attribute *mattr, \ + const char *data, size_t count) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ long value; \ int rc; \ \ - debugf1("%s()\n", __func__); \ + edac_dbg(1, "\n"); \ pvt = mci->pvt_info; \ \ if (pvt->inject.enable) \ @@ -824,13 +841,15 @@ static ssize_t i7core_inject_store_##param( \ } \ \ static ssize_t i7core_inject_show_##param( \ - struct mem_ctl_info *mci, \ - char *data) \ + struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt; \ \ pvt = mci->pvt_info; \ - debugf1("%s() pvt=%p\n", __func__, pvt); \ + edac_dbg(1, "pvt=%p\n", pvt); \ if (pvt->inject.param < 0) \ return sprintf(data, "any\n"); \ else \ @@ -838,14 +857,9 @@ static ssize_t i7core_inject_show_##param( \ } #define ATTR_ADDR_MATCH(param) \ - { \ - .attr = { \ - .name = #param, \ - .mode = (S_IRUGO | S_IWUSR) \ - }, \ - .show = i7core_inject_show_##param, \ - .store = i7core_inject_store_##param, \ - } + static DEVICE_ATTR(param, S_IRUGO | S_IWUSR, \ + i7core_inject_show_##param, \ + i7core_inject_store_##param) DECLARE_ADDR_MATCH(channel, 3); DECLARE_ADDR_MATCH(dimm, 3); @@ -854,14 +868,21 @@ DECLARE_ADDR_MATCH(bank, 32); DECLARE_ADDR_MATCH(page, 0x10000); DECLARE_ADDR_MATCH(col, 0x4000); +ATTR_ADDR_MATCH(channel); +ATTR_ADDR_MATCH(dimm); +ATTR_ADDR_MATCH(rank); +ATTR_ADDR_MATCH(bank); +ATTR_ADDR_MATCH(page); +ATTR_ADDR_MATCH(col); + static int write_and_test(struct pci_dev *dev, const int where, const u32 val) { u32 read; int count; - debugf0("setting pci %02x:%02x.%x reg=%02x value=%08x\n", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), - where, val); + edac_dbg(0, "setting pci %02x:%02x.%x reg=%02x value=%08x\n", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), + where, val); for (count = 0; count < 10; count++) { if (count) @@ -899,9 +920,11 @@ static int write_and_test(struct pci_dev *dev, const int where, const u32 val) * is reliable enough to check if the MC is using the * three channels. However, this is not clear at the datasheet. */ -static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t i7core_inject_enable_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; u32 injectmask; u64 mask = 0; @@ -994,17 +1017,18 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 8); - debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," - " inject 0x%08x\n", - mask, pvt->inject.eccmask, injectmask); + edac_dbg(0, "Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n", + mask, pvt->inject.eccmask, injectmask); return count; } -static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, - char *data) +static ssize_t i7core_inject_enable_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct i7core_pvt *pvt = mci->pvt_info; u32 injectmask; @@ -1014,7 +1038,7 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], MC_CHANNEL_ERROR_INJECT, &injectmask); - debugf0("Inject error read: 0x%018x\n", injectmask); + edac_dbg(0, "Inject error read: 0x%018x\n", injectmask); if (injectmask & 0x0c) pvt->inject.enable = 1; @@ -1024,12 +1048,14 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, #define DECLARE_COUNTER(param) \ static ssize_t i7core_show_counter_##param( \ - struct mem_ctl_info *mci, \ - char *data) \ + struct device *dev, \ + struct device_attribute *mattr, \ + char *data) \ { \ + struct mem_ctl_info *mci = to_mci(dev); \ struct i7core_pvt *pvt = mci->pvt_info; \ \ - debugf1("%s() \n", __func__); \ + edac_dbg(1, "\n"); \ if (!pvt->ce_count_available || (pvt->is_registered)) \ return sprintf(data, "data unavailable\n"); \ return sprintf(data, "%lu\n", \ @@ -1037,121 +1063,179 @@ static ssize_t i7core_show_counter_##param( \ } #define ATTR_COUNTER(param) \ - { \ - .attr = { \ - .name = __stringify(udimm##param), \ - .mode = (S_IRUGO | S_IWUSR) \ - }, \ - .show = i7core_show_counter_##param \ - } + static DEVICE_ATTR(udimm##param, S_IRUGO | S_IWUSR, \ + i7core_show_counter_##param, \ + NULL) DECLARE_COUNTER(0); DECLARE_COUNTER(1); DECLARE_COUNTER(2); +ATTR_COUNTER(0); +ATTR_COUNTER(1); +ATTR_COUNTER(2); + /* - * Sysfs struct + * inject_addrmatch device sysfs struct */ -static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = { - ATTR_ADDR_MATCH(channel), - ATTR_ADDR_MATCH(dimm), - ATTR_ADDR_MATCH(rank), - ATTR_ADDR_MATCH(bank), - ATTR_ADDR_MATCH(page), - ATTR_ADDR_MATCH(col), - { } /* End of list */ +static struct attribute *i7core_addrmatch_attrs[] = { + &dev_attr_channel.attr, + &dev_attr_dimm.attr, + &dev_attr_rank.attr, + &dev_attr_bank.attr, + &dev_attr_page.attr, + &dev_attr_col.attr, + NULL }; -static const struct mcidev_sysfs_group i7core_inject_addrmatch = { - .name = "inject_addrmatch", - .mcidev_attr = i7core_addrmatch_attrs, +static struct attribute_group addrmatch_grp = { + .attrs = i7core_addrmatch_attrs, }; -static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { - ATTR_COUNTER(0), - ATTR_COUNTER(1), - ATTR_COUNTER(2), - { .attr = { .name = NULL } } +static const struct attribute_group *addrmatch_groups[] = { + &addrmatch_grp, + NULL }; -static const struct mcidev_sysfs_group i7core_udimm_counters = { - .name = "all_channel_counts", - .mcidev_attr = i7core_udimm_counters_attrs, +static void addrmatch_release(struct device *device) +{ + edac_dbg(1, "Releasing device %s\n", dev_name(device)); + kfree(device); +} + +static struct device_type addrmatch_type = { + .groups = addrmatch_groups, + .release = addrmatch_release, }; -static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = { - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_section_show, - .store = i7core_inject_section_store, - }, { - .attr = { - .name = "inject_type", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_type_show, - .store = i7core_inject_type_store, - }, { - .attr = { - .name = "inject_eccmask", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_eccmask_show, - .store = i7core_inject_eccmask_store, - }, { - .grp = &i7core_inject_addrmatch, - }, { - .attr = { - .name = "inject_enable", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_enable_show, - .store = i7core_inject_enable_store, - }, - { } /* End of list */ +/* + * all_channel_counts sysfs struct + */ + +static struct attribute *i7core_udimm_counters_attrs[] = { + &dev_attr_udimm0.attr, + &dev_attr_udimm1.attr, + &dev_attr_udimm2.attr, + NULL }; -static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = { - { - .attr = { - .name = "inject_section", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_section_show, - .store = i7core_inject_section_store, - }, { - .attr = { - .name = "inject_type", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_type_show, - .store = i7core_inject_type_store, - }, { - .attr = { - .name = "inject_eccmask", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_eccmask_show, - .store = i7core_inject_eccmask_store, - }, { - .grp = &i7core_inject_addrmatch, - }, { - .attr = { - .name = "inject_enable", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = i7core_inject_enable_show, - .store = i7core_inject_enable_store, - }, { - .grp = &i7core_udimm_counters, - }, - { } /* End of list */ +static struct attribute_group all_channel_counts_grp = { + .attrs = i7core_udimm_counters_attrs, }; +static const struct attribute_group *all_channel_counts_groups[] = { + &all_channel_counts_grp, + NULL +}; + +static void all_channel_counts_release(struct device *device) +{ + edac_dbg(1, "Releasing device %s\n", dev_name(device)); + kfree(device); +} + +static struct device_type all_channel_counts_type = { + .groups = all_channel_counts_groups, + .release = all_channel_counts_release, +}; + +/* + * inject sysfs attributes + */ + +static DEVICE_ATTR(inject_section, S_IRUGO | S_IWUSR, + i7core_inject_section_show, i7core_inject_section_store); + +static DEVICE_ATTR(inject_type, S_IRUGO | S_IWUSR, + i7core_inject_type_show, i7core_inject_type_store); + + +static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR, + i7core_inject_eccmask_show, i7core_inject_eccmask_store); + +static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR, + i7core_inject_enable_show, i7core_inject_enable_store); + +static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) +{ + struct i7core_pvt *pvt = mci->pvt_info; + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_section); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_type); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_enable); + if (rc < 0) + return rc; + + pvt->addrmatch_dev = kzalloc(sizeof(*pvt->addrmatch_dev), GFP_KERNEL); + if (!pvt->addrmatch_dev) + return rc; + + pvt->addrmatch_dev->type = &addrmatch_type; + pvt->addrmatch_dev->bus = mci->dev.bus; + device_initialize(pvt->addrmatch_dev); + pvt->addrmatch_dev->parent = &mci->dev; + dev_set_name(pvt->addrmatch_dev, "inject_addrmatch"); + dev_set_drvdata(pvt->addrmatch_dev, mci); + + edac_dbg(1, "creating %s\n", dev_name(pvt->addrmatch_dev)); + + rc = device_add(pvt->addrmatch_dev); + if (rc < 0) + return rc; + + if (!pvt->is_registered) { + pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), + GFP_KERNEL); + if (!pvt->chancounts_dev) { + put_device(pvt->addrmatch_dev); + device_del(pvt->addrmatch_dev); + return rc; + } + + pvt->chancounts_dev->type = &all_channel_counts_type; + pvt->chancounts_dev->bus = mci->dev.bus; + device_initialize(pvt->chancounts_dev); + pvt->chancounts_dev->parent = &mci->dev; + dev_set_name(pvt->chancounts_dev, "all_channel_counts"); + dev_set_drvdata(pvt->chancounts_dev, mci); + + edac_dbg(1, "creating %s\n", dev_name(pvt->chancounts_dev)); + + rc = device_add(pvt->chancounts_dev); + if (rc < 0) + return rc; + } + return 0; +} + +static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) +{ + struct i7core_pvt *pvt = mci->pvt_info; + + edac_dbg(1, "\n"); + + device_remove_file(&mci->dev, &dev_attr_inject_section); + device_remove_file(&mci->dev, &dev_attr_inject_type); + device_remove_file(&mci->dev, &dev_attr_inject_eccmask); + device_remove_file(&mci->dev, &dev_attr_inject_enable); + + if (!pvt->is_registered) { + put_device(pvt->chancounts_dev); + device_del(pvt->chancounts_dev); + } + put_device(pvt->addrmatch_dev); + device_del(pvt->addrmatch_dev); +} + /**************************************************************************** Device initialization routines: put/get, init/exit ****************************************************************************/ @@ -1164,14 +1248,14 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev) { int i; - debugf0(__FILE__ ": %s()\n", __func__); + edac_dbg(0, "\n"); for (i = 0; i < i7core_dev->n_devs; i++) { struct pci_dev *pdev = i7core_dev->pdev[i]; if (!pdev) continue; - debugf0("Removing dev %02x:%02x.%d\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "Removing dev %02x:%02x.%d\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); pci_dev_put(pdev); } } @@ -1214,12 +1298,12 @@ static unsigned i7core_pci_lastbus(void) while ((b = pci_find_next_bus(b)) != NULL) { bus = b->number; - debugf0("Found bus %d\n", bus); + edac_dbg(0, "Found bus %d\n", bus); if (bus > last_bus) last_bus = bus; } - debugf0("Last bus %d\n", last_bus); + edac_dbg(0, "Last bus %d\n", last_bus); return last_bus; } @@ -1326,10 +1410,10 @@ static int i7core_get_onedevice(struct pci_dev **prev, return -ENODEV; } - debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", - socket, bus, dev_descr->dev, - dev_descr->func, - PCI_VENDOR_ID_INTEL, dev_descr->dev_id); + edac_dbg(0, "Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", + socket, bus, dev_descr->dev, + dev_descr->func, + PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* * As stated on drivers/pci/search.c, the reference count for @@ -1427,13 +1511,13 @@ static int mci_bind_devs(struct mem_ctl_info *mci, family = "unknown"; pvt->enable_scrub = false; } - debugf0("Detected a processor type %s\n", family); + edac_dbg(0, "Detected a processor type %s\n", family); } else goto error; - debugf0("Associated fn %d.%d, dev = %p, socket %d\n", - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pdev, i7core_dev->socket); + edac_dbg(0, "Associated fn %d.%d, dev = %p, socket %d\n", + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev, i7core_dev->socket); if (PCI_SLOT(pdev->devfn) == 3 && PCI_FUNC(pdev->devfn) == 2) @@ -1452,18 +1536,6 @@ error: /**************************************************************************** Error check routines ****************************************************************************/ -static void i7core_rdimm_update_errcount(struct mem_ctl_info *mci, - const int chan, - const int dimm, - const int add) -{ - int i; - - for (i = 0; i < add; i++) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0, - chan, dimm, -1, "error", "", NULL); - } -} static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci, const int chan, @@ -1502,12 +1574,17 @@ static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci, /*updated the edac core */ if (add0 != 0) - i7core_rdimm_update_errcount(mci, chan, 0, add0); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add0, + 0, 0, 0, + chan, 0, -1, "error", ""); if (add1 != 0) - i7core_rdimm_update_errcount(mci, chan, 1, add1); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add1, + 0, 0, 0, + chan, 1, -1, "error", ""); if (add2 != 0) - i7core_rdimm_update_errcount(mci, chan, 2, add2); - + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, add2, + 0, 0, 0, + chan, 2, -1, "error", ""); } static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci) @@ -1530,8 +1607,8 @@ static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5, &rcv[2][1]); for (i = 0 ; i < 3; i++) { - debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n", - (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]); + edac_dbg(3, "MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n", + (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]); /*if the channel has 3 dimms*/ if (pvt->channel[i].dimms > 2) { new0 = DIMM_BOT_COR_ERR(rcv[i][0]); @@ -1562,7 +1639,7 @@ static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci) int new0, new1, new2; if (!pvt->pci_mcr[4]) { - debugf0("%s MCR registers not found\n", __func__); + edac_dbg(0, "MCR registers not found\n"); return; } @@ -1626,7 +1703,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, const struct mce *m) { struct i7core_pvt *pvt = mci->pvt_info; - char *type, *optype, *err, msg[80]; + char *type, *optype, *err; enum hw_event_mc_err_type tp_event; unsigned long error = m->status & 0x1ff0000l; bool uncorrected_error = m->mcgstatus & 1ll << 61; @@ -1704,20 +1781,18 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, err = "unknown"; } - snprintf(msg, sizeof(msg), "count=%d %s", core_err_cnt, optype); - /* * Call the helper to output message * FIXME: what to do if core_err_cnt > 1? Currently, it generates * only one event */ if (uncorrected_error || !pvt->is_registered) - edac_mc_handle_error(tp_event, mci, + edac_mc_handle_error(tp_event, mci, core_err_cnt, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, syndrome, channel, dimm, -1, - err, msg, m); + err, optype); } /* @@ -2094,8 +2169,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) struct i7core_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: " __FILE__ ": %s(): dev = %p\n", - __func__, &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: dev = %p\n", &i7core_dev->pdev[0]->dev); i7core_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -2103,8 +2177,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) pvt = mci->pvt_info; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); /* Disable scrubrate setting */ if (pvt->enable_scrub) @@ -2114,9 +2187,10 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) i7core_pci_ctl_release(pvt); /* Remove MC sysfs nodes */ - edac_mc_del_mc(mci->dev); + i7core_delete_sysfs_devices(mci); + edac_mc_del_mc(mci->pdev); - debugf1("%s: free mci struct\n", mci->ctl_name); + edac_dbg(1, "%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); edac_mc_free(mci); i7core_dev->mci = NULL; @@ -2142,8 +2216,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &i7core_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", mci, &i7core_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -2172,15 +2245,11 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) if (unlikely(rc < 0)) goto fail0; - if (pvt->is_registered) - mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs; - else - mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs; /* Get dimm basic config */ get_dimm_config(mci); /* record ptr to the generic device */ - mci->dev = &i7core_dev->pdev[0]->dev; + mci->pdev = &i7core_dev->pdev[0]->dev; /* Set the function pointer to an actual operation function */ mci->edac_check = i7core_check_error; @@ -2190,8 +2259,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); /* FIXME: perhaps some code should go here that disables error * reporting if we just enabled it */ @@ -2199,6 +2267,12 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) rc = -EINVAL; goto fail0; } + if (i7core_create_sysfs_devices(mci)) { + edac_dbg(0, "MC: failed to create sysfs nodes\n"); + edac_mc_del_mc(mci->pdev); + rc = -EINVAL; + goto fail0; + } /* Default error mask is any memory */ pvt->inject.channel = 0; @@ -2298,7 +2372,7 @@ static void __devexit i7core_remove(struct pci_dev *pdev) { struct i7core_dev *i7core_dev; - debugf0(__FILE__ ": %s()\n", __func__); + edac_dbg(0, "\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -2347,7 +2421,7 @@ static int __init i7core_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -2374,7 +2448,7 @@ static int __init i7core_init(void) */ static void __exit i7core_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); pci_unregister_driver(&i7core_driver); mce_unregister_decode_chain(&i7_mce_dec); } diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 52072c28a8a..90f303db5d1 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -124,7 +124,7 @@ static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci, *info) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, I82443BXGX_EAP, &info->eap); if (info->eap & I82443BXGX_EAP_OFFSET_SBE) /* Clear error to allow next error to be reported [p.61] */ @@ -156,19 +156,19 @@ static int i82443bxgx_edacmc_process_error_info(struct mem_ctl_info *mci, if (info->eap & I82443BXGX_EAP_OFFSET_SBE) { error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), - 0, -1, mci->ctl_name, "", NULL); + 0, -1, mci->ctl_name, ""); } if (info->eap & I82443BXGX_EAP_OFFSET_MBE) { error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, pageoffset, 0, edac_mc_find_csrow_by_page(mci, page), - 0, -1, mci->ctl_name, "", NULL); + 0, -1, mci->ctl_name, ""); } return error_found; @@ -178,7 +178,7 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci) { struct i82443bxgx_edacmc_error_info info; - debugf1("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82443bxgx_edacmc_get_error_info(mci, &info); i82443bxgx_edacmc_process_error_info(mci, &info, 1); } @@ -197,18 +197,17 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc); row_high_limit_last = 0; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); - debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", - mci->mc_idx, __FILE__, __func__, index, drbar); + edac_dbg(1, "MC%d: Row=%d DRB = %#0x\n", + mci->mc_idx, index, drbar); row_high_limit = ((u32) drbar << 23); /* find the DRAM Chip Select Base address and mask */ - debugf1("MC%d: %s: %s() Row=%d, " - "Boundary Address=%#0x, Last = %#0x\n", - mci->mc_idx, __FILE__, __func__, index, row_high_limit, - row_high_limit_last); + edac_dbg(1, "MC%d: Row=%d, Boundary Address=%#0x, Last = %#0x\n", + mci->mc_idx, index, row_high_limit, + row_high_limit_last); /* 440GX goes to 2GB, represented with a DRB of 0. */ if (row_high_limit_last && !row_high_limit) @@ -241,7 +240,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) enum mem_type mtype; enum edac_type edac_mode; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(0, "MC:\n"); /* Something is really hosed if PCI config space reads from * the MC aren't working. @@ -259,8 +258,8 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); - mci->dev = &pdev->dev; + edac_dbg(0, "MC: mci = %p\n", mci); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc); @@ -275,8 +274,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) mtype = MEM_RDR; break; default: - debugf0("Unknown/reserved DRAM type value " - "in DRAMC register!\n"); + edac_dbg(0, "Unknown/reserved DRAM type value in DRAMC register!\n"); mtype = -MEM_UNKNOWN; } @@ -305,8 +303,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) edac_mode = EDAC_SECDED; break; default: - debugf0("%s(): Unknown/reserved ECC state " - "in NBXCFG register!\n", __func__); + edac_dbg(0, "Unknown/reserved ECC state in NBXCFG register!\n"); edac_mode = EDAC_UNKNOWN; break; } @@ -330,7 +327,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) mci->ctl_page_to_phys = NULL; if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -345,7 +342,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("MC: %s: %s(): success\n", __FILE__, __func__); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -361,7 +358,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s: %s()\n", __FILE__, __func__); + edac_dbg(0, "MC:\n"); /* don't need to call pci_enable_device() */ rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); @@ -376,7 +373,7 @@ static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s: %s()\n", __FILE__, __func__); + edac_dbg(0, "\n"); if (i82443bxgx_pci) edac_pci_release_generic_ctl(i82443bxgx_pci); @@ -428,7 +425,7 @@ static int __init i82443bxgx_edacmc_init(void) id = &i82443bxgx_pci_tbl[i]; } if (!mci_pdev) { - debugf0("i82443bxgx pci_get_device fail\n"); + edac_dbg(0, "i82443bxgx pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -436,7 +433,7 @@ static int __init i82443bxgx_edacmc_init(void) pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl); if (pci_rc < 0) { - debugf0("i82443bxgx init fail\n"); + edac_dbg(0, "i82443bxgx init fail\n"); pci_rc = -ENODEV; goto fail1; } diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c index 08045059d10..1faa7497151 100644 --- a/drivers/edac/i82860_edac.c +++ b/drivers/edac/i82860_edac.c @@ -67,7 +67,7 @@ static void i82860_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -109,25 +109,25 @@ static int i82860_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0003) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } info->eap >>= PAGE_SHIFT; row = edac_mc_find_csrow_by_page(mci, info->eap); - dimm = mci->csrows[row].channels[0].dimm; + dimm = mci->csrows[row]->channels[0]->dimm; if (info->errsts & 0x0002) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, 0, dimm->location[0], dimm->location[1], -1, - "i82860 UE", "", NULL); + "i82860 UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, info->derrsyn, dimm->location[0], dimm->location[1], -1, - "i82860 CE", "", NULL); + "i82860 CE", ""); return 1; } @@ -136,7 +136,7 @@ static void i82860_check(struct mem_ctl_info *mci) { struct i82860_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82860_get_error_info(mci, &info); i82860_process_error_info(mci, &info, 1); } @@ -161,14 +161,13 @@ static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev) * in all eight rows. */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_word(pdev, I82860_GBA + index * 2, &value); cumul_size = (value & I82860_GBA_MASK) << (I82860_GBA_SHIFT - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -210,8 +209,8 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + edac_dbg(3, "init mci\n"); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; /* I"m not sure about this but I think that all RDRAM is SECDED */ @@ -229,7 +228,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } @@ -245,7 +244,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; @@ -260,7 +259,7 @@ static int __devinit i82860_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); i82860_printk(KERN_INFO, "i82860 init one\n"); if (pci_enable_device(pdev) < 0) @@ -278,7 +277,7 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (i82860_pci) edac_pci_release_generic_ctl(i82860_pci); @@ -311,7 +310,7 @@ static int __init i82860_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -324,7 +323,7 @@ static int __init i82860_init(void) PCI_DEVICE_ID_INTEL_82860_0, NULL); if (mci_pdev == NULL) { - debugf0("860 pci_get_device fail\n"); + edac_dbg(0, "860 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -332,7 +331,7 @@ static int __init i82860_init(void) pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); if (pci_rc < 0) { - debugf0("860 init fail\n"); + edac_dbg(0, "860 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -352,7 +351,7 @@ fail0: static void __exit i82860_exit(void) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); pci_unregister_driver(&i82860_driver); diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index b613e31c16e..3e416b1a6b5 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -189,7 +189,7 @@ static void i82875p_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -227,7 +227,7 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, { int row, multi_chan; - multi_chan = mci->csrows[0].nr_channels - 1; + multi_chan = mci->csrows[0]->nr_channels - 1; if (!(info->errsts & 0x0081)) return 0; @@ -236,9 +236,9 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0081) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -246,15 +246,15 @@ static int i82875p_process_error_info(struct mem_ctl_info *mci, row = edac_mc_find_csrow_by_page(mci, info->eap); if (info->errsts & 0x0080) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, info->eap, 0, 0, row, -1, -1, - "i82875p UE", "", NULL); + "i82875p UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, info->eap, 0, info->derrsyn, row, multi_chan ? (info->des & 0x1) : 0, - -1, "i82875p CE", "", NULL); + -1, "i82875p CE", ""); return 1; } @@ -263,7 +263,7 @@ static void i82875p_check(struct mem_ctl_info *mci) { struct i82875p_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82875p_get_error_info(mci, &info); i82875p_process_error_info(mci, &info, 1); } @@ -367,12 +367,11 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; value = readb(ovrfl_window + I82875P_DRB + index); cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); if (cumul_size == last_cumul_size) continue; /* not populated */ @@ -382,7 +381,7 @@ static void i82875p_init_csrows(struct mem_ctl_info *mci, last_cumul_size = cumul_size; for (j = 0; j < nr_chans; j++) { - dimm = csrow->channels[j].dimm; + dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / nr_chans; dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ @@ -405,7 +404,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) u32 nr_chans; struct i82875p_error_info discard; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); @@ -426,11 +425,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } - /* Keeps mci available after edac_mc_del_mc() till edac_mc_free() */ - kobject_get(&mci->edac_mci_kobj); - - debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + edac_dbg(3, "init mci\n"); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_UNKNOWN; @@ -440,7 +436,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82875p_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); + edac_dbg(3, "init pvt\n"); pvt = (struct i82875p_pvt *)mci->pvt_info; pvt->ovrfl_pdev = ovrfl_pdev; pvt->ovrfl_window = ovrfl_window; @@ -451,7 +447,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail1; } @@ -467,11 +463,10 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail1: - kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); fail0: @@ -489,7 +484,7 @@ static int __devinit i82875p_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); i82875p_printk(KERN_INFO, "i82875p init one\n"); if (pci_enable_device(pdev) < 0) @@ -508,7 +503,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82875p_pvt *pvt = NULL; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (i82875p_pci) edac_pci_release_generic_ctl(i82875p_pci); @@ -554,7 +549,7 @@ static int __init i82875p_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -569,7 +564,7 @@ static int __init i82875p_init(void) PCI_DEVICE_ID_INTEL_82875_0, NULL); if (!mci_pdev) { - debugf0("875p pci_get_device fail\n"); + edac_dbg(0, "875p pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -577,7 +572,7 @@ static int __init i82875p_init(void) pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); if (pci_rc < 0) { - debugf0("875p init fail\n"); + edac_dbg(0, "875p init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -597,7 +592,7 @@ fail0: static void __exit i82875p_exit(void) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); i82875p_remove_one(mci_pdev); pci_dev_put(mci_pdev); diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 433332c7cdb..069e26c11c4 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -241,7 +241,7 @@ static void i82975x_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -288,8 +288,8 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, return 1; if ((info->errsts ^ info->errsts2) & 0x0003) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, - -1, -1, -1, "UE overwrote CE", "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, + -1, -1, -1, "UE overwrote CE", ""); info->errsts = info->errsts2; } @@ -308,21 +308,21 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); return 0; } - chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1; + chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; offst = info->eap & ((1 << PAGE_SHIFT) - - (1 << mci->csrows[row].channels[chan].dimm->grain)); + (1 << mci->csrows[row]->channels[chan]->dimm->grain)); if (info->errsts & 0x0002) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offst, 0, row, -1, -1, - "i82975x UE", "", NULL); + "i82975x UE", ""); else - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, offst, info->derrsyn, row, chan ? chan : 0, -1, - "i82975x CE", "", NULL); + "i82975x CE", ""); return 1; } @@ -331,7 +331,7 @@ static void i82975x_check(struct mem_ctl_info *mci) { struct i82975x_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); i82975x_get_error_info(mci, &info); i82975x_process_error_info(mci, &info, 1); } @@ -394,7 +394,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; + csrow = mci->csrows[index]; value = readb(mch_window + I82975X_DRB + index + ((index >= 4) ? 0x80 : 0)); @@ -406,8 +406,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ if (csrow->nr_channels > 1) cumul_size <<= 1; - debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, - cumul_size); + edac_dbg(3, "(%d) cumul_size 0x%x\n", index, cumul_size); nr_pages = cumul_size - last_cumul_size; if (!nr_pages) @@ -421,10 +420,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, */ dtype = i82975x_dram_type(mch_window, index); for (chan = 0; chan < csrow->nr_channels; chan++) { - dimm = mci->csrows[index].channels[chan].dimm; + dimm = mci->csrows[index]->channels[chan]->dimm; dimm->nr_pages = nr_pages / csrow->nr_channels; - strncpy(csrow->channels[chan].dimm->label, + strncpy(csrow->channels[chan]->dimm->label, labels[(index >> 1) + (chan * 2)], EDAC_MC_LABEL_LEN); dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ @@ -489,11 +488,11 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) u8 c1drb[4]; #endif - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); pci_read_config_dword(pdev, I82975X_MCHBAR, &mchbar); if (!(mchbar & 1)) { - debugf3("%s(): failed, MCHBAR disabled!\n", __func__); + edac_dbg(3, "failed, MCHBAR disabled!\n"); goto fail0; } mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ @@ -558,8 +557,8 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) goto fail1; } - debugf3("%s(): init mci\n", __func__); - mci->dev = &pdev->dev; + edac_dbg(3, "init mci\n"); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -569,7 +568,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) mci->dev_name = pci_name(pdev); mci->edac_check = i82975x_check; mci->ctl_page_to_phys = NULL; - debugf3("%s(): init pvt\n", __func__); + edac_dbg(3, "init pvt\n"); pvt = (struct i82975x_pvt *) mci->pvt_info; pvt->mch_window = mch_window; i82975x_init_csrows(mci, pdev, mch_window); @@ -578,12 +577,12 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) /* finalize this instance of memory controller with edac core */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail2; } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail2: @@ -601,7 +600,7 @@ static int __devinit i82975x_init_one(struct pci_dev *pdev, { int rc; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -619,7 +618,7 @@ static void __devexit i82975x_remove_one(struct pci_dev *pdev) struct mem_ctl_info *mci; struct i82975x_pvt *pvt; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (mci == NULL) @@ -655,7 +654,7 @@ static int __init i82975x_init(void) { int pci_rc; - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -669,7 +668,7 @@ static int __init i82975x_init(void) PCI_DEVICE_ID_INTEL_82975_0, NULL); if (!mci_pdev) { - debugf0("i82975x pci_get_device fail\n"); + edac_dbg(0, "i82975x pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -677,7 +676,7 @@ static int __init i82975x_init(void) pci_rc = i82975x_init_one(mci_pdev, i82975x_pci_tbl); if (pci_rc < 0) { - debugf0("i82975x init fail\n"); + edac_dbg(0, "i82975x init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -697,7 +696,7 @@ fail0: static void __exit i82975x_exit(void) { - debugf3("%s()\n", __func__); + edac_dbg(3, "\n"); pci_unregister_driver(&i82975x_driver); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 0e374625f6f..a1e791ec25d 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -49,34 +49,45 @@ static u32 orig_hid1[2]; /************************ MC SYSFS parts ***********************************/ -static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci, +#define to_mci(k) container_of(k, struct mem_ctl_info, dev) + +static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI)); } -static ssize_t mpc85xx_mc_inject_data_lo_show(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev, + struct device_attribute *mattr, char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO)); } -static ssize_t mpc85xx_mc_inject_ctrl_show(struct mem_ctl_info *mci, char *data) +static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev, + struct device_attribute *mattr, + char *data) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; return sprintf(data, "0x%08x", in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT)); } -static ssize_t mpc85xx_mc_inject_data_hi_store(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI, @@ -86,9 +97,11 @@ static ssize_t mpc85xx_mc_inject_data_hi_store(struct mem_ctl_info *mci, return 0; } -static ssize_t mpc85xx_mc_inject_data_lo_store(struct mem_ctl_info *mci, +static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev, + struct device_attribute *mattr, const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO, @@ -98,9 +111,11 @@ static ssize_t mpc85xx_mc_inject_data_lo_store(struct mem_ctl_info *mci, return 0; } -static ssize_t mpc85xx_mc_inject_ctrl_store(struct mem_ctl_info *mci, - const char *data, size_t count) +static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev, + struct device_attribute *mattr, + const char *data, size_t count) { + struct mem_ctl_info *mci = to_mci(dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; if (isdigit(*data)) { out_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT, @@ -110,38 +125,35 @@ static ssize_t mpc85xx_mc_inject_ctrl_store(struct mem_ctl_info *mci, return 0; } -static struct mcidev_sysfs_attribute mpc85xx_mc_sysfs_attributes[] = { - { - .attr = { - .name = "inject_data_hi", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_data_hi_show, - .store = mpc85xx_mc_inject_data_hi_store}, - { - .attr = { - .name = "inject_data_lo", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_data_lo_show, - .store = mpc85xx_mc_inject_data_lo_store}, - { - .attr = { - .name = "inject_ctrl", - .mode = (S_IRUGO | S_IWUSR) - }, - .show = mpc85xx_mc_inject_ctrl_show, - .store = mpc85xx_mc_inject_ctrl_store}, +DEVICE_ATTR(inject_data_hi, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_data_hi_show, mpc85xx_mc_inject_data_hi_store); +DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_data_lo_show, mpc85xx_mc_inject_data_lo_store); +DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR, + mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store); - /* End of list */ - { - .attr = {.name = NULL} - } -}; +static int mpc85xx_create_sysfs_attributes(struct mem_ctl_info *mci) +{ + int rc; + + rc = device_create_file(&mci->dev, &dev_attr_inject_data_hi); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_data_lo); + if (rc < 0) + return rc; + rc = device_create_file(&mci->dev, &dev_attr_inject_ctrl); + if (rc < 0) + return rc; -static void mpc85xx_set_mc_sysfs_attributes(struct mem_ctl_info *mci) + return 0; +} + +static void mpc85xx_remove_sysfs_attributes(struct mem_ctl_info *mci) { - mci->mc_driver_sysfs_attributes = mpc85xx_mc_sysfs_attributes; + device_remove_file(&mci->dev, &dev_attr_inject_data_hi); + device_remove_file(&mci->dev, &dev_attr_inject_data_lo); + device_remove_file(&mci->dev, &dev_attr_inject_ctrl); } /**************************** PCI Err device ***************************/ @@ -268,7 +280,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + edac_dbg(3, "failed edac_pci_add_device()\n"); goto err; } @@ -291,7 +303,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_pci_err_probe); - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); return 0; @@ -309,7 +321,7 @@ static int mpc85xx_pci_err_remove(struct platform_device *op) struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev); struct mpc85xx_pci_pdata *pdata = pci->pvt_info; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, orig_pci_err_cap_dr); @@ -570,7 +582,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -598,7 +610,7 @@ static int __devinit mpc85xx_l2_err_probe(struct platform_device *op) devres_remove_group(&op->dev, mpc85xx_l2_err_probe); - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " L2 err registered\n"); return 0; @@ -616,7 +628,7 @@ static int mpc85xx_l2_err_remove(struct platform_device *op) struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0); @@ -813,7 +825,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) pfn = err_addr >> PAGE_SHIFT; for (row_index = 0; row_index < mci->nr_csrows; row_index++) { - csrow = &mci->csrows[row_index]; + csrow = mci->csrows[row_index]; if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page)) break; } @@ -854,16 +866,16 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n"); if (err_detect & DDR_EDE_SBE) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); if (err_detect & DDR_EDE_MBE) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, pfn, err_addr & ~PAGE_MASK, syndrome, row_index, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect); } @@ -933,8 +945,8 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) u32 start; u32 end; - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + (index * MPC85XX_MC_CS_BNDS_OFS)); @@ -990,9 +1002,9 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) pdata = mci->pvt_info; pdata->name = "mpc85xx_mc_err"; pdata->irq = NO_IRQ; - mci->dev = &op->dev; + mci->pdev = &op->dev; pdata->edac_idx = edac_mc_idx++; - dev_set_drvdata(mci->dev, mci); + dev_set_drvdata(mci->pdev, mci); mci->ctl_name = pdata->name; mci->dev_name = pdata->name; @@ -1026,7 +1038,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) goto err; } - debugf3("%s(): init mci\n", __func__); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 | MEM_FLAG_DDR | MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; @@ -1041,8 +1053,6 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) mci->scrub_mode = SCRUB_SW_SRC; - mpc85xx_set_mc_sysfs_attributes(mci); - mpc85xx_init_csrows(mci); /* store the original error disable bits */ @@ -1054,7 +1064,13 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0); if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); + goto err; + } + + if (mpc85xx_create_sysfs_attributes(mci)) { + edac_mc_del_mc(mci->pdev); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto err; } @@ -1088,7 +1104,7 @@ static int __devinit mpc85xx_mc_err_probe(struct platform_device *op) } devres_remove_group(&op->dev, mpc85xx_mc_err_probe); - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); printk(KERN_INFO EDAC_MOD_STR " MC err registered\n"); return 0; @@ -1106,7 +1122,7 @@ static int mpc85xx_mc_err_remove(struct platform_device *op) struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); struct mpc85xx_mc_pdata *pdata = mci->pvt_info; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (edac_op_state == EDAC_OPSTATE_INT) { out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0); @@ -1117,6 +1133,7 @@ static int mpc85xx_mc_err_remove(struct platform_device *op) orig_ddr_err_disable); out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe); + mpc85xx_remove_sysfs_attributes(mci); edac_mc_del_mc(&op->dev); edac_mc_free(mci); return 0; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index b0bb5a3d252..2b315c2edc3 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -169,7 +169,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) MV64X60_PCIx_ERR_MASK_VAL); if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { - debugf3("%s(): failed edac_pci_add_device()\n", __func__); + edac_dbg(3, "failed edac_pci_add_device()\n"); goto err; } @@ -194,7 +194,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_pci_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; @@ -210,7 +210,7 @@ static int mv64x60_pci_err_remove(struct platform_device *pdev) { struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_pci_del_device(&pdev->dev); @@ -336,7 +336,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -363,7 +363,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_sram_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; @@ -379,7 +379,7 @@ static int mv64x60_sram_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -531,7 +531,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) pdata->edac_idx = edac_dev_idx++; if (edac_device_add_device(edac_dev) > 0) { - debugf3("%s(): failed edac_device_add_device()\n", __func__); + edac_dbg(3, "failed edac_device_add_device()\n"); goto err; } @@ -558,7 +558,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe); /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; @@ -574,7 +574,7 @@ static int mv64x60_cpu_err_remove(struct platform_device *pdev) { struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_device_del_device(&pdev->dev); edac_device_free_ctl_info(edac_dev); @@ -611,17 +611,17 @@ static void mv64x60_mc_check(struct mem_ctl_info *mci) /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ if (!(reg & 0x1)) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, syndrome, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); else /* 2 bit error, UE */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & PAGE_MASK, 0, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); /* clear the error */ out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); @@ -670,8 +670,8 @@ static void mv64x60_init_csrows(struct mem_ctl_info *mci, ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); - csrow = &mci->csrows[0]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[0]; + dimm = csrow->channels[0]->dimm; dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT; dimm->grain = 8; @@ -724,7 +724,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) } pdata = mci->pvt_info; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; platform_set_drvdata(pdev, mci); pdata->name = "mv64x60_mc_err"; pdata->irq = NO_IRQ; @@ -766,7 +766,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) goto err2; } - debugf3("%s(): init mci\n", __func__); + edac_dbg(3, "init mci\n"); mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; @@ -790,7 +790,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto err; } @@ -815,7 +815,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) } /* get this far and it's successful */ - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; @@ -831,7 +831,7 @@ static int mv64x60_mc_err_remove(struct platform_device *pdev) { struct mem_ctl_info *mci = platform_get_drvdata(pdev); - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); edac_mc_del_mc(&pdev->dev); edac_mc_free(mci); diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c index b095a906a99..2d35b78ada3 100644 --- a/drivers/edac/pasemi_edac.c +++ b/drivers/edac/pasemi_edac.c @@ -74,7 +74,7 @@ static int system_mmc_id; static u32 pasemi_edac_get_error_info(struct mem_ctl_info *mci) { - struct pci_dev *pdev = to_pci_dev(mci->dev); + struct pci_dev *pdev = to_pci_dev(mci->pdev); u32 tmp; pci_read_config_dword(pdev, MCDEBUG_ERRSTA, @@ -95,7 +95,7 @@ static u32 pasemi_edac_get_error_info(struct mem_ctl_info *mci) static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) { - struct pci_dev *pdev = to_pci_dev(mci->dev); + struct pci_dev *pdev = to_pci_dev(mci->pdev); u32 errlog1a; u32 cs; @@ -110,16 +110,16 @@ static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta) /* uncorrectable/multi-bit errors */ if (errsta & (MCDEBUG_ERRSTA_MBE_STATUS | MCDEBUG_ERRSTA_RFL_STATUS)) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, - mci->csrows[cs].first_page, 0, 0, - cs, 0, -1, mci->ctl_name, "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + mci->csrows[cs]->first_page, 0, 0, + cs, 0, -1, mci->ctl_name, ""); } /* correctable/single-bit errors */ if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, - mci->csrows[cs].first_page, 0, 0, - cs, 0, -1, mci->ctl_name, "", NULL); + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + mci->csrows[cs]->first_page, 0, 0, + cs, 0, -1, mci->ctl_name, ""); } static void pasemi_edac_check(struct mem_ctl_info *mci) @@ -141,8 +141,8 @@ static int pasemi_edac_init_csrows(struct mem_ctl_info *mci, int index; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; pci_read_config_dword(pdev, MCDRAM_RANKCFG + (index * 12), @@ -225,7 +225,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev, MCCFG_ERRCOR_ECC_GEN_EN | MCCFG_ERRCOR_ECC_CRR_EN; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = (errcor & MCCFG_ERRCOR_ECC_GEN_EN) ? diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index f3f9fed06ad..bf095763599 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c @@ -727,10 +727,10 @@ ppc4xx_edac_handle_ce(struct mem_ctl_info *mci, for (row = 0; row < mci->nr_csrows; row++) if (ppc4xx_edac_check_bank_error(status, row)) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, row, 0, -1, - message, "", NULL); + message, ""); } /** @@ -758,10 +758,10 @@ ppc4xx_edac_handle_ue(struct mem_ctl_info *mci, for (row = 0; row < mci->nr_csrows; row++) if (ppc4xx_edac_check_bank_error(status, row)) - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, offset, 0, row, 0, -1, - message, "", NULL); + message, ""); } /** @@ -1027,9 +1027,9 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci, /* Initial driver pointers and private data */ - mci->dev = &op->dev; + mci->pdev = &op->dev; - dev_set_drvdata(mci->dev, mci); + dev_set_drvdata(mci->pdev, mci); pdata = mci->pvt_info; @@ -1334,7 +1334,7 @@ static int __devinit ppc4xx_edac_probe(struct platform_device *op) return 0; fail1: - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); fail: edac_mc_free(mci); @@ -1368,7 +1368,7 @@ ppc4xx_edac_remove(struct platform_device *op) dcr_unmap(pdata->dcr_host, SDRAM_DCR_RESOURCE_LEN); - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); edac_mc_free(mci); return 0; diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c index e1cacd164f3..f854debd553 100644 --- a/drivers/edac/r82600_edac.c +++ b/drivers/edac/r82600_edac.c @@ -140,7 +140,7 @@ static void r82600_get_error_info(struct mem_ctl_info *mci, { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); pci_read_config_dword(pdev, R82600_EAP, &info->eapr); if (info->eapr & BIT(0)) @@ -179,11 +179,11 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, error_found = 1; if (handle_errors) - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, page, 0, syndrome, edac_mc_find_csrow_by_page(mci, page), 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } if (info->eapr & BIT(1)) { /* UE? */ @@ -191,11 +191,11 @@ static int r82600_process_error_info(struct mem_ctl_info *mci, if (handle_errors) /* 82600 doesn't give enough info */ - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, page, 0, 0, edac_mc_find_csrow_by_page(mci, page), 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } return error_found; @@ -205,7 +205,7 @@ static void r82600_check(struct mem_ctl_info *mci) { struct r82600_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); r82600_get_error_info(mci, &info); r82600_process_error_info(mci, &info, 1); } @@ -230,19 +230,19 @@ static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, row_high_limit_last = 0; for (index = 0; index < mci->nr_csrows; index++) { - csrow = &mci->csrows[index]; - dimm = csrow->channels[0].dimm; + csrow = mci->csrows[index]; + dimm = csrow->channels[0]->dimm; /* find the DRAM Chip Select Base address and mask */ pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); - debugf1("%s() Row=%d DRBA = %#0x\n", __func__, index, drbar); + edac_dbg(1, "Row=%d DRBA = %#0x\n", index, drbar); row_high_limit = ((u32) drbar << 24); /* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */ - debugf1("%s() Row=%d, Boundary Address=%#0x, Last = %#0x\n", - __func__, index, row_high_limit, row_high_limit_last); + edac_dbg(1, "Row=%d, Boundary Address=%#0x, Last = %#0x\n", + index, row_high_limit, row_high_limit_last); /* Empty row [p.57] */ if (row_high_limit == row_high_limit_last) @@ -277,14 +277,13 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) u32 sdram_refresh_rate; struct r82600_error_info discard; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); - debugf2("%s(): sdram refresh rate = %#0x\n", __func__, - sdram_refresh_rate); - debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); + edac_dbg(2, "sdram refresh rate = %#0x\n", sdram_refresh_rate); + edac_dbg(2, "DRAMC register = %#0x\n", dramcr); layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; layers[0].size = R82600_NR_CSROWS; layers[0].is_virt_csrow = true; @@ -295,8 +294,8 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; - debugf0("%s(): mci = %p\n", __func__, mci); - mci->dev = &pdev->dev; + edac_dbg(0, "mci = %p\n", mci); + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; /* FIXME try to work out if the chip leads have been used for COM2 @@ -311,8 +310,8 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) if (ecc_enabled(dramcr)) { if (scrub_disabled) - debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " - "%#0x\n", __func__, mci, eapr); + edac_dbg(3, "mci = %p - Scrubbing disabled! EAP: %#0x\n", + mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; @@ -329,15 +328,14 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { - debugf3("%s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ if (disable_hardware_scrub) { - debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", - __func__); + edac_dbg(3, "Disabling Hardware Scrub (scrub on error)\n"); pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); } @@ -352,7 +350,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx) __func__); } - debugf3("%s(): success\n", __func__); + edac_dbg(3, "success\n"); return 0; fail: @@ -364,7 +362,7 @@ fail: static int __devinit r82600_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); /* don't need to call pci_enable_device() */ return r82600_probe1(pdev, ent->driver_data); @@ -374,7 +372,7 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); if (r82600_pci) edac_pci_release_generic_ctl(r82600_pci); diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 36ad17e79d6..f3b1f9fafa4 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -381,8 +381,8 @@ static inline int numrank(u32 mtr) int ranks = (1 << RANK_CNT_BITS(mtr)); if (ranks > 4) { - debugf0("Invalid number of ranks: %d (max = 4) raw value = %x (%04x)", - ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n", + ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); return -EINVAL; } @@ -394,8 +394,8 @@ static inline int numrow(u32 mtr) int rows = (RANK_WIDTH_BITS(mtr) + 12); if (rows < 13 || rows > 18) { - debugf0("Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)", - rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)\n", + rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr); return -EINVAL; } @@ -407,8 +407,8 @@ static inline int numcol(u32 mtr) int cols = (COL_WIDTH_BITS(mtr) + 10); if (cols > 12) { - debugf0("Invalid number of cols: %d (max = 4) raw value = %x (%04x)", - cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr); + edac_dbg(0, "Invalid number of cols: %d (max = 4) raw value = %x (%04x)\n", + cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr); return -EINVAL; } @@ -475,8 +475,8 @@ static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot && PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) { - debugf1("Associated %02x.%02x.%d with %p\n", - bus, slot, func, sbridge_dev->pdev[i]); + edac_dbg(1, "Associated %02x.%02x.%d with %p\n", + bus, slot, func, sbridge_dev->pdev[i]); return sbridge_dev->pdev[i]; } } @@ -523,45 +523,45 @@ static int get_dimm_config(struct mem_ctl_info *mci) pci_read_config_dword(pvt->pci_br, SAD_CONTROL, ®); pvt->sbridge_dev->node_id = NODE_ID(reg); - debugf0("mc#%d: Node ID: %d, source ID: %d\n", - pvt->sbridge_dev->mc, - pvt->sbridge_dev->node_id, - pvt->sbridge_dev->source_id); + edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", + pvt->sbridge_dev->mc, + pvt->sbridge_dev->node_id, + pvt->sbridge_dev->source_id); pci_read_config_dword(pvt->pci_ras, RASENABLES, ®); if (IS_MIRROR_ENABLED(reg)) { - debugf0("Memory mirror is enabled\n"); + edac_dbg(0, "Memory mirror is enabled\n"); pvt->is_mirrored = true; } else { - debugf0("Memory mirror is disabled\n"); + edac_dbg(0, "Memory mirror is disabled\n"); pvt->is_mirrored = false; } pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr); if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) { - debugf0("Lockstep is enabled\n"); + edac_dbg(0, "Lockstep is enabled\n"); mode = EDAC_S8ECD8ED; pvt->is_lockstep = true; } else { - debugf0("Lockstep is disabled\n"); + edac_dbg(0, "Lockstep is disabled\n"); mode = EDAC_S4ECD4ED; pvt->is_lockstep = false; } if (IS_CLOSE_PG(pvt->info.mcmtr)) { - debugf0("address map is on closed page mode\n"); + edac_dbg(0, "address map is on closed page mode\n"); pvt->is_close_pg = true; } else { - debugf0("address map is on open page mode\n"); + edac_dbg(0, "address map is on open page mode\n"); pvt->is_close_pg = false; } pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®); if (IS_RDIMM_ENABLED(reg)) { /* FIXME: Can also be LRDIMM */ - debugf0("Memory is registered\n"); + edac_dbg(0, "Memory is registered\n"); mtype = MEM_RDDR3; } else { - debugf0("Memory is unregistered\n"); + edac_dbg(0, "Memory is unregistered\n"); mtype = MEM_DDR3; } @@ -576,7 +576,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) i, j, 0); pci_read_config_dword(pvt->pci_tad[i], mtr_regs[j], &mtr); - debugf4("Channel #%d MTR%d = %x\n", i, j, mtr); + edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr); if (IS_DIMM_PRESENT(mtr)) { pvt->channel[i].dimms++; @@ -588,10 +588,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) size = (rows * cols * banks * ranks) >> (20 - 3); npages = MiB_TO_PAGES(size); - debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", - pvt->sbridge_dev->mc, i, j, - size, npages, - banks, ranks, rows, cols); + edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", + pvt->sbridge_dev->mc, i, j, + size, npages, + banks, ranks, rows, cols); dimm->nr_pages = npages; dimm->grain = 32; @@ -629,8 +629,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (1 + pvt->tolm) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TOLM: %u.%03u GB (0x%016Lx)\n", - mb, kb, (u64)pvt->tolm); + edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); /* Address range is already 45:25 */ pci_read_config_dword(pvt->pci_sad1, TOHM, @@ -639,8 +638,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (1 + pvt->tohm) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TOHM: %u.%03u GB (0x%016Lx)", - mb, kb, (u64)pvt->tohm); + edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)", mb, kb, (u64)pvt->tohm); /* * Step 2) Get SAD range and SAD Interleave list @@ -663,13 +661,13 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (limit + 1) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("SAD#%d %s up to %u.%03u GB (0x%016Lx) %s reg=0x%08x\n", - n_sads, - get_dram_attr(reg), - mb, kb, - ((u64)tmp_mb) << 20L, - INTERLEAVE_MODE(reg) ? "Interleave: 8:6" : "Interleave: [8:6]XOR[18:16]", - reg); + edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n", + n_sads, + get_dram_attr(reg), + mb, kb, + ((u64)tmp_mb) << 20L, + INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]", + reg); prv = limit; pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads], @@ -679,8 +677,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci) if (j > 0 && sad_interl == sad_pkg(reg, j)) break; - debugf0("SAD#%d, interleave #%d: %d\n", - n_sads, j, sad_pkg(reg, j)); + edac_dbg(0, "SAD#%d, interleave #%d: %d\n", + n_sads, j, sad_pkg(reg, j)); } } @@ -697,16 +695,16 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = (limit + 1) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", - n_tads, mb, kb, - ((u64)tmp_mb) << 20L, - (u32)TAD_SOCK(reg), - (u32)TAD_CH(reg), - (u32)TAD_TGT0(reg), - (u32)TAD_TGT1(reg), - (u32)TAD_TGT2(reg), - (u32)TAD_TGT3(reg), - reg); + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", + n_tads, mb, kb, + ((u64)tmp_mb) << 20L, + (u32)TAD_SOCK(reg), + (u32)TAD_CH(reg), + (u32)TAD_TGT0(reg), + (u32)TAD_TGT1(reg), + (u32)TAD_TGT2(reg), + (u32)TAD_TGT3(reg), + reg); prv = limit; } @@ -722,11 +720,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci) ®); tmp_mb = TAD_OFFSET(reg) >> 20; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", - i, j, - mb, kb, - ((u64)tmp_mb) << 20L, - reg); + edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", + i, j, + mb, kb, + ((u64)tmp_mb) << 20L, + reg); } } @@ -747,12 +745,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = RIR_LIMIT(reg) >> 20; rir_way = 1 << RIR_WAY(reg); mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", - i, j, - mb, kb, - ((u64)tmp_mb) << 20L, - rir_way, - reg); + edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", + i, j, + mb, kb, + ((u64)tmp_mb) << 20L, + rir_way, + reg); for (k = 0; k < rir_way; k++) { pci_read_config_dword(pvt->pci_tad[i], @@ -761,12 +759,12 @@ static void get_memory_layout(const struct mem_ctl_info *mci) tmp_mb = RIR_OFFSET(reg) << 6; mb = div_u64_rem(tmp_mb, 1000, &kb); - debugf0("CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", - i, j, k, - mb, kb, - ((u64)tmp_mb) << 20L, - (u32)RIR_RNK_TGT(reg), - reg); + edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", + i, j, k, + mb, kb, + ((u64)tmp_mb) << 20L, + (u32)RIR_RNK_TGT(reg), + reg); } } } @@ -853,16 +851,16 @@ static int get_memory_error_data(struct mem_ctl_info *mci, if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way)) break; sad_interleave[sad_way] = sad_pkg(reg, sad_way); - debugf0("SAD interleave #%d: %d\n", - sad_way, sad_interleave[sad_way]); + edac_dbg(0, "SAD interleave #%d: %d\n", + sad_way, sad_interleave[sad_way]); } - debugf0("mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", - pvt->sbridge_dev->mc, - n_sads, - addr, - limit, - sad_way + 7, - interleave_mode ? "" : "XOR[18:16]"); + edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", + pvt->sbridge_dev->mc, + n_sads, + addr, + limit, + sad_way + 7, + interleave_mode ? "" : "XOR[18:16]"); if (interleave_mode) idx = ((addr >> 6) ^ (addr >> 16)) & 7; else @@ -884,8 +882,8 @@ static int get_memory_error_data(struct mem_ctl_info *mci, return -EINVAL; } *socket = sad_interleave[idx]; - debugf0("SAD interleave index: %d (wayness %d) = CPU socket %d\n", - idx, sad_way, *socket); + edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", + idx, sad_way, *socket); /* * Move to the proper node structure, in order to access the @@ -972,16 +970,16 @@ static int get_memory_error_data(struct mem_ctl_info *mci, offset = TAD_OFFSET(tad_offset); - debugf0("TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n", - n_tads, - addr, - limit, - (u32)TAD_SOCK(reg), - ch_way, - offset, - idx, - base_ch, - *channel_mask); + edac_dbg(0, "TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx\n", + n_tads, + addr, + limit, + (u32)TAD_SOCK(reg), + ch_way, + offset, + idx, + base_ch, + *channel_mask); /* Calculate channel address */ /* Remove the TAD offset */ @@ -1017,11 +1015,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci, limit = RIR_LIMIT(reg); mb = div_u64_rem(limit >> 20, 1000, &kb); - debugf0("RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", - n_rir, - mb, kb, - limit, - 1 << RIR_WAY(reg)); + edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", + n_rir, + mb, kb, + limit, + 1 << RIR_WAY(reg)); if (ch_addr <= limit) break; } @@ -1042,12 +1040,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci, ®); *rank = RIR_RNK_TGT(reg); - debugf0("RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", - n_rir, - ch_addr, - limit, - rir_way, - idx); + edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n", + n_rir, + ch_addr, + limit, + rir_way, + idx); return 0; } @@ -1064,14 +1062,14 @@ static void sbridge_put_devices(struct sbridge_dev *sbridge_dev) { int i; - debugf0(__FILE__ ": %s()\n", __func__); + edac_dbg(0, "\n"); for (i = 0; i < sbridge_dev->n_devs; i++) { struct pci_dev *pdev = sbridge_dev->pdev[i]; if (!pdev) continue; - debugf0("Removing dev %02x:%02x.%d\n", - pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + edac_dbg(0, "Removing dev %02x:%02x.%d\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); pci_dev_put(pdev); } } @@ -1177,10 +1175,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev, return -ENODEV; } - debugf0("Detected dev %02x:%d.%d PCI ID %04x:%04x\n", - bus, dev_descr->dev, - dev_descr->func, - PCI_VENDOR_ID_INTEL, dev_descr->dev_id); + edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n", + bus, dev_descr->dev, dev_descr->func, + PCI_VENDOR_ID_INTEL, dev_descr->dev_id); /* * As stated on drivers/pci/search.c, the reference count for @@ -1297,10 +1294,10 @@ static int mci_bind_devs(struct mem_ctl_info *mci, goto error; } - debugf0("Associated PCI %02x.%02d.%d with dev = %p\n", - sbridge_dev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pdev); + edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", + sbridge_dev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pdev); } /* Check if everything were registered */ @@ -1435,8 +1432,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, * to the group of dimm's where the error may be happening. */ snprintf(msg, sizeof(msg), - "count:%d%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", - core_err_cnt, + "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", overflow ? " OVERFLOW" : "", (uncorrected_error && recoverable) ? " recoverable" : "", area_type, @@ -1445,20 +1441,20 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, channel_mask, rank); - debugf0("%s", msg); + edac_dbg(0, "%s\n", msg); /* FIXME: need support for channel mask */ /* Call the helper to output message */ - edac_mc_handle_error(tp_event, mci, + edac_mc_handle_error(tp_event, mci, core_err_cnt, m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, channel, dimm, -1, - optype, msg, m); + optype, msg); return; err_parsing: - edac_mc_handle_error(tp_event, mci, 0, 0, 0, + edac_mc_handle_error(tp_event, mci, core_err_cnt, 0, 0, 0, -1, -1, -1, - msg, "", m); + msg, ""); } @@ -1592,8 +1588,7 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) struct sbridge_pvt *pvt; if (unlikely(!mci || !mci->pvt_info)) { - debugf0("MC: " __FILE__ ": %s(): dev = %p\n", - __func__, &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: dev = %p\n", &sbridge_dev->pdev[0]->dev); sbridge_printk(KERN_ERR, "Couldn't find mci handler\n"); return; @@ -1601,13 +1596,13 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) pvt = mci->pvt_info; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); /* Remove MC sysfs nodes */ - edac_mc_del_mc(mci->dev); + edac_mc_del_mc(mci->pdev); - debugf1("%s: free mci struct\n", mci->ctl_name); + edac_dbg(1, "%s: free mci struct\n", mci->ctl_name); kfree(mci->ctl_name); edac_mc_free(mci); sbridge_dev->mci = NULL; @@ -1638,8 +1633,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) if (unlikely(!mci)) return -ENOMEM; - debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", - __func__, mci, &sbridge_dev->pdev[0]->dev); + edac_dbg(0, "MC: mci = %p, dev = %p\n", + mci, &sbridge_dev->pdev[0]->dev); pvt = mci->pvt_info; memset(pvt, 0, sizeof(*pvt)); @@ -1670,12 +1665,11 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) get_memory_layout(mci); /* record ptr to the generic device */ - mci->dev = &sbridge_dev->pdev[0]->dev; + mci->pdev = &sbridge_dev->pdev[0]->dev; /* add this new MC control structure to EDAC's list of MCs */ if (unlikely(edac_mc_add_mc(mci))) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(0, "MC: failed edac_mc_add_mc()\n"); rc = -EINVAL; goto fail0; } @@ -1722,7 +1716,8 @@ static int __devinit sbridge_probe(struct pci_dev *pdev, mc = 0; list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { - debugf0("Registering MC#%d (%d of %d)\n", mc, mc + 1, num_mc); + edac_dbg(0, "Registering MC#%d (%d of %d)\n", + mc, mc + 1, num_mc); sbridge_dev->mc = mc++; rc = sbridge_register_mci(sbridge_dev); if (unlikely(rc < 0)) @@ -1752,7 +1747,7 @@ static void __devexit sbridge_remove(struct pci_dev *pdev) { struct sbridge_dev *sbridge_dev; - debugf0(__FILE__ ": %s()\n", __func__); + edac_dbg(0, "\n"); /* * we have a trouble here: pdev value for removal will be wrong, since @@ -1801,7 +1796,7 @@ static int __init sbridge_init(void) { int pci_rc; - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -1825,7 +1820,7 @@ static int __init sbridge_init(void) */ static void __exit sbridge_exit(void) { - debugf2("MC: " __FILE__ ": %s()\n", __func__); + edac_dbg(2, "\n"); pci_unregister_driver(&sbridge_driver); mce_unregister_decode_chain(&sbridge_mce_dec); } diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c index 7bb4614730d..1e904b7b79a 100644 --- a/drivers/edac/tile_edac.c +++ b/drivers/edac/tile_edac.c @@ -69,12 +69,12 @@ static void tile_edac_check(struct mem_ctl_info *mci) /* Check if the current error count is different from the saved one. */ if (mem_error.sbe_count != priv->ce_count) { - dev_dbg(mci->dev, "ECC CE err on node %d\n", priv->node); + dev_dbg(mci->pdev, "ECC CE err on node %d\n", priv->node); priv->ce_count = mem_error.sbe_count; - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, 0, 0, -1, - mci->ctl_name, "", NULL); + mci->ctl_name, ""); } } @@ -84,10 +84,10 @@ static void tile_edac_check(struct mem_ctl_info *mci) */ static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) { - struct csrow_info *csrow = &mci->csrows[0]; + struct csrow_info *csrow = mci->csrows[0]; struct tile_edac_priv *priv = mci->pvt_info; struct mshim_mem_info mem_info; - struct dimm_info *dimm = csrow->channels[0].dimm; + struct dimm_info *dimm = csrow->channels[0]->dimm; if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info, sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) != @@ -149,7 +149,7 @@ static int __devinit tile_edac_mc_probe(struct platform_device *pdev) priv->node = pdev->id; priv->hv_devhdl = hv_devhdl; - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index 1ac7962d63e..08a992693e6 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -103,10 +103,10 @@ static int how_many_channel(struct pci_dev *pdev) pci_read_config_byte(pdev, X38_CAPID0 + 8, &capid0_8b); if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ - debugf0("In single channel mode.\n"); + edac_dbg(0, "In single channel mode\n"); x38_channel_num = 1; } else { - debugf0("In dual channel mode.\n"); + edac_dbg(0, "In dual channel mode\n"); x38_channel_num = 2; } @@ -151,7 +151,7 @@ static void x38_clear_error_info(struct mem_ctl_info *mci) { struct pci_dev *pdev; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * Clear any error bits. @@ -172,7 +172,7 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, struct pci_dev *pdev; void __iomem *window = mci->pvt_info; - pdev = to_pci_dev(mci->dev); + pdev = to_pci_dev(mci->pdev); /* * This is a mess because there is no atomic way to read all the @@ -215,26 +215,26 @@ static void x38_process_error_info(struct mem_ctl_info *mci, return; if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 0, 0, 0, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, -1, -1, -1, - "UE overwrote CE", "", NULL); + "UE overwrote CE", ""); info->errsts = info->errsts2; } for (channel = 0; channel < x38_channel_num; channel++) { log = info->eccerrlog[channel]; if (log & X38_ECCERRLOG_UE) { - edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, eccerrlog_row(channel, log), -1, -1, - "x38 UE", "", NULL); + "x38 UE", ""); } else if (log & X38_ECCERRLOG_CE) { - edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, eccerrlog_syndrome(log), eccerrlog_row(channel, log), -1, -1, - "x38 CE", "", NULL); + "x38 CE", ""); } } } @@ -243,7 +243,7 @@ static void x38_check(struct mem_ctl_info *mci) { struct x38_error_info info; - debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + edac_dbg(1, "MC%d\n", mci->mc_idx); x38_get_and_clear_error_info(mci, &info); x38_process_error_info(mci, &info); } @@ -331,7 +331,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) bool stacked; void __iomem *window; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); window = x38_map_mchbar(pdev); if (!window) @@ -352,9 +352,9 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) if (!mci) return -ENOMEM; - debugf3("MC: %s(): init mci\n", __func__); + edac_dbg(3, "MC: init mci\n"); - mci->dev = &pdev->dev; + mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; @@ -378,7 +378,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) */ for (i = 0; i < mci->nr_csrows; i++) { unsigned long nr_pages; - struct csrow_info *csrow = &mci->csrows[i]; + struct csrow_info *csrow = mci->csrows[i]; nr_pages = drb_to_nr_pages(drbs, stacked, i / X38_RANKS_PER_CHANNEL, @@ -388,7 +388,7 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) continue; for (j = 0; j < x38_channel_num; j++) { - struct dimm_info *dimm = csrow->channels[j].dimm; + struct dimm_info *dimm = csrow->channels[j]->dimm; dimm->nr_pages = nr_pages / x38_channel_num; dimm->grain = nr_pages << PAGE_SHIFT; @@ -402,12 +402,12 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) rc = -ENODEV; if (edac_mc_add_mc(mci)) { - debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); goto fail; } /* get this far and it's successful */ - debugf3("MC: %s(): success\n", __func__); + edac_dbg(3, "MC: success\n"); return 0; fail: @@ -423,7 +423,7 @@ static int __devinit x38_init_one(struct pci_dev *pdev, { int rc; - debugf0("MC: %s()\n", __func__); + edac_dbg(0, "MC:\n"); if (pci_enable_device(pdev) < 0) return -EIO; @@ -439,7 +439,7 @@ static void __devexit x38_remove_one(struct pci_dev *pdev) { struct mem_ctl_info *mci; - debugf0("%s()\n", __func__); + edac_dbg(0, "\n"); mci = edac_mc_del_mc(&pdev->dev); if (!mci) @@ -472,7 +472,7 @@ static int __init x38_init(void) { int pci_rc; - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); @@ -486,14 +486,14 @@ static int __init x38_init(void) mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X38_HB, NULL); if (!mci_pdev) { - debugf0("x38 pci_get_device fail\n"); + edac_dbg(0, "x38 pci_get_device fail\n"); pci_rc = -ENODEV; goto fail1; } pci_rc = x38_init_one(mci_pdev, x38_pci_tbl); if (pci_rc < 0) { - debugf0("x38 init fail\n"); + edac_dbg(0, "x38 init fail\n"); pci_rc = -ENODEV; goto fail1; } @@ -513,7 +513,7 @@ fail0: static void __exit x38_exit(void) { - debugf3("MC: %s()\n", __func__); + edac_dbg(3, "MC:\n"); pci_unregister_driver(&x38_driver); if (!x38_registered) { diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 16716356d1f..e175c8ed4ec 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -33,7 +33,7 @@ config EXTCON_MAX77693 config EXTCON_MAX8997 tristate "MAX8997 EXTCON Support" - depends on MFD_MAX8997 + depends on MFD_MAX8997 && IRQ_DOMAIN help If you say yes here you get support for the MUIC device of Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index a4ed30bd9a4..ef9090a4271 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -26,6 +26,7 @@ #include <linux/mfd/max8997.h> #include <linux/mfd/max8997-private.h> #include <linux/extcon.h> +#include <linux/irqdomain.h> #define DEV_NAME "max8997-muic" @@ -77,6 +78,7 @@ struct max8997_muic_irq { unsigned int irq; const char *name; + unsigned int virq; }; static struct max8997_muic_irq muic_irqs[] = { @@ -343,12 +345,10 @@ static void max8997_muic_irq_work(struct work_struct *work) { struct max8997_muic_info *info = container_of(work, struct max8997_muic_info, irq_work); - struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); u8 status[2]; u8 adc, chg_type; - - int irq_type = info->irq - max8997->irq_base; - int ret; + int irq_type = 0; + int i, ret; mutex_lock(&info->mutex); @@ -363,6 +363,10 @@ static void max8997_muic_irq_work(struct work_struct *work) dev_dbg(info->dev, "%s: STATUS1:0x%x, 2:0x%x\n", __func__, status[0], status[1]); + for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++) + if (info->irq == muic_irqs[i].virq) + irq_type = muic_irqs[i].irq; + switch (irq_type) { case MAX8997_MUICIRQ_ADC: adc = status[0] & STATUS1_ADC_MASK; @@ -448,11 +452,15 @@ static int __devinit max8997_muic_probe(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) { struct max8997_muic_irq *muic_irq = &muic_irqs[i]; + int virq = 0; + + virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq); + if (!virq) + goto err_irq; + muic_irq->virq = virq; - ret = request_threaded_irq(pdata->irq_base + muic_irq->irq, - NULL, max8997_muic_irq_handler, - 0, muic_irq->name, - info); + ret = request_threaded_irq(virq, NULL,max8997_muic_irq_handler, + 0, muic_irq->name, info); if (ret) { dev_err(&pdev->dev, "failed: irq request (IRQ: %d," @@ -496,7 +504,7 @@ err_extcon: kfree(info->edev); err_irq: while (--i >= 0) - free_irq(pdata->irq_base + muic_irqs[i].irq, info); + free_irq(muic_irqs[i].virq, info); kfree(info); err_kfree: return ret; @@ -505,11 +513,10 @@ err_kfree: static int __devexit max8997_muic_remove(struct platform_device *pdev) { struct max8997_muic_info *info = platform_get_drvdata(pdev); - struct max8997_dev *max8997 = i2c_get_clientdata(info->muic); int i; for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) - free_irq(max8997->irq_base + muic_irqs[i].irq, info); + free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 4d460ef8716..7a05fd24d68 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -398,6 +398,14 @@ static ssize_t guid_show(struct device *dev, return ret; } +static ssize_t is_local_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fw_device *device = fw_device(dev); + + return sprintf(buf, "%u\n", device->is_local); +} + static int units_sprintf(char *buf, const u32 *directory) { struct fw_csr_iterator ci; @@ -447,6 +455,7 @@ static ssize_t units_show(struct device *dev, static struct device_attribute fw_device_attributes[] = { __ATTR_RO(config_rom), __ATTR_RO(guid), + __ATTR_RO(is_local), __ATTR_RO(units), __ATTR_NULL, }; diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 8382e27e9a2..38c0aa60b2c 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -146,7 +146,7 @@ EXPORT_SYMBOL(fw_iso_buffer_destroy); /* Convert DMA address to offset into virtually contiguous buffer. */ size_t fw_iso_buffer_lookup(struct fw_iso_buffer *buffer, dma_addr_t completed) { - int i; + size_t i; dma_addr_t address; ssize_t offset; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 780708dc6e2..87d6f2d2f02 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -525,9 +525,10 @@ const struct fw_address_region fw_high_memory_region = { .start = 0x000100000000ULL, .end = 0xffffe0000000ULL, }; EXPORT_SYMBOL(fw_high_memory_region); -#if 0 -const struct fw_address_region fw_low_memory_region = +static const struct fw_address_region low_memory_region = { .start = 0x000000000000ULL, .end = 0x000100000000ULL, }; + +#if 0 const struct fw_address_region fw_private_region = { .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL, }; const struct fw_address_region fw_csr_region = @@ -1198,6 +1199,23 @@ static struct fw_address_handler registers = { .address_callback = handle_registers, }; +static void handle_low_memory(struct fw_card *card, struct fw_request *request, + int tcode, int destination, int source, int generation, + unsigned long long offset, void *payload, size_t length, + void *callback_data) +{ + /* + * This catches requests not handled by the physical DMA unit, + * i.e., wrong transaction types or unauthorized source nodes. + */ + fw_send_response(card, request, RCODE_TYPE_ERROR); +} + +static struct fw_address_handler low_memory = { + .length = 0x000100000000ULL, + .address_callback = handle_low_memory, +}; + MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); MODULE_DESCRIPTION("Core IEEE1394 transaction logic"); MODULE_LICENSE("GPL"); @@ -1259,6 +1277,7 @@ static int __init fw_core_init(void) fw_core_add_address_handler(&topology_map, &topology_map_region); fw_core_add_address_handler(®isters, ®isters_region); + fw_core_add_address_handler(&low_memory, &low_memory_region); fw_core_add_descriptor(&vendor_id_descriptor); fw_core_add_descriptor(&model_id_descriptor); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index c1af05e834b..c788dbdaf3b 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -191,6 +191,7 @@ struct fw_ohci { unsigned quirks; unsigned int pri_req_max; u32 bus_time; + bool bus_time_running; bool is_root; bool csr_state_setclear_abdicate; int n_ir; @@ -1726,6 +1727,13 @@ static u32 update_bus_time(struct fw_ohci *ohci) { u32 cycle_time_seconds = get_cycle_time(ohci) >> 25; + if (unlikely(!ohci->bus_time_running)) { + reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_cycle64Seconds); + ohci->bus_time = (lower_32_bits(get_seconds()) & ~0x7f) | + (cycle_time_seconds & 0x40); + ohci->bus_time_running = true; + } + if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40)) ohci->bus_time += 0x40; @@ -2213,7 +2221,7 @@ static int ohci_enable(struct fw_card *card, { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); - u32 lps, seconds, version, irqs; + u32 lps, version, irqs; int i, ret; if (software_reset(ohci)) { @@ -2269,9 +2277,12 @@ static int ohci_enable(struct fw_card *card, (OHCI1394_MAX_PHYS_RESP_RETRIES << 8) | (200 << 16)); - seconds = lower_32_bits(get_seconds()); - reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25); - ohci->bus_time = seconds & ~0x3f; + ohci->bus_time_running = false; + + for (i = 0; i < 32; i++) + if (ohci->ir_context_support & (1 << i)) + reg_write(ohci, OHCI1394_IsoRcvContextControlClear(i), + IR_CONTEXT_MULTI_CHANNEL_MODE); version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; if (version >= OHCI_VERSION_1_1) { @@ -2369,7 +2380,6 @@ static int ohci_enable(struct fw_card *card, OHCI1394_postedWriteErr | OHCI1394_selfIDComplete | OHCI1394_regAccessFail | - OHCI1394_cycle64Seconds | OHCI1394_cycleInconsistent | OHCI1394_unrecoverableError | OHCI1394_cycleTooLong | @@ -2658,7 +2668,8 @@ static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value) case CSR_BUS_TIME: spin_lock_irqsave(&ohci->lock, flags); - ohci->bus_time = (ohci->bus_time & 0x7f) | (value & ~0x7f); + ohci->bus_time = (update_bus_time(ohci) & 0x40) | + (value & ~0x7f); spin_unlock_irqrestore(&ohci->lock, flags); break; @@ -3539,6 +3550,13 @@ static int __devinit pci_probe(struct pci_dev *dev, INIT_WORK(&ohci->bus_reset_work, bus_reset_work); + if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) || + pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) { + dev_err(&dev->dev, "invalid MMIO resource\n"); + err = -ENXIO; + goto fail_disable; + } + err = pci_request_region(dev, 0, ohci_driver_name); if (err) { dev_err(&dev->dev, "MMIO resource unavailable\n"); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 502b5ea43f4..b16c8a72a2e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -597,6 +597,13 @@ config GPIO_AB8500 help Select this to enable the AB8500 IC GPIO driver +config GPIO_TPS6586X + bool "TPS6586X GPIO" + depends on MFD_TPS6586X + help + Select this option to enable GPIO driver for the TPS6586X + chip family. + config GPIO_TPS65910 bool "TPS65910 GPIO" depends on MFD_TPS65910 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d37048105a8..153caceeb05 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o obj-$(CONFIG_ARCH_TEGRA) += gpio-tegra.o obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o +obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c new file mode 100644 index 00000000000..2526b3bb0fa --- /dev/null +++ b/drivers/gpio/gpio-tps6586x.c @@ -0,0 +1,158 @@ +/* + * TI TPS6586x GPIO driver + * + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Author: Laxman dewangan <ldewangan@nvidia.com> + * + * Based on tps6586x.c + * Copyright (c) 2010 CompuLab Ltd. + * Mike Rapoport <mike@compulab.co.il> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/errno.h> +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mfd/tps6586x.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +/* GPIO control registers */ +#define TPS6586X_GPIOSET1 0x5d +#define TPS6586X_GPIOSET2 0x5e + +struct tps6586x_gpio { + struct gpio_chip gpio_chip; + struct device *parent; +}; + +static inline struct tps6586x_gpio *to_tps6586x_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct tps6586x_gpio, gpio_chip); +} + +static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); + uint8_t val; + int ret; + + ret = tps6586x_read(tps6586x_gpio->parent, TPS6586X_GPIOSET2, &val); + if (ret) + return ret; + + return !!(val & (1 << offset)); +} + +static void tps6586x_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); + + tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET2, + value << offset, 1 << offset); +} + +static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct tps6586x_gpio *tps6586x_gpio = to_tps6586x_gpio(gc); + uint8_t val, mask; + + tps6586x_gpio_set(gc, offset, value); + + val = 0x1 << (offset * 2); + mask = 0x3 << (offset * 2); + + return tps6586x_update(tps6586x_gpio->parent, TPS6586X_GPIOSET1, + val, mask); +} + +static int __devinit tps6586x_gpio_probe(struct platform_device *pdev) +{ + struct tps6586x_platform_data *pdata; + struct tps6586x_gpio *tps6586x_gpio; + int ret; + + pdata = dev_get_platdata(pdev->dev.parent); + tps6586x_gpio = devm_kzalloc(&pdev->dev, + sizeof(*tps6586x_gpio), GFP_KERNEL); + if (!tps6586x_gpio) { + dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n"); + return -ENOMEM; + } + + tps6586x_gpio->parent = pdev->dev.parent; + + tps6586x_gpio->gpio_chip.owner = THIS_MODULE; + tps6586x_gpio->gpio_chip.label = pdev->name; + tps6586x_gpio->gpio_chip.dev = &pdev->dev; + tps6586x_gpio->gpio_chip.ngpio = 4; + tps6586x_gpio->gpio_chip.can_sleep = 1; + + /* FIXME: add handling of GPIOs as dedicated inputs */ + tps6586x_gpio->gpio_chip.direction_output = tps6586x_gpio_output; + tps6586x_gpio->gpio_chip.set = tps6586x_gpio_set; + tps6586x_gpio->gpio_chip.get = tps6586x_gpio_get; + +#ifdef CONFIG_OF_GPIO + tps6586x_gpio->gpio_chip.of_node = pdev->dev.parent->of_node; +#endif + if (pdata && pdata->gpio_base) + tps6586x_gpio->gpio_chip.base = pdata->gpio_base; + else + tps6586x_gpio->gpio_chip.base = -1; + + ret = gpiochip_add(&tps6586x_gpio->gpio_chip); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, tps6586x_gpio); + + return ret; +} + +static int __devexit tps6586x_gpio_remove(struct platform_device *pdev) +{ + struct tps6586x_gpio *tps6586x_gpio = platform_get_drvdata(pdev); + + return gpiochip_remove(&tps6586x_gpio->gpio_chip); +} + +static struct platform_driver tps6586x_gpio_driver = { + .driver.name = "tps6586x-gpio", + .driver.owner = THIS_MODULE, + .probe = tps6586x_gpio_probe, + .remove = __devexit_p(tps6586x_gpio_remove), +}; + +static int __init tps6586x_gpio_init(void) +{ + return platform_driver_register(&tps6586x_gpio_driver); +} +subsys_initcall(tps6586x_gpio_init); + +static void __exit tps6586x_gpio_exit(void) +{ + platform_driver_unregister(&tps6586x_gpio_driver); +} +module_exit(tps6586x_gpio_exit); + +MODULE_ALIAS("platform:tps6586x-gpio"); +MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC"); +MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index bf791fa0e50..d9568198c30 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -196,7 +196,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector, return ret; } -struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) +static struct drm_encoder *exynos_drm_best_encoder( + struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct exynos_drm_connector *exynos_connector = diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c index eaf630dc5db..84dd099eae3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_core.c +++ b/drivers/gpu/drm/exynos/exynos_drm_core.c @@ -33,7 +33,6 @@ #include "exynos_drm_fbdev.h" static LIST_HEAD(exynos_drm_subdrv_list); -static struct drm_device *drm_dev; static int exynos_drm_subdrv_probe(struct drm_device *dev, struct exynos_drm_subdrv *subdrv) @@ -120,8 +119,6 @@ int exynos_drm_device_register(struct drm_device *dev) if (!dev) return -EINVAL; - drm_dev = dev; - list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { subdrv->drm_dev = dev; err = exynos_drm_subdrv_probe(dev, subdrv); @@ -149,8 +146,6 @@ int exynos_drm_device_unregister(struct drm_device *dev) list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) exynos_drm_subdrv_remove(dev, subdrv); - drm_dev = NULL; - return 0; } EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 32a34c85899..abb1e2f8227 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -29,21 +29,23 @@ #include "drmP.h" #include "drm_crtc_helper.h" -#include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" -#include "exynos_drm_fb.h" #include "exynos_drm_encoder.h" -#include "exynos_drm_gem.h" +#include "exynos_drm_plane.h" #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ drm_crtc) +enum exynos_crtc_mode { + CRTC_MODE_NORMAL, /* normal mode */ + CRTC_MODE_BLANK, /* The private plane of crtc is blank */ +}; + /* * Exynos specific crtc structure. * * @drm_crtc: crtc object. - * @overlay: contain information common to display controller and hdmi and - * contents of this overlay object would be copied to sub driver size. + * @drm_plane: pointer of private plane object for this crtc * @pipe: a crtc index created at load() with a new crtc object creation * and the crtc object would be set to private->crtc array * to get a crtc object corresponding to this pipe from private->crtc @@ -52,115 +54,16 @@ * we can refer to the crtc to current hardware interrupt occured through * this pipe value. * @dpms: store the crtc dpms value + * @mode: store the crtc mode value */ struct exynos_drm_crtc { struct drm_crtc drm_crtc; - struct exynos_drm_overlay overlay; + struct drm_plane *plane; unsigned int pipe; unsigned int dpms; + enum exynos_crtc_mode mode; }; -static void exynos_drm_crtc_apply(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_overlay *overlay = &exynos_crtc->overlay; - - exynos_drm_fn_encoder(crtc, overlay, - exynos_drm_encoder_crtc_mode_set); - exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, - exynos_drm_encoder_crtc_commit); -} - -int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, - struct drm_framebuffer *fb, - struct drm_display_mode *mode, - struct exynos_drm_crtc_pos *pos) -{ - struct exynos_drm_gem_buf *buffer; - unsigned int actual_w; - unsigned int actual_h; - int nr = exynos_drm_format_num_buffers(fb->pixel_format); - int i; - - for (i = 0; i < nr; i++) { - buffer = exynos_drm_fb_buffer(fb, i); - if (!buffer) { - DRM_LOG_KMS("buffer is null\n"); - return -EFAULT; - } - - overlay->dma_addr[i] = buffer->dma_addr; - overlay->vaddr[i] = buffer->kvaddr; - - DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n", - i, (unsigned long)overlay->vaddr[i], - (unsigned long)overlay->dma_addr[i]); - } - - actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w); - actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h); - - /* set drm framebuffer data. */ - overlay->fb_x = pos->fb_x; - overlay->fb_y = pos->fb_y; - overlay->fb_width = fb->width; - overlay->fb_height = fb->height; - overlay->src_width = pos->src_w; - overlay->src_height = pos->src_h; - overlay->bpp = fb->bits_per_pixel; - overlay->pitch = fb->pitches[0]; - overlay->pixel_format = fb->pixel_format; - - /* set overlay range to be displayed. */ - overlay->crtc_x = pos->crtc_x; - overlay->crtc_y = pos->crtc_y; - overlay->crtc_width = actual_w; - overlay->crtc_height = actual_h; - - /* set drm mode data. */ - overlay->mode_width = mode->hdisplay; - overlay->mode_height = mode->vdisplay; - overlay->refresh = mode->vrefresh; - overlay->scan_flag = mode->flags; - - DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", - overlay->crtc_x, overlay->crtc_y, - overlay->crtc_width, overlay->crtc_height); - - return 0; -} - -static int exynos_drm_crtc_update(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc; - struct exynos_drm_overlay *overlay; - struct exynos_drm_crtc_pos pos; - struct drm_display_mode *mode = &crtc->mode; - struct drm_framebuffer *fb = crtc->fb; - - if (!mode || !fb) - return -EINVAL; - - exynos_crtc = to_exynos_crtc(crtc); - overlay = &exynos_crtc->overlay; - - memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); - - /* it means the offset of framebuffer to be displayed. */ - pos.fb_x = crtc->x; - pos.fb_y = crtc->y; - - /* OSD position to be displayed. */ - pos.crtc_x = 0; - pos.crtc_y = 0; - pos.crtc_w = fb->width - crtc->x; - pos.crtc_h = fb->height - crtc->y; - pos.src_w = pos.crtc_w; - pos.src_h = pos.crtc_h; - - return exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos); -} - static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; @@ -175,23 +78,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) mutex_lock(&dev->struct_mutex); - switch (mode) { - case DRM_MODE_DPMS_ON: - exynos_drm_fn_encoder(crtc, &mode, - exynos_drm_encoder_crtc_dpms); - exynos_crtc->dpms = mode; - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - exynos_drm_fn_encoder(crtc, &mode, - exynos_drm_encoder_crtc_dpms); - exynos_crtc->dpms = mode; - break; - default: - DRM_ERROR("unspecified mode %d\n", mode); - break; - } + exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); + exynos_crtc->dpms = mode; mutex_unlock(&dev->struct_mutex); } @@ -209,30 +97,8 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc) DRM_DEBUG_KMS("%s\n", __FILE__); - /* - * when set_crtc is requested from user or at booting time, - * crtc->commit would be called without dpms call so if dpms is - * no power on then crtc->dpms should be called - * with DRM_MODE_DPMS_ON for the hardware power to be on. - */ - if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) { - int mode = DRM_MODE_DPMS_ON; - - /* - * enable hardware(power on) to all encoders hdmi connected - * to current crtc. - */ - exynos_drm_crtc_dpms(crtc, mode); - /* - * enable dma to all encoders connected to current crtc and - * lcd panel. - */ - exynos_drm_fn_encoder(crtc, &mode, - exynos_drm_encoder_dpms_from_crtc); - } - - exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe, - exynos_drm_encoder_crtc_commit); + exynos_plane_commit(exynos_crtc->plane); + exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); } static bool @@ -251,31 +117,61 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct drm_plane *plane = exynos_crtc->plane; + unsigned int crtc_w; + unsigned int crtc_h; + int pipe = exynos_crtc->pipe; + int ret; + DRM_DEBUG_KMS("%s\n", __FILE__); + exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); + /* * copy the mode data adjusted by mode_fixup() into crtc->mode * so that hardware can be seet to proper mode. */ memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); - return exynos_drm_crtc_update(crtc); + crtc_w = crtc->fb->width - x; + crtc_h = crtc->fb->height - y; + + ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, + x, y, crtc_w, crtc_h); + if (ret) + return ret; + + plane->crtc = crtc; + plane->fb = crtc->fb; + + exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe); + + return 0; } static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct drm_plane *plane = exynos_crtc->plane; + unsigned int crtc_w; + unsigned int crtc_h; int ret; DRM_DEBUG_KMS("%s\n", __FILE__); - ret = exynos_drm_crtc_update(crtc); + crtc_w = crtc->fb->width - x; + crtc_h = crtc->fb->height - y; + + ret = exynos_plane_mode_set(plane, crtc, crtc->fb, 0, 0, crtc_w, crtc_h, + x, y, crtc_w, crtc_h); if (ret) return ret; - exynos_drm_crtc_apply(crtc); + exynos_drm_crtc_commit(crtc); - return ret; + return 0; } static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc) @@ -284,6 +180,16 @@ static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc) /* drm framework doesn't check NULL */ } +static void exynos_drm_crtc_disable(struct drm_crtc *crtc) +{ + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + + DRM_DEBUG_KMS("%s\n", __FILE__); + + exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF); + exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +} + static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .dpms = exynos_drm_crtc_dpms, .prepare = exynos_drm_crtc_prepare, @@ -292,6 +198,7 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .mode_set = exynos_drm_crtc_mode_set, .mode_set_base = exynos_drm_crtc_mode_set_base, .load_lut = exynos_drm_crtc_load_lut, + .disable = exynos_drm_crtc_disable, }; static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, @@ -327,7 +234,8 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, &dev_priv->pageflip_event_list); crtc->fb = fb; - ret = exynos_drm_crtc_update(crtc); + ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y, + NULL); if (ret) { crtc->fb = old_fb; drm_vblank_put(dev, exynos_crtc->pipe); @@ -335,14 +243,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, goto out; } - - /* - * the values related to a buffer of the drm framebuffer - * to be applied should be set at here. because these values - * first, are set to shadow registers and then to - * real registers at vsync front porch period. - */ - exynos_drm_crtc_apply(crtc); } out: mutex_unlock(&dev->struct_mutex); @@ -362,18 +262,73 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) kfree(exynos_crtc); } +static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = crtc->dev; + struct exynos_drm_private *dev_priv = dev->dev_private; + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + + DRM_DEBUG_KMS("%s\n", __func__); + + if (property == dev_priv->crtc_mode_property) { + enum exynos_crtc_mode mode = val; + + if (mode == exynos_crtc->mode) + return 0; + + exynos_crtc->mode = mode; + + switch (mode) { + case CRTC_MODE_NORMAL: + exynos_drm_crtc_commit(crtc); + break; + case CRTC_MODE_BLANK: + exynos_plane_dpms(exynos_crtc->plane, + DRM_MODE_DPMS_OFF); + break; + default: + break; + } + + return 0; + } + + return -EINVAL; +} + static struct drm_crtc_funcs exynos_crtc_funcs = { .set_config = drm_crtc_helper_set_config, .page_flip = exynos_drm_crtc_page_flip, .destroy = exynos_drm_crtc_destroy, + .set_property = exynos_drm_crtc_set_property, +}; + +static const struct drm_prop_enum_list mode_names[] = { + { CRTC_MODE_NORMAL, "normal" }, + { CRTC_MODE_BLANK, "blank" }, }; -struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev, - struct drm_crtc *crtc) +static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) { - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct exynos_drm_private *dev_priv = dev->dev_private; + struct drm_property *prop; - return &exynos_crtc->overlay; + DRM_DEBUG_KMS("%s\n", __func__); + + prop = dev_priv->crtc_mode_property; + if (!prop) { + prop = drm_property_create_enum(dev, 0, "mode", mode_names, + ARRAY_SIZE(mode_names)); + if (!prop) + return; + + dev_priv->crtc_mode_property = prop; + } + + drm_object_attach_property(&crtc->base, prop, 0); } int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) @@ -392,7 +347,12 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) exynos_crtc->pipe = nr; exynos_crtc->dpms = DRM_MODE_DPMS_OFF; - exynos_crtc->overlay.zpos = DEFAULT_ZPOS; + exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); + if (!exynos_crtc->plane) { + kfree(exynos_crtc); + return -ENOMEM; + } + crtc = &exynos_crtc->drm_crtc; private->crtc[nr] = crtc; @@ -400,6 +360,8 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) drm_crtc_init(dev, crtc, &exynos_crtc_funcs); drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); + exynos_drm_crtc_attach_mode_property(crtc); + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 16b8e2195a0..6bae8d8c250 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -29,39 +29,8 @@ #ifndef _EXYNOS_DRM_CRTC_H_ #define _EXYNOS_DRM_CRTC_H_ -struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev, - struct drm_crtc *crtc); int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); -/* - * Exynos specific crtc postion structure. - * - * @fb_x: offset x on a framebuffer to be displyed - * - the unit is screen coordinates. - * @fb_y: offset y on a framebuffer to be displayed - * - the unit is screen coordinates. - * @src_w: width of source area to be displayed from a framebuffer. - * @src_h: height of source area to be displayed from a framebuffer. - * @crtc_x: offset x on hardware screen. - * @crtc_y: offset y on hardware screen. - * @crtc_w: width of hardware screen. - * @crtc_h: height of hardware screen. - */ -struct exynos_drm_crtc_pos { - unsigned int fb_x; - unsigned int fb_y; - unsigned int src_w; - unsigned int src_h; - unsigned int crtc_x; - unsigned int crtc_y; - unsigned int crtc_w; - unsigned int crtc_h; -}; - -int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, - struct drm_framebuffer *fb, - struct drm_display_mode *mode, - struct exynos_drm_crtc_pos *pos); #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 274909271c3..613bf8a5d9b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -25,6 +25,7 @@ #include "drmP.h" #include "drm.h" +#include "exynos_drm.h" #include "exynos_drm_drv.h" #include "exynos_drm_gem.h" @@ -86,6 +87,10 @@ static struct sg_table * npages = buf->size / buf->page_size; sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size); + if (!sgt) { + DRM_DEBUG_PRIME("exynos_pages_to_sg returned NULL!\n"); + goto err_unlock; + } nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n", @@ -186,7 +191,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, struct exynos_drm_gem_obj *exynos_gem_obj; struct exynos_drm_gem_buf *buffer; struct page *page; - int ret, i = 0; + int ret; DRM_DEBUG_PRIME("%s\n", __FILE__); @@ -210,7 +215,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); - if (IS_ERR(sgt)) { + if (IS_ERR_OR_NULL(sgt)) { ret = PTR_ERR(sgt); goto err_buf_detach; } @@ -236,13 +241,25 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, } sgl = sgt->sgl; - buffer->dma_addr = sg_dma_address(sgl); - while (i < sgt->nents) { - buffer->pages[i] = sg_page(sgl); - buffer->size += sg_dma_len(sgl); - sgl = sg_next(sgl); - i++; + if (sgt->nents == 1) { + buffer->dma_addr = sg_dma_address(sgt->sgl); + buffer->size = sg_dma_len(sgt->sgl); + + /* always physically continuous memory if sgt->nents is 1. */ + exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; + } else { + unsigned int i = 0; + + buffer->dma_addr = sg_dma_address(sgl); + while (i < sgt->nents) { + buffer->pages[i] = sg_page(sgl); + buffer->size += sg_dma_len(sgl); + sgl = sg_next(sgl); + i++; + } + + exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; } exynos_gem_obj->buffer = buffer; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index d6de2e07fa0..ebacec6f1e4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -85,8 +85,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) } for (nr = 0; nr < MAX_PLANE; nr++) { - ret = exynos_plane_init(dev, nr); - if (ret) + struct drm_plane *plane; + unsigned int possible_crtcs = (1 << MAX_CRTC) - 1; + + plane = exynos_plane_init(dev, possible_crtcs, false); + if (!plane) goto err_crtc; } @@ -221,8 +224,6 @@ static struct drm_ioctl_desc exynos_ioctls[] = { exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS, exynos_plane_set_zpos_ioctl, - DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl, DRM_UNLOCKED | DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 277653d5fda..e22704b249d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -59,12 +59,14 @@ enum exynos_drm_output_type { * * @mode_set: copy drm overlay info to hw specific overlay info. * @commit: apply hardware specific overlay data to registers. + * @enable: enable hardware specific overlay. * @disable: disable hardware specific overlay. */ struct exynos_drm_overlay_ops { void (*mode_set)(struct device *subdrv_dev, struct exynos_drm_overlay *overlay); void (*commit)(struct device *subdrv_dev, int zpos); + void (*enable)(struct device *subdrv_dev, int zpos); void (*disable)(struct device *subdrv_dev, int zpos); }; @@ -235,6 +237,8 @@ struct exynos_drm_private { * this array is used to be aware of which crtc did it request vblank. */ struct drm_crtc *crtc[MAX_CRTC]; + struct drm_property *plane_zpos_property; + struct drm_property *crtc_mode_property; }; /* diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 4a13a747f5d..2c037cd7d2d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -30,7 +30,6 @@ #include "drm_crtc_helper.h" #include "exynos_drm_drv.h" -#include "exynos_drm_crtc.h" #include "exynos_drm_encoder.h" #define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ @@ -136,21 +135,16 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, struct drm_connector *connector; struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); struct exynos_drm_manager_ops *manager_ops = manager->ops; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev, - encoder->crtc); DRM_DEBUG_KMS("%s\n", __FILE__); + exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { + if (connector->encoder == encoder) if (manager_ops && manager_ops->mode_set) manager_ops->mode_set(manager->dev, adjusted_mode); - - if (overlay_ops && overlay_ops->mode_set) - overlay_ops->mode_set(manager->dev, overlay); - } } } @@ -310,8 +304,8 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) struct exynos_drm_manager_ops *manager_ops = manager->ops; int crtc = *(int *)data; - if (manager->pipe == -1) - manager->pipe = crtc; + if (manager->pipe != crtc) + return; if (manager_ops->enable_vblank) manager_ops->enable_vblank(manager->dev); @@ -324,34 +318,41 @@ void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) struct exynos_drm_manager_ops *manager_ops = manager->ops; int crtc = *(int *)data; - if (manager->pipe == -1) - manager->pipe = crtc; + if (manager->pipe != crtc) + return; if (manager_ops->disable_vblank) manager_ops->disable_vblank(manager->dev); } -void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, - void *data) +void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) { - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - int zpos = DEFAULT_ZPOS; + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); + struct exynos_drm_manager *manager = exynos_encoder->manager; + struct exynos_drm_manager_ops *manager_ops = manager->ops; + int mode = *(int *)data; - if (data) - zpos = *(int *)data; + DRM_DEBUG_KMS("%s\n", __FILE__); - if (overlay_ops && overlay_ops->commit) - overlay_ops->commit(manager->dev, zpos); + if (manager_ops && manager_ops->dpms) + manager_ops->dpms(manager->dev, mode); + + /* + * if this condition is ok then it means that the crtc is already + * detached from encoder and last function for detaching is properly + * done, so clear pipe from manager to prevent repeated call. + */ + if (mode > DRM_MODE_DPMS_ON) { + if (!encoder->crtc) + manager->pipe = -1; + } } -void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) +void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data) { struct exynos_drm_manager *manager = to_exynos_encoder(encoder)->manager; - int crtc = *(int *)data; - int zpos = DEFAULT_ZPOS; + int pipe = *(int *)data; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -359,76 +360,62 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) * when crtc is detached from encoder, this pipe is used * to select manager operation */ - manager->pipe = crtc; - - exynos_drm_encoder_crtc_plane_commit(encoder, &zpos); + manager->pipe = pipe; } -void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, void *data) +void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data) { - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - int mode = *(int *)data; + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + struct exynos_drm_overlay *overlay = data; DRM_DEBUG_KMS("%s\n", __FILE__); - exynos_drm_encoder_dpms(encoder, mode); - - exynos_encoder->dpms = mode; + if (overlay_ops && overlay_ops->mode_set) + overlay_ops->mode_set(manager->dev, overlay); } -void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) +void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data) { - struct drm_device *dev = encoder->dev; - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); - struct exynos_drm_manager *manager = exynos_encoder->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - struct drm_connector *connector; - int mode = *(int *)data; + struct exynos_drm_manager *manager = + to_exynos_encoder(encoder)->manager; + struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; + int zpos = DEFAULT_ZPOS; DRM_DEBUG_KMS("%s\n", __FILE__); - if (manager_ops && manager_ops->dpms) - manager_ops->dpms(manager->dev, mode); - - /* - * set current dpms mode to the connector connected to - * current encoder. connector->dpms would be checked - * at drm_helper_connector_dpms() - */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) - if (connector->encoder == encoder) - connector->dpms = mode; + if (data) + zpos = *(int *)data; - /* - * if this condition is ok then it means that the crtc is already - * detached from encoder and last function for detaching is properly - * done, so clear pipe from manager to prevent repeated call. - */ - if (mode > DRM_MODE_DPMS_ON) { - if (!encoder->crtc) - manager->pipe = -1; - } + if (overlay_ops && overlay_ops->commit) + overlay_ops->commit(manager->dev, zpos); } -void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) +void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data) { struct exynos_drm_manager *manager = to_exynos_encoder(encoder)->manager; struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - struct exynos_drm_overlay *overlay = data; + int zpos = DEFAULT_ZPOS; - if (overlay_ops && overlay_ops->mode_set) - overlay_ops->mode_set(manager->dev, overlay); + DRM_DEBUG_KMS("%s\n", __FILE__); + + if (data) + zpos = *(int *)data; + + if (overlay_ops && overlay_ops->enable) + overlay_ops->enable(manager->dev, zpos); } -void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data) +void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) { struct exynos_drm_manager *manager = to_exynos_encoder(encoder)->manager; struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; int zpos = DEFAULT_ZPOS; - DRM_DEBUG_KMS("\n"); + DRM_DEBUG_KMS("%s\n", __FILE__); if (data) zpos = *(int *)data; diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/drivers/gpu/drm/exynos/exynos_drm_encoder.h index eb7d2316847..6470d9ddf5a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.h @@ -40,13 +40,11 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, void (*fn)(struct drm_encoder *, void *)); void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_plane_commit(struct drm_encoder *encoder, - void *data); -void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_dpms_from_crtc(struct drm_encoder *encoder, - void *data); void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data); +void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data); +void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data); +void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data); +void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data); +void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data); #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 29fdbfeb43c..a68d2b313f0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -78,7 +78,6 @@ struct fimd_context { struct drm_crtc *crtc; struct clk *bus_clk; struct clk *lcd_clk; - struct resource *regs_res; void __iomem *regs; struct fimd_win_data win_data[WINDOWS_NR]; unsigned int clkdiv; @@ -813,7 +812,7 @@ static int __devinit fimd_probe(struct platform_device *pdev) return -EINVAL; } - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -838,33 +837,26 @@ static int __devinit fimd_probe(struct platform_device *pdev) goto err_clk; } - ctx->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!ctx->regs_res) { - dev_err(dev, "failed to claim register region\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs = ioremap(res->start, resource_size(res)); + ctx->regs = devm_request_and_ioremap(&pdev->dev, res); if (!ctx->regs) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; - goto err_req_region_io; + goto err_clk; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "irq request failed.\n"); - goto err_req_region_irq; + goto err_clk; } ctx->irq = res->start; - ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx); - if (ret < 0) { + ret = devm_request_irq(&pdev->dev, ctx->irq, fimd_irq_handler, + 0, "drm_fimd", ctx); + if (ret) { dev_err(dev, "irq request failed.\n"); - goto err_req_irq; + goto err_clk; } ctx->vidcon0 = pdata->vidcon0; @@ -899,14 +891,6 @@ static int __devinit fimd_probe(struct platform_device *pdev) return 0; -err_req_irq: -err_req_region_irq: - iounmap(ctx->regs); - -err_req_region_io: - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - err_clk: clk_disable(ctx->lcd_clk); clk_put(ctx->lcd_clk); @@ -916,7 +900,6 @@ err_bus_clk: clk_put(ctx->bus_clk); err_clk_get: - kfree(ctx); return ret; } @@ -944,13 +927,6 @@ out: clk_put(ctx->lcd_clk); clk_put(ctx->bus_clk); - iounmap(ctx->regs); - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - free_irq(ctx->irq, ctx); - - kfree(ctx); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 5c8b683029e..f9efde40c09 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -99,25 +99,17 @@ out: struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask) { - struct inode *inode; - struct address_space *mapping; struct page *p, **pages; int i, npages; - /* This is the shared memory object that backs the GEM resource */ - inode = obj->filp->f_path.dentry->d_inode; - mapping = inode->i_mapping; - npages = obj->size >> PAGE_SHIFT; pages = drm_malloc_ab(npages, sizeof(struct page *)); if (pages == NULL) return ERR_PTR(-ENOMEM); - gfpmask |= mapping_gfp_mask(mapping); - for (i = 0; i < npages; i++) { - p = shmem_read_mapping_page_gfp(mapping, i, gfpmask); + p = alloc_page(gfpmask); if (IS_ERR(p)) goto fail; pages[i] = p; @@ -126,31 +118,22 @@ struct page **exynos_gem_get_pages(struct drm_gem_object *obj, return pages; fail: - while (i--) - page_cache_release(pages[i]); + while (--i) + __free_page(pages[i]); drm_free_large(pages); return ERR_PTR(PTR_ERR(p)); } static void exynos_gem_put_pages(struct drm_gem_object *obj, - struct page **pages, - bool dirty, bool accessed) + struct page **pages) { - int i, npages; + int npages; npages = obj->size >> PAGE_SHIFT; - for (i = 0; i < npages; i++) { - if (dirty) - set_page_dirty(pages[i]); - - if (accessed) - mark_page_accessed(pages[i]); - - /* Undo the reference we took when populating the table */ - page_cache_release(pages[i]); - } + while (--npages >= 0) + __free_page(pages[npages]); drm_free_large(pages); } @@ -189,7 +172,7 @@ static int exynos_drm_gem_get_pages(struct drm_gem_object *obj) return -EINVAL; } - pages = exynos_gem_get_pages(obj, GFP_KERNEL); + pages = exynos_gem_get_pages(obj, GFP_HIGHUSER_MOVABLE); if (IS_ERR(pages)) { DRM_ERROR("failed to get pages.\n"); return PTR_ERR(pages); @@ -230,7 +213,7 @@ err1: kfree(buf->sgt); buf->sgt = NULL; err: - exynos_gem_put_pages(obj, pages, true, false); + exynos_gem_put_pages(obj, pages); return ret; } @@ -248,7 +231,7 @@ static void exynos_drm_gem_put_pages(struct drm_gem_object *obj) kfree(buf->sgt); buf->sgt = NULL; - exynos_gem_put_pages(obj, buf->pages, true, false); + exynos_gem_put_pages(obj, buf->pages); buf->pages = NULL; /* add some codes for UNCACHED type here. TODO */ @@ -291,11 +274,21 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) if (!buf->pages) return; + /* + * do not release memory region from exporter. + * + * the region will be released by exporter + * once dmabuf's refcount becomes 0. + */ + if (obj->import_attach) + goto out; + if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) exynos_drm_gem_put_pages(obj); else exynos_drm_free_buf(obj->dev, exynos_gem_obj->flags, buf); +out: exynos_drm_fini_buf(obj->dev, buf); exynos_gem_obj->buffer = NULL; @@ -668,7 +661,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv, * with DRM_IOCTL_MODE_CREATE_DUMB command. */ - args->pitch = args->width * args->bpp >> 3; + args->pitch = args->width * ((args->bpp + 7) / 8); args->size = PAGE_ALIGN(args->pitch * args->height); exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size); diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 14d038b6cb0..085b2a5d5f7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -63,7 +63,8 @@ struct exynos_drm_gem_buf { * by user request or at framebuffer creation. * continuous memory region allocated by user request * or at framebuffer creation. - * @size: total memory size to physically non-continuous memory region. + * @size: size requested from user, in bytes and this size is aligned + * in page unit. * @flags: indicate memory type to allocated buffer and cache attruibute. * * P.S. this object would be transfered to user as kms_bo.handle so diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c4c6525d465..b89829e5043 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -12,9 +12,12 @@ #include "drmP.h" #include "exynos_drm.h" -#include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" #include "exynos_drm_encoder.h" +#include "exynos_drm_fb.h" +#include "exynos_drm_gem.h" + +#define to_exynos_plane(x) container_of(x, struct exynos_plane, base) struct exynos_plane { struct drm_plane base; @@ -30,6 +33,108 @@ static const uint32_t formats[] = { DRM_FORMAT_NV12MT, }; +int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct exynos_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_overlay *overlay = &exynos_plane->overlay; + unsigned int actual_w; + unsigned int actual_h; + int nr; + int i; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + nr = exynos_drm_format_num_buffers(fb->pixel_format); + for (i = 0; i < nr; i++) { + struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i); + + if (!buffer) { + DRM_LOG_KMS("buffer is null\n"); + return -EFAULT; + } + + overlay->dma_addr[i] = buffer->dma_addr; + overlay->vaddr[i] = buffer->kvaddr; + + DRM_DEBUG_KMS("buffer: %d, vaddr = 0x%lx, dma_addr = 0x%lx\n", + i, (unsigned long)overlay->vaddr[i], + (unsigned long)overlay->dma_addr[i]); + } + + actual_w = min((unsigned)(crtc->mode.hdisplay - crtc_x), crtc_w); + actual_h = min((unsigned)(crtc->mode.vdisplay - crtc_y), crtc_h); + + /* set drm framebuffer data. */ + overlay->fb_x = src_x; + overlay->fb_y = src_y; + overlay->fb_width = fb->width; + overlay->fb_height = fb->height; + overlay->src_width = src_w; + overlay->src_height = src_h; + overlay->bpp = fb->bits_per_pixel; + overlay->pitch = fb->pitches[0]; + overlay->pixel_format = fb->pixel_format; + + /* set overlay range to be displayed. */ + overlay->crtc_x = crtc_x; + overlay->crtc_y = crtc_y; + overlay->crtc_width = actual_w; + overlay->crtc_height = actual_h; + + /* set drm mode data. */ + overlay->mode_width = crtc->mode.hdisplay; + overlay->mode_height = crtc->mode.vdisplay; + overlay->refresh = crtc->mode.vrefresh; + overlay->scan_flag = crtc->mode.flags; + + DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", + overlay->crtc_x, overlay->crtc_y, + overlay->crtc_width, overlay->crtc_height); + + exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set); + + return 0; +} + +void exynos_plane_commit(struct drm_plane *plane) +{ + struct exynos_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_overlay *overlay = &exynos_plane->overlay; + + exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, + exynos_drm_encoder_plane_commit); +} + +void exynos_plane_dpms(struct drm_plane *plane, int mode) +{ + struct exynos_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_overlay *overlay = &exynos_plane->overlay; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + if (mode == DRM_MODE_DPMS_ON) { + if (exynos_plane->enabled) + return; + + exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, + exynos_drm_encoder_plane_enable); + + exynos_plane->enabled = true; + } else { + if (!exynos_plane->enabled) + return; + + exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, + exynos_drm_encoder_plane_disable); + + exynos_plane->enabled = false; + } +} + static int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, int crtc_x, int crtc_y, @@ -37,64 +142,37 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) { - struct exynos_plane *exynos_plane = - container_of(plane, struct exynos_plane, base); - struct exynos_drm_overlay *overlay = &exynos_plane->overlay; - struct exynos_drm_crtc_pos pos; int ret; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); - pos.crtc_x = crtc_x; - pos.crtc_y = crtc_y; - pos.crtc_w = crtc_w; - pos.crtc_h = crtc_h; - - /* considering 16.16 fixed point of source values */ - pos.fb_x = src_x >> 16; - pos.fb_y = src_y >> 16; - pos.src_w = src_w >> 16; - pos.src_h = src_h >> 16; - - ret = exynos_drm_overlay_update(overlay, fb, &crtc->mode, &pos); + ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, + crtc_w, crtc_h, src_x >> 16, src_y >> 16, + src_w >> 16, src_h >> 16); if (ret < 0) return ret; - exynos_drm_fn_encoder(crtc, overlay, - exynos_drm_encoder_crtc_mode_set); - exynos_drm_fn_encoder(crtc, &overlay->zpos, - exynos_drm_encoder_crtc_plane_commit); + plane->crtc = crtc; + plane->fb = crtc->fb; - exynos_plane->enabled = true; + exynos_plane_commit(plane); + exynos_plane_dpms(plane, DRM_MODE_DPMS_ON); return 0; } static int exynos_disable_plane(struct drm_plane *plane) { - struct exynos_plane *exynos_plane = - container_of(plane, struct exynos_plane, base); - struct exynos_drm_overlay *overlay = &exynos_plane->overlay; - DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - if (!exynos_plane->enabled) - return 0; - - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, - exynos_drm_encoder_crtc_disable); - - exynos_plane->enabled = false; - exynos_plane->overlay.zpos = DEFAULT_ZPOS; + exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF); return 0; } static void exynos_plane_destroy(struct drm_plane *plane) { - struct exynos_plane *exynos_plane = - container_of(plane, struct exynos_plane, base); + struct exynos_plane *exynos_plane = to_exynos_plane(plane); DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); @@ -103,69 +181,79 @@ static void exynos_plane_destroy(struct drm_plane *plane) kfree(exynos_plane); } +static int exynos_plane_set_property(struct drm_plane *plane, + struct drm_property *property, + uint64_t val) +{ + struct drm_device *dev = plane->dev; + struct exynos_plane *exynos_plane = to_exynos_plane(plane); + struct exynos_drm_private *dev_priv = dev->dev_private; + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + if (property == dev_priv->plane_zpos_property) { + exynos_plane->overlay.zpos = val; + return 0; + } + + return -EINVAL; +} + static struct drm_plane_funcs exynos_plane_funcs = { .update_plane = exynos_update_plane, .disable_plane = exynos_disable_plane, .destroy = exynos_plane_destroy, + .set_property = exynos_plane_set_property, }; -int exynos_plane_init(struct drm_device *dev, unsigned int nr) +static void exynos_plane_attach_zpos_property(struct drm_plane *plane) { - struct exynos_plane *exynos_plane; - uint32_t possible_crtcs; + struct drm_device *dev = plane->dev; + struct exynos_drm_private *dev_priv = dev->dev_private; + struct drm_property *prop; - exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); - if (!exynos_plane) - return -ENOMEM; + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - /* all CRTCs are available */ - possible_crtcs = (1 << MAX_CRTC) - 1; + prop = dev_priv->plane_zpos_property; + if (!prop) { + prop = drm_property_create_range(dev, 0, "zpos", 0, + MAX_PLANE - 1); + if (!prop) + return; - exynos_plane->overlay.zpos = DEFAULT_ZPOS; + dev_priv->plane_zpos_property = prop; + } - return drm_plane_init(dev, &exynos_plane->base, possible_crtcs, - &exynos_plane_funcs, formats, ARRAY_SIZE(formats), - false); + drm_object_attach_property(&plane->base, prop, 0); } -int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +struct drm_plane *exynos_plane_init(struct drm_device *dev, + unsigned int possible_crtcs, bool priv) { - struct drm_exynos_plane_set_zpos *zpos_req = data; - struct drm_mode_object *obj; - struct drm_plane *plane; struct exynos_plane *exynos_plane; - int ret = 0; + int err; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - - if (zpos_req->zpos < 0 || zpos_req->zpos >= MAX_PLANE) { - if (zpos_req->zpos != DEFAULT_ZPOS) { - DRM_ERROR("zpos not within limits\n"); - return -EINVAL; - } + exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL); + if (!exynos_plane) { + DRM_ERROR("failed to allocate plane\n"); + return NULL; } - mutex_lock(&dev->mode_config.mutex); - - obj = drm_mode_object_find(dev, zpos_req->plane_id, - DRM_MODE_OBJECT_PLANE); - if (!obj) { - DRM_DEBUG_KMS("Unknown plane ID %d\n", - zpos_req->plane_id); - ret = -EINVAL; - goto out; + err = drm_plane_init(dev, &exynos_plane->base, possible_crtcs, + &exynos_plane_funcs, formats, ARRAY_SIZE(formats), + priv); + if (err) { + DRM_ERROR("failed to initialize plane\n"); + kfree(exynos_plane); + return NULL; } - plane = obj_to_plane(obj); - exynos_plane = container_of(plane, struct exynos_plane, base); - - exynos_plane->overlay.zpos = zpos_req->zpos; + if (priv) + exynos_plane->overlay.zpos = DEFAULT_ZPOS; + else + exynos_plane_attach_zpos_property(&exynos_plane->base); -out: - mutex_unlock(&dev->mode_config.mutex); - return ret; + return &exynos_plane->base; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h index 16b71f8217e..88312458580 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.h +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h @@ -9,6 +9,12 @@ * */ -int exynos_plane_init(struct drm_device *dev, unsigned int nr); -int exynos_plane_set_zpos_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); +int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h); +void exynos_plane_commit(struct drm_plane *plane); +void exynos_plane_dpms(struct drm_plane *plane, int mode); +struct drm_plane *exynos_plane_init(struct drm_device *dev, + unsigned int possible_crtcs, bool priv); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 7b9c153dceb..bb1550c4dd5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -85,8 +85,6 @@ static const char fake_edid_info[] = { 0x00, 0x00, 0x00, 0x06 }; -static void vidi_fake_vblank_handler(struct work_struct *work); - static bool vidi_display_is_connected(struct device *dev) { struct vidi_context *ctx = get_vidi_context(dev); @@ -531,6 +529,16 @@ static int vidi_store_connection(struct device *dev, if (ctx->connected > 1) return -EINVAL; + /* use fake edid data for test. */ + if (!ctx->raw_edid) + ctx->raw_edid = (struct edid *)fake_edid_info; + + /* if raw_edid isn't same as fake data then it can't be tested. */ + if (ctx->raw_edid != (struct edid *)fake_edid_info) { + DRM_DEBUG_KMS("edid data is not fake data.\n"); + return -EINVAL; + } + DRM_DEBUG_KMS("requested connection.\n"); drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); @@ -549,6 +557,8 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, struct exynos_drm_manager *manager; struct exynos_drm_display_ops *display_ops; struct drm_exynos_vidi_connection *vidi = data; + struct edid *raw_edid; + int edid_len; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -557,11 +567,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, return -EINVAL; } - if (!vidi->edid) { - DRM_DEBUG_KMS("edid data is null.\n"); - return -EINVAL; - } - if (vidi->connection > 1) { DRM_DEBUG_KMS("connection should be 0 or 1.\n"); return -EINVAL; @@ -588,8 +593,30 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, return -EINVAL; } - if (vidi->connection) - ctx->raw_edid = (struct edid *)vidi->edid; + if (vidi->connection) { + if (!vidi->edid) { + DRM_DEBUG_KMS("edid data is null.\n"); + return -EINVAL; + } + raw_edid = (struct edid *)(uint32_t)vidi->edid; + edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; + ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); + if (!ctx->raw_edid) { + DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); + return -ENOMEM; + } + memcpy(ctx->raw_edid, raw_edid, edid_len); + } else { + /* + * with connection = 0, free raw_edid + * only if raw edid data isn't same as fake data. + */ + if (ctx->raw_edid && ctx->raw_edid != + (struct edid *)fake_edid_info) { + kfree(ctx->raw_edid); + ctx->raw_edid = NULL; + } + } ctx->connected = vidi->connection; drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); @@ -614,9 +641,6 @@ static int __devinit vidi_probe(struct platform_device *pdev) INIT_WORK(&ctx->work, vidi_fake_vblank_handler); - /* for test */ - ctx->raw_edid = (struct edid *)fake_edid_info; - subdrv = &ctx->subdrv; subdrv->dev = dev; subdrv->manager = &vidi_manager; @@ -644,6 +668,11 @@ static int __devexit vidi_remove(struct platform_device *pdev) exynos_drm_subdrv_unregister(&ctx->subdrv); + if (ctx->raw_edid != (struct edid *)fake_edid_info) { + kfree(ctx->raw_edid); + ctx->raw_edid = NULL; + } + kfree(ctx); return 0; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 066bde3f19c..409e2ec1207 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -63,7 +63,6 @@ struct hdmi_context { bool dvi_mode; struct mutex hdmi_mutex; - struct resource *regs_res; void __iomem *regs; unsigned int external_irq; unsigned int internal_irq; @@ -2280,16 +2279,17 @@ static int __devinit hdmi_probe(struct platform_device *pdev) return -EINVAL; } - drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); + drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx), + GFP_KERNEL); if (!drm_hdmi_ctx) { DRM_ERROR("failed to allocate common hdmi context.\n"); return -ENOMEM; } - hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL); + hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context), + GFP_KERNEL); if (!hdata) { DRM_ERROR("out of memory\n"); - kfree(drm_hdmi_ctx); return -ENOMEM; } @@ -2318,26 +2318,18 @@ static int __devinit hdmi_probe(struct platform_device *pdev) goto err_resource; } - hdata->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!hdata->regs_res) { - DRM_ERROR("failed to claim register region\n"); - ret = -ENOENT; - goto err_resource; - } - - hdata->regs = ioremap(res->start, resource_size(res)); + hdata->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hdata->regs) { DRM_ERROR("failed to map registers\n"); ret = -ENXIO; - goto err_req_region; + goto err_resource; } /* DDC i2c driver */ if (i2c_add_driver(&ddc_driver)) { DRM_ERROR("failed to register ddc i2c driver\n"); ret = -ENOENT; - goto err_iomap; + goto err_resource; } hdata->ddc_port = hdmi_ddc; @@ -2398,16 +2390,9 @@ err_hdmiphy: i2c_del_driver(&hdmiphy_driver); err_ddc: i2c_del_driver(&ddc_driver); -err_iomap: - iounmap(hdata->regs); -err_req_region: - release_mem_region(hdata->regs_res->start, - resource_size(hdata->regs_res)); err_resource: hdmi_resources_cleanup(hdata); err_data: - kfree(hdata); - kfree(drm_hdmi_ctx); return ret; } @@ -2425,18 +2410,11 @@ static int __devexit hdmi_remove(struct platform_device *pdev) hdmi_resources_cleanup(hdata); - iounmap(hdata->regs); - - release_mem_region(hdata->regs_res->start, - resource_size(hdata->regs_res)); - /* hdmiphy i2c driver */ i2c_del_driver(&hdmiphy_driver); /* DDC i2c driver */ i2c_del_driver(&ddc_driver); - kfree(hdata); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e2147a2ddce..30fcc12f81d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -956,7 +956,8 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); - mixer_res->mixer_regs = ioremap(res->start, resource_size(res)); + mixer_res->mixer_regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); if (mixer_res->mixer_regs == NULL) { dev_err(dev, "register mapping failed.\n"); ret = -ENXIO; @@ -967,38 +968,34 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, if (res == NULL) { dev_err(dev, "get memory resource failed.\n"); ret = -ENXIO; - goto fail_mixer_regs; + goto fail; } - mixer_res->vp_regs = ioremap(res->start, resource_size(res)); + mixer_res->vp_regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); if (mixer_res->vp_regs == NULL) { dev_err(dev, "register mapping failed.\n"); ret = -ENXIO; - goto fail_mixer_regs; + goto fail; } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); if (res == NULL) { dev_err(dev, "get interrupt resource failed.\n"); ret = -ENXIO; - goto fail_vp_regs; + goto fail; } - ret = request_irq(res->start, mixer_irq_handler, 0, "drm_mixer", ctx); + ret = devm_request_irq(&pdev->dev, res->start, mixer_irq_handler, + 0, "drm_mixer", ctx); if (ret) { dev_err(dev, "request interrupt failed.\n"); - goto fail_vp_regs; + goto fail; } mixer_res->irq = res->start; return 0; -fail_vp_regs: - iounmap(mixer_res->vp_regs); - -fail_mixer_regs: - iounmap(mixer_res->mixer_regs); - fail: if (!IS_ERR_OR_NULL(mixer_res->sclk_dac)) clk_put(mixer_res->sclk_dac); @@ -1013,16 +1010,6 @@ fail: return ret; } -static void mixer_resources_cleanup(struct mixer_context *ctx) -{ - struct mixer_resources *res = &ctx->mixer_res; - - free_irq(res->irq, ctx); - - iounmap(res->vp_regs); - iounmap(res->mixer_regs); -} - static int __devinit mixer_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1032,16 +1019,16 @@ static int __devinit mixer_probe(struct platform_device *pdev) dev_info(dev, "probe start\n"); - drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL); + drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx), + GFP_KERNEL); if (!drm_hdmi_ctx) { DRM_ERROR("failed to allocate common hdmi context.\n"); return -ENOMEM; } - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) { DRM_ERROR("failed to alloc mixer context.\n"); - kfree(drm_hdmi_ctx); return -ENOMEM; } @@ -1072,17 +1059,10 @@ fail: static int mixer_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct exynos_drm_hdmi_context *drm_hdmi_ctx = - platform_get_drvdata(pdev); - struct mixer_context *ctx = drm_hdmi_ctx->ctx; - - dev_info(dev, "remove successful\n"); + dev_info(&pdev->dev, "remove successful\n"); pm_runtime_disable(&pdev->dev); - mixer_resources_cleanup(ctx); - return 0; } diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 563c02904dd..23ab3c496b0 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -927,6 +927,8 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type) return 0; } +#ifdef CONFIG_PM_SLEEP + static int acpi_power_meter_resume(struct device *dev) { struct acpi_power_meter_resource *resource; @@ -944,6 +946,8 @@ static int acpi_power_meter_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ + static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume); static struct acpi_driver acpi_power_meter_driver = { diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 4d937a18fad..28270886051 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -55,9 +55,9 @@ /* wait up to 32 ms for a status change. */ #define APPLESMC_MIN_WAIT 0x0010 +#define APPLESMC_RETRY_WAIT 0x0100 #define APPLESMC_MAX_WAIT 0x8000 -#define APPLESMC_STATUS_MASK 0x0f #define APPLESMC_READ_CMD 0x10 #define APPLESMC_WRITE_CMD 0x11 #define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 @@ -162,51 +162,68 @@ static unsigned int key_at_index; static struct workqueue_struct *applesmc_led_wq; /* - * __wait_status - Wait up to 32ms for the status port to get a certain value - * (masked with 0x0f), returning zero if the value is obtained. Callers must + * wait_read - Wait for a byte to appear on SMC port. Callers must * hold applesmc_lock. */ -static int __wait_status(u8 val) +static int wait_read(void) { + u8 status; int us; - - val = val & APPLESMC_STATUS_MASK; - for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { udelay(us); - if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) + status = inb(APPLESMC_CMD_PORT); + /* read: wait for smc to settle */ + if (status & 0x01) return 0; } + pr_warn("wait_read() fail: 0x%02x\n", status); return -EIO; } /* - * special treatment of command port - on newer macbooks, it seems necessary - * to resend the command byte before polling the status again. Callers must - * hold applesmc_lock. + * send_byte - Write to SMC port, retrying when necessary. Callers + * must hold applesmc_lock. */ -static int send_command(u8 cmd) +static int send_byte(u8 cmd, u16 port) { + u8 status; int us; + + outb(cmd, port); for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { - outb(cmd, APPLESMC_CMD_PORT); udelay(us); - if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) + status = inb(APPLESMC_CMD_PORT); + /* write: wait for smc to settle */ + if (status & 0x02) + continue; + /* ready: cmd accepted, return */ + if (status & 0x04) return 0; + /* timeout: give up */ + if (us << 1 == APPLESMC_MAX_WAIT) + break; + /* busy: long wait and resend */ + udelay(APPLESMC_RETRY_WAIT); + outb(cmd, port); } + + pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status); return -EIO; } +static int send_command(u8 cmd) +{ + return send_byte(cmd, APPLESMC_CMD_PORT); +} + static int send_argument(const char *key) { int i; - for (i = 0; i < 4; i++) { - outb(key[i], APPLESMC_DATA_PORT); - if (__wait_status(0x04)) + for (i = 0; i < 4; i++) + if (send_byte(key[i], APPLESMC_DATA_PORT)) return -EIO; - } return 0; } @@ -219,11 +236,14 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) return -EIO; } - outb(len, APPLESMC_DATA_PORT); + if (send_byte(len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: read len fail\n", key); + return -EIO; + } for (i = 0; i < len; i++) { - if (__wait_status(0x05)) { - pr_warn("%.4s: read data fail\n", key); + if (wait_read()) { + pr_warn("%.4s: read data[%d] fail\n", key, i); return -EIO; } buffer[i] = inb(APPLESMC_DATA_PORT); @@ -241,14 +261,16 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) return -EIO; } - outb(len, APPLESMC_DATA_PORT); + if (send_byte(len, APPLESMC_DATA_PORT)) { + pr_warn("%.4s: write len fail\n", key); + return -EIO; + } for (i = 0; i < len; i++) { - if (__wait_status(0x04)) { + if (send_byte(buffer[i], APPLESMC_DATA_PORT)) { pr_warn("%s: write data fail\n", key); return -EIO; } - outb(buffer[i], APPLESMC_DATA_PORT); } return 0; diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 637c51c11b4..faa16f80db9 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -793,7 +793,7 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { .notifier_call = coretemp_cpu_callback, }; -static const struct x86_cpu_id coretemp_ids[] = { +static const struct x86_cpu_id __initconst coretemp_ids[] = { { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, {} }; diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index e72ba5d2a82..e21e43c1315 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = { #define JC42_CFG_EVENT_LOCK (1 << 7) #define JC42_CFG_SHUTDOWN (1 << 8) #define JC42_CFG_HYST_SHIFT 9 -#define JC42_CFG_HYST_MASK 0x03 +#define JC42_CFG_HYST_MASK (0x03 << 9) /* Capabilities */ #define JC42_CAP_RANGE (1 << 2) @@ -287,8 +287,8 @@ static ssize_t show_temp_crit_hyst(struct device *dev, return PTR_ERR(data); temp = jc42_temp_from_reg(data->temp_crit); - hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) - & JC42_CFG_HYST_MASK]; + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; return sprintf(buf, "%d\n", temp - hyst); } @@ -302,8 +302,8 @@ static ssize_t show_temp_max_hyst(struct device *dev, return PTR_ERR(data); temp = jc42_temp_from_reg(data->temp_max); - hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) - & JC42_CFG_HYST_MASK]; + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; return sprintf(buf, "%d\n", temp - hyst); } @@ -362,8 +362,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev, } mutex_lock(&data->update_lock); - data->config = (data->config - & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT)) + data->config = (data->config & ~JC42_CFG_HYST_MASK) | (hyst << JC42_CFG_HYST_SHIFT); err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config); @@ -535,9 +534,16 @@ static int jc42_remove(struct i2c_client *client) struct jc42_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &jc42_group); - if (data->config != data->orig_config) - i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, - data->orig_config); + + /* Restore original configuration except hysteresis */ + if ((data->config & ~JC42_CFG_HYST_MASK) != + (data->orig_config & ~JC42_CFG_HYST_MASK)) { + int config; + + config = (data->orig_config & ~JC42_CFG_HYST_MASK) + | (data->config & JC42_CFG_HYST_MASK); + i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); + } return 0; } diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 8689664ef03..ee4ebc198a9 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -309,7 +309,7 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { .notifier_call = via_cputemp_cpu_callback, }; -static const struct x86_cpu_id cputemp_ids[] = { +static const struct x86_cpu_id __initconst cputemp_ids[] = { { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index ee139a59881..f44c83549fe 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -2,7 +2,7 @@ * (C) Copyright 2009-2010 * Nokia Siemens Networks, michael.lawnick.ext@nsn.com * - * Portions Copyright (C) 2010 Cavium Networks, Inc. + * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc. * * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors. * @@ -11,17 +11,18 @@ * warranty of any kind, whether express or implied. */ +#include <linux/platform_device.h> +#include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_i2c.h> +#include <linux/delay.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/init.h> - -#include <linux/io.h> #include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/of.h> #include <asm/octeon/octeon.h> @@ -65,7 +66,7 @@ struct octeon_i2c { wait_queue_head_t queue; struct i2c_adapter adap; int irq; - int twsi_freq; + u32 twsi_freq; int sys_freq; resource_size_t twsi_phys; void __iomem *twsi_base; @@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg) */ static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) { - u64 tmp; - __raw_writeq(data, i2c->twsi_base + TWSI_INT); - tmp = __raw_readq(i2c->twsi_base + TWSI_INT); + __raw_readq(i2c->twsi_base + TWSI_INT); } /** @@ -515,7 +514,6 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev) { int irq, result = 0; struct octeon_i2c *i2c; - struct octeon_i2c_data *i2c_data; struct resource *res_mem; /* All adaptors have an irq. */ @@ -523,86 +521,90 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev) if (irq < 0) return irq; - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) { dev_err(&pdev->dev, "kzalloc failed\n"); result = -ENOMEM; goto out; } i2c->dev = &pdev->dev; - i2c_data = pdev->dev.platform_data; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res_mem == NULL) { dev_err(i2c->dev, "found no memory resource\n"); result = -ENXIO; - goto fail_region; + goto out; } + i2c->twsi_phys = res_mem->start; + i2c->regsize = resource_size(res_mem); - if (i2c_data == NULL) { - dev_err(i2c->dev, "no I2C frequency data\n"); + /* + * "clock-rate" is a legacy binding, the official binding is + * "clock-frequency". Try the official one first and then + * fall back if it doesn't exist. + */ + if (of_property_read_u32(pdev->dev.of_node, + "clock-frequency", &i2c->twsi_freq) && + of_property_read_u32(pdev->dev.of_node, + "clock-rate", &i2c->twsi_freq)) { + dev_err(i2c->dev, + "no I2C 'clock-rate' or 'clock-frequency' property\n"); result = -ENXIO; - goto fail_region; + goto out; } - i2c->twsi_phys = res_mem->start; - i2c->regsize = resource_size(res_mem); - i2c->twsi_freq = i2c_data->i2c_freq; - i2c->sys_freq = i2c_data->sys_freq; + i2c->sys_freq = octeon_get_io_clock_rate(); - if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) { + if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize, + res_mem->name)) { dev_err(i2c->dev, "request_mem_region failed\n"); - goto fail_region; + goto out; } - i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize); + i2c->twsi_base = devm_ioremap(&pdev->dev, i2c->twsi_phys, i2c->regsize); init_waitqueue_head(&i2c->queue); i2c->irq = irq; - result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); + result = devm_request_irq(&pdev->dev, i2c->irq, + octeon_i2c_isr, 0, DRV_NAME, i2c); if (result < 0) { dev_err(i2c->dev, "failed to attach interrupt\n"); - goto fail_irq; + goto out; } result = octeon_i2c_initlowlevel(i2c); if (result) { dev_err(i2c->dev, "init low level failed\n"); - goto fail_add; + goto out; } result = octeon_i2c_setclock(i2c); if (result) { dev_err(i2c->dev, "clock init failed\n"); - goto fail_add; + goto out; } i2c->adap = octeon_i2c_ops; i2c->adap.dev.parent = &pdev->dev; - i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; + i2c->adap.dev.of_node = pdev->dev.of_node; i2c_set_adapdata(&i2c->adap, i2c); platform_set_drvdata(pdev, i2c); - result = i2c_add_numbered_adapter(&i2c->adap); + result = i2c_add_adapter(&i2c->adap); if (result < 0) { dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } - dev_info(i2c->dev, "version %s\n", DRV_VERSION); - return result; + of_i2c_register_devices(&i2c->adap); + + return 0; fail_add: platform_set_drvdata(pdev, NULL); - free_irq(i2c->irq, i2c); -fail_irq: - iounmap(i2c->twsi_base); - release_mem_region(i2c->twsi_phys, i2c->regsize); -fail_region: - kfree(i2c); out: return result; }; @@ -613,19 +615,24 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); platform_set_drvdata(pdev, NULL); - free_irq(i2c->irq, i2c); - iounmap(i2c->twsi_base); - release_mem_region(i2c->twsi_phys, i2c->regsize); - kfree(i2c); return 0; }; +static struct of_device_id octeon_i2c_match[] = { + { + .compatible = "cavium,octeon-3860-twsi", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, octeon_i2c_match); + static struct platform_driver octeon_i2c_driver = { .probe = octeon_i2c_probe, .remove = __devexit_p(octeon_i2c_remove), .driver = { .owner = THIS_MODULE, .name = DRV_NAME, + .of_match_table = octeon_i2c_match, }, }; @@ -635,4 +642,3 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>"); MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c new file mode 100644 index 00000000000..7f26e7b6c22 --- /dev/null +++ b/drivers/input/misc/88pm80x_onkey.c @@ -0,0 +1,168 @@ +/* + * Marvell 88PM80x ONKEY driver + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * Qiao Zhou <zhouqiao@marvell.com> + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/input.h> +#include <linux/mfd/88pm80x.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#define PM800_LONG_ONKEY_EN (1 << 0) +#define PM800_LONG_KEY_DELAY (8) /* 1 .. 16 seconds */ +#define PM800_LONKEY_PRESS_TIME ((PM800_LONG_KEY_DELAY-1) << 4) +#define PM800_LONKEY_PRESS_TIME_MASK (0xF0) +#define PM800_SW_PDOWN (1 << 5) + +struct pm80x_onkey_info { + struct input_dev *idev; + struct pm80x_chip *pm80x; + struct regmap *map; + int irq; +}; + +/* 88PM80x gives us an interrupt when ONKEY is held */ +static irqreturn_t pm80x_onkey_handler(int irq, void *data) +{ + struct pm80x_onkey_info *info = data; + int ret = 0; + unsigned int val; + + ret = regmap_read(info->map, PM800_STATUS_1, &val); + if (ret < 0) { + dev_err(info->idev->dev.parent, "failed to read status: %d\n", ret); + return IRQ_NONE; + } + val &= PM800_ONKEY_STS1; + + input_report_key(info->idev, KEY_POWER, val); + input_sync(info->idev); + + return IRQ_HANDLED; +} + +static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend, + pm80x_dev_resume); + +static int __devinit pm80x_onkey_probe(struct platform_device *pdev) +{ + + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm80x_onkey_info *info; + int err; + + info = kzalloc(sizeof(struct pm80x_onkey_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->pm80x = chip; + + info->irq = platform_get_irq(pdev, 0); + if (info->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource!\n"); + err = -EINVAL; + goto out; + } + + info->map = info->pm80x->regmap; + if (!info->map) { + dev_err(&pdev->dev, "no regmap!\n"); + err = -EINVAL; + goto out; + } + + info->idev = input_allocate_device(); + if (!info->idev) { + dev_err(&pdev->dev, "Failed to allocate input dev\n"); + err = -ENOMEM; + goto out; + } + + info->idev->name = "88pm80x_on"; + info->idev->phys = "88pm80x_on/input0"; + info->idev->id.bustype = BUS_I2C; + info->idev->dev.parent = &pdev->dev; + info->idev->evbit[0] = BIT_MASK(EV_KEY); + __set_bit(KEY_POWER, info->idev->keybit); + + err = pm80x_request_irq(info->pm80x, info->irq, pm80x_onkey_handler, + IRQF_ONESHOT, "onkey", info); + if (err < 0) { + dev_err(&pdev->dev, "Failed to request IRQ: #%d: %d\n", + info->irq, err); + goto out_reg; + } + + err = input_register_device(info->idev); + if (err) { + dev_err(&pdev->dev, "Can't register input device: %d\n", err); + goto out_irq; + } + + platform_set_drvdata(pdev, info); + + /* Enable long onkey detection */ + regmap_update_bits(info->map, PM800_RTC_MISC4, PM800_LONG_ONKEY_EN, + PM800_LONG_ONKEY_EN); + /* Set 8-second interval */ + regmap_update_bits(info->map, PM800_RTC_MISC3, + PM800_LONKEY_PRESS_TIME_MASK, + PM800_LONKEY_PRESS_TIME); + + device_init_wakeup(&pdev->dev, 1); + return 0; + +out_irq: + pm80x_free_irq(info->pm80x, info->irq, info); +out_reg: + input_free_device(info->idev); +out: + kfree(info); + return err; +} + +static int __devexit pm80x_onkey_remove(struct platform_device *pdev) +{ + struct pm80x_onkey_info *info = platform_get_drvdata(pdev); + + device_init_wakeup(&pdev->dev, 0); + pm80x_free_irq(info->pm80x, info->irq, info); + input_unregister_device(info->idev); + kfree(info); + return 0; +} + +static struct platform_driver pm80x_onkey_driver = { + .driver = { + .name = "88pm80x-onkey", + .owner = THIS_MODULE, + .pm = &pm80x_onkey_pm_ops, + }, + .probe = pm80x_onkey_probe, + .remove = __devexit_p(pm80x_onkey_remove), +}; + +module_platform_driver(pm80x_onkey_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Marvell 88PM80x ONKEY driver"); +MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); +MODULE_ALIAS("platform:88pm80x-onkey"); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7faf4a7fcaa..7c0f1ecfdd7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY To compile this driver as a module, choose M here: the module will be called 88pm860x_onkey. +config INPUT_88PM80X_ONKEY + tristate "88PM80x ONKEY support" + depends on MFD_88PM800 + help + Support the ONKEY of Marvell 88PM80x PMICs as an input device + reporting power button status. + + To compile this driver as a module, choose M here: the module + will be called 88pm80x_onkey. + config INPUT_AB8500_PONKEY tristate "AB8500 Pon (PowerOn) Key" depends on AB8500_CORE diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f55cdf4916f..83fe6f5b77d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -5,6 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o +obj-$(CONFIG_INPUT_88PM80X_ONKEY) += 88pm80x_onkey.o obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o obj-$(CONFIG_INPUT_AD714X) += ad714x.o obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 84ec691c05a..f06231b7cab 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev) ponkey->idev = input; ponkey->ab8500 = ab8500; - ponkey->irq_dbf = irq_dbf; - ponkey->irq_dbr = irq_dbr; + ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf); + ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr); input->name = "AB8500 POn(PowerOn) Key"; input->dev.parent = &pdev->dev; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d5b390f75c9..14eaecea2b7 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -40,11 +40,27 @@ * Note that newer firmware allows querying device for maximum useable * coordinates. */ +#define XMIN 0 +#define XMAX 6143 +#define YMIN 0 +#define YMAX 6143 #define XMIN_NOMINAL 1472 #define XMAX_NOMINAL 5472 #define YMIN_NOMINAL 1408 #define YMAX_NOMINAL 4448 +/* Size in bits of absolute position values reported by the hardware */ +#define ABS_POS_BITS 13 + +/* + * Any position values from the hardware above the following limits are + * treated as "wrapped around negative" values that have been truncated to + * the 13-bit reporting range of the hardware. These are just reasonable + * guesses and can be adjusted if hardware is found that operates outside + * of these parameters. + */ +#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2) +#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2) /***************************************************************************** * Stuff we need even when we do not want native Synaptics support @@ -588,6 +604,12 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->right = (buf[0] & 0x02) ? 1 : 0; } + /* Convert wrap-around values to negative */ + if (hw->x > X_MAX_POSITIVE) + hw->x -= 1 << ABS_POS_BITS; + if (hw->y > Y_MAX_POSITIVE) + hw->y -= 1 << ABS_POS_BITS; + return 0; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 6533f44be5b..002041975de 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -464,7 +464,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) t = (data[6] << 2) | ((data[7] >> 6) & 3); if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || (features->type >= INTUOS5S && features->type <= INTUOS5L) || - features->type == WACOM_21UX2 || features->type == WACOM_24HD) { + (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) { t = (t << 1) | (data[1] & 1); } input_report_abs(input, ABS_PRESSURE, t); @@ -614,7 +614,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_MISC, 0); } } else { - if (features->type == WACOM_21UX2) { + if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) { input_report_key(input, BTN_0, (data[5] & 0x01)); input_report_key(input, BTN_1, (data[6] & 0x01)); input_report_key(input, BTN_2, (data[6] & 0x02)); @@ -633,6 +633,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_key(input, BTN_Z, (data[8] & 0x20)); input_report_key(input, BTN_BASE, (data[8] & 0x40)); input_report_key(input, BTN_BASE2, (data[8] & 0x80)); + + if (features->type == WACOM_22HD) { + input_report_key(input, KEY_PROG1, data[9] & 0x01); + input_report_key(input, KEY_PROG2, data[9] & 0x02); + input_report_key(input, KEY_PROG3, data[9] & 0x04); + } } else { input_report_key(input, BTN_0, (data[5] & 0x01)); input_report_key(input, BTN_1, (data[5] & 0x02)); @@ -1231,6 +1237,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case CINTIQ: case WACOM_BEE: case WACOM_21UX2: + case WACOM_22HD: case WACOM_24HD: sync = wacom_intuos_irq(wacom_wac); break; @@ -1432,6 +1439,12 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, wacom_setup_cintiq(wacom_wac); break; + case WACOM_22HD: + __set_bit(KEY_PROG1, input_dev->keybit); + __set_bit(KEY_PROG2, input_dev->keybit); + __set_bit(KEY_PROG3, input_dev->keybit); + /* fall through */ + case WACOM_21UX2: __set_bit(BTN_A, input_dev->keybit); __set_bit(BTN_B, input_dev->keybit); @@ -1858,6 +1871,9 @@ static const struct wacom_features wacom_features_0xF0 = static const struct wacom_features wacom_features_0xCC = { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; +static const struct wacom_features wacom_features_0xFA = + { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, + 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x90 = { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2075,6 +2091,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEF) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, + { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } }; diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index bd5d37b2871..96c185cc301 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -73,8 +73,9 @@ enum { INTUOS5S, INTUOS5, INTUOS5L, - WACOM_24HD, WACOM_21UX2, + WACOM_22HD, + WACOM_24HD, CINTIQ, WACOM_BEE, WACOM_MO, diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 73bd2f6b82e..1ba232cbc09 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -472,6 +472,19 @@ config TOUCHSCREEN_PENMOUNT To compile this driver as a module, choose M here: the module will be called penmount. +config TOUCHSCREEN_EDT_FT5X06 + tristate "EDT FocalTech FT5x06 I2C Touchscreen support" + depends on I2C + help + Say Y here if you have an EDT "Polytouch" touchscreen based + on the FocalTech FT5x06 family of controllers connected to + your system. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called edt-ft5x06. + config TOUCHSCREEN_MIGOR tristate "Renesas MIGO-R touchscreen" depends on SH_MIGOR && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 5920c60f999..178eb128d90 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o +obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c new file mode 100644 index 00000000000..9afc777a40a --- /dev/null +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -0,0 +1,898 @@ +/* + * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This is a driver for the EDT "Polytouch" family of touch controllers + * based on the FocalTech FT5x06 line of chips. + * + * Development of this driver has been sponsored by Glyn: + * http://www.glyn.com/Products/Displays + */ + +#include <linux/module.h> +#include <linux/ratelimit.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/uaccess.h> +#include <linux/delay.h> +#include <linux/debugfs.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/input/mt.h> +#include <linux/input/edt-ft5x06.h> + +#define MAX_SUPPORT_POINTS 5 + +#define WORK_REGISTER_THRESHOLD 0x00 +#define WORK_REGISTER_REPORT_RATE 0x08 +#define WORK_REGISTER_GAIN 0x30 +#define WORK_REGISTER_OFFSET 0x31 +#define WORK_REGISTER_NUM_X 0x33 +#define WORK_REGISTER_NUM_Y 0x34 + +#define WORK_REGISTER_OPMODE 0x3c +#define FACTORY_REGISTER_OPMODE 0x01 + +#define TOUCH_EVENT_DOWN 0x00 +#define TOUCH_EVENT_UP 0x01 +#define TOUCH_EVENT_ON 0x02 +#define TOUCH_EVENT_RESERVED 0x03 + +#define EDT_NAME_LEN 23 +#define EDT_SWITCH_MODE_RETRIES 10 +#define EDT_SWITCH_MODE_DELAY 5 /* msec */ +#define EDT_RAW_DATA_RETRIES 100 +#define EDT_RAW_DATA_DELAY 1 /* msec */ + +struct edt_ft5x06_ts_data { + struct i2c_client *client; + struct input_dev *input; + u16 num_x; + u16 num_y; + +#if defined(CONFIG_DEBUG_FS) + struct dentry *debug_dir; + u8 *raw_buffer; + size_t raw_bufsize; +#endif + + struct mutex mutex; + bool factory_mode; + int threshold; + int gain; + int offset; + int report_rate; + + char name[EDT_NAME_LEN]; +}; + +static int edt_ft5x06_ts_readwrite(struct i2c_client *client, + u16 wr_len, u8 *wr_buf, + u16 rd_len, u8 *rd_buf) +{ + struct i2c_msg wrmsg[2]; + int i = 0; + int ret; + + if (wr_len) { + wrmsg[i].addr = client->addr; + wrmsg[i].flags = 0; + wrmsg[i].len = wr_len; + wrmsg[i].buf = wr_buf; + i++; + } + if (rd_len) { + wrmsg[i].addr = client->addr; + wrmsg[i].flags = I2C_M_RD; + wrmsg[i].len = rd_len; + wrmsg[i].buf = rd_buf; + i++; + } + + ret = i2c_transfer(client->adapter, wrmsg, i); + if (ret < 0) + return ret; + if (ret != i) + return -EIO; + + return 0; +} + +static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata, + u8 *buf, int buflen) +{ + int i; + u8 crc = 0; + + for (i = 0; i < buflen - 1; i++) + crc ^= buf[i]; + + if (crc != buf[buflen-1]) { + dev_err_ratelimited(&tsdata->client->dev, + "crc error: 0x%02x expected, got 0x%02x\n", + crc, buf[buflen-1]); + return false; + } + + return true; +} + +static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) +{ + struct edt_ft5x06_ts_data *tsdata = dev_id; + struct device *dev = &tsdata->client->dev; + u8 cmd = 0xf9; + u8 rdbuf[26]; + int i, type, x, y, id; + int error; + + memset(rdbuf, 0, sizeof(rdbuf)); + + error = edt_ft5x06_ts_readwrite(tsdata->client, + sizeof(cmd), &cmd, + sizeof(rdbuf), rdbuf); + if (error) { + dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", + error); + goto out; + } + + if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { + dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", + rdbuf[0], rdbuf[1], rdbuf[2]); + goto out; + } + + if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) + goto out; + + for (i = 0; i < MAX_SUPPORT_POINTS; i++) { + u8 *buf = &rdbuf[i * 4 + 5]; + bool down; + + type = buf[0] >> 6; + /* ignore Reserved events */ + if (type == TOUCH_EVENT_RESERVED) + continue; + + x = ((buf[0] << 8) | buf[1]) & 0x0fff; + y = ((buf[2] << 8) | buf[3]) & 0x0fff; + id = (buf[2] >> 4) & 0x0f; + down = (type != TOUCH_EVENT_UP); + + input_mt_slot(tsdata->input, id); + input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down); + + if (!down) + continue; + + input_report_abs(tsdata->input, ABS_MT_POSITION_X, x); + input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y); + } + + input_mt_report_pointer_emulation(tsdata->input, true); + input_sync(tsdata->input); + +out: + return IRQ_HANDLED; +} + +static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, + u8 addr, u8 value) +{ + u8 wrbuf[4]; + + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; + wrbuf[2] = value; + wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; + + return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); +} + +static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, + u8 addr) +{ + u8 wrbuf[2], rdbuf[2]; + int error; + + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; + wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; + + error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf); + if (error) + return error; + + if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { + dev_err(&tsdata->client->dev, + "crc error: 0x%02x expected, got 0x%02x\n", + wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); + return -EIO; + } + + return rdbuf[0]; +} + +struct edt_ft5x06_attribute { + struct device_attribute dattr; + size_t field_offset; + u8 limit_low; + u8 limit_high; + u8 addr; +}; + +#define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \ + struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ + .dattr = __ATTR(_field, _mode, \ + edt_ft5x06_setting_show, \ + edt_ft5x06_setting_store), \ + .field_offset = \ + offsetof(struct edt_ft5x06_ts_data, _field), \ + .limit_low = _limit_low, \ + .limit_high = _limit_high, \ + .addr = _addr, \ + } + +static ssize_t edt_ft5x06_setting_show(struct device *dev, + struct device_attribute *dattr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + struct edt_ft5x06_attribute *attr = + container_of(dattr, struct edt_ft5x06_attribute, dattr); + u8 *field = (u8 *)((char *)tsdata + attr->field_offset); + int val; + size_t count = 0; + int error = 0; + + mutex_lock(&tsdata->mutex); + + if (tsdata->factory_mode) { + error = -EIO; + goto out; + } + + val = edt_ft5x06_register_read(tsdata, attr->addr); + if (val < 0) { + error = val; + dev_err(&tsdata->client->dev, + "Failed to fetch attribute %s, error %d\n", + dattr->attr.name, error); + goto out; + } + + if (val != *field) { + dev_warn(&tsdata->client->dev, + "%s: read (%d) and stored value (%d) differ\n", + dattr->attr.name, val, *field); + *field = val; + } + + count = scnprintf(buf, PAGE_SIZE, "%d\n", val); +out: + mutex_unlock(&tsdata->mutex); + return error ?: count; +} + +static ssize_t edt_ft5x06_setting_store(struct device *dev, + struct device_attribute *dattr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + struct edt_ft5x06_attribute *attr = + container_of(dattr, struct edt_ft5x06_attribute, dattr); + u8 *field = (u8 *)((char *)tsdata + attr->field_offset); + unsigned int val; + int error; + + mutex_lock(&tsdata->mutex); + + if (tsdata->factory_mode) { + error = -EIO; + goto out; + } + + error = kstrtouint(buf, 0, &val); + if (error) + goto out; + + if (val < attr->limit_low || val > attr->limit_high) { + error = -ERANGE; + goto out; + } + + error = edt_ft5x06_register_write(tsdata, attr->addr, val); + if (error) { + dev_err(&tsdata->client->dev, + "Failed to update attribute %s, error: %d\n", + dattr->attr.name, error); + goto out; + } + + *field = val; + +out: + mutex_unlock(&tsdata->mutex); + return error ?: count; +} + +static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); +static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); +static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, + WORK_REGISTER_THRESHOLD, 20, 80); +static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, + WORK_REGISTER_REPORT_RATE, 3, 14); + +static struct attribute *edt_ft5x06_attrs[] = { + &edt_ft5x06_attr_gain.dattr.attr, + &edt_ft5x06_attr_offset.dattr.attr, + &edt_ft5x06_attr_threshold.dattr.attr, + &edt_ft5x06_attr_report_rate.dattr.attr, + NULL +}; + +static const struct attribute_group edt_ft5x06_attr_group = { + .attrs = edt_ft5x06_attrs, +}; + +#ifdef CONFIG_DEBUG_FS +static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) +{ + struct i2c_client *client = tsdata->client; + int retries = EDT_SWITCH_MODE_RETRIES; + int ret; + int error; + + disable_irq(client->irq); + + if (!tsdata->raw_buffer) { + tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y * + sizeof(u16); + tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL); + if (!tsdata->raw_buffer) { + error = -ENOMEM; + goto err_out; + } + } + + /* mode register is 0x3c when in the work mode */ + error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); + if (error) { + dev_err(&client->dev, + "failed to switch to factory mode, error %d\n", error); + goto err_out; + } + + tsdata->factory_mode = true; + do { + mdelay(EDT_SWITCH_MODE_DELAY); + /* mode register is 0x01 when in factory mode */ + ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE); + if (ret == 0x03) + break; + } while (--retries > 0); + + if (retries == 0) { + dev_err(&client->dev, "not in factory mode after %dms.\n", + EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); + error = -EIO; + goto err_out; + } + + return 0; + +err_out: + kfree(tsdata->raw_buffer); + tsdata->raw_buffer = NULL; + tsdata->factory_mode = false; + enable_irq(client->irq); + + return error; +} + +static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) +{ + struct i2c_client *client = tsdata->client; + int retries = EDT_SWITCH_MODE_RETRIES; + int ret; + int error; + + /* mode register is 0x01 when in the factory mode */ + error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1); + if (error) { + dev_err(&client->dev, + "failed to switch to work mode, error: %d\n", error); + return error; + } + + tsdata->factory_mode = false; + + do { + mdelay(EDT_SWITCH_MODE_DELAY); + /* mode register is 0x01 when in factory mode */ + ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE); + if (ret == 0x01) + break; + } while (--retries > 0); + + if (retries == 0) { + dev_err(&client->dev, "not in work mode after %dms.\n", + EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY); + tsdata->factory_mode = true; + return -EIO; + } + + if (tsdata->raw_buffer) + kfree(tsdata->raw_buffer); + tsdata->raw_buffer = NULL; + + /* restore parameters */ + edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, + tsdata->threshold); + edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, + tsdata->gain); + edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, + tsdata->offset); + edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE, + tsdata->report_rate); + + enable_irq(client->irq); + + return 0; +} + +static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode) +{ + struct edt_ft5x06_ts_data *tsdata = data; + + *mode = tsdata->factory_mode; + + return 0; +}; + +static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode) +{ + struct edt_ft5x06_ts_data *tsdata = data; + int retval = 0; + + if (mode > 1) + return -ERANGE; + + mutex_lock(&tsdata->mutex); + + if (mode != tsdata->factory_mode) { + retval = mode ? edt_ft5x06_factory_mode(tsdata) : + edt_ft5x06_work_mode(tsdata); + } + + mutex_unlock(&tsdata->mutex); + + return retval; +}; + +DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get, + edt_ft5x06_debugfs_mode_set, "%llu\n"); + +static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode, + struct file *file) +{ + file->private_data = inode->i_private; + + return 0; +} + +static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, + char __user *buf, size_t count, loff_t *off) +{ + struct edt_ft5x06_ts_data *tsdata = file->private_data; + struct i2c_client *client = tsdata->client; + int retries = EDT_RAW_DATA_RETRIES; + int val, i, error; + size_t read = 0; + int colbytes; + char wrbuf[3]; + u8 *rdbuf; + + if (*off < 0 || *off >= tsdata->raw_bufsize) + return 0; + + mutex_lock(&tsdata->mutex); + + if (!tsdata->factory_mode || !tsdata->raw_buffer) { + error = -EIO; + goto out; + } + + error = edt_ft5x06_register_write(tsdata, 0x08, 0x01); + if (error) { + dev_dbg(&client->dev, + "failed to write 0x08 register, error %d\n", error); + goto out; + } + + do { + msleep(EDT_RAW_DATA_DELAY); + val = edt_ft5x06_register_read(tsdata, 0x08); + if (val < 1) + break; + } while (--retries > 0); + + if (val < 0) { + error = val; + dev_dbg(&client->dev, + "failed to read 0x08 register, error %d\n", error); + goto out; + } + + if (retries == 0) { + dev_dbg(&client->dev, + "timed out waiting for register to settle\n"); + error = -ETIMEDOUT; + goto out; + } + + rdbuf = tsdata->raw_buffer; + colbytes = tsdata->num_y * sizeof(u16); + + wrbuf[0] = 0xf5; + wrbuf[1] = 0x0e; + for (i = 0; i < tsdata->num_x; i++) { + wrbuf[2] = i; /* column index */ + error = edt_ft5x06_ts_readwrite(tsdata->client, + sizeof(wrbuf), wrbuf, + colbytes, rdbuf); + if (error) + goto out; + + rdbuf += colbytes; + } + + read = min_t(size_t, count, tsdata->raw_bufsize - *off); + error = copy_to_user(buf, tsdata->raw_buffer + *off, read); + if (!error) + *off += read; +out: + mutex_unlock(&tsdata->mutex); + return error ?: read; +}; + + +static const struct file_operations debugfs_raw_data_fops = { + .open = edt_ft5x06_debugfs_raw_data_open, + .read = edt_ft5x06_debugfs_raw_data_read, +}; + +static void __devinit +edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, + const char *debugfs_name) +{ + tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL); + if (!tsdata->debug_dir) + return; + + debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x); + debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y); + + debugfs_create_file("mode", S_IRUSR | S_IWUSR, + tsdata->debug_dir, tsdata, &debugfs_mode_fops); + debugfs_create_file("raw_data", S_IRUSR, + tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); +} + +static void __devexit +edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) +{ + if (tsdata->debug_dir) + debugfs_remove_recursive(tsdata->debug_dir); +} + +#else + +static inline void +edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, + const char *debugfs_name) +{ +} + +static inline void +edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) +{ +} + +#endif /* CONFIG_DEBUGFS */ + + + +static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client, + int reset_pin) +{ + int error; + + if (gpio_is_valid(reset_pin)) { + /* this pulls reset down, enabling the low active reset */ + error = gpio_request_one(reset_pin, GPIOF_OUT_INIT_LOW, + "edt-ft5x06 reset"); + if (error) { + dev_err(&client->dev, + "Failed to request GPIO %d as reset pin, error %d\n", + reset_pin, error); + return error; + } + + mdelay(50); + gpio_set_value(reset_pin, 1); + mdelay(100); + } + + return 0; +} + +static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client, + char *model_name, + char *fw_version) +{ + u8 rdbuf[EDT_NAME_LEN]; + char *p; + int error; + + error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", + EDT_NAME_LEN - 1, rdbuf); + if (error) + return error; + + /* remove last '$' end marker */ + rdbuf[EDT_NAME_LEN - 1] = '\0'; + if (rdbuf[EDT_NAME_LEN - 2] == '$') + rdbuf[EDT_NAME_LEN - 2] = '\0'; + + /* look for Model/Version separator */ + p = strchr(rdbuf, '*'); + if (p) + *p++ = '\0'; + + strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); + + return 0; +} + +#define EDT_ATTR_CHECKSET(name, reg) \ + if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \ + pdata->name <= edt_ft5x06_attr_##name.limit_high) \ + edt_ft5x06_register_write(tsdata, reg, pdata->name) + +static void __devinit +edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, + const struct edt_ft5x06_platform_data *pdata) +{ + if (!pdata->use_parameters) + return; + + /* pick up defaults from the platform data */ + EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); + EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); + EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); + EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); +} + +static void __devinit +edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) +{ + tsdata->threshold = edt_ft5x06_register_read(tsdata, + WORK_REGISTER_THRESHOLD); + tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); + tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); + tsdata->report_rate = edt_ft5x06_register_read(tsdata, + WORK_REGISTER_REPORT_RATE); + tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); + tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); +} + +static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct edt_ft5x06_platform_data *pdata = + client->dev.platform_data; + struct edt_ft5x06_ts_data *tsdata; + struct input_dev *input; + int error; + char fw_version[EDT_NAME_LEN]; + + dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); + + if (!pdata) { + dev_err(&client->dev, "no platform data?\n"); + return -EINVAL; + } + + error = edt_ft5x06_ts_reset(client, pdata->reset_pin); + if (error) + return error; + + if (gpio_is_valid(pdata->irq_pin)) { + error = gpio_request_one(pdata->irq_pin, + GPIOF_IN, "edt-ft5x06 irq"); + if (error) { + dev_err(&client->dev, + "Failed to request GPIO %d, error %d\n", + pdata->irq_pin, error); + return error; + } + } + + tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); + input = input_allocate_device(); + if (!tsdata || !input) { + dev_err(&client->dev, "failed to allocate driver data.\n"); + error = -ENOMEM; + goto err_free_mem; + } + + mutex_init(&tsdata->mutex); + tsdata->client = client; + tsdata->input = input; + tsdata->factory_mode = false; + + error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); + if (error) { + dev_err(&client->dev, "touchscreen probe failed\n"); + goto err_free_mem; + } + + edt_ft5x06_ts_get_defaults(tsdata, pdata); + edt_ft5x06_ts_get_parameters(tsdata); + + dev_dbg(&client->dev, + "Model \"%s\", Rev. \"%s\", %dx%d sensors\n", + tsdata->name, fw_version, tsdata->num_x, tsdata->num_y); + + input->name = tsdata->name; + input->id.bustype = BUS_I2C; + input->dev.parent = &client->dev; + + __set_bit(EV_SYN, input->evbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(EV_ABS, input->evbit); + __set_bit(BTN_TOUCH, input->keybit); + input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0); + input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_X, + 0, tsdata->num_x * 64 - 1, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, + 0, tsdata->num_y * 64 - 1, 0, 0); + error = input_mt_init_slots(input, MAX_SUPPORT_POINTS); + if (error) { + dev_err(&client->dev, "Unable to init MT slots.\n"); + goto err_free_mem; + } + + input_set_drvdata(input, tsdata); + i2c_set_clientdata(client, tsdata); + + error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, tsdata); + if (error) { + dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); + goto err_free_mem; + } + + error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group); + if (error) + goto err_free_irq; + + error = input_register_device(input); + if (error) + goto err_remove_attrs; + + edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); + device_init_wakeup(&client->dev, 1); + + dev_dbg(&client->dev, + "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n", + pdata->irq_pin, pdata->reset_pin); + + return 0; + +err_remove_attrs: + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); +err_free_irq: + free_irq(client->irq, tsdata); +err_free_mem: + input_free_device(input); + kfree(tsdata); + + if (gpio_is_valid(pdata->irq_pin)) + gpio_free(pdata->irq_pin); + + return error; +} + +static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) +{ + const struct edt_ft5x06_platform_data *pdata = + dev_get_platdata(&client->dev); + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + + edt_ft5x06_ts_teardown_debugfs(tsdata); + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); + + free_irq(client->irq, tsdata); + input_unregister_device(tsdata->input); + + if (gpio_is_valid(pdata->irq_pin)) + gpio_free(pdata->irq_pin); + if (gpio_is_valid(pdata->reset_pin)) + gpio_free(pdata->reset_pin); + + kfree(tsdata->raw_buffer); + kfree(tsdata); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int edt_ft5x06_ts_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(client->irq); + + return 0; +} + +static int edt_ft5x06_ts_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops, + edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume); + +static const struct i2c_device_id edt_ft5x06_ts_id[] = { + { "edt-ft5x06", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); + +static struct i2c_driver edt_ft5x06_ts_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "edt_ft5x06", + .pm = &edt_ft5x06_ts_pm_ops, + }, + .id_table = edt_ft5x06_ts_id, + .probe = edt_ft5x06_ts_probe, + .remove = __devexit_p(edt_ft5x06_ts_remove), +}; + +module_i2c_driver(edt_ft5x06_ts_driver); + +MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>"); +MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 10f122a3a85..1eee45b69b7 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -260,15 +260,6 @@ config DM_DEBUG_BLOCK_STACK_TRACING If unsure, say N. -config DM_DEBUG_SPACE_MAPS - boolean "Extra validation for thin provisioning space maps" - depends on DM_THIN_PROVISIONING - ---help--- - Enable this for messages that may help debug problems with the - space maps used by thin provisioning. - - If unsure, say N. - config DM_MIRROR tristate "Mirror target" depends on BLK_DEV_DM diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3f06df59fd8..664743d6a6c 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -42,21 +42,21 @@ struct convert_context { unsigned int offset_out; unsigned int idx_in; unsigned int idx_out; - sector_t sector; - atomic_t pending; + sector_t cc_sector; + atomic_t cc_pending; }; /* * per bio private data */ struct dm_crypt_io { - struct dm_target *target; + struct crypt_config *cc; struct bio *base_bio; struct work_struct work; struct convert_context ctx; - atomic_t pending; + atomic_t io_pending; int error; sector_t sector; struct dm_crypt_io *base_io; @@ -109,9 +109,6 @@ enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID }; */ struct crypt_cpu { struct ablkcipher_request *req; - /* ESSIV: struct crypto_cipher *essiv_tfm */ - void *iv_private; - struct crypto_ablkcipher *tfms[0]; }; /* @@ -151,6 +148,10 @@ struct crypt_config { * per_cpu_ptr() only. */ struct crypt_cpu __percpu *cpu; + + /* ESSIV: struct crypto_cipher *essiv_tfm */ + void *iv_private; + struct crypto_ablkcipher **tfms; unsigned tfms_count; /* @@ -193,7 +194,7 @@ static struct crypt_cpu *this_crypt_config(struct crypt_config *cc) */ static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc) { - return __this_cpu_ptr(cc->cpu)->tfms[0]; + return cc->tfms[0]; } /* @@ -258,7 +259,7 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) struct hash_desc desc; struct scatterlist sg; struct crypto_cipher *essiv_tfm; - int err, cpu; + int err; sg_init_one(&sg, cc->key, cc->key_size); desc.tfm = essiv->hash_tfm; @@ -268,14 +269,12 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) if (err) return err; - for_each_possible_cpu(cpu) { - essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private, + essiv_tfm = cc->iv_private; - err = crypto_cipher_setkey(essiv_tfm, essiv->salt, - crypto_hash_digestsize(essiv->hash_tfm)); - if (err) - return err; - } + err = crypto_cipher_setkey(essiv_tfm, essiv->salt, + crypto_hash_digestsize(essiv->hash_tfm)); + if (err) + return err; return 0; } @@ -286,16 +285,14 @@ static int crypt_iv_essiv_wipe(struct crypt_config *cc) struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm); struct crypto_cipher *essiv_tfm; - int cpu, r, err = 0; + int r, err = 0; memset(essiv->salt, 0, salt_size); - for_each_possible_cpu(cpu) { - essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private; - r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size); - if (r) - err = r; - } + essiv_tfm = cc->iv_private; + r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size); + if (r) + err = r; return err; } @@ -335,8 +332,6 @@ static struct crypto_cipher *setup_essiv_cpu(struct crypt_config *cc, static void crypt_iv_essiv_dtr(struct crypt_config *cc) { - int cpu; - struct crypt_cpu *cpu_cc; struct crypto_cipher *essiv_tfm; struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; @@ -346,15 +341,12 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) kzfree(essiv->salt); essiv->salt = NULL; - for_each_possible_cpu(cpu) { - cpu_cc = per_cpu_ptr(cc->cpu, cpu); - essiv_tfm = cpu_cc->iv_private; + essiv_tfm = cc->iv_private; - if (essiv_tfm) - crypto_free_cipher(essiv_tfm); + if (essiv_tfm) + crypto_free_cipher(essiv_tfm); - cpu_cc->iv_private = NULL; - } + cc->iv_private = NULL; } static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, @@ -363,7 +355,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, struct crypto_cipher *essiv_tfm = NULL; struct crypto_hash *hash_tfm = NULL; u8 *salt = NULL; - int err, cpu; + int err; if (!opts) { ti->error = "Digest algorithm missing for ESSIV mode"; @@ -388,15 +380,13 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, cc->iv_gen_private.essiv.salt = salt; cc->iv_gen_private.essiv.hash_tfm = hash_tfm; - for_each_possible_cpu(cpu) { - essiv_tfm = setup_essiv_cpu(cc, ti, salt, - crypto_hash_digestsize(hash_tfm)); - if (IS_ERR(essiv_tfm)) { - crypt_iv_essiv_dtr(cc); - return PTR_ERR(essiv_tfm); - } - per_cpu_ptr(cc->cpu, cpu)->iv_private = essiv_tfm; + essiv_tfm = setup_essiv_cpu(cc, ti, salt, + crypto_hash_digestsize(hash_tfm)); + if (IS_ERR(essiv_tfm)) { + crypt_iv_essiv_dtr(cc); + return PTR_ERR(essiv_tfm); } + cc->iv_private = essiv_tfm; return 0; @@ -410,7 +400,7 @@ bad: static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, struct dm_crypt_request *dmreq) { - struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private; + struct crypto_cipher *essiv_tfm = cc->iv_private; memset(iv, 0, cc->iv_size); *(__le64 *)iv = cpu_to_le64(dmreq->iv_sector); @@ -664,7 +654,7 @@ static void crypt_convert_init(struct crypt_config *cc, ctx->offset_out = 0; ctx->idx_in = bio_in ? bio_in->bi_idx : 0; ctx->idx_out = bio_out ? bio_out->bi_idx : 0; - ctx->sector = sector + cc->iv_offset; + ctx->cc_sector = sector + cc->iv_offset; init_completion(&ctx->restart); } @@ -695,12 +685,12 @@ static int crypt_convert_block(struct crypt_config *cc, struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); struct dm_crypt_request *dmreq; u8 *iv; - int r = 0; + int r; dmreq = dmreq_of_req(cc, req); iv = iv_of_dmreq(cc, dmreq); - dmreq->iv_sector = ctx->sector; + dmreq->iv_sector = ctx->cc_sector; dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, @@ -749,12 +739,12 @@ static void crypt_alloc_req(struct crypt_config *cc, struct convert_context *ctx) { struct crypt_cpu *this_cc = this_crypt_config(cc); - unsigned key_index = ctx->sector & (cc->tfms_count - 1); + unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1); if (!this_cc->req) this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); - ablkcipher_request_set_tfm(this_cc->req, this_cc->tfms[key_index]); + ablkcipher_request_set_tfm(this_cc->req, cc->tfms[key_index]); ablkcipher_request_set_callback(this_cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, kcryptd_async_done, dmreq_of_req(cc, this_cc->req)); @@ -769,14 +759,14 @@ static int crypt_convert(struct crypt_config *cc, struct crypt_cpu *this_cc = this_crypt_config(cc); int r; - atomic_set(&ctx->pending, 1); + atomic_set(&ctx->cc_pending, 1); while(ctx->idx_in < ctx->bio_in->bi_vcnt && ctx->idx_out < ctx->bio_out->bi_vcnt) { crypt_alloc_req(cc, ctx); - atomic_inc(&ctx->pending); + atomic_inc(&ctx->cc_pending); r = crypt_convert_block(cc, ctx, this_cc->req); @@ -788,19 +778,19 @@ static int crypt_convert(struct crypt_config *cc, /* fall through*/ case -EINPROGRESS: this_cc->req = NULL; - ctx->sector++; + ctx->cc_sector++; continue; /* sync */ case 0: - atomic_dec(&ctx->pending); - ctx->sector++; + atomic_dec(&ctx->cc_pending); + ctx->cc_sector++; cond_resched(); continue; /* error */ default: - atomic_dec(&ctx->pending); + atomic_dec(&ctx->cc_pending); return r; } } @@ -811,7 +801,7 @@ static int crypt_convert(struct crypt_config *cc, static void dm_crypt_bio_destructor(struct bio *bio) { struct dm_crypt_io *io = bio->bi_private; - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; bio_free(bio, cc->bs); } @@ -825,7 +815,7 @@ static void dm_crypt_bio_destructor(struct bio *bio) static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, unsigned *out_of_pages) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; struct bio *clone; unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; @@ -884,26 +874,25 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone) } } -static struct dm_crypt_io *crypt_io_alloc(struct dm_target *ti, +static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc, struct bio *bio, sector_t sector) { - struct crypt_config *cc = ti->private; struct dm_crypt_io *io; io = mempool_alloc(cc->io_pool, GFP_NOIO); - io->target = ti; + io->cc = cc; io->base_bio = bio; io->sector = sector; io->error = 0; io->base_io = NULL; - atomic_set(&io->pending, 0); + atomic_set(&io->io_pending, 0); return io; } static void crypt_inc_pending(struct dm_crypt_io *io) { - atomic_inc(&io->pending); + atomic_inc(&io->io_pending); } /* @@ -913,12 +902,12 @@ static void crypt_inc_pending(struct dm_crypt_io *io) */ static void crypt_dec_pending(struct dm_crypt_io *io) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; struct bio *base_bio = io->base_bio; struct dm_crypt_io *base_io = io->base_io; int error = io->error; - if (!atomic_dec_and_test(&io->pending)) + if (!atomic_dec_and_test(&io->io_pending)) return; mempool_free(io, cc->io_pool); @@ -952,7 +941,7 @@ static void crypt_dec_pending(struct dm_crypt_io *io) static void crypt_endio(struct bio *clone, int error) { struct dm_crypt_io *io = clone->bi_private; - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; unsigned rw = bio_data_dir(clone); if (unlikely(!bio_flagged(clone, BIO_UPTODATE) && !error)) @@ -979,7 +968,7 @@ static void crypt_endio(struct bio *clone, int error) static void clone_init(struct dm_crypt_io *io, struct bio *clone) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; clone->bi_private = io; clone->bi_end_io = crypt_endio; @@ -990,7 +979,7 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone) static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; struct bio *base_bio = io->base_bio; struct bio *clone; @@ -1038,7 +1027,7 @@ static void kcryptd_io(struct work_struct *work) static void kcryptd_queue_io(struct dm_crypt_io *io) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; INIT_WORK(&io->work, kcryptd_io); queue_work(cc->io_queue, &io->work); @@ -1047,7 +1036,7 @@ static void kcryptd_queue_io(struct dm_crypt_io *io) static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) { struct bio *clone = io->ctx.bio_out; - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; if (unlikely(io->error < 0)) { crypt_free_buffer_pages(cc, clone); @@ -1069,7 +1058,7 @@ static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; struct bio *clone; struct dm_crypt_io *new_io; int crypt_finished; @@ -1107,7 +1096,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) if (r < 0) io->error = -EIO; - crypt_finished = atomic_dec_and_test(&io->ctx.pending); + crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending); /* Encryption was already finished, submit io now */ if (crypt_finished) { @@ -1135,7 +1124,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) * between fragments, so switch to a new dm_crypt_io structure. */ if (unlikely(!crypt_finished && remaining)) { - new_io = crypt_io_alloc(io->target, io->base_bio, + new_io = crypt_io_alloc(io->cc, io->base_bio, sector); crypt_inc_pending(new_io); crypt_convert_init(cc, &new_io->ctx, NULL, @@ -1169,7 +1158,7 @@ static void kcryptd_crypt_read_done(struct dm_crypt_io *io) static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; int r = 0; crypt_inc_pending(io); @@ -1181,7 +1170,7 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) if (r < 0) io->error = -EIO; - if (atomic_dec_and_test(&io->ctx.pending)) + if (atomic_dec_and_test(&io->ctx.cc_pending)) kcryptd_crypt_read_done(io); crypt_dec_pending(io); @@ -1193,7 +1182,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, struct dm_crypt_request *dmreq = async_req->data; struct convert_context *ctx = dmreq->ctx; struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; if (error == -EINPROGRESS) { complete(&ctx->restart); @@ -1208,7 +1197,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); - if (!atomic_dec_and_test(&ctx->pending)) + if (!atomic_dec_and_test(&ctx->cc_pending)) return; if (bio_data_dir(io->base_bio) == READ) @@ -1229,7 +1218,7 @@ static void kcryptd_crypt(struct work_struct *work) static void kcryptd_queue_crypt(struct dm_crypt_io *io) { - struct crypt_config *cc = io->target->private; + struct crypt_config *cc = io->cc; INIT_WORK(&io->work, kcryptd_crypt); queue_work(cc->crypt_queue, &io->work); @@ -1241,7 +1230,6 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io) static int crypt_decode_key(u8 *key, char *hex, unsigned int size) { char buffer[3]; - char *endp; unsigned int i; buffer[2] = '\0'; @@ -1250,9 +1238,7 @@ static int crypt_decode_key(u8 *key, char *hex, unsigned int size) buffer[0] = *hex++; buffer[1] = *hex++; - key[i] = (u8)simple_strtoul(buffer, &endp, 16); - - if (endp != &buffer[2]) + if (kstrtou8(buffer, 16, &key[i])) return -EINVAL; } @@ -1276,29 +1262,38 @@ static void crypt_encode_key(char *hex, u8 *key, unsigned int size) } } -static void crypt_free_tfms(struct crypt_config *cc, int cpu) +static void crypt_free_tfms(struct crypt_config *cc) { - struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu); unsigned i; + if (!cc->tfms) + return; + for (i = 0; i < cc->tfms_count; i++) - if (cpu_cc->tfms[i] && !IS_ERR(cpu_cc->tfms[i])) { - crypto_free_ablkcipher(cpu_cc->tfms[i]); - cpu_cc->tfms[i] = NULL; + if (cc->tfms[i] && !IS_ERR(cc->tfms[i])) { + crypto_free_ablkcipher(cc->tfms[i]); + cc->tfms[i] = NULL; } + + kfree(cc->tfms); + cc->tfms = NULL; } -static int crypt_alloc_tfms(struct crypt_config *cc, int cpu, char *ciphermode) +static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode) { - struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu); unsigned i; int err; + cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_ablkcipher *), + GFP_KERNEL); + if (!cc->tfms) + return -ENOMEM; + for (i = 0; i < cc->tfms_count; i++) { - cpu_cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0); - if (IS_ERR(cpu_cc->tfms[i])) { - err = PTR_ERR(cpu_cc->tfms[i]); - crypt_free_tfms(cc, cpu); + cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0); + if (IS_ERR(cc->tfms[i])) { + err = PTR_ERR(cc->tfms[i]); + crypt_free_tfms(cc); return err; } } @@ -1309,15 +1304,14 @@ static int crypt_alloc_tfms(struct crypt_config *cc, int cpu, char *ciphermode) static int crypt_setkey_allcpus(struct crypt_config *cc) { unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count); - int cpu, err = 0, i, r; - - for_each_possible_cpu(cpu) { - for (i = 0; i < cc->tfms_count; i++) { - r = crypto_ablkcipher_setkey(per_cpu_ptr(cc->cpu, cpu)->tfms[i], - cc->key + (i * subkey_size), subkey_size); - if (r) - err = r; - } + int err = 0, i, r; + + for (i = 0; i < cc->tfms_count; i++) { + r = crypto_ablkcipher_setkey(cc->tfms[i], + cc->key + (i * subkey_size), + subkey_size); + if (r) + err = r; } return err; @@ -1379,9 +1373,10 @@ static void crypt_dtr(struct dm_target *ti) cpu_cc = per_cpu_ptr(cc->cpu, cpu); if (cpu_cc->req) mempool_free(cpu_cc->req, cc->req_pool); - crypt_free_tfms(cc, cpu); } + crypt_free_tfms(cc); + if (cc->bs) bioset_free(cc->bs); @@ -1414,7 +1409,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, struct crypt_config *cc = ti->private; char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount; char *cipher_api = NULL; - int cpu, ret = -EINVAL; + int ret = -EINVAL; char dummy; /* Convert to crypto api definition? */ @@ -1455,8 +1450,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, if (tmp) DMWARN("Ignoring unexpected additional cipher options"); - cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)) + - cc->tfms_count * sizeof(*(cc->cpu->tfms)), + cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)), __alignof__(struct crypt_cpu)); if (!cc->cpu) { ti->error = "Cannot allocate per cpu state"; @@ -1489,12 +1483,10 @@ static int crypt_ctr_cipher(struct dm_target *ti, } /* Allocate cipher */ - for_each_possible_cpu(cpu) { - ret = crypt_alloc_tfms(cc, cpu, cipher_api); - if (ret < 0) { - ti->error = "Error allocating crypto tfm"; - goto bad; - } + ret = crypt_alloc_tfms(cc, cipher_api); + if (ret < 0) { + ti->error = "Error allocating crypto tfm"; + goto bad; } /* Initialize and set key */ @@ -1702,7 +1694,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } ti->num_flush_requests = 1; - ti->discard_zeroes_data_unsupported = 1; + ti->discard_zeroes_data_unsupported = true; return 0; @@ -1715,7 +1707,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, union map_info *map_context) { struct dm_crypt_io *io; - struct crypt_config *cc; + struct crypt_config *cc = ti->private; /* * If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues. @@ -1723,14 +1715,13 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, * - for REQ_DISCARD caller must use flush if IO ordering matters */ if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) { - cc = ti->private; bio->bi_bdev = cc->dev->bdev; if (bio_sectors(bio)) bio->bi_sector = cc->start + dm_target_offset(ti, bio->bi_sector); return DM_MAPIO_REMAPPED; } - io = crypt_io_alloc(ti, bio, dm_target_offset(ti, bio->bi_sector)); + io = crypt_io_alloc(cc, bio, dm_target_offset(ti, bio->bi_sector)); if (bio_data_dir(io->base_bio) == READ) { if (kcryptd_io_read(io, GFP_NOWAIT)) @@ -1742,7 +1733,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, } static int crypt_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { struct crypt_config *cc = ti->private; unsigned int sz = 0; diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 2dc22dddb2a..f53846f9ab5 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -295,7 +295,7 @@ static int delay_map(struct dm_target *ti, struct bio *bio, } static int delay_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) + unsigned status_flags, char *result, unsigned maxlen) { struct delay_c *dc = ti->private; int sz = 0; diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index aa70f7d43a1..ebaa4f803ee 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -142,24 +142,19 @@ EXPORT_SYMBOL(dm_exception_store_type_unregister); static int set_chunk_size(struct dm_exception_store *store, const char *chunk_size_arg, char **error) { - unsigned long chunk_size_ulong; - char *value; + unsigned chunk_size; - chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10); - if (*chunk_size_arg == '\0' || *value != '\0' || - chunk_size_ulong > UINT_MAX) { + if (kstrtouint(chunk_size_arg, 10, &chunk_size)) { *error = "Invalid chunk size"; return -EINVAL; } - if (!chunk_size_ulong) { + if (!chunk_size) { store->chunk_size = store->chunk_mask = store->chunk_shift = 0; return 0; } - return dm_exception_store_set_chunk_size(store, - (unsigned) chunk_size_ulong, - error); + return dm_exception_store_set_chunk_size(store, chunk_size, error); } int dm_exception_store_set_chunk_size(struct dm_exception_store *store, diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index ac49c01f1a4..cc15543a6ad 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -333,7 +333,7 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, } static int flakey_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { unsigned sz = 0; struct flakey_c *fc = ti->private; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index a1a3e6df17b..afd95986d09 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1054,6 +1054,7 @@ static void retrieve_status(struct dm_table *table, char *outbuf, *outptr; status_type_t type; size_t remaining, len, used = 0; + unsigned status_flags = 0; outptr = outbuf = get_result_buffer(param, param_size, &len); @@ -1090,7 +1091,9 @@ static void retrieve_status(struct dm_table *table, /* Get the status/table string from the target driver */ if (ti->type->status) { - if (ti->type->status(ti, type, outptr, remaining)) { + if (param->flags & DM_NOFLUSH_FLAG) + status_flags |= DM_STATUS_NOFLUSH_FLAG; + if (ti->type->status(ti, type, status_flags, outptr, remaining)) { param->flags |= DM_BUFFER_FULL_FLAG; break; } diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 3639eeab604..1bf19a93eef 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -96,7 +96,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio, } static int linear_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { struct linear_c *lc = (struct linear_c *) ti->private; diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 638dae048b4..d8abb90a6c2 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -85,6 +85,7 @@ struct multipath { unsigned queue_io:1; /* Must we queue all I/O? */ unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */ unsigned saved_queue_if_no_path:1; /* Saved state during suspension */ + unsigned retain_attached_hw_handler:1; /* If there's already a hw_handler present, don't change it. */ unsigned pg_init_retries; /* Number of times to retry pg_init */ unsigned pg_init_count; /* Number of times pg_init called */ @@ -568,6 +569,8 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps int r; struct pgpath *p; struct multipath *m = ti->private; + struct request_queue *q = NULL; + const char *attached_handler_name; /* we need at least a path arg */ if (as->argc < 1) { @@ -586,13 +589,37 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps goto bad; } - if (m->hw_handler_name) { - struct request_queue *q = bdev_get_queue(p->path.dev->bdev); + if (m->retain_attached_hw_handler || m->hw_handler_name) + q = bdev_get_queue(p->path.dev->bdev); + + if (m->retain_attached_hw_handler) { + attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL); + if (attached_handler_name) { + /* + * Reset hw_handler_name to match the attached handler + * and clear any hw_handler_params associated with the + * ignored handler. + * + * NB. This modifies the table line to show the actual + * handler instead of the original table passed in. + */ + kfree(m->hw_handler_name); + m->hw_handler_name = attached_handler_name; + + kfree(m->hw_handler_params); + m->hw_handler_params = NULL; + } + } + if (m->hw_handler_name) { + /* + * Increments scsi_dh reference, even when using an + * already-attached handler. + */ r = scsi_dh_attach(q, m->hw_handler_name); if (r == -EBUSY) { /* - * Already attached to different hw_handler, + * Already attached to different hw_handler: * try to reattach with correct one. */ scsi_dh_detach(q); @@ -760,7 +787,7 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m) const char *arg_name; static struct dm_arg _args[] = { - {0, 5, "invalid number of feature args"}, + {0, 6, "invalid number of feature args"}, {1, 50, "pg_init_retries must be between 1 and 50"}, {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"}, }; @@ -781,6 +808,11 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m) continue; } + if (!strcasecmp(arg_name, "retain_attached_hw_handler")) { + m->retain_attached_hw_handler = 1; + continue; + } + if (!strcasecmp(arg_name, "pg_init_retries") && (argc >= 1)) { r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error); @@ -1346,7 +1378,7 @@ static void multipath_resume(struct dm_target *ti) * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ */ static int multipath_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { int sz = 0; unsigned long flags; @@ -1364,13 +1396,16 @@ static int multipath_status(struct dm_target *ti, status_type_t type, else { DMEMIT("%u ", m->queue_if_no_path + (m->pg_init_retries > 0) * 2 + - (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2); + (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2 + + m->retain_attached_hw_handler); if (m->queue_if_no_path) DMEMIT("queue_if_no_path "); if (m->pg_init_retries) DMEMIT("pg_init_retries %u ", m->pg_init_retries); if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs); + if (m->retain_attached_hw_handler) + DMEMIT("retain_attached_hw_handler "); } if (!m->hw_handler_name || type == STATUSTYPE_INFO) @@ -1656,7 +1691,7 @@ out: *---------------------------------------------------------------*/ static struct target_type multipath_target = { .name = "multipath", - .version = {1, 4, 0}, + .version = {1, 5, 0}, .module = THIS_MODULE, .ctr = multipath_ctr, .dtr = multipath_dtr, diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 017c34d78d6..f2f29c52654 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -101,20 +101,12 @@ static struct raid_set *context_alloc(struct dm_target *ti, struct raid_type *ra { unsigned i; struct raid_set *rs; - sector_t sectors_per_dev; if (raid_devs <= raid_type->parity_devs) { ti->error = "Insufficient number of devices"; return ERR_PTR(-EINVAL); } - sectors_per_dev = ti->len; - if ((raid_type->level > 1) && - sector_div(sectors_per_dev, (raid_devs - raid_type->parity_devs))) { - ti->error = "Target length not divisible by number of data devices"; - return ERR_PTR(-EINVAL); - } - rs = kzalloc(sizeof(*rs) + raid_devs * sizeof(rs->dev[0]), GFP_KERNEL); if (!rs) { ti->error = "Cannot allocate raid context"; @@ -128,7 +120,6 @@ static struct raid_set *context_alloc(struct dm_target *ti, struct raid_type *ra rs->md.raid_disks = raid_devs; rs->md.level = raid_type->level; rs->md.new_level = rs->md.level; - rs->md.dev_sectors = sectors_per_dev; rs->md.layout = raid_type->algorithm; rs->md.new_layout = rs->md.layout; rs->md.delta_disks = 0; @@ -143,6 +134,7 @@ static struct raid_set *context_alloc(struct dm_target *ti, struct raid_type *ra * rs->md.external * rs->md.chunk_sectors * rs->md.new_chunk_sectors + * rs->md.dev_sectors */ return rs; @@ -353,6 +345,8 @@ static int parse_raid_params(struct raid_set *rs, char **argv, { unsigned i, rebuild_cnt = 0; unsigned long value, region_size = 0; + sector_t sectors_per_dev = rs->ti->len; + sector_t max_io_len; char *key; /* @@ -429,13 +423,28 @@ static int parse_raid_params(struct raid_set *rs, char **argv, if (!strcasecmp(key, "rebuild")) { rebuild_cnt++; - if (((rs->raid_type->level != 1) && - (rebuild_cnt > rs->raid_type->parity_devs)) || - ((rs->raid_type->level == 1) && - (rebuild_cnt > (rs->md.raid_disks - 1)))) { - rs->ti->error = "Too many rebuild devices specified for given RAID type"; + + switch (rs->raid_type->level) { + case 1: + if (rebuild_cnt >= rs->md.raid_disks) { + rs->ti->error = "Too many rebuild devices specified"; + return -EINVAL; + } + break; + case 4: + case 5: + case 6: + if (rebuild_cnt > rs->raid_type->parity_devs) { + rs->ti->error = "Too many rebuild devices specified for given RAID type"; + return -EINVAL; + } + break; + default: + DMERR("The rebuild parameter is not supported for %s", rs->raid_type->name); + rs->ti->error = "Rebuild not supported for this RAID type"; return -EINVAL; } + if (value > rs->md.raid_disks) { rs->ti->error = "Invalid rebuild index given"; return -EINVAL; @@ -522,14 +531,19 @@ static int parse_raid_params(struct raid_set *rs, char **argv, return -EINVAL; if (rs->md.chunk_sectors) - rs->ti->split_io = rs->md.chunk_sectors; + max_io_len = rs->md.chunk_sectors; else - rs->ti->split_io = region_size; + max_io_len = region_size; - if (rs->md.chunk_sectors) - rs->ti->split_io = rs->md.chunk_sectors; - else - rs->ti->split_io = region_size; + if (dm_set_target_max_io_len(rs->ti, max_io_len)) + return -EINVAL; + + if ((rs->raid_type->level > 1) && + sector_div(sectors_per_dev, (rs->md.raid_disks - rs->raid_type->parity_devs))) { + rs->ti->error = "Target length not divisible by number of data devices"; + return -EINVAL; + } + rs->md.dev_sectors = sectors_per_dev; /* Assume there are no metadata devices until the drives are parsed */ rs->md.persistent = 0; @@ -1067,7 +1081,7 @@ static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_c } static int raid_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) + unsigned status_flags, char *result, unsigned maxlen) { struct raid_set *rs = ti->private; unsigned raid_param_cnt = 1; /* at least 1 for chunksize */ diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index b58b7a33914..bc5ddba8045 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1081,10 +1081,14 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) } ti->private = ms; - ti->split_io = dm_rh_get_region_size(ms->rh); + + r = dm_set_target_max_io_len(ti, dm_rh_get_region_size(ms->rh)); + if (r) + goto err_free_context; + ti->num_flush_requests = 1; ti->num_discard_requests = 1; - ti->discard_zeroes_data_unsupported = 1; + ti->discard_zeroes_data_unsupported = true; ms->kmirrord_wq = alloc_workqueue("kmirrord", WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0); @@ -1363,7 +1367,7 @@ static char device_status_char(struct mirror *m) static int mirror_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { unsigned int m, sz = 0; struct mirror_set *ms = (struct mirror_set *) ti->private; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 6f758870fc1..a143921feaf 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -691,7 +691,7 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new) * Return a minimum chunk size of all snapshots that have the specified origin. * Return zero if the origin has no snapshots. */ -static sector_t __minimum_chunk_size(struct origin *o) +static uint32_t __minimum_chunk_size(struct origin *o) { struct dm_snapshot *snap; unsigned chunk_size = 0; @@ -701,7 +701,7 @@ static sector_t __minimum_chunk_size(struct origin *o) chunk_size = min_not_zero(chunk_size, snap->store->chunk_size); - return chunk_size; + return (uint32_t) chunk_size; } /* @@ -1172,7 +1172,10 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error = "Chunk size not set"; goto bad_read_metadata; } - ti->split_io = s->store->chunk_size; + + r = dm_set_target_max_io_len(ti, s->store->chunk_size); + if (r) + goto bad_read_metadata; return 0; @@ -1239,7 +1242,7 @@ static void __handover_exceptions(struct dm_snapshot *snap_src, snap_dest->store->snap = snap_dest; snap_src->store->snap = snap_src; - snap_dest->ti->split_io = snap_dest->store->chunk_size; + snap_dest->ti->max_io_len = snap_dest->store->chunk_size; snap_dest->valid = snap_src->valid; /* @@ -1817,9 +1820,9 @@ static void snapshot_resume(struct dm_target *ti) up_write(&s->lock); } -static sector_t get_origin_minimum_chunksize(struct block_device *bdev) +static uint32_t get_origin_minimum_chunksize(struct block_device *bdev) { - sector_t min_chunksize; + uint32_t min_chunksize; down_read(&_origins_lock); min_chunksize = __minimum_chunk_size(__lookup_origin(bdev)); @@ -1838,15 +1841,15 @@ static void snapshot_merge_resume(struct dm_target *ti) snapshot_resume(ti); /* - * snapshot-merge acts as an origin, so set ti->split_io + * snapshot-merge acts as an origin, so set ti->max_io_len */ - ti->split_io = get_origin_minimum_chunksize(s->origin->bdev); + ti->max_io_len = get_origin_minimum_chunksize(s->origin->bdev); start_merge(s); } static int snapshot_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) + unsigned status_flags, char *result, unsigned maxlen) { unsigned sz = 0; struct dm_snapshot *snap = ti->private; @@ -2073,12 +2076,12 @@ static int origin_write_extent(struct dm_snapshot *merging_snap, struct origin *o; /* - * The origin's __minimum_chunk_size() got stored in split_io + * The origin's __minimum_chunk_size() got stored in max_io_len * by snapshot_merge_resume(). */ down_read(&_origins_lock); o = __lookup_origin(merging_snap->origin->bdev); - for (n = 0; n < size; n += merging_snap->ti->split_io) + for (n = 0; n < size; n += merging_snap->ti->max_io_len) if (__origin_write(&o->snapshots, sector + n, NULL) == DM_MAPIO_SUBMITTED) must_wait = 1; @@ -2138,18 +2141,18 @@ static int origin_map(struct dm_target *ti, struct bio *bio, } /* - * Set the target "split_io" field to the minimum of all the snapshots' + * Set the target "max_io_len" field to the minimum of all the snapshots' * chunk sizes. */ static void origin_resume(struct dm_target *ti) { struct dm_dev *dev = ti->private; - ti->split_io = get_origin_minimum_chunksize(dev->bdev); + ti->max_io_len = get_origin_minimum_chunksize(dev->bdev); } -static int origin_status(struct dm_target *ti, status_type_t type, char *result, - unsigned int maxlen) +static int origin_status(struct dm_target *ti, status_type_t type, + unsigned status_flags, char *result, unsigned maxlen) { struct dm_dev *dev = ti->private; @@ -2176,7 +2179,6 @@ static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, return max_size; bvm->bi_bdev = dev->bdev; - bvm->bi_sector = bvm->bi_sector; return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); } diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 35c94ff24ad..a087bf2a8d6 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -26,14 +26,12 @@ struct stripe { struct stripe_c { uint32_t stripes; int stripes_shift; - sector_t stripes_mask; /* The size of this target / num. stripes */ sector_t stripe_width; - /* stripe chunk size */ - uint32_t chunk_shift; - sector_t chunk_mask; + uint32_t chunk_size; + int chunk_size_shift; /* Needed for handling events */ struct dm_target *ti; @@ -91,7 +89,7 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc, /* * Construct a striped mapping. - * <number of stripes> <chunk size (2^^n)> [<dev_path> <offset>]+ + * <number of stripes> <chunk size> [<dev_path> <offset>]+ */ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) { @@ -99,7 +97,6 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) sector_t width; uint32_t stripes; uint32_t chunk_size; - char *end; int r; unsigned int i; @@ -108,34 +105,23 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) return -EINVAL; } - stripes = simple_strtoul(argv[0], &end, 10); - if (!stripes || *end) { + if (kstrtouint(argv[0], 10, &stripes) || !stripes) { ti->error = "Invalid stripe count"; return -EINVAL; } - chunk_size = simple_strtoul(argv[1], &end, 10); - if (*end) { + if (kstrtouint(argv[1], 10, &chunk_size) || !chunk_size) { ti->error = "Invalid chunk_size"; return -EINVAL; } - /* - * chunk_size is a power of two - */ - if (!is_power_of_2(chunk_size) || - (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) { - ti->error = "Invalid chunk size"; - return -EINVAL; - } - - if (ti->len & (chunk_size - 1)) { + width = ti->len; + if (sector_div(width, chunk_size)) { ti->error = "Target length not divisible by " "chunk size"; return -EINVAL; } - width = ti->len; if (sector_div(width, stripes)) { ti->error = "Target length not divisible by " "number of stripes"; @@ -167,17 +153,21 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (stripes & (stripes - 1)) sc->stripes_shift = -1; - else { - sc->stripes_shift = ffs(stripes) - 1; - sc->stripes_mask = ((sector_t) stripes) - 1; - } + else + sc->stripes_shift = __ffs(stripes); + + r = dm_set_target_max_io_len(ti, chunk_size); + if (r) + return r; - ti->split_io = chunk_size; ti->num_flush_requests = stripes; ti->num_discard_requests = stripes; - sc->chunk_shift = ffs(chunk_size) - 1; - sc->chunk_mask = ((sector_t) chunk_size) - 1; + sc->chunk_size = chunk_size; + if (chunk_size & (chunk_size - 1)) + sc->chunk_size_shift = -1; + else + sc->chunk_size_shift = __ffs(chunk_size); /* * Get the stripe destinations. @@ -216,17 +206,29 @@ static void stripe_dtr(struct dm_target *ti) static void stripe_map_sector(struct stripe_c *sc, sector_t sector, uint32_t *stripe, sector_t *result) { - sector_t offset = dm_target_offset(sc->ti, sector); - sector_t chunk = offset >> sc->chunk_shift; + sector_t chunk = dm_target_offset(sc->ti, sector); + sector_t chunk_offset; + + if (sc->chunk_size_shift < 0) + chunk_offset = sector_div(chunk, sc->chunk_size); + else { + chunk_offset = chunk & (sc->chunk_size - 1); + chunk >>= sc->chunk_size_shift; + } if (sc->stripes_shift < 0) *stripe = sector_div(chunk, sc->stripes); else { - *stripe = chunk & sc->stripes_mask; + *stripe = chunk & (sc->stripes - 1); chunk >>= sc->stripes_shift; } - *result = (chunk << sc->chunk_shift) | (offset & sc->chunk_mask); + if (sc->chunk_size_shift < 0) + chunk *= sc->chunk_size; + else + chunk <<= sc->chunk_size_shift; + + *result = chunk + chunk_offset; } static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, @@ -237,9 +239,16 @@ static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector, stripe_map_sector(sc, sector, &stripe, result); if (stripe == target_stripe) return; - *result &= ~sc->chunk_mask; /* round down */ + + /* round down */ + sector = *result; + if (sc->chunk_size_shift < 0) + *result -= sector_div(sector, sc->chunk_size); + else + *result = sector & ~(sector_t)(sc->chunk_size - 1); + if (target_stripe < stripe) - *result += sc->chunk_mask + 1; /* next chunk */ + *result += sc->chunk_size; /* next chunk */ } static int stripe_map_discard(struct stripe_c *sc, struct bio *bio, @@ -302,8 +311,8 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, * */ -static int stripe_status(struct dm_target *ti, - status_type_t type, char *result, unsigned int maxlen) +static int stripe_status(struct dm_target *ti, status_type_t type, + unsigned status_flags, char *result, unsigned maxlen) { struct stripe_c *sc = (struct stripe_c *) ti->private; char buffer[sc->stripes + 1]; @@ -324,7 +333,7 @@ static int stripe_status(struct dm_target *ti, case STATUSTYPE_TABLE: DMEMIT("%d %llu", sc->stripes, - (unsigned long long)sc->chunk_mask + 1); + (unsigned long long)sc->chunk_size); for (i = 0; i < sc->stripes; i++) DMEMIT(" %s %llu", sc->stripe[i].dev->name, (unsigned long long)sc->stripe[i].physical_start); @@ -391,7 +400,7 @@ static void stripe_io_hints(struct dm_target *ti, struct queue_limits *limits) { struct stripe_c *sc = ti->private; - unsigned chunk_size = (sc->chunk_mask + 1) << 9; + unsigned chunk_size = sc->chunk_size << SECTOR_SHIFT; blk_limits_io_min(limits, chunk_size); blk_limits_io_opt(limits, chunk_size * sc->stripes); @@ -419,7 +428,7 @@ static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm, static struct target_type stripe_target = { .name = "striped", - .version = {1, 4, 0}, + .version = {1, 5, 0}, .module = THIS_MODULE, .ctr = stripe_ctr, .dtr = stripe_dtr, diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2e227fbf162..f90069029aa 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1319,6 +1319,9 @@ static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) if (!ti->num_flush_requests) continue; + if (ti->flush_supported) + return 1; + if (ti->type->iterate_devices && ti->type->iterate_devices(ti, device_flush_capable, &flush)) return 1; diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 3e2907f0bc4..693e149e972 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Red Hat, Inc. + * Copyright (C) 2011-2012 Red Hat, Inc. * * This file is released under the GPL. */ @@ -80,6 +80,12 @@ #define THIN_METADATA_CACHE_SIZE 64 #define SECTOR_TO_BLOCK_SHIFT 3 +/* + * 3 for btree insert + + * 2 for btree lookup used within space map + */ +#define THIN_MAX_CONCURRENT_LOCKS 5 + /* This should be plenty */ #define SPACE_MAP_ROOT_SIZE 128 @@ -172,13 +178,20 @@ struct dm_pool_metadata { struct rw_semaphore root_lock; uint32_t time; - int need_commit; dm_block_t root; dm_block_t details_root; struct list_head thin_devices; uint64_t trans_id; unsigned long flags; sector_t data_block_size; + bool read_only:1; + + /* + * Set if a transaction has to be aborted but the attempt to roll back + * to the previous (good) transaction failed. The only pool metadata + * operation possible in this state is the closing of the device. + */ + bool fail_io:1; }; struct dm_thin_device { @@ -187,7 +200,8 @@ struct dm_thin_device { dm_thin_id id; int open_count; - int changed; + bool changed:1; + bool aborted_with_changes:1; uint64_t mapped_blocks; uint64_t transaction_id; uint32_t creation_time; @@ -338,7 +352,21 @@ static int subtree_equal(void *context, void *value1_le, void *value2_le) /*----------------------------------------------------------------*/ -static int superblock_all_zeroes(struct dm_block_manager *bm, int *result) +static int superblock_lock_zero(struct dm_pool_metadata *pmd, + struct dm_block **sblock) +{ + return dm_bm_write_lock_zero(pmd->bm, THIN_SUPERBLOCK_LOCATION, + &sb_validator, sblock); +} + +static int superblock_lock(struct dm_pool_metadata *pmd, + struct dm_block **sblock) +{ + return dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, + &sb_validator, sblock); +} + +static int __superblock_all_zeroes(struct dm_block_manager *bm, int *result) { int r; unsigned i; @@ -365,72 +393,9 @@ static int superblock_all_zeroes(struct dm_block_manager *bm, int *result) return dm_bm_unlock(b); } -static int init_pmd(struct dm_pool_metadata *pmd, - struct dm_block_manager *bm, - dm_block_t nr_blocks, int create) +static void __setup_btree_details(struct dm_pool_metadata *pmd) { - int r; - struct dm_space_map *sm, *data_sm; - struct dm_transaction_manager *tm; - struct dm_block *sblock; - - if (create) { - r = dm_tm_create_with_sm(bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &tm, &sm, &sblock); - if (r < 0) { - DMERR("tm_create_with_sm failed"); - return r; - } - - data_sm = dm_sm_disk_create(tm, nr_blocks); - if (IS_ERR(data_sm)) { - DMERR("sm_disk_create failed"); - dm_tm_unlock(tm, sblock); - r = PTR_ERR(data_sm); - goto bad; - } - } else { - struct thin_disk_superblock *disk_super = NULL; - size_t space_map_root_offset = - offsetof(struct thin_disk_superblock, metadata_space_map_root); - - r = dm_tm_open_with_sm(bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, space_map_root_offset, - SPACE_MAP_ROOT_SIZE, &tm, &sm, &sblock); - if (r < 0) { - DMERR("tm_open_with_sm failed"); - return r; - } - - disk_super = dm_block_data(sblock); - data_sm = dm_sm_disk_open(tm, disk_super->data_space_map_root, - sizeof(disk_super->data_space_map_root)); - if (IS_ERR(data_sm)) { - DMERR("sm_disk_open failed"); - r = PTR_ERR(data_sm); - goto bad; - } - } - - - r = dm_tm_unlock(tm, sblock); - if (r < 0) { - DMERR("couldn't unlock superblock"); - goto bad_data_sm; - } - - pmd->bm = bm; - pmd->metadata_sm = sm; - pmd->data_sm = data_sm; - pmd->tm = tm; - pmd->nb_tm = dm_tm_create_non_blocking_clone(tm); - if (!pmd->nb_tm) { - DMERR("could not create clone tm"); - r = -ENOMEM; - goto bad_data_sm; - } - - pmd->info.tm = tm; + pmd->info.tm = pmd->tm; pmd->info.levels = 2; pmd->info.value_type.context = pmd->data_sm; pmd->info.value_type.size = sizeof(__le64); @@ -441,7 +406,7 @@ static int init_pmd(struct dm_pool_metadata *pmd, memcpy(&pmd->nb_info, &pmd->info, sizeof(pmd->nb_info)); pmd->nb_info.tm = pmd->nb_tm; - pmd->tl_info.tm = tm; + pmd->tl_info.tm = pmd->tm; pmd->tl_info.levels = 1; pmd->tl_info.value_type.context = &pmd->info; pmd->tl_info.value_type.size = sizeof(__le64); @@ -449,7 +414,7 @@ static int init_pmd(struct dm_pool_metadata *pmd, pmd->tl_info.value_type.dec = subtree_dec; pmd->tl_info.value_type.equal = subtree_equal; - pmd->bl_info.tm = tm; + pmd->bl_info.tm = pmd->tm; pmd->bl_info.levels = 1; pmd->bl_info.value_type.context = pmd->data_sm; pmd->bl_info.value_type.size = sizeof(__le64); @@ -457,48 +422,266 @@ static int init_pmd(struct dm_pool_metadata *pmd, pmd->bl_info.value_type.dec = data_block_dec; pmd->bl_info.value_type.equal = data_block_equal; - pmd->details_info.tm = tm; + pmd->details_info.tm = pmd->tm; pmd->details_info.levels = 1; pmd->details_info.value_type.context = NULL; pmd->details_info.value_type.size = sizeof(struct disk_device_details); pmd->details_info.value_type.inc = NULL; pmd->details_info.value_type.dec = NULL; pmd->details_info.value_type.equal = NULL; +} - pmd->root = 0; +static int __write_initial_superblock(struct dm_pool_metadata *pmd) +{ + int r; + struct dm_block *sblock; + size_t metadata_len, data_len; + struct thin_disk_superblock *disk_super; + sector_t bdev_size = i_size_read(pmd->bdev->bd_inode) >> SECTOR_SHIFT; - init_rwsem(&pmd->root_lock); - pmd->time = 0; - pmd->need_commit = 0; - pmd->details_root = 0; - pmd->trans_id = 0; - pmd->flags = 0; - INIT_LIST_HEAD(&pmd->thin_devices); + if (bdev_size > THIN_METADATA_MAX_SECTORS) + bdev_size = THIN_METADATA_MAX_SECTORS; + + r = dm_sm_root_size(pmd->metadata_sm, &metadata_len); + if (r < 0) + return r; + + r = dm_sm_root_size(pmd->data_sm, &data_len); + if (r < 0) + return r; + + r = dm_sm_commit(pmd->data_sm); + if (r < 0) + return r; + + r = dm_tm_pre_commit(pmd->tm); + if (r < 0) + return r; + + r = superblock_lock_zero(pmd, &sblock); + if (r) + return r; + + disk_super = dm_block_data(sblock); + disk_super->flags = 0; + memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); + disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC); + disk_super->version = cpu_to_le32(THIN_VERSION); + disk_super->time = 0; + disk_super->trans_id = 0; + disk_super->held_root = 0; + + r = dm_sm_copy_root(pmd->metadata_sm, &disk_super->metadata_space_map_root, + metadata_len); + if (r < 0) + goto bad_locked; + + r = dm_sm_copy_root(pmd->data_sm, &disk_super->data_space_map_root, + data_len); + if (r < 0) + goto bad_locked; + + disk_super->data_mapping_root = cpu_to_le64(pmd->root); + disk_super->device_details_root = cpu_to_le64(pmd->details_root); + disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); + disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); + disk_super->data_block_size = cpu_to_le32(pmd->data_block_size); + + return dm_tm_commit(pmd->tm, sblock); + +bad_locked: + dm_bm_unlock(sblock); + return r; +} + +static int __format_metadata(struct dm_pool_metadata *pmd) +{ + int r; + + r = dm_tm_create_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION, + &pmd->tm, &pmd->metadata_sm); + if (r < 0) { + DMERR("tm_create_with_sm failed"); + return r; + } + + pmd->data_sm = dm_sm_disk_create(pmd->tm, 0); + if (IS_ERR(pmd->data_sm)) { + DMERR("sm_disk_create failed"); + r = PTR_ERR(pmd->data_sm); + goto bad_cleanup_tm; + } + + pmd->nb_tm = dm_tm_create_non_blocking_clone(pmd->tm); + if (!pmd->nb_tm) { + DMERR("could not create non-blocking clone tm"); + r = -ENOMEM; + goto bad_cleanup_data_sm; + } + + __setup_btree_details(pmd); + + r = dm_btree_empty(&pmd->info, &pmd->root); + if (r < 0) + goto bad_cleanup_nb_tm; + + r = dm_btree_empty(&pmd->details_info, &pmd->details_root); + if (r < 0) { + DMERR("couldn't create devices root"); + goto bad_cleanup_nb_tm; + } + + r = __write_initial_superblock(pmd); + if (r) + goto bad_cleanup_nb_tm; return 0; -bad_data_sm: - dm_sm_destroy(data_sm); -bad: - dm_tm_destroy(tm); - dm_sm_destroy(sm); +bad_cleanup_nb_tm: + dm_tm_destroy(pmd->nb_tm); +bad_cleanup_data_sm: + dm_sm_destroy(pmd->data_sm); +bad_cleanup_tm: + dm_tm_destroy(pmd->tm); + dm_sm_destroy(pmd->metadata_sm); + + return r; +} + +static int __check_incompat_features(struct thin_disk_superblock *disk_super, + struct dm_pool_metadata *pmd) +{ + uint32_t features; + + features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP; + if (features) { + DMERR("could not access metadata due to unsupported optional features (%lx).", + (unsigned long)features); + return -EINVAL; + } + + /* + * Check for read-only metadata to skip the following RDWR checks. + */ + if (get_disk_ro(pmd->bdev->bd_disk)) + return 0; + + features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP; + if (features) { + DMERR("could not access metadata RDWR due to unsupported optional features (%lx).", + (unsigned long)features); + return -EINVAL; + } + + return 0; +} + +static int __open_metadata(struct dm_pool_metadata *pmd) +{ + int r; + struct dm_block *sblock; + struct thin_disk_superblock *disk_super; + + r = dm_bm_read_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, + &sb_validator, &sblock); + if (r < 0) { + DMERR("couldn't read superblock"); + return r; + } + + disk_super = dm_block_data(sblock); + + r = __check_incompat_features(disk_super, pmd); + if (r < 0) + goto bad_unlock_sblock; + + r = dm_tm_open_with_sm(pmd->bm, THIN_SUPERBLOCK_LOCATION, + disk_super->metadata_space_map_root, + sizeof(disk_super->metadata_space_map_root), + &pmd->tm, &pmd->metadata_sm); + if (r < 0) { + DMERR("tm_open_with_sm failed"); + goto bad_unlock_sblock; + } + + pmd->data_sm = dm_sm_disk_open(pmd->tm, disk_super->data_space_map_root, + sizeof(disk_super->data_space_map_root)); + if (IS_ERR(pmd->data_sm)) { + DMERR("sm_disk_open failed"); + r = PTR_ERR(pmd->data_sm); + goto bad_cleanup_tm; + } + + pmd->nb_tm = dm_tm_create_non_blocking_clone(pmd->tm); + if (!pmd->nb_tm) { + DMERR("could not create non-blocking clone tm"); + r = -ENOMEM; + goto bad_cleanup_data_sm; + } + + __setup_btree_details(pmd); + return dm_bm_unlock(sblock); + +bad_cleanup_data_sm: + dm_sm_destroy(pmd->data_sm); +bad_cleanup_tm: + dm_tm_destroy(pmd->tm); + dm_sm_destroy(pmd->metadata_sm); +bad_unlock_sblock: + dm_bm_unlock(sblock); + + return r; +} + +static int __open_or_format_metadata(struct dm_pool_metadata *pmd, bool format_device) +{ + int r, unformatted; + + r = __superblock_all_zeroes(pmd->bm, &unformatted); + if (r) + return r; + + if (unformatted) + return format_device ? __format_metadata(pmd) : -EPERM; + + return __open_metadata(pmd); +} + +static int __create_persistent_data_objects(struct dm_pool_metadata *pmd, bool format_device) +{ + int r; + + pmd->bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE, + THIN_METADATA_CACHE_SIZE, + THIN_MAX_CONCURRENT_LOCKS); + if (IS_ERR(pmd->bm)) { + DMERR("could not create block manager"); + return PTR_ERR(pmd->bm); + } + + r = __open_or_format_metadata(pmd, format_device); + if (r) + dm_block_manager_destroy(pmd->bm); return r; } +static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd) +{ + dm_sm_destroy(pmd->data_sm); + dm_sm_destroy(pmd->metadata_sm); + dm_tm_destroy(pmd->nb_tm); + dm_tm_destroy(pmd->tm); + dm_block_manager_destroy(pmd->bm); +} + static int __begin_transaction(struct dm_pool_metadata *pmd) { int r; - u32 features; struct thin_disk_superblock *disk_super; struct dm_block *sblock; /* - * __maybe_commit_transaction() resets these - */ - WARN_ON(pmd->need_commit); - - /* * We re-read the superblock every time. Shouldn't need to do this * really. */ @@ -515,32 +698,8 @@ static int __begin_transaction(struct dm_pool_metadata *pmd) pmd->flags = le32_to_cpu(disk_super->flags); pmd->data_block_size = le32_to_cpu(disk_super->data_block_size); - features = le32_to_cpu(disk_super->incompat_flags) & ~THIN_FEATURE_INCOMPAT_SUPP; - if (features) { - DMERR("could not access metadata due to " - "unsupported optional features (%lx).", - (unsigned long)features); - r = -EINVAL; - goto out; - } - - /* - * Check for read-only metadata to skip the following RDWR checks. - */ - if (get_disk_ro(pmd->bdev->bd_disk)) - goto out; - - features = le32_to_cpu(disk_super->compat_ro_flags) & ~THIN_FEATURE_COMPAT_RO_SUPP; - if (features) { - DMERR("could not access metadata RDWR due to " - "unsupported optional features (%lx).", - (unsigned long)features); - r = -EINVAL; - } - -out: dm_bm_unlock(sblock); - return r; + return 0; } static int __write_changed_details(struct dm_pool_metadata *pmd) @@ -573,8 +732,6 @@ static int __write_changed_details(struct dm_pool_metadata *pmd) list_del(&td->list); kfree(td); } - - pmd->need_commit = 1; } return 0; @@ -582,9 +739,6 @@ static int __write_changed_details(struct dm_pool_metadata *pmd) static int __commit_transaction(struct dm_pool_metadata *pmd) { - /* - * FIXME: Associated pool should be made read-only on failure. - */ int r; size_t metadata_len, data_len; struct thin_disk_superblock *disk_super; @@ -597,31 +751,27 @@ static int __commit_transaction(struct dm_pool_metadata *pmd) r = __write_changed_details(pmd); if (r < 0) - goto out; - - if (!pmd->need_commit) - goto out; + return r; r = dm_sm_commit(pmd->data_sm); if (r < 0) - goto out; + return r; r = dm_tm_pre_commit(pmd->tm); if (r < 0) - goto out; + return r; r = dm_sm_root_size(pmd->metadata_sm, &metadata_len); if (r < 0) - goto out; + return r; r = dm_sm_root_size(pmd->data_sm, &data_len); if (r < 0) - goto out; + return r; - r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); + r = superblock_lock(pmd, &sblock); if (r) - goto out; + return r; disk_super = dm_block_data(sblock); disk_super->time = cpu_to_le32(pmd->time); @@ -640,12 +790,7 @@ static int __commit_transaction(struct dm_pool_metadata *pmd) if (r < 0) goto out_locked; - r = dm_tm_commit(pmd->tm, sblock); - if (!r) - pmd->need_commit = 0; - -out: - return r; + return dm_tm_commit(pmd->tm, sblock); out_locked: dm_bm_unlock(sblock); @@ -653,15 +798,11 @@ out_locked: } struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, - sector_t data_block_size) + sector_t data_block_size, + bool format_device) { int r; - struct thin_disk_superblock *disk_super; struct dm_pool_metadata *pmd; - sector_t bdev_size = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT; - struct dm_block_manager *bm; - int create; - struct dm_block *sblock; pmd = kmalloc(sizeof(*pmd), GFP_KERNEL); if (!pmd) { @@ -669,90 +810,28 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, return ERR_PTR(-ENOMEM); } - /* - * Max hex locks: - * 3 for btree insert + - * 2 for btree lookup used within space map - */ - bm = dm_block_manager_create(bdev, THIN_METADATA_BLOCK_SIZE, - THIN_METADATA_CACHE_SIZE, 5); - if (!bm) { - DMERR("could not create block manager"); - kfree(pmd); - return ERR_PTR(-ENOMEM); - } - - r = superblock_all_zeroes(bm, &create); - if (r) { - dm_block_manager_destroy(bm); - kfree(pmd); - return ERR_PTR(r); - } - + init_rwsem(&pmd->root_lock); + pmd->time = 0; + INIT_LIST_HEAD(&pmd->thin_devices); + pmd->read_only = false; + pmd->fail_io = false; + pmd->bdev = bdev; + pmd->data_block_size = data_block_size; - r = init_pmd(pmd, bm, 0, create); + r = __create_persistent_data_objects(pmd, format_device); if (r) { - dm_block_manager_destroy(bm); kfree(pmd); return ERR_PTR(r); } - pmd->bdev = bdev; - - if (!create) { - r = __begin_transaction(pmd); - if (r < 0) - goto bad; - return pmd; - } - - /* - * Create. - */ - r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); - if (r) - goto bad; - - if (bdev_size > THIN_METADATA_MAX_SECTORS) - bdev_size = THIN_METADATA_MAX_SECTORS; - - disk_super = dm_block_data(sblock); - disk_super->magic = cpu_to_le64(THIN_SUPERBLOCK_MAGIC); - disk_super->version = cpu_to_le32(THIN_VERSION); - disk_super->time = 0; - disk_super->metadata_block_size = cpu_to_le32(THIN_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); - disk_super->metadata_nr_blocks = cpu_to_le64(bdev_size >> SECTOR_TO_BLOCK_SHIFT); - disk_super->data_block_size = cpu_to_le32(data_block_size); - - r = dm_bm_unlock(sblock); - if (r < 0) - goto bad; - - r = dm_btree_empty(&pmd->info, &pmd->root); - if (r < 0) - goto bad; - - r = dm_btree_empty(&pmd->details_info, &pmd->details_root); - if (r < 0) { - DMERR("couldn't create devices root"); - goto bad; - } - pmd->flags = 0; - pmd->need_commit = 1; - r = dm_pool_commit_metadata(pmd); + r = __begin_transaction(pmd); if (r < 0) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - goto bad; + if (dm_pool_metadata_close(pmd) < 0) + DMWARN("%s: dm_pool_metadata_close() failed.", __func__); + return ERR_PTR(r); } return pmd; - -bad: - if (dm_pool_metadata_close(pmd) < 0) - DMWARN("%s: dm_pool_metadata_close() failed.", __func__); - return ERR_PTR(r); } int dm_pool_metadata_close(struct dm_pool_metadata *pmd) @@ -778,18 +857,17 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) return -EBUSY; } - r = __commit_transaction(pmd); - if (r < 0) - DMWARN("%s: __commit_transaction() failed, error = %d", - __func__, r); + if (!pmd->read_only && !pmd->fail_io) { + r = __commit_transaction(pmd); + if (r < 0) + DMWARN("%s: __commit_transaction() failed, error = %d", + __func__, r); + } - dm_tm_destroy(pmd->tm); - dm_tm_destroy(pmd->nb_tm); - dm_block_manager_destroy(pmd->bm); - dm_sm_destroy(pmd->metadata_sm); - dm_sm_destroy(pmd->data_sm); - kfree(pmd); + if (!pmd->fail_io) + __destroy_persistent_data_objects(pmd); + kfree(pmd); return 0; } @@ -850,6 +928,7 @@ static int __open_device(struct dm_pool_metadata *pmd, (*td)->id = dev; (*td)->open_count = 1; (*td)->changed = changed; + (*td)->aborted_with_changes = false; (*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks); (*td)->transaction_id = le64_to_cpu(details_le.transaction_id); (*td)->creation_time = le32_to_cpu(details_le.creation_time); @@ -911,10 +990,11 @@ static int __create_thin(struct dm_pool_metadata *pmd, int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __create_thin(pmd, dev); + if (!pmd->fail_io) + r = __create_thin(pmd, dev); up_write(&pmd->root_lock); return r; @@ -1001,10 +1081,11 @@ int dm_pool_create_snap(struct dm_pool_metadata *pmd, dm_thin_id dev, dm_thin_id origin) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __create_snap(pmd, dev, origin); + if (!pmd->fail_io) + r = __create_snap(pmd, dev, origin); up_write(&pmd->root_lock); return r; @@ -1037,18 +1118,17 @@ static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev) if (r) return r; - pmd->need_commit = 1; - return 0; } int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __delete_device(pmd, dev); + if (!pmd->fail_io) + r = __delete_device(pmd, dev); up_write(&pmd->root_lock); return r; @@ -1058,28 +1138,40 @@ int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd, uint64_t current_id, uint64_t new_id) { + int r = -EINVAL; + down_write(&pmd->root_lock); + + if (pmd->fail_io) + goto out; + if (pmd->trans_id != current_id) { - up_write(&pmd->root_lock); DMERR("mismatched transaction id"); - return -EINVAL; + goto out; } pmd->trans_id = new_id; - pmd->need_commit = 1; + r = 0; + +out: up_write(&pmd->root_lock); - return 0; + return r; } int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd, uint64_t *result) { + int r = -EINVAL; + down_read(&pmd->root_lock); - *result = pmd->trans_id; + if (!pmd->fail_io) { + *result = pmd->trans_id; + r = 0; + } up_read(&pmd->root_lock); - return 0; + return r; } static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) @@ -1108,8 +1200,6 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) dm_tm_dec(pmd->tm, held_root); dm_tm_unlock(pmd->tm, copy); - pmd->need_commit = 1; - return -EBUSY; } @@ -1131,29 +1221,25 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) /* * Write the held root into the superblock. */ - r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); + r = superblock_lock(pmd, &sblock); if (r) { dm_tm_dec(pmd->tm, held_root); - pmd->need_commit = 1; return r; } disk_super = dm_block_data(sblock); disk_super->held_root = cpu_to_le64(held_root); dm_bm_unlock(sblock); - - pmd->need_commit = 1; - return 0; } int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __reserve_metadata_snap(pmd); + if (!pmd->fail_io) + r = __reserve_metadata_snap(pmd); up_write(&pmd->root_lock); return r; @@ -1166,15 +1252,13 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) struct dm_block *sblock, *copy; dm_block_t held_root; - r = dm_bm_write_lock(pmd->bm, THIN_SUPERBLOCK_LOCATION, - &sb_validator, &sblock); + r = superblock_lock(pmd, &sblock); if (r) return r; disk_super = dm_block_data(sblock); held_root = le64_to_cpu(disk_super->held_root); disk_super->held_root = cpu_to_le64(0); - pmd->need_commit = 1; dm_bm_unlock(sblock); @@ -1197,10 +1281,11 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd) int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __release_metadata_snap(pmd); + if (!pmd->fail_io) + r = __release_metadata_snap(pmd); up_write(&pmd->root_lock); return r; @@ -1227,10 +1312,11 @@ static int __get_metadata_snap(struct dm_pool_metadata *pmd, int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, dm_block_t *result) { - int r; + int r = -EINVAL; down_read(&pmd->root_lock); - r = __get_metadata_snap(pmd, result); + if (!pmd->fail_io) + r = __get_metadata_snap(pmd, result); up_read(&pmd->root_lock); return r; @@ -1239,10 +1325,11 @@ int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev, struct dm_thin_device **td) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __open_device(pmd, dev, 0, td); + if (!pmd->fail_io) + r = __open_device(pmd, dev, 0, td); up_write(&pmd->root_lock); return r; @@ -1262,7 +1349,7 @@ dm_thin_id dm_thin_dev_id(struct dm_thin_device *td) return td->id; } -static int __snapshotted_since(struct dm_thin_device *td, uint32_t time) +static bool __snapshotted_since(struct dm_thin_device *td, uint32_t time) { return td->snapshotted_time > time; } @@ -1270,28 +1357,31 @@ static int __snapshotted_since(struct dm_thin_device *td, uint32_t time) int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block, int can_block, struct dm_thin_lookup_result *result) { - int r; + int r = -EINVAL; uint64_t block_time = 0; __le64 value; struct dm_pool_metadata *pmd = td->pmd; dm_block_t keys[2] = { td->id, block }; + struct dm_btree_info *info; if (can_block) { down_read(&pmd->root_lock); - r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value); - if (!r) - block_time = le64_to_cpu(value); - up_read(&pmd->root_lock); - - } else if (down_read_trylock(&pmd->root_lock)) { - r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value); - if (!r) - block_time = le64_to_cpu(value); - up_read(&pmd->root_lock); - - } else + info = &pmd->info; + } else if (down_read_trylock(&pmd->root_lock)) + info = &pmd->nb_info; + else return -EWOULDBLOCK; + if (pmd->fail_io) + goto out; + + r = dm_btree_lookup(info, pmd->root, keys, &value); + if (!r) + block_time = le64_to_cpu(value); + +out: + up_read(&pmd->root_lock); + if (!r) { dm_block_t exception_block; uint32_t exception_time; @@ -1312,7 +1402,6 @@ static int __insert(struct dm_thin_device *td, dm_block_t block, struct dm_pool_metadata *pmd = td->pmd; dm_block_t keys[2] = { td->id, block }; - pmd->need_commit = 1; value = cpu_to_le64(pack_block_time(data_block, pmd->time)); __dm_bless_for_disk(&value); @@ -1321,10 +1410,9 @@ static int __insert(struct dm_thin_device *td, dm_block_t block, if (r) return r; - if (inserted) { + td->changed = 1; + if (inserted) td->mapped_blocks++; - td->changed = 1; - } return 0; } @@ -1332,10 +1420,11 @@ static int __insert(struct dm_thin_device *td, dm_block_t block, int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block, dm_block_t data_block) { - int r; + int r = -EINVAL; down_write(&td->pmd->root_lock); - r = __insert(td, block, data_block); + if (!td->pmd->fail_io) + r = __insert(td, block, data_block); up_write(&td->pmd->root_lock); return r; @@ -1353,31 +1442,51 @@ static int __remove(struct dm_thin_device *td, dm_block_t block) td->mapped_blocks--; td->changed = 1; - pmd->need_commit = 1; return 0; } int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block) { - int r; + int r = -EINVAL; down_write(&td->pmd->root_lock); - r = __remove(td, block); + if (!td->pmd->fail_io) + r = __remove(td, block); up_write(&td->pmd->root_lock); return r; } -int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result) +bool dm_thin_changed_this_transaction(struct dm_thin_device *td) { int r; - down_write(&pmd->root_lock); + down_read(&td->pmd->root_lock); + r = td->changed; + up_read(&td->pmd->root_lock); - r = dm_sm_new_block(pmd->data_sm, result); - pmd->need_commit = 1; + return r; +} + +bool dm_thin_aborted_changes(struct dm_thin_device *td) +{ + bool r; + down_read(&td->pmd->root_lock); + r = td->aborted_with_changes; + up_read(&td->pmd->root_lock); + + return r; +} + +int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result) +{ + int r = -EINVAL; + + down_write(&pmd->root_lock); + if (!pmd->fail_io) + r = dm_sm_new_block(pmd->data_sm, result); up_write(&pmd->root_lock); return r; @@ -1385,9 +1494,11 @@ int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result) int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); + if (pmd->fail_io) + goto out; r = __commit_transaction(pmd); if (r <= 0) @@ -1402,12 +1513,41 @@ out: return r; } +static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd) +{ + struct dm_thin_device *td; + + list_for_each_entry(td, &pmd->thin_devices, list) + td->aborted_with_changes = td->changed; +} + +int dm_pool_abort_metadata(struct dm_pool_metadata *pmd) +{ + int r = -EINVAL; + + down_write(&pmd->root_lock); + if (pmd->fail_io) + goto out; + + __set_abort_with_changes_flags(pmd); + __destroy_persistent_data_objects(pmd); + r = __create_persistent_data_objects(pmd, false); + if (r) + pmd->fail_io = true; + +out: + up_write(&pmd->root_lock); + + return r; +} + int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result) { - int r; + int r = -EINVAL; down_read(&pmd->root_lock); - r = dm_sm_get_nr_free(pmd->data_sm, result); + if (!pmd->fail_io) + r = dm_sm_get_nr_free(pmd->data_sm, result); up_read(&pmd->root_lock); return r; @@ -1416,10 +1556,11 @@ int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *resul int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, dm_block_t *result) { - int r; + int r = -EINVAL; down_read(&pmd->root_lock); - r = dm_sm_get_nr_free(pmd->metadata_sm, result); + if (!pmd->fail_io) + r = dm_sm_get_nr_free(pmd->metadata_sm, result); up_read(&pmd->root_lock); return r; @@ -1428,10 +1569,11 @@ int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result) { - int r; + int r = -EINVAL; down_read(&pmd->root_lock); - r = dm_sm_get_nr_blocks(pmd->metadata_sm, result); + if (!pmd->fail_io) + r = dm_sm_get_nr_blocks(pmd->metadata_sm, result); up_read(&pmd->root_lock); return r; @@ -1448,10 +1590,11 @@ int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result) int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result) { - int r; + int r = -EINVAL; down_read(&pmd->root_lock); - r = dm_sm_get_nr_blocks(pmd->data_sm, result); + if (!pmd->fail_io) + r = dm_sm_get_nr_blocks(pmd->data_sm, result); up_read(&pmd->root_lock); return r; @@ -1459,13 +1602,17 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result) int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result) { + int r = -EINVAL; struct dm_pool_metadata *pmd = td->pmd; down_read(&pmd->root_lock); - *result = td->mapped_blocks; + if (!pmd->fail_io) { + *result = td->mapped_blocks; + r = 0; + } up_read(&pmd->root_lock); - return 0; + return r; } static int __highest_block(struct dm_thin_device *td, dm_block_t *result) @@ -1487,11 +1634,12 @@ static int __highest_block(struct dm_thin_device *td, dm_block_t *result) int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, dm_block_t *result) { - int r; + int r = -EINVAL; struct dm_pool_metadata *pmd = td->pmd; down_read(&pmd->root_lock); - r = __highest_block(td, result); + if (!pmd->fail_io) + r = __highest_block(td, result); up_read(&pmd->root_lock); return r; @@ -1514,20 +1662,25 @@ static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count) return -EINVAL; } - r = dm_sm_extend(pmd->data_sm, new_count - old_count); - if (!r) - pmd->need_commit = 1; - - return r; + return dm_sm_extend(pmd->data_sm, new_count - old_count); } int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count) { - int r; + int r = -EINVAL; down_write(&pmd->root_lock); - r = __resize_data_dev(pmd, new_count); + if (!pmd->fail_io) + r = __resize_data_dev(pmd, new_count); up_write(&pmd->root_lock); return r; } + +void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd) +{ + down_write(&pmd->root_lock); + pmd->read_only = true; + dm_bm_set_read_only(pmd->bm); + up_write(&pmd->root_lock); +} diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h index b88918ccdaf..0cecc370288 100644 --- a/drivers/md/dm-thin-metadata.h +++ b/drivers/md/dm-thin-metadata.h @@ -38,7 +38,8 @@ typedef uint64_t dm_thin_id; * Reopens or creates a new, empty metadata volume. */ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev, - sector_t data_block_size); + sector_t data_block_size, + bool format_device); int dm_pool_metadata_close(struct dm_pool_metadata *pmd); @@ -79,6 +80,16 @@ int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd, int dm_pool_commit_metadata(struct dm_pool_metadata *pmd); /* + * Discards all uncommitted changes. Rereads the superblock, rolling back + * to the last good transaction. Thin devices remain open. + * dm_thin_aborted_changes() tells you if they had uncommitted changes. + * + * If this call fails it's only useful to call dm_pool_metadata_close(). + * All other methods will fail with -EINVAL. + */ +int dm_pool_abort_metadata(struct dm_pool_metadata *pmd); + +/* * Set/get userspace transaction id. */ int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd, @@ -119,7 +130,7 @@ dm_thin_id dm_thin_dev_id(struct dm_thin_device *td); struct dm_thin_lookup_result { dm_block_t block; - int shared; + unsigned shared:1; }; /* @@ -147,6 +158,10 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block); /* * Queries. */ +bool dm_thin_changed_this_transaction(struct dm_thin_device *td); + +bool dm_thin_aborted_changes(struct dm_thin_device *td); + int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, dm_block_t *highest_mapped); @@ -171,6 +186,12 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result); */ int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_size); +/* + * Flicks the underlying block manager into read only mode, so you know + * that nothing is changing. + */ +void dm_pool_metadata_read_only(struct dm_pool_metadata *pmd); + /*----------------------------------------------------------------*/ #endif diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 68694da0d21..af1fc3b2c2a 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -1,10 +1,11 @@ /* - * Copyright (C) 2011 Red Hat UK. + * Copyright (C) 2011-2012 Red Hat UK. * * This file is released under the GPL. */ #include "dm-thin-metadata.h" +#include "dm.h" #include <linux/device-mapper.h> #include <linux/dm-io.h> @@ -19,7 +20,7 @@ /* * Tunable constants */ -#define ENDIO_HOOK_POOL_SIZE 10240 +#define ENDIO_HOOK_POOL_SIZE 1024 #define DEFERRED_SET_SIZE 64 #define MAPPING_POOL_SIZE 1024 #define PRISON_CELLS 1024 @@ -496,12 +497,27 @@ static void build_virtual_key(struct dm_thin_device *td, dm_block_t b, */ struct dm_thin_new_mapping; +/* + * The pool runs in 3 modes. Ordered in degraded order for comparisons. + */ +enum pool_mode { + PM_WRITE, /* metadata may be changed */ + PM_READ_ONLY, /* metadata may not be changed */ + PM_FAIL, /* all I/O fails */ +}; + struct pool_features { + enum pool_mode mode; + unsigned zero_new_blocks:1; unsigned discard_enabled:1; unsigned discard_passdown:1; }; +struct thin_c; +typedef void (*process_bio_fn)(struct thin_c *tc, struct bio *bio); +typedef void (*process_mapping_fn)(struct dm_thin_new_mapping *m); + struct pool { struct list_head list; struct dm_target *ti; /* Only set if a pool target is bound */ @@ -510,10 +526,9 @@ struct pool { struct block_device *md_dev; struct dm_pool_metadata *pmd; - uint32_t sectors_per_block; - unsigned block_shift; - dm_block_t offset_mask; dm_block_t low_water_blocks; + uint32_t sectors_per_block; + int sectors_per_block_shift; struct pool_features pf; unsigned low_water_triggered:1; /* A dm event has been sent */ @@ -526,8 +541,8 @@ struct pool { struct work_struct worker; struct delayed_work waker; - unsigned ref_count; unsigned long last_commit_jiffies; + unsigned ref_count; spinlock_t lock; struct bio_list deferred_bios; @@ -543,8 +558,17 @@ struct pool { struct dm_thin_new_mapping *next_mapping; mempool_t *mapping_pool; mempool_t *endio_hook_pool; + + process_bio_fn process_bio; + process_bio_fn process_discard; + + process_mapping_fn process_prepared_mapping; + process_mapping_fn process_prepared_discard; }; +static enum pool_mode get_pool_mode(struct pool *pool); +static void set_pool_mode(struct pool *pool, enum pool_mode mode); + /* * Target context for a pool. */ @@ -679,16 +703,28 @@ static void requeue_io(struct thin_c *tc) static dm_block_t get_bio_block(struct thin_c *tc, struct bio *bio) { - return bio->bi_sector >> tc->pool->block_shift; + sector_t block_nr = bio->bi_sector; + + if (tc->pool->sectors_per_block_shift < 0) + (void) sector_div(block_nr, tc->pool->sectors_per_block); + else + block_nr >>= tc->pool->sectors_per_block_shift; + + return block_nr; } static void remap(struct thin_c *tc, struct bio *bio, dm_block_t block) { struct pool *pool = tc->pool; + sector_t bi_sector = bio->bi_sector; bio->bi_bdev = tc->pool_dev->bdev; - bio->bi_sector = (block << pool->block_shift) + - (bio->bi_sector & pool->offset_mask); + if (tc->pool->sectors_per_block_shift < 0) + bio->bi_sector = (block * pool->sectors_per_block) + + sector_div(bi_sector, pool->sectors_per_block); + else + bio->bi_sector = (block << pool->sectors_per_block_shift) | + (bi_sector & (pool->sectors_per_block - 1)); } static void remap_to_origin(struct thin_c *tc, struct bio *bio) @@ -696,21 +732,39 @@ static void remap_to_origin(struct thin_c *tc, struct bio *bio) bio->bi_bdev = tc->origin_dev->bdev; } +static int bio_triggers_commit(struct thin_c *tc, struct bio *bio) +{ + return (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && + dm_thin_changed_this_transaction(tc->td); +} + static void issue(struct thin_c *tc, struct bio *bio) { struct pool *pool = tc->pool; unsigned long flags; + if (!bio_triggers_commit(tc, bio)) { + generic_make_request(bio); + return; + } + /* - * Batch together any FUA/FLUSH bios we find and then issue - * a single commit for them in process_deferred_bios(). + * Complete bio with an error if earlier I/O caused changes to + * the metadata that can't be committed e.g, due to I/O errors + * on the metadata device. */ - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { - spin_lock_irqsave(&pool->lock, flags); - bio_list_add(&pool->deferred_flush_bios, bio); - spin_unlock_irqrestore(&pool->lock, flags); - } else - generic_make_request(bio); + if (dm_thin_aborted_changes(tc->td)) { + bio_io_error(bio); + return; + } + + /* + * Batch together any bios that trigger commits and then issue a + * single commit for them in process_deferred_bios(). + */ + spin_lock_irqsave(&pool->lock, flags); + bio_list_add(&pool->deferred_flush_bios, bio); + spin_unlock_irqrestore(&pool->lock, flags); } static void remap_to_origin_and_issue(struct thin_c *tc, struct bio *bio) @@ -847,6 +901,14 @@ static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell wake_worker(pool); } +static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m) +{ + if (m->bio) + m->bio->bi_end_io = m->saved_bi_end_io; + cell_error(m->cell); + list_del(&m->list); + mempool_free(m, m->tc->pool->mapping_pool); +} static void process_prepared_mapping(struct dm_thin_new_mapping *m) { struct thin_c *tc = m->tc; @@ -859,7 +921,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) if (m->err) { cell_error(m->cell); - return; + goto out; } /* @@ -871,7 +933,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) if (r) { DMERR("dm_thin_insert_block() failed"); cell_error(m->cell); - return; + goto out; } /* @@ -886,22 +948,25 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m) } else cell_defer(tc, m->cell, m->data_block); +out: list_del(&m->list); mempool_free(m, tc->pool->mapping_pool); } -static void process_prepared_discard(struct dm_thin_new_mapping *m) +static void process_prepared_discard_fail(struct dm_thin_new_mapping *m) { - int r; struct thin_c *tc = m->tc; - r = dm_thin_remove_block(tc->td, m->virt_block); - if (r) - DMERR("dm_thin_remove_block() failed"); + bio_io_error(m->bio); + cell_defer_except(tc, m->cell); + cell_defer_except(tc, m->cell2); + mempool_free(m, tc->pool->mapping_pool); +} + +static void process_prepared_discard_passdown(struct dm_thin_new_mapping *m) +{ + struct thin_c *tc = m->tc; - /* - * Pass the discard down to the underlying device? - */ if (m->pass_discard) remap_and_issue(tc, m->bio, m->data_block); else @@ -912,8 +977,20 @@ static void process_prepared_discard(struct dm_thin_new_mapping *m) mempool_free(m, tc->pool->mapping_pool); } +static void process_prepared_discard(struct dm_thin_new_mapping *m) +{ + int r; + struct thin_c *tc = m->tc; + + r = dm_thin_remove_block(tc->td, m->virt_block); + if (r) + DMERR("dm_thin_remove_block() failed"); + + process_prepared_discard_passdown(m); +} + static void process_prepared(struct pool *pool, struct list_head *head, - void (*fn)(struct dm_thin_new_mapping *)) + process_mapping_fn *fn) { unsigned long flags; struct list_head maps; @@ -925,7 +1002,7 @@ static void process_prepared(struct pool *pool, struct list_head *head, spin_unlock_irqrestore(&pool->lock, flags); list_for_each_entry_safe(m, tmp, &maps, list) - fn(m); + (*fn)(m); } /* @@ -933,9 +1010,7 @@ static void process_prepared(struct pool *pool, struct list_head *head, */ static int io_overlaps_block(struct pool *pool, struct bio *bio) { - return !(bio->bi_sector & pool->offset_mask) && - (bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT)); - + return bio->bi_size == (pool->sectors_per_block << SECTOR_SHIFT); } static int io_overwrites_block(struct pool *pool, struct bio *bio) @@ -1093,6 +1168,35 @@ static void schedule_zero(struct thin_c *tc, dm_block_t virt_block, } } +static int commit(struct pool *pool) +{ + int r; + + r = dm_pool_commit_metadata(pool->pmd); + if (r) + DMERR("commit failed, error = %d", r); + + return r; +} + +/* + * A non-zero return indicates read_only or fail_io mode. + * Many callers don't care about the return value. + */ +static int commit_or_fallback(struct pool *pool) +{ + int r; + + if (get_pool_mode(pool) != PM_WRITE) + return -EINVAL; + + r = commit(pool); + if (r) + set_pool_mode(pool, PM_READ_ONLY); + + return r; +} + static int alloc_data_block(struct thin_c *tc, dm_block_t *result) { int r; @@ -1121,12 +1225,7 @@ static int alloc_data_block(struct thin_c *tc, dm_block_t *result) * Try to commit to see if that will free up some * more space. */ - r = dm_pool_commit_metadata(pool->pmd); - if (r) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - return r; - } + (void) commit_or_fallback(pool); r = dm_pool_get_free_block_count(pool->pmd, &free_blocks); if (r) @@ -1218,7 +1317,7 @@ static void process_discard(struct thin_c *tc, struct bio *bio) */ m = get_next_mapping(pool); m->tc = tc; - m->pass_discard = (!lookup_result.shared) & pool->pf.discard_passdown; + m->pass_discard = (!lookup_result.shared) && pool->pf.discard_passdown; m->virt_block = block; m->data_block = lookup_result.block; m->cell = cell; @@ -1234,15 +1333,10 @@ static void process_discard(struct thin_c *tc, struct bio *bio) } } else { /* - * This path is hit if people are ignoring - * limits->discard_granularity. It ignores any - * part of the discard that is in a subsequent - * block. + * The DM core makes sure that the discard doesn't span + * a block boundary. So we submit the discard of a + * partial block appropriately. */ - sector_t offset = bio->bi_sector - (block << pool->block_shift); - unsigned remaining = (pool->sectors_per_block - offset) << 9; - bio->bi_size = min(bio->bi_size, remaining); - cell_release_singleton(cell, bio); cell_release_singleton(cell2, bio); if ((!lookup_result.shared) && pool->pf.discard_passdown) @@ -1310,7 +1404,7 @@ static void process_shared_bio(struct thin_c *tc, struct bio *bio, if (bio_detain(pool->prison, &key, bio, &cell)) return; - if (bio_data_dir(bio) == WRITE) + if (bio_data_dir(bio) == WRITE && bio->bi_size) break_sharing(tc, bio, block, &key, lookup_result, cell); else { struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; @@ -1362,6 +1456,7 @@ static void provision_block(struct thin_c *tc, struct bio *bio, dm_block_t block default: DMERR("%s: alloc_data_block() failed, error = %d", __func__, r); + set_pool_mode(tc->pool, PM_READ_ONLY); cell_error(cell); break; } @@ -1419,6 +1514,49 @@ static void process_bio(struct thin_c *tc, struct bio *bio) } } +static void process_bio_read_only(struct thin_c *tc, struct bio *bio) +{ + int r; + int rw = bio_data_dir(bio); + dm_block_t block = get_bio_block(tc, bio); + struct dm_thin_lookup_result lookup_result; + + r = dm_thin_find_block(tc->td, block, 1, &lookup_result); + switch (r) { + case 0: + if (lookup_result.shared && (rw == WRITE) && bio->bi_size) + bio_io_error(bio); + else + remap_and_issue(tc, bio, lookup_result.block); + break; + + case -ENODATA: + if (rw != READ) { + bio_io_error(bio); + break; + } + + if (tc->origin_dev) { + remap_to_origin_and_issue(tc, bio); + break; + } + + zero_fill_bio(bio); + bio_endio(bio, 0); + break; + + default: + DMERR("dm_thin_find_block() failed, error = %d", r); + bio_io_error(bio); + break; + } +} + +static void process_bio_fail(struct thin_c *tc, struct bio *bio) +{ + bio_io_error(bio); +} + static int need_commit_due_to_time(struct pool *pool) { return jiffies < pool->last_commit_jiffies || @@ -1430,7 +1568,6 @@ static void process_deferred_bios(struct pool *pool) unsigned long flags; struct bio *bio; struct bio_list bios; - int r; bio_list_init(&bios); @@ -1457,9 +1594,9 @@ static void process_deferred_bios(struct pool *pool) } if (bio->bi_rw & REQ_DISCARD) - process_discard(tc, bio); + pool->process_discard(tc, bio); else - process_bio(tc, bio); + pool->process_bio(tc, bio); } /* @@ -1475,10 +1612,7 @@ static void process_deferred_bios(struct pool *pool) if (bio_list_empty(&bios) && !need_commit_due_to_time(pool)) return; - r = dm_pool_commit_metadata(pool->pmd); - if (r) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); + if (commit_or_fallback(pool)) { while ((bio = bio_list_pop(&bios))) bio_io_error(bio); return; @@ -1493,8 +1627,8 @@ static void do_worker(struct work_struct *ws) { struct pool *pool = container_of(ws, struct pool, worker); - process_prepared(pool, &pool->prepared_mappings, process_prepared_mapping); - process_prepared(pool, &pool->prepared_discards, process_prepared_discard); + process_prepared(pool, &pool->prepared_mappings, &pool->process_prepared_mapping); + process_prepared(pool, &pool->prepared_discards, &pool->process_prepared_discard); process_deferred_bios(pool); } @@ -1511,6 +1645,52 @@ static void do_waker(struct work_struct *ws) /*----------------------------------------------------------------*/ +static enum pool_mode get_pool_mode(struct pool *pool) +{ + return pool->pf.mode; +} + +static void set_pool_mode(struct pool *pool, enum pool_mode mode) +{ + int r; + + pool->pf.mode = mode; + + switch (mode) { + case PM_FAIL: + DMERR("switching pool to failure mode"); + pool->process_bio = process_bio_fail; + pool->process_discard = process_bio_fail; + pool->process_prepared_mapping = process_prepared_mapping_fail; + pool->process_prepared_discard = process_prepared_discard_fail; + break; + + case PM_READ_ONLY: + DMERR("switching pool to read-only mode"); + r = dm_pool_abort_metadata(pool->pmd); + if (r) { + DMERR("aborting transaction failed"); + set_pool_mode(pool, PM_FAIL); + } else { + dm_pool_metadata_read_only(pool->pmd); + pool->process_bio = process_bio_read_only; + pool->process_discard = process_discard; + pool->process_prepared_mapping = process_prepared_mapping_fail; + pool->process_prepared_discard = process_prepared_discard_passdown; + } + break; + + case PM_WRITE: + pool->process_bio = process_bio; + pool->process_discard = process_discard; + pool->process_prepared_mapping = process_prepared_mapping; + pool->process_prepared_discard = process_prepared_discard; + break; + } +} + +/*----------------------------------------------------------------*/ + /* * Mapping functions. */ @@ -1556,6 +1736,12 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, struct dm_thin_lookup_result result; map_context->ptr = thin_hook_bio(tc, bio); + + if (get_pool_mode(tc->pool) == PM_FAIL) { + bio_io_error(bio); + return DM_MAPIO_SUBMITTED; + } + if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) { thin_defer_bio(tc, bio); return DM_MAPIO_SUBMITTED; @@ -1592,14 +1778,35 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio, break; case -ENODATA: + if (get_pool_mode(tc->pool) == PM_READ_ONLY) { + /* + * This block isn't provisioned, and we have no way + * of doing so. Just error it. + */ + bio_io_error(bio); + r = DM_MAPIO_SUBMITTED; + break; + } + /* fall through */ + + case -EWOULDBLOCK: /* * In future, the failed dm_thin_find_block above could * provide the hint to load the metadata into cache. */ - case -EWOULDBLOCK: thin_defer_bio(tc, bio); r = DM_MAPIO_SUBMITTED; break; + + default: + /* + * Must always call bio_io_error on failure. + * dm_thin_find_block can fail with -EINVAL if the + * pool is switched to fail-io mode. + */ + bio_io_error(bio); + r = DM_MAPIO_SUBMITTED; + break; } return r; @@ -1636,15 +1843,26 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti) { struct pool_c *pt = ti->private; + /* + * We want to make sure that degraded pools are never upgraded. + */ + enum pool_mode old_mode = pool->pf.mode; + enum pool_mode new_mode = pt->pf.mode; + + if (old_mode > new_mode) + new_mode = old_mode; + pool->ti = ti; pool->low_water_blocks = pt->low_water_blocks; pool->pf = pt->pf; + set_pool_mode(pool, new_mode); /* * If discard_passdown was enabled verify that the data device * supports discards. Disable discard_passdown if not; otherwise * -EOPNOTSUPP will be returned. */ + /* FIXME: pull this out into a sep fn. */ if (pt->pf.discard_passdown) { struct request_queue *q = bdev_get_queue(pt->data_dev->bdev); if (!q || !blk_queue_discard(q)) { @@ -1670,6 +1888,7 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti) /* Initialize pool features. */ static void pool_features_init(struct pool_features *pf) { + pf->mode = PM_WRITE; pf->zero_new_blocks = 1; pf->discard_enabled = 1; pf->discard_passdown = 1; @@ -1700,14 +1919,16 @@ static struct kmem_cache *_endio_hook_cache; static struct pool *pool_create(struct mapped_device *pool_md, struct block_device *metadata_dev, - unsigned long block_size, char **error) + unsigned long block_size, + int read_only, char **error) { int r; void *err_p; struct pool *pool; struct dm_pool_metadata *pmd; + bool format_device = read_only ? false : true; - pmd = dm_pool_metadata_open(metadata_dev, block_size); + pmd = dm_pool_metadata_open(metadata_dev, block_size, format_device); if (IS_ERR(pmd)) { *error = "Error creating metadata object"; return (struct pool *)pmd; @@ -1722,8 +1943,10 @@ static struct pool *pool_create(struct mapped_device *pool_md, pool->pmd = pmd; pool->sectors_per_block = block_size; - pool->block_shift = ffs(block_size) - 1; - pool->offset_mask = block_size - 1; + if (block_size & (block_size - 1)) + pool->sectors_per_block_shift = -1; + else + pool->sectors_per_block_shift = __ffs(block_size); pool->low_water_blocks = 0; pool_features_init(&pool->pf); pool->prison = prison_create(PRISON_CELLS); @@ -1822,25 +2045,29 @@ static void __pool_dec(struct pool *pool) static struct pool *__pool_find(struct mapped_device *pool_md, struct block_device *metadata_dev, - unsigned long block_size, char **error, - int *created) + unsigned long block_size, int read_only, + char **error, int *created) { struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev); if (pool) { - if (pool->pool_md != pool_md) + if (pool->pool_md != pool_md) { + *error = "metadata device already in use by a pool"; return ERR_PTR(-EBUSY); + } __pool_inc(pool); } else { pool = __pool_table_lookup(pool_md); if (pool) { - if (pool->md_dev != metadata_dev) + if (pool->md_dev != metadata_dev) { + *error = "different pool cannot replace a pool"; return ERR_PTR(-EINVAL); + } __pool_inc(pool); } else { - pool = pool_create(pool_md, metadata_dev, block_size, error); + pool = pool_create(pool_md, metadata_dev, block_size, read_only, error); *created = 1; } } @@ -1891,19 +2118,23 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf, arg_name = dm_shift_arg(as); argc--; - if (!strcasecmp(arg_name, "skip_block_zeroing")) { + if (!strcasecmp(arg_name, "skip_block_zeroing")) pf->zero_new_blocks = 0; - continue; - } else if (!strcasecmp(arg_name, "ignore_discard")) { + + else if (!strcasecmp(arg_name, "ignore_discard")) pf->discard_enabled = 0; - continue; - } else if (!strcasecmp(arg_name, "no_discard_passdown")) { + + else if (!strcasecmp(arg_name, "no_discard_passdown")) pf->discard_passdown = 0; - continue; - } - ti->error = "Unrecognised pool feature requested"; - r = -EINVAL; + else if (!strcasecmp(arg_name, "read_only")) + pf->mode = PM_READ_ONLY; + + else { + ti->error = "Unrecognised pool feature requested"; + r = -EINVAL; + break; + } } return r; @@ -1967,7 +2198,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) if (kstrtoul(argv[2], 10, &block_size) || !block_size || block_size < DATA_DEV_BLOCK_SIZE_MIN_SECTORS || block_size > DATA_DEV_BLOCK_SIZE_MAX_SECTORS || - !is_power_of_2(block_size)) { + block_size & (DATA_DEV_BLOCK_SIZE_MIN_SECTORS - 1)) { ti->error = "Invalid block size"; r = -EINVAL; goto out; @@ -1996,7 +2227,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) } pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev, - block_size, &ti->error, &pool_created); + block_size, pf.mode == PM_READ_ONLY, &ti->error, &pool_created); if (IS_ERR(pool)) { r = PTR_ERR(pool); goto out_free_pt; @@ -2014,6 +2245,15 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) goto out_flags_changed; } + /* + * The block layer requires discard_granularity to be a power of 2. + */ + if (pf.discard_enabled && !is_power_of_2(block_size)) { + ti->error = "Discard support must be disabled when the block size is not a power of 2"; + r = -EINVAL; + goto out_flags_changed; + } + pt->pool = pool; pt->ti = ti; pt->metadata_dev = metadata_dev; @@ -2033,7 +2273,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) * stacking of discard limits (this keeps the pool and * thin devices' discard limits consistent). */ - ti->discards_supported = 1; + ti->discards_supported = true; } ti->private = pt; @@ -2093,7 +2333,8 @@ static int pool_preresume(struct dm_target *ti) int r; struct pool_c *pt = ti->private; struct pool *pool = pt->pool; - dm_block_t data_size, sb_data_size; + sector_t data_size = ti->len; + dm_block_t sb_data_size; /* * Take control of the pool object. @@ -2102,7 +2343,8 @@ static int pool_preresume(struct dm_target *ti) if (r) return r; - data_size = ti->len >> pool->block_shift; + (void) sector_div(data_size, pool->sectors_per_block); + r = dm_pool_get_data_dev_size(pool->pmd, &sb_data_size); if (r) { DMERR("failed to retrieve data device size"); @@ -2111,22 +2353,19 @@ static int pool_preresume(struct dm_target *ti) if (data_size < sb_data_size) { DMERR("pool target too small, is %llu blocks (expected %llu)", - data_size, sb_data_size); + (unsigned long long)data_size, sb_data_size); return -EINVAL; } else if (data_size > sb_data_size) { r = dm_pool_resize_data_dev(pool->pmd, data_size); if (r) { DMERR("failed to resize data device"); + /* FIXME Stricter than necessary: Rollback transaction instead here */ + set_pool_mode(pool, PM_READ_ONLY); return r; } - r = dm_pool_commit_metadata(pool->pmd); - if (r) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - return r; - } + (void) commit_or_fallback(pool); } return 0; @@ -2149,19 +2388,12 @@ static void pool_resume(struct dm_target *ti) static void pool_postsuspend(struct dm_target *ti) { - int r; struct pool_c *pt = ti->private; struct pool *pool = pt->pool; cancel_delayed_work(&pool->waker); flush_workqueue(pool->wq); - - r = dm_pool_commit_metadata(pool->pmd); - if (r < 0) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - /* FIXME: invalidate device? error the next FUA or FLUSH bio ?*/ - } + (void) commit_or_fallback(pool); } static int check_arg_count(unsigned argc, unsigned args_required) @@ -2295,12 +2527,7 @@ static int process_reserve_metadata_snap_mesg(unsigned argc, char **argv, struct if (r) return r; - r = dm_pool_commit_metadata(pool->pmd); - if (r) { - DMERR("%s: dm_pool_commit_metadata() failed, error = %d", - __func__, r); - return r; - } + (void) commit_or_fallback(pool); r = dm_pool_reserve_metadata_snap(pool->pmd); if (r) @@ -2361,25 +2588,41 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) else DMWARN("Unrecognised thin pool target message received: %s", argv[0]); - if (!r) { - r = dm_pool_commit_metadata(pool->pmd); - if (r) - DMERR("%s message: dm_pool_commit_metadata() failed, error = %d", - argv[0], r); - } + if (!r) + (void) commit_or_fallback(pool); return r; } +static void emit_flags(struct pool_features *pf, char *result, + unsigned sz, unsigned maxlen) +{ + unsigned count = !pf->zero_new_blocks + !pf->discard_enabled + + !pf->discard_passdown + (pf->mode == PM_READ_ONLY); + DMEMIT("%u ", count); + + if (!pf->zero_new_blocks) + DMEMIT("skip_block_zeroing "); + + if (!pf->discard_enabled) + DMEMIT("ignore_discard "); + + if (!pf->discard_passdown) + DMEMIT("no_discard_passdown "); + + if (pf->mode == PM_READ_ONLY) + DMEMIT("read_only "); +} + /* * Status line is: * <transaction id> <used metadata sectors>/<total metadata sectors> * <used data sectors>/<total data sectors> <held metadata root> */ static int pool_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) + unsigned status_flags, char *result, unsigned maxlen) { - int r, count; + int r; unsigned sz = 0; uint64_t transaction_id; dm_block_t nr_free_blocks_data; @@ -2394,6 +2637,15 @@ static int pool_status(struct dm_target *ti, status_type_t type, switch (type) { case STATUSTYPE_INFO: + if (get_pool_mode(pool) == PM_FAIL) { + DMEMIT("Fail"); + break; + } + + /* Commit to ensure statistics aren't out-of-date */ + if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti)) + (void) commit_or_fallback(pool); + r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id); if (r) @@ -2429,9 +2681,19 @@ static int pool_status(struct dm_target *ti, status_type_t type, (unsigned long long)nr_blocks_data); if (held_root) - DMEMIT("%llu", held_root); + DMEMIT("%llu ", held_root); + else + DMEMIT("- "); + + if (pool->pf.mode == PM_READ_ONLY) + DMEMIT("ro "); + else + DMEMIT("rw "); + + if (pool->pf.discard_enabled && pool->pf.discard_passdown) + DMEMIT("discard_passdown"); else - DMEMIT("-"); + DMEMIT("no_discard_passdown"); break; @@ -2441,20 +2703,7 @@ static int pool_status(struct dm_target *ti, status_type_t type, format_dev_t(buf2, pt->data_dev->bdev->bd_dev), (unsigned long)pool->sectors_per_block, (unsigned long long)pt->low_water_blocks); - - count = !pool->pf.zero_new_blocks + !pool->pf.discard_enabled + - !pt->pf.discard_passdown; - DMEMIT("%u ", count); - - if (!pool->pf.zero_new_blocks) - DMEMIT("skip_block_zeroing "); - - if (!pool->pf.discard_enabled) - DMEMIT("ignore_discard "); - - if (!pt->pf.discard_passdown) - DMEMIT("no_discard_passdown "); - + emit_flags(&pt->pf, result, sz, maxlen); break; } @@ -2492,7 +2741,8 @@ static void set_discard_limits(struct pool *pool, struct queue_limits *limits) /* * This is just a hint, and not enforced. We have to cope with - * bios that overlap 2 blocks. + * bios that cover a block partially. A discard that spans a block + * boundary is not sent to this target. */ limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; limits->discard_zeroes_data = pool->pf.zero_new_blocks; @@ -2513,7 +2763,7 @@ static struct target_type pool_target = { .name = "thin-pool", .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | DM_TARGET_IMMUTABLE, - .version = {1, 2, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = pool_ctr, .dtr = pool_dtr, @@ -2618,20 +2868,31 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) } __pool_inc(tc->pool); + if (get_pool_mode(tc->pool) == PM_FAIL) { + ti->error = "Couldn't open thin device, Pool is in fail mode"; + goto bad_thin_open; + } + r = dm_pool_open_thin_device(tc->pool->pmd, tc->dev_id, &tc->td); if (r) { ti->error = "Couldn't open thin internal device"; goto bad_thin_open; } - ti->split_io = tc->pool->sectors_per_block; + r = dm_set_target_max_io_len(ti, tc->pool->sectors_per_block); + if (r) + goto bad_thin_open; + ti->num_flush_requests = 1; + ti->flush_supported = true; /* In case the pool supports discards, pass them on. */ if (tc->pool->pf.discard_enabled) { - ti->discards_supported = 1; + ti->discards_supported = true; ti->num_discard_requests = 1; - ti->discard_zeroes_data_unsupported = 1; + ti->discard_zeroes_data_unsupported = true; + /* Discard requests must be split on a block boundary */ + ti->split_discard_requests = true; } dm_put(pool_md); @@ -2712,7 +2973,7 @@ static void thin_postsuspend(struct dm_target *ti) * <nr mapped sectors> <highest mapped sector> */ static int thin_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) + unsigned status_flags, char *result, unsigned maxlen) { int r; ssize_t sz = 0; @@ -2720,6 +2981,11 @@ static int thin_status(struct dm_target *ti, status_type_t type, char buf[BDEVNAME_SIZE]; struct thin_c *tc = ti->private; + if (get_pool_mode(tc->pool) == PM_FAIL) { + DMEMIT("Fail"); + return 0; + } + if (!tc->td) DMEMIT("-"); else { @@ -2757,19 +3023,21 @@ static int thin_status(struct dm_target *ti, status_type_t type, static int thin_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) { - dm_block_t blocks; + sector_t blocks; struct thin_c *tc = ti->private; + struct pool *pool = tc->pool; /* * We can't call dm_pool_get_data_dev_size() since that blocks. So * we follow a more convoluted path through to the pool's target. */ - if (!tc->pool->ti) + if (!pool->ti) return 0; /* nothing is bound */ - blocks = tc->pool->ti->len >> tc->pool->block_shift; + blocks = pool->ti->len; + (void) sector_div(blocks, pool->sectors_per_block); if (blocks) - return fn(ti, tc->pool_dev, 0, tc->pool->sectors_per_block * blocks, data); + return fn(ti, tc->pool_dev, 0, pool->sectors_per_block * blocks, data); return 0; } @@ -2786,7 +3054,7 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) static struct target_type thin_target = { .name = "thin", - .version = {1, 1, 0}, + .version = {1, 3, 0}, .module = THIS_MODULE, .ctr = thin_ctr, .dtr = thin_dtr, diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index fa365d39b61..254d19268ad 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -515,7 +515,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio, * Status: V (valid) or C (corruption found) */ static int verity_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) + unsigned status_flags, char *result, unsigned maxlen) { struct dm_verity *v = ti->private; unsigned sz = 0; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e24143cc204..4e09b6ff5b4 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -968,22 +968,41 @@ static sector_t max_io_len_target_boundary(sector_t sector, struct dm_target *ti static sector_t max_io_len(sector_t sector, struct dm_target *ti) { sector_t len = max_io_len_target_boundary(sector, ti); + sector_t offset, max_len; /* - * Does the target need to split even further ? + * Does the target need to split even further? */ - if (ti->split_io) { - sector_t boundary; - sector_t offset = dm_target_offset(ti, sector); - boundary = ((offset + ti->split_io) & ~(ti->split_io - 1)) - - offset; - if (len > boundary) - len = boundary; + if (ti->max_io_len) { + offset = dm_target_offset(ti, sector); + if (unlikely(ti->max_io_len & (ti->max_io_len - 1))) + max_len = sector_div(offset, ti->max_io_len); + else + max_len = offset & (ti->max_io_len - 1); + max_len = ti->max_io_len - max_len; + + if (len > max_len) + len = max_len; } return len; } +int dm_set_target_max_io_len(struct dm_target *ti, sector_t len) +{ + if (len > UINT_MAX) { + DMERR("Specified maximum size of target IO (%llu) exceeds limit (%u)", + (unsigned long long)len, UINT_MAX); + ti->error = "Maximum size of target IO is too large"; + return -EINVAL; + } + + ti->max_io_len = (uint32_t) len; + + return 0; +} +EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); + static void __map_bio(struct dm_target *ti, struct bio *clone, struct dm_target_io *tio) { @@ -1196,7 +1215,10 @@ static int __clone_and_map_discard(struct clone_info *ci) if (!ti->num_discard_requests) return -EOPNOTSUPP; - len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); + if (!ti->split_discard_requests) + len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); + else + len = min(ci->sector_count, max_io_len(ci->sector, ti)); __issue_target_requests(ci, ti, ti->num_discard_requests, len); diff --git a/drivers/md/dm.h b/drivers/md/dm.h index b7dacd59d8d..52eef493d26 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -23,6 +23,11 @@ #define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) /* + * Status feature flags + */ +#define DM_STATUS_NOFLUSH_FLAG (1 << 0) + +/* * Type of table and mapped_device's mempool */ #define DM_TYPE_NONE 0 diff --git a/drivers/md/persistent-data/Makefile b/drivers/md/persistent-data/Makefile index cfa95f66223..d8e7cb767c1 100644 --- a/drivers/md/persistent-data/Makefile +++ b/drivers/md/persistent-data/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_DM_PERSISTENT_DATA) += dm-persistent-data.o dm-persistent-data-objs := \ dm-block-manager.o \ - dm-space-map-checker.o \ dm-space-map-common.o \ dm-space-map-disk.o \ dm-space-map-metadata.o \ diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index 0317ecdc6e5..5ba277768d9 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c @@ -325,11 +325,6 @@ static struct dm_buffer *to_buffer(struct dm_block *b) return (struct dm_buffer *) b; } -static struct dm_bufio_client *to_bufio(struct dm_block_manager *bm) -{ - return (struct dm_bufio_client *) bm; -} - dm_block_t dm_block_location(struct dm_block *b) { return dm_bufio_get_block_number(to_buffer(b)); @@ -367,34 +362,60 @@ static void dm_block_manager_write_callback(struct dm_buffer *buf) /*---------------------------------------------------------------- * Public interface *--------------------------------------------------------------*/ +struct dm_block_manager { + struct dm_bufio_client *bufio; + bool read_only:1; +}; + struct dm_block_manager *dm_block_manager_create(struct block_device *bdev, unsigned block_size, unsigned cache_size, unsigned max_held_per_thread) { - return (struct dm_block_manager *) - dm_bufio_client_create(bdev, block_size, max_held_per_thread, - sizeof(struct buffer_aux), - dm_block_manager_alloc_callback, - dm_block_manager_write_callback); + int r; + struct dm_block_manager *bm; + + bm = kmalloc(sizeof(*bm), GFP_KERNEL); + if (!bm) { + r = -ENOMEM; + goto bad; + } + + bm->bufio = dm_bufio_client_create(bdev, block_size, max_held_per_thread, + sizeof(struct buffer_aux), + dm_block_manager_alloc_callback, + dm_block_manager_write_callback); + if (IS_ERR(bm->bufio)) { + r = PTR_ERR(bm->bufio); + kfree(bm); + goto bad; + } + + bm->read_only = false; + + return bm; + +bad: + return ERR_PTR(r); } EXPORT_SYMBOL_GPL(dm_block_manager_create); void dm_block_manager_destroy(struct dm_block_manager *bm) { - return dm_bufio_client_destroy(to_bufio(bm)); + dm_bufio_client_destroy(bm->bufio); + kfree(bm); } EXPORT_SYMBOL_GPL(dm_block_manager_destroy); unsigned dm_bm_block_size(struct dm_block_manager *bm) { - return dm_bufio_get_block_size(to_bufio(bm)); + return dm_bufio_get_block_size(bm->bufio); } EXPORT_SYMBOL_GPL(dm_bm_block_size); dm_block_t dm_bm_nr_blocks(struct dm_block_manager *bm) { - return dm_bufio_get_device_size(to_bufio(bm)); + return dm_bufio_get_device_size(bm->bufio); } static int dm_bm_validate_buffer(struct dm_block_manager *bm, @@ -406,7 +427,7 @@ static int dm_bm_validate_buffer(struct dm_block_manager *bm, int r; if (!v) return 0; - r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(to_bufio(bm))); + r = v->check(v, (struct dm_block *) buf, dm_bufio_get_block_size(bm->bufio)); if (unlikely(r)) return r; aux->validator = v; @@ -430,7 +451,7 @@ int dm_bm_read_lock(struct dm_block_manager *bm, dm_block_t b, void *p; int r; - p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result); + p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); if (unlikely(IS_ERR(p))) return PTR_ERR(p); @@ -463,7 +484,10 @@ int dm_bm_write_lock(struct dm_block_manager *bm, void *p; int r; - p = dm_bufio_read(to_bufio(bm), b, (struct dm_buffer **) result); + if (bm->read_only) + return -EPERM; + + p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result); if (unlikely(IS_ERR(p))) return PTR_ERR(p); @@ -496,7 +520,7 @@ int dm_bm_read_try_lock(struct dm_block_manager *bm, void *p; int r; - p = dm_bufio_get(to_bufio(bm), b, (struct dm_buffer **) result); + p = dm_bufio_get(bm->bufio, b, (struct dm_buffer **) result); if (unlikely(IS_ERR(p))) return PTR_ERR(p); if (unlikely(!p)) @@ -529,7 +553,10 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, struct buffer_aux *aux; void *p; - p = dm_bufio_new(to_bufio(bm), b, (struct dm_buffer **) result); + if (bm->read_only) + return -EPERM; + + p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result); if (unlikely(IS_ERR(p))) return PTR_ERR(p); @@ -547,6 +574,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, return 0; } +EXPORT_SYMBOL_GPL(dm_bm_write_lock_zero); int dm_bm_unlock(struct dm_block *b) { @@ -565,45 +593,30 @@ int dm_bm_unlock(struct dm_block *b) } EXPORT_SYMBOL_GPL(dm_bm_unlock); -int dm_bm_unlock_move(struct dm_block *b, dm_block_t n) -{ - struct buffer_aux *aux; - - aux = dm_bufio_get_aux_data(to_buffer(b)); - - if (aux->write_locked) { - dm_bufio_mark_buffer_dirty(to_buffer(b)); - bl_up_write(&aux->lock); - } else - bl_up_read(&aux->lock); - - dm_bufio_release_move(to_buffer(b), n); - return 0; -} - int dm_bm_flush_and_unlock(struct dm_block_manager *bm, struct dm_block *superblock) { int r; - r = dm_bufio_write_dirty_buffers(to_bufio(bm)); - if (unlikely(r)) - return r; - r = dm_bufio_issue_flush(to_bufio(bm)); - if (unlikely(r)) + if (bm->read_only) + return -EPERM; + + r = dm_bufio_write_dirty_buffers(bm->bufio); + if (unlikely(r)) { + dm_bm_unlock(superblock); return r; + } dm_bm_unlock(superblock); - r = dm_bufio_write_dirty_buffers(to_bufio(bm)); - if (unlikely(r)) - return r; - r = dm_bufio_issue_flush(to_bufio(bm)); - if (unlikely(r)) - return r; + return dm_bufio_write_dirty_buffers(bm->bufio); +} - return 0; +void dm_bm_set_read_only(struct dm_block_manager *bm) +{ + bm->read_only = true; } +EXPORT_SYMBOL_GPL(dm_bm_set_read_only); u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) { diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h index 924833d2dfa..be5bff61be2 100644 --- a/drivers/md/persistent-data/dm-block-manager.h +++ b/drivers/md/persistent-data/dm-block-manager.h @@ -97,14 +97,6 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm, dm_block_t b, int dm_bm_unlock(struct dm_block *b); /* - * An optimisation; we often want to copy a block's contents to a new - * block. eg, as part of the shadowing operation. It's far better for - * bufio to do this move behind the scenes than hold 2 locks and memcpy the - * data. - */ -int dm_bm_unlock_move(struct dm_block *b, dm_block_t n); - -/* * It's a common idiom to have a superblock that should be committed last. * * @superblock should be write-locked on entry. It will be unlocked during @@ -116,6 +108,19 @@ int dm_bm_unlock_move(struct dm_block *b, dm_block_t n); int dm_bm_flush_and_unlock(struct dm_block_manager *bm, struct dm_block *superblock); +/* + * Switches the bm to a read only mode. Once read-only mode + * has been entered the following functions will return -EPERM. + * + * dm_bm_write_lock + * dm_bm_write_lock_zero + * dm_bm_flush_and_unlock + * + * Additionally you should not use dm_bm_unlock_move, however no error will + * be returned if you do. + */ +void dm_bm_set_read_only(struct dm_block_manager *bm); + u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); /*----------------------------------------------------------------*/ diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c deleted file mode 100644 index fc90c11620a..00000000000 --- a/drivers/md/persistent-data/dm-space-map-checker.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (C) 2011 Red Hat, Inc. - * - * This file is released under the GPL. - */ - -#include "dm-space-map-checker.h" - -#include <linux/device-mapper.h> -#include <linux/export.h> -#include <linux/vmalloc.h> - -#ifdef CONFIG_DM_DEBUG_SPACE_MAPS - -#define DM_MSG_PREFIX "space map checker" - -/*----------------------------------------------------------------*/ - -struct count_array { - dm_block_t nr; - dm_block_t nr_free; - - uint32_t *counts; -}; - -static int ca_get_count(struct count_array *ca, dm_block_t b, uint32_t *count) -{ - if (b >= ca->nr) - return -EINVAL; - - *count = ca->counts[b]; - return 0; -} - -static int ca_count_more_than_one(struct count_array *ca, dm_block_t b, int *r) -{ - if (b >= ca->nr) - return -EINVAL; - - *r = ca->counts[b] > 1; - return 0; -} - -static int ca_set_count(struct count_array *ca, dm_block_t b, uint32_t count) -{ - uint32_t old_count; - - if (b >= ca->nr) - return -EINVAL; - - old_count = ca->counts[b]; - - if (!count && old_count) - ca->nr_free++; - - else if (count && !old_count) - ca->nr_free--; - - ca->counts[b] = count; - return 0; -} - -static int ca_inc_block(struct count_array *ca, dm_block_t b) -{ - if (b >= ca->nr) - return -EINVAL; - - ca_set_count(ca, b, ca->counts[b] + 1); - return 0; -} - -static int ca_dec_block(struct count_array *ca, dm_block_t b) -{ - if (b >= ca->nr) - return -EINVAL; - - BUG_ON(ca->counts[b] == 0); - ca_set_count(ca, b, ca->counts[b] - 1); - return 0; -} - -static int ca_create(struct count_array *ca, struct dm_space_map *sm) -{ - int r; - dm_block_t nr_blocks; - - r = dm_sm_get_nr_blocks(sm, &nr_blocks); - if (r) - return r; - - ca->nr = nr_blocks; - ca->nr_free = nr_blocks; - - if (!nr_blocks) - ca->counts = NULL; - else { - ca->counts = vzalloc(sizeof(*ca->counts) * nr_blocks); - if (!ca->counts) - return -ENOMEM; - } - - return 0; -} - -static void ca_destroy(struct count_array *ca) -{ - vfree(ca->counts); -} - -static int ca_load(struct count_array *ca, struct dm_space_map *sm) -{ - int r; - uint32_t count; - dm_block_t nr_blocks, i; - - r = dm_sm_get_nr_blocks(sm, &nr_blocks); - if (r) - return r; - - BUG_ON(ca->nr != nr_blocks); - - DMWARN("Loading debug space map from disk. This may take some time"); - for (i = 0; i < nr_blocks; i++) { - r = dm_sm_get_count(sm, i, &count); - if (r) { - DMERR("load failed"); - return r; - } - - ca_set_count(ca, i, count); - } - DMWARN("Load complete"); - - return 0; -} - -static int ca_extend(struct count_array *ca, dm_block_t extra_blocks) -{ - dm_block_t nr_blocks = ca->nr + extra_blocks; - uint32_t *counts = vzalloc(sizeof(*counts) * nr_blocks); - if (!counts) - return -ENOMEM; - - if (ca->counts) { - memcpy(counts, ca->counts, sizeof(*counts) * ca->nr); - ca_destroy(ca); - } - ca->nr = nr_blocks; - ca->nr_free += extra_blocks; - ca->counts = counts; - return 0; -} - -static int ca_commit(struct count_array *old, struct count_array *new) -{ - if (old->nr != new->nr) { - BUG_ON(old->nr > new->nr); - ca_extend(old, new->nr - old->nr); - } - - BUG_ON(old->nr != new->nr); - old->nr_free = new->nr_free; - memcpy(old->counts, new->counts, sizeof(*old->counts) * old->nr); - return 0; -} - -/*----------------------------------------------------------------*/ - -struct sm_checker { - struct dm_space_map sm; - - struct count_array old_counts; - struct count_array counts; - - struct dm_space_map *real_sm; -}; - -static void sm_checker_destroy(struct dm_space_map *sm) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - - dm_sm_destroy(smc->real_sm); - ca_destroy(&smc->old_counts); - ca_destroy(&smc->counts); - kfree(smc); -} - -static int sm_checker_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_get_nr_blocks(smc->real_sm, count); - if (!r) - BUG_ON(smc->old_counts.nr != *count); - return r; -} - -static int sm_checker_get_nr_free(struct dm_space_map *sm, dm_block_t *count) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_get_nr_free(smc->real_sm, count); - if (!r) { - /* - * Slow, but we know it's correct. - */ - dm_block_t b, n = 0; - for (b = 0; b < smc->old_counts.nr; b++) - if (smc->old_counts.counts[b] == 0 && - smc->counts.counts[b] == 0) - n++; - - if (n != *count) - DMERR("free block counts differ, checker %u, sm-disk:%u", - (unsigned) n, (unsigned) *count); - } - return r; -} - -static int sm_checker_new_block(struct dm_space_map *sm, dm_block_t *b) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_new_block(smc->real_sm, b); - - if (!r) { - BUG_ON(*b >= smc->old_counts.nr); - BUG_ON(smc->old_counts.counts[*b] != 0); - BUG_ON(*b >= smc->counts.nr); - BUG_ON(smc->counts.counts[*b] != 0); - ca_set_count(&smc->counts, *b, 1); - } - - return r; -} - -static int sm_checker_inc_block(struct dm_space_map *sm, dm_block_t b) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_inc_block(smc->real_sm, b); - int r2 = ca_inc_block(&smc->counts, b); - BUG_ON(r != r2); - return r; -} - -static int sm_checker_dec_block(struct dm_space_map *sm, dm_block_t b) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_dec_block(smc->real_sm, b); - int r2 = ca_dec_block(&smc->counts, b); - BUG_ON(r != r2); - return r; -} - -static int sm_checker_get_count(struct dm_space_map *sm, dm_block_t b, uint32_t *result) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - uint32_t result2 = 0; - int r = dm_sm_get_count(smc->real_sm, b, result); - int r2 = ca_get_count(&smc->counts, b, &result2); - - BUG_ON(r != r2); - if (!r) - BUG_ON(*result != result2); - return r; -} - -static int sm_checker_count_more_than_one(struct dm_space_map *sm, dm_block_t b, int *result) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int result2 = 0; - int r = dm_sm_count_is_more_than_one(smc->real_sm, b, result); - int r2 = ca_count_more_than_one(&smc->counts, b, &result2); - - BUG_ON(r != r2); - if (!r) - BUG_ON(!(*result) && result2); - return r; -} - -static int sm_checker_set_count(struct dm_space_map *sm, dm_block_t b, uint32_t count) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - uint32_t old_rc; - int r = dm_sm_set_count(smc->real_sm, b, count); - int r2; - - BUG_ON(b >= smc->counts.nr); - old_rc = smc->counts.counts[b]; - r2 = ca_set_count(&smc->counts, b, count); - BUG_ON(r != r2); - - return r; -} - -static int sm_checker_commit(struct dm_space_map *sm) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r; - - r = dm_sm_commit(smc->real_sm); - if (r) - return r; - - r = ca_commit(&smc->old_counts, &smc->counts); - if (r) - return r; - - return 0; -} - -static int sm_checker_extend(struct dm_space_map *sm, dm_block_t extra_blocks) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - int r = dm_sm_extend(smc->real_sm, extra_blocks); - if (r) - return r; - - return ca_extend(&smc->counts, extra_blocks); -} - -static int sm_checker_root_size(struct dm_space_map *sm, size_t *result) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - return dm_sm_root_size(smc->real_sm, result); -} - -static int sm_checker_copy_root(struct dm_space_map *sm, void *copy_to_here_le, size_t len) -{ - struct sm_checker *smc = container_of(sm, struct sm_checker, sm); - return dm_sm_copy_root(smc->real_sm, copy_to_here_le, len); -} - -/*----------------------------------------------------------------*/ - -static struct dm_space_map ops_ = { - .destroy = sm_checker_destroy, - .get_nr_blocks = sm_checker_get_nr_blocks, - .get_nr_free = sm_checker_get_nr_free, - .inc_block = sm_checker_inc_block, - .dec_block = sm_checker_dec_block, - .new_block = sm_checker_new_block, - .get_count = sm_checker_get_count, - .count_is_more_than_one = sm_checker_count_more_than_one, - .set_count = sm_checker_set_count, - .commit = sm_checker_commit, - .extend = sm_checker_extend, - .root_size = sm_checker_root_size, - .copy_root = sm_checker_copy_root -}; - -struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) -{ - int r; - struct sm_checker *smc; - - if (IS_ERR_OR_NULL(sm)) - return ERR_PTR(-EINVAL); - - smc = kmalloc(sizeof(*smc), GFP_KERNEL); - if (!smc) - return ERR_PTR(-ENOMEM); - - memcpy(&smc->sm, &ops_, sizeof(smc->sm)); - r = ca_create(&smc->old_counts, sm); - if (r) { - kfree(smc); - return ERR_PTR(r); - } - - r = ca_create(&smc->counts, sm); - if (r) { - ca_destroy(&smc->old_counts); - kfree(smc); - return ERR_PTR(r); - } - - smc->real_sm = sm; - - r = ca_load(&smc->counts, sm); - if (r) { - ca_destroy(&smc->counts); - ca_destroy(&smc->old_counts); - kfree(smc); - return ERR_PTR(r); - } - - r = ca_commit(&smc->old_counts, &smc->counts); - if (r) { - ca_destroy(&smc->counts); - ca_destroy(&smc->old_counts); - kfree(smc); - return ERR_PTR(r); - } - - return &smc->sm; -} -EXPORT_SYMBOL_GPL(dm_sm_checker_create); - -struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm) -{ - int r; - struct sm_checker *smc; - - if (IS_ERR_OR_NULL(sm)) - return ERR_PTR(-EINVAL); - - smc = kmalloc(sizeof(*smc), GFP_KERNEL); - if (!smc) - return ERR_PTR(-ENOMEM); - - memcpy(&smc->sm, &ops_, sizeof(smc->sm)); - r = ca_create(&smc->old_counts, sm); - if (r) { - kfree(smc); - return ERR_PTR(r); - } - - r = ca_create(&smc->counts, sm); - if (r) { - ca_destroy(&smc->old_counts); - kfree(smc); - return ERR_PTR(r); - } - - smc->real_sm = sm; - return &smc->sm; -} -EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh); - -/*----------------------------------------------------------------*/ - -#else - -struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) -{ - return sm; -} -EXPORT_SYMBOL_GPL(dm_sm_checker_create); - -struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm) -{ - return sm; -} -EXPORT_SYMBOL_GPL(dm_sm_checker_create_fresh); - -/*----------------------------------------------------------------*/ - -#endif diff --git a/drivers/md/persistent-data/dm-space-map-checker.h b/drivers/md/persistent-data/dm-space-map-checker.h deleted file mode 100644 index 444dccf6688..00000000000 --- a/drivers/md/persistent-data/dm-space-map-checker.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2011 Red Hat, Inc. - * - * This file is released under the GPL. - */ - -#ifndef SNAPSHOTS_SPACE_MAP_CHECKER_H -#define SNAPSHOTS_SPACE_MAP_CHECKER_H - -#include "dm-space-map.h" - -/*----------------------------------------------------------------*/ - -/* - * This space map wraps a real on-disk space map, and verifies all of its - * operations. It uses a lot of memory, so only use if you have a specific - * problem that you're debugging. - * - * Ownership of @sm passes. - */ -struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm); -struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm); - -/*----------------------------------------------------------------*/ - -#endif diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index ff3beed6ad2..d77602d63c8 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c @@ -224,6 +224,7 @@ static int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm) ll->nr_blocks = 0; ll->bitmap_root = 0; ll->ref_count_root = 0; + ll->bitmap_index_changed = false; return 0; } @@ -476,7 +477,15 @@ int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) int sm_ll_commit(struct ll_disk *ll) { - return ll->commit(ll); + int r = 0; + + if (ll->bitmap_index_changed) { + r = ll->commit(ll); + if (!r) + ll->bitmap_index_changed = false; + } + + return r; } /*----------------------------------------------------------------*/ @@ -491,6 +500,7 @@ static int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index, static int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie) { + ll->bitmap_index_changed = true; memcpy(ll->mi_le.index + index, ie, sizeof(*ie)); return 0; } diff --git a/drivers/md/persistent-data/dm-space-map-common.h b/drivers/md/persistent-data/dm-space-map-common.h index 8f220821a9a..b3078d5eda0 100644 --- a/drivers/md/persistent-data/dm-space-map-common.h +++ b/drivers/md/persistent-data/dm-space-map-common.h @@ -78,6 +78,7 @@ struct ll_disk { open_index_fn open_index; max_index_entries_fn max_entries; commit_fn commit; + bool bitmap_index_changed:1; }; struct disk_sm_root { diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index 3d0ed533288..f6d29e614ab 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -4,7 +4,6 @@ * This file is released under the GPL. */ -#include "dm-space-map-checker.h" #include "dm-space-map-common.h" #include "dm-space-map-disk.h" #include "dm-space-map.h" @@ -252,9 +251,8 @@ static struct dm_space_map ops = { .copy_root = sm_disk_copy_root }; -static struct dm_space_map *dm_sm_disk_create_real( - struct dm_transaction_manager *tm, - dm_block_t nr_blocks) +struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm, + dm_block_t nr_blocks) { int r; struct sm_disk *smd; @@ -285,27 +283,10 @@ bad: kfree(smd); return ERR_PTR(r); } - -struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm, - dm_block_t nr_blocks) -{ - struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks); - struct dm_space_map *smc; - - if (IS_ERR_OR_NULL(sm)) - return sm; - - smc = dm_sm_checker_create_fresh(sm); - if (IS_ERR(smc)) - dm_sm_destroy(sm); - - return smc; -} EXPORT_SYMBOL_GPL(dm_sm_disk_create); -static struct dm_space_map *dm_sm_disk_open_real( - struct dm_transaction_manager *tm, - void *root_le, size_t len) +struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm, + void *root_le, size_t len) { int r; struct sm_disk *smd; @@ -332,13 +313,6 @@ bad: kfree(smd); return ERR_PTR(r); } - -struct dm_space_map *dm_sm_disk_open(struct dm_transaction_manager *tm, - void *root_le, size_t len) -{ - return dm_sm_checker_create( - dm_sm_disk_open_real(tm, root_le, len)); -} EXPORT_SYMBOL_GPL(dm_sm_disk_open); /*----------------------------------------------------------------*/ diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index e5604b32d91..d247a35da3c 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c @@ -5,7 +5,6 @@ */ #include "dm-transaction-manager.h" #include "dm-space-map.h" -#include "dm-space-map-checker.h" #include "dm-space-map-disk.h" #include "dm-space-map-metadata.h" #include "dm-persistent-data-internal.h" @@ -220,13 +219,24 @@ static int __shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, if (r < 0) return r; - r = dm_bm_unlock_move(orig_block, new); - if (r < 0) { + /* + * It would be tempting to use dm_bm_unlock_move here, but some + * code, such as the space maps, keeps using the old data structures + * secure in the knowledge they won't be changed until the next + * transaction. Using unlock_move would force a synchronous read + * since the old block would no longer be in the cache. + */ + r = dm_bm_write_lock_zero(tm->bm, new, v, result); + if (r) { dm_bm_unlock(orig_block); return r; } - return dm_bm_write_lock(tm->bm, new, v, result); + memcpy(dm_block_data(*result), dm_block_data(orig_block), + dm_bm_block_size(tm->bm)); + + dm_bm_unlock(orig_block); + return r; } int dm_tm_shadow_block(struct dm_transaction_manager *tm, dm_block_t orig, @@ -311,98 +321,61 @@ struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm) static int dm_tm_create_internal(struct dm_block_manager *bm, dm_block_t sb_location, - struct dm_block_validator *sb_validator, - size_t root_offset, size_t root_max_len, struct dm_transaction_manager **tm, struct dm_space_map **sm, - struct dm_block **sblock, - int create) + int create, + void *sm_root, size_t sm_len) { int r; - struct dm_space_map *inner; - inner = dm_sm_metadata_init(); - if (IS_ERR(inner)) - return PTR_ERR(inner); + *sm = dm_sm_metadata_init(); + if (IS_ERR(*sm)) + return PTR_ERR(*sm); - *tm = dm_tm_create(bm, inner); + *tm = dm_tm_create(bm, *sm); if (IS_ERR(*tm)) { - dm_sm_destroy(inner); + dm_sm_destroy(*sm); return PTR_ERR(*tm); } if (create) { - r = dm_bm_write_lock_zero(dm_tm_get_bm(*tm), sb_location, - sb_validator, sblock); - if (r < 0) { - DMERR("couldn't lock superblock"); - goto bad1; - } - - r = dm_sm_metadata_create(inner, *tm, dm_bm_nr_blocks(bm), + r = dm_sm_metadata_create(*sm, *tm, dm_bm_nr_blocks(bm), sb_location); if (r) { DMERR("couldn't create metadata space map"); - goto bad2; - } - - *sm = dm_sm_checker_create(inner); - if (IS_ERR(*sm)) { - r = PTR_ERR(*sm); - goto bad2; + goto bad; } } else { - r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location, - sb_validator, sblock); - if (r < 0) { - DMERR("couldn't lock superblock"); - goto bad1; - } - - r = dm_sm_metadata_open(inner, *tm, - dm_block_data(*sblock) + root_offset, - root_max_len); + r = dm_sm_metadata_open(*sm, *tm, sm_root, sm_len); if (r) { DMERR("couldn't open metadata space map"); - goto bad2; - } - - *sm = dm_sm_checker_create(inner); - if (IS_ERR(*sm)) { - r = PTR_ERR(*sm); - goto bad2; + goto bad; } } return 0; -bad2: - dm_tm_unlock(*tm, *sblock); -bad1: +bad: dm_tm_destroy(*tm); - dm_sm_destroy(inner); + dm_sm_destroy(*sm); return r; } int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, - struct dm_block_validator *sb_validator, struct dm_transaction_manager **tm, - struct dm_space_map **sm, struct dm_block **sblock) + struct dm_space_map **sm) { - return dm_tm_create_internal(bm, sb_location, sb_validator, - 0, 0, tm, sm, sblock, 1); + return dm_tm_create_internal(bm, sb_location, tm, sm, 1, NULL, 0); } EXPORT_SYMBOL_GPL(dm_tm_create_with_sm); int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, - struct dm_block_validator *sb_validator, - size_t root_offset, size_t root_max_len, + void *sm_root, size_t root_len, struct dm_transaction_manager **tm, - struct dm_space_map **sm, struct dm_block **sblock) + struct dm_space_map **sm) { - return dm_tm_create_internal(bm, sb_location, sb_validator, root_offset, - root_max_len, tm, sm, sblock, 0); + return dm_tm_create_internal(bm, sb_location, tm, sm, 0, sm_root, root_len); } EXPORT_SYMBOL_GPL(dm_tm_open_with_sm); diff --git a/drivers/md/persistent-data/dm-transaction-manager.h b/drivers/md/persistent-data/dm-transaction-manager.h index 6da784871db..b5b139076ca 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.h +++ b/drivers/md/persistent-data/dm-transaction-manager.h @@ -115,16 +115,17 @@ struct dm_block_manager *dm_tm_get_bm(struct dm_transaction_manager *tm); * * Returns a tm that has an open transaction to write the new disk sm. * Caller should store the new sm root and commit. + * + * The superblock location is passed so the metadata space map knows it + * shouldn't be used. */ int dm_tm_create_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, - struct dm_block_validator *sb_validator, struct dm_transaction_manager **tm, - struct dm_space_map **sm, struct dm_block **sblock); + struct dm_space_map **sm); int dm_tm_open_with_sm(struct dm_block_manager *bm, dm_block_t sb_location, - struct dm_block_validator *sb_validator, - size_t root_offset, size_t root_max_len, + void *sm_root, size_t root_len, struct dm_transaction_manager **tm, - struct dm_space_map **sm, struct dm_block **sblock); + struct dm_space_map **sm); #endif /* _LINUX_DM_TRANSACTION_MANAGER_H */ diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c new file mode 100644 index 00000000000..b67a3018b13 --- /dev/null +++ b/drivers/mfd/88pm800.c @@ -0,0 +1,596 @@ +/* + * Base driver for Marvell 88PM800 + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * Joseph(Yossi) Hanin <yhanin@marvell.com> + * Qiao Zhou <zhouqiao@marvell.com> + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mfd/core.h> +#include <linux/mfd/88pm80x.h> +#include <linux/slab.h> + +#define PM800_CHIP_ID (0x00) + +/* Interrupt Registers */ +#define PM800_INT_STATUS1 (0x05) +#define PM800_ONKEY_INT_STS1 (1 << 0) +#define PM800_EXTON_INT_STS1 (1 << 1) +#define PM800_CHG_INT_STS1 (1 << 2) +#define PM800_BAT_INT_STS1 (1 << 3) +#define PM800_RTC_INT_STS1 (1 << 4) +#define PM800_CLASSD_OC_INT_STS1 (1 << 5) + +#define PM800_INT_STATUS2 (0x06) +#define PM800_VBAT_INT_STS2 (1 << 0) +#define PM800_VSYS_INT_STS2 (1 << 1) +#define PM800_VCHG_INT_STS2 (1 << 2) +#define PM800_TINT_INT_STS2 (1 << 3) +#define PM800_GPADC0_INT_STS2 (1 << 4) +#define PM800_TBAT_INT_STS2 (1 << 5) +#define PM800_GPADC2_INT_STS2 (1 << 6) +#define PM800_GPADC3_INT_STS2 (1 << 7) + +#define PM800_INT_STATUS3 (0x07) + +#define PM800_INT_STATUS4 (0x08) +#define PM800_GPIO0_INT_STS4 (1 << 0) +#define PM800_GPIO1_INT_STS4 (1 << 1) +#define PM800_GPIO2_INT_STS4 (1 << 2) +#define PM800_GPIO3_INT_STS4 (1 << 3) +#define PM800_GPIO4_INT_STS4 (1 << 4) + +#define PM800_INT_ENA_1 (0x09) +#define PM800_ONKEY_INT_ENA1 (1 << 0) +#define PM800_EXTON_INT_ENA1 (1 << 1) +#define PM800_CHG_INT_ENA1 (1 << 2) +#define PM800_BAT_INT_ENA1 (1 << 3) +#define PM800_RTC_INT_ENA1 (1 << 4) +#define PM800_CLASSD_OC_INT_ENA1 (1 << 5) + +#define PM800_INT_ENA_2 (0x0A) +#define PM800_VBAT_INT_ENA2 (1 << 0) +#define PM800_VSYS_INT_ENA2 (1 << 1) +#define PM800_VCHG_INT_ENA2 (1 << 2) +#define PM800_TINT_INT_ENA2 (1 << 3) + +#define PM800_INT_ENA_3 (0x0B) +#define PM800_GPADC0_INT_ENA3 (1 << 0) +#define PM800_GPADC1_INT_ENA3 (1 << 1) +#define PM800_GPADC2_INT_ENA3 (1 << 2) +#define PM800_GPADC3_INT_ENA3 (1 << 3) +#define PM800_GPADC4_INT_ENA3 (1 << 4) + +#define PM800_INT_ENA_4 (0x0C) +#define PM800_GPIO0_INT_ENA4 (1 << 0) +#define PM800_GPIO1_INT_ENA4 (1 << 1) +#define PM800_GPIO2_INT_ENA4 (1 << 2) +#define PM800_GPIO3_INT_ENA4 (1 << 3) +#define PM800_GPIO4_INT_ENA4 (1 << 4) + +/* number of INT_ENA & INT_STATUS regs */ +#define PM800_INT_REG_NUM (4) + +/* Interrupt Number in 88PM800 */ +enum { + PM800_IRQ_ONKEY, /*EN1b0 *//*0 */ + PM800_IRQ_EXTON, /*EN1b1 */ + PM800_IRQ_CHG, /*EN1b2 */ + PM800_IRQ_BAT, /*EN1b3 */ + PM800_IRQ_RTC, /*EN1b4 */ + PM800_IRQ_CLASSD, /*EN1b5 *//*5 */ + PM800_IRQ_VBAT, /*EN2b0 */ + PM800_IRQ_VSYS, /*EN2b1 */ + PM800_IRQ_VCHG, /*EN2b2 */ + PM800_IRQ_TINT, /*EN2b3 */ + PM800_IRQ_GPADC0, /*EN3b0 *//*10 */ + PM800_IRQ_GPADC1, /*EN3b1 */ + PM800_IRQ_GPADC2, /*EN3b2 */ + PM800_IRQ_GPADC3, /*EN3b3 */ + PM800_IRQ_GPADC4, /*EN3b4 */ + PM800_IRQ_GPIO0, /*EN4b0 *//*15 */ + PM800_IRQ_GPIO1, /*EN4b1 */ + PM800_IRQ_GPIO2, /*EN4b2 */ + PM800_IRQ_GPIO3, /*EN4b3 */ + PM800_IRQ_GPIO4, /*EN4b4 *//*19 */ + PM800_MAX_IRQ, +}; + +enum { + /* Procida */ + PM800_CHIP_A0 = 0x60, + PM800_CHIP_A1 = 0x61, + PM800_CHIP_B0 = 0x62, + PM800_CHIP_C0 = 0x63, + PM800_CHIP_END = PM800_CHIP_C0, + + /* Make sure to update this to the last stepping */ + PM8XXX_CHIP_END = PM800_CHIP_END +}; + +static const struct i2c_device_id pm80x_id_table[] = { + {"88PM800", CHIP_PM800}, + {} /* NULL terminated */ +}; +MODULE_DEVICE_TABLE(i2c, pm80x_id_table); + +static struct resource rtc_resources[] = { + { + .name = "88pm80x-rtc", + .start = PM800_IRQ_RTC, + .end = PM800_IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell rtc_devs[] = { + { + .name = "88pm80x-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + .id = -1, + }, +}; + +static struct resource onkey_resources[] = { + { + .name = "88pm80x-onkey", + .start = PM800_IRQ_ONKEY, + .end = PM800_IRQ_ONKEY, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell onkey_devs[] = { + { + .name = "88pm80x-onkey", + .num_resources = 1, + .resources = &onkey_resources[0], + .id = -1, + }, +}; + +static const struct regmap_irq pm800_irqs[] = { + /* INT0 */ + [PM800_IRQ_ONKEY] = { + .mask = PM800_ONKEY_INT_ENA1, + }, + [PM800_IRQ_EXTON] = { + .mask = PM800_EXTON_INT_ENA1, + }, + [PM800_IRQ_CHG] = { + .mask = PM800_CHG_INT_ENA1, + }, + [PM800_IRQ_BAT] = { + .mask = PM800_BAT_INT_ENA1, + }, + [PM800_IRQ_RTC] = { + .mask = PM800_RTC_INT_ENA1, + }, + [PM800_IRQ_CLASSD] = { + .mask = PM800_CLASSD_OC_INT_ENA1, + }, + /* INT1 */ + [PM800_IRQ_VBAT] = { + .reg_offset = 1, + .mask = PM800_VBAT_INT_ENA2, + }, + [PM800_IRQ_VSYS] = { + .reg_offset = 1, + .mask = PM800_VSYS_INT_ENA2, + }, + [PM800_IRQ_VCHG] = { + .reg_offset = 1, + .mask = PM800_VCHG_INT_ENA2, + }, + [PM800_IRQ_TINT] = { + .reg_offset = 1, + .mask = PM800_TINT_INT_ENA2, + }, + /* INT2 */ + [PM800_IRQ_GPADC0] = { + .reg_offset = 2, + .mask = PM800_GPADC0_INT_ENA3, + }, + [PM800_IRQ_GPADC1] = { + .reg_offset = 2, + .mask = PM800_GPADC1_INT_ENA3, + }, + [PM800_IRQ_GPADC2] = { + .reg_offset = 2, + .mask = PM800_GPADC2_INT_ENA3, + }, + [PM800_IRQ_GPADC3] = { + .reg_offset = 2, + .mask = PM800_GPADC3_INT_ENA3, + }, + [PM800_IRQ_GPADC4] = { + .reg_offset = 2, + .mask = PM800_GPADC4_INT_ENA3, + }, + /* INT3 */ + [PM800_IRQ_GPIO0] = { + .reg_offset = 3, + .mask = PM800_GPIO0_INT_ENA4, + }, + [PM800_IRQ_GPIO1] = { + .reg_offset = 3, + .mask = PM800_GPIO1_INT_ENA4, + }, + [PM800_IRQ_GPIO2] = { + .reg_offset = 3, + .mask = PM800_GPIO2_INT_ENA4, + }, + [PM800_IRQ_GPIO3] = { + .reg_offset = 3, + .mask = PM800_GPIO3_INT_ENA4, + }, + [PM800_IRQ_GPIO4] = { + .reg_offset = 3, + .mask = PM800_GPIO4_INT_ENA4, + }, +}; + +static int __devinit device_gpadc_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + struct pm80x_subchip *subchip = chip->subchip; + struct regmap *map = subchip->regmap_gpadc; + int data = 0, mask = 0, ret = 0; + + if (!map) { + dev_warn(chip->dev, + "Warning: gpadc regmap is not available!\n"); + return -EINVAL; + } + /* + * initialize GPADC without activating it turn on GPADC + * measurments + */ + ret = regmap_update_bits(map, + PM800_GPADC_MISC_CONFIG2, + PM800_GPADC_MISC_GPFSM_EN, + PM800_GPADC_MISC_GPFSM_EN); + if (ret < 0) + goto out; + /* + * This function configures the ADC as requires for + * CP implementation.CP does not "own" the ADC configuration + * registers and relies on AP. + * Reason: enable automatic ADC measurements needed + * for CP to get VBAT and RF temperature readings. + */ + ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN1, + PM800_MEAS_EN1_VBAT, PM800_MEAS_EN1_VBAT); + if (ret < 0) + goto out; + ret = regmap_update_bits(map, PM800_GPADC_MEAS_EN2, + (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN), + (PM800_MEAS_EN2_RFTMP | PM800_MEAS_GP0_EN)); + if (ret < 0) + goto out; + + /* + * the defult of PM800 is GPADC operates at 100Ks/s rate + * and Number of GPADC slots with active current bias prior + * to GPADC sampling = 1 slot for all GPADCs set for + * Temprature mesurmants + */ + mask = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 | + PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3); + + if (pdata && (pdata->batt_det == 0)) + data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN1 | + PM800_GPADC_GP_BIAS_EN2 | PM800_GPADC_GP_BIAS_EN3); + else + data = (PM800_GPADC_GP_BIAS_EN0 | PM800_GPADC_GP_BIAS_EN2 | + PM800_GPADC_GP_BIAS_EN3); + + ret = regmap_update_bits(map, PM800_GP_BIAS_ENA1, mask, data); + if (ret < 0) + goto out; + + dev_info(chip->dev, "pm800 device_gpadc_init: Done\n"); + return 0; + +out: + dev_info(chip->dev, "pm800 device_gpadc_init: Failed!\n"); + return ret; +} + +static int __devinit device_irq_init_800(struct pm80x_chip *chip) +{ + struct regmap *map = chip->regmap; + unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + int data, mask, ret = -EINVAL; + + if (!map || !chip->irq) { + dev_err(chip->dev, "incorrect parameters\n"); + return -EINVAL; + } + + /* + * irq_mode defines the way of clearing interrupt. it's read-clear by + * default. + */ + mask = + PM800_WAKEUP2_INV_INT | PM800_WAKEUP2_INT_CLEAR | + PM800_WAKEUP2_INT_MASK; + + data = PM800_WAKEUP2_INT_CLEAR; + ret = regmap_update_bits(map, PM800_WAKEUP2, mask, data); + + if (ret < 0) + goto out; + + ret = + regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1, + chip->regmap_irq_chip, &chip->irq_data); + +out: + return ret; +} + +static void device_irq_exit_800(struct pm80x_chip *chip) +{ + regmap_del_irq_chip(chip->irq, chip->irq_data); +} + +static struct regmap_irq_chip pm800_irq_chip = { + .name = "88pm800", + .irqs = pm800_irqs, + .num_irqs = ARRAY_SIZE(pm800_irqs), + + .num_regs = 4, + .status_base = PM800_INT_STATUS1, + .mask_base = PM800_INT_ENA_1, + .ack_base = PM800_INT_STATUS1, +}; + +static int pm800_pages_init(struct pm80x_chip *chip) +{ + struct pm80x_subchip *subchip; + struct i2c_client *client = chip->client; + + subchip = chip->subchip; + /* PM800 block power: i2c addr 0x31 */ + if (subchip->power_page_addr) { + subchip->power_page = + i2c_new_dummy(client->adapter, subchip->power_page_addr); + subchip->regmap_power = + devm_regmap_init_i2c(subchip->power_page, + &pm80x_regmap_config); + i2c_set_clientdata(subchip->power_page, chip); + } else + dev_info(chip->dev, + "PM800 block power 0x31: No power_page_addr\n"); + + /* PM800 block GPADC: i2c addr 0x32 */ + if (subchip->gpadc_page_addr) { + subchip->gpadc_page = i2c_new_dummy(client->adapter, + subchip->gpadc_page_addr); + subchip->regmap_gpadc = + devm_regmap_init_i2c(subchip->gpadc_page, + &pm80x_regmap_config); + i2c_set_clientdata(subchip->gpadc_page, chip); + } else + dev_info(chip->dev, + "PM800 block GPADC 0x32: No gpadc_page_addr\n"); + + return 0; +} + +static void pm800_pages_exit(struct pm80x_chip *chip) +{ + struct pm80x_subchip *subchip; + + regmap_exit(chip->regmap); + i2c_unregister_device(chip->client); + + subchip = chip->subchip; + if (subchip->power_page) { + regmap_exit(subchip->regmap_power); + i2c_unregister_device(subchip->power_page); + } + if (subchip->gpadc_page) { + regmap_exit(subchip->regmap_gpadc); + i2c_unregister_device(subchip->gpadc_page); + } +} + +static int __devinit device_800_init(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata) +{ + int ret, pmic_id; + unsigned int val; + + ret = regmap_read(chip->regmap, PM800_CHIP_ID, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + goto out; + } + + pmic_id = val & PM80X_VERSION_MASK; + + if ((pmic_id >= PM800_CHIP_A0) && (pmic_id <= PM800_CHIP_END)) { + chip->version = val; + dev_info(chip->dev, + "88PM80x:Marvell 88PM800 (ID:0x%x) detected\n", val); + } else { + dev_err(chip->dev, + "Failed to detect Marvell 88PM800:ChipID[0x%x]\n", val); + ret = -EINVAL; + goto out; + } + + /* + * alarm wake up bit will be clear in device_irq_init(), + * read before that + */ + ret = regmap_read(chip->regmap, PM800_RTC_CONTROL, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read RTC register: %d\n", ret); + goto out; + } + if (val & PM800_ALARM_WAKEUP) { + if (pdata && pdata->rtc) + pdata->rtc->rtc_wakeup = 1; + } + + ret = device_gpadc_init(chip, pdata); + if (ret < 0) { + dev_err(chip->dev, "[%s]Failed to init gpadc\n", __func__); + goto out; + } + + chip->regmap_irq_chip = &pm800_irq_chip; + + ret = device_irq_init_800(chip); + if (ret < 0) { + dev_err(chip->dev, "[%s]Failed to init pm800 irq\n", __func__); + goto out; + } + + ret = + mfd_add_devices(chip->dev, 0, &onkey_devs[0], + ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add onkey subdev\n"); + goto out_dev; + } else + dev_info(chip->dev, "[%s]:Added mfd onkey_devs\n", __func__); + + if (pdata && pdata->rtc) { + rtc_devs[0].platform_data = pdata->rtc; + rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata); + ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], + ARRAY_SIZE(rtc_devs), NULL, 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add rtc subdev\n"); + goto out_dev; + } else + dev_info(chip->dev, + "[%s]:Added mfd rtc_devs\n", __func__); + } + + return 0; +out_dev: + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); +out: + return ret; +} + +static int __devinit pm800_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct pm80x_chip *chip; + struct pm80x_platform_data *pdata = client->dev.platform_data; + struct pm80x_subchip *subchip; + + ret = pm80x_init(client, id); + if (ret) { + dev_err(&client->dev, "pm800_init fail\n"); + goto out_init; + } + + chip = i2c_get_clientdata(client); + + /* init subchip for PM800 */ + subchip = + devm_kzalloc(&client->dev, sizeof(struct pm80x_subchip), + GFP_KERNEL); + if (!subchip) { + ret = -ENOMEM; + goto err_subchip_alloc; + } + + subchip->power_page_addr = pdata->power_page_addr; + subchip->gpadc_page_addr = pdata->gpadc_page_addr; + chip->subchip = subchip; + + ret = device_800_init(chip, pdata); + if (ret) { + dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + goto err_800_init; + } + + ret = pm800_pages_init(chip); + if (ret) { + dev_err(&client->dev, "pm800_pages_init failed!\n"); + goto err_page_init; + } + + if (pdata->plat_config) + pdata->plat_config(chip, pdata); + +err_page_init: + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); +err_800_init: + devm_kfree(&client->dev, subchip); +err_subchip_alloc: + pm80x_deinit(client); +out_init: + return ret; +} + +static int __devexit pm800_remove(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + mfd_remove_devices(chip->dev); + device_irq_exit_800(chip); + + pm800_pages_exit(chip); + devm_kfree(&client->dev, chip->subchip); + + pm80x_deinit(client); + + return 0; +} + +static struct i2c_driver pm800_driver = { + .driver = { + .name = "88PM80X", + .owner = THIS_MODULE, + .pm = &pm80x_pm_ops, + }, + .probe = pm800_probe, + .remove = __devexit_p(pm800_remove), + .id_table = pm80x_id_table, +}; + +static int __init pm800_i2c_init(void) +{ + return i2c_add_driver(&pm800_driver); +} +subsys_initcall(pm800_i2c_init); + +static void __exit pm800_i2c_exit(void) +{ + i2c_del_driver(&pm800_driver); +} +module_exit(pm800_i2c_exit); + +MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM800"); +MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c new file mode 100644 index 00000000000..6146583589f --- /dev/null +++ b/drivers/mfd/88pm805.c @@ -0,0 +1,301 @@ +/* + * Base driver for Marvell 88PM805 + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * Joseph(Yossi) Hanin <yhanin@marvell.com> + * Qiao Zhou <zhouqiao@marvell.com> + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/irq.h> +#include <linux/mfd/core.h> +#include <linux/mfd/88pm80x.h> +#include <linux/slab.h> +#include <linux/delay.h> + +#define PM805_CHIP_ID (0x00) + +static const struct i2c_device_id pm80x_id_table[] = { + {"88PM805", CHIP_PM805}, + {} /* NULL terminated */ +}; +MODULE_DEVICE_TABLE(i2c, pm80x_id_table); + +/* Interrupt Number in 88PM805 */ +enum { + PM805_IRQ_LDO_OFF, /*0 */ + PM805_IRQ_SRC_DPLL_LOCK, /*1 */ + PM805_IRQ_CLIP_FAULT, + PM805_IRQ_MIC_CONFLICT, + PM805_IRQ_HP2_SHRT, + PM805_IRQ_HP1_SHRT, /*5 */ + PM805_IRQ_FINE_PLL_FAULT, + PM805_IRQ_RAW_PLL_FAULT, + PM805_IRQ_VOLP_BTN_DET, + PM805_IRQ_VOLM_BTN_DET, + PM805_IRQ_SHRT_BTN_DET, /*10 */ + PM805_IRQ_MIC_DET, /*11 */ + + PM805_MAX_IRQ, +}; + +static struct resource codec_resources[] = { + { + /* Headset microphone insertion or removal */ + .name = "micin", + .start = PM805_IRQ_MIC_DET, + .end = PM805_IRQ_MIC_DET, + .flags = IORESOURCE_IRQ, + }, + { + /* Audio short HP1 */ + .name = "audio-short1", + .start = PM805_IRQ_HP1_SHRT, + .end = PM805_IRQ_HP1_SHRT, + .flags = IORESOURCE_IRQ, + }, + { + /* Audio short HP2 */ + .name = "audio-short2", + .start = PM805_IRQ_HP2_SHRT, + .end = PM805_IRQ_HP2_SHRT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell codec_devs[] = { + { + .name = "88pm80x-codec", + .num_resources = ARRAY_SIZE(codec_resources), + .resources = &codec_resources[0], + .id = -1, + }, +}; + +static struct regmap_irq pm805_irqs[] = { + /* INT0 */ + [PM805_IRQ_LDO_OFF] = { + .mask = PM805_INT1_HP1_SHRT, + }, + [PM805_IRQ_SRC_DPLL_LOCK] = { + .mask = PM805_INT1_HP2_SHRT, + }, + [PM805_IRQ_CLIP_FAULT] = { + .mask = PM805_INT1_MIC_CONFLICT, + }, + [PM805_IRQ_MIC_CONFLICT] = { + .mask = PM805_INT1_CLIP_FAULT, + }, + [PM805_IRQ_HP2_SHRT] = { + .mask = PM805_INT1_LDO_OFF, + }, + [PM805_IRQ_HP1_SHRT] = { + .mask = PM805_INT1_SRC_DPLL_LOCK, + }, + /* INT1 */ + [PM805_IRQ_FINE_PLL_FAULT] = { + .reg_offset = 1, + .mask = PM805_INT2_MIC_DET, + }, + [PM805_IRQ_RAW_PLL_FAULT] = { + .reg_offset = 1, + .mask = PM805_INT2_SHRT_BTN_DET, + }, + [PM805_IRQ_VOLP_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_VOLM_BTN_DET, + }, + [PM805_IRQ_VOLM_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_VOLP_BTN_DET, + }, + [PM805_IRQ_SHRT_BTN_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_RAW_PLL_FAULT, + }, + [PM805_IRQ_MIC_DET] = { + .reg_offset = 1, + .mask = PM805_INT2_FINE_PLL_FAULT, + }, +}; + +static int __devinit device_irq_init_805(struct pm80x_chip *chip) +{ + struct regmap *map = chip->regmap; + unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + int data, mask, ret = -EINVAL; + + if (!map || !chip->irq) { + dev_err(chip->dev, "incorrect parameters\n"); + return -EINVAL; + } + + /* + * irq_mode defines the way of clearing interrupt. it's read-clear by + * default. + */ + mask = + PM805_STATUS0_INT_CLEAR | PM805_STATUS0_INV_INT | + PM800_STATUS0_INT_MASK; + + data = PM805_STATUS0_INT_CLEAR; + ret = regmap_update_bits(map, PM805_INT_STATUS0, mask, data); + /* + * PM805_INT_STATUS is under 32K clock domain, so need to + * add proper delay before the next I2C register access. + */ + msleep(1); + + if (ret < 0) + goto out; + + ret = + regmap_add_irq_chip(chip->regmap, chip->irq, flags, -1, + chip->regmap_irq_chip, &chip->irq_data); + +out: + return ret; +} + +static void device_irq_exit_805(struct pm80x_chip *chip) +{ + regmap_del_irq_chip(chip->irq, chip->irq_data); +} + +static struct regmap_irq_chip pm805_irq_chip = { + .name = "88pm805", + .irqs = pm805_irqs, + .num_irqs = ARRAY_SIZE(pm805_irqs), + + .num_regs = 2, + .status_base = PM805_INT_STATUS1, + .mask_base = PM805_INT_MASK1, + .ack_base = PM805_INT_STATUS1, +}; + +static int __devinit device_805_init(struct pm80x_chip *chip) +{ + int ret = 0; + unsigned int val; + struct regmap *map = chip->regmap; + + if (!map) { + dev_err(chip->dev, "regmap is invalid\n"); + return -EINVAL; + } + + ret = regmap_read(map, PM805_CHIP_ID, &val); + if (ret < 0) { + dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); + goto out_irq_init; + } + chip->version = val; + + chip->regmap_irq_chip = &pm805_irq_chip; + + ret = device_irq_init_805(chip); + if (ret < 0) { + dev_err(chip->dev, "Failed to init pm805 irq!\n"); + goto out_irq_init; + } + + ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], + ARRAY_SIZE(codec_devs), &codec_resources[0], 0); + if (ret < 0) { + dev_err(chip->dev, "Failed to add codec subdev\n"); + goto out_codec; + } else + dev_info(chip->dev, "[%s]:Added mfd codec_devs\n", __func__); + + return 0; + +out_codec: + device_irq_exit_805(chip); +out_irq_init: + return ret; +} + +static int __devinit pm805_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct pm80x_chip *chip; + struct pm80x_platform_data *pdata = client->dev.platform_data; + + ret = pm80x_init(client, id); + if (ret) { + dev_err(&client->dev, "pm805_init fail!\n"); + goto out_init; + } + + chip = i2c_get_clientdata(client); + + ret = device_805_init(chip); + if (ret) { + dev_err(chip->dev, "%s id 0x%x failed!\n", __func__, chip->id); + goto err_805_init; + } + + if (pdata->plat_config) + pdata->plat_config(chip, pdata); + +err_805_init: + pm80x_deinit(client); +out_init: + return ret; +} + +static int __devexit pm805_remove(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + mfd_remove_devices(chip->dev); + device_irq_exit_805(chip); + + pm80x_deinit(client); + + return 0; +} + +static struct i2c_driver pm805_driver = { + .driver = { + .name = "88PM80X", + .owner = THIS_MODULE, + .pm = &pm80x_pm_ops, + }, + .probe = pm805_probe, + .remove = __devexit_p(pm805_remove), + .id_table = pm80x_id_table, +}; + +static int __init pm805_i2c_init(void) +{ + return i2c_add_driver(&pm805_driver); +} +subsys_initcall(pm805_i2c_init); + +static void __exit pm805_i2c_exit(void) +{ + i2c_del_driver(&pm805_driver); +} +module_exit(pm805_i2c_exit); + +MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM805"); +MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c new file mode 100644 index 00000000000..cd0bf527d76 --- /dev/null +++ b/drivers/mfd/88pm80x.c @@ -0,0 +1,145 @@ +/* + * I2C driver for Marvell 88PM80x + * + * Copyright (C) 2012 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * Joseph(Yossi) Hanin <yhanin@marvell.com> + * Qiao Zhou <zhouqiao@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mfd/88pm80x.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/err.h> + +/* + * workaround: some registers needed by pm805 are defined in pm800, so + * need to use this global variable to maintain the relation between + * pm800 and pm805. would remove it after HW chip fixes the issue. + */ +static struct pm80x_chip *g_pm80x_chip; + +const struct regmap_config pm80x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; +EXPORT_SYMBOL_GPL(pm80x_regmap_config); + +int __devinit pm80x_init(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pm80x_chip *chip; + struct regmap *map; + int ret = 0; + + chip = + devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + map = devm_regmap_init_i2c(client, &pm80x_regmap_config); + if (IS_ERR(map)) { + ret = PTR_ERR(map); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + ret); + goto err_regmap_init; + } + + chip->id = id->driver_data; + if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) { + ret = -EINVAL; + goto err_chip_id; + } + + chip->client = client; + chip->regmap = map; + + chip->irq = client->irq; + + chip->dev = &client->dev; + dev_set_drvdata(chip->dev, chip); + i2c_set_clientdata(chip->client, chip); + + device_init_wakeup(&client->dev, 1); + + /* + * workaround: set g_pm80x_chip to the first probed chip. if the + * second chip is probed, just point to the companion to each + * other so that pm805 can access those specific register. would + * remove it after HW chip fixes the issue. + */ + if (!g_pm80x_chip) + g_pm80x_chip = chip; + else { + chip->companion = g_pm80x_chip->client; + g_pm80x_chip->companion = chip->client; + } + + return 0; + +err_chip_id: + regmap_exit(map); +err_regmap_init: + devm_kfree(&client->dev, chip); + return ret; +} +EXPORT_SYMBOL_GPL(pm80x_init); + +int pm80x_deinit(struct i2c_client *client) +{ + struct pm80x_chip *chip = i2c_get_clientdata(client); + + /* + * workaround: clear the dependency between pm800 and pm805. + * would remove it after HW chip fixes the issue. + */ + if (g_pm80x_chip->companion) + g_pm80x_chip->companion = NULL; + else + g_pm80x_chip = NULL; + + regmap_exit(chip->regmap); + devm_kfree(&client->dev, chip); + + return 0; +} +EXPORT_SYMBOL_GPL(pm80x_deinit); + +#ifdef CONFIG_PM_SLEEP +static int pm80x_suspend(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct pm80x_chip *chip = i2c_get_clientdata(client); + + if (chip && chip->wu_flag) + if (device_may_wakeup(chip->dev)) + enable_irq_wake(chip->irq); + + return 0; +} + +static int pm80x_resume(struct device *dev) +{ + struct i2c_client *client = container_of(dev, struct i2c_client, dev); + struct pm80x_chip *chip = i2c_get_clientdata(client); + + if (chip && chip->wu_flag) + if (device_may_wakeup(chip->dev)) + disable_irq_wake(chip->irq); + + return 0; +} +#endif + +SIMPLE_DEV_PM_OPS(pm80x_pm_ops, pm80x_suspend, pm80x_resume); +EXPORT_SYMBOL_GPL(pm80x_pm_ops); + +MODULE_DESCRIPTION("I2C Driver for Marvell 88PM80x"); +MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 87bd5ba38d5..d09918cf1b1 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c @@ -90,6 +90,10 @@ static struct resource charger_resources[] __devinitdata = { {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, }; +static struct resource preg_resources[] __devinitdata = { + {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO,}, +}; + static struct resource rtc_resources[] __devinitdata = { {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, }; @@ -142,9 +146,19 @@ static struct mfd_cell codec_devs[] = { {"88pm860x-codec", -1,}, }; +static struct regulator_consumer_supply preg_supply[] = { + REGULATOR_SUPPLY("preg", "charger-manager"), +}; + +static struct regulator_init_data preg_init_data = { + .num_consumer_supplies = ARRAY_SIZE(preg_supply), + .consumer_supplies = &preg_supply[0], +}; + static struct mfd_cell power_devs[] = { {"88pm860x-battery", -1,}, {"88pm860x-charger", -1,}, + {"88pm860x-preg", -1,}, }; static struct mfd_cell rtc_devs[] = { @@ -768,6 +782,15 @@ static void __devinit device_power_init(struct pm860x_chip *chip, &charger_resources[0], chip->irq_base); if (ret < 0) dev_err(chip->dev, "Failed to add charger subdev\n"); + + power_devs[2].platform_data = &preg_init_data; + power_devs[2].pdata_size = sizeof(struct regulator_init_data); + power_devs[2].num_resources = ARRAY_SIZE(preg_resources); + power_devs[2].resources = &preg_resources[0], + ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, + &preg_resources[0], chip->irq_base); + if (ret < 0) + dev_err(chip->dev, "Failed to add preg subdev\n"); } static void __devinit device_onkey_init(struct pm860x_chip *chip, diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 92144ed1ad4..d1facef28a6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -7,6 +7,7 @@ menu "Multifunction device drivers" config MFD_CORE tristate + select IRQ_DOMAIN default n config MFD_88PM860X @@ -20,6 +21,30 @@ config MFD_88PM860X select individual components like voltage regulators, RTC and battery-charger under the corresponding menus. +config MFD_88PM800 + tristate "Support Marvell 88PM800" + depends on I2C=y && GENERIC_HARDIRQS + select REGMAP_I2C + select REGMAP_IRQ + select MFD_CORE + help + This supports for Marvell 88PM800 Power Management IC. + This includes the I2C driver and the core APIs _only_, you have to + select individual components like voltage regulators, RTC and + battery-charger under the corresponding menus. + +config MFD_88PM805 + tristate "Support Marvell 88PM805" + depends on I2C=y && GENERIC_HARDIRQS + select REGMAP_I2C + select REGMAP_IRQ + select MFD_CORE + help + This supports for Marvell 88PM805 Power Management IC. This includes + the I2C driver and the core APIs _only_, you have to select individual + components like codec device, headset/Mic device under the + corresponding menus. + config MFD_SM501 tristate "Support for Silicon Motion SM501" ---help--- @@ -173,8 +198,9 @@ config MFD_TPS65217 config MFD_TPS6586X bool "TPS6586x Power Management chips" - depends on I2C=y && GPIOLIB && GENERIC_HARDIRQS + depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select REGMAP_I2C depends on REGULATOR help If you say yes here you get support for the TPS6586X series of @@ -276,6 +302,7 @@ config TWL6030_PWM tristate "TWL6030 PWM (Pulse Width Modulator) Support" depends on TWL4030_CORE select HAVE_PWM + depends on !PWM default n help Say yes here if you want support for TWL6030 PWM. @@ -423,6 +450,19 @@ config PMIC_ADP5520 individual components like LCD backlight, LEDs, GPIOs and Kepad under the corresponding menus. +config MFD_MAX77686 + bool "Maxim Semiconductor MAX77686 PMIC Support" + depends on I2C=y && GENERIC_HARDIRQS + select MFD_CORE + select REGMAP_I2C + select IRQ_DOMAIN + help + Say yes here to support for Maxim Semiconductor MAX77686. + This is a Power Management IC with RTC on chip. + This driver provides common support for accessing the device; + additional drivers must be enabled in order to use the functionality + of the device. + config MFD_MAX77693 bool "Maxim Semiconductor MAX77693 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS @@ -450,6 +490,7 @@ config MFD_MAX8997 bool "Maxim Semiconductor MAX8997/8966 PMIC Support" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE + select IRQ_DOMAIN help Say yes here to support for Maxim Semiconductor MAX8997/8966. This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic, @@ -469,17 +510,56 @@ config MFD_MAX8998 additional drivers must be enabled in order to use the functionality of the device. -config MFD_S5M_CORE - bool "SAMSUNG S5M Series Support" +config MFD_SEC_CORE + bool "SAMSUNG Electronics PMIC Series Support" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE select REGMAP_I2C + select REGMAP_IRQ help - Support for the Samsung Electronics S5M MFD series. + Support for the Samsung Electronics MFD series. This driver provides common support for accessing the device, additional drivers must be enabled in order to use the functionality of the device +config MFD_ARIZONA + select REGMAP + select REGMAP_IRQ + select MFD_CORE + bool + +config MFD_ARIZONA_I2C + tristate "Support Wolfson Microelectronics Arizona platform with I2C" + select MFD_ARIZONA + select MFD_CORE + select REGMAP_I2C + depends on I2C + help + Support for the Wolfson Microelectronics Arizona platform audio SoC + core functionality controlled via I2C. + +config MFD_ARIZONA_SPI + tristate "Support Wolfson Microelectronics Arizona platform with SPI" + select MFD_ARIZONA + select MFD_CORE + select REGMAP_SPI + depends on SPI_MASTER + help + Support for the Wolfson Microelectronics Arizona platform audio SoC + core functionality controlled via I2C. + +config MFD_WM5102 + bool "Support Wolfson Microelectronics WM5102" + depends on MFD_ARIZONA + help + Support for Wolfson Microelectronics WM5102 low power audio SoC + +config MFD_WM5110 + bool "Support Wolfson Microelectronics WM5110" + depends on MFD_ARIZONA + help + Support for Wolfson Microelectronics WM5110 low power audio SoC + config MFD_WM8400 bool "Support Wolfson Microelectronics WM8400" select MFD_CORE @@ -697,6 +777,7 @@ config AB8500_CORE bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU select MFD_CORE + select IRQ_DOMAIN help Select this option to enable access to AB8500 power management chip. This connects to U8500 either on the SSP/SPI bus (deprecated @@ -704,16 +785,6 @@ config AB8500_CORE the irq_chip parts for handling the Mixed Signal chip events. This chip embeds various other multimedia funtionalities as well. -config AB8500_I2C_CORE - bool "AB8500 register access via PRCMU I2C" - depends on AB8500_CORE && MFD_DB8500_PRCMU - default y - help - This enables register access to the AB8500 chip via PRCMU I2C. - The AB8500 chip can be accessed via SPI or I2C. On DB8500 hardware - the I2C bus is connected to the Power Reset - and Mangagement Unit, PRCMU. - config AB8500_DEBUG bool "Enable debug info via debugfs" depends on AB8500_CORE && DEBUG_FS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 75f6ed68a4b..79dd22d1dc3 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -4,6 +4,8 @@ 88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o +obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o +obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o @@ -24,6 +26,16 @@ obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o +obj-$(CONFIG_MFD_ARIZONA) += arizona-core.o +obj-$(CONFIG_MFD_ARIZONA) += arizona-irq.o +obj-$(CONFIG_MFD_ARIZONA_I2C) += arizona-i2c.o +obj-$(CONFIG_MFD_ARIZONA_SPI) += arizona-spi.o +ifneq ($(CONFIG_MFD_WM5102),n) +obj-$(CONFIG_MFD_ARIZONA) += wm5102-tables.o +endif +ifneq ($(CONFIG_MFD_WM5110),n) +obj-$(CONFIG_MFD_ARIZONA) += wm5110-tables.o +endif obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs += wm831x-auxadc.o @@ -78,6 +90,7 @@ 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_MAX77686) += max77686.o max77686-irq.o obj-$(CONFIG_MFD_MAX77693) += max77693.o max77693-irq.o max8925-objs := max8925-core.o max8925-i2c.o obj-$(CONFIG_MFD_MAX8925) += max8925.o @@ -116,6 +129,6 @@ obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o -obj-$(CONFIG_MFD_S5M_CORE) += s5m-core.o s5m-irq.o +obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_ANATOP) += anatop-mfd.o obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 1efad20fb17..4276aab4f19 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -867,7 +867,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, int err; int i; - ab3100 = kzalloc(sizeof(struct ab3100), GFP_KERNEL); + ab3100 = devm_kzalloc(&client->dev, sizeof(struct ab3100), GFP_KERNEL); if (!ab3100) { dev_err(&client->dev, "could not allocate AB3100 device\n"); return -ENOMEM; @@ -921,7 +921,7 @@ static int __devinit ab3100_probe(struct i2c_client *client, /* Attach a second dummy i2c_client to the test register address */ ab3100->testreg_client = i2c_new_dummy(client->adapter, - client->addr + 1); + client->addr + 1); if (!ab3100->testreg_client) { err = -ENOMEM; goto exit_no_testreg_client; @@ -931,13 +931,13 @@ static int __devinit ab3100_probe(struct i2c_client *client, if (err) goto exit_no_setup; - err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, - IRQF_ONESHOT, "ab3100-core", ab3100); - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); - + err = devm_request_threaded_irq(&client->dev, + client->irq, NULL, ab3100_irq_handler, + IRQF_ONESHOT, "ab3100-core", ab3100); if (err) goto exit_no_irq; + /* This real unpredictable IRQ is of course sampled for entropy */ + rand_initialize_irq(client->irq); err = abx500_register_ops(&client->dev, &ab3100_ops); if (err) @@ -962,7 +962,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, i2c_unregister_device(ab3100->testreg_client); exit_no_testreg_client: exit_no_detect: - kfree(ab3100); return err; } @@ -972,16 +971,8 @@ static int __devexit ab3100_remove(struct i2c_client *client) /* Unregister subdevices */ mfd_remove_devices(&client->dev); - ab3100_remove_debugfs(); i2c_unregister_device(ab3100->testreg_client); - - /* - * At this point, all subscribers should have unregistered - * their notifiers so deactivate IRQ - */ - free_irq(client->irq, ab3100); - kfree(ab3100); return 0; } diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index dac0e299860..626b4ecaf64 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -11,6 +11,7 @@ #include <linux/slab.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/irqdomain.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/module.h> @@ -140,7 +141,7 @@ static const char ab8500_version_str[][7] = { [AB8500_VERSION_AB8540] = "AB8540", }; -static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) +static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data) { int ret; @@ -150,7 +151,7 @@ static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) return ret; } -static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, +static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data) { int ret; @@ -162,7 +163,7 @@ static int ab8500_i2c_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask, return ret; } -static int ab8500_i2c_read(struct ab8500 *ab8500, u16 addr) +static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr) { int ret; u8 data; @@ -361,7 +362,7 @@ static void ab8500_irq_sync_unlock(struct irq_data *data) static void ab8500_irq_mask(struct irq_data *data) { struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); - int offset = data->irq - ab8500->irq_base; + int offset = data->hwirq; int index = offset / 8; int mask = 1 << (offset % 8); @@ -371,7 +372,7 @@ static void ab8500_irq_mask(struct irq_data *data) static void ab8500_irq_unmask(struct irq_data *data) { struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data); - int offset = data->irq - ab8500->irq_base; + int offset = data->hwirq; int index = offset / 8; int mask = 1 << (offset % 8); @@ -510,38 +511,51 @@ static irqreturn_t ab8500_irq(int irq, void *dev) return IRQ_HANDLED; } -static int ab8500_irq_init(struct ab8500 *ab8500) +/** + * ab8500_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ + * + * @ab8500: ab8500_irq controller to operate on. + * @irq: index of the interrupt requested in the chip IRQs + * + * Useful for drivers to request their own IRQs. + */ +int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq) { - int base = ab8500->irq_base; - int irq; - int num_irqs; + if (!ab8500) + return -EINVAL; - if (is_ab9540(ab8500)) - num_irqs = AB9540_NR_IRQS; - else if (is_ab8505(ab8500)) - num_irqs = AB8505_NR_IRQS; - else - num_irqs = AB8500_NR_IRQS; + return irq_create_mapping(ab8500->domain, irq); +} +EXPORT_SYMBOL_GPL(ab8500_irq_get_virq); + +static int ab8500_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hwirq) +{ + struct ab8500 *ab8500 = d->host_data; - for (irq = base; irq < base + num_irqs; irq++) { - irq_set_chip_data(irq, ab8500); - irq_set_chip_and_handler(irq, &ab8500_irq_chip, - handle_simple_irq); - irq_set_nested_thread(irq, 1); + if (!ab8500) + return -EINVAL; + + irq_set_chip_data(virq, ab8500); + irq_set_chip_and_handler(virq, &ab8500_irq_chip, + handle_simple_irq); + irq_set_nested_thread(virq, 1); #ifdef CONFIG_ARM - set_irq_flags(irq, IRQF_VALID); + set_irq_flags(virq, IRQF_VALID); #else - irq_set_noprobe(irq); + irq_set_noprobe(virq); #endif - } return 0; } -static void ab8500_irq_remove(struct ab8500 *ab8500) +static struct irq_domain_ops ab8500_irq_ops = { + .map = ab8500_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np) { - int base = ab8500->irq_base; - int irq; int num_irqs; if (is_ab9540(ab8500)) @@ -551,13 +565,22 @@ static void ab8500_irq_remove(struct ab8500 *ab8500) else num_irqs = AB8500_NR_IRQS; - for (irq = base; irq < base + num_irqs; irq++) { -#ifdef CONFIG_ARM - set_irq_flags(irq, 0); -#endif - irq_set_chip_and_handler(irq, NULL, NULL); - irq_set_chip_data(irq, NULL); + if (ab8500->irq_base) { + ab8500->domain = irq_domain_add_legacy( + NULL, num_irqs, ab8500->irq_base, + 0, &ab8500_irq_ops, ab8500); + } + else { + ab8500->domain = irq_domain_add_linear( + np, num_irqs, &ab8500_irq_ops, ab8500); + } + + if (!ab8500->domain) { + dev_err(ab8500->dev, "Failed to create irqdomain\n"); + return -ENOSYS; } + + return 0; } int ab8500_suspend(struct ab8500 *ab8500) @@ -947,54 +970,69 @@ static struct mfd_cell __devinitdata abx500_common_devs[] = { #ifdef CONFIG_DEBUG_FS { .name = "ab8500-debug", + .of_compatible = "stericsson,ab8500-debug", .num_resources = ARRAY_SIZE(ab8500_debug_resources), .resources = ab8500_debug_resources, }, #endif { .name = "ab8500-sysctrl", + .of_compatible = "stericsson,ab8500-sysctrl", }, { .name = "ab8500-regulator", + .of_compatible = "stericsson,ab8500-regulator", }, { .name = "ab8500-gpadc", + .of_compatible = "stericsson,ab8500-gpadc", .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), .resources = ab8500_gpadc_resources, }, { .name = "ab8500-rtc", + .of_compatible = "stericsson,ab8500-rtc", .num_resources = ARRAY_SIZE(ab8500_rtc_resources), .resources = ab8500_rtc_resources, }, { .name = "ab8500-acc-det", + .of_compatible = "stericsson,ab8500-acc-det", .num_resources = ARRAY_SIZE(ab8500_av_acc_detect_resources), .resources = ab8500_av_acc_detect_resources, }, { .name = "ab8500-poweron-key", + .of_compatible = "stericsson,ab8500-poweron-key", .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), .resources = ab8500_poweronkey_db_resources, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 1, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 2, }, { .name = "ab8500-pwm", + .of_compatible = "stericsson,ab8500-pwm", .id = 3, }, - { .name = "ab8500-leds", }, + { + .name = "ab8500-leds", + .of_compatible = "stericsson,ab8500-leds", + }, { .name = "ab8500-denc", + .of_compatible = "stericsson,ab8500-denc", }, { .name = "ab8500-temp", + .of_compatible = "stericsson,ab8500-temp", .num_resources = ARRAY_SIZE(ab8500_temp_resources), .resources = ab8500_temp_resources, }, @@ -1026,11 +1064,13 @@ static struct mfd_cell __devinitdata ab8500_bm_devs[] = { static struct mfd_cell __devinitdata ab8500_devs[] = { { .name = "ab8500-gpio", + .of_compatible = "stericsson,ab8500-gpio", .num_resources = ARRAY_SIZE(ab8500_gpio_resources), .resources = ab8500_gpio_resources, }, { .name = "ab8500-usb", + .of_compatible = "stericsson,ab8500-usb", .num_resources = ARRAY_SIZE(ab8500_usb_resources), .resources = ab8500_usb_resources, }, @@ -1207,16 +1247,17 @@ static struct attribute_group ab9540_attr_group = { .attrs = ab9540_sysfs_entries, }; -static const struct of_device_id ab8500_match[] = { - { - .compatible = "stericsson,ab8500", - .data = (void *)AB8500_VERSION_AB8500, - }, - {}, -}; - static int __devinit ab8500_probe(struct platform_device *pdev) { + static char *switch_off_status[] = { + "Swoff bit programming", + "Thermal protection activation", + "Vbat lower then BattOk falling threshold", + "Watchdog expired", + "Non presence of 32kHz clock", + "Battery level lower than power on reset threshold", + "Power on key 1 pressed longer than 10 seconds", + "DB8500 thermal shutdown"}; struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev); const struct platform_device_id *platid = platform_get_device_id(pdev); enum ab8500_version version = AB8500_VERSION_UNDEFINED; @@ -1233,14 +1274,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev) if (plat) ab8500->irq_base = plat->irq_base; - else if (np) - ret = of_property_read_u32(np, "stericsson,irq-base", &ab8500->irq_base); - - if (!ab8500->irq_base) { - dev_info(&pdev->dev, "couldn't find irq-base\n"); - ret = -EINVAL; - goto out_free_ab8500; - } ab8500->dev = &pdev->dev; @@ -1252,9 +1285,9 @@ static int __devinit ab8500_probe(struct platform_device *pdev) ab8500->irq = resource->start; - ab8500->read = ab8500_i2c_read; - ab8500->write = ab8500_i2c_write; - ab8500->write_masked = ab8500_i2c_write_masked; + ab8500->read = ab8500_prcmu_read; + ab8500->write = ab8500_prcmu_write; + ab8500->write_masked = ab8500_prcmu_write_masked; mutex_init(&ab8500->lock); mutex_init(&ab8500->irq_lock); @@ -1264,9 +1297,6 @@ static int __devinit ab8500_probe(struct platform_device *pdev) if (platid) version = platid->driver_data; - else if (np) - version = (unsigned int) - of_match_device(ab8500_match, &pdev->dev)->data; if (version != AB8500_VERSION_UNDEFINED) ab8500->version = version; @@ -1323,7 +1353,20 @@ static int __devinit ab8500_probe(struct platform_device *pdev) AB8500_SWITCH_OFF_STATUS, &value); if (ret < 0) return ret; - dev_info(ab8500->dev, "switch off status: %#x", value); + dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value); + + if (value) { + for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) { + if (value & 1) + printk(KERN_CONT " \"%s\"", + switch_off_status[i]); + value = value >> 1; + + } + printk(KERN_CONT "\n"); + } else { + printk(KERN_CONT " None\n"); + } if (plat && plat->init) plat->init(ab8500); @@ -1352,53 +1395,50 @@ static int __devinit ab8500_probe(struct platform_device *pdev) for (i = 0; i < ab8500->mask_size; i++) ab8500->mask[i] = ab8500->oldmask[i] = 0xff; - if (ab8500->irq_base) { - ret = ab8500_irq_init(ab8500); - if (ret) - goto out_freeoldmask; + ret = ab8500_irq_init(ab8500, np); + if (ret) + goto out_freeoldmask; - /* Activate this feature only in ab9540 */ - /* till tests are done on ab8500 1p2 or later*/ - if (is_ab9540(ab8500)) - ret = request_threaded_irq(ab8500->irq, NULL, + /* Activate this feature only in ab9540 */ + /* till tests are done on ab8500 1p2 or later*/ + if (is_ab9540(ab8500)) { + ret = request_threaded_irq(ab8500->irq, NULL, ab8500_hierarchical_irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, "ab8500", ab8500); - else - ret = request_threaded_irq(ab8500->irq, NULL, + } + else { + ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, IRQF_ONESHOT | IRQF_NO_SUSPEND, "ab8500", ab8500); if (ret) - goto out_removeirq; + goto out_freeoldmask; } - if (!np) { - ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, - ARRAY_SIZE(abx500_common_devs), NULL, - ab8500->irq_base); + ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs, + ARRAY_SIZE(abx500_common_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; - if (ret) - goto out_freeirq; - - if (is_ab9540(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, - ARRAY_SIZE(ab9540_devs), NULL, - ab8500->irq_base); - else - ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, - ARRAY_SIZE(ab8500_devs), NULL, - ab8500->irq_base); - if (ret) - goto out_freeirq; + if (is_ab9540(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, + ARRAY_SIZE(ab9540_devs), NULL, + ab8500->irq_base); + else + ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, + ARRAY_SIZE(ab8500_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; - if (is_ab9540(ab8500) || is_ab8505(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, - ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base); - if (ret) - goto out_freeirq; - } + if (is_ab9540(ab8500) || is_ab8505(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, + ARRAY_SIZE(ab9540_ab8505_devs), NULL, + ab8500->irq_base); + if (ret) + goto out_freeirq; if (!no_bm) { /* Add battery management devices */ @@ -1417,15 +1457,11 @@ static int __devinit ab8500_probe(struct platform_device *pdev) &ab8500_attr_group); if (ret) dev_err(ab8500->dev, "error creating sysfs entries\n"); - else - return ret; + + return ret; out_freeirq: - if (ab8500->irq_base) - free_irq(ab8500->irq, ab8500); -out_removeirq: - if (ab8500->irq_base) - ab8500_irq_remove(ab8500); + free_irq(ab8500->irq, ab8500); out_freeoldmask: kfree(ab8500->oldmask); out_freemask: @@ -1444,11 +1480,10 @@ static int __devexit ab8500_remove(struct platform_device *pdev) sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group); else sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group); + mfd_remove_devices(ab8500->dev); - if (ab8500->irq_base) { - free_irq(ab8500->irq, ab8500); - ab8500_irq_remove(ab8500); - } + free_irq(ab8500->irq, ab8500); + kfree(ab8500->oldmask); kfree(ab8500->mask); kfree(ab8500); @@ -1468,7 +1503,6 @@ static struct platform_driver ab8500_core_driver = { .driver = { .name = "ab8500-core", .owner = THIS_MODULE, - .of_match_table = ab8500_match, }, .probe = ab8500_probe, .remove = __devexit_p(ab8500_remove), @@ -1484,7 +1518,7 @@ static void __exit ab8500_core_exit(void) { platform_driver_unregister(&ab8500_core_driver); } -arch_initcall(ab8500_core_init); +core_initcall(ab8500_core_init); module_exit(ab8500_core_exit); MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent"); diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c index 50c4c89ab22..c4cb806978a 100644 --- a/drivers/mfd/ab8500-debugfs.c +++ b/drivers/mfd/ab8500-debugfs.c @@ -31,12 +31,12 @@ struct ab8500_reg_range { }; /** - * struct ab8500_i2c_ranges + * struct ab8500_prcmu_ranges * @num_ranges: the number of ranges in the list * @bankid: bank identifier * @range: the list of register ranges */ -struct ab8500_i2c_ranges { +struct ab8500_prcmu_ranges { u8 num_ranges; u8 bankid; const struct ab8500_reg_range *range; @@ -47,7 +47,7 @@ struct ab8500_i2c_ranges { #define AB8500_REV_REG 0x80 -static struct ab8500_i2c_ranges debug_ranges[AB8500_NUM_BANKS] = { +static struct ab8500_prcmu_ranges debug_ranges[AB8500_NUM_BANKS] = { [0x0] = { .num_ranges = 0, .range = 0, @@ -608,16 +608,10 @@ static int __devexit ab8500_debug_remove(struct platform_device *plf) return 0; } -static const struct of_device_id ab8500_debug_match[] = { - { .compatible = "stericsson,ab8500-debug", }, - {} -}; - static struct platform_driver ab8500_debug_driver = { .driver = { .name = "ab8500-debug", .owner = THIS_MODULE, - .of_match_table = ab8500_debug_match, }, .probe = ab8500_debug_probe, .remove = __devexit_p(ab8500_debug_remove) diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index b86fd8e1ec3..866f95960b4 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -599,7 +599,8 @@ static int __devinit ab8500_gpadc_probe(struct platform_device *pdev) /* Register interrupt - SwAdcComplete */ ret = request_threaded_irq(gpadc->irq, NULL, ab8500_bm_gpswadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc", gpadc); + IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, + "ab8500-gpadc", gpadc); if (ret < 0) { dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", gpadc->irq); @@ -648,18 +649,12 @@ static int __devexit ab8500_gpadc_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_gpadc_match[] = { - { .compatible = "stericsson,ab8500-gpadc", }, - {} -}; - static struct platform_driver ab8500_gpadc_driver = { .probe = ab8500_gpadc_probe, .remove = __devexit_p(ab8500_gpadc_remove), .driver = { .name = "ab8500-gpadc", .owner = THIS_MODULE, - .of_match_table = ab8500_gpadc_match, }, }; diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c index 5a3e51ccf25..c28d4eb1eff 100644 --- a/drivers/mfd/ab8500-sysctrl.c +++ b/drivers/mfd/ab8500-sysctrl.c @@ -61,16 +61,10 @@ static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_sysctrl_match[] = { - { .compatible = "stericsson,ab8500-sysctrl", }, - {} -}; - static struct platform_driver ab8500_sysctrl_driver = { .driver = { .name = "ab8500-sysctrl", .owner = THIS_MODULE, - .of_match_table = ab8500_sysctrl_match, }, .probe = ab8500_sysctrl_probe, .remove = __devexit_p(ab8500_sysctrl_remove), diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 8d816cce832..ea8b9475731 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -320,7 +320,7 @@ static int __devexit adp5520_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int adp5520_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); diff --git a/drivers/mfd/anatop-mfd.c b/drivers/mfd/anatop-mfd.c index 6da06341f6c..5576e07576d 100644 --- a/drivers/mfd/anatop-mfd.c +++ b/drivers/mfd/anatop-mfd.c @@ -83,7 +83,7 @@ static int __devinit of_anatop_probe(struct platform_device *pdev) drvdata->ioreg = ioreg; spin_lock_init(&drvdata->reglock); platform_set_drvdata(pdev, drvdata); - of_platform_populate(np, of_anatop_match, NULL, dev); + of_platform_populate(np, NULL, NULL, dev); return 0; } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c new file mode 100644 index 00000000000..c7983e86254 --- /dev/null +++ b/drivers/mfd/arizona-core.c @@ -0,0 +1,566 @@ +/* + * Arizona core driver + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/mfd/core.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +#include <linux/mfd/arizona/core.h> +#include <linux/mfd/arizona/registers.h> + +#include "arizona.h" + +static const char *wm5102_core_supplies[] = { + "AVDD", + "DBVDD1", +}; + +int arizona_clk32k_enable(struct arizona *arizona) +{ + int ret = 0; + + mutex_lock(&arizona->clk_lock); + + arizona->clk32k_ref++; + + if (arizona->clk32k_ref == 1) + ret = regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, + ARIZONA_CLK_32K_ENA, + ARIZONA_CLK_32K_ENA); + + if (ret != 0) + arizona->clk32k_ref--; + + mutex_unlock(&arizona->clk_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(arizona_clk32k_enable); + +int arizona_clk32k_disable(struct arizona *arizona) +{ + int ret = 0; + + mutex_lock(&arizona->clk_lock); + + BUG_ON(arizona->clk32k_ref <= 0); + + arizona->clk32k_ref--; + + if (arizona->clk32k_ref == 0) + regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, + ARIZONA_CLK_32K_ENA, 0); + + mutex_unlock(&arizona->clk_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(arizona_clk32k_disable); + +static irqreturn_t arizona_clkgen_err(int irq, void *data) +{ + struct arizona *arizona = data; + + dev_err(arizona->dev, "CLKGEN error\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t arizona_underclocked(int irq, void *data) +{ + struct arizona *arizona = data; + unsigned int val; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_8, + &val); + if (ret != 0) { + dev_err(arizona->dev, "Failed to read underclock status: %d\n", + ret); + return IRQ_NONE; + } + + if (val & ARIZONA_AIF3_UNDERCLOCKED_STS) + dev_err(arizona->dev, "AIF3 underclocked\n"); + if (val & ARIZONA_AIF3_UNDERCLOCKED_STS) + dev_err(arizona->dev, "AIF3 underclocked\n"); + if (val & ARIZONA_AIF2_UNDERCLOCKED_STS) + dev_err(arizona->dev, "AIF1 underclocked\n"); + if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS) + dev_err(arizona->dev, "ISRC2 underclocked\n"); + if (val & ARIZONA_ISRC1_UNDERCLOCKED_STS) + dev_err(arizona->dev, "ISRC1 underclocked\n"); + if (val & ARIZONA_FX_UNDERCLOCKED_STS) + dev_err(arizona->dev, "FX underclocked\n"); + if (val & ARIZONA_ASRC_UNDERCLOCKED_STS) + dev_err(arizona->dev, "ASRC underclocked\n"); + if (val & ARIZONA_DAC_UNDERCLOCKED_STS) + dev_err(arizona->dev, "DAC underclocked\n"); + if (val & ARIZONA_ADC_UNDERCLOCKED_STS) + dev_err(arizona->dev, "ADC underclocked\n"); + if (val & ARIZONA_MIXER_UNDERCLOCKED_STS) + dev_err(arizona->dev, "Mixer underclocked\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t arizona_overclocked(int irq, void *data) +{ + struct arizona *arizona = data; + unsigned int val[2]; + int ret; + + ret = regmap_bulk_read(arizona->regmap, ARIZONA_INTERRUPT_RAW_STATUS_6, + &val[0], 2); + if (ret != 0) { + dev_err(arizona->dev, "Failed to read overclock status: %d\n", + ret); + return IRQ_NONE; + } + + if (val[0] & ARIZONA_PWM_OVERCLOCKED_STS) + dev_err(arizona->dev, "PWM overclocked\n"); + if (val[0] & ARIZONA_FX_CORE_OVERCLOCKED_STS) + dev_err(arizona->dev, "FX core overclocked\n"); + if (val[0] & ARIZONA_DAC_SYS_OVERCLOCKED_STS) + dev_err(arizona->dev, "DAC SYS overclocked\n"); + if (val[0] & ARIZONA_DAC_WARP_OVERCLOCKED_STS) + dev_err(arizona->dev, "DAC WARP overclocked\n"); + if (val[0] & ARIZONA_ADC_OVERCLOCKED_STS) + dev_err(arizona->dev, "ADC overclocked\n"); + if (val[0] & ARIZONA_MIXER_OVERCLOCKED_STS) + dev_err(arizona->dev, "Mixer overclocked\n"); + if (val[0] & ARIZONA_AIF3_SYNC_OVERCLOCKED_STS) + dev_err(arizona->dev, "AIF3 overclocked\n"); + if (val[0] & ARIZONA_AIF2_SYNC_OVERCLOCKED_STS) + dev_err(arizona->dev, "AIF2 overclocked\n"); + if (val[0] & ARIZONA_AIF1_SYNC_OVERCLOCKED_STS) + dev_err(arizona->dev, "AIF1 overclocked\n"); + if (val[0] & ARIZONA_PAD_CTRL_OVERCLOCKED_STS) + dev_err(arizona->dev, "Pad control overclocked\n"); + + if (val[1] & ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS) + dev_err(arizona->dev, "Slimbus subsystem overclocked\n"); + if (val[1] & ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS) + dev_err(arizona->dev, "Slimbus async overclocked\n"); + if (val[1] & ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS) + dev_err(arizona->dev, "Slimbus sync overclocked\n"); + if (val[1] & ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS) + dev_err(arizona->dev, "ASRC async system overclocked\n"); + if (val[1] & ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS) + dev_err(arizona->dev, "ASRC async WARP overclocked\n"); + if (val[1] & ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS) + dev_err(arizona->dev, "ASRC sync system overclocked\n"); + if (val[1] & ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS) + dev_err(arizona->dev, "ASRC sync WARP overclocked\n"); + if (val[1] & ARIZONA_ADSP2_1_OVERCLOCKED_STS) + dev_err(arizona->dev, "DSP1 overclocked\n"); + if (val[1] & ARIZONA_ISRC2_OVERCLOCKED_STS) + dev_err(arizona->dev, "ISRC2 overclocked\n"); + if (val[1] & ARIZONA_ISRC1_OVERCLOCKED_STS) + dev_err(arizona->dev, "ISRC1 overclocked\n"); + + return IRQ_HANDLED; +} + +static int arizona_wait_for_boot(struct arizona *arizona) +{ + unsigned int reg; + int ret, i; + + /* + * We can't use an interrupt as we need to runtime resume to do so, + * we won't race with the interrupt handler as it'll be blocked on + * runtime resume. + */ + for (i = 0; i < 5; i++) { + msleep(1); + + ret = regmap_read(arizona->regmap, + ARIZONA_INTERRUPT_RAW_STATUS_5, ®); + if (ret != 0) { + dev_err(arizona->dev, "Failed to read boot state: %d\n", + ret); + continue; + } + + if (reg & ARIZONA_BOOT_DONE_STS) + break; + } + + if (reg & ARIZONA_BOOT_DONE_STS) { + regmap_write(arizona->regmap, ARIZONA_INTERRUPT_STATUS_5, + ARIZONA_BOOT_DONE_STS); + } else { + dev_err(arizona->dev, "Device boot timed out: %x\n", reg); + return -ETIMEDOUT; + } + + pm_runtime_mark_last_busy(arizona->dev); + + return 0; +} + +#ifdef CONFIG_PM_RUNTIME +static int arizona_runtime_resume(struct device *dev) +{ + struct arizona *arizona = dev_get_drvdata(dev); + int ret; + + dev_dbg(arizona->dev, "Leaving AoD mode\n"); + + ret = regulator_enable(arizona->dcvdd); + if (ret != 0) { + dev_err(arizona->dev, "Failed to enable DCVDD: %d\n", ret); + return ret; + } + + regcache_cache_only(arizona->regmap, false); + + ret = arizona_wait_for_boot(arizona); + if (ret != 0) { + regulator_disable(arizona->dcvdd); + return ret; + } + + regcache_sync(arizona->regmap); + + return 0; +} + +static int arizona_runtime_suspend(struct device *dev) +{ + struct arizona *arizona = dev_get_drvdata(dev); + + dev_dbg(arizona->dev, "Entering AoD mode\n"); + + regulator_disable(arizona->dcvdd); + regcache_cache_only(arizona->regmap, true); + regcache_mark_dirty(arizona->regmap); + + return 0; +} +#endif + +const struct dev_pm_ops arizona_pm_ops = { + SET_RUNTIME_PM_OPS(arizona_runtime_suspend, + arizona_runtime_resume, + NULL) +}; +EXPORT_SYMBOL_GPL(arizona_pm_ops); + +static struct mfd_cell early_devs[] = { + { .name = "arizona-ldo1" }, +}; + +static struct mfd_cell wm5102_devs[] = { + { .name = "arizona-extcon" }, + { .name = "arizona-gpio" }, + { .name = "arizona-micsupp" }, + { .name = "arizona-pwm" }, + { .name = "wm5102-codec" }, +}; + +static struct mfd_cell wm5110_devs[] = { + { .name = "arizona-extcon" }, + { .name = "arizona-gpio" }, + { .name = "arizona-micsupp" }, + { .name = "arizona-pwm" }, + { .name = "wm5110-codec" }, +}; + +int __devinit arizona_dev_init(struct arizona *arizona) +{ + struct device *dev = arizona->dev; + const char *type_name; + unsigned int reg, val; + int ret, i; + + dev_set_drvdata(arizona->dev, arizona); + mutex_init(&arizona->clk_lock); + + if (dev_get_platdata(arizona->dev)) + memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), + sizeof(arizona->pdata)); + + regcache_cache_only(arizona->regmap, true); + + switch (arizona->type) { + case WM5102: + case WM5110: + for (i = 0; i < ARRAY_SIZE(wm5102_core_supplies); i++) + arizona->core_supplies[i].supply + = wm5102_core_supplies[i]; + arizona->num_core_supplies = ARRAY_SIZE(wm5102_core_supplies); + break; + default: + dev_err(arizona->dev, "Unknown device type %d\n", + arizona->type); + return -EINVAL; + } + + ret = mfd_add_devices(arizona->dev, -1, early_devs, + ARRAY_SIZE(early_devs), NULL, 0); + if (ret != 0) { + dev_err(dev, "Failed to add early children: %d\n", ret); + return ret; + } + + ret = devm_regulator_bulk_get(dev, arizona->num_core_supplies, + arizona->core_supplies); + if (ret != 0) { + dev_err(dev, "Failed to request core supplies: %d\n", + ret); + goto err_early; + } + + arizona->dcvdd = devm_regulator_get(arizona->dev, "DCVDD"); + if (IS_ERR(arizona->dcvdd)) { + ret = PTR_ERR(arizona->dcvdd); + dev_err(dev, "Failed to request DCVDD: %d\n", ret); + goto err_early; + } + + ret = regulator_bulk_enable(arizona->num_core_supplies, + arizona->core_supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable core supplies: %d\n", + ret); + goto err_early; + } + + ret = regulator_enable(arizona->dcvdd); + if (ret != 0) { + dev_err(dev, "Failed to enable DCVDD: %d\n", ret); + goto err_enable; + } + + if (arizona->pdata.reset) { + /* Start out with /RESET low to put the chip into reset */ + ret = gpio_request_one(arizona->pdata.reset, + GPIOF_DIR_OUT | GPIOF_INIT_LOW, + "arizona /RESET"); + if (ret != 0) { + dev_err(dev, "Failed to request /RESET: %d\n", ret); + goto err_dcvdd; + } + + gpio_set_value_cansleep(arizona->pdata.reset, 1); + } + + regcache_cache_only(arizona->regmap, false); + + ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); + if (ret != 0) { + dev_err(dev, "Failed to read ID register: %d\n", ret); + goto err_reset; + } + + ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, + &arizona->rev); + if (ret != 0) { + dev_err(dev, "Failed to read revision register: %d\n", ret); + goto err_reset; + } + arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; + + switch (reg) { +#ifdef CONFIG_MFD_WM5102 + case 0x5102: + type_name = "WM5102"; + if (arizona->type != WM5102) { + dev_err(arizona->dev, "WM5102 registered as %d\n", + arizona->type); + arizona->type = WM5102; + } + ret = wm5102_patch(arizona); + break; +#endif +#ifdef CONFIG_MFD_WM5110 + case 0x5110: + type_name = "WM5110"; + if (arizona->type != WM5110) { + dev_err(arizona->dev, "WM5110 registered as %d\n", + arizona->type); + arizona->type = WM5110; + } + ret = wm5110_patch(arizona); + break; +#endif + default: + dev_err(arizona->dev, "Unknown device ID %x\n", reg); + goto err_reset; + } + + dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); + + if (ret != 0) + dev_err(arizona->dev, "Failed to apply patch: %d\n", ret); + + /* If we have a /RESET GPIO we'll already be reset */ + if (!arizona->pdata.reset) { + ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0); + if (ret != 0) { + dev_err(dev, "Failed to reset device: %d\n", ret); + goto err_reset; + } + } + + ret = arizona_wait_for_boot(arizona); + if (ret != 0) { + dev_err(arizona->dev, "Device failed initial boot: %d\n", ret); + goto err_reset; + } + + for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { + if (!arizona->pdata.gpio_defaults[i]) + continue; + + regmap_write(arizona->regmap, ARIZONA_GPIO1_CTRL + i, + arizona->pdata.gpio_defaults[i]); + } + + pm_runtime_set_autosuspend_delay(arizona->dev, 100); + pm_runtime_use_autosuspend(arizona->dev); + pm_runtime_enable(arizona->dev); + + /* Chip default */ + if (!arizona->pdata.clk32k_src) + arizona->pdata.clk32k_src = ARIZONA_32KZ_MCLK2; + + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, + ARIZONA_CLK_32K_SRC_MASK, + arizona->pdata.clk32k_src - 1); + break; + case ARIZONA_32KZ_NONE: + regmap_update_bits(arizona->regmap, ARIZONA_CLOCK_32K_1, + ARIZONA_CLK_32K_SRC_MASK, 2); + break; + default: + dev_err(arizona->dev, "Invalid 32kHz clock source: %d\n", + arizona->pdata.clk32k_src); + ret = -EINVAL; + goto err_reset; + } + + for (i = 0; i < ARIZONA_MAX_INPUT; i++) { + /* Default for both is 0 so noop with defaults */ + val = arizona->pdata.dmic_ref[i] + << ARIZONA_IN1_DMIC_SUP_SHIFT; + val |= arizona->pdata.inmode[i] << ARIZONA_IN1_MODE_SHIFT; + + regmap_update_bits(arizona->regmap, + ARIZONA_IN1L_CONTROL + (i * 8), + ARIZONA_IN1_DMIC_SUP_MASK | + ARIZONA_IN1_MODE_MASK, val); + } + + for (i = 0; i < ARIZONA_MAX_OUTPUT; i++) { + /* Default is 0 so noop with defaults */ + if (arizona->pdata.out_mono[i]) + val = ARIZONA_OUT1_MONO; + else + val = 0; + + regmap_update_bits(arizona->regmap, + ARIZONA_OUTPUT_PATH_CONFIG_1L + (i * 8), + ARIZONA_OUT1_MONO, val); + } + + for (i = 0; i < ARIZONA_MAX_PDM_SPK; i++) { + if (arizona->pdata.spk_mute[i]) + regmap_update_bits(arizona->regmap, + ARIZONA_PDM_SPK1_CTRL_1 + (i * 2), + ARIZONA_SPK1_MUTE_ENDIAN_MASK | + ARIZONA_SPK1_MUTE_SEQ1_MASK, + arizona->pdata.spk_mute[i]); + + if (arizona->pdata.spk_fmt[i]) + regmap_update_bits(arizona->regmap, + ARIZONA_PDM_SPK1_CTRL_2 + (i * 2), + ARIZONA_SPK1_FMT_MASK, + arizona->pdata.spk_fmt[i]); + } + + /* Set up for interrupts */ + ret = arizona_irq_init(arizona); + if (ret != 0) + goto err_reset; + + arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, "CLKGEN error", + arizona_clkgen_err, arizona); + arizona_request_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, "Overclocked", + arizona_overclocked, arizona); + arizona_request_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, "Underclocked", + arizona_underclocked, arizona); + + switch (arizona->type) { + case WM5102: + ret = mfd_add_devices(arizona->dev, -1, wm5102_devs, + ARRAY_SIZE(wm5102_devs), NULL, 0); + break; + case WM5110: + ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, + ARRAY_SIZE(wm5102_devs), NULL, 0); + break; + } + + if (ret != 0) { + dev_err(arizona->dev, "Failed to add subdevices: %d\n", ret); + goto err_irq; + } + +#ifdef CONFIG_PM_RUNTIME + regulator_disable(arizona->dcvdd); +#endif + + return 0; + +err_irq: + arizona_irq_exit(arizona); +err_reset: + if (arizona->pdata.reset) { + gpio_set_value_cansleep(arizona->pdata.reset, 1); + gpio_free(arizona->pdata.reset); + } +err_dcvdd: + regulator_disable(arizona->dcvdd); +err_enable: + regulator_bulk_disable(arizona->num_core_supplies, + arizona->core_supplies); +err_early: + mfd_remove_devices(dev); + return ret; +} +EXPORT_SYMBOL_GPL(arizona_dev_init); + +int __devexit arizona_dev_exit(struct arizona *arizona) +{ + mfd_remove_devices(arizona->dev); + arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona); + arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona); + arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona); + pm_runtime_disable(arizona->dev); + arizona_irq_exit(arizona); + return 0; +} +EXPORT_SYMBOL_GPL(arizona_dev_exit); diff --git a/drivers/mfd/arizona-i2c.c b/drivers/mfd/arizona-i2c.c new file mode 100644 index 00000000000..570c4b43808 --- /dev/null +++ b/drivers/mfd/arizona-i2c.c @@ -0,0 +1,97 @@ +/* + * Arizona-i2c.c -- Arizona I2C bus interface + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +#include <linux/mfd/arizona/core.h> + +#include "arizona.h" + +static __devinit int arizona_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct arizona *arizona; + const struct regmap_config *regmap_config; + int ret; + + switch (id->driver_data) { +#ifdef CONFIG_MFD_WM5102 + case WM5102: + regmap_config = &wm5102_i2c_regmap; + break; +#endif +#ifdef CONFIG_MFD_WM5110 + case WM5110: + regmap_config = &wm5110_i2c_regmap; + break; +#endif + default: + dev_err(&i2c->dev, "Unknown device type %ld\n", + id->driver_data); + return -EINVAL; + } + + arizona = devm_kzalloc(&i2c->dev, sizeof(*arizona), GFP_KERNEL); + if (arizona == NULL) + return -ENOMEM; + + arizona->regmap = devm_regmap_init_i2c(i2c, regmap_config); + if (IS_ERR(arizona->regmap)) { + ret = PTR_ERR(arizona->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + arizona->type = id->driver_data; + arizona->dev = &i2c->dev; + arizona->irq = i2c->irq; + + return arizona_dev_init(arizona); +} + +static int __devexit arizona_i2c_remove(struct i2c_client *i2c) +{ + struct arizona *arizona = dev_get_drvdata(&i2c->dev); + arizona_dev_exit(arizona); + return 0; +} + +static const struct i2c_device_id arizona_i2c_id[] = { + { "wm5102", WM5102 }, + { "wm5110", WM5110 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, arizona_i2c_id); + +static struct i2c_driver arizona_i2c_driver = { + .driver = { + .name = "arizona", + .owner = THIS_MODULE, + .pm = &arizona_pm_ops, + }, + .probe = arizona_i2c_probe, + .remove = __devexit_p(arizona_i2c_remove), + .id_table = arizona_i2c_id, +}; + +module_i2c_driver(arizona_i2c_driver); + +MODULE_DESCRIPTION("Arizona I2C bus interface"); +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c new file mode 100644 index 00000000000..98ac345f468 --- /dev/null +++ b/drivers/mfd/arizona-irq.c @@ -0,0 +1,275 @@ +/* + * Arizona interrupt support + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +#include <linux/mfd/arizona/core.h> +#include <linux/mfd/arizona/registers.h> + +#include "arizona.h" + +static int arizona_map_irq(struct arizona *arizona, int irq) +{ + int ret; + + ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq); + if (ret < 0) + ret = regmap_irq_get_virq(arizona->irq_chip, irq); + + return ret; +} + +int arizona_request_irq(struct arizona *arizona, int irq, char *name, + irq_handler_t handler, void *data) +{ + irq = arizona_map_irq(arizona, irq); + if (irq < 0) + return irq; + + return request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, + name, data); +} +EXPORT_SYMBOL_GPL(arizona_request_irq); + +void arizona_free_irq(struct arizona *arizona, int irq, void *data) +{ + irq = arizona_map_irq(arizona, irq); + if (irq < 0) + return; + + free_irq(irq, data); +} +EXPORT_SYMBOL_GPL(arizona_free_irq); + +int arizona_set_irq_wake(struct arizona *arizona, int irq, int on) +{ + irq = arizona_map_irq(arizona, irq); + if (irq < 0) + return irq; + + return irq_set_irq_wake(irq, on); +} +EXPORT_SYMBOL_GPL(arizona_set_irq_wake); + +static irqreturn_t arizona_boot_done(int irq, void *data) +{ + struct arizona *arizona = data; + + dev_dbg(arizona->dev, "Boot done\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t arizona_ctrlif_err(int irq, void *data) +{ + struct arizona *arizona = data; + + /* + * For pretty much all potential sources a register cache sync + * won't help, we've just got a software bug somewhere. + */ + dev_err(arizona->dev, "Control interface error\n"); + + return IRQ_HANDLED; +} + +static irqreturn_t arizona_irq_thread(int irq, void *data) +{ + struct arizona *arizona = data; + int i, ret; + + ret = pm_runtime_get_sync(arizona->dev); + if (ret < 0) { + dev_err(arizona->dev, "Failed to resume device: %d\n", ret); + return IRQ_NONE; + } + + /* Check both domains */ + for (i = 0; i < 2; i++) + handle_nested_irq(irq_find_mapping(arizona->virq, i)); + + pm_runtime_mark_last_busy(arizona->dev); + pm_runtime_put_autosuspend(arizona->dev); + + return IRQ_HANDLED; +} + +static void arizona_irq_enable(struct irq_data *data) +{ +} + +static void arizona_irq_disable(struct irq_data *data) +{ +} + +static struct irq_chip arizona_irq_chip = { + .name = "arizona", + .irq_disable = arizona_irq_disable, + .irq_enable = arizona_irq_enable, +}; + +static int arizona_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct regmap_irq_chip_data *data = h->host_data; + + irq_set_chip_data(virq, data); + irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_edge_irq); + irq_set_nested_thread(virq, 1); + + /* ARM needs us to explicitly flag the IRQ as valid + * and will set them noprobe when we do so. */ +#ifdef CONFIG_ARM + set_irq_flags(virq, IRQF_VALID); +#else + irq_set_noprobe(virq); +#endif + + return 0; +} + +static struct irq_domain_ops arizona_domain_ops = { + .map = arizona_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +int arizona_irq_init(struct arizona *arizona) +{ + int flags = IRQF_ONESHOT; + int ret, i; + const struct regmap_irq_chip *aod, *irq; + + switch (arizona->type) { +#ifdef CONFIG_MFD_WM5102 + case WM5102: + aod = &wm5102_aod; + irq = &wm5102_irq; + break; +#endif +#ifdef CONFIG_MFD_WM5110 + case WM5110: + aod = &wm5110_aod; + irq = &wm5110_irq; + break; +#endif + default: + BUG_ON("Unknown Arizona class device" == NULL); + return -EINVAL; + } + + if (arizona->pdata.irq_active_high) { + ret = regmap_update_bits(arizona->regmap, ARIZONA_IRQ_CTRL_1, + ARIZONA_IRQ_POL, 0); + if (ret != 0) { + dev_err(arizona->dev, "Couldn't set IRQ polarity: %d\n", + ret); + goto err; + } + + flags |= IRQF_TRIGGER_HIGH; + } else { + flags |= IRQF_TRIGGER_LOW; + } + + /* Allocate a virtual IRQ domain to distribute to the regmap domains */ + arizona->virq = irq_domain_add_linear(NULL, 2, &arizona_domain_ops, + arizona); + if (!arizona->virq) { + ret = -EINVAL; + goto err; + } + + ret = regmap_add_irq_chip(arizona->regmap, + irq_create_mapping(arizona->virq, 0), + IRQF_ONESHOT, -1, aod, + &arizona->aod_irq_chip); + if (ret != 0) { + dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); + goto err_domain; + } + + ret = regmap_add_irq_chip(arizona->regmap, + irq_create_mapping(arizona->virq, 1), + IRQF_ONESHOT, -1, irq, + &arizona->irq_chip); + if (ret != 0) { + dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret); + goto err_aod; + } + + /* Make sure the boot done IRQ is unmasked for resumes */ + i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE); + ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT, + "Boot done", arizona); + if (ret != 0) { + dev_err(arizona->dev, "Failed to request boot done %d: %d\n", + arizona->irq, ret); + goto err_boot_done; + } + + /* Handle control interface errors in the core */ + i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR); + ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT, + "Control interface error", arizona); + if (ret != 0) { + dev_err(arizona->dev, "Failed to request boot done %d: %d\n", + arizona->irq, ret); + goto err_ctrlif; + } + + ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, + flags, "arizona", arizona); + + if (ret != 0) { + dev_err(arizona->dev, "Failed to request IRQ %d: %d\n", + arizona->irq, ret); + goto err_main_irq; + } + + return 0; + +err_main_irq: + free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); +err_ctrlif: + free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); +err_boot_done: + regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1), + arizona->irq_chip); +err_aod: + regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0), + arizona->aod_irq_chip); +err_domain: +err: + return ret; +} + +int arizona_irq_exit(struct arizona *arizona) +{ + free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona); + free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); + regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1), + arizona->irq_chip); + regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0), + arizona->aod_irq_chip); + free_irq(arizona->irq, arizona); + + return 0; +} diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c new file mode 100644 index 00000000000..df2e5a8bee2 --- /dev/null +++ b/drivers/mfd/arizona-spi.c @@ -0,0 +1,97 @@ +/* + * arizona-spi.c -- Arizona SPI bus interface + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> + +#include <linux/mfd/arizona/core.h> + +#include "arizona.h" + +static int __devinit arizona_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct arizona *arizona; + const struct regmap_config *regmap_config; + int ret; + + switch (id->driver_data) { +#ifdef CONFIG_MFD_WM5102 + case WM5102: + regmap_config = &wm5102_spi_regmap; + break; +#endif +#ifdef CONFIG_MFD_WM5110 + case WM5110: + regmap_config = &wm5110_spi_regmap; + break; +#endif + default: + dev_err(&spi->dev, "Unknown device type %ld\n", + id->driver_data); + return -EINVAL; + } + + arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL); + if (arizona == NULL) + return -ENOMEM; + + arizona->regmap = devm_regmap_init_spi(spi, regmap_config); + if (IS_ERR(arizona->regmap)) { + ret = PTR_ERR(arizona->regmap); + dev_err(&spi->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + arizona->type = id->driver_data; + arizona->dev = &spi->dev; + arizona->irq = spi->irq; + + return arizona_dev_init(arizona); +} + +static int __devexit arizona_spi_remove(struct spi_device *spi) +{ + struct arizona *arizona = dev_get_drvdata(&spi->dev); + arizona_dev_exit(arizona); + return 0; +} + +static const struct spi_device_id arizona_spi_ids[] = { + { "wm5102", WM5102 }, + { "wm5110", WM5110 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, arizona_spi_ids); + +static struct spi_driver arizona_spi_driver = { + .driver = { + .name = "arizona", + .owner = THIS_MODULE, + .pm = &arizona_pm_ops, + }, + .probe = arizona_spi_probe, + .remove = __devexit_p(arizona_spi_remove), + .id_table = arizona_spi_ids, +}; + +module_spi_driver(arizona_spi_driver); + +MODULE_DESCRIPTION("Arizona SPI bus interface"); +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/arizona.h b/drivers/mfd/arizona.h new file mode 100644 index 00000000000..9798ae5da67 --- /dev/null +++ b/drivers/mfd/arizona.h @@ -0,0 +1,40 @@ +/* + * wm5102.h -- WM5102 MFD internals + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM5102_H +#define _WM5102_H + +#include <linux/regmap.h> +#include <linux/pm.h> + +struct wm_arizona; + +extern const struct regmap_config wm5102_i2c_regmap; +extern const struct regmap_config wm5102_spi_regmap; + +extern const struct regmap_config wm5110_i2c_regmap; +extern const struct regmap_config wm5110_spi_regmap; + +extern const struct dev_pm_ops arizona_pm_ops; + +extern const struct regmap_irq_chip wm5102_aod; +extern const struct regmap_irq_chip wm5102_irq; + +extern const struct regmap_irq_chip wm5110_aod; +extern const struct regmap_irq_chip wm5110_irq; + +int arizona_dev_init(struct arizona *arizona); +int arizona_dev_exit(struct arizona *arizona); +int arizona_irq_init(struct arizona *arizona); +int arizona_irq_exit(struct arizona *arizona); + +#endif diff --git a/drivers/mfd/da9052-core.c b/drivers/mfd/da9052-core.c index 1f1313c9057..2544910e1fd 100644 --- a/drivers/mfd/da9052-core.c +++ b/drivers/mfd/da9052-core.c @@ -772,7 +772,6 @@ EXPORT_SYMBOL_GPL(da9052_regmap_config); int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id) { struct da9052_pdata *pdata = da9052->dev->platform_data; - struct irq_desc *desc; int ret; mutex_init(&da9052->auxadc_lock); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 50e83dc5dc4..7040a008113 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -28,6 +28,7 @@ #include <linux/uaccess.h> #include <linux/mfd/core.h> #include <linux/mfd/dbx500-prcmu.h> +#include <linux/mfd/abx500/ab8500.h> #include <linux/regulator/db8500-prcmu.h> #include <linux/regulator/machine.h> #include <asm/hardware/gic.h> @@ -2269,10 +2270,10 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) /** * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem */ -void prcmu_ac_wake_req(void) +int prcmu_ac_wake_req(void) { u32 val; - u32 status; + int ret = 0; mutex_lock(&mb0_transfer.ac_wake_lock); @@ -2282,39 +2283,32 @@ void prcmu_ac_wake_req(void) atomic_set(&ac_wake_req_state, 1); -retry: - writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ); + /* + * Force Modem Wake-up before hostaccess_req ping-pong. + * It prevents Modem to enter in Sleep while acking the hostaccess + * request. The 31us delay has been calculated by HWI. + */ + val |= PRCM_HOSTACCESS_REQ_WAKE_REQ; + writel(val, PRCM_HOSTACCESS_REQ); + + udelay(31); + + val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ; + writel(val, PRCM_HOSTACCESS_REQ); 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__); - goto unlock_and_return; - } - - /* - * The modem can generate an AC_WAKE_ACK, and then still go to sleep. - * As a workaround, we wait, and then check that the modem is indeed - * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS - * register, which may not be the whole truth). - */ - udelay(400); - status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2)); - if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE | - PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) { - pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n", - __func__, status); - udelay(1200); - writel(val, PRCM_HOSTACCESS_REQ); - if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work, - msecs_to_jiffies(5000))) - goto retry; - pr_crit("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n", - __func__); + ret = -EFAULT; } unlock_and_return: mutex_unlock(&mb0_transfer.ac_wake_lock); + return ret; } /** @@ -2945,14 +2939,31 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { }, }; +static struct resource ab8500_resources[] = { + [0] = { + .start = IRQ_DB8500_AB8500, + .end = IRQ_DB8500_AB8500, + .flags = IORESOURCE_IRQ + } +}; + static struct mfd_cell db8500_prcmu_devs[] = { { .name = "db8500-prcmu-regulators", + .of_compatible = "stericsson,db8500-prcmu-regulator", .platform_data = &db8500_regulators, .pdata_size = sizeof(db8500_regulators), }, { .name = "cpufreq-u8500", + .of_compatible = "stericsson,cpufreq-u8500", + }, + { + .name = "ab8500-core", + .of_compatible = "stericsson,ab8500", + .num_resources = ARRAY_SIZE(ab8500_resources), + .resources = ab8500_resources, + .id = AB8500_VERSION_AB8500, }, }; @@ -2962,8 +2973,9 @@ static struct mfd_cell db8500_prcmu_devs[] = { */ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) { + struct ab8500_platform_data *ab8500_platdata = pdev->dev.platform_data; struct device_node *np = pdev->dev.of_node; - int irq = 0, err = 0; + int irq = 0, err = 0, i; if (ux500_is_svp()) return -ENODEV; @@ -2987,16 +2999,21 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) goto no_irq_return; } + for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) { + if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) { + db8500_prcmu_devs[i].platform_data = ab8500_platdata; + db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data); + } + } + if (cpu_is_u8500v20_or_later()) prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); - if (!np) { - err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, - ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); - if (err) { - pr_err("prcmu: Failed to add subdevices\n"); - return err; - } + err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs, + ARRAY_SIZE(db8500_prcmu_devs), NULL, 0); + if (err) { + pr_err("prcmu: Failed to add subdevices\n"); + return err; } pr_info("DB8500 PRCMU initialized\n"); @@ -3004,11 +3021,16 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev) no_irq_return: return err; } +static const struct of_device_id db8500_prcmu_match[] = { + { .compatible = "stericsson,db8500-prcmu"}, + { }, +}; static struct platform_driver db8500_prcmu_driver = { .driver = { .name = "db8500-prcmu", .owner = THIS_MODULE, + .of_match_table = db8500_prcmu_match, }, .probe = db8500_prcmu_probe, }; @@ -3018,7 +3040,7 @@ static int __init db8500_prcmu_init(void) return platform_driver_register(&db8500_prcmu_driver); } -arch_initcall(db8500_prcmu_init); +core_initcall(db8500_prcmu_init); MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>"); MODULE_DESCRIPTION("DB8500 PRCM Unit driver"); diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index 3a0bf91d778..23108a6e316 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -106,6 +106,7 @@ #define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) #define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1 +#define PRCM_HOSTACCESS_REQ_WAKE_REQ BIT(16) #define ARM_WAKEUP_MODEM 0x1 #define PRCM_ARM_IT1_CLR (_PRCMU_BASE + 0x48C) diff --git a/drivers/mfd/max77686-irq.c b/drivers/mfd/max77686-irq.c new file mode 100644 index 00000000000..cdc3280e2ec --- /dev/null +++ b/drivers/mfd/max77686-irq.c @@ -0,0 +1,319 @@ +/* + * max77686-irq.c - Interrupt controller support for MAX77686 + * + * Copyright (C) 2012 Samsung Electronics Co.Ltd + * Chiwoong Byun <woong.byun@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + * + * This driver is based on max8997-irq.c + */ + +#include <linux/err.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/mfd/max77686.h> +#include <linux/mfd/max77686-private.h> +#include <linux/irqdomain.h> +#include <linux/regmap.h> + +enum { + MAX77686_DEBUG_IRQ_INFO = 1 << 0, + MAX77686_DEBUG_IRQ_MASK = 1 << 1, + MAX77686_DEBUG_IRQ_INT = 1 << 2, +}; + +static int debug_mask = 0; +module_param(debug_mask, int, 0); +MODULE_PARM_DESC(debug_mask, "Set debug_mask : 0x0=off 0x1=IRQ_INFO 0x2=IRQ_MASK 0x4=IRQ_INI)"); + +static const u8 max77686_mask_reg[] = { + [PMIC_INT1] = MAX77686_REG_INT1MSK, + [PMIC_INT2] = MAX77686_REG_INT2MSK, + [RTC_INT] = MAX77686_RTC_INTM, +}; + +static struct regmap *max77686_get_regmap(struct max77686_dev *max77686, + enum max77686_irq_source src) +{ + switch (src) { + case PMIC_INT1 ... PMIC_INT2: + return max77686->regmap; + case RTC_INT: + return max77686->rtc_regmap; + default: + return ERR_PTR(-EINVAL); + } +} + +struct max77686_irq_data { + int mask; + enum max77686_irq_source group; +}; + +#define DECLARE_IRQ(idx, _group, _mask) \ + [(idx)] = { .group = (_group), .mask = (_mask) } +static const struct max77686_irq_data max77686_irqs[] = { + DECLARE_IRQ(MAX77686_PMICIRQ_PWRONF, PMIC_INT1, 1 << 0), + DECLARE_IRQ(MAX77686_PMICIRQ_PWRONR, PMIC_INT1, 1 << 1), + DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBF, PMIC_INT1, 1 << 2), + DECLARE_IRQ(MAX77686_PMICIRQ_JIGONBR, PMIC_INT1, 1 << 3), + DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBF, PMIC_INT1, 1 << 4), + DECLARE_IRQ(MAX77686_PMICIRQ_ACOKBR, PMIC_INT1, 1 << 5), + DECLARE_IRQ(MAX77686_PMICIRQ_ONKEY1S, PMIC_INT1, 1 << 6), + DECLARE_IRQ(MAX77686_PMICIRQ_MRSTB, PMIC_INT1, 1 << 7), + DECLARE_IRQ(MAX77686_PMICIRQ_140C, PMIC_INT2, 1 << 0), + DECLARE_IRQ(MAX77686_PMICIRQ_120C, PMIC_INT2, 1 << 1), + DECLARE_IRQ(MAX77686_RTCIRQ_RTC60S, RTC_INT, 1 << 0), + DECLARE_IRQ(MAX77686_RTCIRQ_RTCA1, RTC_INT, 1 << 1), + DECLARE_IRQ(MAX77686_RTCIRQ_RTCA2, RTC_INT, 1 << 2), + DECLARE_IRQ(MAX77686_RTCIRQ_SMPL, RTC_INT, 1 << 3), + DECLARE_IRQ(MAX77686_RTCIRQ_RTC1S, RTC_INT, 1 << 4), + DECLARE_IRQ(MAX77686_RTCIRQ_WTSR, RTC_INT, 1 << 5), +}; + +static void max77686_irq_lock(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s\n", __func__); + + mutex_lock(&max77686->irqlock); +} + +static void max77686_irq_sync_unlock(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + int i; + + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { + u8 mask_reg = max77686_mask_reg[i]; + struct regmap *map = max77686_get_regmap(max77686, i); + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_debug("%s: mask_reg[%d]=0x%x, cur=0x%x\n", + __func__, i, mask_reg, max77686->irq_masks_cur[i]); + + if (mask_reg == MAX77686_REG_INVALID || + IS_ERR_OR_NULL(map)) + continue; + + max77686->irq_masks_cache[i] = max77686->irq_masks_cur[i]; + + regmap_write(map, max77686_mask_reg[i], + max77686->irq_masks_cur[i]); + } + + mutex_unlock(&max77686->irqlock); +} + +static const inline struct max77686_irq_data *to_max77686_irq(int irq) +{ + struct irq_data *data = irq_get_irq_data(irq); + return &max77686_irqs[data->hwirq]; +} + +static void max77686_irq_mask(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); + + max77686->irq_masks_cur[irq_data->group] |= irq_data->mask; + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s: group=%d, cur=0x%x\n", + __func__, irq_data->group, + max77686->irq_masks_cur[irq_data->group]); +} + +static void max77686_irq_unmask(struct irq_data *data) +{ + struct max77686_dev *max77686 = irq_get_chip_data(data->irq); + const struct max77686_irq_data *irq_data = to_max77686_irq(data->irq); + + max77686->irq_masks_cur[irq_data->group] &= ~irq_data->mask; + + if (debug_mask & MAX77686_DEBUG_IRQ_MASK) + pr_info("%s: group=%d, cur=0x%x\n", + __func__, irq_data->group, + max77686->irq_masks_cur[irq_data->group]); +} + +static struct irq_chip max77686_irq_chip = { + .name = "max77686", + .irq_bus_lock = max77686_irq_lock, + .irq_bus_sync_unlock = max77686_irq_sync_unlock, + .irq_mask = max77686_irq_mask, + .irq_unmask = max77686_irq_unmask, +}; + +static irqreturn_t max77686_irq_thread(int irq, void *data) +{ + struct max77686_dev *max77686 = data; + unsigned int irq_reg[MAX77686_IRQ_GROUP_NR] = {}; + unsigned int irq_src; + int ret; + int i, cur_irq; + + ret = regmap_read(max77686->regmap, MAX77686_REG_INTSRC, &irq_src); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: irq_src=0x%x\n", __func__, irq_src); + + if (irq_src == MAX77686_IRQSRC_PMIC) { + ret = regmap_bulk_read(max77686->regmap, + MAX77686_REG_INT1, irq_reg, 2); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: int1=0x%x, int2=0x%x\n", __func__, + irq_reg[PMIC_INT1], irq_reg[PMIC_INT2]); + } + + if (irq_src & MAX77686_IRQSRC_RTC) { + ret = regmap_read(max77686->rtc_regmap, + MAX77686_RTC_INT, &irq_reg[RTC_INT]); + if (ret < 0) { + dev_err(max77686->dev, "Failed to read interrupt source: %d\n", + ret); + return IRQ_NONE; + } + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) + pr_info("%s: rtc int=0x%x\n", __func__, + irq_reg[RTC_INT]); + + } + + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) + irq_reg[i] &= ~max77686->irq_masks_cur[i]; + + for (i = 0; i < MAX77686_IRQ_NR; i++) { + if (irq_reg[max77686_irqs[i].group] & max77686_irqs[i].mask) { + cur_irq = irq_find_mapping(max77686->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); + } + } + + return IRQ_HANDLED; +} + +static int max77686_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max77686_dev *max77686 = d->host_data; + + irq_set_chip_data(irq, max77686); + irq_set_chip_and_handler(irq, &max77686_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif + return 0; +} + +static struct irq_domain_ops max77686_irq_domain_ops = { + .map = max77686_irq_domain_map, +}; + +int max77686_irq_init(struct max77686_dev *max77686) +{ + struct irq_domain *domain; + int i; + int ret; + int val; + struct regmap *map; + + mutex_init(&max77686->irqlock); + + if (max77686->irq_gpio && !max77686->irq) { + max77686->irq = gpio_to_irq(max77686->irq_gpio); + + if (debug_mask & MAX77686_DEBUG_IRQ_INT) { + ret = gpio_request(max77686->irq_gpio, "pmic_irq"); + if (ret < 0) { + dev_err(max77686->dev, + "Failed to request gpio %d with ret:" + "%d\n", max77686->irq_gpio, ret); + return IRQ_NONE; + } + + gpio_direction_input(max77686->irq_gpio); + val = gpio_get_value(max77686->irq_gpio); + gpio_free(max77686->irq_gpio); + pr_info("%s: gpio_irq=%x\n", __func__, val); + } + } + + if (!max77686->irq) { + dev_err(max77686->dev, "irq is not specified\n"); + return -ENODEV; + } + + /* Mask individual interrupt sources */ + for (i = 0; i < MAX77686_IRQ_GROUP_NR; i++) { + max77686->irq_masks_cur[i] = 0xff; + max77686->irq_masks_cache[i] = 0xff; + map = max77686_get_regmap(max77686, i); + + if (IS_ERR_OR_NULL(map)) + continue; + if (max77686_mask_reg[i] == MAX77686_REG_INVALID) + continue; + + regmap_write(map, max77686_mask_reg[i], 0xff); + } + domain = irq_domain_add_linear(NULL, MAX77686_IRQ_NR, + &max77686_irq_domain_ops, max77686); + if (!domain) { + dev_err(max77686->dev, "could not create irq domain\n"); + return -ENODEV; + } + max77686->irq_domain = domain; + + ret = request_threaded_irq(max77686->irq, NULL, max77686_irq_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "max77686-irq", max77686); + + if (ret) + dev_err(max77686->dev, "Failed to request IRQ %d: %d\n", + max77686->irq, ret); + + + if (debug_mask & MAX77686_DEBUG_IRQ_INFO) + pr_info("%s-\n", __func__); + + return 0; +} + +void max77686_irq_exit(struct max77686_dev *max77686) +{ + if (max77686->irq) + free_irq(max77686->irq, max77686); +} diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c new file mode 100644 index 00000000000..c03e12b5192 --- /dev/null +++ b/drivers/mfd/max77686.c @@ -0,0 +1,187 @@ +/* + * max77686.c - mfd core driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun <woong.byun@smasung.com> + * Jonghwa Lee <jonghwa3.lee@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + * + * This driver is based on max8997.c + */ + +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/pm_runtime.h> +#include <linux/module.h> +#include <linux/mfd/core.h> +#include <linux/mfd/max77686.h> +#include <linux/mfd/max77686-private.h> +#include <linux/err.h> + +#define I2C_ADDR_RTC (0x0C >> 1) + +static struct mfd_cell max77686_devs[] = { + { .name = "max77686-pmic", }, + { .name = "max77686-rtc", }, +}; + +static struct regmap_config max77686_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +#ifdef CONFIG_OF +static struct of_device_id __devinitdata max77686_pmic_dt_match[] = { + {.compatible = "maxim,max77686", .data = 0}, + {}, +}; + +static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device + *dev) +{ + struct max77686_platform_data *pd; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) { + dev_err(dev, "could not allocate memory for pdata\n"); + return NULL; + } + + dev->platform_data = pd; + return pd; +} +#else +static struct max77686_platform_data *max77686_i2c_parse_dt_pdata(struct device + *dev) +{ + return 0; +} +#endif + +static int max77686_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct max77686_dev *max77686 = NULL; + struct max77686_platform_data *pdata = i2c->dev.platform_data; + unsigned int data; + int ret = 0; + + if (i2c->dev.of_node) + pdata = max77686_i2c_parse_dt_pdata(&i2c->dev); + + if (!pdata) { + ret = -EIO; + dev_err(&i2c->dev, "No platform data found.\n"); + goto err; + } + + max77686 = kzalloc(sizeof(struct max77686_dev), GFP_KERNEL); + if (max77686 == NULL) + return -ENOMEM; + + max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); + if (IS_ERR(max77686->regmap)) { + ret = PTR_ERR(max77686->regmap); + dev_err(max77686->dev, "Failed to allocate register map: %d\n", + ret); + kfree(max77686); + return ret; + } + + i2c_set_clientdata(i2c, max77686); + max77686->dev = &i2c->dev; + max77686->i2c = i2c; + max77686->type = id->driver_data; + + max77686->wakeup = pdata->wakeup; + max77686->irq_gpio = pdata->irq_gpio; + max77686->irq = i2c->irq; + + if (regmap_read(max77686->regmap, + MAX77686_REG_DEVICE_ID, &data) < 0) { + dev_err(max77686->dev, + "device not found on this channel (this is not an error)\n"); + ret = -ENODEV; + goto err; + } else + dev_info(max77686->dev, "device found\n"); + + max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC); + i2c_set_clientdata(max77686->rtc, max77686); + + max77686_irq_init(max77686); + + ret = mfd_add_devices(max77686->dev, -1, max77686_devs, + ARRAY_SIZE(max77686_devs), NULL, 0); + + if (ret < 0) + goto err_mfd; + + return ret; + +err_mfd: + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); +err: + kfree(max77686); + return ret; +} + +static int max77686_i2c_remove(struct i2c_client *i2c) +{ + struct max77686_dev *max77686 = i2c_get_clientdata(i2c); + + mfd_remove_devices(max77686->dev); + i2c_unregister_device(max77686->rtc); + kfree(max77686); + + return 0; +} + +static const struct i2c_device_id max77686_i2c_id[] = { + { "max77686", TYPE_MAX77686 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max77686_i2c_id); + +static struct i2c_driver max77686_i2c_driver = { + .driver = { + .name = "max77686", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max77686_pmic_dt_match), + }, + .probe = max77686_i2c_probe, + .remove = max77686_i2c_remove, + .id_table = max77686_i2c_id, +}; + +static int __init max77686_i2c_init(void) +{ + return i2c_add_driver(&max77686_i2c_driver); +} +/* init early so consumer devices can complete system boot */ +subsys_initcall(max77686_i2c_init); + +static void __exit max77686_i2c_exit(void) +{ + i2c_del_driver(&max77686_i2c_driver); +} +module_exit(max77686_i2c_exit); + +MODULE_DESCRIPTION("MAXIM 77686 multi-function core driver"); +MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index e9e4278722f..a1811cb50ec 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c @@ -138,8 +138,6 @@ static int max77693_i2c_probe(struct i2c_client *i2c, max77693->wakeup = pdata->wakeup; - mutex_init(&max77693->iolock); - if (max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, ®_data) < 0) { dev_err(max77693->dev, "device not found on this channel\n"); @@ -156,7 +154,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, ret = max77693_irq_init(max77693); if (ret < 0) - goto err_mfd; + goto err_irq; pm_runtime_set_active(max77693->dev); @@ -170,11 +168,11 @@ static int max77693_i2c_probe(struct i2c_client *i2c, return ret; err_mfd: + max77693_irq_exit(max77693); +err_irq: i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); err_regmap: - kfree(max77693); - return ret; } @@ -183,6 +181,7 @@ static int max77693_i2c_remove(struct i2c_client *i2c) struct max77693_dev *max77693 = i2c_get_clientdata(i2c); mfd_remove_devices(max77693->dev); + max77693_irq_exit(max77693); i2c_unregister_device(max77693->muic); i2c_unregister_device(max77693->haptic); @@ -215,7 +214,7 @@ static int max77693_resume(struct device *dev) return max77693_irq_resume(max77693); } -const struct dev_pm_ops max77693_pm = { +static const struct dev_pm_ops max77693_pm = { .suspend = max77693_suspend, .resume = max77693_resume, }; diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index ca881efedf7..825a7f06d9b 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -75,9 +75,9 @@ static struct mfd_cell power_devs[] = { static struct resource rtc_resources[] = { { .name = "max8925-rtc", - .start = MAX8925_RTC_IRQ, - .end = MAX8925_RTC_IRQ_MASK, - .flags = IORESOURCE_IO, + .start = MAX8925_IRQ_RTC_ALARM0, + .end = MAX8925_IRQ_RTC_ALARM0, + .flags = IORESOURCE_IRQ, }, }; @@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip, ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], ARRAY_SIZE(rtc_devs), - &rtc_resources[0], 0); + &rtc_resources[0], chip->irq_base); if (ret < 0) { dev_err(chip->dev, "Failed to add rtc subdev\n"); goto out; diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c index 09274cf7c33..43fa61413e9 100644 --- a/drivers/mfd/max8997-irq.c +++ b/drivers/mfd/max8997-irq.c @@ -142,7 +142,8 @@ static void max8997_irq_sync_unlock(struct irq_data *data) static const inline struct max8997_irq_data * irq_to_max8997_irq(struct max8997_dev *max8997, int irq) { - return &max8997_irqs[irq - max8997->irq_base]; + struct irq_data *data = irq_get_irq_data(irq); + return &max8997_irqs[data->hwirq]; } static void max8997_irq_mask(struct irq_data *data) @@ -182,7 +183,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {}; u8 irq_src; int ret; - int i; + int i, cur_irq; ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src); if (ret < 0) { @@ -269,8 +270,11 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) /* Report */ for (i = 0; i < MAX8997_IRQ_NR; i++) { - if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) - handle_nested_irq(max8997->irq_base + i); + if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask) { + cur_irq = irq_find_mapping(max8997->irq_domain, i); + if (cur_irq) + handle_nested_irq(cur_irq); + } } return IRQ_HANDLED; @@ -278,26 +282,40 @@ static irqreturn_t max8997_irq_thread(int irq, void *data) int max8997_irq_resume(struct max8997_dev *max8997) { - if (max8997->irq && max8997->irq_base) - max8997_irq_thread(max8997->irq_base, max8997); + if (max8997->irq && max8997->irq_domain) + max8997_irq_thread(0, max8997); + return 0; +} + +static int max8997_irq_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + struct max8997_dev *max8997 = d->host_data; + + irq_set_chip_data(irq, max8997); + irq_set_chip_and_handler(irq, &max8997_irq_chip, handle_edge_irq); + irq_set_nested_thread(irq, 1); +#ifdef CONFIG_ARM + set_irq_flags(irq, IRQF_VALID); +#else + irq_set_noprobe(irq); +#endif return 0; } +static struct irq_domain_ops max8997_irq_domain_ops = { + .map = max8997_irq_domain_map, +}; + int max8997_irq_init(struct max8997_dev *max8997) { + struct irq_domain *domain; int i; - int cur_irq; int ret; u8 val; if (!max8997->irq) { dev_warn(max8997->dev, "No interrupt specified.\n"); - max8997->irq_base = 0; - return 0; - } - - if (!max8997->irq_base) { - dev_err(max8997->dev, "No interrupt base specified.\n"); return 0; } @@ -327,19 +345,13 @@ int max8997_irq_init(struct max8997_dev *max8997) true : false; } - /* Register with genirq */ - for (i = 0; i < MAX8997_IRQ_NR; i++) { - cur_irq = i + max8997->irq_base; - irq_set_chip_data(cur_irq, max8997); - irq_set_chip_and_handler(cur_irq, &max8997_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif + domain = irq_domain_add_linear(NULL, MAX8997_IRQ_NR, + &max8997_irq_domain_ops, max8997); + if (!domain) { + dev_err(max8997->dev, "could not create irq domain\n"); + return -ENODEV; } + max8997->irq_domain = domain; ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index cb83a7ab53e..10b629c245b 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c @@ -143,7 +143,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c, if (!pdata) goto err; - max8997->irq_base = pdata->irq_base; max8997->ono = pdata->ono; mutex_init(&max8997->iolock); @@ -206,7 +205,7 @@ static const struct i2c_device_id max8997_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, max8998_i2c_id); -u8 max8997_dumpaddr_pmic[] = { +static u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_INT1MSK, MAX8997_REG_INT2MSK, MAX8997_REG_INT3MSK, @@ -331,7 +330,7 @@ u8 max8997_dumpaddr_pmic[] = { MAX8997_REG_DVSOKTIMER5, }; -u8 max8997_dumpaddr_muic[] = { +static u8 max8997_dumpaddr_muic[] = { MAX8997_MUIC_REG_INTMASK1, MAX8997_MUIC_REG_INTMASK2, MAX8997_MUIC_REG_INTMASK3, @@ -341,7 +340,7 @@ u8 max8997_dumpaddr_muic[] = { MAX8997_MUIC_REG_CONTROL3, }; -u8 max8997_dumpaddr_haptic[] = { +static u8 max8997_dumpaddr_haptic[] = { MAX8997_HAPTIC_REG_CONF1, MAX8997_HAPTIC_REG_CONF2, MAX8997_HAPTIC_REG_DRVCONF, @@ -423,7 +422,7 @@ static int max8997_resume(struct device *dev) return max8997_irq_resume(max8997); } -const struct dev_pm_ops max8997_pm = { +static const struct dev_pm_ops max8997_pm = { .suspend = max8997_suspend, .resume = max8997_resume, .freeze = max8997_freeze, diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index f0ea3b8b3e4..b801dc72f04 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c @@ -723,10 +723,6 @@ void mc13xxx_common_cleanup(struct mc13xxx *mc13xxx) free_irq(mc13xxx->irq, mc13xxx); mfd_remove_devices(mc13xxx->dev); - - regmap_exit(mc13xxx->regmap); - - kfree(mc13xxx); } EXPORT_SYMBOL_GPL(mc13xxx_common_cleanup); diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index d22501dad6a..9d18dde3cd2 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c @@ -53,17 +53,11 @@ static struct regmap_config mc13xxx_regmap_i2c_config = { static int mc13xxx_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct of_device_id *of_id; - struct i2c_driver *idrv = to_i2c_driver(client->dev.driver); struct mc13xxx *mc13xxx; struct mc13xxx_platform_data *pdata = dev_get_platdata(&client->dev); int ret; - of_id = of_match_device(mc13xxx_dt_ids, &client->dev); - if (of_id) - idrv->id_table = (const struct i2c_device_id*) of_id->data; - - mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); + mc13xxx = devm_kzalloc(&client->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; @@ -72,13 +66,13 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, mc13xxx->dev = &client->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init_i2c(client, &mc13xxx_regmap_i2c_config); + mc13xxx->regmap = devm_regmap_init_i2c(client, + &mc13xxx_regmap_i2c_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", ret); dev_set_drvdata(&client->dev, NULL); - kfree(mc13xxx); return ret; } diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 03df422feb7..0bdb43a0aff 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -119,17 +119,11 @@ static struct regmap_bus regmap_mc13xxx_bus = { static int mc13xxx_spi_probe(struct spi_device *spi) { - const struct of_device_id *of_id; - struct spi_driver *sdrv = to_spi_driver(spi->dev.driver); struct mc13xxx *mc13xxx; struct mc13xxx_platform_data *pdata = dev_get_platdata(&spi->dev); int ret; - of_id = of_match_device(mc13xxx_dt_ids, &spi->dev); - if (of_id) - sdrv->id_table = &mc13xxx_device_id[(enum mc13xxx_id) of_id->data]; - - mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); + mc13xxx = devm_kzalloc(&spi->dev, sizeof(*mc13xxx), GFP_KERNEL); if (!mc13xxx) return -ENOMEM; @@ -139,15 +133,14 @@ static int mc13xxx_spi_probe(struct spi_device *spi) mc13xxx->dev = &spi->dev; mutex_init(&mc13xxx->lock); - mc13xxx->regmap = regmap_init(&spi->dev, ®map_mc13xxx_bus, &spi->dev, - &mc13xxx_regmap_spi_config); - + mc13xxx->regmap = devm_regmap_init(&spi->dev, ®map_mc13xxx_bus, + &spi->dev, + &mc13xxx_regmap_spi_config); if (IS_ERR(mc13xxx->regmap)) { ret = PTR_ERR(mc13xxx->regmap); dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n", ret); dev_set_drvdata(&spi->dev, NULL); - kfree(mc13xxx); return ret; } diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index ffc3d48676a..0c3a01cde2f 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -18,6 +18,8 @@ #include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/irqdomain.h> +#include <linux/of.h> int mfd_cell_enable(struct platform_device *pdev) { @@ -76,6 +78,8 @@ static int mfd_add_device(struct device *parent, int id, { struct resource *res; struct platform_device *pdev; + struct device_node *np = NULL; + struct irq_domain *domain = NULL; int ret = -ENOMEM; int r; @@ -89,6 +93,16 @@ static int mfd_add_device(struct device *parent, int id, pdev->dev.parent = parent; + if (parent->of_node && cell->of_compatible) { + for_each_child_of_node(parent->of_node, np) { + if (of_device_is_compatible(np, cell->of_compatible)) { + pdev->dev.of_node = np; + domain = irq_find_host(parent->of_node); + break; + } + } + } + if (cell->pdata_size) { ret = platform_device_add_data(pdev, cell->platform_data, cell->pdata_size); @@ -112,10 +126,18 @@ static int mfd_add_device(struct device *parent, int id, res[r].end = mem_base->start + cell->resources[r].end; } else if (cell->resources[r].flags & IORESOURCE_IRQ) { - res[r].start = irq_base + - cell->resources[r].start; - res[r].end = irq_base + - cell->resources[r].end; + if (domain) { + /* Unable to create mappings for IRQ ranges. */ + WARN_ON(cell->resources[r].start != + cell->resources[r].end); + res[r].start = res[r].end = irq_create_mapping( + domain, cell->resources[r].start); + } else { + res[r].start = irq_base + + cell->resources[r].start; + res[r].end = irq_base + + cell->resources[r].end; + } } else { res[r].parent = cell->resources[r].parent; res[r].start = cell->resources[r].start; diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 29c122bf28e..45ce1fb5a54 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -253,8 +253,13 @@ static int __devinit pcf50633_probe(struct i2c_client *client, } pdev->dev.parent = pcf->dev; - platform_device_add_data(pdev, &pdata->reg_init_data[i], - sizeof(pdata->reg_init_data[i])); + if (platform_device_add_data(pdev, &pdata->reg_init_data[i], + sizeof(pdata->reg_init_data[i])) < 0) { + platform_device_put(pdev); + dev_err(pcf->dev, "Out of memory for regulator parameters %d\n", + i); + continue; + } pcf->regulator_pdev[i] = pdev; platform_device_add(pdev); diff --git a/drivers/mfd/s5m-core.c b/drivers/mfd/s5m-core.c deleted file mode 100644 index dd170307e60..00000000000 --- a/drivers/mfd/s5m-core.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * s5m87xx.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/pm_runtime.h> -#include <linux/mutex.h> -#include <linux/mfd/core.h> -#include <linux/mfd/s5m87xx/s5m-core.h> -#include <linux/mfd/s5m87xx/s5m-pmic.h> -#include <linux/mfd/s5m87xx/s5m-rtc.h> -#include <linux/regmap.h> - -static struct mfd_cell s5m8751_devs[] = { - { - .name = "s5m8751-pmic", - }, { - .name = "s5m-charger", - }, { - .name = "s5m8751-codec", - }, -}; - -static struct mfd_cell s5m8763_devs[] = { - { - .name = "s5m8763-pmic", - }, { - .name = "s5m-rtc", - }, { - .name = "s5m-charger", - }, -}; - -static struct mfd_cell s5m8767_devs[] = { - { - .name = "s5m8767-pmic", - }, { - .name = "s5m-rtc", - }, -}; - -int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, void *dest) -{ - return regmap_read(s5m87xx->regmap, reg, dest); -} -EXPORT_SYMBOL_GPL(s5m_reg_read); - -int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) -{ - return regmap_bulk_read(s5m87xx->regmap, reg, buf, count); -} -EXPORT_SYMBOL_GPL(s5m_bulk_read); - -int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value) -{ - return regmap_write(s5m87xx->regmap, reg, value); -} -EXPORT_SYMBOL_GPL(s5m_reg_write); - -int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf) -{ - return regmap_raw_write(s5m87xx->regmap, reg, buf, count); -} -EXPORT_SYMBOL_GPL(s5m_bulk_write); - -int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask) -{ - return regmap_update_bits(s5m87xx->regmap, reg, mask, val); -} -EXPORT_SYMBOL_GPL(s5m_reg_update); - -static struct regmap_config s5m_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - -static int s5m87xx_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct s5m_platform_data *pdata = i2c->dev.platform_data; - struct s5m87xx_dev *s5m87xx; - int ret; - - s5m87xx = devm_kzalloc(&i2c->dev, sizeof(struct s5m87xx_dev), - GFP_KERNEL); - if (s5m87xx == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, s5m87xx); - s5m87xx->dev = &i2c->dev; - s5m87xx->i2c = i2c; - s5m87xx->irq = i2c->irq; - s5m87xx->type = id->driver_data; - - if (pdata) { - s5m87xx->device_type = pdata->device_type; - s5m87xx->ono = pdata->ono; - s5m87xx->irq_base = pdata->irq_base; - s5m87xx->wakeup = pdata->wakeup; - } - - s5m87xx->regmap = devm_regmap_init_i2c(i2c, &s5m_regmap_config); - if (IS_ERR(s5m87xx->regmap)) { - ret = PTR_ERR(s5m87xx->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", - ret); - return ret; - } - - s5m87xx->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); - i2c_set_clientdata(s5m87xx->rtc, s5m87xx); - - if (pdata && pdata->cfg_pmic_irq) - pdata->cfg_pmic_irq(); - - s5m_irq_init(s5m87xx); - - pm_runtime_set_active(s5m87xx->dev); - - switch (s5m87xx->device_type) { - case S5M8751X: - ret = mfd_add_devices(s5m87xx->dev, -1, s5m8751_devs, - ARRAY_SIZE(s5m8751_devs), NULL, 0); - break; - case S5M8763X: - ret = mfd_add_devices(s5m87xx->dev, -1, s5m8763_devs, - ARRAY_SIZE(s5m8763_devs), NULL, 0); - break; - case S5M8767X: - ret = mfd_add_devices(s5m87xx->dev, -1, s5m8767_devs, - ARRAY_SIZE(s5m8767_devs), NULL, 0); - break; - default: - /* If this happens the probe function is problem */ - BUG(); - } - - if (ret < 0) - goto err; - - return ret; - -err: - mfd_remove_devices(s5m87xx->dev); - s5m_irq_exit(s5m87xx); - i2c_unregister_device(s5m87xx->rtc); - return ret; -} - -static int s5m87xx_i2c_remove(struct i2c_client *i2c) -{ - struct s5m87xx_dev *s5m87xx = i2c_get_clientdata(i2c); - - mfd_remove_devices(s5m87xx->dev); - s5m_irq_exit(s5m87xx); - i2c_unregister_device(s5m87xx->rtc); - return 0; -} - -static const struct i2c_device_id s5m87xx_i2c_id[] = { - { "s5m87xx", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, s5m87xx_i2c_id); - -static struct i2c_driver s5m87xx_i2c_driver = { - .driver = { - .name = "s5m87xx", - .owner = THIS_MODULE, - }, - .probe = s5m87xx_i2c_probe, - .remove = s5m87xx_i2c_remove, - .id_table = s5m87xx_i2c_id, -}; - -static int __init s5m87xx_i2c_init(void) -{ - return i2c_add_driver(&s5m87xx_i2c_driver); -} - -subsys_initcall(s5m87xx_i2c_init); - -static void __exit s5m87xx_i2c_exit(void) -{ - i2c_del_driver(&s5m87xx_i2c_driver); -} -module_exit(s5m87xx_i2c_exit); - -MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); -MODULE_DESCRIPTION("Core support for the S5M MFD"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/s5m-irq.c b/drivers/mfd/s5m-irq.c deleted file mode 100644 index 0236676085c..00000000000 --- a/drivers/mfd/s5m-irq.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * s5m-irq.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/mfd/s5m87xx/s5m-core.h> - -struct s5m_irq_data { - int reg; - int mask; -}; - -static struct s5m_irq_data s5m8767_irqs[] = { - [S5M8767_IRQ_PWRR] = { - .reg = 1, - .mask = S5M8767_IRQ_PWRR_MASK, - }, - [S5M8767_IRQ_PWRF] = { - .reg = 1, - .mask = S5M8767_IRQ_PWRF_MASK, - }, - [S5M8767_IRQ_PWR1S] = { - .reg = 1, - .mask = S5M8767_IRQ_PWR1S_MASK, - }, - [S5M8767_IRQ_JIGR] = { - .reg = 1, - .mask = S5M8767_IRQ_JIGR_MASK, - }, - [S5M8767_IRQ_JIGF] = { - .reg = 1, - .mask = S5M8767_IRQ_JIGF_MASK, - }, - [S5M8767_IRQ_LOWBAT2] = { - .reg = 1, - .mask = S5M8767_IRQ_LOWBAT2_MASK, - }, - [S5M8767_IRQ_LOWBAT1] = { - .reg = 1, - .mask = S5M8767_IRQ_LOWBAT1_MASK, - }, - [S5M8767_IRQ_MRB] = { - .reg = 2, - .mask = S5M8767_IRQ_MRB_MASK, - }, - [S5M8767_IRQ_DVSOK2] = { - .reg = 2, - .mask = S5M8767_IRQ_DVSOK2_MASK, - }, - [S5M8767_IRQ_DVSOK3] = { - .reg = 2, - .mask = S5M8767_IRQ_DVSOK3_MASK, - }, - [S5M8767_IRQ_DVSOK4] = { - .reg = 2, - .mask = S5M8767_IRQ_DVSOK4_MASK, - }, - [S5M8767_IRQ_RTC60S] = { - .reg = 3, - .mask = S5M8767_IRQ_RTC60S_MASK, - }, - [S5M8767_IRQ_RTCA1] = { - .reg = 3, - .mask = S5M8767_IRQ_RTCA1_MASK, - }, - [S5M8767_IRQ_RTCA2] = { - .reg = 3, - .mask = S5M8767_IRQ_RTCA2_MASK, - }, - [S5M8767_IRQ_SMPL] = { - .reg = 3, - .mask = S5M8767_IRQ_SMPL_MASK, - }, - [S5M8767_IRQ_RTC1S] = { - .reg = 3, - .mask = S5M8767_IRQ_RTC1S_MASK, - }, - [S5M8767_IRQ_WTSR] = { - .reg = 3, - .mask = S5M8767_IRQ_WTSR_MASK, - }, -}; - -static struct s5m_irq_data s5m8763_irqs[] = { - [S5M8763_IRQ_DCINF] = { - .reg = 1, - .mask = S5M8763_IRQ_DCINF_MASK, - }, - [S5M8763_IRQ_DCINR] = { - .reg = 1, - .mask = S5M8763_IRQ_DCINR_MASK, - }, - [S5M8763_IRQ_JIGF] = { - .reg = 1, - .mask = S5M8763_IRQ_JIGF_MASK, - }, - [S5M8763_IRQ_JIGR] = { - .reg = 1, - .mask = S5M8763_IRQ_JIGR_MASK, - }, - [S5M8763_IRQ_PWRONF] = { - .reg = 1, - .mask = S5M8763_IRQ_PWRONF_MASK, - }, - [S5M8763_IRQ_PWRONR] = { - .reg = 1, - .mask = S5M8763_IRQ_PWRONR_MASK, - }, - [S5M8763_IRQ_WTSREVNT] = { - .reg = 2, - .mask = S5M8763_IRQ_WTSREVNT_MASK, - }, - [S5M8763_IRQ_SMPLEVNT] = { - .reg = 2, - .mask = S5M8763_IRQ_SMPLEVNT_MASK, - }, - [S5M8763_IRQ_ALARM1] = { - .reg = 2, - .mask = S5M8763_IRQ_ALARM1_MASK, - }, - [S5M8763_IRQ_ALARM0] = { - .reg = 2, - .mask = S5M8763_IRQ_ALARM0_MASK, - }, - [S5M8763_IRQ_ONKEY1S] = { - .reg = 3, - .mask = S5M8763_IRQ_ONKEY1S_MASK, - }, - [S5M8763_IRQ_TOPOFFR] = { - .reg = 3, - .mask = S5M8763_IRQ_TOPOFFR_MASK, - }, - [S5M8763_IRQ_DCINOVPR] = { - .reg = 3, - .mask = S5M8763_IRQ_DCINOVPR_MASK, - }, - [S5M8763_IRQ_CHGRSTF] = { - .reg = 3, - .mask = S5M8763_IRQ_CHGRSTF_MASK, - }, - [S5M8763_IRQ_DONER] = { - .reg = 3, - .mask = S5M8763_IRQ_DONER_MASK, - }, - [S5M8763_IRQ_CHGFAULT] = { - .reg = 3, - .mask = S5M8763_IRQ_CHGFAULT_MASK, - }, - [S5M8763_IRQ_LOBAT1] = { - .reg = 4, - .mask = S5M8763_IRQ_LOBAT1_MASK, - }, - [S5M8763_IRQ_LOBAT2] = { - .reg = 4, - .mask = S5M8763_IRQ_LOBAT2_MASK, - }, -}; - -static inline struct s5m_irq_data * -irq_to_s5m8767_irq(struct s5m87xx_dev *s5m87xx, int irq) -{ - return &s5m8767_irqs[irq - s5m87xx->irq_base]; -} - -static void s5m8767_irq_lock(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - - mutex_lock(&s5m87xx->irqlock); -} - -static void s5m8767_irq_sync_unlock(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - int i; - - for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) { - if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) { - s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i]; - s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i, - s5m87xx->irq_masks_cur[i]); - } - } - - mutex_unlock(&s5m87xx->irqlock); -} - -static void s5m8767_irq_unmask(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx, - data->irq); - - s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; -} - -static void s5m8767_irq_mask(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx, - data->irq); - - s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; -} - -static struct irq_chip s5m8767_irq_chip = { - .name = "s5m8767", - .irq_bus_lock = s5m8767_irq_lock, - .irq_bus_sync_unlock = s5m8767_irq_sync_unlock, - .irq_mask = s5m8767_irq_mask, - .irq_unmask = s5m8767_irq_unmask, -}; - -static inline struct s5m_irq_data * -irq_to_s5m8763_irq(struct s5m87xx_dev *s5m87xx, int irq) -{ - return &s5m8763_irqs[irq - s5m87xx->irq_base]; -} - -static void s5m8763_irq_lock(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - - mutex_lock(&s5m87xx->irqlock); -} - -static void s5m8763_irq_sync_unlock(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - int i; - - for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) { - if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) { - s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i]; - s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i, - s5m87xx->irq_masks_cur[i]); - } - } - - mutex_unlock(&s5m87xx->irqlock); -} - -static void s5m8763_irq_unmask(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx, - data->irq); - - s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; -} - -static void s5m8763_irq_mask(struct irq_data *data) -{ - struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data); - struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx, - data->irq); - - s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; -} - -static struct irq_chip s5m8763_irq_chip = { - .name = "s5m8763", - .irq_bus_lock = s5m8763_irq_lock, - .irq_bus_sync_unlock = s5m8763_irq_sync_unlock, - .irq_mask = s5m8763_irq_mask, - .irq_unmask = s5m8763_irq_unmask, -}; - - -static irqreturn_t s5m8767_irq_thread(int irq, void *data) -{ - struct s5m87xx_dev *s5m87xx = data; - u8 irq_reg[NUM_IRQ_REGS-1]; - int ret; - int i; - - - ret = s5m_bulk_read(s5m87xx, S5M8767_REG_INT1, - NUM_IRQ_REGS - 1, irq_reg); - if (ret < 0) { - dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n", - ret); - return IRQ_NONE; - } - - for (i = 0; i < NUM_IRQ_REGS - 1; i++) - irq_reg[i] &= ~s5m87xx->irq_masks_cur[i]; - - for (i = 0; i < S5M8767_IRQ_NR; i++) { - if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask) - handle_nested_irq(s5m87xx->irq_base + i); - } - - return IRQ_HANDLED; -} - -static irqreturn_t s5m8763_irq_thread(int irq, void *data) -{ - struct s5m87xx_dev *s5m87xx = data; - u8 irq_reg[NUM_IRQ_REGS]; - int ret; - int i; - - ret = s5m_bulk_read(s5m87xx, S5M8763_REG_IRQ1, - NUM_IRQ_REGS, irq_reg); - if (ret < 0) { - dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n", - ret); - return IRQ_NONE; - } - - for (i = 0; i < NUM_IRQ_REGS; i++) - irq_reg[i] &= ~s5m87xx->irq_masks_cur[i]; - - for (i = 0; i < S5M8763_IRQ_NR; i++) { - if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask) - handle_nested_irq(s5m87xx->irq_base + i); - } - - return IRQ_HANDLED; -} - -int s5m_irq_resume(struct s5m87xx_dev *s5m87xx) -{ - if (s5m87xx->irq && s5m87xx->irq_base){ - switch (s5m87xx->device_type) { - case S5M8763X: - s5m8763_irq_thread(s5m87xx->irq_base, s5m87xx); - break; - case S5M8767X: - s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx); - break; - default: - dev_err(s5m87xx->dev, - "Unknown device type %d\n", - s5m87xx->device_type); - return -EINVAL; - - } - } - return 0; -} - -int s5m_irq_init(struct s5m87xx_dev *s5m87xx) -{ - int i; - int cur_irq; - int ret = 0; - int type = s5m87xx->device_type; - - if (!s5m87xx->irq) { - dev_warn(s5m87xx->dev, - "No interrupt specified, no interrupts\n"); - s5m87xx->irq_base = 0; - return 0; - } - - if (!s5m87xx->irq_base) { - dev_err(s5m87xx->dev, - "No interrupt base specified, no interrupts\n"); - return 0; - } - - mutex_init(&s5m87xx->irqlock); - - switch (type) { - case S5M8763X: - for (i = 0; i < NUM_IRQ_REGS; i++) { - s5m87xx->irq_masks_cur[i] = 0xff; - s5m87xx->irq_masks_cache[i] = 0xff; - s5m_reg_write(s5m87xx, S5M8763_REG_IRQM1 + i, - 0xff); - } - - s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM1, 0xff); - s5m_reg_write(s5m87xx, S5M8763_REG_STATUSM2, 0xff); - - for (i = 0; i < S5M8763_IRQ_NR; i++) { - cur_irq = i + s5m87xx->irq_base; - irq_set_chip_data(cur_irq, s5m87xx); - irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif - } - - ret = request_threaded_irq(s5m87xx->irq, NULL, - s5m8763_irq_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "s5m87xx-irq", s5m87xx); - if (ret) { - dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n", - s5m87xx->irq, ret); - return ret; - } - break; - case S5M8767X: - for (i = 0; i < NUM_IRQ_REGS - 1; i++) { - s5m87xx->irq_masks_cur[i] = 0xff; - s5m87xx->irq_masks_cache[i] = 0xff; - s5m_reg_write(s5m87xx, S5M8767_REG_INT1M + i, - 0xff); - } - for (i = 0; i < S5M8767_IRQ_NR; i++) { - cur_irq = i + s5m87xx->irq_base; - irq_set_chip_data(cur_irq, s5m87xx); - if (ret) { - dev_err(s5m87xx->dev, - "Failed to irq_set_chip_data %d: %d\n", - s5m87xx->irq, ret); - return ret; - } - - irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); -#ifdef CONFIG_ARM - set_irq_flags(cur_irq, IRQF_VALID); -#else - irq_set_noprobe(cur_irq); -#endif - } - - ret = request_threaded_irq(s5m87xx->irq, NULL, - s5m8767_irq_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "s5m87xx-irq", s5m87xx); - if (ret) { - dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n", - s5m87xx->irq, ret); - return ret; - } - break; - default: - dev_err(s5m87xx->dev, - "Unknown device type %d\n", s5m87xx->device_type); - return -EINVAL; - } - - if (!s5m87xx->ono) - return 0; - - switch (type) { - case S5M8763X: - ret = request_threaded_irq(s5m87xx->ono, NULL, - s5m8763_irq_thread, - IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | - IRQF_ONESHOT, "s5m87xx-ono", - s5m87xx); - break; - case S5M8767X: - ret = request_threaded_irq(s5m87xx->ono, NULL, - s5m8767_irq_thread, - IRQF_TRIGGER_FALLING | - IRQF_TRIGGER_RISING | - IRQF_ONESHOT, "s5m87xx-ono", s5m87xx); - break; - default: - ret = -EINVAL; - break; - } - - if (ret) { - dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n", - s5m87xx->ono, ret); - return ret; - } - - return 0; -} - -void s5m_irq_exit(struct s5m87xx_dev *s5m87xx) -{ - if (s5m87xx->ono) - free_irq(s5m87xx->ono, s5m87xx); - - if (s5m87xx->irq) - free_irq(s5m87xx->irq, s5m87xx); -} diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c new file mode 100644 index 00000000000..2988efde11e --- /dev/null +++ b/drivers/mfd/sec-core.c @@ -0,0 +1,216 @@ +/* + * sec-core.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/pm_runtime.h> +#include <linux/mutex.h> +#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/regmap.h> + +static struct mfd_cell s5m8751_devs[] = { + { + .name = "s5m8751-pmic", + }, { + .name = "s5m-charger", + }, { + .name = "s5m8751-codec", + }, +}; + +static struct mfd_cell s5m8763_devs[] = { + { + .name = "s5m8763-pmic", + }, { + .name = "s5m-rtc", + }, { + .name = "s5m-charger", + }, +}; + +static struct mfd_cell s5m8767_devs[] = { + { + .name = "s5m8767-pmic", + }, { + .name = "s5m-rtc", + }, +}; + +static struct mfd_cell s2mps11_devs[] = { + { + .name = "s2mps11-pmic", + }, +}; + +int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) +{ + return regmap_read(sec_pmic->regmap, reg, dest); +} +EXPORT_SYMBOL_GPL(sec_reg_read); + +int sec_bulk_read(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf) +{ + return regmap_bulk_read(sec_pmic->regmap, reg, buf, count); +} +EXPORT_SYMBOL_GPL(sec_bulk_read); + +int sec_reg_write(struct sec_pmic_dev *sec_pmic, u8 reg, u8 value) +{ + return regmap_write(sec_pmic->regmap, reg, value); +} +EXPORT_SYMBOL_GPL(sec_reg_write); + +int sec_bulk_write(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf) +{ + return regmap_raw_write(sec_pmic->regmap, reg, buf, count); +} +EXPORT_SYMBOL_GPL(sec_bulk_write); + +int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask) +{ + return regmap_update_bits(sec_pmic->regmap, reg, mask, val); +} +EXPORT_SYMBOL_GPL(sec_reg_update); + +static struct regmap_config sec_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int sec_pmic_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct sec_platform_data *pdata = i2c->dev.platform_data; + struct sec_pmic_dev *sec_pmic; + int ret; + + sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), + GFP_KERNEL); + if (sec_pmic == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, sec_pmic); + sec_pmic->dev = &i2c->dev; + sec_pmic->i2c = i2c; + sec_pmic->irq = i2c->irq; + sec_pmic->type = id->driver_data; + + if (pdata) { + sec_pmic->device_type = pdata->device_type; + sec_pmic->ono = pdata->ono; + sec_pmic->irq_base = pdata->irq_base; + sec_pmic->wakeup = pdata->wakeup; + } + + sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); + if (IS_ERR(sec_pmic->regmap)) { + ret = PTR_ERR(sec_pmic->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); + i2c_set_clientdata(sec_pmic->rtc, sec_pmic); + + if (pdata && pdata->cfg_pmic_irq) + pdata->cfg_pmic_irq(); + + sec_irq_init(sec_pmic); + + pm_runtime_set_active(sec_pmic->dev); + + switch (sec_pmic->device_type) { + case S5M8751X: + ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, + ARRAY_SIZE(s5m8751_devs), NULL, 0); + break; + case S5M8763X: + ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, + ARRAY_SIZE(s5m8763_devs), NULL, 0); + break; + case S5M8767X: + ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, + ARRAY_SIZE(s5m8767_devs), NULL, 0); + break; + case S2MPS11X: + ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, + ARRAY_SIZE(s2mps11_devs), NULL, 0); + break; + default: + /* If this happens the probe function is problem */ + BUG(); + } + + if (ret < 0) + goto err; + + return ret; + +err: + mfd_remove_devices(sec_pmic->dev); + sec_irq_exit(sec_pmic); + i2c_unregister_device(sec_pmic->rtc); + return ret; +} + +static int sec_pmic_remove(struct i2c_client *i2c) +{ + struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); + + mfd_remove_devices(sec_pmic->dev); + sec_irq_exit(sec_pmic); + i2c_unregister_device(sec_pmic->rtc); + return 0; +} + +static const struct i2c_device_id sec_pmic_id[] = { + { "sec_pmic", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, sec_pmic_id); + +static struct i2c_driver sec_pmic_driver = { + .driver = { + .name = "sec_pmic", + .owner = THIS_MODULE, + }, + .probe = sec_pmic_probe, + .remove = sec_pmic_remove, + .id_table = sec_pmic_id, +}; + +static int __init sec_pmic_init(void) +{ + return i2c_add_driver(&sec_pmic_driver); +} + +subsys_initcall(sec_pmic_init); + +static void __exit sec_pmic_exit(void) +{ + i2c_del_driver(&sec_pmic_driver); +} +module_exit(sec_pmic_exit); + +MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); +MODULE_DESCRIPTION("Core support for the S5M MFD"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c new file mode 100644 index 00000000000..c901fa50fea --- /dev/null +++ b/drivers/mfd/sec-irq.c @@ -0,0 +1,317 @@ +/* + * sec-irq.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/regmap.h> + +#include <linux/mfd/samsung/core.h> +#include <linux/mfd/samsung/irq.h> +#include <linux/mfd/samsung/s2mps11.h> +#include <linux/mfd/samsung/s5m8763.h> +#include <linux/mfd/samsung/s5m8767.h> + +static struct regmap_irq s2mps11_irqs[] = { + [S2MPS11_IRQ_PWRONF] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_PWRONF_MASK, + }, + [S2MPS11_IRQ_PWRONR] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_PWRONR_MASK, + }, + [S2MPS11_IRQ_JIGONBF] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_JIGONBF_MASK, + }, + [S2MPS11_IRQ_JIGONBR] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_JIGONBR_MASK, + }, + [S2MPS11_IRQ_ACOKBF] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_ACOKBF_MASK, + }, + [S2MPS11_IRQ_ACOKBR] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_ACOKBR_MASK, + }, + [S2MPS11_IRQ_PWRON1S] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_PWRON1S_MASK, + }, + [S2MPS11_IRQ_MRB] = { + .reg_offset = 1, + .mask = S2MPS11_IRQ_MRB_MASK, + }, + [S2MPS11_IRQ_RTC60S] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_RTC60S_MASK, + }, + [S2MPS11_IRQ_RTCA1] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_RTCA1_MASK, + }, + [S2MPS11_IRQ_RTCA2] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_RTCA2_MASK, + }, + [S2MPS11_IRQ_SMPL] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_SMPL_MASK, + }, + [S2MPS11_IRQ_RTC1S] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_RTC1S_MASK, + }, + [S2MPS11_IRQ_WTSR] = { + .reg_offset = 2, + .mask = S2MPS11_IRQ_WTSR_MASK, + }, + [S2MPS11_IRQ_INT120C] = { + .reg_offset = 3, + .mask = S2MPS11_IRQ_INT120C_MASK, + }, + [S2MPS11_IRQ_INT140C] = { + .reg_offset = 3, + .mask = S2MPS11_IRQ_INT140C_MASK, + }, +}; + + +static struct regmap_irq s5m8767_irqs[] = { + [S5M8767_IRQ_PWRR] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_PWRR_MASK, + }, + [S5M8767_IRQ_PWRF] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_PWRF_MASK, + }, + [S5M8767_IRQ_PWR1S] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_PWR1S_MASK, + }, + [S5M8767_IRQ_JIGR] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_JIGR_MASK, + }, + [S5M8767_IRQ_JIGF] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_JIGF_MASK, + }, + [S5M8767_IRQ_LOWBAT2] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_LOWBAT2_MASK, + }, + [S5M8767_IRQ_LOWBAT1] = { + .reg_offset = 1, + .mask = S5M8767_IRQ_LOWBAT1_MASK, + }, + [S5M8767_IRQ_MRB] = { + .reg_offset = 2, + .mask = S5M8767_IRQ_MRB_MASK, + }, + [S5M8767_IRQ_DVSOK2] = { + .reg_offset = 2, + .mask = S5M8767_IRQ_DVSOK2_MASK, + }, + [S5M8767_IRQ_DVSOK3] = { + .reg_offset = 2, + .mask = S5M8767_IRQ_DVSOK3_MASK, + }, + [S5M8767_IRQ_DVSOK4] = { + .reg_offset = 2, + .mask = S5M8767_IRQ_DVSOK4_MASK, + }, + [S5M8767_IRQ_RTC60S] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_RTC60S_MASK, + }, + [S5M8767_IRQ_RTCA1] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_RTCA1_MASK, + }, + [S5M8767_IRQ_RTCA2] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_RTCA2_MASK, + }, + [S5M8767_IRQ_SMPL] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_SMPL_MASK, + }, + [S5M8767_IRQ_RTC1S] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_RTC1S_MASK, + }, + [S5M8767_IRQ_WTSR] = { + .reg_offset = 3, + .mask = S5M8767_IRQ_WTSR_MASK, + }, +}; + +static struct regmap_irq s5m8763_irqs[] = { + [S5M8763_IRQ_DCINF] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_DCINF_MASK, + }, + [S5M8763_IRQ_DCINR] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_DCINR_MASK, + }, + [S5M8763_IRQ_JIGF] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_JIGF_MASK, + }, + [S5M8763_IRQ_JIGR] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_JIGR_MASK, + }, + [S5M8763_IRQ_PWRONF] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_PWRONF_MASK, + }, + [S5M8763_IRQ_PWRONR] = { + .reg_offset = 1, + .mask = S5M8763_IRQ_PWRONR_MASK, + }, + [S5M8763_IRQ_WTSREVNT] = { + .reg_offset = 2, + .mask = S5M8763_IRQ_WTSREVNT_MASK, + }, + [S5M8763_IRQ_SMPLEVNT] = { + .reg_offset = 2, + .mask = S5M8763_IRQ_SMPLEVNT_MASK, + }, + [S5M8763_IRQ_ALARM1] = { + .reg_offset = 2, + .mask = S5M8763_IRQ_ALARM1_MASK, + }, + [S5M8763_IRQ_ALARM0] = { + .reg_offset = 2, + .mask = S5M8763_IRQ_ALARM0_MASK, + }, + [S5M8763_IRQ_ONKEY1S] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_ONKEY1S_MASK, + }, + [S5M8763_IRQ_TOPOFFR] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_TOPOFFR_MASK, + }, + [S5M8763_IRQ_DCINOVPR] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_DCINOVPR_MASK, + }, + [S5M8763_IRQ_CHGRSTF] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_CHGRSTF_MASK, + }, + [S5M8763_IRQ_DONER] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_DONER_MASK, + }, + [S5M8763_IRQ_CHGFAULT] = { + .reg_offset = 3, + .mask = S5M8763_IRQ_CHGFAULT_MASK, + }, + [S5M8763_IRQ_LOBAT1] = { + .reg_offset = 4, + .mask = S5M8763_IRQ_LOBAT1_MASK, + }, + [S5M8763_IRQ_LOBAT2] = { + .reg_offset = 4, + .mask = S5M8763_IRQ_LOBAT2_MASK, + }, +}; + +static struct regmap_irq_chip s2mps11_irq_chip = { + .name = "s2mps11", + .irqs = s2mps11_irqs, + .num_irqs = ARRAY_SIZE(s2mps11_irqs), + .num_regs = 3, + .status_base = S2MPS11_REG_INT1, + .mask_base = S2MPS11_REG_INT1M, + .ack_base = S2MPS11_REG_INT1, +}; + +static struct regmap_irq_chip s5m8767_irq_chip = { + .name = "s5m8767", + .irqs = s5m8767_irqs, + .num_irqs = ARRAY_SIZE(s5m8767_irqs), + .num_regs = 3, + .status_base = S5M8767_REG_INT1, + .mask_base = S5M8767_REG_INT1M, + .ack_base = S5M8767_REG_INT1, +}; + +static struct regmap_irq_chip s5m8763_irq_chip = { + .name = "s5m8763", + .irqs = s5m8763_irqs, + .num_irqs = ARRAY_SIZE(s5m8763_irqs), + .num_regs = 4, + .status_base = S5M8763_REG_IRQ1, + .mask_base = S5M8763_REG_IRQM1, + .ack_base = S5M8763_REG_IRQ1, +}; + +int sec_irq_init(struct sec_pmic_dev *sec_pmic) +{ + int ret = 0; + int type = sec_pmic->device_type; + + if (!sec_pmic->irq) { + dev_warn(sec_pmic->dev, + "No interrupt specified, no interrupts\n"); + sec_pmic->irq_base = 0; + return 0; + } + + switch (type) { + case S5M8763X: + ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq_base, &s5m8763_irq_chip, + &sec_pmic->irq_data); + break; + case S5M8767X: + ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq_base, &s5m8767_irq_chip, + &sec_pmic->irq_data); + break; + case S2MPS11X: + ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + sec_pmic->irq_base, &s2mps11_irq_chip, + &sec_pmic->irq_data); + break; + default: + dev_err(sec_pmic->dev, "Unknown device type %d\n", + sec_pmic->device_type); + return -EINVAL; + } + + if (ret != 0) { + dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); + return ret; + } + + return 0; +} + +void sec_irq_exit(struct sec_pmic_dev *sec_pmic) +{ + regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data); +} diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index de979742c6f..048bf0532a0 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -357,7 +357,7 @@ static int __devexit tc3589x_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tc3589x_suspend(struct device *dev) { struct tc3589x *tc3589x = dev_get_drvdata(dev); @@ -385,11 +385,10 @@ static int tc3589x_resume(struct device *dev) return ret; } - -static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, - tc3589x_resume); #endif +static SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, tc3589x_resume); + static const struct i2c_device_id tc3589x_id[] = { { "tc3589x", 24 }, { } @@ -399,9 +398,7 @@ MODULE_DEVICE_TABLE(i2c, tc3589x_id); static struct i2c_driver tc3589x_driver = { .driver.name = "tc3589x", .driver.owner = THIS_MODULE, -#ifdef CONFIG_PM .driver.pm = &tc3589x_dev_pm_ops, -#endif .probe = tc3589x_probe, .remove = __devexit_p(tc3589x_remove), .id_table = tc3589x_id, diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c index 396b9d1b6bd..80e24f4b47b 100644 --- a/drivers/mfd/tps65090.c +++ b/drivers/mfd/tps65090.c @@ -71,10 +71,10 @@ static const struct tps65090_irq_data tps65090_irqs[] = { static struct mfd_cell tps65090s[] = { { - .name = "tps65910-pmic", + .name = "tps65090-pmic", }, { - .name = "tps65910-regulator", + .name = "tps65090-regulator", }, }; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index c84b5506d5f..353c3481212 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -21,17 +21,14 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> -#include <linux/gpio.h> +#include <linux/err.h> #include <linux/i2c.h> +#include <linux/regmap.h> #include <linux/regulator/of_regulator.h> #include <linux/mfd/core.h> #include <linux/mfd/tps6586x.h> -/* GPIO control registers */ -#define TPS6586X_GPIOSET1 0x5d -#define TPS6586X_GPIOSET2 0x5e - /* interrupt control registers */ #define TPS6586X_INT_ACK1 0xb5 #define TPS6586X_INT_ACK2 0xb6 @@ -48,6 +45,9 @@ /* device id */ #define TPS6586X_VERSIONCRC 0xcd +/* Maximum register */ +#define TPS6586X_MAX_REGISTER (TPS6586X_VERSIONCRC + 1) + struct tps6586x_irq_data { u8 mask_reg; u8 mask_mask; @@ -89,226 +89,96 @@ static const struct tps6586x_irq_data tps6586x_irqs[] = { [TPS6586X_INT_RTC_ALM2] = TPS6586X_IRQ(TPS6586X_INT_MASK4, 1 << 1), }; +static struct mfd_cell tps6586x_cell[] = { + { + .name = "tps6586x-gpio", + }, + { + .name = "tps6586x-rtc", + }, + { + .name = "tps6586x-onkey", + }, +}; + struct tps6586x { - struct mutex lock; struct device *dev; struct i2c_client *client; + struct regmap *regmap; - struct gpio_chip gpio; struct irq_chip irq_chip; struct mutex irq_lock; int irq_base; u32 irq_en; - u8 mask_cache[5]; u8 mask_reg[5]; }; -static inline int __tps6586x_read(struct i2c_client *client, - int reg, uint8_t *val) -{ - int ret; - - ret = i2c_smbus_read_byte_data(client, reg); - if (ret < 0) { - dev_err(&client->dev, "failed reading at 0x%02x\n", reg); - return ret; - } - - *val = (uint8_t)ret; - - return 0; -} - -static inline int __tps6586x_reads(struct i2c_client *client, int reg, - int len, uint8_t *val) -{ - int ret; - - ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); - if (ret < 0) { - dev_err(&client->dev, "failed reading from 0x%02x\n", reg); - return ret; - } - - return 0; -} - -static inline int __tps6586x_write(struct i2c_client *client, - int reg, uint8_t val) +static inline struct tps6586x *dev_to_tps6586x(struct device *dev) { - int ret; - - ret = i2c_smbus_write_byte_data(client, reg, val); - if (ret < 0) { - dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", - val, reg); - return ret; - } - - return 0; -} - -static inline int __tps6586x_writes(struct i2c_client *client, int reg, - int len, uint8_t *val) -{ - int ret, i; - - for (i = 0; i < len; i++) { - ret = __tps6586x_write(client, reg + i, *(val + i)); - if (ret < 0) - return ret; - } - - return 0; + return i2c_get_clientdata(to_i2c_client(dev)); } int tps6586x_write(struct device *dev, int reg, uint8_t val) { - return __tps6586x_write(to_i2c_client(dev), reg, val); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); + + return regmap_write(tps6586x->regmap, reg, val); } EXPORT_SYMBOL_GPL(tps6586x_write); int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val) { - return __tps6586x_writes(to_i2c_client(dev), reg, len, val); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); + + return regmap_bulk_write(tps6586x->regmap, reg, val, len); } EXPORT_SYMBOL_GPL(tps6586x_writes); int tps6586x_read(struct device *dev, int reg, uint8_t *val) { - return __tps6586x_read(to_i2c_client(dev), reg, val); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); + unsigned int rval; + int ret; + + ret = regmap_read(tps6586x->regmap, reg, &rval); + if (!ret) + *val = rval; + return ret; } EXPORT_SYMBOL_GPL(tps6586x_read); int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val) { - return __tps6586x_reads(to_i2c_client(dev), reg, len, val); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); + + return regmap_bulk_read(tps6586x->regmap, reg, val, len); } EXPORT_SYMBOL_GPL(tps6586x_reads); int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask) { - struct tps6586x *tps6586x = dev_get_drvdata(dev); - uint8_t reg_val; - int ret = 0; - - mutex_lock(&tps6586x->lock); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); - ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); - if (ret) - goto out; - - if ((reg_val & bit_mask) != bit_mask) { - reg_val |= bit_mask; - ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); - } -out: - mutex_unlock(&tps6586x->lock); - return ret; + return regmap_update_bits(tps6586x->regmap, reg, bit_mask, bit_mask); } EXPORT_SYMBOL_GPL(tps6586x_set_bits); int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) { - struct tps6586x *tps6586x = dev_get_drvdata(dev); - uint8_t reg_val; - int ret = 0; - - mutex_lock(&tps6586x->lock); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); - ret = __tps6586x_read(to_i2c_client(dev), reg, ®_val); - if (ret) - goto out; - - if (reg_val & bit_mask) { - reg_val &= ~bit_mask; - ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val); - } -out: - mutex_unlock(&tps6586x->lock); - return ret; + return regmap_update_bits(tps6586x->regmap, reg, bit_mask, 0); } EXPORT_SYMBOL_GPL(tps6586x_clr_bits); int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) { - struct tps6586x *tps6586x = dev_get_drvdata(dev); - uint8_t reg_val; - int ret = 0; - - mutex_lock(&tps6586x->lock); + struct tps6586x *tps6586x = dev_to_tps6586x(dev); - ret = __tps6586x_read(tps6586x->client, reg, ®_val); - if (ret) - goto out; - - if ((reg_val & mask) != val) { - reg_val = (reg_val & ~mask) | val; - ret = __tps6586x_write(tps6586x->client, reg, reg_val); - } -out: - mutex_unlock(&tps6586x->lock); - return ret; + return regmap_update_bits(tps6586x->regmap, reg, mask, val); } EXPORT_SYMBOL_GPL(tps6586x_update); -static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); - uint8_t val; - int ret; - - ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val); - if (ret) - return ret; - - return !!(val & (1 << offset)); -} - - -static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset, - int value) -{ - struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio); - - tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET2, - value << offset, 1 << offset); -} - -static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio); - uint8_t val, mask; - - tps6586x_gpio_set(gc, offset, value); - - val = 0x1 << (offset * 2); - mask = 0x3 << (offset * 2); - - return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask); -} - -static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base) -{ - if (!gpio_base) - return 0; - - tps6586x->gpio.owner = THIS_MODULE; - tps6586x->gpio.label = tps6586x->client->name; - tps6586x->gpio.dev = tps6586x->dev; - tps6586x->gpio.base = gpio_base; - tps6586x->gpio.ngpio = 4; - tps6586x->gpio.can_sleep = 1; - - /* FIXME: add handling of GPIOs as dedicated inputs */ - tps6586x->gpio.direction_output = tps6586x_gpio_output; - tps6586x->gpio.set = tps6586x_gpio_set; - tps6586x->gpio.get = tps6586x_gpio_get; - - return gpiochip_add(&tps6586x->gpio); -} - static int __remove_subdev(struct device *dev, void *unused) { platform_device_unregister(to_platform_device(dev)); @@ -354,12 +224,11 @@ static void tps6586x_irq_sync_unlock(struct irq_data *data) int i; for (i = 0; i < ARRAY_SIZE(tps6586x->mask_reg); i++) { - if (tps6586x->mask_reg[i] != tps6586x->mask_cache[i]) { - if (!WARN_ON(tps6586x_write(tps6586x->dev, - TPS6586X_INT_MASK1 + i, - tps6586x->mask_reg[i]))) - tps6586x->mask_cache[i] = tps6586x->mask_reg[i]; - } + int ret; + ret = tps6586x_write(tps6586x->dev, + TPS6586X_INT_MASK1 + i, + tps6586x->mask_reg[i]); + WARN_ON(ret); } mutex_unlock(&tps6586x->irq_lock); @@ -406,7 +275,6 @@ static int __devinit tps6586x_irq_init(struct tps6586x *tps6586x, int irq, mutex_init(&tps6586x->irq_lock); for (i = 0; i < 5; i++) { - tps6586x->mask_cache[i] = 0xff; tps6586x->mask_reg[i] = 0xff; tps6586x_write(tps6586x->dev, TPS6586X_INT_MASK1 + i, 0xff); } @@ -556,6 +424,23 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien } #endif +static bool is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* Cache all interrupt mask register */ + if ((reg >= TPS6586X_INT_MASK1) && (reg <= TPS6586X_INT_MASK5)) + return false; + + return true; +} + +static const struct regmap_config tps6586x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPS6586X_MAX_REGISTER - 1, + .volatile_reg = is_volatile_reg, + .cache_type = REGCACHE_RBTREE, +}; + static int __devinit tps6586x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -579,29 +464,39 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, dev_info(&client->dev, "VERSIONCRC is %02x\n", ret); - tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL); - if (tps6586x == NULL) + tps6586x = devm_kzalloc(&client->dev, sizeof(*tps6586x), GFP_KERNEL); + if (tps6586x == NULL) { + dev_err(&client->dev, "memory for tps6586x alloc failed\n"); return -ENOMEM; + } tps6586x->client = client; tps6586x->dev = &client->dev; i2c_set_clientdata(client, tps6586x); - mutex_init(&tps6586x->lock); + tps6586x->regmap = devm_regmap_init_i2c(client, + &tps6586x_regmap_config); + if (IS_ERR(tps6586x->regmap)) { + ret = PTR_ERR(tps6586x->regmap); + dev_err(&client->dev, "regmap init failed: %d\n", ret); + return ret; + } + if (client->irq) { ret = tps6586x_irq_init(tps6586x, client->irq, pdata->irq_base); if (ret) { dev_err(&client->dev, "IRQ init failed: %d\n", ret); - goto err_irq_init; + return ret; } } - ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base); - if (ret) { - dev_err(&client->dev, "GPIO registration failed: %d\n", ret); - goto err_gpio_init; + ret = mfd_add_devices(tps6586x->dev, -1, + tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0); + if (ret < 0) { + dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret); + goto err_mfd_add; } ret = tps6586x_add_subdevs(tps6586x, pdata); @@ -613,38 +508,21 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client, return 0; err_add_devs: - if (pdata->gpio_base) { - ret = gpiochip_remove(&tps6586x->gpio); - if (ret) - dev_err(&client->dev, "Can't remove gpio chip: %d\n", - ret); - } -err_gpio_init: + mfd_remove_devices(tps6586x->dev); +err_mfd_add: if (client->irq) free_irq(client->irq, tps6586x); -err_irq_init: - kfree(tps6586x); return ret; } static int __devexit tps6586x_i2c_remove(struct i2c_client *client) { struct tps6586x *tps6586x = i2c_get_clientdata(client); - struct tps6586x_platform_data *pdata = client->dev.platform_data; - int ret; + tps6586x_remove_subdevs(tps6586x); + mfd_remove_devices(tps6586x->dev); if (client->irq) free_irq(client->irq, tps6586x); - - if (pdata->gpio_base) { - ret = gpiochip_remove(&tps6586x->gpio); - if (ret) - dev_err(&client->dev, "Can't remove gpio chip: %d\n", - ret); - } - - tps6586x_remove_subdevs(tps6586x); - kfree(tps6586x); return 0; } diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c index be9e07b7732..1c563792c77 100644 --- a/drivers/mfd/tps65910.c +++ b/drivers/mfd/tps65910.c @@ -68,6 +68,24 @@ static const struct regmap_config tps65910_regmap_config = { .cache_type = REGCACHE_RBTREE, }; +static int __devinit tps65910_ck32k_init(struct tps65910 *tps65910, + struct tps65910_board *pmic_pdata) +{ + int ret; + + if (!pmic_pdata->en_ck32k_xtal) + return 0; + + ret = tps65910_reg_clear_bits(tps65910, TPS65910_DEVCTRL, + DEVCTRL_CK32K_CTRL_MASK); + if (ret < 0) { + dev_err(tps65910->dev, "clear ck32k_ctrl failed: %d\n", ret); + return ret; + } + + return 0; +} + static int __devinit tps65910_sleepinit(struct tps65910 *tps65910, struct tps65910_board *pmic_pdata) { @@ -175,6 +193,9 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client, else if (*chip_id == TPS65911) dev_warn(&client->dev, "VMBCH2-Threshold not specified"); + prop = of_property_read_bool(np, "ti,en-ck32k-xtal"); + board_info->en_ck32k_xtal = prop; + board_info->irq = client->irq; board_info->irq_base = -1; @@ -243,7 +264,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c, init_data->irq_base = pmic_plat_data->irq_base; tps65910_irq_init(tps65910, init_data->irq, init_data); - + tps65910_ck32k_init(tps65910, pmic_plat_data); tps65910_sleepinit(tps65910, pmic_plat_data); return ret; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 6fc90befa79..b012efd29e0 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -568,7 +568,6 @@ add_numbered_child(unsigned chip, const char *name, int num, goto err; } - device_init_wakeup(&pdev->dev, can_wakeup); pdev->dev.parent = &twl->client->dev; if (pdata) { @@ -593,6 +592,8 @@ add_numbered_child(unsigned chip, const char *name, int num, } status = platform_device_add(pdev); + if (status == 0) + device_init_wakeup(&pdev->dev, can_wakeup); err: if (status < 0) { diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index 4ded9e7aa24..b0fad0ffca5 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -64,19 +64,15 @@ int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg) int ret; unsigned int val; - mutex_lock(&twl6040->io_mutex); /* Vibra control registers from cache */ if (unlikely(reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)) { val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)]; } else { ret = regmap_read(twl6040->regmap, reg, &val); - if (ret < 0) { - mutex_unlock(&twl6040->io_mutex); + if (ret < 0) return ret; - } } - mutex_unlock(&twl6040->io_mutex); return val; } @@ -86,12 +82,10 @@ int twl6040_reg_write(struct twl6040 *twl6040, unsigned int reg, u8 val) { int ret; - mutex_lock(&twl6040->io_mutex); ret = regmap_write(twl6040->regmap, reg, val); /* Cache the vibra control registers */ if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR) twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val; - mutex_unlock(&twl6040->io_mutex); return ret; } @@ -99,23 +93,13 @@ EXPORT_SYMBOL(twl6040_reg_write); int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask) { - int ret; - - mutex_lock(&twl6040->io_mutex); - ret = regmap_update_bits(twl6040->regmap, reg, mask, mask); - mutex_unlock(&twl6040->io_mutex); - return ret; + return regmap_update_bits(twl6040->regmap, reg, mask, mask); } EXPORT_SYMBOL(twl6040_set_bits); int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask) { - int ret; - - mutex_lock(&twl6040->io_mutex); - ret = regmap_update_bits(twl6040->regmap, reg, mask, 0); - mutex_unlock(&twl6040->io_mutex); - return ret; + return regmap_update_bits(twl6040->regmap, reg, mask, 0); } EXPORT_SYMBOL(twl6040_clear_bits); @@ -573,7 +557,6 @@ static int __devinit twl6040_probe(struct i2c_client *client, twl6040->irq = client->irq; mutex_init(&twl6040->mutex); - mutex_init(&twl6040->io_mutex); init_completion(&twl6040->ready); twl6040->rev = twl6040_reg_read(twl6040, TWL6040_REG_ASICREV); @@ -696,6 +679,7 @@ static int __devexit twl6040_remove(struct i2c_client *client) static const struct i2c_device_id twl6040_i2c_id[] = { { "twl6040", 0, }, + { "twl6041", 0, }, { }, }; MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id); diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c new file mode 100644 index 00000000000..01b9255ed63 --- /dev/null +++ b/drivers/mfd/wm5102-tables.c @@ -0,0 +1,2399 @@ +/* + * wm5102-tables.c -- WM5102 data tables + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> + +#include <linux/mfd/arizona/core.h> +#include <linux/mfd/arizona/registers.h> + +#include "arizona.h" + +#define WM5102_NUM_AOD_ISR 2 +#define WM5102_NUM_ISR 5 + +static const struct reg_default wm5102_reva_patch[] = { + { 0x80, 0x0003 }, + { 0x221, 0x0090 }, + { 0x211, 0x0014 }, + { 0x212, 0x0000 }, + { 0x214, 0x000C }, + { 0x171, 0x0002 }, + { 0x171, 0x0000 }, + { 0x461, 0x8000 }, + { 0x463, 0x50F0 }, + { 0x465, 0x4820 }, + { 0x467, 0x4040 }, + { 0x469, 0x3940 }, + { 0x46B, 0x3310 }, + { 0x46D, 0x2D80 }, + { 0x46F, 0x2890 }, + { 0x471, 0x1990 }, + { 0x473, 0x1450 }, + { 0x475, 0x1020 }, + { 0x477, 0x0CD0 }, + { 0x479, 0x0A30 }, + { 0x47B, 0x0810 }, + { 0x47D, 0x0510 }, + { 0x500, 0x000D }, + { 0x507, 0x1820 }, + { 0x508, 0x1820 }, + { 0x540, 0x000D }, + { 0x547, 0x1820 }, + { 0x548, 0x1820 }, + { 0x580, 0x000D }, + { 0x587, 0x1820 }, + { 0x588, 0x1820 }, + { 0x101, 0x8140 }, + { 0x3000, 0x2225 }, + { 0x3001, 0x3a03 }, + { 0x3002, 0x0225 }, + { 0x3003, 0x0801 }, + { 0x3004, 0x6249 }, + { 0x3005, 0x0c04 }, + { 0x3006, 0x0225 }, + { 0x3007, 0x5901 }, + { 0x3008, 0xe249 }, + { 0x3009, 0x030d }, + { 0x300a, 0x0249 }, + { 0x300b, 0x2c01 }, + { 0x300c, 0xe249 }, + { 0x300d, 0x4342 }, + { 0x300e, 0xe249 }, + { 0x300f, 0x73c0 }, + { 0x3010, 0x4249 }, + { 0x3011, 0x0c00 }, + { 0x3012, 0x0225 }, + { 0x3013, 0x1f01 }, + { 0x3014, 0x0225 }, + { 0x3015, 0x1e01 }, + { 0x3016, 0x0225 }, + { 0x3017, 0xfa00 }, + { 0x3018, 0x0000 }, + { 0x3019, 0xf000 }, + { 0x301a, 0x0000 }, + { 0x301b, 0xf000 }, + { 0x301c, 0x0000 }, + { 0x301d, 0xf000 }, + { 0x301e, 0x0000 }, + { 0x301f, 0xf000 }, + { 0x3020, 0x0000 }, + { 0x3021, 0xf000 }, + { 0x3022, 0x0000 }, + { 0x3023, 0xf000 }, + { 0x3024, 0x0000 }, + { 0x3025, 0xf000 }, + { 0x3026, 0x0000 }, + { 0x3027, 0xf000 }, + { 0x3028, 0x0000 }, + { 0x3029, 0xf000 }, + { 0x302a, 0x0000 }, + { 0x302b, 0xf000 }, + { 0x302c, 0x0000 }, + { 0x302d, 0xf000 }, + { 0x302e, 0x0000 }, + { 0x302f, 0xf000 }, + { 0x3030, 0x0225 }, + { 0x3031, 0x1a01 }, + { 0x3032, 0x0225 }, + { 0x3033, 0x1e00 }, + { 0x3034, 0x0225 }, + { 0x3035, 0x1f00 }, + { 0x3036, 0x6225 }, + { 0x3037, 0xf800 }, + { 0x3038, 0x0000 }, + { 0x3039, 0xf000 }, + { 0x303a, 0x0000 }, + { 0x303b, 0xf000 }, + { 0x303c, 0x0000 }, + { 0x303d, 0xf000 }, + { 0x303e, 0x0000 }, + { 0x303f, 0xf000 }, + { 0x3040, 0x2226 }, + { 0x3041, 0x3a03 }, + { 0x3042, 0x0226 }, + { 0x3043, 0x0801 }, + { 0x3044, 0x6249 }, + { 0x3045, 0x0c06 }, + { 0x3046, 0x0226 }, + { 0x3047, 0x5901 }, + { 0x3048, 0xe249 }, + { 0x3049, 0x030d }, + { 0x304a, 0x0249 }, + { 0x304b, 0x2c01 }, + { 0x304c, 0xe249 }, + { 0x304d, 0x4342 }, + { 0x304e, 0xe249 }, + { 0x304f, 0x73c0 }, + { 0x3050, 0x4249 }, + { 0x3051, 0x0c00 }, + { 0x3052, 0x0226 }, + { 0x3053, 0x1f01 }, + { 0x3054, 0x0226 }, + { 0x3055, 0x1e01 }, + { 0x3056, 0x0226 }, + { 0x3057, 0xfa00 }, + { 0x3058, 0x0000 }, + { 0x3059, 0xf000 }, + { 0x305a, 0x0000 }, + { 0x305b, 0xf000 }, + { 0x305c, 0x0000 }, + { 0x305d, 0xf000 }, + { 0x305e, 0x0000 }, + { 0x305f, 0xf000 }, + { 0x3060, 0x0000 }, + { 0x3061, 0xf000 }, + { 0x3062, 0x0000 }, + { 0x3063, 0xf000 }, + { 0x3064, 0x0000 }, + { 0x3065, 0xf000 }, + { 0x3066, 0x0000 }, + { 0x3067, 0xf000 }, + { 0x3068, 0x0000 }, + { 0x3069, 0xf000 }, + { 0x306a, 0x0000 }, + { 0x306b, 0xf000 }, + { 0x306c, 0x0000 }, + { 0x306d, 0xf000 }, + { 0x306e, 0x0000 }, + { 0x306f, 0xf000 }, + { 0x3070, 0x0226 }, + { 0x3071, 0x1a01 }, + { 0x3072, 0x0226 }, + { 0x3073, 0x1e00 }, + { 0x3074, 0x0226 }, + { 0x3075, 0x1f00 }, + { 0x3076, 0x6226 }, + { 0x3077, 0xf800 }, + { 0x3078, 0x0000 }, + { 0x3079, 0xf000 }, + { 0x307a, 0x0000 }, + { 0x307b, 0xf000 }, + { 0x307c, 0x0000 }, + { 0x307d, 0xf000 }, + { 0x307e, 0x0000 }, + { 0x307f, 0xf000 }, + { 0x3080, 0x2227 }, + { 0x3081, 0x3a03 }, + { 0x3082, 0x0227 }, + { 0x3083, 0x0801 }, + { 0x3084, 0x6255 }, + { 0x3085, 0x0c04 }, + { 0x3086, 0x0227 }, + { 0x3087, 0x5901 }, + { 0x3088, 0xe255 }, + { 0x3089, 0x030d }, + { 0x308a, 0x0255 }, + { 0x308b, 0x2c01 }, + { 0x308c, 0xe255 }, + { 0x308d, 0x4342 }, + { 0x308e, 0xe255 }, + { 0x308f, 0x73c0 }, + { 0x3090, 0x4255 }, + { 0x3091, 0x0c00 }, + { 0x3092, 0x0227 }, + { 0x3093, 0x1f01 }, + { 0x3094, 0x0227 }, + { 0x3095, 0x1e01 }, + { 0x3096, 0x0227 }, + { 0x3097, 0xfa00 }, + { 0x3098, 0x0000 }, + { 0x3099, 0xf000 }, + { 0x309a, 0x0000 }, + { 0x309b, 0xf000 }, + { 0x309c, 0x0000 }, + { 0x309d, 0xf000 }, + { 0x309e, 0x0000 }, + { 0x309f, 0xf000 }, + { 0x30a0, 0x0000 }, + { 0x30a1, 0xf000 }, + { 0x30a2, 0x0000 }, + { 0x30a3, 0xf000 }, + { 0x30a4, 0x0000 }, + { 0x30a5, 0xf000 }, + { 0x30a6, 0x0000 }, + { 0x30a7, 0xf000 }, + { 0x30a8, 0x0000 }, + { 0x30a9, 0xf000 }, + { 0x30aa, 0x0000 }, + { 0x30ab, 0xf000 }, + { 0x30ac, 0x0000 }, + { 0x30ad, 0xf000 }, + { 0x30ae, 0x0000 }, + { 0x30af, 0xf000 }, + { 0x30b0, 0x0227 }, + { 0x30b1, 0x1a01 }, + { 0x30b2, 0x0227 }, + { 0x30b3, 0x1e00 }, + { 0x30b4, 0x0227 }, + { 0x30b5, 0x1f00 }, + { 0x30b6, 0x6227 }, + { 0x30b7, 0xf800 }, + { 0x30b8, 0x0000 }, + { 0x30b9, 0xf000 }, + { 0x30ba, 0x0000 }, + { 0x30bb, 0xf000 }, + { 0x30bc, 0x0000 }, + { 0x30bd, 0xf000 }, + { 0x30be, 0x0000 }, + { 0x30bf, 0xf000 }, + { 0x30c0, 0x2228 }, + { 0x30c1, 0x3a03 }, + { 0x30c2, 0x0228 }, + { 0x30c3, 0x0801 }, + { 0x30c4, 0x6255 }, + { 0x30c5, 0x0c06 }, + { 0x30c6, 0x0228 }, + { 0x30c7, 0x5901 }, + { 0x30c8, 0xe255 }, + { 0x30c9, 0x030d }, + { 0x30ca, 0x0255 }, + { 0x30cb, 0x2c01 }, + { 0x30cc, 0xe255 }, + { 0x30cd, 0x4342 }, + { 0x30ce, 0xe255 }, + { 0x30cf, 0x73c0 }, + { 0x30d0, 0x4255 }, + { 0x30d1, 0x0c00 }, + { 0x30d2, 0x0228 }, + { 0x30d3, 0x1f01 }, + { 0x30d4, 0x0228 }, + { 0x30d5, 0x1e01 }, + { 0x30d6, 0x0228 }, + { 0x30d7, 0xfa00 }, + { 0x30d8, 0x0000 }, + { 0x30d9, 0xf000 }, + { 0x30da, 0x0000 }, + { 0x30db, 0xf000 }, + { 0x30dc, 0x0000 }, + { 0x30dd, 0xf000 }, + { 0x30de, 0x0000 }, + { 0x30df, 0xf000 }, + { 0x30e0, 0x0000 }, + { 0x30e1, 0xf000 }, + { 0x30e2, 0x0000 }, + { 0x30e3, 0xf000 }, + { 0x30e4, 0x0000 }, + { 0x30e5, 0xf000 }, + { 0x30e6, 0x0000 }, + { 0x30e7, 0xf000 }, + { 0x30e8, 0x0000 }, + { 0x30e9, 0xf000 }, + { 0x30ea, 0x0000 }, + { 0x30eb, 0xf000 }, + { 0x30ec, 0x0000 }, + { 0x30ed, 0xf000 }, + { 0x30ee, 0x0000 }, + { 0x30ef, 0xf000 }, + { 0x30f0, 0x0228 }, + { 0x30f1, 0x1a01 }, + { 0x30f2, 0x0228 }, + { 0x30f3, 0x1e00 }, + { 0x30f4, 0x0228 }, + { 0x30f5, 0x1f00 }, + { 0x30f6, 0x6228 }, + { 0x30f7, 0xf800 }, + { 0x30f8, 0x0000 }, + { 0x30f9, 0xf000 }, + { 0x30fa, 0x0000 }, + { 0x30fb, 0xf000 }, + { 0x30fc, 0x0000 }, + { 0x30fd, 0xf000 }, + { 0x30fe, 0x0000 }, + { 0x30ff, 0xf000 }, + { 0x3100, 0x222b }, + { 0x3101, 0x3a03 }, + { 0x3102, 0x222b }, + { 0x3103, 0x5803 }, + { 0x3104, 0xe26f }, + { 0x3105, 0x030d }, + { 0x3106, 0x626f }, + { 0x3107, 0x2c01 }, + { 0x3108, 0xe26f }, + { 0x3109, 0x4342 }, + { 0x310a, 0xe26f }, + { 0x310b, 0x73c0 }, + { 0x310c, 0x026f }, + { 0x310d, 0x0c00 }, + { 0x310e, 0x022b }, + { 0x310f, 0x1f01 }, + { 0x3110, 0x022b }, + { 0x3111, 0x1e01 }, + { 0x3112, 0x022b }, + { 0x3113, 0xfa00 }, + { 0x3114, 0x0000 }, + { 0x3115, 0xf000 }, + { 0x3116, 0x0000 }, + { 0x3117, 0xf000 }, + { 0x3118, 0x0000 }, + { 0x3119, 0xf000 }, + { 0x311a, 0x0000 }, + { 0x311b, 0xf000 }, + { 0x311c, 0x0000 }, + { 0x311d, 0xf000 }, + { 0x311e, 0x0000 }, + { 0x311f, 0xf000 }, + { 0x3120, 0x022b }, + { 0x3121, 0x0a01 }, + { 0x3122, 0x022b }, + { 0x3123, 0x1e00 }, + { 0x3124, 0x022b }, + { 0x3125, 0x1f00 }, + { 0x3126, 0x622b }, + { 0x3127, 0xf800 }, + { 0x3128, 0x0000 }, + { 0x3129, 0xf000 }, + { 0x312a, 0x0000 }, + { 0x312b, 0xf000 }, + { 0x312c, 0x0000 }, + { 0x312d, 0xf000 }, + { 0x312e, 0x0000 }, + { 0x312f, 0xf000 }, + { 0x3130, 0x0000 }, + { 0x3131, 0xf000 }, + { 0x3132, 0x0000 }, + { 0x3133, 0xf000 }, + { 0x3134, 0x0000 }, + { 0x3135, 0xf000 }, + { 0x3136, 0x0000 }, + { 0x3137, 0xf000 }, + { 0x3138, 0x0000 }, + { 0x3139, 0xf000 }, + { 0x313a, 0x0000 }, + { 0x313b, 0xf000 }, + { 0x313c, 0x0000 }, + { 0x313d, 0xf000 }, + { 0x313e, 0x0000 }, + { 0x313f, 0xf000 }, + { 0x3140, 0x0000 }, + { 0x3141, 0xf000 }, + { 0x3142, 0x0000 }, + { 0x3143, 0xf000 }, + { 0x3144, 0x0000 }, + { 0x3145, 0xf000 }, + { 0x3146, 0x0000 }, + { 0x3147, 0xf000 }, + { 0x3148, 0x0000 }, + { 0x3149, 0xf000 }, + { 0x314a, 0x0000 }, + { 0x314b, 0xf000 }, + { 0x314c, 0x0000 }, + { 0x314d, 0xf000 }, + { 0x314e, 0x0000 }, + { 0x314f, 0xf000 }, + { 0x3150, 0x0000 }, + { 0x3151, 0xf000 }, + { 0x3152, 0x0000 }, + { 0x3153, 0xf000 }, + { 0x3154, 0x0000 }, + { 0x3155, 0xf000 }, + { 0x3156, 0x0000 }, + { 0x3157, 0xf000 }, + { 0x3158, 0x0000 }, + { 0x3159, 0xf000 }, + { 0x315a, 0x0000 }, + { 0x315b, 0xf000 }, + { 0x315c, 0x0000 }, + { 0x315d, 0xf000 }, + { 0x315e, 0x0000 }, + { 0x315f, 0xf000 }, + { 0x3160, 0x0000 }, + { 0x3161, 0xf000 }, + { 0x3162, 0x0000 }, + { 0x3163, 0xf000 }, + { 0x3164, 0x0000 }, + { 0x3165, 0xf000 }, + { 0x3166, 0x0000 }, + { 0x3167, 0xf000 }, + { 0x3168, 0x0000 }, + { 0x3169, 0xf000 }, + { 0x316a, 0x0000 }, + { 0x316b, 0xf000 }, + { 0x316c, 0x0000 }, + { 0x316d, 0xf000 }, + { 0x316e, 0x0000 }, + { 0x316f, 0xf000 }, + { 0x3170, 0x0000 }, + { 0x3171, 0xf000 }, + { 0x3172, 0x0000 }, + { 0x3173, 0xf000 }, + { 0x3174, 0x0000 }, + { 0x3175, 0xf000 }, + { 0x3176, 0x0000 }, + { 0x3177, 0xf000 }, + { 0x3178, 0x0000 }, + { 0x3179, 0xf000 }, + { 0x317a, 0x0000 }, + { 0x317b, 0xf000 }, + { 0x317c, 0x0000 }, + { 0x317d, 0xf000 }, + { 0x317e, 0x0000 }, + { 0x317f, 0xf000 }, + { 0x3180, 0x2001 }, + { 0x3181, 0xf101 }, + { 0x3182, 0x0000 }, + { 0x3183, 0xf000 }, + { 0x3184, 0x0000 }, + { 0x3185, 0xf000 }, + { 0x3186, 0x0000 }, + { 0x3187, 0xf000 }, + { 0x3188, 0x0000 }, + { 0x3189, 0xf000 }, + { 0x318a, 0x0000 }, + { 0x318b, 0xf000 }, + { 0x318c, 0x0000 }, + { 0x318d, 0xf000 }, + { 0x318e, 0x0000 }, + { 0x318f, 0xf000 }, + { 0x3190, 0x0000 }, + { 0x3191, 0xf000 }, + { 0x3192, 0x0000 }, + { 0x3193, 0xf000 }, + { 0x3194, 0x0000 }, + { 0x3195, 0xf000 }, + { 0x3196, 0x0000 }, + { 0x3197, 0xf000 }, + { 0x3198, 0x0000 }, + { 0x3199, 0xf000 }, + { 0x319a, 0x0000 }, + { 0x319b, 0xf000 }, + { 0x319c, 0x0000 }, + { 0x319d, 0xf000 }, + { 0x319e, 0x0000 }, + { 0x319f, 0xf000 }, + { 0x31a0, 0x0000 }, + { 0x31a1, 0xf000 }, + { 0x31a2, 0x0000 }, + { 0x31a3, 0xf000 }, + { 0x31a4, 0x0000 }, + { 0x31a5, 0xf000 }, + { 0x31a6, 0x0000 }, + { 0x31a7, 0xf000 }, + { 0x31a8, 0x0000 }, + { 0x31a9, 0xf000 }, + { 0x31aa, 0x0000 }, + { 0x31ab, 0xf000 }, + { 0x31ac, 0x0000 }, + { 0x31ad, 0xf000 }, + { 0x31ae, 0x0000 }, + { 0x31af, 0xf000 }, + { 0x31b0, 0x0000 }, + { 0x31b1, 0xf000 }, + { 0x31b2, 0x0000 }, + { 0x31b3, 0xf000 }, + { 0x31b4, 0x0000 }, + { 0x31b5, 0xf000 }, + { 0x31b6, 0x0000 }, + { 0x31b7, 0xf000 }, + { 0x31b8, 0x0000 }, + { 0x31b9, 0xf000 }, + { 0x31ba, 0x0000 }, + { 0x31bb, 0xf000 }, + { 0x31bc, 0x0000 }, + { 0x31bd, 0xf000 }, + { 0x31be, 0x0000 }, + { 0x31bf, 0xf000 }, + { 0x31c0, 0x0000 }, + { 0x31c1, 0xf000 }, + { 0x31c2, 0x0000 }, + { 0x31c3, 0xf000 }, + { 0x31c4, 0x0000 }, + { 0x31c5, 0xf000 }, + { 0x31c6, 0x0000 }, + { 0x31c7, 0xf000 }, + { 0x31c8, 0x0000 }, + { 0x31c9, 0xf000 }, + { 0x31ca, 0x0000 }, + { 0x31cb, 0xf000 }, + { 0x31cc, 0x0000 }, + { 0x31cd, 0xf000 }, + { 0x31ce, 0x0000 }, + { 0x31cf, 0xf000 }, + { 0x31d0, 0x0000 }, + { 0x31d1, 0xf000 }, + { 0x31d2, 0x0000 }, + { 0x31d3, 0xf000 }, + { 0x31d4, 0x0000 }, + { 0x31d5, 0xf000 }, + { 0x31d6, 0x0000 }, + { 0x31d7, 0xf000 }, + { 0x31d8, 0x0000 }, + { 0x31d9, 0xf000 }, + { 0x31da, 0x0000 }, + { 0x31db, 0xf000 }, + { 0x31dc, 0x0000 }, + { 0x31dd, 0xf000 }, + { 0x31de, 0x0000 }, + { 0x31df, 0xf000 }, + { 0x31e0, 0x0000 }, + { 0x31e1, 0xf000 }, + { 0x31e2, 0x0000 }, + { 0x31e3, 0xf000 }, + { 0x31e4, 0x0000 }, + { 0x31e5, 0xf000 }, + { 0x31e6, 0x0000 }, + { 0x31e7, 0xf000 }, + { 0x31e8, 0x0000 }, + { 0x31e9, 0xf000 }, + { 0x31ea, 0x0000 }, + { 0x31eb, 0xf000 }, + { 0x31ec, 0x0000 }, + { 0x31ed, 0xf000 }, + { 0x31ee, 0x0000 }, + { 0x31ef, 0xf000 }, + { 0x31f0, 0x0000 }, + { 0x31f1, 0xf000 }, + { 0x31f2, 0x0000 }, + { 0x31f3, 0xf000 }, + { 0x31f4, 0x0000 }, + { 0x31f5, 0xf000 }, + { 0x31f6, 0x0000 }, + { 0x31f7, 0xf000 }, + { 0x31f8, 0x0000 }, + { 0x31f9, 0xf000 }, + { 0x31fa, 0x0000 }, + { 0x31fb, 0xf000 }, + { 0x31fc, 0x0000 }, + { 0x31fd, 0xf000 }, + { 0x31fe, 0x0000 }, + { 0x31ff, 0xf000 }, + { 0x024d, 0xff50 }, + { 0x0252, 0xff50 }, + { 0x0259, 0x0112 }, + { 0x025e, 0x0112 }, + { 0x101, 0x0304 }, + { 0x80, 0x0000 }, +}; + +/* We use a function so we can use ARRAY_SIZE() */ +int wm5102_patch(struct arizona *arizona) +{ + switch (arizona->rev) { + case 0: + return regmap_register_patch(arizona->regmap, + wm5102_reva_patch, + ARRAY_SIZE(wm5102_reva_patch)); + default: + return 0; + } +} + +static const struct regmap_irq wm5102_aod_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 }, + [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 }, + [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 }, + [ARIZONA_IRQ_JD_RISE] = { .mask = ARIZONA_JD1_RISE_EINT1 }, +}; + +const struct regmap_irq_chip wm5102_aod = { + .name = "wm5102 AOD", + .status_base = ARIZONA_AOD_IRQ1, + .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, + .ack_base = ARIZONA_AOD_IRQ1, + .wake_base = ARIZONA_WAKE_CONTROL, + .num_regs = 1, + .irqs = wm5102_aod_irqs, + .num_irqs = ARRAY_SIZE(wm5102_aod_irqs), +}; + +static const struct regmap_irq wm5102_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 }, + [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 }, + [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 }, + [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 }, + + [ARIZONA_IRQ_DSP1_RAM_RDY] = { + .reg_offset = 1, .mask = ARIZONA_DSP1_RAM_RDY_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ2] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ1] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1 + }, + + [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1 + }, + [ARIZONA_IRQ_SPK_SHUTDOWN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1 + }, + [ARIZONA_IRQ_HPDET] = { + .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1 + }, + [ARIZONA_IRQ_MICDET] = { + .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1 + }, + [ARIZONA_IRQ_WSEQ_DONE] = { + .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1 + }, + [ARIZONA_IRQ_DRC2_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_DRC1_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_ASRC2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1 + }, + [ARIZONA_IRQ_ASRC1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1 + }, + [ARIZONA_IRQ_UNDERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_OVERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_FLL2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1 + }, + [ARIZONA_IRQ_FLL1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1 + }, + + [ARIZONA_IRQ_ASRC_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ASRC_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF3_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF3_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF2_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF2_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF1_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF1_ERR_EINT1 + }, + [ARIZONA_IRQ_CTRLIF_ERR] = { + .reg_offset = 3, .mask = ARIZONA_CTRLIF_ERR_EINT1 + }, + [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = { + .reg_offset = 3, .mask = ARIZONA_MIXER_DROPPED_SAMPLE_EINT1 + }, + [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_ASYNC_CLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_SYSCLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_SYSCLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_ISRC1_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC1_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_ISRC2_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1 + }, + + [ARIZONA_IRQ_BOOT_DONE] = { + .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_DAC_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_HP_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1 + }, + [ARIZONA_IRQ_FLL2_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1 + }, + [ARIZONA_IRQ_FLL1_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1 + }, +}; + +const struct regmap_irq_chip wm5102_irq = { + .name = "wm5102 IRQ", + .status_base = ARIZONA_INTERRUPT_STATUS_1, + .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK, + .ack_base = ARIZONA_INTERRUPT_STATUS_1, + .num_regs = 5, + .irqs = wm5102_irqs, + .num_irqs = ARRAY_SIZE(wm5102_irqs), +}; + +static const struct reg_default wm5102_reg_default[] = { + { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */ + { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ + { 0x0000000D, 0x0000 }, /* R13 - Ctrl IF Status 1 */ + { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ + { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ + { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ + { 0x0000001A, 0x0000 }, /* R26 - Write Sequencer PROM */ + { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ + { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ + { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ + { 0x00000023, 0x1000 }, /* R35 - Tone Generator 4 */ + { 0x00000024, 0x0000 }, /* R36 - Tone Generator 5 */ + { 0x00000030, 0x0000 }, /* R48 - PWM Drive 1 */ + { 0x00000031, 0x0100 }, /* R49 - PWM Drive 2 */ + { 0x00000032, 0x0100 }, /* R50 - PWM Drive 3 */ + { 0x00000040, 0x0000 }, /* R64 - Wake control */ + { 0x00000041, 0x0000 }, /* R65 - Sequence control */ + { 0x00000061, 0x01FF }, /* R97 - Sample Rate Sequence Select 1 */ + { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ + { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ + { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ + { 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 */ + { 0x0000006C, 0x01FF }, /* R108 - Always On Triggers Sequence Select 5 */ + { 0x0000006D, 0x01FF }, /* R109 - Always On Triggers Sequence Select 6 */ + { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ + { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ + { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ + { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ + { 0x00000093, 0x0000 }, /* R147 - Haptics phase 1 duration */ + { 0x00000094, 0x0000 }, /* R148 - Haptics phase 2 intensity */ + { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ + { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ + { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ + { 0x00000100, 0x0001 }, /* R256 - Clock 32k 1 */ + { 0x00000101, 0x0304 }, /* R257 - System Clock 1 */ + { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ + { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ + { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ + { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ + { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ + { 0x00000149, 0x0000 }, /* R329 - Output system clock */ + { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ + { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ + { 0x00000153, 0x0000 }, /* R339 - Rate Estimator 2 */ + { 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */ + { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ + { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ + { 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */ + { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ + { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ + { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ + { 0x00000175, 0x0004 }, /* R373 - FLL1 Control 5 */ + { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ + { 0x00000177, 0x0181 }, /* R375 - FLL1 Loop Filter Test 1 */ + { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ + { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ + { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ + { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */ + { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */ + { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */ + { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */ + { 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */ + { 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */ + { 0x00000192, 0x0008 }, /* R402 - FLL2 Control 2 */ + { 0x00000193, 0x0018 }, /* R403 - FLL2 Control 3 */ + { 0x00000194, 0x007D }, /* R404 - FLL2 Control 4 */ + { 0x00000195, 0x0004 }, /* R405 - FLL2 Control 5 */ + { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ + { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ + { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ + { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ + { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ + { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */ + { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */ + { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */ + { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */ + { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ + { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ + { 0x00000210, 0x00D4 }, /* R528 - LDO1 Control 1 */ + { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */ + { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ + { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ + { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ + { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ + { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ + { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ + { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ + { 0x000002A5, 0x0000 }, /* R677 - Mic Detect 3 */ + { 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 */ + { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ + { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ + { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ + { 0x00000314, 0x0080 }, /* R788 - IN1R Control */ + { 0x00000315, 0x0180 }, /* R789 - ADC Digital Volume 1R */ + { 0x00000316, 0x0000 }, /* R790 - DMIC1R Control */ + { 0x00000318, 0x2080 }, /* R792 - IN2L Control */ + { 0x00000319, 0x0180 }, /* R793 - ADC Digital Volume 2L */ + { 0x0000031A, 0x0000 }, /* R794 - DMIC2L Control */ + { 0x0000031C, 0x0080 }, /* R796 - IN2R Control */ + { 0x0000031D, 0x0180 }, /* R797 - ADC Digital Volume 2R */ + { 0x0000031E, 0x0000 }, /* R798 - DMIC2R Control */ + { 0x00000320, 0x2080 }, /* R800 - IN3L Control */ + { 0x00000321, 0x0180 }, /* R801 - ADC Digital Volume 3L */ + { 0x00000322, 0x0000 }, /* R802 - DMIC3L Control */ + { 0x00000324, 0x0080 }, /* R804 - IN3R Control */ + { 0x00000325, 0x0180 }, /* R805 - ADC Digital Volume 3R */ + { 0x00000326, 0x0000 }, /* R806 - DMIC3R Control */ + { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ + { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ + { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ + { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */ + { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ + { 0x00000412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ + { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ + { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ + { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ + { 0x00000416, 0x0080 }, /* R1046 - DAC Volume Limit 1R */ + { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ + { 0x00000418, 0x0080 }, /* R1048 - Output Path Config 2L */ + { 0x00000419, 0x0180 }, /* R1049 - DAC Digital Volume 2L */ + { 0x0000041A, 0x0080 }, /* R1050 - DAC Volume Limit 2L */ + { 0x0000041B, 0x0004 }, /* R1051 - Noise Gate Select 2L */ + { 0x0000041C, 0x0080 }, /* R1052 - Output Path Config 2R */ + { 0x0000041D, 0x0180 }, /* R1053 - DAC Digital Volume 2R */ + { 0x0000041E, 0x0080 }, /* R1054 - DAC Volume Limit 2R */ + { 0x0000041F, 0x0008 }, /* R1055 - Noise Gate Select 2R */ + { 0x00000420, 0x0080 }, /* R1056 - Output Path Config 3L */ + { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ + { 0x00000422, 0x0080 }, /* R1058 - DAC Volume Limit 3L */ + { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ + { 0x00000424, 0x0080 }, /* R1060 - Output Path Config 3R */ + { 0x00000425, 0x0180 }, /* R1061 - DAC Digital Volume 3R */ + { 0x00000426, 0x0080 }, /* R1062 - DAC Volume Limit 3R */ + { 0x00000428, 0x0000 }, /* R1064 - Output Path Config 4L */ + { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ + { 0x0000042A, 0x0080 }, /* R1066 - Out Volume 4L */ + { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ + { 0x0000042C, 0x0000 }, /* R1068 - Output Path Config 4R */ + { 0x0000042D, 0x0180 }, /* R1069 - DAC Digital Volume 4R */ + { 0x0000042E, 0x0080 }, /* R1070 - Out Volume 4R */ + { 0x0000042F, 0x0080 }, /* R1071 - Noise Gate Select 4R */ + { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ + { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ + { 0x00000432, 0x0080 }, /* R1074 - DAC Volume Limit 5L */ + { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ + { 0x00000434, 0x0000 }, /* R1076 - Output Path Config 5R */ + { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ + { 0x00000436, 0x0080 }, /* R1078 - DAC Volume Limit 5R */ + { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ + { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ + { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */ + { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ + { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ + { 0x000004DC, 0x0000 }, /* R1244 - DAC comp 1 */ + { 0x000004DD, 0x0000 }, /* R1245 - DAC comp 2 */ + { 0x000004DE, 0x0000 }, /* R1246 - DAC comp 3 */ + { 0x000004DF, 0x0000 }, /* R1247 - DAC comp 4 */ + { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ + { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ + { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ + { 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */ + { 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */ + { 0x00000505, 0x0040 }, /* R1285 - AIF1 Tx BCLK Rate */ + { 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */ + { 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */ + { 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */ + { 0x00000509, 0x0000 }, /* R1289 - AIF1 Frame Ctrl 3 */ + { 0x0000050A, 0x0001 }, /* R1290 - AIF1 Frame Ctrl 4 */ + { 0x0000050B, 0x0002 }, /* R1291 - AIF1 Frame Ctrl 5 */ + { 0x0000050C, 0x0003 }, /* R1292 - AIF1 Frame Ctrl 6 */ + { 0x0000050D, 0x0004 }, /* R1293 - AIF1 Frame Ctrl 7 */ + { 0x0000050E, 0x0005 }, /* R1294 - AIF1 Frame Ctrl 8 */ + { 0x0000050F, 0x0006 }, /* R1295 - AIF1 Frame Ctrl 9 */ + { 0x00000510, 0x0007 }, /* R1296 - AIF1 Frame Ctrl 10 */ + { 0x00000511, 0x0000 }, /* R1297 - AIF1 Frame Ctrl 11 */ + { 0x00000512, 0x0001 }, /* R1298 - AIF1 Frame Ctrl 12 */ + { 0x00000513, 0x0002 }, /* R1299 - AIF1 Frame Ctrl 13 */ + { 0x00000514, 0x0003 }, /* R1300 - AIF1 Frame Ctrl 14 */ + { 0x00000515, 0x0004 }, /* R1301 - AIF1 Frame Ctrl 15 */ + { 0x00000516, 0x0005 }, /* R1302 - AIF1 Frame Ctrl 16 */ + { 0x00000517, 0x0006 }, /* R1303 - AIF1 Frame Ctrl 17 */ + { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ + { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ + { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ + { 0x0000051B, 0x0000 }, /* R1307 - AIF1 Force Write */ + { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ + { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ + { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ + { 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */ + { 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */ + { 0x00000545, 0x0040 }, /* R1349 - AIF2 Tx BCLK Rate */ + { 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */ + { 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */ + { 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */ + { 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */ + { 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */ + { 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */ + { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ + { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ + { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ + { 0x0000055B, 0x0000 }, /* R1371 - AIF2 Force Write */ + { 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */ + { 0x00000581, 0x0008 }, /* R1409 - AIF3 Tx Pin Ctrl */ + { 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */ + { 0x00000583, 0x0000 }, /* R1411 - AIF3 Rate Ctrl */ + { 0x00000584, 0x0000 }, /* R1412 - AIF3 Format */ + { 0x00000585, 0x0040 }, /* R1413 - AIF3 Tx BCLK Rate */ + { 0x00000586, 0x0040 }, /* R1414 - AIF3 Rx BCLK Rate */ + { 0x00000587, 0x1818 }, /* R1415 - AIF3 Frame Ctrl 1 */ + { 0x00000588, 0x1818 }, /* R1416 - AIF3 Frame Ctrl 2 */ + { 0x00000589, 0x0000 }, /* R1417 - AIF3 Frame Ctrl 3 */ + { 0x0000058A, 0x0001 }, /* R1418 - AIF3 Frame Ctrl 4 */ + { 0x00000591, 0x0000 }, /* R1425 - AIF3 Frame Ctrl 11 */ + { 0x00000592, 0x0001 }, /* R1426 - AIF3 Frame Ctrl 12 */ + { 0x00000599, 0x0000 }, /* R1433 - AIF3 Tx Enables */ + { 0x0000059A, 0x0000 }, /* R1434 - AIF3 Rx Enables */ + { 0x0000059B, 0x0000 }, /* R1435 - AIF3 Force Write */ + { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ + { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ + { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ + { 0x000005E7, 0x0000 }, /* R1511 - SLIMbus Rates 3 */ + { 0x000005E8, 0x0000 }, /* R1512 - SLIMbus Rates 4 */ + { 0x000005E9, 0x0000 }, /* R1513 - SLIMbus Rates 5 */ + { 0x000005EA, 0x0000 }, /* R1514 - SLIMbus Rates 6 */ + { 0x000005EB, 0x0000 }, /* R1515 - SLIMbus Rates 7 */ + { 0x000005EC, 0x0000 }, /* R1516 - SLIMbus Rates 8 */ + { 0x000005F5, 0x0000 }, /* R1525 - SLIMbus RX Channel Enable */ + { 0x000005F6, 0x0000 }, /* R1526 - SLIMbus TX Channel Enable */ + { 0x00000640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */ + { 0x00000641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */ + { 0x00000642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */ + { 0x00000643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */ + { 0x00000644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */ + { 0x00000645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */ + { 0x00000646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */ + { 0x00000647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */ + { 0x00000648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */ + { 0x00000649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */ + { 0x0000064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */ + { 0x0000064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */ + { 0x0000064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */ + { 0x0000064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */ + { 0x0000064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */ + { 0x0000064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */ + { 0x00000660, 0x0000 }, /* R1632 - MICMIX Input 1 Source */ + { 0x00000661, 0x0080 }, /* R1633 - MICMIX Input 1 Volume */ + { 0x00000662, 0x0000 }, /* R1634 - MICMIX Input 2 Source */ + { 0x00000663, 0x0080 }, /* R1635 - MICMIX Input 2 Volume */ + { 0x00000664, 0x0000 }, /* R1636 - MICMIX Input 3 Source */ + { 0x00000665, 0x0080 }, /* R1637 - MICMIX Input 3 Volume */ + { 0x00000666, 0x0000 }, /* R1638 - MICMIX Input 4 Source */ + { 0x00000667, 0x0080 }, /* R1639 - MICMIX Input 4 Volume */ + { 0x00000668, 0x0000 }, /* R1640 - NOISEMIX Input 1 Source */ + { 0x00000669, 0x0080 }, /* R1641 - NOISEMIX Input 1 Volume */ + { 0x0000066A, 0x0000 }, /* R1642 - NOISEMIX Input 2 Source */ + { 0x0000066B, 0x0080 }, /* R1643 - NOISEMIX Input 2 Volume */ + { 0x0000066C, 0x0000 }, /* R1644 - NOISEMIX Input 3 Source */ + { 0x0000066D, 0x0080 }, /* R1645 - NOISEMIX Input 3 Volume */ + { 0x0000066E, 0x0000 }, /* R1646 - NOISEMIX Input 4 Source */ + { 0x0000066F, 0x0080 }, /* R1647 - NOISEMIX Input 4 Volume */ + { 0x00000680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */ + { 0x00000681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */ + { 0x00000682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */ + { 0x00000683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */ + { 0x00000684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */ + { 0x00000685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */ + { 0x00000686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */ + { 0x00000687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */ + { 0x00000688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */ + { 0x00000689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */ + { 0x0000068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */ + { 0x0000068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */ + { 0x0000068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */ + { 0x0000068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */ + { 0x0000068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */ + { 0x0000068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */ + { 0x00000690, 0x0000 }, /* R1680 - OUT2LMIX Input 1 Source */ + { 0x00000691, 0x0080 }, /* R1681 - OUT2LMIX Input 1 Volume */ + { 0x00000692, 0x0000 }, /* R1682 - OUT2LMIX Input 2 Source */ + { 0x00000693, 0x0080 }, /* R1683 - OUT2LMIX Input 2 Volume */ + { 0x00000694, 0x0000 }, /* R1684 - OUT2LMIX Input 3 Source */ + { 0x00000695, 0x0080 }, /* R1685 - OUT2LMIX Input 3 Volume */ + { 0x00000696, 0x0000 }, /* R1686 - OUT2LMIX Input 4 Source */ + { 0x00000697, 0x0080 }, /* R1687 - OUT2LMIX Input 4 Volume */ + { 0x00000698, 0x0000 }, /* R1688 - OUT2RMIX Input 1 Source */ + { 0x00000699, 0x0080 }, /* R1689 - OUT2RMIX Input 1 Volume */ + { 0x0000069A, 0x0000 }, /* R1690 - OUT2RMIX Input 2 Source */ + { 0x0000069B, 0x0080 }, /* R1691 - OUT2RMIX Input 2 Volume */ + { 0x0000069C, 0x0000 }, /* R1692 - OUT2RMIX Input 3 Source */ + { 0x0000069D, 0x0080 }, /* R1693 - OUT2RMIX Input 3 Volume */ + { 0x0000069E, 0x0000 }, /* R1694 - OUT2RMIX Input 4 Source */ + { 0x0000069F, 0x0080 }, /* R1695 - OUT2RMIX Input 4 Volume */ + { 0x000006A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */ + { 0x000006A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */ + { 0x000006A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */ + { 0x000006A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */ + { 0x000006A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */ + { 0x000006A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */ + { 0x000006A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */ + { 0x000006A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */ + { 0x000006B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */ + { 0x000006B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */ + { 0x000006B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */ + { 0x000006B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */ + { 0x000006B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */ + { 0x000006B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */ + { 0x000006B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */ + { 0x000006B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */ + { 0x000006B8, 0x0000 }, /* R1720 - OUT4RMIX Input 1 Source */ + { 0x000006B9, 0x0080 }, /* R1721 - OUT4RMIX Input 1 Volume */ + { 0x000006BA, 0x0000 }, /* R1722 - OUT4RMIX Input 2 Source */ + { 0x000006BB, 0x0080 }, /* R1723 - OUT4RMIX Input 2 Volume */ + { 0x000006BC, 0x0000 }, /* R1724 - OUT4RMIX Input 3 Source */ + { 0x000006BD, 0x0080 }, /* R1725 - OUT4RMIX Input 3 Volume */ + { 0x000006BE, 0x0000 }, /* R1726 - OUT4RMIX Input 4 Source */ + { 0x000006BF, 0x0080 }, /* R1727 - OUT4RMIX Input 4 Volume */ + { 0x000006C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */ + { 0x000006C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */ + { 0x000006C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */ + { 0x000006C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */ + { 0x000006C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */ + { 0x000006C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */ + { 0x000006C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */ + { 0x000006C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */ + { 0x000006C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */ + { 0x000006C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */ + { 0x000006CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */ + { 0x000006CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */ + { 0x000006CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */ + { 0x000006CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */ + { 0x000006CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */ + { 0x000006CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */ + { 0x00000700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */ + { 0x00000701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */ + { 0x00000702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */ + { 0x00000703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */ + { 0x00000704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */ + { 0x00000705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */ + { 0x00000706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */ + { 0x00000707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */ + { 0x00000708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */ + { 0x00000709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */ + { 0x0000070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */ + { 0x0000070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */ + { 0x0000070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */ + { 0x0000070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */ + { 0x0000070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */ + { 0x0000070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */ + { 0x00000710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */ + { 0x00000711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */ + { 0x00000712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */ + { 0x00000713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */ + { 0x00000714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */ + { 0x00000715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */ + { 0x00000716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */ + { 0x00000717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */ + { 0x00000718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */ + { 0x00000719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */ + { 0x0000071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */ + { 0x0000071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */ + { 0x0000071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */ + { 0x0000071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */ + { 0x0000071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */ + { 0x0000071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */ + { 0x00000720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */ + { 0x00000721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */ + { 0x00000722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */ + { 0x00000723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */ + { 0x00000724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */ + { 0x00000725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */ + { 0x00000726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */ + { 0x00000727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */ + { 0x00000728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */ + { 0x00000729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */ + { 0x0000072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */ + { 0x0000072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */ + { 0x0000072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */ + { 0x0000072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */ + { 0x0000072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */ + { 0x0000072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */ + { 0x00000730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */ + { 0x00000731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */ + { 0x00000732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */ + { 0x00000733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */ + { 0x00000734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */ + { 0x00000735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */ + { 0x00000736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */ + { 0x00000737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */ + { 0x00000738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */ + { 0x00000739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */ + { 0x0000073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */ + { 0x0000073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */ + { 0x0000073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */ + { 0x0000073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */ + { 0x0000073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */ + { 0x0000073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */ + { 0x00000740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */ + { 0x00000741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */ + { 0x00000742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */ + { 0x00000743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */ + { 0x00000744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */ + { 0x00000745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */ + { 0x00000746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */ + { 0x00000747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */ + { 0x00000748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */ + { 0x00000749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */ + { 0x0000074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */ + { 0x0000074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */ + { 0x0000074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */ + { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ + { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ + { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */ + { 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */ + { 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */ + { 0x00000783, 0x0080 }, /* R1923 - AIF3TX1MIX Input 2 Volume */ + { 0x00000784, 0x0000 }, /* R1924 - AIF3TX1MIX Input 3 Source */ + { 0x00000785, 0x0080 }, /* R1925 - AIF3TX1MIX Input 3 Volume */ + { 0x00000786, 0x0000 }, /* R1926 - AIF3TX1MIX Input 4 Source */ + { 0x00000787, 0x0080 }, /* R1927 - AIF3TX1MIX Input 4 Volume */ + { 0x00000788, 0x0000 }, /* R1928 - AIF3TX2MIX Input 1 Source */ + { 0x00000789, 0x0080 }, /* R1929 - AIF3TX2MIX Input 1 Volume */ + { 0x0000078A, 0x0000 }, /* R1930 - AIF3TX2MIX Input 2 Source */ + { 0x0000078B, 0x0080 }, /* R1931 - AIF3TX2MIX Input 2 Volume */ + { 0x0000078C, 0x0000 }, /* R1932 - AIF3TX2MIX Input 3 Source */ + { 0x0000078D, 0x0080 }, /* R1933 - AIF3TX2MIX Input 3 Volume */ + { 0x0000078E, 0x0000 }, /* R1934 - AIF3TX2MIX Input 4 Source */ + { 0x0000078F, 0x0080 }, /* R1935 - AIF3TX2MIX Input 4 Volume */ + { 0x000007C0, 0x0000 }, /* R1984 - SLIMTX1MIX Input 1 Source */ + { 0x000007C1, 0x0080 }, /* R1985 - SLIMTX1MIX Input 1 Volume */ + { 0x000007C2, 0x0000 }, /* R1986 - SLIMTX1MIX Input 2 Source */ + { 0x000007C3, 0x0080 }, /* R1987 - SLIMTX1MIX Input 2 Volume */ + { 0x000007C4, 0x0000 }, /* R1988 - SLIMTX1MIX Input 3 Source */ + { 0x000007C5, 0x0080 }, /* R1989 - SLIMTX1MIX Input 3 Volume */ + { 0x000007C6, 0x0000 }, /* R1990 - SLIMTX1MIX Input 4 Source */ + { 0x000007C7, 0x0080 }, /* R1991 - SLIMTX1MIX Input 4 Volume */ + { 0x000007C8, 0x0000 }, /* R1992 - SLIMTX2MIX Input 1 Source */ + { 0x000007C9, 0x0080 }, /* R1993 - SLIMTX2MIX Input 1 Volume */ + { 0x000007CA, 0x0000 }, /* R1994 - SLIMTX2MIX Input 2 Source */ + { 0x000007CB, 0x0080 }, /* R1995 - SLIMTX2MIX Input 2 Volume */ + { 0x000007CC, 0x0000 }, /* R1996 - SLIMTX2MIX Input 3 Source */ + { 0x000007CD, 0x0080 }, /* R1997 - SLIMTX2MIX Input 3 Volume */ + { 0x000007CE, 0x0000 }, /* R1998 - SLIMTX2MIX Input 4 Source */ + { 0x000007CF, 0x0080 }, /* R1999 - SLIMTX2MIX Input 4 Volume */ + { 0x000007D0, 0x0000 }, /* R2000 - SLIMTX3MIX Input 1 Source */ + { 0x000007D1, 0x0080 }, /* R2001 - SLIMTX3MIX Input 1 Volume */ + { 0x000007D2, 0x0000 }, /* R2002 - SLIMTX3MIX Input 2 Source */ + { 0x000007D3, 0x0080 }, /* R2003 - SLIMTX3MIX Input 2 Volume */ + { 0x000007D4, 0x0000 }, /* R2004 - SLIMTX3MIX Input 3 Source */ + { 0x000007D5, 0x0080 }, /* R2005 - SLIMTX3MIX Input 3 Volume */ + { 0x000007D6, 0x0000 }, /* R2006 - SLIMTX3MIX Input 4 Source */ + { 0x000007D7, 0x0080 }, /* R2007 - SLIMTX3MIX Input 4 Volume */ + { 0x000007D8, 0x0000 }, /* R2008 - SLIMTX4MIX Input 1 Source */ + { 0x000007D9, 0x0080 }, /* R2009 - SLIMTX4MIX Input 1 Volume */ + { 0x000007DA, 0x0000 }, /* R2010 - SLIMTX4MIX Input 2 Source */ + { 0x000007DB, 0x0080 }, /* R2011 - SLIMTX4MIX Input 2 Volume */ + { 0x000007DC, 0x0000 }, /* R2012 - SLIMTX4MIX Input 3 Source */ + { 0x000007DD, 0x0080 }, /* R2013 - SLIMTX4MIX Input 3 Volume */ + { 0x000007DE, 0x0000 }, /* R2014 - SLIMTX4MIX Input 4 Source */ + { 0x000007DF, 0x0080 }, /* R2015 - SLIMTX4MIX Input 4 Volume */ + { 0x000007E0, 0x0000 }, /* R2016 - SLIMTX5MIX Input 1 Source */ + { 0x000007E1, 0x0080 }, /* R2017 - SLIMTX5MIX Input 1 Volume */ + { 0x000007E2, 0x0000 }, /* R2018 - SLIMTX5MIX Input 2 Source */ + { 0x000007E3, 0x0080 }, /* R2019 - SLIMTX5MIX Input 2 Volume */ + { 0x000007E4, 0x0000 }, /* R2020 - SLIMTX5MIX Input 3 Source */ + { 0x000007E5, 0x0080 }, /* R2021 - SLIMTX5MIX Input 3 Volume */ + { 0x000007E6, 0x0000 }, /* R2022 - SLIMTX5MIX Input 4 Source */ + { 0x000007E7, 0x0080 }, /* R2023 - SLIMTX5MIX Input 4 Volume */ + { 0x000007E8, 0x0000 }, /* R2024 - SLIMTX6MIX Input 1 Source */ + { 0x000007E9, 0x0080 }, /* R2025 - SLIMTX6MIX Input 1 Volume */ + { 0x000007EA, 0x0000 }, /* R2026 - SLIMTX6MIX Input 2 Source */ + { 0x000007EB, 0x0080 }, /* R2027 - SLIMTX6MIX Input 2 Volume */ + { 0x000007EC, 0x0000 }, /* R2028 - SLIMTX6MIX Input 3 Source */ + { 0x000007ED, 0x0080 }, /* R2029 - SLIMTX6MIX Input 3 Volume */ + { 0x000007EE, 0x0000 }, /* R2030 - SLIMTX6MIX Input 4 Source */ + { 0x000007EF, 0x0080 }, /* R2031 - SLIMTX6MIX Input 4 Volume */ + { 0x000007F0, 0x0000 }, /* R2032 - SLIMTX7MIX Input 1 Source */ + { 0x000007F1, 0x0080 }, /* R2033 - SLIMTX7MIX Input 1 Volume */ + { 0x000007F2, 0x0000 }, /* R2034 - SLIMTX7MIX Input 2 Source */ + { 0x000007F3, 0x0080 }, /* R2035 - SLIMTX7MIX Input 2 Volume */ + { 0x000007F4, 0x0000 }, /* R2036 - SLIMTX7MIX Input 3 Source */ + { 0x000007F5, 0x0080 }, /* R2037 - SLIMTX7MIX Input 3 Volume */ + { 0x000007F6, 0x0000 }, /* R2038 - SLIMTX7MIX Input 4 Source */ + { 0x000007F7, 0x0080 }, /* R2039 - SLIMTX7MIX Input 4 Volume */ + { 0x000007F8, 0x0000 }, /* R2040 - SLIMTX8MIX Input 1 Source */ + { 0x000007F9, 0x0080 }, /* R2041 - SLIMTX8MIX Input 1 Volume */ + { 0x000007FA, 0x0000 }, /* R2042 - SLIMTX8MIX Input 2 Source */ + { 0x000007FB, 0x0080 }, /* R2043 - SLIMTX8MIX Input 2 Volume */ + { 0x000007FC, 0x0000 }, /* R2044 - SLIMTX8MIX Input 3 Source */ + { 0x000007FD, 0x0080 }, /* R2045 - SLIMTX8MIX Input 3 Volume */ + { 0x000007FE, 0x0000 }, /* R2046 - SLIMTX8MIX Input 4 Source */ + { 0x000007FF, 0x0080 }, /* R2047 - SLIMTX8MIX Input 4 Volume */ + { 0x00000880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */ + { 0x00000881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */ + { 0x00000882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */ + { 0x00000883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */ + { 0x00000884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */ + { 0x00000885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */ + { 0x00000886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */ + { 0x00000887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */ + { 0x00000888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */ + { 0x00000889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */ + { 0x0000088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */ + { 0x0000088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */ + { 0x0000088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */ + { 0x0000088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */ + { 0x0000088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */ + { 0x0000088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */ + { 0x00000890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */ + { 0x00000891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */ + { 0x00000892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */ + { 0x00000893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */ + { 0x00000894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */ + { 0x00000895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */ + { 0x00000896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */ + { 0x00000897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */ + { 0x00000898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */ + { 0x00000899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */ + { 0x0000089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */ + { 0x0000089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */ + { 0x0000089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */ + { 0x0000089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */ + { 0x0000089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */ + { 0x0000089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */ + { 0x000008C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */ + { 0x000008C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */ + { 0x000008C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */ + { 0x000008C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */ + { 0x000008C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */ + { 0x000008C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */ + { 0x000008C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */ + { 0x000008C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */ + { 0x000008C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */ + { 0x000008C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */ + { 0x000008CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */ + { 0x000008CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */ + { 0x000008CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */ + { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ + { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ + { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ + { 0x000008D0, 0x0000 }, /* R2256 - DRC2LMIX Input 1 Source */ + { 0x000008D1, 0x0080 }, /* R2257 - DRC2LMIX Input 1 Volume */ + { 0x000008D2, 0x0000 }, /* R2258 - DRC2LMIX Input 2 Source */ + { 0x000008D3, 0x0080 }, /* R2259 - DRC2LMIX Input 2 Volume */ + { 0x000008D4, 0x0000 }, /* R2260 - DRC2LMIX Input 3 Source */ + { 0x000008D5, 0x0080 }, /* R2261 - DRC2LMIX Input 3 Volume */ + { 0x000008D6, 0x0000 }, /* R2262 - DRC2LMIX Input 4 Source */ + { 0x000008D7, 0x0080 }, /* R2263 - DRC2LMIX Input 4 Volume */ + { 0x000008D8, 0x0000 }, /* R2264 - DRC2RMIX Input 1 Source */ + { 0x000008D9, 0x0080 }, /* R2265 - DRC2RMIX Input 1 Volume */ + { 0x000008DA, 0x0000 }, /* R2266 - DRC2RMIX Input 2 Source */ + { 0x000008DB, 0x0080 }, /* R2267 - DRC2RMIX Input 2 Volume */ + { 0x000008DC, 0x0000 }, /* R2268 - DRC2RMIX Input 3 Source */ + { 0x000008DD, 0x0080 }, /* R2269 - DRC2RMIX Input 3 Volume */ + { 0x000008DE, 0x0000 }, /* R2270 - DRC2RMIX Input 4 Source */ + { 0x000008DF, 0x0080 }, /* R2271 - DRC2RMIX Input 4 Volume */ + { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ + { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ + { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ + { 0x00000903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */ + { 0x00000904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */ + { 0x00000905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */ + { 0x00000906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */ + { 0x00000907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */ + { 0x00000908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */ + { 0x00000909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */ + { 0x0000090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */ + { 0x0000090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */ + { 0x0000090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */ + { 0x0000090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */ + { 0x0000090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */ + { 0x0000090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */ + { 0x00000910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */ + { 0x00000911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */ + { 0x00000912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */ + { 0x00000913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */ + { 0x00000914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */ + { 0x00000915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */ + { 0x00000916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */ + { 0x00000917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */ + { 0x00000918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */ + { 0x00000919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */ + { 0x0000091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */ + { 0x0000091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */ + { 0x0000091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */ + { 0x0000091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */ + { 0x0000091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */ + { 0x0000091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */ + { 0x00000940, 0x0000 }, /* R2368 - DSP1LMIX Input 1 Source */ + { 0x00000941, 0x0080 }, /* R2369 - DSP1LMIX Input 1 Volume */ + { 0x00000942, 0x0000 }, /* R2370 - DSP1LMIX Input 2 Source */ + { 0x00000943, 0x0080 }, /* R2371 - DSP1LMIX Input 2 Volume */ + { 0x00000944, 0x0000 }, /* R2372 - DSP1LMIX Input 3 Source */ + { 0x00000945, 0x0080 }, /* R2373 - DSP1LMIX Input 3 Volume */ + { 0x00000946, 0x0000 }, /* R2374 - DSP1LMIX Input 4 Source */ + { 0x00000947, 0x0080 }, /* R2375 - DSP1LMIX Input 4 Volume */ + { 0x00000948, 0x0000 }, /* R2376 - DSP1RMIX Input 1 Source */ + { 0x00000949, 0x0080 }, /* R2377 - DSP1RMIX Input 1 Volume */ + { 0x0000094A, 0x0000 }, /* R2378 - DSP1RMIX Input 2 Source */ + { 0x0000094B, 0x0080 }, /* R2379 - DSP1RMIX Input 2 Volume */ + { 0x0000094C, 0x0000 }, /* R2380 - DSP1RMIX Input 3 Source */ + { 0x0000094D, 0x0080 }, /* R2381 - DSP1RMIX Input 3 Volume */ + { 0x0000094E, 0x0000 }, /* R2382 - DSP1RMIX Input 4 Source */ + { 0x0000094F, 0x0080 }, /* R2383 - DSP1RMIX Input 4 Volume */ + { 0x00000950, 0x0000 }, /* R2384 - DSP1AUX1MIX Input 1 Source */ + { 0x00000958, 0x0000 }, /* R2392 - DSP1AUX2MIX Input 1 Source */ + { 0x00000960, 0x0000 }, /* R2400 - DSP1AUX3MIX Input 1 Source */ + { 0x00000968, 0x0000 }, /* R2408 - DSP1AUX4MIX Input 1 Source */ + { 0x00000970, 0x0000 }, /* R2416 - DSP1AUX5MIX Input 1 Source */ + { 0x00000978, 0x0000 }, /* R2424 - DSP1AUX6MIX Input 1 Source */ + { 0x00000A80, 0x0000 }, /* R2688 - ASRC1LMIX Input 1 Source */ + { 0x00000A88, 0x0000 }, /* R2696 - ASRC1RMIX Input 1 Source */ + { 0x00000A90, 0x0000 }, /* R2704 - ASRC2LMIX Input 1 Source */ + { 0x00000A98, 0x0000 }, /* R2712 - ASRC2RMIX Input 1 Source */ + { 0x00000B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */ + { 0x00000B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */ + { 0x00000B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */ + { 0x00000B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */ + { 0x00000B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */ + { 0x00000B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */ + { 0x00000B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */ + { 0x00000B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */ + { 0x00000C00, 0xA101 }, /* R3072 - GPIO1 CTRL */ + { 0x00000C01, 0xA101 }, /* R3073 - GPIO2 CTRL */ + { 0x00000C02, 0xA101 }, /* R3074 - GPIO3 CTRL */ + { 0x00000C03, 0xA101 }, /* R3075 - GPIO4 CTRL */ + { 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */ + { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */ + { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */ + { 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */ + { 0x00000C21, 0x8001 }, /* R3105 - Misc Pad Ctrl 2 */ + { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */ + { 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */ + { 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */ + { 0x00000C25, 0x0000 }, /* R3109 - Misc Pad Ctrl 6 */ + { 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */ + { 0x00000D09, 0xFFFF }, /* R3337 - Interrupt Status 2 Mask */ + { 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */ + { 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */ + { 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */ + { 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */ + { 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */ + { 0x00000D19, 0xFFFF }, /* R3353 - IRQ2 Status 2 Mask */ + { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ + { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ + { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ + { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ + { 0x00000D41, 0x0000 }, /* R3393 - ADSP2 IRQ0 */ + { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ + { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ + { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ + { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ + { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */ + { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ + { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ + { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ + { 0x00000E13, 0x03FE }, /* R3603 - EQ1_4 */ + { 0x00000E14, 0x00E0 }, /* R3604 - EQ1_5 */ + { 0x00000E15, 0x1EC4 }, /* R3605 - EQ1_6 */ + { 0x00000E16, 0xF136 }, /* R3606 - EQ1_7 */ + { 0x00000E17, 0x0409 }, /* R3607 - EQ1_8 */ + { 0x00000E18, 0x04CC }, /* R3608 - EQ1_9 */ + { 0x00000E19, 0x1C9B }, /* R3609 - EQ1_10 */ + { 0x00000E1A, 0xF337 }, /* R3610 - EQ1_11 */ + { 0x00000E1B, 0x040B }, /* R3611 - EQ1_12 */ + { 0x00000E1C, 0x0CBB }, /* R3612 - EQ1_13 */ + { 0x00000E1D, 0x16F8 }, /* R3613 - EQ1_14 */ + { 0x00000E1E, 0xF7D9 }, /* R3614 - EQ1_15 */ + { 0x00000E1F, 0x040A }, /* R3615 - EQ1_16 */ + { 0x00000E20, 0x1F14 }, /* R3616 - EQ1_17 */ + { 0x00000E21, 0x058C }, /* R3617 - EQ1_18 */ + { 0x00000E22, 0x0563 }, /* R3618 - EQ1_19 */ + { 0x00000E23, 0x4000 }, /* R3619 - EQ1_20 */ + { 0x00000E24, 0x0B75 }, /* R3620 - EQ1_21 */ + { 0x00000E26, 0x6318 }, /* R3622 - EQ2_1 */ + { 0x00000E27, 0x6300 }, /* R3623 - EQ2_2 */ + { 0x00000E28, 0x0FC8 }, /* R3624 - EQ2_3 */ + { 0x00000E29, 0x03FE }, /* R3625 - EQ2_4 */ + { 0x00000E2A, 0x00E0 }, /* R3626 - EQ2_5 */ + { 0x00000E2B, 0x1EC4 }, /* R3627 - EQ2_6 */ + { 0x00000E2C, 0xF136 }, /* R3628 - EQ2_7 */ + { 0x00000E2D, 0x0409 }, /* R3629 - EQ2_8 */ + { 0x00000E2E, 0x04CC }, /* R3630 - EQ2_9 */ + { 0x00000E2F, 0x1C9B }, /* R3631 - EQ2_10 */ + { 0x00000E30, 0xF337 }, /* R3632 - EQ2_11 */ + { 0x00000E31, 0x040B }, /* R3633 - EQ2_12 */ + { 0x00000E32, 0x0CBB }, /* R3634 - EQ2_13 */ + { 0x00000E33, 0x16F8 }, /* R3635 - EQ2_14 */ + { 0x00000E34, 0xF7D9 }, /* R3636 - EQ2_15 */ + { 0x00000E35, 0x040A }, /* R3637 - EQ2_16 */ + { 0x00000E36, 0x1F14 }, /* R3638 - EQ2_17 */ + { 0x00000E37, 0x058C }, /* R3639 - EQ2_18 */ + { 0x00000E38, 0x0563 }, /* R3640 - EQ2_19 */ + { 0x00000E39, 0x4000 }, /* R3641 - EQ2_20 */ + { 0x00000E3A, 0x0B75 }, /* R3642 - EQ2_21 */ + { 0x00000E3C, 0x6318 }, /* R3644 - EQ3_1 */ + { 0x00000E3D, 0x6300 }, /* R3645 - EQ3_2 */ + { 0x00000E3E, 0x0FC8 }, /* R3646 - EQ3_3 */ + { 0x00000E3F, 0x03FE }, /* R3647 - EQ3_4 */ + { 0x00000E40, 0x00E0 }, /* R3648 - EQ3_5 */ + { 0x00000E41, 0x1EC4 }, /* R3649 - EQ3_6 */ + { 0x00000E42, 0xF136 }, /* R3650 - EQ3_7 */ + { 0x00000E43, 0x0409 }, /* R3651 - EQ3_8 */ + { 0x00000E44, 0x04CC }, /* R3652 - EQ3_9 */ + { 0x00000E45, 0x1C9B }, /* R3653 - EQ3_10 */ + { 0x00000E46, 0xF337 }, /* R3654 - EQ3_11 */ + { 0x00000E47, 0x040B }, /* R3655 - EQ3_12 */ + { 0x00000E48, 0x0CBB }, /* R3656 - EQ3_13 */ + { 0x00000E49, 0x16F8 }, /* R3657 - EQ3_14 */ + { 0x00000E4A, 0xF7D9 }, /* R3658 - EQ3_15 */ + { 0x00000E4B, 0x040A }, /* R3659 - EQ3_16 */ + { 0x00000E4C, 0x1F14 }, /* R3660 - EQ3_17 */ + { 0x00000E4D, 0x058C }, /* R3661 - EQ3_18 */ + { 0x00000E4E, 0x0563 }, /* R3662 - EQ3_19 */ + { 0x00000E4F, 0x4000 }, /* R3663 - EQ3_20 */ + { 0x00000E50, 0x0B75 }, /* R3664 - EQ3_21 */ + { 0x00000E52, 0x6318 }, /* R3666 - EQ4_1 */ + { 0x00000E53, 0x6300 }, /* R3667 - EQ4_2 */ + { 0x00000E54, 0x0FC8 }, /* R3668 - EQ4_3 */ + { 0x00000E55, 0x03FE }, /* R3669 - EQ4_4 */ + { 0x00000E56, 0x00E0 }, /* R3670 - EQ4_5 */ + { 0x00000E57, 0x1EC4 }, /* R3671 - EQ4_6 */ + { 0x00000E58, 0xF136 }, /* R3672 - EQ4_7 */ + { 0x00000E59, 0x0409 }, /* R3673 - EQ4_8 */ + { 0x00000E5A, 0x04CC }, /* R3674 - EQ4_9 */ + { 0x00000E5B, 0x1C9B }, /* R3675 - EQ4_10 */ + { 0x00000E5C, 0xF337 }, /* R3676 - EQ4_11 */ + { 0x00000E5D, 0x040B }, /* R3677 - EQ4_12 */ + { 0x00000E5E, 0x0CBB }, /* R3678 - EQ4_13 */ + { 0x00000E5F, 0x16F8 }, /* R3679 - EQ4_14 */ + { 0x00000E60, 0xF7D9 }, /* R3680 - EQ4_15 */ + { 0x00000E61, 0x040A }, /* R3681 - EQ4_16 */ + { 0x00000E62, 0x1F14 }, /* R3682 - EQ4_17 */ + { 0x00000E63, 0x058C }, /* R3683 - EQ4_18 */ + { 0x00000E64, 0x0563 }, /* R3684 - EQ4_19 */ + { 0x00000E65, 0x4000 }, /* R3685 - EQ4_20 */ + { 0x00000E66, 0x0B75 }, /* R3686 - EQ4_21 */ + { 0x00000E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */ + { 0x00000E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */ + { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ + { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ + { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ + { 0x00000E89, 0x0018 }, /* R3721 - DRC2 ctrl1 */ + { 0x00000E8A, 0x0933 }, /* R3722 - DRC2 ctrl2 */ + { 0x00000E8B, 0x0018 }, /* R3723 - DRC2 ctrl3 */ + { 0x00000E8C, 0x0000 }, /* R3724 - DRC2 ctrl4 */ + { 0x00000E8D, 0x0000 }, /* R3725 - DRC2 ctrl5 */ + { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ + { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ + { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ + { 0x00000EC5, 0x0000 }, /* R3781 - HPLPF2_2 */ + { 0x00000EC8, 0x0000 }, /* R3784 - HPLPF3_1 */ + { 0x00000EC9, 0x0000 }, /* R3785 - HPLPF3_2 */ + { 0x00000ECC, 0x0000 }, /* R3788 - HPLPF4_1 */ + { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ + { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */ + { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */ + { 0x00000EE3, 0x4000 }, /* R3811 - ASRC_RATE2 */ + { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ + { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ + { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ + { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ + { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ + { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ + { 0x00000EF6, 0x0000 }, /* R3830 - ISRC 3 CTRL 1 */ + { 0x00000EF7, 0x0000 }, /* R3831 - ISRC 3 CTRL 2 */ + { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */ + { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ + { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ +}; + +static bool wm5102_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_CTRL_IF_SPI_CFG_1: + case ARIZONA_CTRL_IF_I2C1_CFG_1: + case ARIZONA_CTRL_IF_STATUS_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_WRITE_SEQUENCER_PROM: + case ARIZONA_TONE_GENERATOR_1: + case ARIZONA_TONE_GENERATOR_2: + case ARIZONA_TONE_GENERATOR_3: + case ARIZONA_TONE_GENERATOR_4: + case ARIZONA_TONE_GENERATOR_5: + case ARIZONA_PWM_DRIVE_1: + case ARIZONA_PWM_DRIVE_2: + case ARIZONA_PWM_DRIVE_3: + case ARIZONA_WAKE_CONTROL: + case ARIZONA_SEQUENCE_CONTROL: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4: + case ARIZONA_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: + case ARIZONA_HAPTICS_PHASE_1_INTENSITY: + case ARIZONA_HAPTICS_PHASE_1_DURATION: + case ARIZONA_HAPTICS_PHASE_2_INTENSITY: + case ARIZONA_HAPTICS_PHASE_2_DURATION: + case ARIZONA_HAPTICS_PHASE_3_INTENSITY: + case ARIZONA_HAPTICS_PHASE_3_DURATION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_CLOCK_32K_1: + case ARIZONA_SYSTEM_CLOCK_1: + case ARIZONA_SAMPLE_RATE_1: + case ARIZONA_SAMPLE_RATE_2: + case ARIZONA_SAMPLE_RATE_3: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_CLOCK_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_OUTPUT_SYSTEM_CLOCK: + case ARIZONA_OUTPUT_ASYNC_CLOCK: + case ARIZONA_RATE_ESTIMATOR_1: + case ARIZONA_RATE_ESTIMATOR_2: + case ARIZONA_RATE_ESTIMATOR_3: + case ARIZONA_RATE_ESTIMATOR_4: + case ARIZONA_RATE_ESTIMATOR_5: + case ARIZONA_FLL1_CONTROL_1: + case ARIZONA_FLL1_CONTROL_2: + case ARIZONA_FLL1_CONTROL_3: + case ARIZONA_FLL1_CONTROL_4: + case ARIZONA_FLL1_CONTROL_5: + case ARIZONA_FLL1_CONTROL_6: + case ARIZONA_FLL1_LOOP_FILTER_TEST_1: + case ARIZONA_FLL1_SYNCHRONISER_1: + case ARIZONA_FLL1_SYNCHRONISER_2: + case ARIZONA_FLL1_SYNCHRONISER_3: + case ARIZONA_FLL1_SYNCHRONISER_4: + case ARIZONA_FLL1_SYNCHRONISER_5: + case ARIZONA_FLL1_SYNCHRONISER_6: + case ARIZONA_FLL1_SPREAD_SPECTRUM: + case ARIZONA_FLL1_GPIO_CLOCK: + case ARIZONA_FLL2_CONTROL_1: + case ARIZONA_FLL2_CONTROL_2: + case ARIZONA_FLL2_CONTROL_3: + case ARIZONA_FLL2_CONTROL_4: + case ARIZONA_FLL2_CONTROL_5: + case ARIZONA_FLL2_CONTROL_6: + case ARIZONA_FLL2_LOOP_FILTER_TEST_1: + case ARIZONA_FLL2_SYNCHRONISER_1: + case ARIZONA_FLL2_SYNCHRONISER_2: + case ARIZONA_FLL2_SYNCHRONISER_3: + case ARIZONA_FLL2_SYNCHRONISER_4: + case ARIZONA_FLL2_SYNCHRONISER_5: + case ARIZONA_FLL2_SYNCHRONISER_6: + case ARIZONA_FLL2_SPREAD_SPECTRUM: + case ARIZONA_FLL2_GPIO_CLOCK: + case ARIZONA_MIC_CHARGE_PUMP_1: + case ARIZONA_LDO1_CONTROL_1: + case ARIZONA_LDO2_CONTROL_1: + case ARIZONA_MIC_BIAS_CTRL_1: + case ARIZONA_MIC_BIAS_CTRL_2: + case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_ACCESSORY_DETECT_MODE_1: + case ARIZONA_HEADPHONE_DETECT_1: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MIC_DETECT_1: + case ARIZONA_MIC_DETECT_2: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_NOISE_MIX_CONTROL_1: + case ARIZONA_ISOLATION_CONTROL: + case ARIZONA_JACK_DETECT_ANALOGUE: + case ARIZONA_INPUT_ENABLES: + case ARIZONA_INPUT_RATE: + case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_IN1L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1L: + case ARIZONA_DMIC1L_CONTROL: + case ARIZONA_IN1R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1R: + case ARIZONA_DMIC1R_CONTROL: + case ARIZONA_IN2L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2L: + case ARIZONA_DMIC2L_CONTROL: + case ARIZONA_IN2R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2R: + case ARIZONA_DMIC2R_CONTROL: + case ARIZONA_IN3L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_3L: + case ARIZONA_DMIC3L_CONTROL: + case ARIZONA_IN3R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_3R: + case ARIZONA_DMIC3R_CONTROL: + case ARIZONA_OUTPUT_ENABLES_1: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_OUTPUT_RATE_1: + case ARIZONA_OUTPUT_VOLUME_RAMP: + case ARIZONA_OUTPUT_PATH_CONFIG_1L: + case ARIZONA_DAC_DIGITAL_VOLUME_1L: + case ARIZONA_DAC_VOLUME_LIMIT_1L: + case ARIZONA_NOISE_GATE_SELECT_1L: + case ARIZONA_OUTPUT_PATH_CONFIG_1R: + case ARIZONA_DAC_DIGITAL_VOLUME_1R: + case ARIZONA_DAC_VOLUME_LIMIT_1R: + case ARIZONA_NOISE_GATE_SELECT_1R: + case ARIZONA_OUTPUT_PATH_CONFIG_2L: + case ARIZONA_DAC_DIGITAL_VOLUME_2L: + case ARIZONA_DAC_VOLUME_LIMIT_2L: + case ARIZONA_NOISE_GATE_SELECT_2L: + case ARIZONA_OUTPUT_PATH_CONFIG_2R: + case ARIZONA_DAC_DIGITAL_VOLUME_2R: + case ARIZONA_DAC_VOLUME_LIMIT_2R: + case ARIZONA_NOISE_GATE_SELECT_2R: + case ARIZONA_OUTPUT_PATH_CONFIG_3L: + case ARIZONA_DAC_DIGITAL_VOLUME_3L: + case ARIZONA_DAC_VOLUME_LIMIT_3L: + case ARIZONA_NOISE_GATE_SELECT_3L: + case ARIZONA_OUTPUT_PATH_CONFIG_3R: + case ARIZONA_DAC_DIGITAL_VOLUME_3R: + case ARIZONA_DAC_VOLUME_LIMIT_3R: + case ARIZONA_OUTPUT_PATH_CONFIG_4L: + case ARIZONA_DAC_DIGITAL_VOLUME_4L: + case ARIZONA_OUT_VOLUME_4L: + case ARIZONA_NOISE_GATE_SELECT_4L: + case ARIZONA_OUTPUT_PATH_CONFIG_4R: + case ARIZONA_DAC_DIGITAL_VOLUME_4R: + case ARIZONA_OUT_VOLUME_4R: + case ARIZONA_NOISE_GATE_SELECT_4R: + case ARIZONA_OUTPUT_PATH_CONFIG_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5L: + case ARIZONA_DAC_VOLUME_LIMIT_5L: + case ARIZONA_NOISE_GATE_SELECT_5L: + case ARIZONA_OUTPUT_PATH_CONFIG_5R: + case ARIZONA_DAC_DIGITAL_VOLUME_5R: + case ARIZONA_DAC_VOLUME_LIMIT_5R: + case ARIZONA_NOISE_GATE_SELECT_5R: + case ARIZONA_DAC_AEC_CONTROL_1: + case ARIZONA_NOISE_GATE_CONTROL: + case ARIZONA_PDM_SPK1_CTRL_1: + case ARIZONA_PDM_SPK1_CTRL_2: + case ARIZONA_DAC_COMP_1: + case ARIZONA_DAC_COMP_2: + case ARIZONA_DAC_COMP_3: + case ARIZONA_DAC_COMP_4: + case ARIZONA_AIF1_BCLK_CTRL: + case ARIZONA_AIF1_TX_PIN_CTRL: + case ARIZONA_AIF1_RX_PIN_CTRL: + case ARIZONA_AIF1_RATE_CTRL: + case ARIZONA_AIF1_FORMAT: + case ARIZONA_AIF1_TX_BCLK_RATE: + case ARIZONA_AIF1_RX_BCLK_RATE: + case ARIZONA_AIF1_FRAME_CTRL_1: + case ARIZONA_AIF1_FRAME_CTRL_2: + case ARIZONA_AIF1_FRAME_CTRL_3: + case ARIZONA_AIF1_FRAME_CTRL_4: + case ARIZONA_AIF1_FRAME_CTRL_5: + case ARIZONA_AIF1_FRAME_CTRL_6: + case ARIZONA_AIF1_FRAME_CTRL_7: + case ARIZONA_AIF1_FRAME_CTRL_8: + case ARIZONA_AIF1_FRAME_CTRL_9: + case ARIZONA_AIF1_FRAME_CTRL_10: + case ARIZONA_AIF1_FRAME_CTRL_11: + case ARIZONA_AIF1_FRAME_CTRL_12: + case ARIZONA_AIF1_FRAME_CTRL_13: + case ARIZONA_AIF1_FRAME_CTRL_14: + case ARIZONA_AIF1_FRAME_CTRL_15: + case ARIZONA_AIF1_FRAME_CTRL_16: + case ARIZONA_AIF1_FRAME_CTRL_17: + case ARIZONA_AIF1_FRAME_CTRL_18: + case ARIZONA_AIF1_TX_ENABLES: + case ARIZONA_AIF1_RX_ENABLES: + case ARIZONA_AIF1_FORCE_WRITE: + case ARIZONA_AIF2_BCLK_CTRL: + case ARIZONA_AIF2_TX_PIN_CTRL: + case ARIZONA_AIF2_RX_PIN_CTRL: + case ARIZONA_AIF2_RATE_CTRL: + case ARIZONA_AIF2_FORMAT: + case ARIZONA_AIF2_TX_BCLK_RATE: + case ARIZONA_AIF2_RX_BCLK_RATE: + case ARIZONA_AIF2_FRAME_CTRL_1: + case ARIZONA_AIF2_FRAME_CTRL_2: + case ARIZONA_AIF2_FRAME_CTRL_3: + case ARIZONA_AIF2_FRAME_CTRL_4: + case ARIZONA_AIF2_FRAME_CTRL_11: + case ARIZONA_AIF2_FRAME_CTRL_12: + case ARIZONA_AIF2_TX_ENABLES: + case ARIZONA_AIF2_RX_ENABLES: + case ARIZONA_AIF2_FORCE_WRITE: + case ARIZONA_AIF3_BCLK_CTRL: + case ARIZONA_AIF3_TX_PIN_CTRL: + case ARIZONA_AIF3_RX_PIN_CTRL: + case ARIZONA_AIF3_RATE_CTRL: + case ARIZONA_AIF3_FORMAT: + case ARIZONA_AIF3_TX_BCLK_RATE: + case ARIZONA_AIF3_RX_BCLK_RATE: + case ARIZONA_AIF3_FRAME_CTRL_1: + case ARIZONA_AIF3_FRAME_CTRL_2: + case ARIZONA_AIF3_FRAME_CTRL_3: + case ARIZONA_AIF3_FRAME_CTRL_4: + case ARIZONA_AIF3_FRAME_CTRL_11: + case ARIZONA_AIF3_FRAME_CTRL_12: + case ARIZONA_AIF3_TX_ENABLES: + case ARIZONA_AIF3_RX_ENABLES: + case ARIZONA_AIF3_FORCE_WRITE: + case ARIZONA_SLIMBUS_FRAMER_REF_GEAR: + case ARIZONA_SLIMBUS_RATES_1: + case ARIZONA_SLIMBUS_RATES_2: + case ARIZONA_SLIMBUS_RATES_3: + case ARIZONA_SLIMBUS_RATES_4: + case ARIZONA_SLIMBUS_RATES_5: + case ARIZONA_SLIMBUS_RATES_6: + case ARIZONA_SLIMBUS_RATES_7: + case ARIZONA_SLIMBUS_RATES_8: + case ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_PWM1MIX_INPUT_1_SOURCE: + case ARIZONA_PWM1MIX_INPUT_1_VOLUME: + case ARIZONA_PWM1MIX_INPUT_2_SOURCE: + case ARIZONA_PWM1MIX_INPUT_2_VOLUME: + case ARIZONA_PWM1MIX_INPUT_3_SOURCE: + case ARIZONA_PWM1MIX_INPUT_3_VOLUME: + case ARIZONA_PWM1MIX_INPUT_4_SOURCE: + case ARIZONA_PWM1MIX_INPUT_4_VOLUME: + case ARIZONA_PWM2MIX_INPUT_1_SOURCE: + case ARIZONA_PWM2MIX_INPUT_1_VOLUME: + case ARIZONA_PWM2MIX_INPUT_2_SOURCE: + case ARIZONA_PWM2MIX_INPUT_2_VOLUME: + case ARIZONA_PWM2MIX_INPUT_3_SOURCE: + case ARIZONA_PWM2MIX_INPUT_3_VOLUME: + case ARIZONA_PWM2MIX_INPUT_4_SOURCE: + case ARIZONA_PWM2MIX_INPUT_4_VOLUME: + case ARIZONA_MICMIX_INPUT_1_SOURCE: + case ARIZONA_MICMIX_INPUT_1_VOLUME: + case ARIZONA_MICMIX_INPUT_2_SOURCE: + case ARIZONA_MICMIX_INPUT_2_VOLUME: + case ARIZONA_MICMIX_INPUT_3_SOURCE: + case ARIZONA_MICMIX_INPUT_3_VOLUME: + case ARIZONA_MICMIX_INPUT_4_SOURCE: + case ARIZONA_MICMIX_INPUT_4_VOLUME: + case ARIZONA_NOISEMIX_INPUT_1_SOURCE: + case ARIZONA_NOISEMIX_INPUT_1_VOLUME: + case ARIZONA_NOISEMIX_INPUT_2_SOURCE: + case ARIZONA_NOISEMIX_INPUT_2_VOLUME: + case ARIZONA_NOISEMIX_INPUT_3_SOURCE: + case ARIZONA_NOISEMIX_INPUT_3_VOLUME: + case ARIZONA_NOISEMIX_INPUT_4_SOURCE: + case ARIZONA_NOISEMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME: + case ARIZONA_EQ1MIX_INPUT_1_SOURCE: + case ARIZONA_EQ1MIX_INPUT_1_VOLUME: + case ARIZONA_EQ1MIX_INPUT_2_SOURCE: + case ARIZONA_EQ1MIX_INPUT_2_VOLUME: + case ARIZONA_EQ1MIX_INPUT_3_SOURCE: + case ARIZONA_EQ1MIX_INPUT_3_VOLUME: + case ARIZONA_EQ1MIX_INPUT_4_SOURCE: + case ARIZONA_EQ1MIX_INPUT_4_VOLUME: + case ARIZONA_EQ2MIX_INPUT_1_SOURCE: + case ARIZONA_EQ2MIX_INPUT_1_VOLUME: + case ARIZONA_EQ2MIX_INPUT_2_SOURCE: + case ARIZONA_EQ2MIX_INPUT_2_VOLUME: + case ARIZONA_EQ2MIX_INPUT_3_SOURCE: + case ARIZONA_EQ2MIX_INPUT_3_VOLUME: + case ARIZONA_EQ2MIX_INPUT_4_SOURCE: + case ARIZONA_EQ2MIX_INPUT_4_VOLUME: + case ARIZONA_EQ3MIX_INPUT_1_SOURCE: + case ARIZONA_EQ3MIX_INPUT_1_VOLUME: + case ARIZONA_EQ3MIX_INPUT_2_SOURCE: + case ARIZONA_EQ3MIX_INPUT_2_VOLUME: + case ARIZONA_EQ3MIX_INPUT_3_SOURCE: + case ARIZONA_EQ3MIX_INPUT_3_VOLUME: + case ARIZONA_EQ3MIX_INPUT_4_SOURCE: + case ARIZONA_EQ3MIX_INPUT_4_VOLUME: + case ARIZONA_EQ4MIX_INPUT_1_SOURCE: + case ARIZONA_EQ4MIX_INPUT_1_VOLUME: + case ARIZONA_EQ4MIX_INPUT_2_SOURCE: + case ARIZONA_EQ4MIX_INPUT_2_VOLUME: + case ARIZONA_EQ4MIX_INPUT_3_SOURCE: + case ARIZONA_EQ4MIX_INPUT_3_VOLUME: + case ARIZONA_EQ4MIX_INPUT_4_SOURCE: + case ARIZONA_EQ4MIX_INPUT_4_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_4_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_4_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_4_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_1_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_1_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_2_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_2_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_3_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_3_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_4_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_4_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_1_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_1_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_2_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_2_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_3_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_3_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_4_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_4_VOLUME: + case ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX2MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX3MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX4MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX5MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX6MIX_INPUT_1_SOURCE: + case ARIZONA_ASRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC2LMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC2RMIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE: + case ARIZONA_GPIO1_CTRL: + case ARIZONA_GPIO2_CTRL: + case ARIZONA_GPIO3_CTRL: + case ARIZONA_GPIO4_CTRL: + case ARIZONA_GPIO5_CTRL: + case ARIZONA_IRQ_CTRL_1: + case ARIZONA_GPIO_DEBOUNCE_CONFIG: + case ARIZONA_MISC_PAD_CTRL_1: + case ARIZONA_MISC_PAD_CTRL_2: + case ARIZONA_MISC_PAD_CTRL_3: + case ARIZONA_MISC_PAD_CTRL_4: + case ARIZONA_MISC_PAD_CTRL_5: + case ARIZONA_MISC_PAD_CTRL_6: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_INTERRUPT_STATUS_1_MASK: + case ARIZONA_INTERRUPT_STATUS_2_MASK: + case ARIZONA_INTERRUPT_STATUS_3_MASK: + case ARIZONA_INTERRUPT_STATUS_4_MASK: + case ARIZONA_INTERRUPT_STATUS_5_MASK: + case ARIZONA_INTERRUPT_CONTROL: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_2: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_IRQ2_STATUS_1_MASK: + case ARIZONA_IRQ2_STATUS_2_MASK: + case ARIZONA_IRQ2_STATUS_3_MASK: + case ARIZONA_IRQ2_STATUS_4_MASK: + case ARIZONA_IRQ2_STATUS_5_MASK: + case ARIZONA_IRQ2_CONTROL: + case ARIZONA_INTERRUPT_RAW_STATUS_2: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_ADSP2_IRQ0: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_MASK_IRQ1: + case ARIZONA_AOD_IRQ_MASK_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_JACK_DETECT_DEBOUNCE: + case ARIZONA_FX_CTRL1: + case ARIZONA_FX_CTRL2: + case ARIZONA_EQ1_1: + case ARIZONA_EQ1_2: + case ARIZONA_EQ1_3: + case ARIZONA_EQ1_4: + case ARIZONA_EQ1_5: + case ARIZONA_EQ1_6: + case ARIZONA_EQ1_7: + case ARIZONA_EQ1_8: + case ARIZONA_EQ1_9: + case ARIZONA_EQ1_10: + case ARIZONA_EQ1_11: + case ARIZONA_EQ1_12: + case ARIZONA_EQ1_13: + case ARIZONA_EQ1_14: + case ARIZONA_EQ1_15: + case ARIZONA_EQ1_16: + case ARIZONA_EQ1_17: + case ARIZONA_EQ1_18: + case ARIZONA_EQ1_19: + case ARIZONA_EQ1_20: + case ARIZONA_EQ1_21: + case ARIZONA_EQ2_1: + case ARIZONA_EQ2_2: + case ARIZONA_EQ2_3: + case ARIZONA_EQ2_4: + case ARIZONA_EQ2_5: + case ARIZONA_EQ2_6: + case ARIZONA_EQ2_7: + case ARIZONA_EQ2_8: + case ARIZONA_EQ2_9: + case ARIZONA_EQ2_10: + case ARIZONA_EQ2_11: + case ARIZONA_EQ2_12: + case ARIZONA_EQ2_13: + case ARIZONA_EQ2_14: + case ARIZONA_EQ2_15: + case ARIZONA_EQ2_16: + case ARIZONA_EQ2_17: + case ARIZONA_EQ2_18: + case ARIZONA_EQ2_19: + case ARIZONA_EQ2_20: + case ARIZONA_EQ2_21: + case ARIZONA_EQ3_1: + case ARIZONA_EQ3_2: + case ARIZONA_EQ3_3: + case ARIZONA_EQ3_4: + case ARIZONA_EQ3_5: + case ARIZONA_EQ3_6: + case ARIZONA_EQ3_7: + case ARIZONA_EQ3_8: + case ARIZONA_EQ3_9: + case ARIZONA_EQ3_10: + case ARIZONA_EQ3_11: + case ARIZONA_EQ3_12: + case ARIZONA_EQ3_13: + case ARIZONA_EQ3_14: + case ARIZONA_EQ3_15: + case ARIZONA_EQ3_16: + case ARIZONA_EQ3_17: + case ARIZONA_EQ3_18: + case ARIZONA_EQ3_19: + case ARIZONA_EQ3_20: + case ARIZONA_EQ3_21: + case ARIZONA_EQ4_1: + case ARIZONA_EQ4_2: + case ARIZONA_EQ4_3: + case ARIZONA_EQ4_4: + case ARIZONA_EQ4_5: + case ARIZONA_EQ4_6: + case ARIZONA_EQ4_7: + case ARIZONA_EQ4_8: + case ARIZONA_EQ4_9: + case ARIZONA_EQ4_10: + case ARIZONA_EQ4_11: + case ARIZONA_EQ4_12: + case ARIZONA_EQ4_13: + case ARIZONA_EQ4_14: + case ARIZONA_EQ4_15: + case ARIZONA_EQ4_16: + case ARIZONA_EQ4_17: + case ARIZONA_EQ4_18: + case ARIZONA_EQ4_19: + case ARIZONA_EQ4_20: + case ARIZONA_EQ4_21: + case ARIZONA_DRC1_CTRL1: + case ARIZONA_DRC1_CTRL2: + case ARIZONA_DRC1_CTRL3: + case ARIZONA_DRC1_CTRL4: + case ARIZONA_DRC1_CTRL5: + case ARIZONA_DRC2_CTRL1: + case ARIZONA_DRC2_CTRL2: + case ARIZONA_DRC2_CTRL3: + case ARIZONA_DRC2_CTRL4: + case ARIZONA_DRC2_CTRL5: + case ARIZONA_HPLPF1_1: + case ARIZONA_HPLPF1_2: + case ARIZONA_HPLPF2_1: + case ARIZONA_HPLPF2_2: + case ARIZONA_HPLPF3_1: + case ARIZONA_HPLPF3_2: + case ARIZONA_HPLPF4_1: + case ARIZONA_HPLPF4_2: + case ARIZONA_ASRC_ENABLE: + case ARIZONA_ASRC_RATE1: + case ARIZONA_ASRC_RATE2: + case ARIZONA_ISRC_1_CTRL_1: + case ARIZONA_ISRC_1_CTRL_2: + case ARIZONA_ISRC_1_CTRL_3: + case ARIZONA_ISRC_2_CTRL_1: + case ARIZONA_ISRC_2_CTRL_2: + case ARIZONA_ISRC_2_CTRL_3: + case ARIZONA_ISRC_3_CTRL_1: + case ARIZONA_ISRC_3_CTRL_2: + case ARIZONA_ISRC_3_CTRL_3: + case ARIZONA_DSP1_CONTROL_1: + case ARIZONA_DSP1_CLOCKING_1: + case ARIZONA_DSP1_STATUS_1: + case ARIZONA_DSP1_STATUS_2: + return true; + default: + return false; + } +} + +static bool wm5102_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_FX_CTRL2: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_2: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_2: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_DSP1_STATUS_1: + case ARIZONA_DSP1_STATUS_2: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MIC_DETECT_3: + return true; + default: + return false; + } +} + +const struct regmap_config wm5102_spi_regmap = { + .reg_bits = 32, + .pad_bits = 16, + .val_bits = 16, + + .max_register = ARIZONA_DSP1_STATUS_2, + .readable_reg = wm5102_readable_register, + .volatile_reg = wm5102_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm5102_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm5102_reg_default), +}; +EXPORT_SYMBOL_GPL(wm5102_spi_regmap); + +const struct regmap_config wm5102_i2c_regmap = { + .reg_bits = 32, + .val_bits = 16, + + .max_register = ARIZONA_DSP1_STATUS_2, + .readable_reg = wm5102_readable_register, + .volatile_reg = wm5102_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm5102_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm5102_reg_default), +}; +EXPORT_SYMBOL_GPL(wm5102_i2c_regmap); diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c new file mode 100644 index 00000000000..bd8782c8896 --- /dev/null +++ b/drivers/mfd/wm5110-tables.c @@ -0,0 +1,2281 @@ +/* + * wm5110-tables.c -- WM5110 data tables + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> + +#include <linux/mfd/arizona/core.h> +#include <linux/mfd/arizona/registers.h> + +#include "arizona.h" + +#define WM5110_NUM_AOD_ISR 2 +#define WM5110_NUM_ISR 5 + +static const struct reg_default wm5110_reva_patch[] = { + { 0x80, 0x3 }, + { 0x44, 0x20 }, + { 0x45, 0x40 }, + { 0x46, 0x60 }, + { 0x47, 0x80 }, + { 0x48, 0xa0 }, + { 0x51, 0x13 }, + { 0x52, 0x33 }, + { 0x53, 0x53 }, + { 0x54, 0x73 }, + { 0x55, 0x75 }, + { 0x56, 0xb3 }, + { 0x2ef, 0x124 }, + { 0x2ef, 0x124 }, + { 0x2f0, 0x124 }, + { 0x2f0, 0x124 }, + { 0x2f1, 0x124 }, + { 0x2f1, 0x124 }, + { 0x2f2, 0x124 }, + { 0x2f2, 0x124 }, + { 0x2f3, 0x124 }, + { 0x2f3, 0x124 }, + { 0x2f4, 0x124 }, + { 0x2f4, 0x124 }, + { 0x2eb, 0x60 }, + { 0x2ec, 0x60 }, + { 0x2ed, 0x60 }, + { 0xc30, 0x3e3e }, + { 0xc30, 0x3e3e }, + { 0xc31, 0x3e }, + { 0xc32, 0x3e3e }, + { 0xc32, 0x3e3e }, + { 0xc33, 0x3e3e }, + { 0xc33, 0x3e3e }, + { 0xc34, 0x3e3e }, + { 0xc34, 0x3e3e }, + { 0xc35, 0x3e3e }, + { 0xc35, 0x3e3e }, + { 0xc36, 0x3e3e }, + { 0xc36, 0x3e3e }, + { 0xc37, 0x3e3e }, + { 0xc37, 0x3e3e }, + { 0xc38, 0x3e3e }, + { 0xc38, 0x3e3e }, + { 0xc30, 0x3e3e }, + { 0xc30, 0x3e3e }, + { 0xc39, 0x3e3e }, + { 0xc39, 0x3e3e }, + { 0xc3a, 0x3e3e }, + { 0xc3a, 0x3e3e }, + { 0xc3b, 0x3e3e }, + { 0xc3b, 0x3e3e }, + { 0xc3c, 0x3e }, + { 0x201, 0x18a5 }, + { 0x201, 0x18a5 }, + { 0x201, 0x18a5 }, + { 0x202, 0x4100 }, + { 0x460, 0xc00 }, + { 0x461, 0x8000 }, + { 0x462, 0xc01 }, + { 0x463, 0x50f0 }, + { 0x464, 0xc01 }, + { 0x465, 0x4820 }, + { 0x466, 0xc01 }, + { 0x466, 0xc01 }, + { 0x467, 0x4040 }, + { 0x468, 0xc01 }, + { 0x468, 0xc01 }, + { 0x469, 0x3940 }, + { 0x46a, 0xc01 }, + { 0x46a, 0xc01 }, + { 0x46a, 0xc01 }, + { 0x46b, 0x3310 }, + { 0x46c, 0x801 }, + { 0x46c, 0x801 }, + { 0x46d, 0x2d80 }, + { 0x46e, 0x801 }, + { 0x46e, 0x801 }, + { 0x46f, 0x2890 }, + { 0x470, 0x801 }, + { 0x470, 0x801 }, + { 0x471, 0x1990 }, + { 0x472, 0x801 }, + { 0x472, 0x801 }, + { 0x473, 0x1450 }, + { 0x474, 0x801 }, + { 0x474, 0x801 }, + { 0x474, 0x801 }, + { 0x475, 0x1020 }, + { 0x476, 0x801 }, + { 0x476, 0x801 }, + { 0x476, 0x801 }, + { 0x477, 0xcd0 }, + { 0x478, 0x806 }, + { 0x478, 0x806 }, + { 0x479, 0xa30 }, + { 0x47a, 0x806 }, + { 0x47a, 0x806 }, + { 0x47b, 0x810 }, + { 0x47c, 0x80e }, + { 0x47c, 0x80e }, + { 0x47d, 0x510 }, + { 0x47e, 0x81f }, + { 0x47e, 0x81f }, + { 0x2DB, 0x0A00 }, + { 0x2DD, 0x0023 }, + { 0x2DF, 0x0102 }, + { 0x80, 0x0 }, + { 0xC20, 0x0002 }, + { 0x209, 0x002A }, +}; + +/* We use a function so we can use ARRAY_SIZE() */ +int wm5110_patch(struct arizona *arizona) +{ + switch (arizona->rev) { + case 0: + case 1: + return regmap_register_patch(arizona->regmap, + wm5110_reva_patch, + ARRAY_SIZE(wm5110_reva_patch)); + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(wm5110_patch); + +static const struct regmap_irq wm5110_aod_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP5_FALL] = { .mask = ARIZONA_GP5_FALL_EINT1 }, + [ARIZONA_IRQ_GP5_RISE] = { .mask = ARIZONA_GP5_RISE_EINT1 }, + [ARIZONA_IRQ_JD_FALL] = { .mask = ARIZONA_JD1_FALL_EINT1 }, + [ARIZONA_IRQ_JD_RISE] = { .mask = ARIZONA_JD1_RISE_EINT1 }, +}; + +const struct regmap_irq_chip wm5110_aod = { + .name = "wm5110 AOD", + .status_base = ARIZONA_AOD_IRQ1, + .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, + .ack_base = ARIZONA_AOD_IRQ1, + .wake_base = ARIZONA_WAKE_CONTROL, + .num_regs = 1, + .irqs = wm5110_aod_irqs, + .num_irqs = ARRAY_SIZE(wm5110_aod_irqs), +}; +EXPORT_SYMBOL_GPL(wm5110_aod); + +static const struct regmap_irq wm5110_irqs[ARIZONA_NUM_IRQ] = { + [ARIZONA_IRQ_GP4] = { .reg_offset = 0, .mask = ARIZONA_GP4_EINT1 }, + [ARIZONA_IRQ_GP3] = { .reg_offset = 0, .mask = ARIZONA_GP3_EINT1 }, + [ARIZONA_IRQ_GP2] = { .reg_offset = 0, .mask = ARIZONA_GP2_EINT1 }, + [ARIZONA_IRQ_GP1] = { .reg_offset = 0, .mask = ARIZONA_GP1_EINT1 }, + + [ARIZONA_IRQ_DSP4_RAM_RDY] = { + .reg_offset = 1, .mask = ARIZONA_DSP4_RAM_RDY_EINT1 + }, + [ARIZONA_IRQ_DSP3_RAM_RDY] = { + .reg_offset = 1, .mask = ARIZONA_DSP3_RAM_RDY_EINT1 + }, + [ARIZONA_IRQ_DSP2_RAM_RDY] = { + .reg_offset = 1, .mask = ARIZONA_DSP2_RAM_RDY_EINT1 + }, + [ARIZONA_IRQ_DSP1_RAM_RDY] = { + .reg_offset = 1, .mask = ARIZONA_DSP1_RAM_RDY_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ8] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ8_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ7] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ7_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ6] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ6_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ5] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ5_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ4] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ4_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ3] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ3_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ2] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ2_EINT1 + }, + [ARIZONA_IRQ_DSP_IRQ1] = { + .reg_offset = 1, .mask = ARIZONA_DSP_IRQ1_EINT1 + }, + + [ARIZONA_IRQ_SPK_SHUTDOWN_WARN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_WARN_EINT1 + }, + [ARIZONA_IRQ_SPK_SHUTDOWN] = { + .reg_offset = 2, .mask = ARIZONA_SPK_SHUTDOWN_EINT1 + }, + [ARIZONA_IRQ_HPDET] = { + .reg_offset = 2, .mask = ARIZONA_HPDET_EINT1 + }, + [ARIZONA_IRQ_MICDET] = { + .reg_offset = 2, .mask = ARIZONA_MICDET_EINT1 + }, + [ARIZONA_IRQ_WSEQ_DONE] = { + .reg_offset = 2, .mask = ARIZONA_WSEQ_DONE_EINT1 + }, + [ARIZONA_IRQ_DRC2_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC2_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_DRC1_SIG_DET] = { + .reg_offset = 2, .mask = ARIZONA_DRC1_SIG_DET_EINT1 + }, + [ARIZONA_IRQ_ASRC2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_ASRC2_LOCK_EINT1 + }, + [ARIZONA_IRQ_ASRC1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_ASRC1_LOCK_EINT1 + }, + [ARIZONA_IRQ_UNDERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_UNDERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_OVERCLOCKED] = { + .reg_offset = 2, .mask = ARIZONA_OVERCLOCKED_EINT1 + }, + [ARIZONA_IRQ_FLL2_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL2_LOCK_EINT1 + }, + [ARIZONA_IRQ_FLL1_LOCK] = { + .reg_offset = 2, .mask = ARIZONA_FLL1_LOCK_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_EINT1 + }, + [ARIZONA_IRQ_CLKGEN_ERR_ASYNC] = { + .reg_offset = 2, .mask = ARIZONA_CLKGEN_ERR_ASYNC_EINT1 + }, + + [ARIZONA_IRQ_ASRC_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ASRC_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF3_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF3_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF2_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF2_ERR_EINT1 + }, + [ARIZONA_IRQ_AIF1_ERR] = { + .reg_offset = 3, .mask = ARIZONA_AIF1_ERR_EINT1 + }, + [ARIZONA_IRQ_CTRLIF_ERR] = { + .reg_offset = 3, .mask = ARIZONA_CTRLIF_ERR_EINT1 + }, + [ARIZONA_IRQ_MIXER_DROPPED_SAMPLES] = { + .reg_offset = 3, .mask = ARIZONA_MIXER_DROPPED_SAMPLE_EINT1 + }, + [ARIZONA_IRQ_ASYNC_CLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_ASYNC_CLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_SYSCLK_ENA_LOW] = { + .reg_offset = 3, .mask = ARIZONA_SYSCLK_ENA_LOW_EINT1 + }, + [ARIZONA_IRQ_ISRC1_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC1_CFG_ERR_EINT1 + }, + [ARIZONA_IRQ_ISRC2_CFG_ERR] = { + .reg_offset = 3, .mask = ARIZONA_ISRC2_CFG_ERR_EINT1 + }, + + [ARIZONA_IRQ_BOOT_DONE] = { + .reg_offset = 4, .mask = ARIZONA_BOOT_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_DAC_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_DAC_DONE_EINT1 + }, + [ARIZONA_IRQ_DCS_HP_DONE] = { + .reg_offset = 4, .mask = ARIZONA_DCS_HP_DONE_EINT1 + }, + [ARIZONA_IRQ_FLL2_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL2_CLOCK_OK_EINT1 + }, + [ARIZONA_IRQ_FLL1_CLOCK_OK] = { + .reg_offset = 4, .mask = ARIZONA_FLL1_CLOCK_OK_EINT1 + }, +}; + +const struct regmap_irq_chip wm5110_irq = { + .name = "wm5110 IRQ", + .status_base = ARIZONA_INTERRUPT_STATUS_1, + .mask_base = ARIZONA_INTERRUPT_STATUS_1_MASK, + .ack_base = ARIZONA_INTERRUPT_STATUS_1, + .num_regs = 5, + .irqs = wm5110_irqs, + .num_irqs = ARRAY_SIZE(wm5110_irqs), +}; +EXPORT_SYMBOL_GPL(wm5110_irq); + +static const struct reg_default wm5110_reg_default[] = { + { 0x00000008, 0x0019 }, /* R8 - Ctrl IF SPI CFG 1 */ + { 0x00000009, 0x0001 }, /* R9 - Ctrl IF I2C1 CFG 1 */ + { 0x0000000A, 0x0001 }, /* R10 - Ctrl IF I2C2 CFG 1 */ + { 0x0000000B, 0x0036 }, /* R11 - Ctrl IF I2C1 CFG 2 */ + { 0x0000000C, 0x0036 }, /* R12 - Ctrl IF I2C2 CFG 2 */ + { 0x00000016, 0x0000 }, /* R22 - Write Sequencer Ctrl 0 */ + { 0x00000017, 0x0000 }, /* R23 - Write Sequencer Ctrl 1 */ + { 0x00000018, 0x0000 }, /* R24 - Write Sequencer Ctrl 2 */ + { 0x00000020, 0x0000 }, /* R32 - Tone Generator 1 */ + { 0x00000021, 0x1000 }, /* R33 - Tone Generator 2 */ + { 0x00000022, 0x0000 }, /* R34 - Tone Generator 3 */ + { 0x00000023, 0x1000 }, /* R35 - Tone Generator 4 */ + { 0x00000024, 0x0000 }, /* R36 - Tone Generator 5 */ + { 0x00000030, 0x0000 }, /* R48 - PWM Drive 1 */ + { 0x00000031, 0x0100 }, /* R49 - PWM Drive 2 */ + { 0x00000032, 0x0100 }, /* R50 - PWM Drive 3 */ + { 0x00000040, 0x0000 }, /* R64 - Wake control */ + { 0x00000041, 0x0000 }, /* R65 - Sequence control */ + { 0x00000061, 0x01FF }, /* R97 - Sample Rate Sequence Select 1 */ + { 0x00000062, 0x01FF }, /* R98 - Sample Rate Sequence Select 2 */ + { 0x00000063, 0x01FF }, /* R99 - Sample Rate Sequence Select 3 */ + { 0x00000064, 0x01FF }, /* R100 - Sample Rate Sequence Select 4 */ + { 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 */ + { 0x00000070, 0x0000 }, /* R112 - Comfort Noise Generator */ + { 0x00000090, 0x0000 }, /* R144 - Haptics Control 1 */ + { 0x00000091, 0x7FFF }, /* R145 - Haptics Control 2 */ + { 0x00000092, 0x0000 }, /* R146 - Haptics phase 1 intensity */ + { 0x00000093, 0x0000 }, /* R147 - Haptics phase 1 duration */ + { 0x00000094, 0x0000 }, /* R148 - Haptics phase 2 intensity */ + { 0x00000095, 0x0000 }, /* R149 - Haptics phase 2 duration */ + { 0x00000096, 0x0000 }, /* R150 - Haptics phase 3 intensity */ + { 0x00000097, 0x0000 }, /* R151 - Haptics phase 3 duration */ + { 0x00000100, 0x0001 }, /* R256 - Clock 32k 1 */ + { 0x00000101, 0x0504 }, /* R257 - System Clock 1 */ + { 0x00000102, 0x0011 }, /* R258 - Sample rate 1 */ + { 0x00000103, 0x0011 }, /* R259 - Sample rate 2 */ + { 0x00000104, 0x0011 }, /* R260 - Sample rate 3 */ + { 0x00000112, 0x0305 }, /* R274 - Async clock 1 */ + { 0x00000113, 0x0011 }, /* R275 - Async sample rate 1 */ + { 0x00000149, 0x0000 }, /* R329 - Output system clock */ + { 0x0000014A, 0x0000 }, /* R330 - Output async clock */ + { 0x00000152, 0x0000 }, /* R338 - Rate Estimator 1 */ + { 0x00000153, 0x0000 }, /* R339 - Rate Estimator 2 */ + { 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */ + { 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */ + { 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */ + { 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */ + { 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */ + { 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */ + { 0x00000174, 0x007D }, /* R372 - FLL1 Control 4 */ + { 0x00000175, 0x0006 }, /* R373 - FLL1 Control 5 */ + { 0x00000176, 0x0000 }, /* R374 - FLL1 Control 6 */ + { 0x00000177, 0x0281 }, /* R375 - FLL1 Loop Filter Test 1 */ + { 0x00000178, 0x0000 }, /* R376 - FLL1 NCO Test 0 */ + { 0x00000181, 0x0000 }, /* R385 - FLL1 Synchroniser 1 */ + { 0x00000182, 0x0000 }, /* R386 - FLL1 Synchroniser 2 */ + { 0x00000183, 0x0000 }, /* R387 - FLL1 Synchroniser 3 */ + { 0x00000184, 0x0000 }, /* R388 - FLL1 Synchroniser 4 */ + { 0x00000185, 0x0000 }, /* R389 - FLL1 Synchroniser 5 */ + { 0x00000186, 0x0000 }, /* R390 - FLL1 Synchroniser 6 */ + { 0x00000189, 0x0000 }, /* R393 - FLL1 Spread Spectrum */ + { 0x0000018A, 0x0004 }, /* R394 - FLL1 GPIO Clock */ + { 0x00000191, 0x0000 }, /* R401 - FLL2 Control 1 */ + { 0x00000192, 0x0008 }, /* R402 - FLL2 Control 2 */ + { 0x00000193, 0x0018 }, /* R403 - FLL2 Control 3 */ + { 0x00000194, 0x007D }, /* R404 - FLL2 Control 4 */ + { 0x00000195, 0x000C }, /* R405 - FLL2 Control 5 */ + { 0x00000196, 0x0000 }, /* R406 - FLL2 Control 6 */ + { 0x00000197, 0x0000 }, /* R407 - FLL2 Loop Filter Test 1 */ + { 0x00000198, 0x0000 }, /* R408 - FLL2 NCO Test 0 */ + { 0x000001A1, 0x0000 }, /* R417 - FLL2 Synchroniser 1 */ + { 0x000001A2, 0x0000 }, /* R418 - FLL2 Synchroniser 2 */ + { 0x000001A3, 0x0000 }, /* R419 - FLL2 Synchroniser 3 */ + { 0x000001A4, 0x0000 }, /* R420 - FLL2 Synchroniser 4 */ + { 0x000001A5, 0x0000 }, /* R421 - FLL2 Synchroniser 5 */ + { 0x000001A6, 0x0000 }, /* R422 - FLL2 Synchroniser 6 */ + { 0x000001A9, 0x0000 }, /* R425 - FLL2 Spread Spectrum */ + { 0x000001AA, 0x0004 }, /* R426 - FLL2 GPIO Clock */ + { 0x00000200, 0x0006 }, /* R512 - Mic Charge Pump 1 */ + { 0x00000210, 0x0184 }, /* R528 - LDO1 Control 1 */ + { 0x00000213, 0x0344 }, /* R531 - LDO2 Control 1 */ + { 0x00000218, 0x01A6 }, /* R536 - Mic Bias Ctrl 1 */ + { 0x00000219, 0x01A6 }, /* R537 - Mic Bias Ctrl 2 */ + { 0x0000021A, 0x01A6 }, /* R538 - Mic Bias Ctrl 3 */ + { 0x00000293, 0x0000 }, /* R659 - Accessory Detect Mode 1 */ + { 0x0000029B, 0x0020 }, /* R667 - Headphone Detect 1 */ + { 0x0000029C, 0x0000 }, /* R668 - Headphone Detect 2 */ + { 0x000002A3, 0x1102 }, /* R675 - Mic Detect 1 */ + { 0x000002A4, 0x009F }, /* R676 - Mic Detect 2 */ + { 0x000002C3, 0x0000 }, /* R707 - Mic noise mix control 1 */ + { 0x000002D3, 0x0000 }, /* R723 - Jack detect analogue */ + { 0x00000300, 0x0000 }, /* R768 - Input Enables */ + { 0x00000308, 0x0000 }, /* R776 - Input Rate */ + { 0x00000309, 0x0022 }, /* R777 - Input Volume Ramp */ + { 0x00000310, 0x2080 }, /* R784 - IN1L Control */ + { 0x00000311, 0x0180 }, /* R785 - ADC Digital Volume 1L */ + { 0x00000312, 0x0000 }, /* R786 - DMIC1L Control */ + { 0x00000314, 0x0080 }, /* R788 - IN1R Control */ + { 0x00000315, 0x0180 }, /* R789 - ADC Digital Volume 1R */ + { 0x00000316, 0x0000 }, /* R790 - DMIC1R Control */ + { 0x00000318, 0x2080 }, /* R792 - IN2L Control */ + { 0x00000319, 0x0180 }, /* R793 - ADC Digital Volume 2L */ + { 0x0000031A, 0x0000 }, /* R794 - DMIC2L Control */ + { 0x0000031C, 0x0080 }, /* R796 - IN2R Control */ + { 0x0000031D, 0x0180 }, /* R797 - ADC Digital Volume 2R */ + { 0x0000031E, 0x0000 }, /* R798 - DMIC2R Control */ + { 0x00000320, 0x2080 }, /* R800 - IN3L Control */ + { 0x00000321, 0x0180 }, /* R801 - ADC Digital Volume 3L */ + { 0x00000322, 0x0000 }, /* R802 - DMIC3L Control */ + { 0x00000324, 0x0080 }, /* R804 - IN3R Control */ + { 0x00000325, 0x0180 }, /* R805 - ADC Digital Volume 3R */ + { 0x00000326, 0x0000 }, /* R806 - DMIC3R Control */ + { 0x00000328, 0x2000 }, /* R808 - IN4L Control */ + { 0x00000329, 0x0180 }, /* R809 - ADC Digital Volume 4L */ + { 0x0000032A, 0x0000 }, /* R810 - DMIC4L Control */ + { 0x0000032D, 0x0180 }, /* R813 - ADC Digital Volume 4R */ + { 0x0000032E, 0x0000 }, /* R814 - DMIC4R Control */ + { 0x00000400, 0x0000 }, /* R1024 - Output Enables 1 */ + { 0x00000408, 0x0000 }, /* R1032 - Output Rate 1 */ + { 0x00000409, 0x0022 }, /* R1033 - Output Volume Ramp */ + { 0x00000410, 0x0080 }, /* R1040 - Output Path Config 1L */ + { 0x00000411, 0x0180 }, /* R1041 - DAC Digital Volume 1L */ + { 0x00000412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */ + { 0x00000413, 0x0001 }, /* R1043 - Noise Gate Select 1L */ + { 0x00000414, 0x0080 }, /* R1044 - Output Path Config 1R */ + { 0x00000415, 0x0180 }, /* R1045 - DAC Digital Volume 1R */ + { 0x00000416, 0x0080 }, /* R1046 - DAC Volume Limit 1R */ + { 0x00000417, 0x0002 }, /* R1047 - Noise Gate Select 1R */ + { 0x00000418, 0x0080 }, /* R1048 - Output Path Config 2L */ + { 0x00000419, 0x0180 }, /* R1049 - DAC Digital Volume 2L */ + { 0x0000041A, 0x0080 }, /* R1050 - DAC Volume Limit 2L */ + { 0x0000041B, 0x0004 }, /* R1051 - Noise Gate Select 2L */ + { 0x0000041C, 0x0080 }, /* R1052 - Output Path Config 2R */ + { 0x0000041D, 0x0180 }, /* R1053 - DAC Digital Volume 2R */ + { 0x0000041E, 0x0080 }, /* R1054 - DAC Volume Limit 2R */ + { 0x0000041F, 0x0008 }, /* R1055 - Noise Gate Select 2R */ + { 0x00000420, 0x0080 }, /* R1056 - Output Path Config 3L */ + { 0x00000421, 0x0180 }, /* R1057 - DAC Digital Volume 3L */ + { 0x00000422, 0x0080 }, /* R1058 - DAC Volume Limit 3L */ + { 0x00000423, 0x0010 }, /* R1059 - Noise Gate Select 3L */ + { 0x00000424, 0x0080 }, /* R1060 - Output Path Config 3R */ + { 0x00000425, 0x0180 }, /* R1061 - DAC Digital Volume 3R */ + { 0x00000426, 0x0080 }, /* R1062 - DAC Volume Limit 3R */ + { 0x00000427, 0x0020 }, /* R1063 - Noise Gate Select 3R */ + { 0x00000428, 0x0000 }, /* R1064 - Output Path Config 4L */ + { 0x00000429, 0x0180 }, /* R1065 - DAC Digital Volume 4L */ + { 0x0000042A, 0x0080 }, /* R1066 - Out Volume 4L */ + { 0x0000042B, 0x0040 }, /* R1067 - Noise Gate Select 4L */ + { 0x0000042C, 0x0000 }, /* R1068 - Output Path Config 4R */ + { 0x0000042D, 0x0180 }, /* R1069 - DAC Digital Volume 4R */ + { 0x0000042E, 0x0080 }, /* R1070 - Out Volume 4R */ + { 0x0000042F, 0x0080 }, /* R1071 - Noise Gate Select 4R */ + { 0x00000430, 0x0000 }, /* R1072 - Output Path Config 5L */ + { 0x00000431, 0x0180 }, /* R1073 - DAC Digital Volume 5L */ + { 0x00000432, 0x0080 }, /* R1074 - DAC Volume Limit 5L */ + { 0x00000433, 0x0100 }, /* R1075 - Noise Gate Select 5L */ + { 0x00000434, 0x0000 }, /* R1076 - Output Path Config 5R */ + { 0x00000435, 0x0180 }, /* R1077 - DAC Digital Volume 5R */ + { 0x00000436, 0x0080 }, /* R1078 - DAC Volume Limit 5R */ + { 0x00000437, 0x0200 }, /* R1079 - Noise Gate Select 5R */ + { 0x00000438, 0x0000 }, /* R1080 - Output Path Config 6L */ + { 0x00000439, 0x0180 }, /* R1081 - DAC Digital Volume 6L */ + { 0x0000043A, 0x0080 }, /* R1082 - DAC Volume Limit 6L */ + { 0x0000043B, 0x0400 }, /* R1083 - Noise Gate Select 6L */ + { 0x0000043C, 0x0000 }, /* R1084 - Output Path Config 6R */ + { 0x0000043D, 0x0180 }, /* R1085 - DAC Digital Volume 6R */ + { 0x0000043E, 0x0080 }, /* R1086 - DAC Volume Limit 6R */ + { 0x0000043F, 0x0800 }, /* R1087 - Noise Gate Select 6R */ + { 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */ + { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */ + { 0x00000480, 0x0040 }, /* R1152 - Class W ANC Threshold 1 */ + { 0x00000481, 0x0040 }, /* R1153 - Class W ANC Threshold 2 */ + { 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */ + { 0x00000491, 0x0000 }, /* R1169 - PDM SPK1 CTRL 2 */ + { 0x00000492, 0x0069 }, /* R1170 - PDM SPK2 CTRL 1 */ + { 0x00000493, 0x0000 }, /* R1171 - PDM SPK2 CTRL 2 */ + { 0x00000500, 0x000C }, /* R1280 - AIF1 BCLK Ctrl */ + { 0x00000501, 0x0008 }, /* R1281 - AIF1 Tx Pin Ctrl */ + { 0x00000502, 0x0000 }, /* R1282 - AIF1 Rx Pin Ctrl */ + { 0x00000503, 0x0000 }, /* R1283 - AIF1 Rate Ctrl */ + { 0x00000504, 0x0000 }, /* R1284 - AIF1 Format */ + { 0x00000505, 0x0040 }, /* R1285 - AIF1 Tx BCLK Rate */ + { 0x00000506, 0x0040 }, /* R1286 - AIF1 Rx BCLK Rate */ + { 0x00000507, 0x1818 }, /* R1287 - AIF1 Frame Ctrl 1 */ + { 0x00000508, 0x1818 }, /* R1288 - AIF1 Frame Ctrl 2 */ + { 0x00000509, 0x0000 }, /* R1289 - AIF1 Frame Ctrl 3 */ + { 0x0000050A, 0x0001 }, /* R1290 - AIF1 Frame Ctrl 4 */ + { 0x0000050B, 0x0002 }, /* R1291 - AIF1 Frame Ctrl 5 */ + { 0x0000050C, 0x0003 }, /* R1292 - AIF1 Frame Ctrl 6 */ + { 0x0000050D, 0x0004 }, /* R1293 - AIF1 Frame Ctrl 7 */ + { 0x0000050E, 0x0005 }, /* R1294 - AIF1 Frame Ctrl 8 */ + { 0x0000050F, 0x0006 }, /* R1295 - AIF1 Frame Ctrl 9 */ + { 0x00000510, 0x0007 }, /* R1296 - AIF1 Frame Ctrl 10 */ + { 0x00000511, 0x0000 }, /* R1297 - AIF1 Frame Ctrl 11 */ + { 0x00000512, 0x0001 }, /* R1298 - AIF1 Frame Ctrl 12 */ + { 0x00000513, 0x0002 }, /* R1299 - AIF1 Frame Ctrl 13 */ + { 0x00000514, 0x0003 }, /* R1300 - AIF1 Frame Ctrl 14 */ + { 0x00000515, 0x0004 }, /* R1301 - AIF1 Frame Ctrl 15 */ + { 0x00000516, 0x0005 }, /* R1302 - AIF1 Frame Ctrl 16 */ + { 0x00000517, 0x0006 }, /* R1303 - AIF1 Frame Ctrl 17 */ + { 0x00000518, 0x0007 }, /* R1304 - AIF1 Frame Ctrl 18 */ + { 0x00000519, 0x0000 }, /* R1305 - AIF1 Tx Enables */ + { 0x0000051A, 0x0000 }, /* R1306 - AIF1 Rx Enables */ + { 0x00000540, 0x000C }, /* R1344 - AIF2 BCLK Ctrl */ + { 0x00000541, 0x0008 }, /* R1345 - AIF2 Tx Pin Ctrl */ + { 0x00000542, 0x0000 }, /* R1346 - AIF2 Rx Pin Ctrl */ + { 0x00000543, 0x0000 }, /* R1347 - AIF2 Rate Ctrl */ + { 0x00000544, 0x0000 }, /* R1348 - AIF2 Format */ + { 0x00000545, 0x0040 }, /* R1349 - AIF2 Tx BCLK Rate */ + { 0x00000546, 0x0040 }, /* R1350 - AIF2 Rx BCLK Rate */ + { 0x00000547, 0x1818 }, /* R1351 - AIF2 Frame Ctrl 1 */ + { 0x00000548, 0x1818 }, /* R1352 - AIF2 Frame Ctrl 2 */ + { 0x00000549, 0x0000 }, /* R1353 - AIF2 Frame Ctrl 3 */ + { 0x0000054A, 0x0001 }, /* R1354 - AIF2 Frame Ctrl 4 */ + { 0x00000551, 0x0000 }, /* R1361 - AIF2 Frame Ctrl 11 */ + { 0x00000552, 0x0001 }, /* R1362 - AIF2 Frame Ctrl 12 */ + { 0x00000559, 0x0000 }, /* R1369 - AIF2 Tx Enables */ + { 0x0000055A, 0x0000 }, /* R1370 - AIF2 Rx Enables */ + { 0x00000580, 0x000C }, /* R1408 - AIF3 BCLK Ctrl */ + { 0x00000581, 0x0008 }, /* R1409 - AIF3 Tx Pin Ctrl */ + { 0x00000582, 0x0000 }, /* R1410 - AIF3 Rx Pin Ctrl */ + { 0x00000583, 0x0000 }, /* R1411 - AIF3 Rate Ctrl */ + { 0x00000584, 0x0000 }, /* R1412 - AIF3 Format */ + { 0x00000585, 0x0040 }, /* R1413 - AIF3 Tx BCLK Rate */ + { 0x00000586, 0x0040 }, /* R1414 - AIF3 Rx BCLK Rate */ + { 0x00000587, 0x1818 }, /* R1415 - AIF3 Frame Ctrl 1 */ + { 0x00000588, 0x1818 }, /* R1416 - AIF3 Frame Ctrl 2 */ + { 0x00000589, 0x0000 }, /* R1417 - AIF3 Frame Ctrl 3 */ + { 0x0000058A, 0x0001 }, /* R1418 - AIF3 Frame Ctrl 4 */ + { 0x00000591, 0x0000 }, /* R1425 - AIF3 Frame Ctrl 11 */ + { 0x00000592, 0x0001 }, /* R1426 - AIF3 Frame Ctrl 12 */ + { 0x00000599, 0x0000 }, /* R1433 - AIF3 Tx Enables */ + { 0x0000059A, 0x0000 }, /* R1434 - AIF3 Rx Enables */ + { 0x000005E3, 0x0004 }, /* R1507 - SLIMbus Framer Ref Gear */ + { 0x000005E5, 0x0000 }, /* R1509 - SLIMbus Rates 1 */ + { 0x000005E6, 0x0000 }, /* R1510 - SLIMbus Rates 2 */ + { 0x000005E7, 0x0000 }, /* R1511 - SLIMbus Rates 3 */ + { 0x000005E8, 0x0000 }, /* R1512 - SLIMbus Rates 4 */ + { 0x000005E9, 0x0000 }, /* R1513 - SLIMbus Rates 5 */ + { 0x000005EA, 0x0000 }, /* R1514 - SLIMbus Rates 6 */ + { 0x000005EB, 0x0000 }, /* R1515 - SLIMbus Rates 7 */ + { 0x000005EC, 0x0000 }, /* R1516 - SLIMbus Rates 8 */ + { 0x000005F5, 0x0000 }, /* R1525 - SLIMbus RX Channel Enable */ + { 0x000005F6, 0x0000 }, /* R1526 - SLIMbus TX Channel Enable */ + { 0x00000640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */ + { 0x00000641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */ + { 0x00000642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */ + { 0x00000643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */ + { 0x00000644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */ + { 0x00000645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */ + { 0x00000646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */ + { 0x00000647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */ + { 0x00000648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */ + { 0x00000649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */ + { 0x0000064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */ + { 0x0000064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */ + { 0x0000064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */ + { 0x0000064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */ + { 0x0000064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */ + { 0x0000064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */ + { 0x00000660, 0x0000 }, /* R1632 - MICMIX Input 1 Source */ + { 0x00000661, 0x0080 }, /* R1633 - MICMIX Input 1 Volume */ + { 0x00000662, 0x0000 }, /* R1634 - MICMIX Input 2 Source */ + { 0x00000663, 0x0080 }, /* R1635 - MICMIX Input 2 Volume */ + { 0x00000664, 0x0000 }, /* R1636 - MICMIX Input 3 Source */ + { 0x00000665, 0x0080 }, /* R1637 - MICMIX Input 3 Volume */ + { 0x00000666, 0x0000 }, /* R1638 - MICMIX Input 4 Source */ + { 0x00000667, 0x0080 }, /* R1639 - MICMIX Input 4 Volume */ + { 0x00000668, 0x0000 }, /* R1640 - NOISEMIX Input 1 Source */ + { 0x00000669, 0x0080 }, /* R1641 - NOISEMIX Input 1 Volume */ + { 0x0000066A, 0x0000 }, /* R1642 - NOISEMIX Input 2 Source */ + { 0x0000066B, 0x0080 }, /* R1643 - NOISEMIX Input 2 Volume */ + { 0x0000066C, 0x0000 }, /* R1644 - NOISEMIX Input 3 Source */ + { 0x0000066D, 0x0080 }, /* R1645 - NOISEMIX Input 3 Volume */ + { 0x0000066E, 0x0000 }, /* R1646 - NOISEMIX Input 4 Source */ + { 0x0000066F, 0x0080 }, /* R1647 - NOISEMIX Input 4 Volume */ + { 0x00000680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */ + { 0x00000681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */ + { 0x00000682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */ + { 0x00000683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */ + { 0x00000684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */ + { 0x00000685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */ + { 0x00000686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */ + { 0x00000687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */ + { 0x00000688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */ + { 0x00000689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */ + { 0x0000068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */ + { 0x0000068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */ + { 0x0000068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */ + { 0x0000068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */ + { 0x0000068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */ + { 0x0000068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */ + { 0x00000690, 0x0000 }, /* R1680 - OUT2LMIX Input 1 Source */ + { 0x00000691, 0x0080 }, /* R1681 - OUT2LMIX Input 1 Volume */ + { 0x00000692, 0x0000 }, /* R1682 - OUT2LMIX Input 2 Source */ + { 0x00000693, 0x0080 }, /* R1683 - OUT2LMIX Input 2 Volume */ + { 0x00000694, 0x0000 }, /* R1684 - OUT2LMIX Input 3 Source */ + { 0x00000695, 0x0080 }, /* R1685 - OUT2LMIX Input 3 Volume */ + { 0x00000696, 0x0000 }, /* R1686 - OUT2LMIX Input 4 Source */ + { 0x00000697, 0x0080 }, /* R1687 - OUT2LMIX Input 4 Volume */ + { 0x00000698, 0x0000 }, /* R1688 - OUT2RMIX Input 1 Source */ + { 0x00000699, 0x0080 }, /* R1689 - OUT2RMIX Input 1 Volume */ + { 0x0000069A, 0x0000 }, /* R1690 - OUT2RMIX Input 2 Source */ + { 0x0000069B, 0x0080 }, /* R1691 - OUT2RMIX Input 2 Volume */ + { 0x0000069C, 0x0000 }, /* R1692 - OUT2RMIX Input 3 Source */ + { 0x0000069D, 0x0080 }, /* R1693 - OUT2RMIX Input 3 Volume */ + { 0x0000069E, 0x0000 }, /* R1694 - OUT2RMIX Input 4 Source */ + { 0x0000069F, 0x0080 }, /* R1695 - OUT2RMIX Input 4 Volume */ + { 0x000006A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */ + { 0x000006A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */ + { 0x000006A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */ + { 0x000006A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */ + { 0x000006A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */ + { 0x000006A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */ + { 0x000006A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */ + { 0x000006A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */ + { 0x000006A8, 0x0000 }, /* R1704 - OUT3RMIX Input 1 Source */ + { 0x000006A9, 0x0080 }, /* R1705 - OUT3RMIX Input 1 Volume */ + { 0x000006AA, 0x0000 }, /* R1706 - OUT3RMIX Input 2 Source */ + { 0x000006AB, 0x0080 }, /* R1707 - OUT3RMIX Input 2 Volume */ + { 0x000006AC, 0x0000 }, /* R1708 - OUT3RMIX Input 3 Source */ + { 0x000006AD, 0x0080 }, /* R1709 - OUT3RMIX Input 3 Volume */ + { 0x000006AE, 0x0000 }, /* R1710 - OUT3RMIX Input 4 Source */ + { 0x000006AF, 0x0080 }, /* R1711 - OUT3RMIX Input 4 Volume */ + { 0x000006B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */ + { 0x000006B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */ + { 0x000006B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */ + { 0x000006B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */ + { 0x000006B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */ + { 0x000006B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */ + { 0x000006B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */ + { 0x000006B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */ + { 0x000006B8, 0x0000 }, /* R1720 - OUT4RMIX Input 1 Source */ + { 0x000006B9, 0x0080 }, /* R1721 - OUT4RMIX Input 1 Volume */ + { 0x000006BA, 0x0000 }, /* R1722 - OUT4RMIX Input 2 Source */ + { 0x000006BB, 0x0080 }, /* R1723 - OUT4RMIX Input 2 Volume */ + { 0x000006BC, 0x0000 }, /* R1724 - OUT4RMIX Input 3 Source */ + { 0x000006BD, 0x0080 }, /* R1725 - OUT4RMIX Input 3 Volume */ + { 0x000006BE, 0x0000 }, /* R1726 - OUT4RMIX Input 4 Source */ + { 0x000006BF, 0x0080 }, /* R1727 - OUT4RMIX Input 4 Volume */ + { 0x000006C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */ + { 0x000006C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */ + { 0x000006C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */ + { 0x000006C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */ + { 0x000006C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */ + { 0x000006C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */ + { 0x000006C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */ + { 0x000006C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */ + { 0x000006C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */ + { 0x000006C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */ + { 0x000006CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */ + { 0x000006CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */ + { 0x000006CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */ + { 0x000006CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */ + { 0x000006CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */ + { 0x000006CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */ + { 0x000006D0, 0x0000 }, /* R1744 - OUT6LMIX Input 1 Source */ + { 0x000006D1, 0x0080 }, /* R1745 - OUT6LMIX Input 1 Volume */ + { 0x000006D2, 0x0000 }, /* R1746 - OUT6LMIX Input 2 Source */ + { 0x000006D3, 0x0080 }, /* R1747 - OUT6LMIX Input 2 Volume */ + { 0x000006D4, 0x0000 }, /* R1748 - OUT6LMIX Input 3 Source */ + { 0x000006D5, 0x0080 }, /* R1749 - OUT6LMIX Input 3 Volume */ + { 0x000006D6, 0x0000 }, /* R1750 - OUT6LMIX Input 4 Source */ + { 0x000006D7, 0x0080 }, /* R1751 - OUT6LMIX Input 4 Volume */ + { 0x000006D8, 0x0000 }, /* R1752 - OUT6RMIX Input 1 Source */ + { 0x000006D9, 0x0080 }, /* R1753 - OUT6RMIX Input 1 Volume */ + { 0x000006DA, 0x0000 }, /* R1754 - OUT6RMIX Input 2 Source */ + { 0x000006DB, 0x0080 }, /* R1755 - OUT6RMIX Input 2 Volume */ + { 0x000006DC, 0x0000 }, /* R1756 - OUT6RMIX Input 3 Source */ + { 0x000006DD, 0x0080 }, /* R1757 - OUT6RMIX Input 3 Volume */ + { 0x000006DE, 0x0000 }, /* R1758 - OUT6RMIX Input 4 Source */ + { 0x000006DF, 0x0080 }, /* R1759 - OUT6RMIX Input 4 Volume */ + { 0x00000700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */ + { 0x00000701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */ + { 0x00000702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */ + { 0x00000703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */ + { 0x00000704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */ + { 0x00000705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */ + { 0x00000706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */ + { 0x00000707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */ + { 0x00000708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */ + { 0x00000709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */ + { 0x0000070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */ + { 0x0000070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */ + { 0x0000070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */ + { 0x0000070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */ + { 0x0000070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */ + { 0x0000070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */ + { 0x00000710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */ + { 0x00000711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */ + { 0x00000712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */ + { 0x00000713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */ + { 0x00000714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */ + { 0x00000715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */ + { 0x00000716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */ + { 0x00000717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */ + { 0x00000718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */ + { 0x00000719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */ + { 0x0000071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */ + { 0x0000071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */ + { 0x0000071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */ + { 0x0000071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */ + { 0x0000071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */ + { 0x0000071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */ + { 0x00000720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */ + { 0x00000721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */ + { 0x00000722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */ + { 0x00000723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */ + { 0x00000724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */ + { 0x00000725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */ + { 0x00000726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */ + { 0x00000727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */ + { 0x00000728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */ + { 0x00000729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */ + { 0x0000072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */ + { 0x0000072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */ + { 0x0000072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */ + { 0x0000072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */ + { 0x0000072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */ + { 0x0000072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */ + { 0x00000730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */ + { 0x00000731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */ + { 0x00000732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */ + { 0x00000733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */ + { 0x00000734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */ + { 0x00000735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */ + { 0x00000736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */ + { 0x00000737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */ + { 0x00000738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */ + { 0x00000739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */ + { 0x0000073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */ + { 0x0000073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */ + { 0x0000073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */ + { 0x0000073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */ + { 0x0000073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */ + { 0x0000073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */ + { 0x00000740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */ + { 0x00000741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */ + { 0x00000742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */ + { 0x00000743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */ + { 0x00000744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */ + { 0x00000745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */ + { 0x00000746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */ + { 0x00000747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */ + { 0x00000748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */ + { 0x00000749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */ + { 0x0000074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */ + { 0x0000074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */ + { 0x0000074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */ + { 0x0000074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */ + { 0x0000074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */ + { 0x0000074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */ + { 0x00000780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */ + { 0x00000781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */ + { 0x00000782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */ + { 0x00000783, 0x0080 }, /* R1923 - AIF3TX1MIX Input 2 Volume */ + { 0x00000784, 0x0000 }, /* R1924 - AIF3TX1MIX Input 3 Source */ + { 0x00000785, 0x0080 }, /* R1925 - AIF3TX1MIX Input 3 Volume */ + { 0x00000786, 0x0000 }, /* R1926 - AIF3TX1MIX Input 4 Source */ + { 0x00000787, 0x0080 }, /* R1927 - AIF3TX1MIX Input 4 Volume */ + { 0x00000788, 0x0000 }, /* R1928 - AIF3TX2MIX Input 1 Source */ + { 0x00000789, 0x0080 }, /* R1929 - AIF3TX2MIX Input 1 Volume */ + { 0x0000078A, 0x0000 }, /* R1930 - AIF3TX2MIX Input 2 Source */ + { 0x0000078B, 0x0080 }, /* R1931 - AIF3TX2MIX Input 2 Volume */ + { 0x0000078C, 0x0000 }, /* R1932 - AIF3TX2MIX Input 3 Source */ + { 0x0000078D, 0x0080 }, /* R1933 - AIF3TX2MIX Input 3 Volume */ + { 0x0000078E, 0x0000 }, /* R1934 - AIF3TX2MIX Input 4 Source */ + { 0x0000078F, 0x0080 }, /* R1935 - AIF3TX2MIX Input 4 Volume */ + { 0x000007C0, 0x0000 }, /* R1984 - SLIMTX1MIX Input 1 Source */ + { 0x000007C1, 0x0080 }, /* R1985 - SLIMTX1MIX Input 1 Volume */ + { 0x000007C2, 0x0000 }, /* R1986 - SLIMTX1MIX Input 2 Source */ + { 0x000007C3, 0x0080 }, /* R1987 - SLIMTX1MIX Input 2 Volume */ + { 0x000007C4, 0x0000 }, /* R1988 - SLIMTX1MIX Input 3 Source */ + { 0x000007C5, 0x0080 }, /* R1989 - SLIMTX1MIX Input 3 Volume */ + { 0x000007C6, 0x0000 }, /* R1990 - SLIMTX1MIX Input 4 Source */ + { 0x000007C7, 0x0080 }, /* R1991 - SLIMTX1MIX Input 4 Volume */ + { 0x000007C8, 0x0000 }, /* R1992 - SLIMTX2MIX Input 1 Source */ + { 0x000007C9, 0x0080 }, /* R1993 - SLIMTX2MIX Input 1 Volume */ + { 0x000007CA, 0x0000 }, /* R1994 - SLIMTX2MIX Input 2 Source */ + { 0x000007CB, 0x0080 }, /* R1995 - SLIMTX2MIX Input 2 Volume */ + { 0x000007CC, 0x0000 }, /* R1996 - SLIMTX2MIX Input 3 Source */ + { 0x000007CD, 0x0080 }, /* R1997 - SLIMTX2MIX Input 3 Volume */ + { 0x000007CE, 0x0000 }, /* R1998 - SLIMTX2MIX Input 4 Source */ + { 0x000007CF, 0x0080 }, /* R1999 - SLIMTX2MIX Input 4 Volume */ + { 0x000007D0, 0x0000 }, /* R2000 - SLIMTX3MIX Input 1 Source */ + { 0x000007D1, 0x0080 }, /* R2001 - SLIMTX3MIX Input 1 Volume */ + { 0x000007D2, 0x0000 }, /* R2002 - SLIMTX3MIX Input 2 Source */ + { 0x000007D3, 0x0080 }, /* R2003 - SLIMTX3MIX Input 2 Volume */ + { 0x000007D4, 0x0000 }, /* R2004 - SLIMTX3MIX Input 3 Source */ + { 0x000007D5, 0x0080 }, /* R2005 - SLIMTX3MIX Input 3 Volume */ + { 0x000007D6, 0x0000 }, /* R2006 - SLIMTX3MIX Input 4 Source */ + { 0x000007D7, 0x0080 }, /* R2007 - SLIMTX3MIX Input 4 Volume */ + { 0x000007D8, 0x0000 }, /* R2008 - SLIMTX4MIX Input 1 Source */ + { 0x000007D9, 0x0080 }, /* R2009 - SLIMTX4MIX Input 1 Volume */ + { 0x000007DA, 0x0000 }, /* R2010 - SLIMTX4MIX Input 2 Source */ + { 0x000007DB, 0x0080 }, /* R2011 - SLIMTX4MIX Input 2 Volume */ + { 0x000007DC, 0x0000 }, /* R2012 - SLIMTX4MIX Input 3 Source */ + { 0x000007DD, 0x0080 }, /* R2013 - SLIMTX4MIX Input 3 Volume */ + { 0x000007DE, 0x0000 }, /* R2014 - SLIMTX4MIX Input 4 Source */ + { 0x000007DF, 0x0080 }, /* R2015 - SLIMTX4MIX Input 4 Volume */ + { 0x000007E0, 0x0000 }, /* R2016 - SLIMTX5MIX Input 1 Source */ + { 0x000007E1, 0x0080 }, /* R2017 - SLIMTX5MIX Input 1 Volume */ + { 0x000007E2, 0x0000 }, /* R2018 - SLIMTX5MIX Input 2 Source */ + { 0x000007E3, 0x0080 }, /* R2019 - SLIMTX5MIX Input 2 Volume */ + { 0x000007E4, 0x0000 }, /* R2020 - SLIMTX5MIX Input 3 Source */ + { 0x000007E5, 0x0080 }, /* R2021 - SLIMTX5MIX Input 3 Volume */ + { 0x000007E6, 0x0000 }, /* R2022 - SLIMTX5MIX Input 4 Source */ + { 0x000007E7, 0x0080 }, /* R2023 - SLIMTX5MIX Input 4 Volume */ + { 0x000007E8, 0x0000 }, /* R2024 - SLIMTX6MIX Input 1 Source */ + { 0x000007E9, 0x0080 }, /* R2025 - SLIMTX6MIX Input 1 Volume */ + { 0x000007EA, 0x0000 }, /* R2026 - SLIMTX6MIX Input 2 Source */ + { 0x000007EB, 0x0080 }, /* R2027 - SLIMTX6MIX Input 2 Volume */ + { 0x000007EC, 0x0000 }, /* R2028 - SLIMTX6MIX Input 3 Source */ + { 0x000007ED, 0x0080 }, /* R2029 - SLIMTX6MIX Input 3 Volume */ + { 0x000007EE, 0x0000 }, /* R2030 - SLIMTX6MIX Input 4 Source */ + { 0x000007EF, 0x0080 }, /* R2031 - SLIMTX6MIX Input 4 Volume */ + { 0x000007F0, 0x0000 }, /* R2032 - SLIMTX7MIX Input 1 Source */ + { 0x000007F1, 0x0080 }, /* R2033 - SLIMTX7MIX Input 1 Volume */ + { 0x000007F2, 0x0000 }, /* R2034 - SLIMTX7MIX Input 2 Source */ + { 0x000007F3, 0x0080 }, /* R2035 - SLIMTX7MIX Input 2 Volume */ + { 0x000007F4, 0x0000 }, /* R2036 - SLIMTX7MIX Input 3 Source */ + { 0x000007F5, 0x0080 }, /* R2037 - SLIMTX7MIX Input 3 Volume */ + { 0x000007F6, 0x0000 }, /* R2038 - SLIMTX7MIX Input 4 Source */ + { 0x000007F7, 0x0080 }, /* R2039 - SLIMTX7MIX Input 4 Volume */ + { 0x000007F8, 0x0000 }, /* R2040 - SLIMTX8MIX Input 1 Source */ + { 0x000007F9, 0x0080 }, /* R2041 - SLIMTX8MIX Input 1 Volume */ + { 0x000007FA, 0x0000 }, /* R2042 - SLIMTX8MIX Input 2 Source */ + { 0x000007FB, 0x0080 }, /* R2043 - SLIMTX8MIX Input 2 Volume */ + { 0x000007FC, 0x0000 }, /* R2044 - SLIMTX8MIX Input 3 Source */ + { 0x000007FD, 0x0080 }, /* R2045 - SLIMTX8MIX Input 3 Volume */ + { 0x000007FE, 0x0000 }, /* R2046 - SLIMTX8MIX Input 4 Source */ + { 0x000007FF, 0x0080 }, /* R2047 - SLIMTX8MIX Input 4 Volume */ + { 0x00000880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */ + { 0x00000881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */ + { 0x00000882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */ + { 0x00000883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */ + { 0x00000884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */ + { 0x00000885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */ + { 0x00000886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */ + { 0x00000887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */ + { 0x00000888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */ + { 0x00000889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */ + { 0x0000088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */ + { 0x0000088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */ + { 0x0000088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */ + { 0x0000088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */ + { 0x0000088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */ + { 0x0000088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */ + { 0x00000890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */ + { 0x00000891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */ + { 0x00000892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */ + { 0x00000893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */ + { 0x00000894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */ + { 0x00000895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */ + { 0x00000896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */ + { 0x00000897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */ + { 0x00000898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */ + { 0x00000899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */ + { 0x0000089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */ + { 0x0000089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */ + { 0x0000089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */ + { 0x0000089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */ + { 0x0000089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */ + { 0x0000089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */ + { 0x000008C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */ + { 0x000008C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */ + { 0x000008C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */ + { 0x000008C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */ + { 0x000008C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */ + { 0x000008C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */ + { 0x000008C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */ + { 0x000008C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */ + { 0x000008C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */ + { 0x000008C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */ + { 0x000008CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */ + { 0x000008CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */ + { 0x000008CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */ + { 0x000008CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */ + { 0x000008CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */ + { 0x000008CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */ + { 0x000008D0, 0x0000 }, /* R2256 - DRC2LMIX Input 1 Source */ + { 0x000008D1, 0x0080 }, /* R2257 - DRC2LMIX Input 1 Volume */ + { 0x000008D2, 0x0000 }, /* R2258 - DRC2LMIX Input 2 Source */ + { 0x000008D3, 0x0080 }, /* R2259 - DRC2LMIX Input 2 Volume */ + { 0x000008D4, 0x0000 }, /* R2260 - DRC2LMIX Input 3 Source */ + { 0x000008D5, 0x0080 }, /* R2261 - DRC2LMIX Input 3 Volume */ + { 0x000008D6, 0x0000 }, /* R2262 - DRC2LMIX Input 4 Source */ + { 0x000008D7, 0x0080 }, /* R2263 - DRC2LMIX Input 4 Volume */ + { 0x000008D8, 0x0000 }, /* R2264 - DRC2RMIX Input 1 Source */ + { 0x000008D9, 0x0080 }, /* R2265 - DRC2RMIX Input 1 Volume */ + { 0x000008DA, 0x0000 }, /* R2266 - DRC2RMIX Input 2 Source */ + { 0x000008DB, 0x0080 }, /* R2267 - DRC2RMIX Input 2 Volume */ + { 0x000008DC, 0x0000 }, /* R2268 - DRC2RMIX Input 3 Source */ + { 0x000008DD, 0x0080 }, /* R2269 - DRC2RMIX Input 3 Volume */ + { 0x000008DE, 0x0000 }, /* R2270 - DRC2RMIX Input 4 Source */ + { 0x000008DF, 0x0080 }, /* R2271 - DRC2RMIX Input 4 Volume */ + { 0x00000900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */ + { 0x00000901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */ + { 0x00000902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */ + { 0x00000903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */ + { 0x00000904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */ + { 0x00000905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */ + { 0x00000906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */ + { 0x00000907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */ + { 0x00000908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */ + { 0x00000909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */ + { 0x0000090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */ + { 0x0000090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */ + { 0x0000090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */ + { 0x0000090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */ + { 0x0000090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */ + { 0x0000090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */ + { 0x00000910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */ + { 0x00000911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */ + { 0x00000912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */ + { 0x00000913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */ + { 0x00000914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */ + { 0x00000915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */ + { 0x00000916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */ + { 0x00000917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */ + { 0x00000918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */ + { 0x00000919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */ + { 0x0000091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */ + { 0x0000091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */ + { 0x0000091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */ + { 0x0000091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */ + { 0x0000091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */ + { 0x0000091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */ + { 0x00000940, 0x0000 }, /* R2368 - DSP1LMIX Input 1 Source */ + { 0x00000941, 0x0080 }, /* R2369 - DSP1LMIX Input 1 Volume */ + { 0x00000942, 0x0000 }, /* R2370 - DSP1LMIX Input 2 Source */ + { 0x00000943, 0x0080 }, /* R2371 - DSP1LMIX Input 2 Volume */ + { 0x00000944, 0x0000 }, /* R2372 - DSP1LMIX Input 3 Source */ + { 0x00000945, 0x0080 }, /* R2373 - DSP1LMIX Input 3 Volume */ + { 0x00000946, 0x0000 }, /* R2374 - DSP1LMIX Input 4 Source */ + { 0x00000947, 0x0080 }, /* R2375 - DSP1LMIX Input 4 Volume */ + { 0x00000948, 0x0000 }, /* R2376 - DSP1RMIX Input 1 Source */ + { 0x00000949, 0x0080 }, /* R2377 - DSP1RMIX Input 1 Volume */ + { 0x0000094A, 0x0000 }, /* R2378 - DSP1RMIX Input 2 Source */ + { 0x0000094B, 0x0080 }, /* R2379 - DSP1RMIX Input 2 Volume */ + { 0x0000094C, 0x0000 }, /* R2380 - DSP1RMIX Input 3 Source */ + { 0x0000094D, 0x0080 }, /* R2381 - DSP1RMIX Input 3 Volume */ + { 0x0000094E, 0x0000 }, /* R2382 - DSP1RMIX Input 4 Source */ + { 0x0000094F, 0x0080 }, /* R2383 - DSP1RMIX Input 4 Volume */ + { 0x00000950, 0x0000 }, /* R2384 - DSP1AUX1MIX Input 1 Source */ + { 0x00000958, 0x0000 }, /* R2392 - DSP1AUX2MIX Input 1 Source */ + { 0x00000960, 0x0000 }, /* R2400 - DSP1AUX3MIX Input 1 Source */ + { 0x00000968, 0x0000 }, /* R2408 - DSP1AUX4MIX Input 1 Source */ + { 0x00000970, 0x0000 }, /* R2416 - DSP1AUX5MIX Input 1 Source */ + { 0x00000978, 0x0000 }, /* R2424 - DSP1AUX6MIX Input 1 Source */ + { 0x00000980, 0x0000 }, /* R2432 - DSP2LMIX Input 1 Source */ + { 0x00000981, 0x0080 }, /* R2433 - DSP2LMIX Input 1 Volume */ + { 0x00000982, 0x0000 }, /* R2434 - DSP2LMIX Input 2 Source */ + { 0x00000983, 0x0080 }, /* R2435 - DSP2LMIX Input 2 Volume */ + { 0x00000984, 0x0000 }, /* R2436 - DSP2LMIX Input 3 Source */ + { 0x00000985, 0x0080 }, /* R2437 - DSP2LMIX Input 3 Volume */ + { 0x00000986, 0x0000 }, /* R2438 - DSP2LMIX Input 4 Source */ + { 0x00000987, 0x0080 }, /* R2439 - DSP2LMIX Input 4 Volume */ + { 0x00000988, 0x0000 }, /* R2440 - DSP2RMIX Input 1 Source */ + { 0x00000989, 0x0080 }, /* R2441 - DSP2RMIX Input 1 Volume */ + { 0x0000098A, 0x0000 }, /* R2442 - DSP2RMIX Input 2 Source */ + { 0x0000098B, 0x0080 }, /* R2443 - DSP2RMIX Input 2 Volume */ + { 0x0000098C, 0x0000 }, /* R2444 - DSP2RMIX Input 3 Source */ + { 0x0000098D, 0x0080 }, /* R2445 - DSP2RMIX Input 3 Volume */ + { 0x0000098E, 0x0000 }, /* R2446 - DSP2RMIX Input 4 Source */ + { 0x0000098F, 0x0080 }, /* R2447 - DSP2RMIX Input 4 Volume */ + { 0x00000990, 0x0000 }, /* R2448 - DSP2AUX1MIX Input 1 Source */ + { 0x00000998, 0x0000 }, /* R2456 - DSP2AUX2MIX Input 1 Source */ + { 0x000009A0, 0x0000 }, /* R2464 - DSP2AUX3MIX Input 1 Source */ + { 0x000009A8, 0x0000 }, /* R2472 - DSP2AUX4MIX Input 1 Source */ + { 0x000009B0, 0x0000 }, /* R2480 - DSP2AUX5MIX Input 1 Source */ + { 0x000009B8, 0x0000 }, /* R2488 - DSP2AUX6MIX Input 1 Source */ + { 0x000009C0, 0x0000 }, /* R2496 - DSP3LMIX Input 1 Source */ + { 0x000009C1, 0x0080 }, /* R2497 - DSP3LMIX Input 1 Volume */ + { 0x000009C2, 0x0000 }, /* R2498 - DSP3LMIX Input 2 Source */ + { 0x000009C3, 0x0080 }, /* R2499 - DSP3LMIX Input 2 Volume */ + { 0x000009C4, 0x0000 }, /* R2500 - DSP3LMIX Input 3 Source */ + { 0x000009C5, 0x0080 }, /* R2501 - DSP3LMIX Input 3 Volume */ + { 0x000009C6, 0x0000 }, /* R2502 - DSP3LMIX Input 4 Source */ + { 0x000009C7, 0x0080 }, /* R2503 - DSP3LMIX Input 4 Volume */ + { 0x000009C8, 0x0000 }, /* R2504 - DSP3RMIX Input 1 Source */ + { 0x000009C9, 0x0080 }, /* R2505 - DSP3RMIX Input 1 Volume */ + { 0x000009CA, 0x0000 }, /* R2506 - DSP3RMIX Input 2 Source */ + { 0x000009CB, 0x0080 }, /* R2507 - DSP3RMIX Input 2 Volume */ + { 0x000009CC, 0x0000 }, /* R2508 - DSP3RMIX Input 3 Source */ + { 0x000009CD, 0x0080 }, /* R2509 - DSP3RMIX Input 3 Volume */ + { 0x000009CE, 0x0000 }, /* R2510 - DSP3RMIX Input 4 Source */ + { 0x000009CF, 0x0080 }, /* R2511 - DSP3RMIX Input 4 Volume */ + { 0x000009D0, 0x0000 }, /* R2512 - DSP3AUX1MIX Input 1 Source */ + { 0x000009D8, 0x0000 }, /* R2520 - DSP3AUX2MIX Input 1 Source */ + { 0x000009E0, 0x0000 }, /* R2528 - DSP3AUX3MIX Input 1 Source */ + { 0x000009E8, 0x0000 }, /* R2536 - DSP3AUX4MIX Input 1 Source */ + { 0x000009F0, 0x0000 }, /* R2544 - DSP3AUX5MIX Input 1 Source */ + { 0x000009F8, 0x0000 }, /* R2552 - DSP3AUX6MIX Input 1 Source */ + { 0x00000A00, 0x0000 }, /* R2560 - DSP4LMIX Input 1 Source */ + { 0x00000A01, 0x0080 }, /* R2561 - DSP4LMIX Input 1 Volume */ + { 0x00000A02, 0x0000 }, /* R2562 - DSP4LMIX Input 2 Source */ + { 0x00000A03, 0x0080 }, /* R2563 - DSP4LMIX Input 2 Volume */ + { 0x00000A04, 0x0000 }, /* R2564 - DSP4LMIX Input 3 Source */ + { 0x00000A05, 0x0080 }, /* R2565 - DSP4LMIX Input 3 Volume */ + { 0x00000A06, 0x0000 }, /* R2566 - DSP4LMIX Input 4 Source */ + { 0x00000A07, 0x0080 }, /* R2567 - DSP4LMIX Input 4 Volume */ + { 0x00000A08, 0x0000 }, /* R2568 - DSP4RMIX Input 1 Source */ + { 0x00000A09, 0x0080 }, /* R2569 - DSP4RMIX Input 1 Volume */ + { 0x00000A0A, 0x0000 }, /* R2570 - DSP4RMIX Input 2 Source */ + { 0x00000A0B, 0x0080 }, /* R2571 - DSP4RMIX Input 2 Volume */ + { 0x00000A0C, 0x0000 }, /* R2572 - DSP4RMIX Input 3 Source */ + { 0x00000A0D, 0x0080 }, /* R2573 - DSP4RMIX Input 3 Volume */ + { 0x00000A0E, 0x0000 }, /* R2574 - DSP4RMIX Input 4 Source */ + { 0x00000A0F, 0x0080 }, /* R2575 - DSP4RMIX Input 4 Volume */ + { 0x00000A10, 0x0000 }, /* R2576 - DSP4AUX1MIX Input 1 Source */ + { 0x00000A18, 0x0000 }, /* R2584 - DSP4AUX2MIX Input 1 Source */ + { 0x00000A20, 0x0000 }, /* R2592 - DSP4AUX3MIX Input 1 Source */ + { 0x00000A28, 0x0000 }, /* R2600 - DSP4AUX4MIX Input 1 Source */ + { 0x00000A30, 0x0000 }, /* R2608 - DSP4AUX5MIX Input 1 Source */ + { 0x00000A38, 0x0000 }, /* R2616 - DSP4AUX6MIX Input 1 Source */ + { 0x00000A80, 0x0000 }, /* R2688 - ASRC1LMIX Input 1 Source */ + { 0x00000A88, 0x0000 }, /* R2696 - ASRC1RMIX Input 1 Source */ + { 0x00000A90, 0x0000 }, /* R2704 - ASRC2LMIX Input 1 Source */ + { 0x00000A98, 0x0000 }, /* R2712 - ASRC2RMIX Input 1 Source */ + { 0x00000B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */ + { 0x00000B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */ + { 0x00000B10, 0x0000 }, /* R2832 - ISRC1DEC3MIX Input 1 Source */ + { 0x00000B18, 0x0000 }, /* R2840 - ISRC1DEC4MIX Input 1 Source */ + { 0x00000B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */ + { 0x00000B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */ + { 0x00000B30, 0x0000 }, /* R2864 - ISRC1INT3MIX Input 1 Source */ + { 0x00000B38, 0x0000 }, /* R2872 - ISRC1INT4MIX Input 1 Source */ + { 0x00000B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */ + { 0x00000B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */ + { 0x00000B50, 0x0000 }, /* R2896 - ISRC2DEC3MIX Input 1 Source */ + { 0x00000B58, 0x0000 }, /* R2904 - ISRC2DEC4MIX Input 1 Source */ + { 0x00000B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */ + { 0x00000B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */ + { 0x00000B70, 0x0000 }, /* R2928 - ISRC2INT3MIX Input 1 Source */ + { 0x00000B78, 0x0000 }, /* R2936 - ISRC2INT4MIX Input 1 Source */ + { 0x00000B80, 0x0000 }, /* R2944 - ISRC3DEC1MIX Input 1 Source */ + { 0x00000B88, 0x0000 }, /* R2952 - ISRC3DEC2MIX Input 1 Source */ + { 0x00000B90, 0x0000 }, /* R2960 - ISRC3DEC3MIX Input 1 Source */ + { 0x00000B98, 0x0000 }, /* R2968 - ISRC3DEC4MIX Input 1 Source */ + { 0x00000BA0, 0x0000 }, /* R2976 - ISRC3INT1MIX Input 1 Source */ + { 0x00000BA8, 0x0000 }, /* R2984 - ISRC3INT2MIX Input 1 Source */ + { 0x00000BB0, 0x0000 }, /* R2992 - ISRC3INT3MIX Input 1 Source */ + { 0x00000BB8, 0x0000 }, /* R3000 - ISRC3INT4MIX Input 1 Source */ + { 0x00000C00, 0xA101 }, /* R3072 - GPIO1 CTRL */ + { 0x00000C01, 0xA101 }, /* R3073 - GPIO2 CTRL */ + { 0x00000C02, 0xA101 }, /* R3074 - GPIO3 CTRL */ + { 0x00000C03, 0xA101 }, /* R3075 - GPIO4 CTRL */ + { 0x00000C04, 0xA101 }, /* R3076 - GPIO5 CTRL */ + { 0x00000C0F, 0x0400 }, /* R3087 - IRQ CTRL 1 */ + { 0x00000C10, 0x1000 }, /* R3088 - GPIO Debounce Config */ + { 0x00000C20, 0x8002 }, /* R3104 - Misc Pad Ctrl 1 */ + { 0x00000C21, 0x8001 }, /* R3105 - Misc Pad Ctrl 2 */ + { 0x00000C22, 0x0000 }, /* R3106 - Misc Pad Ctrl 3 */ + { 0x00000C23, 0x0000 }, /* R3107 - Misc Pad Ctrl 4 */ + { 0x00000C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 5 */ + { 0x00000C25, 0x0000 }, /* R3109 - Misc Pad Ctrl 6 */ + { 0x00000C30, 0x8282 }, /* R3120 - Misc Pad Ctrl 7 */ + { 0x00000C31, 0x0082 }, /* R3121 - Misc Pad Ctrl 8 */ + { 0x00000C32, 0x8282 }, /* R3122 - Misc Pad Ctrl 9 */ + { 0x00000C33, 0x8282 }, /* R3123 - Misc Pad Ctrl 10 */ + { 0x00000C34, 0x8282 }, /* R3124 - Misc Pad Ctrl 11 */ + { 0x00000C35, 0x8282 }, /* R3125 - Misc Pad Ctrl 12 */ + { 0x00000C36, 0x8282 }, /* R3126 - Misc Pad Ctrl 13 */ + { 0x00000C37, 0x8282 }, /* R3127 - Misc Pad Ctrl 14 */ + { 0x00000C38, 0x8282 }, /* R3128 - Misc Pad Ctrl 15 */ + { 0x00000C39, 0x8282 }, /* R3129 - Misc Pad Ctrl 16 */ + { 0x00000C3A, 0x8282 }, /* R3130 - Misc Pad Ctrl 17 */ + { 0x00000C3B, 0x8282 }, /* R3131 - Misc Pad Ctrl 18 */ + { 0x00000D08, 0xFFFF }, /* R3336 - Interrupt Status 1 Mask */ + { 0x00000D09, 0xFFFF }, /* R3337 - Interrupt Status 2 Mask */ + { 0x00000D0A, 0xFFFF }, /* R3338 - Interrupt Status 3 Mask */ + { 0x00000D0B, 0xFFFF }, /* R3339 - Interrupt Status 4 Mask */ + { 0x00000D0C, 0xFEFF }, /* R3340 - Interrupt Status 5 Mask */ + { 0x00000D0F, 0x0000 }, /* R3343 - Interrupt Control */ + { 0x00000D18, 0xFFFF }, /* R3352 - IRQ2 Status 1 Mask */ + { 0x00000D19, 0xFFFF }, /* R3353 - IRQ2 Status 2 Mask */ + { 0x00000D1A, 0xFFFF }, /* R3354 - IRQ2 Status 3 Mask */ + { 0x00000D1B, 0xFFFF }, /* R3355 - IRQ2 Status 4 Mask */ + { 0x00000D1C, 0xFFFF }, /* R3356 - IRQ2 Status 5 Mask */ + { 0x00000D1F, 0x0000 }, /* R3359 - IRQ2 Control */ + { 0x00000D50, 0x0000 }, /* R3408 - AOD wkup and trig */ + { 0x00000D53, 0xFFFF }, /* R3411 - AOD IRQ Mask IRQ1 */ + { 0x00000D54, 0xFFFF }, /* R3412 - AOD IRQ Mask IRQ2 */ + { 0x00000D56, 0x0000 }, /* R3414 - Jack detect debounce */ + { 0x00000E00, 0x0000 }, /* R3584 - FX_Ctrl1 */ + { 0x00000E01, 0x0000 }, /* R3585 - FX_Ctrl2 */ + { 0x00000E10, 0x6318 }, /* R3600 - EQ1_1 */ + { 0x00000E11, 0x6300 }, /* R3601 - EQ1_2 */ + { 0x00000E12, 0x0FC8 }, /* R3602 - EQ1_3 */ + { 0x00000E13, 0x03FE }, /* R3603 - EQ1_4 */ + { 0x00000E14, 0x00E0 }, /* R3604 - EQ1_5 */ + { 0x00000E15, 0x1EC4 }, /* R3605 - EQ1_6 */ + { 0x00000E16, 0xF136 }, /* R3606 - EQ1_7 */ + { 0x00000E17, 0x0409 }, /* R3607 - EQ1_8 */ + { 0x00000E18, 0x04CC }, /* R3608 - EQ1_9 */ + { 0x00000E19, 0x1C9B }, /* R3609 - EQ1_10 */ + { 0x00000E1A, 0xF337 }, /* R3610 - EQ1_11 */ + { 0x00000E1B, 0x040B }, /* R3611 - EQ1_12 */ + { 0x00000E1C, 0x0CBB }, /* R3612 - EQ1_13 */ + { 0x00000E1D, 0x16F8 }, /* R3613 - EQ1_14 */ + { 0x00000E1E, 0xF7D9 }, /* R3614 - EQ1_15 */ + { 0x00000E1F, 0x040A }, /* R3615 - EQ1_16 */ + { 0x00000E20, 0x1F14 }, /* R3616 - EQ1_17 */ + { 0x00000E21, 0x058C }, /* R3617 - EQ1_18 */ + { 0x00000E22, 0x0563 }, /* R3618 - EQ1_19 */ + { 0x00000E23, 0x4000 }, /* R3619 - EQ1_20 */ + { 0x00000E24, 0x0B75 }, /* R3620 - EQ1_21 */ + { 0x00000E26, 0x6318 }, /* R3622 - EQ2_1 */ + { 0x00000E27, 0x6300 }, /* R3623 - EQ2_2 */ + { 0x00000E28, 0x0FC8 }, /* R3624 - EQ2_3 */ + { 0x00000E29, 0x03FE }, /* R3625 - EQ2_4 */ + { 0x00000E2A, 0x00E0 }, /* R3626 - EQ2_5 */ + { 0x00000E2B, 0x1EC4 }, /* R3627 - EQ2_6 */ + { 0x00000E2C, 0xF136 }, /* R3628 - EQ2_7 */ + { 0x00000E2D, 0x0409 }, /* R3629 - EQ2_8 */ + { 0x00000E2E, 0x04CC }, /* R3630 - EQ2_9 */ + { 0x00000E2F, 0x1C9B }, /* R3631 - EQ2_10 */ + { 0x00000E30, 0xF337 }, /* R3632 - EQ2_11 */ + { 0x00000E31, 0x040B }, /* R3633 - EQ2_12 */ + { 0x00000E32, 0x0CBB }, /* R3634 - EQ2_13 */ + { 0x00000E33, 0x16F8 }, /* R3635 - EQ2_14 */ + { 0x00000E34, 0xF7D9 }, /* R3636 - EQ2_15 */ + { 0x00000E35, 0x040A }, /* R3637 - EQ2_16 */ + { 0x00000E36, 0x1F14 }, /* R3638 - EQ2_17 */ + { 0x00000E37, 0x058C }, /* R3639 - EQ2_18 */ + { 0x00000E38, 0x0563 }, /* R3640 - EQ2_19 */ + { 0x00000E39, 0x4000 }, /* R3641 - EQ2_20 */ + { 0x00000E3A, 0x0B75 }, /* R3642 - EQ2_21 */ + { 0x00000E3C, 0x6318 }, /* R3644 - EQ3_1 */ + { 0x00000E3D, 0x6300 }, /* R3645 - EQ3_2 */ + { 0x00000E3E, 0x0FC8 }, /* R3646 - EQ3_3 */ + { 0x00000E3F, 0x03FE }, /* R3647 - EQ3_4 */ + { 0x00000E40, 0x00E0 }, /* R3648 - EQ3_5 */ + { 0x00000E41, 0x1EC4 }, /* R3649 - EQ3_6 */ + { 0x00000E42, 0xF136 }, /* R3650 - EQ3_7 */ + { 0x00000E43, 0x0409 }, /* R3651 - EQ3_8 */ + { 0x00000E44, 0x04CC }, /* R3652 - EQ3_9 */ + { 0x00000E45, 0x1C9B }, /* R3653 - EQ3_10 */ + { 0x00000E46, 0xF337 }, /* R3654 - EQ3_11 */ + { 0x00000E47, 0x040B }, /* R3655 - EQ3_12 */ + { 0x00000E48, 0x0CBB }, /* R3656 - EQ3_13 */ + { 0x00000E49, 0x16F8 }, /* R3657 - EQ3_14 */ + { 0x00000E4A, 0xF7D9 }, /* R3658 - EQ3_15 */ + { 0x00000E4B, 0x040A }, /* R3659 - EQ3_16 */ + { 0x00000E4C, 0x1F14 }, /* R3660 - EQ3_17 */ + { 0x00000E4D, 0x058C }, /* R3661 - EQ3_18 */ + { 0x00000E4E, 0x0563 }, /* R3662 - EQ3_19 */ + { 0x00000E4F, 0x4000 }, /* R3663 - EQ3_20 */ + { 0x00000E50, 0x0B75 }, /* R3664 - EQ3_21 */ + { 0x00000E52, 0x6318 }, /* R3666 - EQ4_1 */ + { 0x00000E53, 0x6300 }, /* R3667 - EQ4_2 */ + { 0x00000E54, 0x0FC8 }, /* R3668 - EQ4_3 */ + { 0x00000E55, 0x03FE }, /* R3669 - EQ4_4 */ + { 0x00000E56, 0x00E0 }, /* R3670 - EQ4_5 */ + { 0x00000E57, 0x1EC4 }, /* R3671 - EQ4_6 */ + { 0x00000E58, 0xF136 }, /* R3672 - EQ4_7 */ + { 0x00000E59, 0x0409 }, /* R3673 - EQ4_8 */ + { 0x00000E5A, 0x04CC }, /* R3674 - EQ4_9 */ + { 0x00000E5B, 0x1C9B }, /* R3675 - EQ4_10 */ + { 0x00000E5C, 0xF337 }, /* R3676 - EQ4_11 */ + { 0x00000E5D, 0x040B }, /* R3677 - EQ4_12 */ + { 0x00000E5E, 0x0CBB }, /* R3678 - EQ4_13 */ + { 0x00000E5F, 0x16F8 }, /* R3679 - EQ4_14 */ + { 0x00000E60, 0xF7D9 }, /* R3680 - EQ4_15 */ + { 0x00000E61, 0x040A }, /* R3681 - EQ4_16 */ + { 0x00000E62, 0x1F14 }, /* R3682 - EQ4_17 */ + { 0x00000E63, 0x058C }, /* R3683 - EQ4_18 */ + { 0x00000E64, 0x0563 }, /* R3684 - EQ4_19 */ + { 0x00000E65, 0x4000 }, /* R3685 - EQ4_20 */ + { 0x00000E66, 0x0B75 }, /* R3686 - EQ4_21 */ + { 0x00000E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */ + { 0x00000E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */ + { 0x00000E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */ + { 0x00000E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */ + { 0x00000E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */ + { 0x00000E89, 0x0018 }, /* R3721 - DRC2 ctrl1 */ + { 0x00000E8A, 0x0933 }, /* R3722 - DRC2 ctrl2 */ + { 0x00000E8B, 0x0018 }, /* R3723 - DRC2 ctrl3 */ + { 0x00000E8C, 0x0000 }, /* R3724 - DRC2 ctrl4 */ + { 0x00000E8D, 0x0000 }, /* R3725 - DRC2 ctrl5 */ + { 0x00000EC0, 0x0000 }, /* R3776 - HPLPF1_1 */ + { 0x00000EC1, 0x0000 }, /* R3777 - HPLPF1_2 */ + { 0x00000EC4, 0x0000 }, /* R3780 - HPLPF2_1 */ + { 0x00000EC5, 0x0000 }, /* R3781 - HPLPF2_2 */ + { 0x00000EC8, 0x0000 }, /* R3784 - HPLPF3_1 */ + { 0x00000EC9, 0x0000 }, /* R3785 - HPLPF3_2 */ + { 0x00000ECC, 0x0000 }, /* R3788 - HPLPF4_1 */ + { 0x00000ECD, 0x0000 }, /* R3789 - HPLPF4_2 */ + { 0x00000EE0, 0x0000 }, /* R3808 - ASRC_ENABLE */ + { 0x00000EE2, 0x0000 }, /* R3810 - ASRC_RATE1 */ + { 0x00000EF0, 0x0000 }, /* R3824 - ISRC 1 CTRL 1 */ + { 0x00000EF1, 0x0000 }, /* R3825 - ISRC 1 CTRL 2 */ + { 0x00000EF2, 0x0000 }, /* R3826 - ISRC 1 CTRL 3 */ + { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ + { 0x00000EF4, 0x0000 }, /* R3828 - ISRC 2 CTRL 2 */ + { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ + { 0x00000EF6, 0x0000 }, /* R3830 - ISRC 3 CTRL 1 */ + { 0x00000EF7, 0x0000 }, /* R3831 - ISRC 3 CTRL 2 */ + { 0x00000EF8, 0x0000 }, /* R3832 - ISRC 3 CTRL 3 */ + { 0x00000F00, 0x0000 }, /* R3840 - Clock Control */ + { 0x00000F01, 0x0000 }, /* R3841 - ANC_SRC */ + { 0x00001100, 0x0010 }, /* R4352 - DSP1 Control 1 */ + { 0x00001101, 0x0000 }, /* R4353 - DSP1 Clocking 1 */ + { 0x00001200, 0x0010 }, /* R4608 - DSP2 Control 1 */ + { 0x00001201, 0x0000 }, /* R4609 - DSP2 Clocking 1 */ + { 0x00001300, 0x0010 }, /* R4864 - DSP3 Control 1 */ + { 0x00001301, 0x0000 }, /* R4865 - DSP3 Clocking 1 */ + { 0x00001400, 0x0010 }, /* R5120 - DSP4 Control 1 */ + { 0x00001401, 0x0000 }, /* R5121 - DSP4 Clocking 1 */ + { 0x00001404, 0x0000 }, /* R5124 - DSP4 Status 1 */ +}; + +static bool wm5110_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_CTRL_IF_SPI_CFG_1: + case ARIZONA_CTRL_IF_I2C1_CFG_1: + case ARIZONA_CTRL_IF_I2C2_CFG_1: + case ARIZONA_CTRL_IF_I2C1_CFG_2: + case ARIZONA_CTRL_IF_I2C2_CFG_2: + case ARIZONA_WRITE_SEQUENCER_CTRL_0: + case ARIZONA_WRITE_SEQUENCER_CTRL_1: + case ARIZONA_WRITE_SEQUENCER_CTRL_2: + case ARIZONA_TONE_GENERATOR_1: + case ARIZONA_TONE_GENERATOR_2: + case ARIZONA_TONE_GENERATOR_3: + case ARIZONA_TONE_GENERATOR_4: + case ARIZONA_TONE_GENERATOR_5: + case ARIZONA_PWM_DRIVE_1: + case ARIZONA_PWM_DRIVE_2: + case ARIZONA_PWM_DRIVE_3: + case ARIZONA_WAKE_CONTROL: + case ARIZONA_SEQUENCE_CONTROL: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_2: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_3: + case ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_4: + case ARIZONA_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_COMFORT_NOISE_GENERATOR: + case ARIZONA_HAPTICS_CONTROL_1: + case ARIZONA_HAPTICS_CONTROL_2: + case ARIZONA_HAPTICS_PHASE_1_INTENSITY: + case ARIZONA_HAPTICS_PHASE_1_DURATION: + case ARIZONA_HAPTICS_PHASE_2_INTENSITY: + case ARIZONA_HAPTICS_PHASE_2_DURATION: + case ARIZONA_HAPTICS_PHASE_3_INTENSITY: + case ARIZONA_HAPTICS_PHASE_3_DURATION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_CLOCK_32K_1: + case ARIZONA_SYSTEM_CLOCK_1: + case ARIZONA_SAMPLE_RATE_1: + case ARIZONA_SAMPLE_RATE_2: + case ARIZONA_SAMPLE_RATE_3: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_CLOCK_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_OUTPUT_SYSTEM_CLOCK: + case ARIZONA_OUTPUT_ASYNC_CLOCK: + case ARIZONA_RATE_ESTIMATOR_1: + case ARIZONA_RATE_ESTIMATOR_2: + case ARIZONA_RATE_ESTIMATOR_3: + case ARIZONA_RATE_ESTIMATOR_4: + case ARIZONA_RATE_ESTIMATOR_5: + case ARIZONA_FLL1_CONTROL_1: + case ARIZONA_FLL1_CONTROL_2: + case ARIZONA_FLL1_CONTROL_3: + case ARIZONA_FLL1_CONTROL_4: + case ARIZONA_FLL1_CONTROL_5: + case ARIZONA_FLL1_CONTROL_6: + case ARIZONA_FLL1_LOOP_FILTER_TEST_1: + case ARIZONA_FLL1_NCO_TEST_0: + case ARIZONA_FLL1_SYNCHRONISER_1: + case ARIZONA_FLL1_SYNCHRONISER_2: + case ARIZONA_FLL1_SYNCHRONISER_3: + case ARIZONA_FLL1_SYNCHRONISER_4: + case ARIZONA_FLL1_SYNCHRONISER_5: + case ARIZONA_FLL1_SYNCHRONISER_6: + case ARIZONA_FLL1_SPREAD_SPECTRUM: + case ARIZONA_FLL1_GPIO_CLOCK: + case ARIZONA_FLL2_CONTROL_1: + case ARIZONA_FLL2_CONTROL_2: + case ARIZONA_FLL2_CONTROL_3: + case ARIZONA_FLL2_CONTROL_4: + case ARIZONA_FLL2_CONTROL_5: + case ARIZONA_FLL2_CONTROL_6: + case ARIZONA_FLL2_LOOP_FILTER_TEST_1: + case ARIZONA_FLL2_NCO_TEST_0: + case ARIZONA_FLL2_SYNCHRONISER_1: + case ARIZONA_FLL2_SYNCHRONISER_2: + case ARIZONA_FLL2_SYNCHRONISER_3: + case ARIZONA_FLL2_SYNCHRONISER_4: + case ARIZONA_FLL2_SYNCHRONISER_5: + case ARIZONA_FLL2_SYNCHRONISER_6: + case ARIZONA_FLL2_SPREAD_SPECTRUM: + case ARIZONA_FLL2_GPIO_CLOCK: + case ARIZONA_MIC_CHARGE_PUMP_1: + case ARIZONA_LDO1_CONTROL_1: + case ARIZONA_LDO2_CONTROL_1: + case ARIZONA_MIC_BIAS_CTRL_1: + case ARIZONA_MIC_BIAS_CTRL_2: + case ARIZONA_MIC_BIAS_CTRL_3: + case ARIZONA_ACCESSORY_DETECT_MODE_1: + case ARIZONA_HEADPHONE_DETECT_1: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_MIC_DETECT_1: + case ARIZONA_MIC_DETECT_2: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_MIC_NOISE_MIX_CONTROL_1: + case ARIZONA_JACK_DETECT_ANALOGUE: + case ARIZONA_INPUT_ENABLES: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_INPUT_RATE: + case ARIZONA_INPUT_VOLUME_RAMP: + case ARIZONA_IN1L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1L: + case ARIZONA_DMIC1L_CONTROL: + case ARIZONA_IN1R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_1R: + case ARIZONA_DMIC1R_CONTROL: + case ARIZONA_IN2L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2L: + case ARIZONA_DMIC2L_CONTROL: + case ARIZONA_IN2R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_2R: + case ARIZONA_DMIC2R_CONTROL: + case ARIZONA_IN3L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_3L: + case ARIZONA_DMIC3L_CONTROL: + case ARIZONA_IN3R_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_3R: + case ARIZONA_DMIC3R_CONTROL: + case ARIZONA_IN4L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_4L: + case ARIZONA_DMIC4L_CONTROL: + case ARIZONA_ADC_DIGITAL_VOLUME_4R: + case ARIZONA_DMIC4R_CONTROL: + case ARIZONA_OUTPUT_ENABLES_1: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_OUTPUT_RATE_1: + case ARIZONA_OUTPUT_VOLUME_RAMP: + case ARIZONA_OUTPUT_PATH_CONFIG_1L: + case ARIZONA_DAC_DIGITAL_VOLUME_1L: + case ARIZONA_DAC_VOLUME_LIMIT_1L: + case ARIZONA_NOISE_GATE_SELECT_1L: + case ARIZONA_OUTPUT_PATH_CONFIG_1R: + case ARIZONA_DAC_DIGITAL_VOLUME_1R: + case ARIZONA_DAC_VOLUME_LIMIT_1R: + case ARIZONA_NOISE_GATE_SELECT_1R: + case ARIZONA_OUTPUT_PATH_CONFIG_2L: + case ARIZONA_DAC_DIGITAL_VOLUME_2L: + case ARIZONA_DAC_VOLUME_LIMIT_2L: + case ARIZONA_NOISE_GATE_SELECT_2L: + case ARIZONA_OUTPUT_PATH_CONFIG_2R: + case ARIZONA_DAC_DIGITAL_VOLUME_2R: + case ARIZONA_DAC_VOLUME_LIMIT_2R: + case ARIZONA_NOISE_GATE_SELECT_2R: + case ARIZONA_OUTPUT_PATH_CONFIG_3L: + case ARIZONA_DAC_DIGITAL_VOLUME_3L: + case ARIZONA_DAC_VOLUME_LIMIT_3L: + case ARIZONA_NOISE_GATE_SELECT_3L: + case ARIZONA_OUTPUT_PATH_CONFIG_3R: + case ARIZONA_DAC_DIGITAL_VOLUME_3R: + case ARIZONA_DAC_VOLUME_LIMIT_3R: + case ARIZONA_NOISE_GATE_SELECT_3R: + case ARIZONA_OUTPUT_PATH_CONFIG_4L: + case ARIZONA_DAC_DIGITAL_VOLUME_4L: + case ARIZONA_OUT_VOLUME_4L: + case ARIZONA_NOISE_GATE_SELECT_4L: + case ARIZONA_OUTPUT_PATH_CONFIG_4R: + case ARIZONA_DAC_DIGITAL_VOLUME_4R: + case ARIZONA_OUT_VOLUME_4R: + case ARIZONA_NOISE_GATE_SELECT_4R: + case ARIZONA_OUTPUT_PATH_CONFIG_5L: + case ARIZONA_DAC_DIGITAL_VOLUME_5L: + case ARIZONA_DAC_VOLUME_LIMIT_5L: + case ARIZONA_NOISE_GATE_SELECT_5L: + case ARIZONA_OUTPUT_PATH_CONFIG_5R: + case ARIZONA_DAC_DIGITAL_VOLUME_5R: + case ARIZONA_DAC_VOLUME_LIMIT_5R: + case ARIZONA_NOISE_GATE_SELECT_5R: + case ARIZONA_OUTPUT_PATH_CONFIG_6L: + case ARIZONA_DAC_DIGITAL_VOLUME_6L: + case ARIZONA_DAC_VOLUME_LIMIT_6L: + case ARIZONA_NOISE_GATE_SELECT_6L: + case ARIZONA_OUTPUT_PATH_CONFIG_6R: + case ARIZONA_DAC_DIGITAL_VOLUME_6R: + case ARIZONA_DAC_VOLUME_LIMIT_6R: + case ARIZONA_NOISE_GATE_SELECT_6R: + case ARIZONA_DAC_AEC_CONTROL_1: + case ARIZONA_NOISE_GATE_CONTROL: + case ARIZONA_PDM_SPK1_CTRL_1: + case ARIZONA_PDM_SPK1_CTRL_2: + case ARIZONA_PDM_SPK2_CTRL_1: + case ARIZONA_PDM_SPK2_CTRL_2: + case ARIZONA_AIF1_BCLK_CTRL: + case ARIZONA_AIF1_TX_PIN_CTRL: + case ARIZONA_AIF1_RX_PIN_CTRL: + case ARIZONA_AIF1_RATE_CTRL: + case ARIZONA_AIF1_FORMAT: + case ARIZONA_AIF1_TX_BCLK_RATE: + case ARIZONA_AIF1_RX_BCLK_RATE: + case ARIZONA_AIF1_FRAME_CTRL_1: + case ARIZONA_AIF1_FRAME_CTRL_2: + case ARIZONA_AIF1_FRAME_CTRL_3: + case ARIZONA_AIF1_FRAME_CTRL_4: + case ARIZONA_AIF1_FRAME_CTRL_5: + case ARIZONA_AIF1_FRAME_CTRL_6: + case ARIZONA_AIF1_FRAME_CTRL_7: + case ARIZONA_AIF1_FRAME_CTRL_8: + case ARIZONA_AIF1_FRAME_CTRL_9: + case ARIZONA_AIF1_FRAME_CTRL_10: + case ARIZONA_AIF1_FRAME_CTRL_11: + case ARIZONA_AIF1_FRAME_CTRL_12: + case ARIZONA_AIF1_FRAME_CTRL_13: + case ARIZONA_AIF1_FRAME_CTRL_14: + case ARIZONA_AIF1_FRAME_CTRL_15: + case ARIZONA_AIF1_FRAME_CTRL_16: + case ARIZONA_AIF1_FRAME_CTRL_17: + case ARIZONA_AIF1_FRAME_CTRL_18: + case ARIZONA_AIF1_TX_ENABLES: + case ARIZONA_AIF1_RX_ENABLES: + case ARIZONA_AIF2_BCLK_CTRL: + case ARIZONA_AIF2_TX_PIN_CTRL: + case ARIZONA_AIF2_RX_PIN_CTRL: + case ARIZONA_AIF2_RATE_CTRL: + case ARIZONA_AIF2_FORMAT: + case ARIZONA_AIF2_TX_BCLK_RATE: + case ARIZONA_AIF2_RX_BCLK_RATE: + case ARIZONA_AIF2_FRAME_CTRL_1: + case ARIZONA_AIF2_FRAME_CTRL_2: + case ARIZONA_AIF2_FRAME_CTRL_3: + case ARIZONA_AIF2_FRAME_CTRL_4: + case ARIZONA_AIF2_FRAME_CTRL_11: + case ARIZONA_AIF2_FRAME_CTRL_12: + case ARIZONA_AIF2_TX_ENABLES: + case ARIZONA_AIF2_RX_ENABLES: + case ARIZONA_AIF3_BCLK_CTRL: + case ARIZONA_AIF3_TX_PIN_CTRL: + case ARIZONA_AIF3_RX_PIN_CTRL: + case ARIZONA_AIF3_RATE_CTRL: + case ARIZONA_AIF3_FORMAT: + case ARIZONA_AIF3_TX_BCLK_RATE: + case ARIZONA_AIF3_RX_BCLK_RATE: + case ARIZONA_AIF3_FRAME_CTRL_1: + case ARIZONA_AIF3_FRAME_CTRL_2: + case ARIZONA_AIF3_FRAME_CTRL_3: + case ARIZONA_AIF3_FRAME_CTRL_4: + case ARIZONA_AIF3_FRAME_CTRL_11: + case ARIZONA_AIF3_FRAME_CTRL_12: + case ARIZONA_AIF3_TX_ENABLES: + case ARIZONA_AIF3_RX_ENABLES: + case ARIZONA_SLIMBUS_FRAMER_REF_GEAR: + case ARIZONA_SLIMBUS_RATES_1: + case ARIZONA_SLIMBUS_RATES_2: + case ARIZONA_SLIMBUS_RATES_3: + case ARIZONA_SLIMBUS_RATES_4: + case ARIZONA_SLIMBUS_RATES_5: + case ARIZONA_SLIMBUS_RATES_6: + case ARIZONA_SLIMBUS_RATES_7: + case ARIZONA_SLIMBUS_RATES_8: + case ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_PWM1MIX_INPUT_1_SOURCE: + case ARIZONA_PWM1MIX_INPUT_1_VOLUME: + case ARIZONA_PWM1MIX_INPUT_2_SOURCE: + case ARIZONA_PWM1MIX_INPUT_2_VOLUME: + case ARIZONA_PWM1MIX_INPUT_3_SOURCE: + case ARIZONA_PWM1MIX_INPUT_3_VOLUME: + case ARIZONA_PWM1MIX_INPUT_4_SOURCE: + case ARIZONA_PWM1MIX_INPUT_4_VOLUME: + case ARIZONA_PWM2MIX_INPUT_1_SOURCE: + case ARIZONA_PWM2MIX_INPUT_1_VOLUME: + case ARIZONA_PWM2MIX_INPUT_2_SOURCE: + case ARIZONA_PWM2MIX_INPUT_2_VOLUME: + case ARIZONA_PWM2MIX_INPUT_3_SOURCE: + case ARIZONA_PWM2MIX_INPUT_3_VOLUME: + case ARIZONA_PWM2MIX_INPUT_4_SOURCE: + case ARIZONA_PWM2MIX_INPUT_4_VOLUME: + case ARIZONA_MICMIX_INPUT_1_SOURCE: + case ARIZONA_MICMIX_INPUT_1_VOLUME: + case ARIZONA_MICMIX_INPUT_2_SOURCE: + case ARIZONA_MICMIX_INPUT_2_VOLUME: + case ARIZONA_MICMIX_INPUT_3_SOURCE: + case ARIZONA_MICMIX_INPUT_3_VOLUME: + case ARIZONA_MICMIX_INPUT_4_SOURCE: + case ARIZONA_MICMIX_INPUT_4_VOLUME: + case ARIZONA_NOISEMIX_INPUT_1_SOURCE: + case ARIZONA_NOISEMIX_INPUT_1_VOLUME: + case ARIZONA_NOISEMIX_INPUT_2_SOURCE: + case ARIZONA_NOISEMIX_INPUT_2_VOLUME: + case ARIZONA_NOISEMIX_INPUT_3_SOURCE: + case ARIZONA_NOISEMIX_INPUT_3_VOLUME: + case ARIZONA_NOISEMIX_INPUT_4_SOURCE: + case ARIZONA_NOISEMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT1RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT1RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT2LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT2LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT2RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT2RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT3LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT3LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT3RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT3RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT3RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT3RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT3RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT3RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT3RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT3RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT4RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT4RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT5RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT5RMIX_INPUT_4_VOLUME: + case ARIZONA_OUT6LMIX_INPUT_1_SOURCE: + case ARIZONA_OUT6LMIX_INPUT_1_VOLUME: + case ARIZONA_OUT6LMIX_INPUT_2_SOURCE: + case ARIZONA_OUT6LMIX_INPUT_2_VOLUME: + case ARIZONA_OUT6LMIX_INPUT_3_SOURCE: + case ARIZONA_OUT6LMIX_INPUT_3_VOLUME: + case ARIZONA_OUT6LMIX_INPUT_4_SOURCE: + case ARIZONA_OUT6LMIX_INPUT_4_VOLUME: + case ARIZONA_OUT6RMIX_INPUT_1_SOURCE: + case ARIZONA_OUT6RMIX_INPUT_1_VOLUME: + case ARIZONA_OUT6RMIX_INPUT_2_SOURCE: + case ARIZONA_OUT6RMIX_INPUT_2_VOLUME: + case ARIZONA_OUT6RMIX_INPUT_3_SOURCE: + case ARIZONA_OUT6RMIX_INPUT_3_VOLUME: + case ARIZONA_OUT6RMIX_INPUT_4_SOURCE: + case ARIZONA_OUT6RMIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME: + case ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE: + case ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_2_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_3_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_3_VOLUME: + case ARIZONA_AIF3TX1MIX_INPUT_4_SOURCE: + case ARIZONA_AIF3TX1MIX_INPUT_4_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_1_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_2_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_2_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_3_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_3_VOLUME: + case ARIZONA_AIF3TX2MIX_INPUT_4_SOURCE: + case ARIZONA_AIF3TX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME: + case ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE: + case ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME: + case ARIZONA_EQ1MIX_INPUT_1_SOURCE: + case ARIZONA_EQ1MIX_INPUT_1_VOLUME: + case ARIZONA_EQ1MIX_INPUT_2_SOURCE: + case ARIZONA_EQ1MIX_INPUT_2_VOLUME: + case ARIZONA_EQ1MIX_INPUT_3_SOURCE: + case ARIZONA_EQ1MIX_INPUT_3_VOLUME: + case ARIZONA_EQ1MIX_INPUT_4_SOURCE: + case ARIZONA_EQ1MIX_INPUT_4_VOLUME: + case ARIZONA_EQ2MIX_INPUT_1_SOURCE: + case ARIZONA_EQ2MIX_INPUT_1_VOLUME: + case ARIZONA_EQ2MIX_INPUT_2_SOURCE: + case ARIZONA_EQ2MIX_INPUT_2_VOLUME: + case ARIZONA_EQ2MIX_INPUT_3_SOURCE: + case ARIZONA_EQ2MIX_INPUT_3_VOLUME: + case ARIZONA_EQ2MIX_INPUT_4_SOURCE: + case ARIZONA_EQ2MIX_INPUT_4_VOLUME: + case ARIZONA_EQ3MIX_INPUT_1_SOURCE: + case ARIZONA_EQ3MIX_INPUT_1_VOLUME: + case ARIZONA_EQ3MIX_INPUT_2_SOURCE: + case ARIZONA_EQ3MIX_INPUT_2_VOLUME: + case ARIZONA_EQ3MIX_INPUT_3_SOURCE: + case ARIZONA_EQ3MIX_INPUT_3_VOLUME: + case ARIZONA_EQ3MIX_INPUT_4_SOURCE: + case ARIZONA_EQ3MIX_INPUT_4_VOLUME: + case ARIZONA_EQ4MIX_INPUT_1_SOURCE: + case ARIZONA_EQ4MIX_INPUT_1_VOLUME: + case ARIZONA_EQ4MIX_INPUT_2_SOURCE: + case ARIZONA_EQ4MIX_INPUT_2_VOLUME: + case ARIZONA_EQ4MIX_INPUT_3_SOURCE: + case ARIZONA_EQ4MIX_INPUT_3_VOLUME: + case ARIZONA_EQ4MIX_INPUT_4_SOURCE: + case ARIZONA_EQ4MIX_INPUT_4_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC1RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC1RMIX_INPUT_4_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_1_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_1_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_2_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_2_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_3_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_3_VOLUME: + case ARIZONA_DRC2LMIX_INPUT_4_SOURCE: + case ARIZONA_DRC2LMIX_INPUT_4_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_1_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_1_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_2_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_2_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_3_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_3_VOLUME: + case ARIZONA_DRC2RMIX_INPUT_4_SOURCE: + case ARIZONA_DRC2RMIX_INPUT_4_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP1MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP1MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP2MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP2MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP3MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP3MIX_INPUT_4_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_1_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_1_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_2_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_2_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_3_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_3_VOLUME: + case ARIZONA_HPLP4MIX_INPUT_4_SOURCE: + case ARIZONA_HPLP4MIX_INPUT_4_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_1_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_1_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_2_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_2_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_3_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_3_VOLUME: + case ARIZONA_DSP1LMIX_INPUT_4_SOURCE: + case ARIZONA_DSP1LMIX_INPUT_4_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_1_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_1_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_2_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_2_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_3_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_3_VOLUME: + case ARIZONA_DSP1RMIX_INPUT_4_SOURCE: + case ARIZONA_DSP1RMIX_INPUT_4_VOLUME: + case ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX2MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX3MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX4MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX5MIX_INPUT_1_SOURCE: + case ARIZONA_DSP1AUX6MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2LMIX_INPUT_1_SOURCE: + case ARIZONA_DSP2LMIX_INPUT_1_VOLUME: + case ARIZONA_DSP2LMIX_INPUT_2_SOURCE: + case ARIZONA_DSP2LMIX_INPUT_2_VOLUME: + case ARIZONA_DSP2LMIX_INPUT_3_SOURCE: + case ARIZONA_DSP2LMIX_INPUT_3_VOLUME: + case ARIZONA_DSP2LMIX_INPUT_4_SOURCE: + case ARIZONA_DSP2LMIX_INPUT_4_VOLUME: + case ARIZONA_DSP2RMIX_INPUT_1_SOURCE: + case ARIZONA_DSP2RMIX_INPUT_1_VOLUME: + case ARIZONA_DSP2RMIX_INPUT_2_SOURCE: + case ARIZONA_DSP2RMIX_INPUT_2_VOLUME: + case ARIZONA_DSP2RMIX_INPUT_3_SOURCE: + case ARIZONA_DSP2RMIX_INPUT_3_VOLUME: + case ARIZONA_DSP2RMIX_INPUT_4_SOURCE: + case ARIZONA_DSP2RMIX_INPUT_4_VOLUME: + case ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2AUX2MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2AUX3MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2AUX4MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2AUX5MIX_INPUT_1_SOURCE: + case ARIZONA_DSP2AUX6MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3LMIX_INPUT_1_SOURCE: + case ARIZONA_DSP3LMIX_INPUT_1_VOLUME: + case ARIZONA_DSP3LMIX_INPUT_2_SOURCE: + case ARIZONA_DSP3LMIX_INPUT_2_VOLUME: + case ARIZONA_DSP3LMIX_INPUT_3_SOURCE: + case ARIZONA_DSP3LMIX_INPUT_3_VOLUME: + case ARIZONA_DSP3LMIX_INPUT_4_SOURCE: + case ARIZONA_DSP3LMIX_INPUT_4_VOLUME: + case ARIZONA_DSP3RMIX_INPUT_1_SOURCE: + case ARIZONA_DSP3RMIX_INPUT_1_VOLUME: + case ARIZONA_DSP3RMIX_INPUT_2_SOURCE: + case ARIZONA_DSP3RMIX_INPUT_2_VOLUME: + case ARIZONA_DSP3RMIX_INPUT_3_SOURCE: + case ARIZONA_DSP3RMIX_INPUT_3_VOLUME: + case ARIZONA_DSP3RMIX_INPUT_4_SOURCE: + case ARIZONA_DSP3RMIX_INPUT_4_VOLUME: + case ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3AUX2MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3AUX3MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3AUX4MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3AUX5MIX_INPUT_1_SOURCE: + case ARIZONA_DSP3AUX6MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4LMIX_INPUT_1_SOURCE: + case ARIZONA_DSP4LMIX_INPUT_1_VOLUME: + case ARIZONA_DSP4LMIX_INPUT_2_SOURCE: + case ARIZONA_DSP4LMIX_INPUT_2_VOLUME: + case ARIZONA_DSP4LMIX_INPUT_3_SOURCE: + case ARIZONA_DSP4LMIX_INPUT_3_VOLUME: + case ARIZONA_DSP4LMIX_INPUT_4_SOURCE: + case ARIZONA_DSP4LMIX_INPUT_4_VOLUME: + case ARIZONA_DSP4RMIX_INPUT_1_SOURCE: + case ARIZONA_DSP4RMIX_INPUT_1_VOLUME: + case ARIZONA_DSP4RMIX_INPUT_2_SOURCE: + case ARIZONA_DSP4RMIX_INPUT_2_VOLUME: + case ARIZONA_DSP4RMIX_INPUT_3_SOURCE: + case ARIZONA_DSP4RMIX_INPUT_3_VOLUME: + case ARIZONA_DSP4RMIX_INPUT_4_SOURCE: + case ARIZONA_DSP4RMIX_INPUT_4_VOLUME: + case ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4AUX2MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4AUX3MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4AUX4MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4AUX5MIX_INPUT_1_SOURCE: + case ARIZONA_DSP4AUX6MIX_INPUT_1_SOURCE: + case ARIZONA_ASRC1LMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC1RMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC2LMIX_INPUT_1_SOURCE: + case ARIZONA_ASRC2RMIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE: + case ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE: + case ARIZONA_GPIO1_CTRL: + case ARIZONA_GPIO2_CTRL: + case ARIZONA_GPIO3_CTRL: + case ARIZONA_GPIO4_CTRL: + case ARIZONA_GPIO5_CTRL: + case ARIZONA_IRQ_CTRL_1: + case ARIZONA_GPIO_DEBOUNCE_CONFIG: + case ARIZONA_MISC_PAD_CTRL_1: + case ARIZONA_MISC_PAD_CTRL_2: + case ARIZONA_MISC_PAD_CTRL_3: + case ARIZONA_MISC_PAD_CTRL_4: + case ARIZONA_MISC_PAD_CTRL_5: + case ARIZONA_MISC_PAD_CTRL_6: + case ARIZONA_MISC_PAD_CTRL_7: + case ARIZONA_MISC_PAD_CTRL_8: + case ARIZONA_MISC_PAD_CTRL_9: + case ARIZONA_MISC_PAD_CTRL_10: + case ARIZONA_MISC_PAD_CTRL_11: + case ARIZONA_MISC_PAD_CTRL_12: + case ARIZONA_MISC_PAD_CTRL_13: + case ARIZONA_MISC_PAD_CTRL_14: + case ARIZONA_MISC_PAD_CTRL_15: + case ARIZONA_MISC_PAD_CTRL_16: + case ARIZONA_MISC_PAD_CTRL_17: + case ARIZONA_MISC_PAD_CTRL_18: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_INTERRUPT_STATUS_1_MASK: + case ARIZONA_INTERRUPT_STATUS_2_MASK: + case ARIZONA_INTERRUPT_STATUS_3_MASK: + case ARIZONA_INTERRUPT_STATUS_4_MASK: + case ARIZONA_INTERRUPT_STATUS_5_MASK: + case ARIZONA_INTERRUPT_CONTROL: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_2: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_IRQ2_STATUS_1_MASK: + case ARIZONA_IRQ2_STATUS_2_MASK: + case ARIZONA_IRQ2_STATUS_3_MASK: + case ARIZONA_IRQ2_STATUS_4_MASK: + case ARIZONA_IRQ2_STATUS_5_MASK: + case ARIZONA_IRQ2_CONTROL: + case ARIZONA_INTERRUPT_RAW_STATUS_2: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_WKUP_AND_TRIG: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_AOD_IRQ_MASK_IRQ1: + case ARIZONA_AOD_IRQ_MASK_IRQ2: + case ARIZONA_AOD_IRQ_RAW_STATUS: + case ARIZONA_JACK_DETECT_DEBOUNCE: + case ARIZONA_FX_CTRL1: + case ARIZONA_FX_CTRL2: + case ARIZONA_EQ1_1: + case ARIZONA_EQ1_2: + case ARIZONA_EQ1_3: + case ARIZONA_EQ1_4: + case ARIZONA_EQ1_5: + case ARIZONA_EQ1_6: + case ARIZONA_EQ1_7: + case ARIZONA_EQ1_8: + case ARIZONA_EQ1_9: + case ARIZONA_EQ1_10: + case ARIZONA_EQ1_11: + case ARIZONA_EQ1_12: + case ARIZONA_EQ1_13: + case ARIZONA_EQ1_14: + case ARIZONA_EQ1_15: + case ARIZONA_EQ1_16: + case ARIZONA_EQ1_17: + case ARIZONA_EQ1_18: + case ARIZONA_EQ1_19: + case ARIZONA_EQ1_20: + case ARIZONA_EQ1_21: + case ARIZONA_EQ2_1: + case ARIZONA_EQ2_2: + case ARIZONA_EQ2_3: + case ARIZONA_EQ2_4: + case ARIZONA_EQ2_5: + case ARIZONA_EQ2_6: + case ARIZONA_EQ2_7: + case ARIZONA_EQ2_8: + case ARIZONA_EQ2_9: + case ARIZONA_EQ2_10: + case ARIZONA_EQ2_11: + case ARIZONA_EQ2_12: + case ARIZONA_EQ2_13: + case ARIZONA_EQ2_14: + case ARIZONA_EQ2_15: + case ARIZONA_EQ2_16: + case ARIZONA_EQ2_17: + case ARIZONA_EQ2_18: + case ARIZONA_EQ2_19: + case ARIZONA_EQ2_20: + case ARIZONA_EQ2_21: + case ARIZONA_EQ3_1: + case ARIZONA_EQ3_2: + case ARIZONA_EQ3_3: + case ARIZONA_EQ3_4: + case ARIZONA_EQ3_5: + case ARIZONA_EQ3_6: + case ARIZONA_EQ3_7: + case ARIZONA_EQ3_8: + case ARIZONA_EQ3_9: + case ARIZONA_EQ3_10: + case ARIZONA_EQ3_11: + case ARIZONA_EQ3_12: + case ARIZONA_EQ3_13: + case ARIZONA_EQ3_14: + case ARIZONA_EQ3_15: + case ARIZONA_EQ3_16: + case ARIZONA_EQ3_17: + case ARIZONA_EQ3_18: + case ARIZONA_EQ3_19: + case ARIZONA_EQ3_20: + case ARIZONA_EQ3_21: + case ARIZONA_EQ4_1: + case ARIZONA_EQ4_2: + case ARIZONA_EQ4_3: + case ARIZONA_EQ4_4: + case ARIZONA_EQ4_5: + case ARIZONA_EQ4_6: + case ARIZONA_EQ4_7: + case ARIZONA_EQ4_8: + case ARIZONA_EQ4_9: + case ARIZONA_EQ4_10: + case ARIZONA_EQ4_11: + case ARIZONA_EQ4_12: + case ARIZONA_EQ4_13: + case ARIZONA_EQ4_14: + case ARIZONA_EQ4_15: + case ARIZONA_EQ4_16: + case ARIZONA_EQ4_17: + case ARIZONA_EQ4_18: + case ARIZONA_EQ4_19: + case ARIZONA_EQ4_20: + case ARIZONA_EQ4_21: + case ARIZONA_DRC1_CTRL1: + case ARIZONA_DRC1_CTRL2: + case ARIZONA_DRC1_CTRL3: + case ARIZONA_DRC1_CTRL4: + case ARIZONA_DRC1_CTRL5: + case ARIZONA_DRC2_CTRL1: + case ARIZONA_DRC2_CTRL2: + case ARIZONA_DRC2_CTRL3: + case ARIZONA_DRC2_CTRL4: + case ARIZONA_DRC2_CTRL5: + case ARIZONA_HPLPF1_1: + case ARIZONA_HPLPF1_2: + case ARIZONA_HPLPF2_1: + case ARIZONA_HPLPF2_2: + case ARIZONA_HPLPF3_1: + case ARIZONA_HPLPF3_2: + case ARIZONA_HPLPF4_1: + case ARIZONA_HPLPF4_2: + case ARIZONA_ASRC_ENABLE: + case ARIZONA_ASRC_STATUS: + case ARIZONA_ASRC_RATE1: + case ARIZONA_ISRC_1_CTRL_1: + case ARIZONA_ISRC_1_CTRL_2: + case ARIZONA_ISRC_1_CTRL_3: + case ARIZONA_ISRC_2_CTRL_1: + case ARIZONA_ISRC_2_CTRL_2: + case ARIZONA_ISRC_2_CTRL_3: + case ARIZONA_ISRC_3_CTRL_1: + case ARIZONA_ISRC_3_CTRL_2: + case ARIZONA_ISRC_3_CTRL_3: + case ARIZONA_CLOCK_CONTROL: + case ARIZONA_ANC_SRC: + case ARIZONA_DSP_STATUS: + case ARIZONA_DSP1_CONTROL_1: + case ARIZONA_DSP1_CLOCKING_1: + case ARIZONA_DSP1_STATUS_1: + case ARIZONA_DSP1_STATUS_2: + case ARIZONA_DSP2_CONTROL_1: + case ARIZONA_DSP2_CLOCKING_1: + case ARIZONA_DSP2_STATUS_1: + case ARIZONA_DSP2_STATUS_2: + case ARIZONA_DSP3_CONTROL_1: + case ARIZONA_DSP3_CLOCKING_1: + case ARIZONA_DSP3_STATUS_1: + case ARIZONA_DSP3_STATUS_2: + case ARIZONA_DSP4_CONTROL_1: + case ARIZONA_DSP4_CLOCKING_1: + case ARIZONA_DSP4_STATUS_1: + case ARIZONA_DSP4_STATUS_2: + return true; + default: + return false; + } +} + +static bool wm5110_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ARIZONA_SOFTWARE_RESET: + case ARIZONA_DEVICE_REVISION: + case ARIZONA_HAPTICS_STATUS: + case ARIZONA_SAMPLE_RATE_1_STATUS: + case ARIZONA_SAMPLE_RATE_2_STATUS: + case ARIZONA_SAMPLE_RATE_3_STATUS: + case ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS: + case ARIZONA_MIC_DETECT_3: + case ARIZONA_HEADPHONE_DETECT_2: + case ARIZONA_INPUT_ENABLES_STATUS: + case ARIZONA_OUTPUT_STATUS_1: + case ARIZONA_RAW_OUTPUT_STATUS_1: + case ARIZONA_SLIMBUS_RX_PORT_STATUS: + case ARIZONA_SLIMBUS_TX_PORT_STATUS: + case ARIZONA_INTERRUPT_STATUS_1: + case ARIZONA_INTERRUPT_STATUS_2: + case ARIZONA_INTERRUPT_STATUS_3: + case ARIZONA_INTERRUPT_STATUS_4: + case ARIZONA_INTERRUPT_STATUS_5: + case ARIZONA_IRQ2_STATUS_1: + case ARIZONA_IRQ2_STATUS_2: + case ARIZONA_IRQ2_STATUS_3: + case ARIZONA_IRQ2_STATUS_4: + case ARIZONA_IRQ2_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_2: + case ARIZONA_INTERRUPT_RAW_STATUS_3: + case ARIZONA_INTERRUPT_RAW_STATUS_4: + case ARIZONA_INTERRUPT_RAW_STATUS_5: + case ARIZONA_INTERRUPT_RAW_STATUS_6: + case ARIZONA_INTERRUPT_RAW_STATUS_7: + case ARIZONA_INTERRUPT_RAW_STATUS_8: + case ARIZONA_IRQ_PIN_STATUS: + case ARIZONA_AOD_IRQ1: + case ARIZONA_AOD_IRQ2: + case ARIZONA_ASRC_STATUS: + case ARIZONA_DSP_STATUS: + case ARIZONA_DSP1_CONTROL_1: + case ARIZONA_DSP1_CLOCKING_1: + case ARIZONA_DSP1_STATUS_1: + case ARIZONA_DSP1_STATUS_2: + case ARIZONA_DSP2_STATUS_1: + case ARIZONA_DSP2_STATUS_2: + case ARIZONA_DSP3_STATUS_1: + case ARIZONA_DSP3_STATUS_2: + case ARIZONA_DSP4_STATUS_1: + case ARIZONA_DSP4_STATUS_2: + return true; + default: + return false; + } +} + +const struct regmap_config wm5110_spi_regmap = { + .reg_bits = 32, + .pad_bits = 16, + .val_bits = 16, + + .max_register = ARIZONA_DSP1_STATUS_2, + .readable_reg = wm5110_readable_register, + .volatile_reg = wm5110_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm5110_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm5110_reg_default), +}; +EXPORT_SYMBOL_GPL(wm5110_spi_regmap); + +const struct regmap_config wm5110_i2c_regmap = { + .reg_bits = 32, + .val_bits = 16, + + .max_register = ARIZONA_DSP1_STATUS_2, + .readable_reg = wm5110_readable_register, + .volatile_reg = wm5110_volatile_register, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = wm5110_reg_default, + .num_reg_defaults = ARRAY_SIZE(wm5110_reg_default), +}; +EXPORT_SYMBOL_GPL(wm5110_i2c_regmap); diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 8a9b11ca076..7c1ae24605d 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -32,9 +32,6 @@ #include <linux/mfd/wm8350/supply.h> #include <linux/mfd/wm8350/wdt.h> -#define WM8350_UNLOCK_KEY 0x0013 -#define WM8350_LOCK_KEY 0x0000 - #define WM8350_CLOCK_CONTROL_1 0x28 #define WM8350_AIF_TEST 0x74 @@ -63,181 +60,32 @@ /* * WM8350 Device IO */ -static DEFINE_MUTEX(io_mutex); static DEFINE_MUTEX(reg_lock_mutex); -/* Perform a physical read from the device. - */ -static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs, - u16 *dest) -{ - int i, ret; - int bytes = num_regs * 2; - - dev_dbg(wm8350->dev, "volatile read\n"); - ret = regmap_raw_read(wm8350->regmap, reg, dest, bytes); - - for (i = reg; i < reg + num_regs; i++) { - /* Cache is CPU endian */ - dest[i - reg] = be16_to_cpu(dest[i - reg]); - - /* Mask out non-readable bits */ - dest[i - reg] &= wm8350_reg_io_map[i].readable; - } - - dump(num_regs, dest); - - return ret; -} - -static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest) -{ - int i; - int end = reg + num_regs; - int ret = 0; - int bytes = num_regs * 2; - - if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { - dev_err(wm8350->dev, "invalid reg %x\n", - reg + num_regs - 1); - return -EINVAL; - } - - dev_dbg(wm8350->dev, - "%s R%d(0x%2.2x) %d regs\n", __func__, reg, reg, num_regs); - -#if WM8350_BUS_DEBUG - /* we can _safely_ read any register, but warn if read not supported */ - for (i = reg; i < end; i++) { - if (!wm8350_reg_io_map[i].readable) - dev_warn(wm8350->dev, - "reg R%d is not readable\n", i); - } -#endif - - /* if any volatile registers are required, then read back all */ - for (i = reg; i < end; i++) - if (wm8350_reg_io_map[i].vol) - return wm8350_phys_read(wm8350, reg, num_regs, dest); - - /* no volatiles, then cache is good */ - dev_dbg(wm8350->dev, "cache read\n"); - memcpy(dest, &wm8350->reg_cache[reg], bytes); - dump(num_regs, dest); - return ret; -} - -static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) -{ - if (reg == WM8350_SECURITY || - wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) - return 0; - - if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && - reg <= WM8350_GPIO_FUNCTION_SELECT_4) || - (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && - reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) - return 1; - return 0; -} - -static int wm8350_write(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *src) -{ - int i; - int end = reg + num_regs; - int bytes = num_regs * 2; - - if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) { - dev_err(wm8350->dev, "invalid reg %x\n", - reg + num_regs - 1); - return -EINVAL; - } - - /* it's generally not a good idea to write to RO or locked registers */ - for (i = reg; i < end; i++) { - if (!wm8350_reg_io_map[i].writable) { - dev_err(wm8350->dev, - "attempted write to read only reg R%d\n", i); - return -EINVAL; - } - - if (is_reg_locked(wm8350, i)) { - dev_err(wm8350->dev, - "attempted write to locked reg R%d\n", i); - return -EINVAL; - } - - src[i - reg] &= wm8350_reg_io_map[i].writable; - - wm8350->reg_cache[i] = - (wm8350->reg_cache[i] & ~wm8350_reg_io_map[i].writable) - | src[i - reg]; - - src[i - reg] = cpu_to_be16(src[i - reg]); - } - - /* Actually write it out */ - return regmap_raw_write(wm8350->regmap, reg, src, bytes); -} - /* * Safe read, modify, write methods */ int wm8350_clear_bits(struct wm8350 *wm8350, u16 reg, u16 mask) { - u16 data; - int err; - - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); - if (err) { - dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - goto out; - } - - data &= ~mask; - err = wm8350_write(wm8350, reg, 1, &data); - if (err) - dev_err(wm8350->dev, "write to reg R%d failed\n", reg); -out: - mutex_unlock(&io_mutex); - return err; + return regmap_update_bits(wm8350->regmap, reg, mask, 0); } EXPORT_SYMBOL_GPL(wm8350_clear_bits); int wm8350_set_bits(struct wm8350 *wm8350, u16 reg, u16 mask) { - u16 data; - int err; - - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); - if (err) { - dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - goto out; - } - - data |= mask; - err = wm8350_write(wm8350, reg, 1, &data); - if (err) - dev_err(wm8350->dev, "write to reg R%d failed\n", reg); -out: - mutex_unlock(&io_mutex); - return err; + return regmap_update_bits(wm8350->regmap, reg, mask, mask); } EXPORT_SYMBOL_GPL(wm8350_set_bits); u16 wm8350_reg_read(struct wm8350 *wm8350, int reg) { - u16 data; + unsigned int data; int err; - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, reg, 1, &data); + err = regmap_read(wm8350->regmap, reg, &data); if (err) dev_err(wm8350->dev, "read from reg R%d failed\n", reg); - mutex_unlock(&io_mutex); return data; } EXPORT_SYMBOL_GPL(wm8350_reg_read); @@ -245,13 +93,11 @@ EXPORT_SYMBOL_GPL(wm8350_reg_read); int wm8350_reg_write(struct wm8350 *wm8350, int reg, u16 val) { int ret; - u16 data = val; - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, reg, 1, &data); + ret = regmap_write(wm8350->regmap, reg, val); + if (ret) dev_err(wm8350->dev, "write to reg R%d failed\n", reg); - mutex_unlock(&io_mutex); return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_write); @@ -261,12 +107,11 @@ int wm8350_block_read(struct wm8350 *wm8350, int start_reg, int regs, { int err = 0; - mutex_lock(&io_mutex); - err = wm8350_read(wm8350, start_reg, regs, dest); + err = regmap_bulk_read(wm8350->regmap, start_reg, dest, regs); if (err) dev_err(wm8350->dev, "block read starting from R%d failed\n", start_reg); - mutex_unlock(&io_mutex); + return err; } EXPORT_SYMBOL_GPL(wm8350_block_read); @@ -276,12 +121,11 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, { int ret = 0; - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, start_reg, regs, src); + ret = regmap_bulk_write(wm8350->regmap, start_reg, src, regs); if (ret) dev_err(wm8350->dev, "block write starting at R%d failed\n", start_reg); - mutex_unlock(&io_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_block_write); @@ -295,15 +139,20 @@ EXPORT_SYMBOL_GPL(wm8350_block_write); */ int wm8350_reg_lock(struct wm8350 *wm8350) { - u16 key = WM8350_LOCK_KEY; int ret; + mutex_lock(®_lock_mutex); + ldbg(__func__); - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); + + ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_LOCK_KEY); if (ret) dev_err(wm8350->dev, "lock failed\n"); - mutex_unlock(&io_mutex); + + wm8350->unlocked = false; + + mutex_unlock(®_lock_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_lock); @@ -319,15 +168,20 @@ EXPORT_SYMBOL_GPL(wm8350_reg_lock); */ int wm8350_reg_unlock(struct wm8350 *wm8350) { - u16 key = WM8350_UNLOCK_KEY; int ret; + mutex_lock(®_lock_mutex); + ldbg(__func__); - mutex_lock(&io_mutex); - ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key); + + ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_UNLOCK_KEY); if (ret) dev_err(wm8350->dev, "unlock failed\n"); - mutex_unlock(&io_mutex); + + wm8350->unlocked = true; + + mutex_unlock(®_lock_mutex); + return ret; } EXPORT_SYMBOL_GPL(wm8350_reg_unlock); @@ -395,146 +249,6 @@ static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data) } /* - * Cache is always host endian. - */ -static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) -{ - int i, ret = 0; - u16 value; - const u16 *reg_map; - - switch (type) { - case 0: - switch (mode) { -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 - case 0: - reg_map = wm8350_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 - case 1: - reg_map = wm8350_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 - case 2: - reg_map = wm8350_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 - case 3: - reg_map = wm8350_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8350 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - case 1: - switch (mode) { -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 - case 0: - reg_map = wm8351_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 - case 1: - reg_map = wm8351_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 - case 2: - reg_map = wm8351_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 - case 3: - reg_map = wm8351_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8351 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - case 2: - switch (mode) { -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 - case 0: - reg_map = wm8352_mode0_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 - case 1: - reg_map = wm8352_mode1_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 - case 2: - reg_map = wm8352_mode2_defaults; - break; -#endif -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 - case 3: - reg_map = wm8352_mode3_defaults; - break; -#endif - default: - dev_err(wm8350->dev, - "WM8352 configuration mode %d not supported\n", - mode); - return -EINVAL; - } - break; - - default: - dev_err(wm8350->dev, - "WM835x configuration mode %d not supported\n", - mode); - return -EINVAL; - } - - wm8350->reg_cache = - kmalloc(sizeof(u16) * (WM8350_MAX_REGISTER + 1), GFP_KERNEL); - if (wm8350->reg_cache == NULL) - return -ENOMEM; - - /* Read the initial cache state back from the device - this is - * a PMIC so the device many not be in a virgin state and we - * can't rely on the silicon values. - */ - ret = regmap_raw_read(wm8350->regmap, 0, wm8350->reg_cache, - sizeof(u16) * (WM8350_MAX_REGISTER + 1)); - if (ret < 0) { - dev_err(wm8350->dev, - "failed to read initial cache values\n"); - goto out; - } - - /* Mask out uncacheable/unreadable bits and the audio. */ - for (i = 0; i < WM8350_MAX_REGISTER; i++) { - if (wm8350_reg_io_map[i].readable && - (i < WM8350_CLOCK_CONTROL_1 || i > WM8350_AIF_TEST)) { - value = be16_to_cpu(wm8350->reg_cache[i]); - value &= wm8350_reg_io_map[i].readable; - wm8350->reg_cache[i] = value; - } else - wm8350->reg_cache[i] = reg_map[i]; - } - -out: - kfree(wm8350->reg_cache); - return ret; -} - -/* * Register a client device. This is non-fatal since there is no need to * fail the entire device init due to a single platform device failing. */ @@ -681,18 +395,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, goto err; } - ret = wm8350_create_cache(wm8350, mask_rev, mode); - if (ret < 0) { - dev_err(wm8350->dev, "Failed to create register cache\n"); - return ret; - } - mutex_init(&wm8350->auxadc_mutex); init_completion(&wm8350->auxadc_done); ret = wm8350_irq_init(wm8350, irq, pdata); if (ret < 0) - goto err_free; + goto err; if (wm8350->irq_base) { ret = request_threaded_irq(wm8350->irq_base + @@ -730,8 +438,6 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, err_irq: wm8350_irq_exit(wm8350); -err_free: - kfree(wm8350->reg_cache); err: return ret; } @@ -758,8 +464,6 @@ void wm8350_device_exit(struct wm8350 *wm8350) free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350); wm8350_irq_exit(wm8350); - - kfree(wm8350->reg_cache); } EXPORT_SYMBOL_GPL(wm8350_device_exit); diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index a68aceb4e48..2e57101c8d3 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c @@ -23,11 +23,6 @@ #include <linux/regmap.h> #include <linux/slab.h> -static const struct regmap_config wm8350_regmap = { - .reg_bits = 8, - .val_bits = 16, -}; - static int wm8350_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c index 9fd01bf63c5..624ff90501c 100644 --- a/drivers/mfd/wm8350-irq.c +++ b/drivers/mfd/wm8350-irq.c @@ -432,11 +432,9 @@ static void wm8350_irq_sync_unlock(struct irq_data *data) for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) { /* If there's been a change in the mask write it back * to the hardware. */ - if (wm8350->irq_masks[i] != - wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i]) - WARN_ON(wm8350_reg_write(wm8350, - WM8350_INT_STATUS_1_MASK + i, - wm8350->irq_masks[i])); + WARN_ON(regmap_update_bits(wm8350->regmap, + WM8350_INT_STATUS_1_MASK + i, + 0xffff, wm8350->irq_masks[i])); } mutex_unlock(&wm8350->irq_lock); diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index e965139e5cd..9efc64750fb 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c @@ -14,3170 +14,18 @@ #include <linux/mfd/wm8350/core.h> -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode0_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0000, /* R195 - DCDC6 Control */ - 0x0000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode1_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0014, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x00FB, /* R134 - GPIO Configuration (i/o) */ - 0x04FE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0312, /* R140 - GPIO Function Select 1 */ - 0x1003, /* R141 - GPIO Function Select 2 */ - 0x1331, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0062, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0800, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0400, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0006, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode2_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1002, /* R3 - System Control 1 */ - 0x0014, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x08FB, /* R134 - GPIO Configuration (i/o) */ - 0x0CFE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0312, /* R140 - GPIO Function Select 1 */ - 0x0003, /* R141 - GPIO Function Select 2 */ - 0x2331, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x002E, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x0800, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0C00, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001A, /* R200 - LDO1 Control */ - 0x0800, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0800, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x000A, /* R206 - LDO3 Control */ - 0x0C00, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0800, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8350_mode3_defaults[] = { - 0x17FF, /* R0 - Reset/ID */ - 0x1000, /* R1 - ID */ - 0x0000, /* R2 */ - 0x1000, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 - Power Up Interrupt Status */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 - Power Up Interrupt Status Mask */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3B00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - LOUT1 Volume */ - 0x00E4, /* R105 - ROUT1 Volume */ - 0x00E4, /* R106 - LOUT2 Volume */ - 0x02E4, /* R107 - ROUT2 Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 - AIF Test */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x03FC, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0A7B, /* R134 - GPIO Configuration (i/o) */ - 0x06FE, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1312, /* R140 - GPIO Function Select 1 */ - 0x1030, /* R141 - GPIO Function Select 2 */ - 0x2231, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x002D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x000E, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0026, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0400, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001C, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001C, /* R206 - LDO3 Control */ - 0x0400, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001F, /* R209 - LDO4 Control */ - 0x0400, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 */ - 0x4000, /* R220 - RAM BIST 1 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 */ - 0x0000, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 */ - 0x0000, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0000, /* R245 */ - 0x0000, /* R246 */ - 0x0000, /* R247 */ - 0x0000, /* R248 */ - 0x0000, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0000, /* R252 */ - 0x0000, /* R253 */ - 0x0000, /* R254 */ - 0x0000, /* R255 */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode0_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0000, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode1_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0CFB, /* R134 - GPIO Configuration (i/o) */ - 0x0C1F, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0300, /* R140 - GPIO Function Select 1 */ - 0x1110, /* R141 - GPIO Function Select 2 */ - 0x0013, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0C00, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x0800, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x000A, /* R195 */ - 0x1000, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0C00, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001F, /* R206 - LDO3 Control */ - 0x0800, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x000A, /* R209 - LDO4 Control */ - 0x0800, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x1000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode2_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0214, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0110, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x09FA, /* R134 - GPIO Configuration (i/o) */ - 0x0DF6, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1310, /* R140 - GPIO Function Select 1 */ - 0x0003, /* R141 - GPIO Function Select 2 */ - 0x2000, /* R142 - GPIO Function Select 3 */ - 0x0000, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x001A, /* R180 - DCDC1 Control */ - 0x0800, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0056, /* R186 - DCDC3 Control */ - 0x0400, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0026, /* R189 - DCDC4 Control */ - 0x0C00, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0026, /* R195 */ - 0x0C00, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0400, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0010, /* R203 - LDO2 Control */ - 0x0C00, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0015, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8351_mode3_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0001, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0010, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0310, /* R140 - GPIO Function Select 1 */ - 0x0001, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0026, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0062, /* R189 - DCDC4 Control */ - 0x1400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0026, /* R195 */ - 0x0400, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0006, /* R200 - LDO1 Control */ - 0x0C00, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0016, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0019, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x1000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 - FLL Test 1 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x1000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode0_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0004, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0FFC, /* R134 - GPIO Configuration (i/o) */ - 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0013, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x0000, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0000, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0000, /* R186 - DCDC3 Control */ - 0x0000, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0000, /* R189 - DCDC4 Control */ - 0x0000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0000, /* R195 - DCDC6 Control */ - 0x0000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001B, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001B, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001B, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode1_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFF, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0300, /* R140 - GPIO Function Select 1 */ - 0x0000, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0062, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0006, /* R186 - DCDC3 Control */ - 0x0800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x0006, /* R189 - DCDC4 Control */ - 0x0C00, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x1000, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x0002, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x001A, /* R203 - LDO2 Control */ - 0x0000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001F, /* R206 - LDO3 Control */ - 0x0000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001F, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode2_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0000, /* R129 - GPIO Pin pull up Control */ - 0x0110, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x09DA, /* R134 - GPIO Configuration (i/o) */ - 0x0DD6, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x1310, /* R140 - GPIO Function Select 1 */ - 0x0033, /* R141 - GPIO Function Select 2 */ - 0x2000, /* R142 - GPIO Function Select 3 */ - 0x0000, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x000E, /* R180 - DCDC1 Control */ - 0x0800, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0056, /* R186 - DCDC3 Control */ - 0x1800, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x1000, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0026, /* R195 - DCDC6 Control */ - 0x0C00, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001C, /* R200 - LDO1 Control */ - 0x0000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0006, /* R203 - LDO2 Control */ - 0x0400, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x001C, /* R206 - LDO3 Control */ - 0x1400, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x001A, /* R209 - LDO4 Control */ - 0x0000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - -#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 - -#undef WM8350_HAVE_CONFIG_MODE -#define WM8350_HAVE_CONFIG_MODE - -const u16 wm8352_mode3_defaults[] = { - 0x6143, /* R0 - Reset/ID */ - 0x0000, /* R1 - ID */ - 0x0002, /* R2 - Revision */ - 0x1C02, /* R3 - System Control 1 */ - 0x0204, /* R4 - System Control 2 */ - 0x0000, /* R5 - System Hibernate */ - 0x8A00, /* R6 - Interface Control */ - 0x0000, /* R7 */ - 0x8000, /* R8 - Power mgmt (1) */ - 0x0000, /* R9 - Power mgmt (2) */ - 0x0000, /* R10 - Power mgmt (3) */ - 0x2000, /* R11 - Power mgmt (4) */ - 0x0E00, /* R12 - Power mgmt (5) */ - 0x0000, /* R13 - Power mgmt (6) */ - 0x0000, /* R14 - Power mgmt (7) */ - 0x0000, /* R15 */ - 0x0000, /* R16 - RTC Seconds/Minutes */ - 0x0100, /* R17 - RTC Hours/Day */ - 0x0101, /* R18 - RTC Date/Month */ - 0x1400, /* R19 - RTC Year */ - 0x0000, /* R20 - Alarm Seconds/Minutes */ - 0x0000, /* R21 - Alarm Hours/Day */ - 0x0000, /* R22 - Alarm Date/Month */ - 0x0320, /* R23 - RTC Time Control */ - 0x0000, /* R24 - System Interrupts */ - 0x0000, /* R25 - Interrupt Status 1 */ - 0x0000, /* R26 - Interrupt Status 2 */ - 0x0000, /* R27 */ - 0x0000, /* R28 - Under Voltage Interrupt status */ - 0x0000, /* R29 - Over Current Interrupt status */ - 0x0000, /* R30 - GPIO Interrupt Status */ - 0x0000, /* R31 - Comparator Interrupt Status */ - 0x3FFF, /* R32 - System Interrupts Mask */ - 0x0000, /* R33 - Interrupt Status 1 Mask */ - 0x0000, /* R34 - Interrupt Status 2 Mask */ - 0x0000, /* R35 */ - 0x0000, /* R36 - Under Voltage Interrupt status Mask */ - 0x0000, /* R37 - Over Current Interrupt status Mask */ - 0x0000, /* R38 - GPIO Interrupt Status Mask */ - 0x0000, /* R39 - Comparator Interrupt Status Mask */ - 0x0040, /* R40 - Clock Control 1 */ - 0x0000, /* R41 - Clock Control 2 */ - 0x3A00, /* R42 - FLL Control 1 */ - 0x7086, /* R43 - FLL Control 2 */ - 0xC226, /* R44 - FLL Control 3 */ - 0x0000, /* R45 - FLL Control 4 */ - 0x0000, /* R46 */ - 0x0000, /* R47 */ - 0x0000, /* R48 - DAC Control */ - 0x0000, /* R49 */ - 0x00C0, /* R50 - DAC Digital Volume L */ - 0x00C0, /* R51 - DAC Digital Volume R */ - 0x0000, /* R52 */ - 0x0040, /* R53 - DAC LR Rate */ - 0x0000, /* R54 - DAC Clock Control */ - 0x0000, /* R55 */ - 0x0000, /* R56 */ - 0x0000, /* R57 */ - 0x4000, /* R58 - DAC Mute */ - 0x0000, /* R59 - DAC Mute Volume */ - 0x0000, /* R60 - DAC Side */ - 0x0000, /* R61 */ - 0x0000, /* R62 */ - 0x0000, /* R63 */ - 0x8000, /* R64 - ADC Control */ - 0x0000, /* R65 */ - 0x00C0, /* R66 - ADC Digital Volume L */ - 0x00C0, /* R67 - ADC Digital Volume R */ - 0x0000, /* R68 - ADC Divider */ - 0x0000, /* R69 */ - 0x0040, /* R70 - ADC LR Rate */ - 0x0000, /* R71 */ - 0x0303, /* R72 - Input Control */ - 0x0000, /* R73 - IN3 Input Control */ - 0x0000, /* R74 - Mic Bias Control */ - 0x0000, /* R75 */ - 0x0000, /* R76 - Output Control */ - 0x0000, /* R77 - Jack Detect */ - 0x0000, /* R78 - Anti Pop Control */ - 0x0000, /* R79 */ - 0x0040, /* R80 - Left Input Volume */ - 0x0040, /* R81 - Right Input Volume */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 */ - 0x0000, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 */ - 0x0800, /* R88 - Left Mixer Control */ - 0x1000, /* R89 - Right Mixer Control */ - 0x0000, /* R90 */ - 0x0000, /* R91 */ - 0x0000, /* R92 - OUT3 Mixer Control */ - 0x0000, /* R93 - OUT4 Mixer Control */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 - Output Left Mixer Volume */ - 0x0000, /* R97 - Output Right Mixer Volume */ - 0x0000, /* R98 - Input Mixer Volume L */ - 0x0000, /* R99 - Input Mixer Volume R */ - 0x0000, /* R100 - Input Mixer Volume */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x00E4, /* R104 - OUT1L Volume */ - 0x00E4, /* R105 - OUT1R Volume */ - 0x00E4, /* R106 - OUT2L Volume */ - 0x02E4, /* R107 - OUT2R Volume */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 - BEEP Volume */ - 0x0A00, /* R112 - AI Formating */ - 0x0000, /* R113 - ADC DAC COMP */ - 0x0020, /* R114 - AI ADC Control */ - 0x0020, /* R115 - AI DAC Control */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x1FFF, /* R128 - GPIO Debounce */ - 0x0010, /* R129 - GPIO Pin pull up Control */ - 0x0000, /* R130 - GPIO Pull down Control */ - 0x0000, /* R131 - GPIO Interrupt Mode */ - 0x0000, /* R132 */ - 0x0000, /* R133 - GPIO Control */ - 0x0BFB, /* R134 - GPIO Configuration (i/o) */ - 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0310, /* R140 - GPIO Function Select 1 */ - 0x0001, /* R141 - GPIO Function Select 2 */ - 0x2300, /* R142 - GPIO Function Select 3 */ - 0x0003, /* R143 - GPIO Function Select 4 */ - 0x0000, /* R144 - Digitiser Control (1) */ - 0x0002, /* R145 - Digitiser Control (2) */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x7000, /* R152 - AUX1 Readback */ - 0x7000, /* R153 - AUX2 Readback */ - 0x7000, /* R154 - AUX3 Readback */ - 0x7000, /* R155 - AUX4 Readback */ - 0x0000, /* R156 - USB Voltage Readback */ - 0x0000, /* R157 - LINE Voltage Readback */ - 0x0000, /* R158 - BATT Voltage Readback */ - 0x0000, /* R159 - Chip Temp Readback */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 - Generic Comparator Control */ - 0x0000, /* R164 - Generic comparator 1 */ - 0x0000, /* R165 - Generic comparator 2 */ - 0x0000, /* R166 - Generic comparator 3 */ - 0x0000, /* R167 - Generic comparator 4 */ - 0xA00F, /* R168 - Battery Charger Control 1 */ - 0x0B06, /* R169 - Battery Charger Control 2 */ - 0x0000, /* R170 - Battery Charger Control 3 */ - 0x0000, /* R171 */ - 0x0000, /* R172 - Current Sink Driver A */ - 0x0000, /* R173 - CSA Flash control */ - 0x0000, /* R174 - Current Sink Driver B */ - 0x0000, /* R175 - CSB Flash control */ - 0x0000, /* R176 - DCDC/LDO requested */ - 0x032D, /* R177 - DCDC Active options */ - 0x0000, /* R178 - DCDC Sleep options */ - 0x0025, /* R179 - Power-check comparator */ - 0x0006, /* R180 - DCDC1 Control */ - 0x0400, /* R181 - DCDC1 Timeouts */ - 0x1006, /* R182 - DCDC1 Low Power */ - 0x0018, /* R183 - DCDC2 Control */ - 0x0000, /* R184 - DCDC2 Timeouts */ - 0x0000, /* R185 */ - 0x0050, /* R186 - DCDC3 Control */ - 0x0C00, /* R187 - DCDC3 Timeouts */ - 0x0006, /* R188 - DCDC3 Low Power */ - 0x000E, /* R189 - DCDC4 Control */ - 0x0400, /* R190 - DCDC4 Timeouts */ - 0x0006, /* R191 - DCDC4 Low Power */ - 0x0008, /* R192 - DCDC5 Control */ - 0x0000, /* R193 - DCDC5 Timeouts */ - 0x0000, /* R194 */ - 0x0029, /* R195 - DCDC6 Control */ - 0x0800, /* R196 - DCDC6 Timeouts */ - 0x0006, /* R197 - DCDC6 Low Power */ - 0x0000, /* R198 */ - 0x0003, /* R199 - Limit Switch Control */ - 0x001D, /* R200 - LDO1 Control */ - 0x1000, /* R201 - LDO1 Timeouts */ - 0x001C, /* R202 - LDO1 Low Power */ - 0x0017, /* R203 - LDO2 Control */ - 0x1000, /* R204 - LDO2 Timeouts */ - 0x001C, /* R205 - LDO2 Low Power */ - 0x0006, /* R206 - LDO3 Control */ - 0x1000, /* R207 - LDO3 Timeouts */ - 0x001C, /* R208 - LDO3 Low Power */ - 0x0010, /* R209 - LDO4 Control */ - 0x1000, /* R210 - LDO4 Timeouts */ - 0x001C, /* R211 - LDO4 Low Power */ - 0x0000, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 - VCC_FAULT Masks */ - 0x001F, /* R216 - Main Bandgap Control */ - 0x0000, /* R217 - OSC Control */ - 0x9000, /* R218 - RTC Tick Control */ - 0x0000, /* R219 - Security1 */ - 0x4000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0000, /* R223 */ - 0x0000, /* R224 - Signal overrides */ - 0x0000, /* R225 - DCDC/LDO status */ - 0x0000, /* R226 - Charger Overides/status */ - 0x0000, /* R227 - misc overrides */ - 0x0000, /* R228 - Supply overrides/status 1 */ - 0x0000, /* R229 - Supply overrides/status 2 */ - 0xE000, /* R230 - GPIO Pin Status */ - 0x0000, /* R231 - comparotor overrides */ - 0x0000, /* R232 */ - 0x0000, /* R233 - State Machine status */ - 0x1200, /* R234 */ - 0x0000, /* R235 */ - 0x8000, /* R236 */ - 0x0000, /* R237 */ - 0x0000, /* R238 */ - 0x0000, /* R239 */ - 0x0003, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0004, /* R243 */ - 0x0300, /* R244 */ - 0x0000, /* R245 */ - 0x0200, /* R246 */ - 0x0000, /* R247 */ - 0x1000, /* R248 - DCDC1 Test Controls */ - 0x5000, /* R249 */ - 0x1000, /* R250 - DCDC3 Test Controls */ - 0x1000, /* R251 - DCDC4 Test Controls */ - 0x5100, /* R252 */ - 0x1000, /* R253 - DCDC6 Test Controls */ -}; -#endif - /* * Access masks. */ -const struct wm8350_reg_access wm8350_reg_io_map[] = { +static const struct wm8350_reg_access { + u16 readable; /* Mask of readable bits */ + u16 writable; /* Mask of writable bits */ + u16 vol; /* Mask of volatile bits */ +} wm8350_reg_io_map[] = { /* read write volatile */ - { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */ - { 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */ + { 0xFFFF, 0xFFFF, 0x0000 }, /* R0 - Reset/ID */ + { 0x7CFF, 0x0C00, 0x0000 }, /* R1 - ID */ { 0x007F, 0x0000, 0x0000 }, /* R2 - ROM Mask ID */ { 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */ { 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */ @@ -3433,3 +281,59 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = { { 0x0000, 0x0000, 0x0000 }, /* R254 */ { 0x0000, 0x0000, 0x0000 }, /* R255 */ }; + +static bool wm8350_readable(struct device *dev, unsigned int reg) +{ + return wm8350_reg_io_map[reg].readable; +} + +static bool wm8350_writeable(struct device *dev, unsigned int reg) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + + if (!wm8350->unlocked) { + if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && + reg <= WM8350_GPIO_FUNCTION_SELECT_4) || + (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && + reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) + return false; + } + + return wm8350_reg_io_map[reg].writable; +} + +static bool wm8350_volatile(struct device *dev, unsigned int reg) +{ + return wm8350_reg_io_map[reg].vol; +} + +static bool wm8350_precious(struct device *dev, unsigned int reg) +{ + switch (reg) { + case WM8350_SYSTEM_INTERRUPTS: + case WM8350_INT_STATUS_1: + case WM8350_INT_STATUS_2: + case WM8350_POWER_UP_INT_STATUS: + case WM8350_UNDER_VOLTAGE_INT_STATUS: + case WM8350_OVER_CURRENT_INT_STATUS: + case WM8350_GPIO_INT_STATUS: + case WM8350_COMPARATOR_INT_STATUS: + return true; + + default: + return false; + } +} + +const struct regmap_config wm8350_regmap = { + .reg_bits = 8, + .val_bits = 16, + + .cache_type = REGCACHE_RBTREE, + + .max_register = WM8350_MAX_REGISTER, + .readable_reg = wm8350_readable, + .writeable_reg = wm8350_writeable, + .volatile_reg = wm8350_volatile, + .precious_reg = wm8350_precious, +}; diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 1e321d34977..eec74aa55fd 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -283,9 +283,24 @@ static int wm8994_suspend(struct device *dev) wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET)); - regcache_cache_only(wm8994->regmap, true); regcache_mark_dirty(wm8994->regmap); + /* Restore GPIO registers to prevent problems with mismatched + * pin configurations. + */ + ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1, + WM8994_GPIO_11); + if (ret != 0) + dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); + + /* In case one of the GPIOs is used as a wake input. */ + ret = regcache_sync_region(wm8994->regmap, + WM8994_INTERRUPT_STATUS_1_MASK, + WM8994_INTERRUPT_STATUS_1_MASK); + if (ret != 0) + dev_err(dev, "Failed to restore interrupt mask: %d\n", ret); + + regcache_cache_only(wm8994->regmap, true); wm8994->suspended = true; ret = regulator_bulk_disable(wm8994->num_supplies, diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c index f1837f66975..0aac4aff17a 100644 --- a/drivers/mfd/wm8994-irq.c +++ b/drivers/mfd/wm8994-irq.c @@ -21,6 +21,7 @@ #include <linux/regmap.h> #include <linux/mfd/wm8994/core.h> +#include <linux/mfd/wm8994/pdata.h> #include <linux/mfd/wm8994/registers.h> #include <linux/delay.h> @@ -139,6 +140,8 @@ static struct regmap_irq_chip wm8994_irq_chip = { int wm8994_irq_init(struct wm8994 *wm8994) { int ret; + unsigned long irqflags; + struct wm8994_pdata *pdata = wm8994->dev->platform_data; if (!wm8994->irq) { dev_warn(wm8994->dev, @@ -147,8 +150,13 @@ int wm8994_irq_init(struct wm8994 *wm8994) return 0; } + /* select user or default irq flags */ + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; + if (pdata->irq_flags) + irqflags = pdata->irq_flags; + ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, - IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + irqflags, wm8994->irq_base, &wm8994_irq_chip, &wm8994->irq_data); if (ret != 0) { diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 154f3ef0763..98a442da892 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -64,6 +64,7 @@ config AB8500_PWM bool "AB8500 PWM support" depends on AB8500_CORE && ARCH_U8500 select HAVE_PWM + depends on !PWM help This driver exports functions to enable/disble/config/free Pulse Width Modulation in the Analog Baseband Chip AB8500. diff --git a/drivers/misc/ab8500-pwm.c b/drivers/misc/ab8500-pwm.c index 042a8fe4efa..d7a9aa14e5d 100644 --- a/drivers/misc/ab8500-pwm.c +++ b/drivers/misc/ab8500-pwm.c @@ -142,16 +142,10 @@ static int __devexit ab8500_pwm_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_pwm_match[] = { - { .compatible = "stericsson,ab8500-pwm", }, - {} -}; - static struct platform_driver ab8500_pwm_driver = { .driver = { .name = "ab8500-pwm", .owner = THIS_MODULE, - .of_match_table = ab8500_pwm_match, }, .probe = ab8500_pwm_probe, .remove = __devexit_p(ab8500_pwm_remove), diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index a6fa884ae49..100b6775e17 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -52,9 +52,10 @@ #define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1) #define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1) +#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa -#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 #define JZ_NAND_MEM_CMD_OFFSET 0x08000 +#define JZ_NAND_MEM_ADDR_OFFSET 0x10000 struct jz_nand { struct mtd_info mtd; @@ -62,8 +63,11 @@ struct jz_nand { void __iomem *base; struct resource *mem; - void __iomem *bank_base; - struct resource *bank_mem; + unsigned char banks[JZ_NAND_NUM_BANKS]; + void __iomem *bank_base[JZ_NAND_NUM_BANKS]; + struct resource *bank_mem[JZ_NAND_NUM_BANKS]; + + int selected_bank; struct jz_nand_platform_data *pdata; bool is_reading; @@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) return container_of(mtd, struct jz_nand, mtd); } +static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr) +{ + struct jz_nand *nand = mtd_to_jz_nand(mtd); + struct nand_chip *chip = mtd->priv; + uint32_t ctrl; + int banknr; + + ctrl = readl(nand->base + JZ_REG_NAND_CTRL); + ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK; + + if (chipnr == -1) { + banknr = -1; + } else { + banknr = nand->banks[chipnr] - 1; + chip->IO_ADDR_R = nand->bank_base[banknr]; + chip->IO_ADDR_W = nand->bank_base[banknr]; + } + writel(ctrl, nand->base + JZ_REG_NAND_CTRL); + + nand->selected_bank = banknr; +} + static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) { struct jz_nand *nand = mtd_to_jz_nand(mtd); struct nand_chip *chip = mtd->priv; uint32_t reg; + void __iomem *bank_base = nand->bank_base[nand->selected_bank]; + + BUG_ON(nand->selected_bank < 0); if (ctrl & NAND_CTRL_CHANGE) { BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); if (ctrl & NAND_ALE) - chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET; + bank_base += JZ_NAND_MEM_ADDR_OFFSET; else if (ctrl & NAND_CLE) - chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET; - else - chip->IO_ADDR_W = nand->bank_base; + bank_base += JZ_NAND_MEM_CMD_OFFSET; + chip->IO_ADDR_W = bank_base; reg = readl(nand->base + JZ_REG_NAND_CTRL); if (ctrl & NAND_NCE) - reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); + reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank); else - reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); + reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank); writel(reg, nand->base + JZ_REG_NAND_CTRL); } if (dat != NAND_CMD_NONE) @@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, } static int jz_nand_ioremap_resource(struct platform_device *pdev, - const char *name, struct resource **res, void __iomem **base) + const char *name, struct resource **res, void *__iomem *base) { int ret; @@ -288,6 +316,90 @@ err: return ret; } +static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base) +{ + iounmap(base); + release_mem_region(res->start, resource_size(res)); +} + +static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) { + int ret; + int gpio; + char gpio_name[9]; + char res_name[6]; + uint32_t ctrl; + struct mtd_info *mtd = &nand->mtd; + struct nand_chip *chip = &nand->chip; + + /* Request GPIO port. */ + gpio = JZ_GPIO_MEM_CS0 + bank - 1; + sprintf(gpio_name, "NAND CS%d", bank); + ret = gpio_request(gpio, gpio_name); + if (ret) { + dev_warn(&pdev->dev, + "Failed to request %s gpio %d: %d\n", + gpio_name, gpio, ret); + goto notfound_gpio; + } + + /* Request I/O resource. */ + sprintf(res_name, "bank%d", bank); + ret = jz_nand_ioremap_resource(pdev, res_name, + &nand->bank_mem[bank - 1], + &nand->bank_base[bank - 1]); + if (ret) + goto notfound_resource; + + /* Enable chip in bank. */ + jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0); + ctrl = readl(nand->base + JZ_REG_NAND_CTRL); + ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1); + writel(ctrl, nand->base + JZ_REG_NAND_CTRL); + + if (chipnr == 0) { + /* Detect first chip. */ + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) + goto notfound_id; + + /* Retrieve the IDs from the first chip. */ + chip->select_chip(mtd, 0); + chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); + *nand_maf_id = chip->read_byte(mtd); + *nand_dev_id = chip->read_byte(mtd); + } else { + /* Detect additional chip. */ + chip->select_chip(mtd, chipnr); + chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); + chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); + if (*nand_maf_id != chip->read_byte(mtd) + || *nand_dev_id != chip->read_byte(mtd)) { + ret = -ENODEV; + goto notfound_id; + } + + /* Update size of the MTD. */ + chip->numchips++; + mtd->size += chip->chipsize; + } + + dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank); + return 0; + +notfound_id: + dev_info(&pdev->dev, "No chip found on bank %i\n", bank); + ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1)); + writel(ctrl, nand->base + JZ_REG_NAND_CTRL); + jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE); + jz_nand_iounmap_resource(nand->bank_mem[bank - 1], + nand->bank_base[bank - 1]); +notfound_resource: + gpio_free(gpio); +notfound_gpio: + return ret; +} + static int __devinit jz_nand_probe(struct platform_device *pdev) { int ret; @@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) struct nand_chip *chip; struct mtd_info *mtd; struct jz_nand_platform_data *pdata = pdev->dev.platform_data; + size_t chipnr, bank_idx; + uint8_t nand_maf_id = 0, nand_dev_id = 0; nand = kzalloc(sizeof(*nand), GFP_KERNEL); if (!nand) { @@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); if (ret) goto err_free; - ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem, - &nand->bank_base); - if (ret) - goto err_iounmap_mmio; if (pdata && gpio_is_valid(pdata->busy_gpio)) { ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); @@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to request busy gpio %d: %d\n", pdata->busy_gpio, ret); - goto err_iounmap_mem; + goto err_iounmap_mmio; } } @@ -339,22 +449,51 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) chip->chip_delay = 50; chip->cmd_ctrl = jz_nand_cmd_ctrl; + chip->select_chip = jz_nand_select_chip; if (pdata && gpio_is_valid(pdata->busy_gpio)) chip->dev_ready = jz_nand_dev_ready; - chip->IO_ADDR_R = nand->bank_base; - chip->IO_ADDR_W = nand->bank_base; - nand->pdata = pdata; platform_set_drvdata(pdev, nand); - writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL); - - ret = nand_scan_ident(mtd, 1, NULL); - if (ret) { - dev_err(&pdev->dev, "Failed to scan nand\n"); - goto err_gpio_free; + /* We are going to autodetect NAND chips in the banks specified in the + * platform data. Although nand_scan_ident() can detect multiple chips, + * it requires those chips to be numbered consecuitively, which is not + * always the case for external memory banks. And a fixed chip-to-bank + * mapping is not practical either, since for example Dingoo units + * produced at different times have NAND chips in different banks. + */ + chipnr = 0; + for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) { + unsigned char bank; + + /* If there is no platform data, look for NAND in bank 1, + * which is the most likely bank since it is the only one + * that can be booted from. + */ + bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1; + if (bank == 0) + break; + if (bank > JZ_NAND_NUM_BANKS) { + dev_warn(&pdev->dev, + "Skipping non-existing bank: %d\n", bank); + continue; + } + /* The detection routine will directly or indirectly call + * jz_nand_select_chip(), so nand->banks has to contain the + * bank we're checking. + */ + nand->banks[chipnr] = bank; + if (jz_nand_detect_bank(pdev, nand, bank, chipnr, + &nand_maf_id, &nand_dev_id) == 0) + chipnr++; + else + nand->banks[chipnr] = 0; + } + if (chipnr == 0) { + dev_err(&pdev->dev, "No NAND chips found\n"); + goto err_gpio_busy; } if (pdata && pdata->ident_callback) { @@ -364,8 +503,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ret = nand_scan_tail(mtd); if (ret) { - dev_err(&pdev->dev, "Failed to scan nand\n"); - goto err_gpio_free; + dev_err(&pdev->dev, "Failed to scan NAND\n"); + goto err_unclaim_banks; } ret = mtd_device_parse_register(mtd, NULL, NULL, @@ -382,14 +521,21 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) return 0; err_nand_release: - nand_release(&nand->mtd); -err_gpio_free: + nand_release(mtd); +err_unclaim_banks: + while (chipnr--) { + unsigned char bank = nand->banks[chipnr]; + gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); + jz_nand_iounmap_resource(nand->bank_mem[bank - 1], + nand->bank_base[bank - 1]); + } + writel(0, nand->base + JZ_REG_NAND_CTRL); +err_gpio_busy: + if (pdata && gpio_is_valid(pdata->busy_gpio)) + gpio_free(pdata->busy_gpio); platform_set_drvdata(pdev, NULL); - gpio_free(pdata->busy_gpio); -err_iounmap_mem: - iounmap(nand->bank_base); err_iounmap_mmio: - iounmap(nand->base); + jz_nand_iounmap_resource(nand->mem, nand->base); err_free: kfree(nand); return ret; @@ -398,16 +544,26 @@ err_free: static int __devexit jz_nand_remove(struct platform_device *pdev) { struct jz_nand *nand = platform_get_drvdata(pdev); + struct jz_nand_platform_data *pdata = pdev->dev.platform_data; + size_t i; nand_release(&nand->mtd); /* Deassert and disable all chips */ writel(0, nand->base + JZ_REG_NAND_CTRL); - iounmap(nand->bank_base); - release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem)); - iounmap(nand->base); - release_mem_region(nand->mem->start, resource_size(nand->mem)); + for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) { + unsigned char bank = nand->banks[i]; + if (bank != 0) { + jz_nand_iounmap_resource(nand->bank_mem[bank - 1], + nand->bank_base[bank - 1]); + gpio_free(JZ_GPIO_MEM_CS0 + bank - 1); + } + } + if (pdata && gpio_is_valid(pdata->busy_gpio)) + gpio_free(pdata->busy_gpio); + + jz_nand_iounmap_resource(nand->mem, nand->base); platform_set_drvdata(pdev, NULL); kfree(nand); diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c index cd827ff4a02..c42bbb16cda 100644 --- a/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -6,19 +6,21 @@ * Copyright (C) 2009 Cavium Networks */ -#include <linux/capability.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/module.h> +#include <linux/etherdevice.h> +#include <linux/capability.h> #include <linux/interrupt.h> -#include <linux/platform_device.h> #include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/if.h> +#include <linux/spinlock.h> #include <linux/if_vlan.h> +#include <linux/of_mdio.h> +#include <linux/module.h> +#include <linux/of_net.h> +#include <linux/init.h> #include <linux/slab.h> #include <linux/phy.h> -#include <linux/spinlock.h> +#include <linux/io.h> #include <asm/octeon/octeon.h> #include <asm/octeon/cvmx-mixx-defs.h> @@ -58,8 +60,56 @@ union mgmt_port_ring_entry { } s; }; +#define MIX_ORING1 0x0 +#define MIX_ORING2 0x8 +#define MIX_IRING1 0x10 +#define MIX_IRING2 0x18 +#define MIX_CTL 0x20 +#define MIX_IRHWM 0x28 +#define MIX_IRCNT 0x30 +#define MIX_ORHWM 0x38 +#define MIX_ORCNT 0x40 +#define MIX_ISR 0x48 +#define MIX_INTENA 0x50 +#define MIX_REMCNT 0x58 +#define MIX_BIST 0x78 + +#define AGL_GMX_PRT_CFG 0x10 +#define AGL_GMX_RX_FRM_CTL 0x18 +#define AGL_GMX_RX_FRM_MAX 0x30 +#define AGL_GMX_RX_JABBER 0x38 +#define AGL_GMX_RX_STATS_CTL 0x50 + +#define AGL_GMX_RX_STATS_PKTS_DRP 0xb0 +#define AGL_GMX_RX_STATS_OCTS_DRP 0xb8 +#define AGL_GMX_RX_STATS_PKTS_BAD 0xc0 + +#define AGL_GMX_RX_ADR_CTL 0x100 +#define AGL_GMX_RX_ADR_CAM_EN 0x108 +#define AGL_GMX_RX_ADR_CAM0 0x180 +#define AGL_GMX_RX_ADR_CAM1 0x188 +#define AGL_GMX_RX_ADR_CAM2 0x190 +#define AGL_GMX_RX_ADR_CAM3 0x198 +#define AGL_GMX_RX_ADR_CAM4 0x1a0 +#define AGL_GMX_RX_ADR_CAM5 0x1a8 + +#define AGL_GMX_TX_STATS_CTL 0x268 +#define AGL_GMX_TX_CTL 0x270 +#define AGL_GMX_TX_STAT0 0x280 +#define AGL_GMX_TX_STAT1 0x288 +#define AGL_GMX_TX_STAT2 0x290 +#define AGL_GMX_TX_STAT3 0x298 +#define AGL_GMX_TX_STAT4 0x2a0 +#define AGL_GMX_TX_STAT5 0x2a8 +#define AGL_GMX_TX_STAT6 0x2b0 +#define AGL_GMX_TX_STAT7 0x2b8 +#define AGL_GMX_TX_STAT8 0x2c0 +#define AGL_GMX_TX_STAT9 0x2c8 + struct octeon_mgmt { struct net_device *netdev; + u64 mix; + u64 agl; int port; int irq; u64 *tx_ring; @@ -85,31 +135,34 @@ struct octeon_mgmt { struct napi_struct napi; struct tasklet_struct tx_clean_tasklet; struct phy_device *phydev; + struct device_node *phy_np; + resource_size_t mix_phys; + resource_size_t mix_size; + resource_size_t agl_phys; + resource_size_t agl_size; }; static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable) { - int port = p->port; union cvmx_mixx_intena mix_intena; unsigned long flags; spin_lock_irqsave(&p->lock, flags); - mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port)); + mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA); mix_intena.s.ithena = enable ? 1 : 0; - cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); + cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64); spin_unlock_irqrestore(&p->lock, flags); } static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable) { - int port = p->port; union cvmx_mixx_intena mix_intena; unsigned long flags; spin_lock_irqsave(&p->lock, flags); - mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port)); + mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA); mix_intena.s.othena = enable ? 1 : 0; - cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); + cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64); spin_unlock_irqrestore(&p->lock, flags); } @@ -146,7 +199,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size) static void octeon_mgmt_rx_fill_ring(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) { unsigned int size; @@ -177,24 +229,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev) (p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE; p->rx_current_fill++; /* Ring the bell. */ - cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); + cvmx_write_csr(p->mix + MIX_IRING2, 1); } } static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) { - int port = p->port; union cvmx_mixx_orcnt mix_orcnt; union mgmt_port_ring_entry re; struct sk_buff *skb; int cleaned = 0; unsigned long flags; - mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); + mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT); while (mix_orcnt.s.orcnt) { spin_lock_irqsave(&p->tx_list.lock, flags); - mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); + mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT); if (mix_orcnt.s.orcnt == 0) { spin_unlock_irqrestore(&p->tx_list.lock, flags); @@ -214,7 +265,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) mix_orcnt.s.orcnt = 1; /* Acknowledge to hardware that we have the buffer. */ - cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64); + cvmx_write_csr(p->mix + MIX_ORCNT, mix_orcnt.u64); p->tx_current_fill--; spin_unlock_irqrestore(&p->tx_list.lock, flags); @@ -224,7 +275,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) dev_kfree_skb_any(skb); cleaned++; - mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); + mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT); } if (cleaned && netif_queue_stopped(p->netdev)) @@ -241,13 +292,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg) static void octeon_mgmt_update_rx_stats(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; unsigned long flags; u64 drop, bad; /* These reads also clear the count registers. */ - drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port)); - bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port)); + drop = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP); + bad = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD); if (drop || bad) { /* Do an atomic update. */ @@ -261,15 +311,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev) static void octeon_mgmt_update_tx_stats(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; unsigned long flags; union cvmx_agl_gmx_txx_stat0 s0; union cvmx_agl_gmx_txx_stat1 s1; /* These reads also clear the count registers. */ - s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port)); - s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port)); + s0.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT0); + s1.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT1); if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) { /* Do an atomic update. */ @@ -308,7 +357,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p, static int octeon_mgmt_receive_one(struct octeon_mgmt *p) { - int port = p->port; struct net_device *netdev = p->netdev; union cvmx_mixx_ircnt mix_ircnt; union mgmt_port_ring_entry re; @@ -381,18 +429,17 @@ done: /* Tell the hardware we processed a packet. */ mix_ircnt.u64 = 0; mix_ircnt.s.ircnt = 1; - cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64); + cvmx_write_csr(p->mix + MIX_IRCNT, mix_ircnt.u64); return rc; } static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget) { - int port = p->port; unsigned int work_done = 0; union cvmx_mixx_ircnt mix_ircnt; int rc; - mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); + mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT); while (work_done < budget && mix_ircnt.s.ircnt) { rc = octeon_mgmt_receive_one(p); @@ -400,7 +447,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget) work_done++; /* Check for more packets. */ - mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); + mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT); } octeon_mgmt_rx_fill_ring(p->netdev); @@ -434,16 +481,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p) union cvmx_agl_gmx_bist agl_gmx_bist; mix_ctl.u64 = 0; - cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64); + cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64); do { - mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port)); + mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL); } while (mix_ctl.s.busy); mix_ctl.s.reset = 1; - cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64); - cvmx_read_csr(CVMX_MIXX_CTL(p->port)); + cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64); + cvmx_read_csr(p->mix + MIX_CTL); cvmx_wait(64); - mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port)); + mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST); if (mix_bist.u64) dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n", (unsigned long long)mix_bist.u64); @@ -474,7 +521,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs, static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; union cvmx_agl_gmx_rxx_adr_ctl adr_ctl; union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; unsigned long flags; @@ -520,29 +566,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) spin_lock_irqsave(&p->lock, flags); /* Disable packet I/O. */ - agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); + agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG); prev_packet_enable = agl_gmx_prtx.s.en; agl_gmx_prtx.s.en = 0; - cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); + cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64); adr_ctl.u64 = 0; adr_ctl.s.cam_mode = cam_mode; adr_ctl.s.mcst = multicast_mode; adr_ctl.s.bcst = 1; /* Allow broadcast */ - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]); - cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]); + cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask); /* Restore packet I/O. */ agl_gmx_prtx.s.en = prev_packet_enable; - cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); + cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64); spin_unlock_irqrestore(&p->lock, flags); } @@ -564,7 +610,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr) static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM; /* @@ -580,8 +625,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; - cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs); - cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port), + cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs); + cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER, (size_without_fcs + 7) & 0xfff8); return 0; @@ -591,14 +636,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id) { struct net_device *netdev = dev_id; struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; union cvmx_mixx_isr mixx_isr; - mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port)); + mixx_isr.u64 = cvmx_read_csr(p->mix + MIX_ISR); /* Clear any pending interrupts */ - cvmx_write_csr(CVMX_MIXX_ISR(port), mixx_isr.u64); - cvmx_read_csr(CVMX_MIXX_ISR(port)); + cvmx_write_csr(p->mix + MIX_ISR, mixx_isr.u64); + cvmx_read_csr(p->mix + MIX_ISR); if (mixx_isr.s.irthresh) { octeon_mgmt_disable_rx_irq(p); @@ -629,7 +673,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev, static void octeon_mgmt_adjust_link(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; union cvmx_agl_gmx_prtx_cfg prtx_cfg; unsigned long flags; int link_changed = 0; @@ -640,11 +683,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev) link_changed = 1; if (p->last_duplex != p->phydev->duplex) { p->last_duplex = p->phydev->duplex; - prtx_cfg.u64 = - cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); + prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG); prtx_cfg.s.duplex = p->phydev->duplex; - cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), - prtx_cfg.u64); + cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64); } } else { if (p->last_link) @@ -670,18 +711,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev) static int octeon_mgmt_init_phy(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - char phy_id[MII_BUS_ID_SIZE + 3]; - if (octeon_is_simulation()) { + if (octeon_is_simulation() || p->phy_np == NULL) { /* No PHYs in the simulator. */ netif_carrier_on(netdev); return 0; } - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port); - - p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + p->phydev = of_phy_connect(netdev, p->phy_np, + octeon_mgmt_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(p->phydev)) { p->phydev = NULL; @@ -737,14 +776,14 @@ static int octeon_mgmt_open(struct net_device *netdev) octeon_mgmt_reset_hw(p); - mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); + mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL); /* Bring it out of reset if needed. */ if (mix_ctl.s.reset) { mix_ctl.s.reset = 0; - cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); + cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64); do { - mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); + mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL); } while (mix_ctl.s.reset); } @@ -755,17 +794,17 @@ static int octeon_mgmt_open(struct net_device *netdev) oring1.u64 = 0; oring1.s.obase = p->tx_ring_handle >> 3; oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE; - cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64); + cvmx_write_csr(p->mix + MIX_ORING1, oring1.u64); iring1.u64 = 0; iring1.s.ibase = p->rx_ring_handle >> 3; iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE; - cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64); + cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64); /* Disable packet I/O. */ - prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); + prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG); prtx_cfg.s.en = 0; - cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64); + cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64); memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN); octeon_mgmt_set_mac_address(netdev, &sa); @@ -782,7 +821,7 @@ static int octeon_mgmt_open(struct net_device *netdev) mix_ctl.s.nbtarb = 0; /* Arbitration mode */ /* MII CB-request FIFO programmable high watermark */ mix_ctl.s.mrq_hwm = 1; - cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); + cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64); if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { @@ -809,16 +848,16 @@ static int octeon_mgmt_open(struct net_device *netdev) /* Clear statistics. */ /* Clear on read. */ - cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1); - cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0); - cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0); + cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_CTL, 1); + cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP, 0); + cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD, 0); - cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1); - cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0); - cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0); + cvmx_write_csr(p->agl + AGL_GMX_TX_STATS_CTL, 1); + cvmx_write_csr(p->agl + AGL_GMX_TX_STAT0, 0); + cvmx_write_csr(p->agl + AGL_GMX_TX_STAT1, 0); /* Clear any pending interrupts */ - cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port))); + cvmx_write_csr(p->mix + MIX_ISR, cvmx_read_csr(p->mix + MIX_ISR)); if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name, netdev)) { @@ -829,18 +868,18 @@ static int octeon_mgmt_open(struct net_device *netdev) /* Interrupt every single RX packet */ mix_irhwm.u64 = 0; mix_irhwm.s.irhwm = 0; - cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64); + cvmx_write_csr(p->mix + MIX_IRHWM, mix_irhwm.u64); /* Interrupt when we have 1 or more packets to clean. */ mix_orhwm.u64 = 0; mix_orhwm.s.orhwm = 1; - cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64); + cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64); /* Enable receive and transmit interrupts */ mix_intena.u64 = 0; mix_intena.s.ithena = 1; mix_intena.s.othena = 1; - cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); + cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64); /* Enable packet I/O. */ @@ -871,7 +910,7 @@ static int octeon_mgmt_open(struct net_device *netdev) * frame. GMX checks that the PREAMBLE is sent correctly. */ rxx_frm_ctl.s.pre_chk = 1; - cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64); + cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64); /* Enable the AGL block */ agl_gmx_inf_mode.u64 = 0; @@ -879,13 +918,13 @@ static int octeon_mgmt_open(struct net_device *netdev) cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64); /* Configure the port duplex and enables */ - prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); + prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG); prtx_cfg.s.tx_en = 1; prtx_cfg.s.rx_en = 1; prtx_cfg.s.en = 1; p->last_duplex = 1; prtx_cfg.s.duplex = p->last_duplex; - cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64); + cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64); p->last_link = 0; netif_carrier_off(netdev); @@ -949,7 +988,6 @@ static int octeon_mgmt_stop(struct net_device *netdev) static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); - int port = p->port; union mgmt_port_ring_entry re; unsigned long flags; int rv = NETDEV_TX_BUSY; @@ -993,7 +1031,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) netdev->stats.tx_bytes += skb->len; /* Ring the bell. */ - cvmx_write_csr(CVMX_MIXX_ORING2(port), 1); + cvmx_write_csr(p->mix + MIX_ORING2, 1); rv = NETDEV_TX_OK; out: @@ -1071,10 +1109,14 @@ static const struct net_device_ops octeon_mgmt_ops = { static int __devinit octeon_mgmt_probe(struct platform_device *pdev) { - struct resource *res_irq; struct net_device *netdev; struct octeon_mgmt *p; - int i; + const __be32 *data; + const u8 *mac; + struct resource *res_mix; + struct resource *res_agl; + int len; + int result; netdev = alloc_etherdev(sizeof(struct octeon_mgmt)); if (netdev == NULL) @@ -1088,14 +1130,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev) p->netdev = netdev; p->dev = &pdev->dev; - p->port = pdev->id; + data = of_get_property(pdev->dev.of_node, "cell-index", &len); + if (data && len == sizeof(*data)) { + p->port = be32_to_cpup(data); + } else { + dev_err(&pdev->dev, "no 'cell-index' property\n"); + result = -ENXIO; + goto err; + } + snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port); - res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res_irq) + result = platform_get_irq(pdev, 0); + if (result < 0) + goto err; + + p->irq = result; + + res_mix = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res_mix == NULL) { + dev_err(&pdev->dev, "no 'reg' resource\n"); + result = -ENXIO; + goto err; + } + + res_agl = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res_agl == NULL) { + dev_err(&pdev->dev, "no 'reg' resource\n"); + result = -ENXIO; + goto err; + } + + p->mix_phys = res_mix->start; + p->mix_size = resource_size(res_mix); + p->agl_phys = res_agl->start; + p->agl_size = resource_size(res_agl); + + + if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size, + res_mix->name)) { + dev_err(&pdev->dev, "request_mem_region (%s) failed\n", + res_mix->name); + result = -ENXIO; + goto err; + } + + if (!devm_request_mem_region(&pdev->dev, p->agl_phys, p->agl_size, + res_agl->name)) { + result = -ENXIO; + dev_err(&pdev->dev, "request_mem_region (%s) failed\n", + res_agl->name); goto err; + } + + + p->mix = (u64)devm_ioremap(&pdev->dev, p->mix_phys, p->mix_size); + p->agl = (u64)devm_ioremap(&pdev->dev, p->agl_phys, p->agl_size); - p->irq = res_irq->start; spin_lock_init(&p->lock); skb_queue_head_init(&p->tx_list); @@ -1108,24 +1199,26 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev) netdev->netdev_ops = &octeon_mgmt_ops; netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; - /* The mgmt ports get the first N MACs. */ - for (i = 0; i < 6; i++) - netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i]; - netdev->dev_addr[5] += p->port; + mac = of_get_mac_address(pdev->dev.of_node); + + if (mac) + memcpy(netdev->dev_addr, mac, 6); - if (p->port >= octeon_bootinfo->mac_addr_count) - dev_err(&pdev->dev, - "Error %s: Using MAC outside of the assigned range: %pM\n", - netdev->name, netdev->dev_addr); + p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); - if (register_netdev(netdev)) + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64); + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + + result = register_netdev(netdev); + if (result) goto err; dev_info(&pdev->dev, "Version " DRV_VERSION "\n"); return 0; + err: free_netdev(netdev); - return -ENOENT; + return result; } static int __devexit octeon_mgmt_remove(struct platform_device *pdev) @@ -1137,10 +1230,19 @@ static int __devexit octeon_mgmt_remove(struct platform_device *pdev) return 0; } +static struct of_device_id octeon_mgmt_match[] = { + { + .compatible = "cavium,octeon-5750-mix", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, octeon_mgmt_match); + static struct platform_driver octeon_mgmt_driver = { .driver = { .name = "octeon_mgmt", .owner = THIS_MODULE, + .of_match_table = octeon_mgmt_match, }, .probe = octeon_mgmt_probe, .remove = __devexit_p(octeon_mgmt_remove), diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index 826d961f39f..d4015aa663e 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -3,14 +3,17 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2009 Cavium Networks + * Copyright (C) 2009,2011 Cavium, Inc. */ -#include <linux/gfp.h> -#include <linux/init.h> -#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/of_mdio.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/gfp.h> #include <linux/phy.h> +#include <linux/io.h> #include <asm/octeon/octeon.h> #include <asm/octeon/cvmx-smix-defs.h> @@ -18,9 +21,17 @@ #define DRV_VERSION "1.0" #define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver" +#define SMI_CMD 0x0 +#define SMI_WR_DAT 0x8 +#define SMI_RD_DAT 0x10 +#define SMI_CLK 0x18 +#define SMI_EN 0x20 + struct octeon_mdiobus { struct mii_bus *mii_bus; - int unit; + u64 register_base; + resource_size_t mdio_phys; + resource_size_t regsize; int phy_irq[PHY_MAX_ADDR]; }; @@ -35,15 +46,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */ smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; - cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); + cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); do { /* * Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ - cvmx_wait(1000); - smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit)); + __delay(1000); + smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT); } while (smi_rd.s.pending && --timeout); if (smi_rd.s.val) @@ -62,21 +73,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, smi_wr.u64 = 0; smi_wr.s.dat = val; - cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64); + cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64); smi_cmd.u64 = 0; smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */ smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; - cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); + cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); do { /* * Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ - cvmx_wait(1000); - smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit)); + __delay(1000); + smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT); } while (smi_wr.s.pending && --timeout); if (timeout <= 0) @@ -88,38 +99,44 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) { struct octeon_mdiobus *bus; + struct resource *res_mem; union cvmx_smix_en smi_en; - int i; int err = -ENOENT; bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL); if (!bus) return -ENOMEM; - /* The platform_device id is our unit number. */ - bus->unit = pdev->id; + res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (res_mem == NULL) { + dev_err(&pdev->dev, "found no memory resource\n"); + err = -ENXIO; + goto fail; + } + bus->mdio_phys = res_mem->start; + bus->regsize = resource_size(res_mem); + if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize, + res_mem->name)) { + dev_err(&pdev->dev, "request_mem_region failed\n"); + goto fail; + } + bus->register_base = + (u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize); bus->mii_bus = mdiobus_alloc(); if (!bus->mii_bus) - goto err; + goto fail; smi_en.u64 = 0; smi_en.s.en = 1; - cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); - - /* - * Standard Octeon evaluation boards don't support phy - * interrupts, we need to poll. - */ - for (i = 0; i < PHY_MAX_ADDR; i++) - bus->phy_irq[i] = PHY_POLL; + cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); bus->mii_bus->priv = bus; bus->mii_bus->irq = bus->phy_irq; bus->mii_bus->name = "mdio-octeon"; - snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", - bus->mii_bus->name, bus->unit); + snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base); bus->mii_bus->parent = &pdev->dev; bus->mii_bus->read = octeon_mdiobus_read; @@ -127,20 +144,18 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, bus); - err = mdiobus_register(bus->mii_bus); + err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node); if (err) - goto err_register; + goto fail_register; dev_info(&pdev->dev, "Version " DRV_VERSION "\n"); return 0; -err_register: +fail_register: mdiobus_free(bus->mii_bus); - -err: - devm_kfree(&pdev->dev, bus); +fail: smi_en.u64 = 0; - cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); + cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); return err; } @@ -154,14 +169,23 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev) mdiobus_unregister(bus->mii_bus); mdiobus_free(bus->mii_bus); smi_en.u64 = 0; - cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); + cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); return 0; } +static struct of_device_id octeon_mdiobus_match[] = { + { + .compatible = "cavium,octeon-3860-mdio", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, octeon_mdiobus_match); + static struct platform_driver octeon_mdiobus_driver = { .driver = { .name = "mdio-octeon", .owner = THIS_MODULE, + .of_match_table = octeon_mdiobus_match, }, .probe = octeon_mdiobus_probe, .remove = __devexit_p(octeon_mdiobus_remove), diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index c8f40c9c042..3782e1cd369 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -95,6 +95,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026"); enum acer_wmi_event_ids { WMID_HOTKEY_EVENT = 0x1, + WMID_ACCEL_EVENT = 0x5, }; static const struct key_entry acer_wmi_keymap[] = { @@ -130,6 +131,7 @@ static const struct key_entry acer_wmi_keymap[] = { }; static struct input_dev *acer_wmi_input_dev; +static struct input_dev *acer_wmi_accel_dev; struct event_return_value { u8 function; @@ -200,6 +202,7 @@ struct hotkey_function_type_aa { #define ACER_CAP_BLUETOOTH (1<<2) #define ACER_CAP_BRIGHTNESS (1<<3) #define ACER_CAP_THREEG (1<<4) +#define ACER_CAP_ACCEL (1<<5) #define ACER_CAP_ANY (0xFFFFFFFF) /* @@ -1399,6 +1402,60 @@ static void acer_backlight_exit(void) } /* + * Accelerometer device + */ +static acpi_handle gsensor_handle; + +static int acer_gsensor_init(void) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object out_obj; + + output.length = sizeof(out_obj); + output.pointer = &out_obj; + status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output); + if (ACPI_FAILURE(status)) + return -1; + + return 0; +} + +static int acer_gsensor_open(struct input_dev *input) +{ + return acer_gsensor_init(); +} + +static int acer_gsensor_event(void) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object out_obj[5]; + + if (!has_cap(ACER_CAP_ACCEL)) + return -1; + + output.length = sizeof(out_obj); + output.pointer = out_obj; + + status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output); + if (ACPI_FAILURE(status)) + return -1; + + if (out_obj->package.count != 4) + return -1; + + input_report_abs(acer_wmi_accel_dev, ABS_X, + (s16)out_obj->package.elements[0].integer.value); + input_report_abs(acer_wmi_accel_dev, ABS_Y, + (s16)out_obj->package.elements[1].integer.value); + input_report_abs(acer_wmi_accel_dev, ABS_Z, + (s16)out_obj->package.elements[2].integer.value); + input_sync(acer_wmi_accel_dev); + return 0; +} + +/* * Rfkill devices */ static void acer_rfkill_update(struct work_struct *ignored); @@ -1673,6 +1730,9 @@ static void acer_wmi_notify(u32 value, void *context) 1, true); } break; + case WMID_ACCEL_EVENT: + acer_gsensor_event(); + break; default: pr_warn("Unknown function number - %d - %d\n", return_value.function, return_value.key_num); @@ -1758,6 +1818,73 @@ static int acer_wmi_enable_lm(void) return status; } +static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, + void *ctx, void **retval) +{ + *(acpi_handle *)retval = ah; + return AE_OK; +} + +static int __init acer_wmi_get_handle(const char *name, const char *prop, + acpi_handle *ah) +{ + acpi_status status; + acpi_handle handle; + + BUG_ON(!name || !ah); + + handle = NULL; + status = acpi_get_devices(prop, acer_wmi_get_handle_cb, + (void *)name, &handle); + + if (ACPI_SUCCESS(status)) { + *ah = handle; + return 0; + } else { + return -ENODEV; + } +} + +static int __init acer_wmi_accel_setup(void) +{ + int err; + + err = acer_wmi_get_handle("SENR", "BST0001", &gsensor_handle); + if (err) + return err; + + interface->capability |= ACER_CAP_ACCEL; + + acer_wmi_accel_dev = input_allocate_device(); + if (!acer_wmi_accel_dev) + return -ENOMEM; + + acer_wmi_accel_dev->open = acer_gsensor_open; + + acer_wmi_accel_dev->name = "Acer BMA150 accelerometer"; + acer_wmi_accel_dev->phys = "wmi/input1"; + acer_wmi_accel_dev->id.bustype = BUS_HOST; + acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS); + input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0); + input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0); + input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0); + + err = input_register_device(acer_wmi_accel_dev); + if (err) + goto err_free_dev; + + return 0; + +err_free_dev: + input_free_device(acer_wmi_accel_dev); + return err; +} + +static void acer_wmi_accel_destroy(void) +{ + input_unregister_device(acer_wmi_accel_dev); +} + static int __init acer_wmi_input_setup(void) { acpi_status status; @@ -1912,6 +2039,9 @@ static int acer_resume(struct device *dev) if (has_cap(ACER_CAP_BRIGHTNESS)) set_u32(data->brightness, ACER_CAP_BRIGHTNESS); + if (has_cap(ACER_CAP_ACCEL)) + acer_gsensor_init(); + return 0; } @@ -2060,14 +2190,16 @@ static int __init acer_wmi_init(void) set_quirks(); + if (dmi_check_system(video_vendor_dmi_table)) + acpi_video_dmi_promote_vendor(); if (acpi_video_backlight_support()) { - if (dmi_check_system(video_vendor_dmi_table)) { - acpi_video_unregister(); - } else { - interface->capability &= ~ACER_CAP_BRIGHTNESS; - pr_info("Brightness must be controlled by " - "acpi video driver\n"); - } + interface->capability &= ~ACER_CAP_BRIGHTNESS; + pr_info("Brightness must be controlled by acpi video driver\n"); + } else { +#ifdef CONFIG_ACPI_VIDEO + pr_info("Disabling ACPI video driver\n"); + acpi_video_unregister(); +#endif } if (wmi_has_guid(WMID_GUID3)) { @@ -2090,6 +2222,8 @@ static int __init acer_wmi_init(void) return err; } + acer_wmi_accel_setup(); + err = platform_driver_register(&acer_platform_driver); if (err) { pr_err("Unable to register platform driver\n"); @@ -2133,6 +2267,8 @@ error_device_alloc: error_platform_register: if (wmi_has_guid(ACERWMID_EVENT_GUID)) acer_wmi_input_destroy(); + if (has_cap(ACER_CAP_ACCEL)) + acer_wmi_accel_destroy(); return err; } @@ -2142,6 +2278,9 @@ static void __exit acer_wmi_exit(void) if (wmi_has_guid(ACERWMID_EVENT_GUID)) acer_wmi_input_destroy(); + if (has_cap(ACER_CAP_ACCEL)) + acer_wmi_accel_destroy(); + remove_sysfs(acer_platform_device); remove_debugfs(); platform_device_unregister(acer_platform_device); diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 694a15a5623..905fa01ac8d 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -193,7 +193,10 @@ static int __devinit gmux_probe(struct pnp_dev *pnp, * backlight control and supports more levels than other options. * Disable the other backlight choices. */ + acpi_video_dmi_promote_vendor(); +#ifdef CONFIG_ACPI_VIDEO acpi_video_unregister(); +#endif apple_bl_unregister(); return 0; @@ -213,7 +216,10 @@ static void __devexit gmux_remove(struct pnp_dev *pnp) release_region(gmux_data->iostart, gmux_data->iolen); kfree(gmux_data); + acpi_video_dmi_demote_vendor(); +#ifdef CONFIG_ACPI_VIDEO acpi_video_register(); +#endif apple_bl_register(); } diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 99a30b51313..6b0ebdeae91 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -26,6 +26,7 @@ #include <linux/input.h> #include <linux/input/sparse-keymap.h> #include <linux/fb.h> +#include <linux/dmi.h> #include "asus-wmi.h" @@ -48,18 +49,115 @@ MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); * 1 | Hardware | Software * 4 | Software | Software */ -static uint wapf; +static int wapf = -1; module_param(wapf, uint, 0444); MODULE_PARM_DESC(wapf, "WAPF value"); +static struct quirk_entry *quirks; + static struct quirk_entry quirk_asus_unknown = { + .wapf = 0, +}; + +static struct quirk_entry quirk_asus_x401u = { + .wapf = 4, +}; + +static int dmi_matched(const struct dmi_system_id *dmi) +{ + quirks = dmi->driver_data; + return 1; +} + +static struct dmi_system_id asus_quirks[] = { + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X401U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X401U"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X401A1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X501U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X501U"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X501A1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X55A", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X55C", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X55U", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X55U"), + }, + .driver_data = &quirk_asus_x401u, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK COMPUTER INC. X55VD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), + }, + .driver_data = &quirk_asus_x401u, + }, + {}, }; static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) { - driver->quirks = &quirk_asus_unknown; - driver->quirks->wapf = wapf; + quirks = &quirk_asus_unknown; + dmi_check_system(asus_quirks); + + driver->quirks = quirks; driver->panel_power = FB_BLANK_UNBLANK; + + /* overwrite the wapf setting if the wapf paramater is specified */ + if (wapf != -1) + quirks->wapf = wapf; + else + wapf = quirks->wapf; } static const struct key_entry asus_nb_wmi_keymap[] = { @@ -94,6 +192,10 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x8A, { KEY_PROG1 } }, { KE_KEY, 0x95, { KEY_MEDIA } }, { KE_KEY, 0x99, { KEY_PHONE } }, + { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ + { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ + { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ + { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ { KE_KEY, 0xb5, { KEY_CALC } }, { KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 77aadde5281..c7a36f6b058 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -47,6 +47,9 @@ #include <linux/thermal.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> +#ifdef CONFIG_ACPI_VIDEO +#include <acpi/video.h> +#endif #include "asus-wmi.h" @@ -136,6 +139,9 @@ MODULE_LICENSE("GPL"); /* Power */ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 +/* Deep S3 / Resume on LID open */ +#define ASUS_WMI_DEVID_LID_RESUME 0x00120031 + /* DSTS masks */ #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 @@ -1365,6 +1371,7 @@ static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf) ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD); ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA); ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER); +ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME); static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1390,6 +1397,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_touchpad.attr, + &dev_attr_lid_resume.attr, NULL }; @@ -1408,6 +1416,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, devid = ASUS_WMI_DEVID_CARDREADER; else if (attr == &dev_attr_touchpad.attr) devid = ASUS_WMI_DEVID_TOUCHPAD; + else if (attr == &dev_attr_lid_resume.attr) + devid = ASUS_WMI_DEVID_LID_RESUME; if (devid != -1) ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); @@ -1467,14 +1477,9 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) asus->dsts_id = ASUS_WMI_METHODID_DSTS; - else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) + else asus->dsts_id = ASUS_WMI_METHODID_DSTS2; - if (!asus->dsts_id) { - pr_err("Can't find DSTS"); - return -ENODEV; - } - /* CWAP allow to define the behavior of the Fn+F2 key, * this method doesn't seems to be present on Eee PCs */ if (asus->driver->quirks->wapf >= 0) @@ -1681,7 +1686,13 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_rfkill; + if (asus->driver->quirks->wmi_backlight_power) + acpi_video_dmi_promote_vendor(); if (!acpi_video_backlight_support()) { +#ifdef CONFIG_ACPI_VIDEO + pr_info("Disabling ACPI video driver\n"); + acpi_video_unregister(); +#endif err = asus_wmi_backlight_init(asus); if (err && err != -ENODEV) goto fail_backlight; diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index d43b6674200..9c1da8b81be 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -39,6 +39,7 @@ struct quirk_entry { bool hotplug_wireless; bool scalar_panel_brightness; bool store_backlight_power; + bool wmi_backlight_power; int wapf; }; diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index e2230a2b2f8..2ca7dd1ab3e 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -31,15 +31,21 @@ MODULE_LICENSE("GPL"); struct cmpc_accel { int sensitivity; + int g_select; + int inputdev_state; }; -#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_DEV_STATE_CLOSED 0 +#define CMPC_ACCEL_DEV_STATE_OPEN 1 +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 +#define CMPC_ACCEL_G_SELECT_DEFAULT 0 #define CMPC_ACCEL_HID "ACCE0000" +#define CMPC_ACCEL_HID_V4 "ACCE0001" #define CMPC_TABLET_HID "TBLT0000" #define CMPC_IPML_HID "IPML200" -#define CMPC_KEYS_HID "FnBT0000" +#define CMPC_KEYS_HID "FNBT0000" /* * Generic input device code. @@ -76,7 +82,391 @@ static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) } /* - * Accelerometer code. + * Accelerometer code for Classmate V4 + */ +static acpi_status cmpc_start_accel_v4(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x3; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_stop_accel_v4(acpi_handle handle) +{ + union acpi_object param[4]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x4; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_accel_set_sensitivity_v4(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x02; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_accel_set_g_select_v4(acpi_handle handle, int val) +{ + union acpi_object param[4]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x05; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_get_accel_v4(acpi_handle handle, + int16_t *x, + int16_t *y, + int16_t *z) +{ + union acpi_object param[4]; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + int16_t *locs; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x01; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = 0; + param[2].type = ACPI_TYPE_INTEGER; + param[2].integer.value = 0; + param[3].type = ACPI_TYPE_INTEGER; + param[3].integer.value = 0; + input.count = 4; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *obj; + obj = output.pointer; + locs = (int16_t *) obj->buffer.pointer; + *x = locs[0]; + *y = locs[1]; + *z = locs[2]; + kfree(output.pointer); + } + return status; +} + +static void cmpc_accel_handler_v4(struct acpi_device *dev, u32 event) +{ + if (event == 0x81) { + int16_t x, y, z; + acpi_status status; + + status = cmpc_get_accel_v4(dev->handle, &x, &y, &z); + if (ACPI_SUCCESS(status)) { + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + input_report_abs(inputdev, ABS_X, x); + input_report_abs(inputdev, ABS_Y, y); + input_report_abs(inputdev, ABS_Z, z); + input_sync(inputdev); + } + } +} + +static ssize_t cmpc_accel_sensitivity_show_v4(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->sensitivity); +} + +static ssize_t cmpc_accel_sensitivity_store_v4(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long sensitivity; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &sensitivity); + if (r) + return r; + + /* sensitivity must be between 1 and 127 */ + if (sensitivity < 1 || sensitivity > 127) + return -EINVAL; + + accel->sensitivity = sensitivity; + cmpc_accel_set_sensitivity_v4(acpi->handle, sensitivity); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_sensitivity_attr_v4 = { + .attr = { .name = "sensitivity", .mode = 0660 }, + .show = cmpc_accel_sensitivity_show_v4, + .store = cmpc_accel_sensitivity_store_v4 +}; + +static ssize_t cmpc_accel_g_select_show_v4(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->g_select); +} + +static ssize_t cmpc_accel_g_select_store_v4(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long g_select; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = kstrtoul(buf, 0, &g_select); + if (r) + return r; + + /* 0 means 1.5g, 1 means 6g, everything else is wrong */ + if (g_select != 0 && g_select != 1) + return -EINVAL; + + accel->g_select = g_select; + cmpc_accel_set_g_select_v4(acpi->handle, g_select); + + return strnlen(buf, count); +} + +static struct device_attribute cmpc_accel_g_select_attr_v4 = { + .attr = { .name = "g_select", .mode = 0660 }, + .show = cmpc_accel_g_select_show_v4, + .store = cmpc_accel_g_select_store_v4 +}; + +static int cmpc_accel_open_v4(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); + + if (ACPI_SUCCESS(cmpc_start_accel_v4(acpi->handle))) { + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_OPEN; + return 0; + } + return -EIO; +} + +static void cmpc_accel_close_v4(struct input_dev *input) +{ + struct acpi_device *acpi; + struct cmpc_accel *accel; + + acpi = to_acpi_device(input->dev.parent); + accel = dev_get_drvdata(&input->dev); + + cmpc_stop_accel_v4(acpi->handle); + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; +} + +static void cmpc_accel_idev_init_v4(struct input_dev *inputdev) +{ + set_bit(EV_ABS, inputdev->evbit); + input_set_abs_params(inputdev, ABS_X, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Y, -255, 255, 16, 0); + input_set_abs_params(inputdev, ABS_Z, -255, 255, 16, 0); + inputdev->open = cmpc_accel_open_v4; + inputdev->close = cmpc_accel_close_v4; +} + +static int cmpc_accel_suspend_v4(struct device *dev) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) + return cmpc_stop_accel_v4(to_acpi_device(dev)->handle); + + return 0; +} + +static int cmpc_accel_resume_v4(struct device *dev) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(dev); + accel = dev_get_drvdata(&inputdev->dev); + + if (accel->inputdev_state == CMPC_ACCEL_DEV_STATE_OPEN) { + cmpc_accel_set_sensitivity_v4(to_acpi_device(dev)->handle, + accel->sensitivity); + cmpc_accel_set_g_select_v4(to_acpi_device(dev)->handle, + accel->g_select); + + if (ACPI_FAILURE(cmpc_start_accel_v4(to_acpi_device(dev)->handle))) + return -EIO; + } + + return 0; +} + +static int cmpc_accel_add_v4(struct acpi_device *acpi) +{ + int error; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + accel = kmalloc(sizeof(*accel), GFP_KERNEL); + if (!accel) + return -ENOMEM; + + accel->inputdev_state = CMPC_ACCEL_DEV_STATE_CLOSED; + + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; + cmpc_accel_set_sensitivity_v4(acpi->handle, accel->sensitivity); + + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); + if (error) + goto failed_sensitivity; + + accel->g_select = CMPC_ACCEL_G_SELECT_DEFAULT; + cmpc_accel_set_g_select_v4(acpi->handle, accel->g_select); + + error = device_create_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); + if (error) + goto failed_g_select; + + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel_v4", + cmpc_accel_idev_init_v4); + if (error) + goto failed_input; + + inputdev = dev_get_drvdata(&acpi->dev); + dev_set_drvdata(&inputdev->dev, accel); + + return 0; + +failed_input: + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); +failed_g_select: + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); +failed_sensitivity: + kfree(accel); + return error; +} + +static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr_v4); + device_remove_file(&acpi->dev, &cmpc_accel_g_select_attr_v4); + return cmpc_remove_acpi_notify_device(acpi); +} + +static SIMPLE_DEV_PM_OPS(cmpc_accel_pm, cmpc_accel_suspend_v4, + cmpc_accel_resume_v4); + +static const struct acpi_device_id cmpc_accel_device_ids_v4[] = { + {CMPC_ACCEL_HID_V4, 0}, + {"", 0} +}; + +static struct acpi_driver cmpc_accel_acpi_driver_v4 = { + .owner = THIS_MODULE, + .name = "cmpc_accel_v4", + .class = "cmpc_accel_v4", + .ids = cmpc_accel_device_ids_v4, + .ops = { + .add = cmpc_accel_add_v4, + .remove = cmpc_accel_remove_v4, + .notify = cmpc_accel_handler_v4, + }, + .drv.pm = &cmpc_accel_pm, +}; + + +/* + * Accelerometer code for Classmate versions prior to V4 */ static acpi_status cmpc_start_accel(acpi_handle handle) { @@ -726,8 +1116,15 @@ static int cmpc_init(void) if (r) goto failed_accel; + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver_v4); + if (r) + goto failed_accel_v4; + return r; +failed_accel_v4: + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); + failed_accel: acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); @@ -743,6 +1140,7 @@ failed_keys: static void cmpc_exit(void) { + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver_v4); acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); acpi_bus_unregister_driver(&cmpc_ipml_acpi_driver); @@ -754,6 +1152,7 @@ module_exit(cmpc_exit); static const struct acpi_device_id cmpc_device_ids[] = { {CMPC_ACCEL_HID, 0}, + {CMPC_ACCEL_HID_V4, 0}, {CMPC_TABLET_HID, 0}, {CMPC_IPML_HID, 0}, {CMPC_KEYS_HID, 0}, diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 5f78aac9b16..4e96e8c0b60 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -206,6 +206,60 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { }, .driver_data = &quirk_dell_vostro_v130, }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 5420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 5520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 5720", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 7420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 7520", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, + { + .callback = dmi_matched, + .ident = "Dell Inspiron 7720", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), + }, + .driver_data = &quirk_dell_vostro_v130, + }, { } }; diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 65676138034..5838332ea5b 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -79,7 +79,7 @@ static const struct key_entry eeepc_wmi_keymap[] = { { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */ { KE_KEY, HOME_PRESS, { KEY_CONFIG } }, /* Home/Express gate key */ { KE_KEY, 0xe8, { KEY_SCREENLOCK } }, - { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } }, + { KE_KEY, 0xe9, { KEY_DISPLAYTOGGLE } }, { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } }, { KE_KEY, 0xec, { KEY_CAMERA_UP } }, { KE_KEY, 0xed, { KEY_CAMERA_DOWN } }, @@ -107,6 +107,11 @@ static struct quirk_entry quirk_asus_et2012_type3 = { .store_backlight_power = true, }; +static struct quirk_entry quirk_asus_x101ch = { + /* We need this when ACPI function doesn't do this well */ + .wmi_backlight_power = true, +}; + static struct quirk_entry *quirks; static void et2012_quirks(void) @@ -157,6 +162,24 @@ static struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_unknown, }, + { + .callback = dmi_matched, + .ident = "ASUSTeK Computer INC. X101CH", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X101CH"), + }, + .driver_data = &quirk_asus_x101ch, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK Computer INC. 1015CX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1015CX"), + }, + .driver_data = &quirk_asus_x101ch, + }, {}, }; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index e2a34b42ddc..c1ca7bcebb6 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,7 +26,7 @@ #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/ctype.h> -#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) +#ifdef CONFIG_ACPI_VIDEO #include <acpi/video.h> #endif @@ -1465,6 +1465,15 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ }, }, + /* DMI ids for laptops with bad Chassis Type */ + { + .ident = "R40/R41", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "R40/R41"), + DMI_MATCH(DMI_BOARD_NAME, "R40/R41"), + }, + }, /* Specific DMI ids for laptop with quirks */ { .callback = samsung_dmi_matched, @@ -1506,6 +1515,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, .driver_data = &samsung_broken_acpi_video, }, + { + .callback = samsung_dmi_matched, + .ident = "X360", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "X360"), + DMI_MATCH(DMI_BOARD_NAME, "X360"), + }, + .driver_data = &samsung_broken_acpi_video, + }, { }, }; MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); @@ -1530,15 +1549,18 @@ static int __init samsung_init(void) samsung->quirks = quirks; -#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) +#ifdef CONFIG_ACPI + if (samsung->quirks->broken_acpi_video) + acpi_video_dmi_promote_vendor(); + /* Don't handle backlight here if the acpi video already handle it */ if (acpi_video_backlight_support()) { - if (samsung->quirks->broken_acpi_video) { - pr_info("Disabling ACPI video driver\n"); - acpi_video_unregister(); - } else { - samsung->handle_backlight = false; - } + samsung->handle_backlight = false; + } else if (samsung->quirks->broken_acpi_video) { + pr_info("Disabling ACPI video driver\n"); +#ifdef CONFIG_ACPI_VIDEO + acpi_video_unregister(); +#endif } #endif @@ -1552,8 +1574,7 @@ static int __init samsung_init(void) #ifdef CONFIG_ACPI /* Only log that if we are really on a sabi platform */ - if (acpi_video_backlight_support() && - !samsung->quirks->broken_acpi_video) + if (acpi_video_backlight_support()) pr_info("Backlight controlled by ACPI video driver\n"); #endif diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d5fd4a1193f..e7f73287636 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3015,8 +3015,6 @@ static void hotkey_exit(void) if (hotkey_dev_attributes) delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); - kfree(hotkey_keycode_map); - dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY, "restoring original HKEY status and mask\n"); /* yes, there is a bitwise or below, we want the @@ -5217,6 +5215,7 @@ static void led_exit(void) led_classdev_unregister(&tpacpi_leds[i].led_classdev); } + flush_workqueue(tpacpi_wq); kfree(tpacpi_leds); } @@ -8936,6 +8935,7 @@ static void thinkpad_acpi_module_exit(void) input_unregister_device(tpacpi_inputdev); else input_free_device(tpacpi_inputdev); + kfree(hotkey_keycode_map); } if (tpacpi_hwmon) @@ -8969,6 +8969,7 @@ static void thinkpad_acpi_module_exit(void) kfree(thinkpad_id.bios_version_str); kfree(thinkpad_id.ec_version_str); kfree(thinkpad_id.model_str); + kfree(thinkpad_id.nummodel_str); } diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig new file mode 100644 index 00000000000..8fc3808d7a3 --- /dev/null +++ b/drivers/pwm/Kconfig @@ -0,0 +1,108 @@ +menuconfig PWM + bool "PWM Support" + depends on !MACH_JZ4740 && !PUV3_PWM + help + This enables PWM support through the generic PWM framework. + You only need to enable this, if you also want to enable + one or more of the PWM drivers below. + + If unsure, say N. + +if PWM + +config PWM_BFIN + tristate "Blackfin PWM support" + depends on BFIN_GPTIMERS + help + Generic PWM framework driver for Blackfin. + + To compile this driver as a module, choose M here: the module + will be called pwm-bfin. + +config PWM_IMX + tristate "i.MX pwm support" + depends on ARCH_MXC + help + Generic PWM framework driver for i.MX. + + To compile this driver as a module, choose M here: the module + will be called pwm-imx. + +config PWM_LPC32XX + tristate "LPC32XX PWM support" + depends on ARCH_LPC32XX + help + Generic PWM framework driver for LPC32XX. The LPC32XX SOC has two + PWM controllers. + + To compile this driver as a module, choose M here: the module + will be called pwm-lpc32xx. + +config PWM_MXS + tristate "Freescale MXS PWM support" + depends on ARCH_MXS && OF + select STMP_DEVICE + help + Generic PWM framework driver for Freescale MXS. + + To compile this driver as a module, choose M here: the module + will be called pwm-mxs. + +config PWM_PXA + tristate "PXA PWM support" + depends on ARCH_PXA + help + Generic PWM framework driver for PXA. + + To compile this driver as a module, choose M here: the module + will be called pwm-pxa. + +config PWM_SAMSUNG + tristate "Samsung pwm support" + depends on PLAT_SAMSUNG + help + Generic PWM framework driver for Samsung. + + To compile this driver as a module, choose M here: the module + will be called pwm-samsung. + +config PWM_TEGRA + tristate "NVIDIA Tegra PWM support" + depends on ARCH_TEGRA + help + Generic PWM framework driver for the PWFM controller found on NVIDIA + Tegra SoCs. + + To compile this driver as a module, choose M here: the module + will be called pwm-tegra. + +config PWM_TIECAP + tristate "ECAP PWM support" + depends on SOC_AM33XX + help + PWM driver support for the ECAP APWM controller found on AM33XX + TI SOC + + To compile this driver as a module, choose M here: the module + will be called pwm-tiecap. + +config PWM_TIEHRPWM + tristate "EHRPWM PWM support" + depends on SOC_AM33XX + help + PWM driver support for the EHRPWM controller found on AM33XX + TI SOC + + To compile this driver as a module, choose M here: the module + will be called pwm-tiehrpwm. + +config PWM_VT8500 + tristate "vt8500 pwm support" + depends on ARCH_VT8500 + help + Generic PWM framework driver for vt8500. + + To compile this driver as a module, choose M here: the module + will be called pwm-vt8500. + +endif diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile new file mode 100644 index 00000000000..e4b2c898964 --- /dev/null +++ b/drivers/pwm/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_PWM) += core.o +obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o +obj-$(CONFIG_PWM_IMX) += pwm-imx.o +obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx.o +obj-$(CONFIG_PWM_MXS) += pwm-mxs.o +obj-$(CONFIG_PWM_PXA) += pwm-pxa.o +obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o +obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o +obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o +obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o +obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c new file mode 100644 index 00000000000..ecb76909e94 --- /dev/null +++ b/drivers/pwm/core.c @@ -0,0 +1,713 @@ +/* + * Generic pwmlib implementation + * + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de> + * Copyright (C) 2011-2012 Avionic Design GmbH + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/pwm.h> +#include <linux/radix-tree.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +#define MAX_PWMS 1024 + +static DEFINE_MUTEX(pwm_lookup_lock); +static LIST_HEAD(pwm_lookup_list); +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_chips); +static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); +static RADIX_TREE(pwm_tree, GFP_KERNEL); + +static struct pwm_device *pwm_to_device(unsigned int pwm) +{ + return radix_tree_lookup(&pwm_tree, pwm); +} + +static int alloc_pwms(int pwm, unsigned int count) +{ + unsigned int from = 0; + unsigned int start; + + if (pwm >= MAX_PWMS) + return -EINVAL; + + if (pwm >= 0) + from = pwm; + + start = bitmap_find_next_zero_area(allocated_pwms, MAX_PWMS, from, + count, 0); + + if (pwm >= 0 && start != pwm) + return -EEXIST; + + if (start + count > MAX_PWMS) + return -ENOSPC; + + return start; +} + +static void free_pwms(struct pwm_chip *chip) +{ + unsigned int i; + + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; + radix_tree_delete(&pwm_tree, pwm->pwm); + } + + bitmap_clear(allocated_pwms, chip->base, chip->npwm); + + kfree(chip->pwms); + chip->pwms = NULL; +} + +static struct pwm_chip *pwmchip_find_by_name(const char *name) +{ + struct pwm_chip *chip; + + if (!name) + return NULL; + + mutex_lock(&pwm_lock); + + list_for_each_entry(chip, &pwm_chips, list) { + const char *chip_name = dev_name(chip->dev); + + if (chip_name && strcmp(chip_name, name) == 0) { + mutex_unlock(&pwm_lock); + return chip; + } + } + + mutex_unlock(&pwm_lock); + + return NULL; +} + +static int pwm_device_request(struct pwm_device *pwm, const char *label) +{ + int err; + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + return -EBUSY; + + if (!try_module_get(pwm->chip->ops->owner)) + return -ENODEV; + + if (pwm->chip->ops->request) { + err = pwm->chip->ops->request(pwm->chip, pwm); + if (err) { + module_put(pwm->chip->ops->owner); + return err; + } + } + + set_bit(PWMF_REQUESTED, &pwm->flags); + pwm->label = label; + + return 0; +} + +static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, + const struct of_phandle_args *args) +{ + struct pwm_device *pwm; + + if (pc->of_pwm_n_cells < 2) + return ERR_PTR(-EINVAL); + + if (args->args[0] >= pc->npwm) + return ERR_PTR(-EINVAL); + + pwm = pwm_request_from_chip(pc, args->args[0], NULL); + if (IS_ERR(pwm)) + return pwm; + + pwm_set_period(pwm, args->args[1]); + + return pwm; +} + +void of_pwmchip_add(struct pwm_chip *chip) +{ + if (!chip->dev || !chip->dev->of_node) + return; + + if (!chip->of_xlate) { + chip->of_xlate = of_pwm_simple_xlate; + chip->of_pwm_n_cells = 2; + } + + of_node_get(chip->dev->of_node); +} + +void of_pwmchip_remove(struct pwm_chip *chip) +{ + if (chip->dev && chip->dev->of_node) + of_node_put(chip->dev->of_node); +} + +/** + * pwm_set_chip_data() - set private chip data for a PWM + * @pwm: PWM device + * @data: pointer to chip-specific data + */ +int pwm_set_chip_data(struct pwm_device *pwm, void *data) +{ + if (!pwm) + return -EINVAL; + + pwm->chip_data = data; + + return 0; +} + +/** + * pwm_get_chip_data() - get private chip data for a PWM + * @pwm: PWM device + */ +void *pwm_get_chip_data(struct pwm_device *pwm) +{ + return pwm ? pwm->chip_data : NULL; +} + +/** + * pwmchip_add() - register a new PWM chip + * @chip: the PWM chip to add + * + * Register a new PWM chip. If chip->base < 0 then a dynamically assigned base + * will be used. + */ +int pwmchip_add(struct pwm_chip *chip) +{ + struct pwm_device *pwm; + unsigned int i; + int ret; + + if (!chip || !chip->dev || !chip->ops || !chip->ops->config || + !chip->ops->enable || !chip->ops->disable) + return -EINVAL; + + mutex_lock(&pwm_lock); + + ret = alloc_pwms(chip->base, chip->npwm); + if (ret < 0) + goto out; + + chip->pwms = kzalloc(chip->npwm * sizeof(*pwm), GFP_KERNEL); + if (!chip->pwms) { + ret = -ENOMEM; + goto out; + } + + chip->base = ret; + + for (i = 0; i < chip->npwm; i++) { + pwm = &chip->pwms[i]; + + pwm->chip = chip; + pwm->pwm = chip->base + i; + pwm->hwpwm = i; + + radix_tree_insert(&pwm_tree, pwm->pwm, pwm); + } + + bitmap_set(allocated_pwms, chip->base, chip->npwm); + + INIT_LIST_HEAD(&chip->list); + list_add(&chip->list, &pwm_chips); + + ret = 0; + + if (IS_ENABLED(CONFIG_OF)) + of_pwmchip_add(chip); + +out: + mutex_unlock(&pwm_lock); + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_add); + +/** + * pwmchip_remove() - remove a PWM chip + * @chip: the PWM chip to remove + * + * Removes a PWM chip. This function may return busy if the PWM chip provides + * a PWM device that is still requested. + */ +int pwmchip_remove(struct pwm_chip *chip) +{ + unsigned int i; + int ret = 0; + + mutex_lock(&pwm_lock); + + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) { + ret = -EBUSY; + goto out; + } + } + + list_del_init(&chip->list); + + if (IS_ENABLED(CONFIG_OF)) + of_pwmchip_remove(chip); + + free_pwms(chip); + +out: + mutex_unlock(&pwm_lock); + return ret; +} +EXPORT_SYMBOL_GPL(pwmchip_remove); + +/** + * pwm_request() - request a PWM device + * @pwm_id: global PWM device index + * @label: PWM device label + * + * This function is deprecated, use pwm_get() instead. + */ +struct pwm_device *pwm_request(int pwm, const char *label) +{ + struct pwm_device *dev; + int err; + + if (pwm < 0 || pwm >= MAX_PWMS) + return ERR_PTR(-EINVAL); + + mutex_lock(&pwm_lock); + + dev = pwm_to_device(pwm); + if (!dev) { + dev = ERR_PTR(-EPROBE_DEFER); + goto out; + } + + err = pwm_device_request(dev, label); + if (err < 0) + dev = ERR_PTR(err); + +out: + mutex_unlock(&pwm_lock); + + return dev; +} +EXPORT_SYMBOL_GPL(pwm_request); + +/** + * pwm_request_from_chip() - request a PWM device relative to a PWM chip + * @chip: PWM chip + * @index: per-chip index of the PWM to request + * @label: a literal description string of this PWM + * + * Returns the PWM at the given index of the given PWM chip. A negative error + * code is returned if the index is not valid for the specified PWM chip or + * if the PWM device cannot be requested. + */ +struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, + unsigned int index, + const char *label) +{ + struct pwm_device *pwm; + int err; + + if (!chip || index >= chip->npwm) + return ERR_PTR(-EINVAL); + + mutex_lock(&pwm_lock); + pwm = &chip->pwms[index]; + + err = pwm_device_request(pwm, label); + if (err < 0) + pwm = ERR_PTR(err); + + mutex_unlock(&pwm_lock); + return pwm; +} +EXPORT_SYMBOL_GPL(pwm_request_from_chip); + +/** + * pwm_free() - free a PWM device + * @pwm: PWM device + * + * This function is deprecated, use pwm_put() instead. + */ +void pwm_free(struct pwm_device *pwm) +{ + pwm_put(pwm); +} +EXPORT_SYMBOL_GPL(pwm_free); + +/** + * pwm_config() - change a PWM device configuration + * @pwm: PWM device + * @duty_ns: "on" time (in nanoseconds) + * @period_ns: duration (in nanoseconds) of one cycle + */ +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + if (!pwm || period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns); +} +EXPORT_SYMBOL_GPL(pwm_config); + +/** + * pwm_enable() - start a PWM output toggling + * @pwm: PWM device + */ +int pwm_enable(struct pwm_device *pwm) +{ + if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags)) + return pwm->chip->ops->enable(pwm->chip, pwm); + + return pwm ? 0 : -EINVAL; +} +EXPORT_SYMBOL_GPL(pwm_enable); + +/** + * pwm_disable() - stop a PWM output toggling + * @pwm: PWM device + */ +void pwm_disable(struct pwm_device *pwm) +{ + if (pwm && test_and_clear_bit(PWMF_ENABLED, &pwm->flags)) + pwm->chip->ops->disable(pwm->chip, pwm); +} +EXPORT_SYMBOL_GPL(pwm_disable); + +static struct pwm_chip *of_node_to_pwmchip(struct device_node *np) +{ + struct pwm_chip *chip; + + mutex_lock(&pwm_lock); + + list_for_each_entry(chip, &pwm_chips, list) + if (chip->dev && chip->dev->of_node == np) { + mutex_unlock(&pwm_lock); + return chip; + } + + mutex_unlock(&pwm_lock); + + return ERR_PTR(-EPROBE_DEFER); +} + +/** + * of_pwm_request() - request a PWM via the PWM framework + * @np: device node to get the PWM from + * @con_id: consumer name + * + * Returns the PWM device parsed from the phandle and index specified in the + * "pwms" property of a device tree node or a negative error-code on failure. + * Values parsed from the device tree are stored in the returned PWM device + * object. + * + * If con_id is NULL, the first PWM device listed in the "pwms" property will + * be requested. Otherwise the "pwm-names" property is used to do a reverse + * lookup of the PWM index. This also means that the "pwm-names" property + * becomes mandatory for devices that look up the PWM device via the con_id + * parameter. + */ +static struct pwm_device *of_pwm_request(struct device_node *np, + const char *con_id) +{ + struct pwm_device *pwm = NULL; + struct of_phandle_args args; + struct pwm_chip *pc; + int index = 0; + int err; + + if (con_id) { + index = of_property_match_string(np, "pwm-names", con_id); + if (index < 0) + return ERR_PTR(index); + } + + err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index, + &args); + if (err) { + pr_debug("%s(): can't parse \"pwms\" property\n", __func__); + return ERR_PTR(err); + } + + pc = of_node_to_pwmchip(args.np); + if (IS_ERR(pc)) { + pr_debug("%s(): PWM chip not found\n", __func__); + pwm = ERR_CAST(pc); + goto put; + } + + if (args.args_count != pc->of_pwm_n_cells) { + pr_debug("%s: wrong #pwm-cells for %s\n", np->full_name, + args.np->full_name); + pwm = ERR_PTR(-EINVAL); + goto put; + } + + pwm = pc->of_xlate(pc, &args); + if (IS_ERR(pwm)) + goto put; + + /* + * If a consumer name was not given, try to look it up from the + * "pwm-names" property if it exists. Otherwise use the name of + * the user device node. + */ + if (!con_id) { + err = of_property_read_string_index(np, "pwm-names", index, + &con_id); + if (err < 0) + con_id = np->name; + } + + pwm->label = con_id; + +put: + of_node_put(args.np); + + return pwm; +} + +/** + * pwm_add_table() - register PWM device consumers + * @table: array of consumers to register + * @num: number of consumers in table + */ +void __init pwm_add_table(struct pwm_lookup *table, size_t num) +{ + mutex_lock(&pwm_lookup_lock); + + while (num--) { + list_add_tail(&table->list, &pwm_lookup_list); + table++; + } + + mutex_unlock(&pwm_lookup_lock); +} + +/** + * pwm_get() - look up and request a PWM device + * @dev: device for PWM consumer + * @con_id: consumer name + * + * Lookup is first attempted using DT. If the device was not instantiated from + * a device tree, a PWM chip and a relative index is looked up via a table + * supplied by board setup code (see pwm_add_table()). + * + * Once a PWM chip has been found the specified PWM device will be requested + * and is ready to be used. + */ +struct pwm_device *pwm_get(struct device *dev, const char *con_id) +{ + struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); + const char *dev_id = dev ? dev_name(dev): NULL; + struct pwm_chip *chip = NULL; + unsigned int index = 0; + unsigned int best = 0; + struct pwm_lookup *p; + unsigned int match; + + /* look up via DT first */ + if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) + return of_pwm_request(dev->of_node, con_id); + + /* + * We look up the provider in the static table typically provided by + * board setup code. We first try to lookup the consumer device by + * name. If the consumer device was passed in as NULL or if no match + * was found, we try to find the consumer by directly looking it up + * by name. + * + * If a match is found, the provider PWM chip is looked up by name + * and a PWM device is requested using the PWM device per-chip index. + * + * The lookup algorithm was shamelessly taken from the clock + * framework: + * + * We do slightly fuzzy matching here: + * An entry with a NULL ID is assumed to be a wildcard. + * If an entry has a device ID, it must match + * If an entry has a connection ID, it must match + * Then we take the most specific entry - with the following order + * of precedence: dev+con > dev only > con only. + */ + mutex_lock(&pwm_lookup_lock); + + list_for_each_entry(p, &pwm_lookup_list, list) { + match = 0; + + if (p->dev_id) { + if (!dev_id || strcmp(p->dev_id, dev_id)) + continue; + + match += 2; + } + + if (p->con_id) { + if (!con_id || strcmp(p->con_id, con_id)) + continue; + + match += 1; + } + + if (match > best) { + chip = pwmchip_find_by_name(p->provider); + index = p->index; + + if (match != 3) + best = match; + else + break; + } + } + + if (chip) + pwm = pwm_request_from_chip(chip, index, con_id ?: dev_id); + + mutex_unlock(&pwm_lookup_lock); + + return pwm; +} +EXPORT_SYMBOL_GPL(pwm_get); + +/** + * pwm_put() - release a PWM device + * @pwm: PWM device + */ +void pwm_put(struct pwm_device *pwm) +{ + if (!pwm) + return; + + mutex_lock(&pwm_lock); + + if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { + pr_warning("PWM device already freed\n"); + goto out; + } + + if (pwm->chip->ops->free) + pwm->chip->ops->free(pwm->chip, pwm); + + pwm->label = NULL; + + module_put(pwm->chip->ops->owner); +out: + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL_GPL(pwm_put); + +#ifdef CONFIG_DEBUG_FS +static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) +{ + unsigned int i; + + for (i = 0; i < chip->npwm; i++) { + struct pwm_device *pwm = &chip->pwms[i]; + + seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); + + if (test_bit(PWMF_REQUESTED, &pwm->flags)) + seq_printf(s, " requested"); + + if (test_bit(PWMF_ENABLED, &pwm->flags)) + seq_printf(s, " enabled"); + + seq_printf(s, "\n"); + } +} + +static void *pwm_seq_start(struct seq_file *s, loff_t *pos) +{ + mutex_lock(&pwm_lock); + s->private = ""; + + return seq_list_start(&pwm_chips, *pos); +} + +static void *pwm_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + s->private = "\n"; + + return seq_list_next(v, &pwm_chips, pos); +} + +static void pwm_seq_stop(struct seq_file *s, void *v) +{ + mutex_unlock(&pwm_lock); +} + +static int pwm_seq_show(struct seq_file *s, void *v) +{ + struct pwm_chip *chip = list_entry(v, struct pwm_chip, list); + + seq_printf(s, "%s%s/%s, %d PWM device%s\n", (char *)s->private, + chip->dev->bus ? chip->dev->bus->name : "no-bus", + dev_name(chip->dev), chip->npwm, + (chip->npwm != 1) ? "s" : ""); + + if (chip->ops->dbg_show) + chip->ops->dbg_show(chip, s); + else + pwm_dbg_show(chip, s); + + return 0; +} + +static const struct seq_operations pwm_seq_ops = { + .start = pwm_seq_start, + .next = pwm_seq_next, + .stop = pwm_seq_stop, + .show = pwm_seq_show, +}; + +static int pwm_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &pwm_seq_ops); +} + +static const struct file_operations pwm_debugfs_ops = { + .owner = THIS_MODULE, + .open = pwm_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init pwm_debugfs_init(void) +{ + debugfs_create_file("pwm", S_IFREG | S_IRUGO, NULL, NULL, + &pwm_debugfs_ops); + + return 0; +} + +subsys_initcall(pwm_debugfs_init); +#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/pwm/pwm-bfin.c b/drivers/pwm/pwm-bfin.c new file mode 100644 index 00000000000..d53c4e7941e --- /dev/null +++ b/drivers/pwm/pwm-bfin.c @@ -0,0 +1,162 @@ +/* + * Blackfin Pulse Width Modulation (PWM) core + * + * Copyright (c) 2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/slab.h> + +#include <asm/gptimers.h> +#include <asm/portmux.h> + +struct bfin_pwm_chip { + struct pwm_chip chip; +}; + +struct bfin_pwm { + unsigned short pin; +}; + +static const unsigned short pwm_to_gptimer_per[] = { + P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5, + P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11, +}; + +static int bfin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct bfin_pwm *priv; + int ret; + + if (pwm->hwpwm >= ARRAY_SIZE(pwm_to_gptimer_per)) + return -EINVAL; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->pin = pwm_to_gptimer_per[pwm->hwpwm]; + + ret = peripheral_request(priv->pin, NULL); + if (ret) { + kfree(priv); + return ret; + } + + pwm_set_chip_data(pwm, priv); + + return 0; +} + +static void bfin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct bfin_pwm *priv = pwm_get_chip_data(pwm); + + if (priv) { + peripheral_free(priv->pin); + kfree(priv); + } +} + +static int bfin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct bfin_pwm *priv = pwm_get_chip_data(pwm); + unsigned long period, duty; + unsigned long long val; + + if (duty_ns < 0 || duty_ns > period_ns) + return -EINVAL; + + val = (unsigned long long)get_sclk() * period_ns; + do_div(val, NSEC_PER_SEC); + period = val; + + val = (unsigned long long)period * duty_ns; + do_div(val, period_ns); + duty = period - val; + + if (duty >= period) + duty = period - 1; + + set_gptimer_config(priv->pin, TIMER_MODE_PWM | TIMER_PERIOD_CNT); + set_gptimer_pwidth(priv->pin, duty); + set_gptimer_period(priv->pin, period); + + return 0; +} + +static int bfin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct bfin_pwm *priv = pwm_get_chip_data(pwm); + + enable_gptimer(priv->pin); + + return 0; +} + +static void bfin_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct bfin_pwm *priv = pwm_get_chip_data(pwm); + + disable_gptimer(priv->pin); +} + +static struct pwm_ops bfin_pwm_ops = { + .request = bfin_pwm_request, + .free = bfin_pwm_free, + .config = bfin_pwm_config, + .enable = bfin_pwm_enable, + .disable = bfin_pwm_disable, + .owner = THIS_MODULE, +}; + +static int bfin_pwm_probe(struct platform_device *pdev) +{ + struct bfin_pwm_chip *pwm; + int ret; + + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, pwm); + + pwm->chip.dev = &pdev->dev; + pwm->chip.ops = &bfin_pwm_ops; + pwm->chip.base = -1; + pwm->chip.npwm = 12; + + ret = pwmchip_add(&pwm->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int __devexit bfin_pwm_remove(struct platform_device *pdev) +{ + struct bfin_pwm_chip *pwm = platform_get_drvdata(pdev); + + return pwmchip_remove(&pwm->chip); +} + +static struct platform_driver bfin_pwm_driver = { + .driver = { + .name = "bfin-pwm", + }, + .probe = bfin_pwm_probe, + .remove = __devexit_p(bfin_pwm_remove), +}; + +module_platform_driver(bfin_pwm_driver); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-mxc/pwm.c b/drivers/pwm/pwm-imx.c index c0cab2270dd..2a0b3533397 100644 --- a/arch/arm/plat-mxc/pwm.c +++ b/drivers/pwm/pwm-imx.c @@ -39,33 +39,28 @@ #define MX3_PWMCR_CLKSRC_IPG (1 << 16) #define MX3_PWMCR_EN (1 << 0) - - -struct pwm_device { - struct list_head node; - struct platform_device *pdev; - - const char *label; +struct imx_chip { struct clk *clk; int clk_enabled; void __iomem *mmio_base; - unsigned int use_count; - unsigned int pwm_id; + struct pwm_chip chip; }; -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip) + +static int imx_pwm_config(struct pwm_chip *chip, + struct pwm_device *pwm, int duty_ns, int period_ns) { - if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) - return -EINVAL; + struct imx_chip *imx = to_imx_chip(chip); if (!(cpu_is_mx1() || cpu_is_mx21())) { unsigned long long c; unsigned long period_cycles, duty_cycles, prescale; u32 cr; - c = clk_get_rate(pwm->clk); + c = clk_get_rate(imx->clk); c = c * period_ns; do_div(c, 1000000000); period_cycles = c; @@ -86,8 +81,8 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) else period_cycles = 0; - writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR); - writel(period_cycles, pwm->mmio_base + MX3_PWMPR); + writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); + writel(period_cycles, imx->mmio_base + MX3_PWMPR); cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | @@ -98,7 +93,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) else cr |= MX3_PWMCR_CLKSRC_IPG_HIGH; - writel(cr, pwm->mmio_base + MX3_PWMCR); + writel(cr, imx->mmio_base + MX3_PWMCR); } else if (cpu_is_mx1() || cpu_is_mx21()) { /* The PWM subsystem allows for exact frequencies. However, * I cannot connect a scope on my device to the PWM line and @@ -116,191 +111,120 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) * both the prescaler (/1 .. /128) and then by CLKSEL * (/2 .. /16). */ - u32 max = readl(pwm->mmio_base + MX1_PWMP); + u32 max = readl(imx->mmio_base + MX1_PWMP); u32 p = max * duty_ns / period_ns; - writel(max - p, pwm->mmio_base + MX1_PWMS); + writel(max - p, imx->mmio_base + MX1_PWMS); } else { BUG(); } return 0; } -EXPORT_SYMBOL(pwm_config); -int pwm_enable(struct pwm_device *pwm) +static int imx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { + struct imx_chip *imx = to_imx_chip(chip); int rc = 0; - if (!pwm->clk_enabled) { - rc = clk_prepare_enable(pwm->clk); + if (!imx->clk_enabled) { + rc = clk_prepare_enable(imx->clk); if (!rc) - pwm->clk_enabled = 1; + imx->clk_enabled = 1; } return rc; } -EXPORT_SYMBOL(pwm_enable); -void pwm_disable(struct pwm_device *pwm) +static void imx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { - writel(0, pwm->mmio_base + MX3_PWMCR); + struct imx_chip *imx = to_imx_chip(chip); - if (pwm->clk_enabled) { - clk_disable_unprepare(pwm->clk); - pwm->clk_enabled = 0; - } -} -EXPORT_SYMBOL(pwm_disable); + writel(0, imx->mmio_base + MX3_PWMCR); -static DEFINE_MUTEX(pwm_lock); -static LIST_HEAD(pwm_list); - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int found = 0; - - mutex_lock(&pwm_lock); - - list_for_each_entry(pwm, &pwm_list, node) { - if (pwm->pwm_id == pwm_id) { - found = 1; - break; - } + if (imx->clk_enabled) { + clk_disable_unprepare(imx->clk); + imx->clk_enabled = 0; } - - if (found) { - if (pwm->use_count == 0) { - pwm->use_count++; - pwm->label = label; - } else - pwm = ERR_PTR(-EBUSY); - } else - pwm = ERR_PTR(-ENOENT); - - mutex_unlock(&pwm_lock); - return pwm; } -EXPORT_SYMBOL(pwm_request); -void pwm_free(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - - if (pwm->use_count) { - pwm->use_count--; - pwm->label = NULL; - } else - pr_warning("PWM device already freed\n"); - - mutex_unlock(&pwm_lock); -} -EXPORT_SYMBOL(pwm_free); +static struct pwm_ops imx_pwm_ops = { + .enable = imx_pwm_enable, + .disable = imx_pwm_disable, + .config = imx_pwm_config, + .owner = THIS_MODULE, +}; -static int __devinit mxc_pwm_probe(struct platform_device *pdev) +static int __devinit imx_pwm_probe(struct platform_device *pdev) { - struct pwm_device *pwm; + struct imx_chip *imx; struct resource *r; int ret = 0; - pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); - if (pwm == NULL) { + imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); + if (imx == NULL) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } - pwm->clk = clk_get(&pdev->dev, "pwm"); + imx->clk = devm_clk_get(&pdev->dev, "pwm"); - if (IS_ERR(pwm->clk)) { - ret = PTR_ERR(pwm->clk); - goto err_free; - } + if (IS_ERR(imx->clk)) + return PTR_ERR(imx->clk); - pwm->clk_enabled = 0; + imx->chip.ops = &imx_pwm_ops; + imx->chip.dev = &pdev->dev; + imx->chip.base = -1; + imx->chip.npwm = 1; - pwm->use_count = 0; - pwm->pwm_id = pdev->id; - pwm->pdev = pdev; + imx->clk_enabled = 0; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto err_free_clk; - } - - r = request_mem_region(r->start, resource_size(r), pdev->name); - if (r == NULL) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - ret = -EBUSY; - goto err_free_clk; + return -ENODEV; } - pwm->mmio_base = ioremap(r->start, resource_size(r)); - if (pwm->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); - ret = -ENODEV; - goto err_free_mem; - } + imx->mmio_base = devm_request_and_ioremap(&pdev->dev, r); + if (imx->mmio_base == NULL) + return -EADDRNOTAVAIL; - mutex_lock(&pwm_lock); - list_add_tail(&pwm->node, &pwm_list); - mutex_unlock(&pwm_lock); + ret = pwmchip_add(&imx->chip); + if (ret < 0) + return ret; - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, imx); return 0; - -err_free_mem: - release_mem_region(r->start, resource_size(r)); -err_free_clk: - clk_put(pwm->clk); -err_free: - kfree(pwm); - return ret; } -static int __devexit mxc_pwm_remove(struct platform_device *pdev) +static int __devexit imx_pwm_remove(struct platform_device *pdev) { - struct pwm_device *pwm; - struct resource *r; + struct imx_chip *imx; - pwm = platform_get_drvdata(pdev); - if (pwm == NULL) + imx = platform_get_drvdata(pdev); + if (imx == NULL) return -ENODEV; - mutex_lock(&pwm_lock); - list_del(&pwm->node); - mutex_unlock(&pwm_lock); - - iounmap(pwm->mmio_base); - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(r->start, resource_size(r)); - - clk_put(pwm->clk); - - kfree(pwm); - return 0; + return pwmchip_remove(&imx->chip); } -static struct platform_driver mxc_pwm_driver = { +static struct platform_driver imx_pwm_driver = { .driver = { .name = "mxc_pwm", }, - .probe = mxc_pwm_probe, - .remove = __devexit_p(mxc_pwm_remove), + .probe = imx_pwm_probe, + .remove = __devexit_p(imx_pwm_remove), }; -static int __init mxc_pwm_init(void) +static int __init imx_pwm_init(void) { - return platform_driver_register(&mxc_pwm_driver); + return platform_driver_register(&imx_pwm_driver); } -arch_initcall(mxc_pwm_init); +arch_initcall(imx_pwm_init); -static void __exit mxc_pwm_exit(void) +static void __exit imx_pwm_exit(void) { - platform_driver_unregister(&mxc_pwm_driver); + platform_driver_unregister(&imx_pwm_driver); } -module_exit(mxc_pwm_exit); +module_exit(imx_pwm_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c new file mode 100644 index 00000000000..adb87f0c163 --- /dev/null +++ b/drivers/pwm/pwm-lpc32xx.c @@ -0,0 +1,148 @@ +/* + * Copyright 2012 Alexandre Pereira da Silva <aletes.xgr@gmail.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; version 2. + * + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/slab.h> + +struct lpc32xx_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + void __iomem *base; +}; + +#define PWM_ENABLE (1 << 31) +#define PWM_RELOADV(x) (((x) & 0xFF) << 8) +#define PWM_DUTY(x) ((x) & 0xFF) + +#define to_lpc32xx_pwm_chip(_chip) \ + container_of(_chip, struct lpc32xx_pwm_chip, chip) + +static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); + unsigned long long c; + int period_cycles, duty_cycles; + + c = clk_get_rate(lpc32xx->clk) / 256; + c = c * period_ns; + do_div(c, NSEC_PER_SEC); + + /* Handle high and low extremes */ + if (c == 0) + c = 1; + if (c > 255) + c = 0; /* 0 set division by 256 */ + period_cycles = c; + + c = 256 * duty_ns; + do_div(c, period_ns); + duty_cycles = c; + + writel(PWM_ENABLE | PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles), + lpc32xx->base + (pwm->hwpwm << 2)); + + return 0; +} + +static int lpc32xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); + + return clk_enable(lpc32xx->clk); +} + +static void lpc32xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); + + writel(0, lpc32xx->base + (pwm->hwpwm << 2)); + clk_disable(lpc32xx->clk); +} + +static const struct pwm_ops lpc32xx_pwm_ops = { + .config = lpc32xx_pwm_config, + .enable = lpc32xx_pwm_enable, + .disable = lpc32xx_pwm_disable, + .owner = THIS_MODULE, +}; + +static int lpc32xx_pwm_probe(struct platform_device *pdev) +{ + struct lpc32xx_pwm_chip *lpc32xx; + struct resource *res; + int ret; + + lpc32xx = devm_kzalloc(&pdev->dev, sizeof(*lpc32xx), GFP_KERNEL); + if (!lpc32xx) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + lpc32xx->base = devm_request_and_ioremap(&pdev->dev, res); + if (!lpc32xx->base) + return -EADDRNOTAVAIL; + + lpc32xx->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(lpc32xx->clk)) + return PTR_ERR(lpc32xx->clk); + + lpc32xx->chip.dev = &pdev->dev; + lpc32xx->chip.ops = &lpc32xx_pwm_ops; + lpc32xx->chip.npwm = 2; + + ret = pwmchip_add(&lpc32xx->chip); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, lpc32xx); + + return 0; +} + +static int __devexit lpc32xx_pwm_remove(struct platform_device *pdev) +{ + struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev); + + clk_disable(lpc32xx->clk); + return pwmchip_remove(&lpc32xx->chip); +} + +static struct of_device_id lpc32xx_pwm_dt_ids[] = { + { .compatible = "nxp,lpc3220-pwm", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lpc32xx_pwm_dt_ids); + +static struct platform_driver lpc32xx_pwm_driver = { + .driver = { + .name = "lpc32xx-pwm", + .of_match_table = of_match_ptr(lpc32xx_pwm_dt_ids), + }, + .probe = lpc32xx_pwm_probe, + .remove = __devexit_p(lpc32xx_pwm_remove), +}; +module_platform_driver(lpc32xx_pwm_driver); + +MODULE_ALIAS("platform:lpc32xx-pwm"); +MODULE_AUTHOR("Alexandre Pereira da Silva <aletes.xgr@gmail.com>"); +MODULE_DESCRIPTION("LPC32XX PWM Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c new file mode 100644 index 00000000000..e5852646f08 --- /dev/null +++ b/drivers/pwm/pwm-mxs.c @@ -0,0 +1,203 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/slab.h> +#include <linux/stmp_device.h> + +#define SET 0x4 +#define CLR 0x8 +#define TOG 0xc + +#define PWM_CTRL 0x0 +#define PWM_ACTIVE0 0x10 +#define PWM_PERIOD0 0x20 +#define PERIOD_PERIOD(p) ((p) & 0xffff) +#define PERIOD_PERIOD_MAX 0x10000 +#define PERIOD_ACTIVE_HIGH (3 << 16) +#define PERIOD_INACTIVE_LOW (2 << 18) +#define PERIOD_CDIV(div) (((div) & 0x7) << 20) +#define PERIOD_CDIV_MAX 8 + +struct mxs_pwm_chip { + struct pwm_chip chip; + struct device *dev; + struct clk *clk; + void __iomem *base; +}; + +#define to_mxs_pwm_chip(_chip) container_of(_chip, struct mxs_pwm_chip, chip) + +static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip); + int ret, div = 0; + unsigned int period_cycles, duty_cycles; + unsigned long rate; + unsigned long long c; + + rate = clk_get_rate(mxs->clk); + while (1) { + c = rate / (1 << div); + c = c * period_ns; + do_div(c, 1000000000); + if (c < PERIOD_PERIOD_MAX) + break; + div++; + if (div > PERIOD_CDIV_MAX) + return -EINVAL; + } + + period_cycles = c; + c *= duty_ns; + do_div(c, period_ns); + duty_cycles = c; + + /* + * If the PWM channel is disabled, make sure to turn on the clock + * before writing the register. Otherwise, keep it enabled. + */ + if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + ret = clk_prepare_enable(mxs->clk); + if (ret) + return ret; + } + + writel(duty_cycles << 16, + mxs->base + PWM_ACTIVE0 + pwm->hwpwm * 0x20); + writel(PERIOD_PERIOD(period_cycles) | PERIOD_ACTIVE_HIGH | + PERIOD_INACTIVE_LOW | PERIOD_CDIV(div), + mxs->base + PWM_PERIOD0 + pwm->hwpwm * 0x20); + + /* + * If the PWM is not enabled, turn the clock off again to save power. + */ + if (!test_bit(PWMF_ENABLED, &pwm->flags)) + clk_disable_unprepare(mxs->clk); + + return 0; +} + +static int mxs_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip); + int ret; + + ret = clk_prepare_enable(mxs->clk); + if (ret) + return ret; + + writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + SET); + + return 0; +} + +static void mxs_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip); + + writel(1 << pwm->hwpwm, mxs->base + PWM_CTRL + CLR); + + clk_disable_unprepare(mxs->clk); +} + +static const struct pwm_ops mxs_pwm_ops = { + .config = mxs_pwm_config, + .enable = mxs_pwm_enable, + .disable = mxs_pwm_disable, + .owner = THIS_MODULE, +}; + +static int mxs_pwm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct mxs_pwm_chip *mxs; + struct resource *res; + struct pinctrl *pinctrl; + int ret; + + mxs = devm_kzalloc(&pdev->dev, sizeof(*mxs), GFP_KERNEL); + if (!mxs) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mxs->base = devm_request_and_ioremap(&pdev->dev, res); + if (!mxs->base) + return -EADDRNOTAVAIL; + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); + + mxs->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mxs->clk)) + return PTR_ERR(mxs->clk); + + mxs->chip.dev = &pdev->dev; + mxs->chip.ops = &mxs_pwm_ops; + mxs->chip.base = -1; + ret = of_property_read_u32(np, "fsl,pwm-number", &mxs->chip.npwm); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get pwm number: %d\n", ret); + return ret; + } + + ret = pwmchip_add(&mxs->chip); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret); + return ret; + } + + mxs->dev = &pdev->dev; + platform_set_drvdata(pdev, mxs); + + stmp_reset_block(mxs->base); + + return 0; +} + +static int __devexit mxs_pwm_remove(struct platform_device *pdev) +{ + struct mxs_pwm_chip *mxs = platform_get_drvdata(pdev); + + return pwmchip_remove(&mxs->chip); +} + +static struct of_device_id mxs_pwm_dt_ids[] = { + { .compatible = "fsl,imx23-pwm", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_pwm_dt_ids); + +static struct platform_driver mxs_pwm_driver = { + .driver = { + .name = "mxs-pwm", + .of_match_table = of_match_ptr(mxs_pwm_dt_ids), + }, + .probe = mxs_pwm_probe, + .remove = __devexit_p(mxs_pwm_remove), +}; +module_platform_driver(mxs_pwm_driver); + +MODULE_ALIAS("platform:mxs-pwm"); +MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>"); +MODULE_DESCRIPTION("Freescale MXS PWM Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c new file mode 100644 index 00000000000..bd5867a1c70 --- /dev/null +++ b/drivers/pwm/pwm-pxa.c @@ -0,0 +1,218 @@ +/* + * drivers/pwm/pwm-pxa.c + * + * simple driver for PWM (Pulse Width Modulator) controller + * + * 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. + * + * 2008-02-13 initial version + * eric miao <eric.miao@marvell.com> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/pwm.h> + +#include <asm/div64.h> + +#define HAS_SECONDARY_PWM 0x10 +#define PWM_ID_BASE(d) ((d) & 0xf) + +static const struct platform_device_id pwm_id_table[] = { + /* PWM has_secondary_pwm? */ + { "pxa25x-pwm", 0 }, + { "pxa27x-pwm", 0 | HAS_SECONDARY_PWM }, + { "pxa168-pwm", 1 }, + { "pxa910-pwm", 1 }, + { }, +}; +MODULE_DEVICE_TABLE(platform, pwm_id_table); + +/* PWM registers and bits definitions */ +#define PWMCR (0x00) +#define PWMDCR (0x04) +#define PWMPCR (0x08) + +#define PWMCR_SD (1 << 6) +#define PWMDCR_FD (1 << 10) + +struct pxa_pwm_chip { + struct pwm_chip chip; + struct device *dev; + + struct clk *clk; + int clk_enabled; + void __iomem *mmio_base; +}; + +static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct pxa_pwm_chip, chip); +} + +/* + * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE + * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE + */ +static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); + unsigned long long c; + unsigned long period_cycles, prescale, pv, dc; + unsigned long offset; + int rc; + + if (period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + offset = pwm->hwpwm ? 0x10 : 0; + + c = clk_get_rate(pc->clk); + c = c * period_ns; + do_div(c, 1000000000); + period_cycles = c; + + if (period_cycles < 1) + period_cycles = 1; + prescale = (period_cycles - 1) / 1024; + pv = period_cycles / (prescale + 1) - 1; + + if (prescale > 63) + return -EINVAL; + + if (duty_ns == period_ns) + dc = PWMDCR_FD; + else + dc = (pv + 1) * duty_ns / period_ns; + + /* NOTE: the clock to PWM has to be enabled first + * before writing to the registers + */ + rc = clk_prepare_enable(pc->clk); + if (rc < 0) + return rc; + + writel(prescale, pc->mmio_base + offset + PWMCR); + writel(dc, pc->mmio_base + offset + PWMDCR); + writel(pv, pc->mmio_base + offset + PWMPCR); + + clk_disable_unprepare(pc->clk); + return 0; +} + +static int pxa_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); + int rc = 0; + + if (!pc->clk_enabled) { + rc = clk_prepare_enable(pc->clk); + if (!rc) + pc->clk_enabled++; + } + return rc; +} + +static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); + + if (pc->clk_enabled) { + clk_disable_unprepare(pc->clk); + pc->clk_enabled--; + } +} + +static struct pwm_ops pxa_pwm_ops = { + .config = pxa_pwm_config, + .enable = pxa_pwm_enable, + .disable = pxa_pwm_disable, + .owner = THIS_MODULE, +}; + +static int __devinit pwm_probe(struct platform_device *pdev) +{ + const struct platform_device_id *id = platform_get_device_id(pdev); + struct pxa_pwm_chip *pwm; + struct resource *r; + int ret = 0; + + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); + if (pwm == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pwm->clk)) + return PTR_ERR(pwm->clk); + + pwm->clk_enabled = 0; + + pwm->chip.dev = &pdev->dev; + pwm->chip.ops = &pxa_pwm_ops; + pwm->chip.base = -1; + pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); + if (pwm->mmio_base == NULL) + return -EADDRNOTAVAIL; + + ret = pwmchip_add(&pwm->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, pwm); + return 0; +} + +static int __devexit pwm_remove(struct platform_device *pdev) +{ + struct pxa_pwm_chip *chip; + + chip = platform_get_drvdata(pdev); + if (chip == NULL) + return -ENODEV; + + return pwmchip_remove(&chip->chip); +} + +static struct platform_driver pwm_driver = { + .driver = { + .name = "pxa25x-pwm", + .owner = THIS_MODULE, + }, + .probe = pwm_probe, + .remove = __devexit_p(pwm_remove), + .id_table = pwm_id_table, +}; + +static int __init pwm_init(void) +{ + return platform_driver_register(&pwm_driver); +} +arch_initcall(pwm_init); + +static void __exit pwm_exit(void) +{ + platform_driver_unregister(&pwm_driver); +} +module_exit(pwm_exit); + +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/plat-samsung/pwm.c b/drivers/pwm/pwm-samsung.c index d3583050fb0..d10386528c9 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/drivers/pwm/pwm-samsung.c @@ -1,4 +1,4 @@ -/* arch/arm/plat-s3c/pwm.c +/* drivers/pwm/pwm-samsung.c * * Copyright (c) 2007 Ben Dooks * Copyright (c) 2008 Simtec Electronics @@ -11,6 +11,8 @@ * the Free Software Foundation; either version 2 of the License. */ +#define pr_fmt(fmt) "pwm-samsung: " fmt + #include <linux/export.h> #include <linux/kernel.h> #include <linux/platform_device.h> @@ -24,8 +26,7 @@ #include <plat/regs-timer.h> -struct pwm_device { - struct list_head list; +struct s3c_chip { struct platform_device *pdev; struct clk *clk_div; @@ -36,81 +37,36 @@ struct pwm_device { unsigned int duty_ns; unsigned char tcon_base; - unsigned char use_count; unsigned char pwm_id; + struct pwm_chip chip; }; +#define to_s3c_chip(chip) container_of(chip, struct s3c_chip, chip) + #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) static struct clk *clk_scaler[2]; -static inline int pwm_is_tdiv(struct pwm_device *pwm) -{ - return clk_get_parent(pwm->clk) == pwm->clk_div; -} - -static DEFINE_MUTEX(pwm_lock); -static LIST_HEAD(pwm_list); - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int found = 0; - - mutex_lock(&pwm_lock); - - list_for_each_entry(pwm, &pwm_list, list) { - if (pwm->pwm_id == pwm_id) { - found = 1; - break; - } - } - - if (found) { - if (pwm->use_count == 0) { - pwm->use_count = 1; - pwm->label = label; - } else - pwm = ERR_PTR(-EBUSY); - } else - pwm = ERR_PTR(-ENOENT); - - mutex_unlock(&pwm_lock); - return pwm; -} - -EXPORT_SYMBOL(pwm_request); - - -void pwm_free(struct pwm_device *pwm) +static inline int pwm_is_tdiv(struct s3c_chip *chip) { - mutex_lock(&pwm_lock); - - if (pwm->use_count) { - pwm->use_count--; - pwm->label = NULL; - } else - printk(KERN_ERR "PWM%d device already freed\n", pwm->pwm_id); - - mutex_unlock(&pwm_lock); + return clk_get_parent(chip->clk) == chip->clk_div; } -EXPORT_SYMBOL(pwm_free); - #define pwm_tcon_start(pwm) (1 << (pwm->tcon_base + 0)) #define pwm_tcon_invert(pwm) (1 << (pwm->tcon_base + 2)) #define pwm_tcon_autoreload(pwm) (1 << (pwm->tcon_base + 3)) #define pwm_tcon_manulupdate(pwm) (1 << (pwm->tcon_base + 1)) -int pwm_enable(struct pwm_device *pwm) +static int s3c_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { + struct s3c_chip *s3c = to_s3c_chip(chip); unsigned long flags; unsigned long tcon; local_irq_save(flags); tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_start(pwm); + tcon |= pwm_tcon_start(s3c); __raw_writel(tcon, S3C2410_TCON); local_irq_restore(flags); @@ -118,31 +74,28 @@ int pwm_enable(struct pwm_device *pwm) return 0; } -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) +static void s3c_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { + struct s3c_chip *s3c = to_s3c_chip(chip); unsigned long flags; unsigned long tcon; local_irq_save(flags); tcon = __raw_readl(S3C2410_TCON); - tcon &= ~pwm_tcon_start(pwm); + tcon &= ~pwm_tcon_start(s3c); __raw_writel(tcon, S3C2410_TCON); local_irq_restore(flags); } -EXPORT_SYMBOL(pwm_disable); - -static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) +static unsigned long pwm_calc_tin(struct s3c_chip *s3c, unsigned long freq) { unsigned long tin_parent_rate; unsigned int div; - tin_parent_rate = clk_get_rate(clk_get_parent(pwm->clk_div)); - pwm_dbg(pwm, "tin parent at %lu\n", tin_parent_rate); + tin_parent_rate = clk_get_rate(clk_get_parent(s3c->clk_div)); + pwm_dbg(s3c, "tin parent at %lu\n", tin_parent_rate); for (div = 2; div <= 16; div *= 2) { if ((tin_parent_rate / (div << 16)) < freq) @@ -154,8 +107,10 @@ static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) #define NS_IN_HZ (1000000000UL) -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) { + struct s3c_chip *s3c = to_s3c_chip(chip); unsigned long tin_rate; unsigned long tin_ns; unsigned long period; @@ -174,38 +129,38 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) if (duty_ns > period_ns) return -EINVAL; - if (period_ns == pwm->period_ns && - duty_ns == pwm->duty_ns) + if (period_ns == s3c->period_ns && + duty_ns == s3c->duty_ns) return 0; /* The TCMP and TCNT can be read without a lock, they're not * shared between the timers. */ - tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id)); - tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); + tcmp = __raw_readl(S3C2410_TCMPB(s3c->pwm_id)); + tcnt = __raw_readl(S3C2410_TCNTB(s3c->pwm_id)); period = NS_IN_HZ / period_ns; - pwm_dbg(pwm, "duty_ns=%d, period_ns=%d (%lu)\n", + pwm_dbg(s3c, "duty_ns=%d, period_ns=%d (%lu)\n", duty_ns, period_ns, period); /* Check to see if we are changing the clock rate of the PWM */ - if (pwm->period_ns != period_ns) { - if (pwm_is_tdiv(pwm)) { - tin_rate = pwm_calc_tin(pwm, period); - clk_set_rate(pwm->clk_div, tin_rate); + if (s3c->period_ns != period_ns) { + if (pwm_is_tdiv(s3c)) { + tin_rate = pwm_calc_tin(s3c, period); + clk_set_rate(s3c->clk_div, tin_rate); } else - tin_rate = clk_get_rate(pwm->clk); + tin_rate = clk_get_rate(s3c->clk); - pwm->period_ns = period_ns; + s3c->period_ns = period_ns; - pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate); + pwm_dbg(s3c, "tin_rate=%lu\n", tin_rate); tin_ns = NS_IN_HZ / tin_rate; tcnt = period_ns / tin_ns; } else - tin_ns = NS_IN_HZ / clk_get_rate(pwm->clk); + tin_ns = NS_IN_HZ / clk_get_rate(s3c->clk); /* Note, counters count down */ @@ -216,7 +171,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) if (tcmp == tcnt) tcmp--; - pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); + pwm_dbg(s3c, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); if (tcmp < 0) tcmp = 0; @@ -225,15 +180,15 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) local_irq_save(flags); - __raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id)); - __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); + __raw_writel(tcmp, S3C2410_TCMPB(s3c->pwm_id)); + __raw_writel(tcnt, S3C2410_TCNTB(s3c->pwm_id)); tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_manulupdate(pwm); - tcon |= pwm_tcon_autoreload(pwm); + tcon |= pwm_tcon_manulupdate(s3c); + tcon |= pwm_tcon_autoreload(s3c); __raw_writel(tcon, S3C2410_TCON); - tcon &= ~pwm_tcon_manulupdate(pwm); + tcon &= ~pwm_tcon_manulupdate(s3c); __raw_writel(tcon, S3C2410_TCON); local_irq_restore(flags); @@ -241,24 +196,17 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) return 0; } -EXPORT_SYMBOL(pwm_config); - -static int pwm_register(struct pwm_device *pwm) -{ - pwm->duty_ns = -1; - pwm->period_ns = -1; - - mutex_lock(&pwm_lock); - list_add_tail(&pwm->list, &pwm_list); - mutex_unlock(&pwm_lock); - - return 0; -} +static struct pwm_ops s3c_pwm_ops = { + .enable = s3c_pwm_enable, + .disable = s3c_pwm_disable, + .config = s3c_pwm_config, + .owner = THIS_MODULE, +}; static int s3c_pwm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct pwm_device *pwm; + struct s3c_chip *s3c; unsigned long flags; unsigned long tcon; unsigned int id = pdev->id; @@ -269,83 +217,75 @@ static int s3c_pwm_probe(struct platform_device *pdev) return -ENXIO; } - pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); - if (pwm == NULL) { + s3c = devm_kzalloc(&pdev->dev, sizeof(*s3c), GFP_KERNEL); + if (s3c == NULL) { dev_err(dev, "failed to allocate pwm_device\n"); return -ENOMEM; } - pwm->pdev = pdev; - pwm->pwm_id = id; - /* calculate base of control bits in TCON */ - pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4; + s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; + s3c->chip.ops = &s3c_pwm_ops; + s3c->chip.base = -1; + s3c->chip.npwm = 1; - pwm->clk = clk_get(dev, "pwm-tin"); - if (IS_ERR(pwm->clk)) { + s3c->clk = devm_clk_get(dev, "pwm-tin"); + if (IS_ERR(s3c->clk)) { dev_err(dev, "failed to get pwm tin clk\n"); - ret = PTR_ERR(pwm->clk); - goto err_alloc; + return PTR_ERR(s3c->clk); } - pwm->clk_div = clk_get(dev, "pwm-tdiv"); - if (IS_ERR(pwm->clk_div)) { + s3c->clk_div = devm_clk_get(dev, "pwm-tdiv"); + if (IS_ERR(s3c->clk_div)) { dev_err(dev, "failed to get pwm tdiv clk\n"); - ret = PTR_ERR(pwm->clk_div); - goto err_clk_tin; + return PTR_ERR(s3c->clk_div); } - clk_enable(pwm->clk); - clk_enable(pwm->clk_div); + clk_enable(s3c->clk); + clk_enable(s3c->clk_div); local_irq_save(flags); tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_invert(pwm); + tcon |= pwm_tcon_invert(s3c); __raw_writel(tcon, S3C2410_TCON); local_irq_restore(flags); - - ret = pwm_register(pwm); - if (ret) { + ret = pwmchip_add(&s3c->chip); + if (ret < 0) { dev_err(dev, "failed to register pwm\n"); goto err_clk_tdiv; } - pwm_dbg(pwm, "config bits %02x\n", - (__raw_readl(S3C2410_TCON) >> pwm->tcon_base) & 0x0f); + pwm_dbg(s3c, "config bits %02x\n", + (__raw_readl(S3C2410_TCON) >> s3c->tcon_base) & 0x0f); dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n", - clk_get_rate(pwm->clk), - clk_get_rate(pwm->clk_div), - pwm_is_tdiv(pwm) ? "div" : "ext", pwm->tcon_base); + clk_get_rate(s3c->clk), + clk_get_rate(s3c->clk_div), + pwm_is_tdiv(s3c) ? "div" : "ext", s3c->tcon_base); - platform_set_drvdata(pdev, pwm); + platform_set_drvdata(pdev, s3c); return 0; err_clk_tdiv: - clk_disable(pwm->clk_div); - clk_disable(pwm->clk); - clk_put(pwm->clk_div); - - err_clk_tin: - clk_put(pwm->clk); - - err_alloc: - kfree(pwm); + clk_disable(s3c->clk_div); + clk_disable(s3c->clk); return ret; } static int __devexit s3c_pwm_remove(struct platform_device *pdev) { - struct pwm_device *pwm = platform_get_drvdata(pdev); + struct s3c_chip *s3c = platform_get_drvdata(pdev); + int err; + + err = pwmchip_remove(&s3c->chip); + if (err < 0) + return err; - clk_disable(pwm->clk_div); - clk_disable(pwm->clk); - clk_put(pwm->clk_div); - clk_put(pwm->clk); - kfree(pwm); + clk_disable(s3c->clk_div); + clk_disable(s3c->clk); return 0; } @@ -353,26 +293,26 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) { - struct pwm_device *pwm = platform_get_drvdata(pdev); + struct s3c_chip *s3c = platform_get_drvdata(pdev); /* No one preserve these values during suspend so reset them * Otherwise driver leaves PWM unconfigured if same values * passed to pwm_config */ - pwm->period_ns = 0; - pwm->duty_ns = 0; + s3c->period_ns = 0; + s3c->duty_ns = 0; return 0; } static int s3c_pwm_resume(struct platform_device *pdev) { - struct pwm_device *pwm = platform_get_drvdata(pdev); + struct s3c_chip *s3c = platform_get_drvdata(pdev); unsigned long tcon; /* Restore invertion */ tcon = __raw_readl(S3C2410_TCON); - tcon |= pwm_tcon_invert(pwm); + tcon |= pwm_tcon_invert(s3c); __raw_writel(tcon, S3C2410_TCON); return 0; @@ -402,13 +342,13 @@ static int __init pwm_init(void) clk_scaler[1] = clk_get(NULL, "pwm-scaler1"); if (IS_ERR(clk_scaler[0]) || IS_ERR(clk_scaler[1])) { - printk(KERN_ERR "%s: failed to get scaler clocks\n", __func__); + pr_err("failed to get scaler clocks\n"); return -EINVAL; } ret = platform_driver_register(&s3c_pwm_driver); if (ret) - printk(KERN_ERR "%s: failed to add pwm driver\n", __func__); + pr_err("failed to add pwm driver\n"); return ret; } diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c new file mode 100644 index 00000000000..02ce18d5e49 --- /dev/null +++ b/drivers/pwm/pwm-tegra.c @@ -0,0 +1,261 @@ +/* + * drivers/pwm/pwm-tegra.c + * + * Tegra pulse-width-modulation controller driver + * + * Copyright (c) 2010, NVIDIA Corporation. + * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/pwm.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define PWM_ENABLE (1 << 31) +#define PWM_DUTY_WIDTH 8 +#define PWM_DUTY_SHIFT 16 +#define PWM_SCALE_WIDTH 13 +#define PWM_SCALE_SHIFT 0 + +#define NUM_PWM 4 + +struct tegra_pwm_chip { + struct pwm_chip chip; + struct device *dev; + + struct clk *clk; + + void __iomem *mmio_base; +}; + +static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct tegra_pwm_chip, chip); +} + +static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num) +{ + return readl(chip->mmio_base + (num << 4)); +} + +static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num, + unsigned long val) +{ + writel(val, chip->mmio_base + (num << 4)); +} + +static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); + unsigned long long c; + unsigned long rate, hz; + u32 val = 0; + int err; + + /* + * Convert from duty_ns / period_ns to a fixed number of duty ticks + * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the + * nearest integer during division. + */ + c = duty_ns * ((1 << PWM_DUTY_WIDTH) - 1) + period_ns / 2; + do_div(c, period_ns); + + val = (u32)c << PWM_DUTY_SHIFT; + + /* + * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH) + * cycles at the PWM clock rate will take period_ns nanoseconds. + */ + rate = clk_get_rate(pc->clk) >> PWM_DUTY_WIDTH; + hz = 1000000000ul / period_ns; + + rate = (rate + (hz / 2)) / hz; + + /* + * Since the actual PWM divider is the register's frequency divider + * field minus 1, we need to decrement to get the correct value to + * write to the register. + */ + if (rate > 0) + rate--; + + /* + * Make sure that the rate will fit in the register's frequency + * divider field. + */ + if (rate >> PWM_SCALE_WIDTH) + return -EINVAL; + + val |= rate << PWM_SCALE_SHIFT; + + /* + * If the PWM channel is disabled, make sure to turn on the clock + * before writing the register. Otherwise, keep it enabled. + */ + if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + err = clk_prepare_enable(pc->clk); + if (err < 0) + return err; + } else + val |= PWM_ENABLE; + + pwm_writel(pc, pwm->hwpwm, val); + + /* + * If the PWM is not enabled, turn the clock off again to save power. + */ + if (!test_bit(PWMF_ENABLED, &pwm->flags)) + clk_disable_unprepare(pc->clk); + + return 0; +} + +static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); + int rc = 0; + u32 val; + + rc = clk_prepare_enable(pc->clk); + if (rc < 0) + return rc; + + val = pwm_readl(pc, pwm->hwpwm); + val |= PWM_ENABLE; + pwm_writel(pc, pwm->hwpwm, val); + + return 0; +} + +static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip); + u32 val; + + val = pwm_readl(pc, pwm->hwpwm); + val &= ~PWM_ENABLE; + pwm_writel(pc, pwm->hwpwm, val); + + clk_disable_unprepare(pc->clk); +} + +static const struct pwm_ops tegra_pwm_ops = { + .config = tegra_pwm_config, + .enable = tegra_pwm_enable, + .disable = tegra_pwm_disable, + .owner = THIS_MODULE, +}; + +static int tegra_pwm_probe(struct platform_device *pdev) +{ + struct tegra_pwm_chip *pwm; + struct resource *r; + int ret; + + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + pwm->dev = &pdev->dev; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resources defined\n"); + return -ENODEV; + } + + pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); + if (!pwm->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() region\n"); + return -EADDRNOTAVAIL; + } + + platform_set_drvdata(pdev, pwm); + + pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pwm->clk)) + return PTR_ERR(pwm->clk); + + pwm->chip.dev = &pdev->dev; + pwm->chip.ops = &tegra_pwm_ops; + pwm->chip.base = -1; + pwm->chip.npwm = NUM_PWM; + + ret = pwmchip_add(&pwm->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int __devexit tegra_pwm_remove(struct platform_device *pdev) +{ + struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); + int i; + + if (WARN_ON(!pc)) + return -ENODEV; + + for (i = 0; i < NUM_PWM; i++) { + struct pwm_device *pwm = &pc->chip.pwms[i]; + + if (!test_bit(PWMF_ENABLED, &pwm->flags)) + if (clk_prepare_enable(pc->clk) < 0) + continue; + + pwm_writel(pc, i, 0); + + clk_disable_unprepare(pc->clk); + } + + return pwmchip_remove(&pc->chip); +} + +#ifdef CONFIG_OF +static struct of_device_id tegra_pwm_of_match[] = { + { .compatible = "nvidia,tegra20-pwm" }, + { .compatible = "nvidia,tegra30-pwm" }, + { } +}; + +MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); +#endif + +static struct platform_driver tegra_pwm_driver = { + .driver = { + .name = "tegra-pwm", + .of_match_table = of_match_ptr(tegra_pwm_of_match), + }, + .probe = tegra_pwm_probe, + .remove = __devexit_p(tegra_pwm_remove), +}; + +module_platform_driver(tegra_pwm_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("NVIDIA Corporation"); +MODULE_ALIAS("platform:tegra-pwm"); diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c new file mode 100644 index 00000000000..3c2ad284ee3 --- /dev/null +++ b/drivers/pwm/pwm-tiecap.c @@ -0,0 +1,232 @@ +/* + * ECAP PWM driver + * + * Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/pm_runtime.h> +#include <linux/pwm.h> + +/* ECAP registers and bits definitions */ +#define CAP1 0x08 +#define CAP2 0x0C +#define CAP3 0x10 +#define CAP4 0x14 +#define ECCTL2 0x2A +#define ECCTL2_APWM_MODE BIT(9) +#define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6)) +#define ECCTL2_TSCTR_FREERUN BIT(4) + +struct ecap_pwm_chip { + struct pwm_chip chip; + unsigned int clk_rate; + void __iomem *mmio_base; +}; + +static inline struct ecap_pwm_chip *to_ecap_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct ecap_pwm_chip, chip); +} + +/* + * period_ns = 10^9 * period_cycles / PWM_CLK_RATE + * duty_ns = 10^9 * duty_cycles / PWM_CLK_RATE + */ +static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); + unsigned long long c; + unsigned long period_cycles, duty_cycles; + unsigned int reg_val; + + if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) + return -ERANGE; + + c = pc->clk_rate; + c = c * period_ns; + do_div(c, NSEC_PER_SEC); + period_cycles = (unsigned long)c; + + if (period_cycles < 1) { + period_cycles = 1; + duty_cycles = 1; + } else { + c = pc->clk_rate; + c = c * duty_ns; + do_div(c, NSEC_PER_SEC); + duty_cycles = (unsigned long)c; + } + + pm_runtime_get_sync(pc->chip.dev); + + reg_val = readw(pc->mmio_base + ECCTL2); + + /* Configure APWM mode & disable sync option */ + reg_val |= ECCTL2_APWM_MODE | ECCTL2_SYNC_SEL_DISA; + + writew(reg_val, pc->mmio_base + ECCTL2); + + if (!test_bit(PWMF_ENABLED, &pwm->flags)) { + /* Update active registers if not running */ + writel(duty_cycles, pc->mmio_base + CAP2); + writel(period_cycles, pc->mmio_base + CAP1); + } else { + /* + * Update shadow registers to configure period and + * compare values. This helps current PWM period to + * complete on reconfiguring + */ + writel(duty_cycles, pc->mmio_base + CAP4); + writel(period_cycles, pc->mmio_base + CAP3); + } + + pm_runtime_put_sync(pc->chip.dev); + return 0; +} + +static int ecap_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); + unsigned int reg_val; + + /* Leave clock enabled on enabling PWM */ + pm_runtime_get_sync(pc->chip.dev); + + /* + * Enable 'Free run Time stamp counter mode' to start counter + * and 'APWM mode' to enable APWM output + */ + reg_val = readw(pc->mmio_base + ECCTL2); + reg_val |= ECCTL2_TSCTR_FREERUN | ECCTL2_APWM_MODE; + writew(reg_val, pc->mmio_base + ECCTL2); + return 0; +} + +static void ecap_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ecap_pwm_chip *pc = to_ecap_pwm_chip(chip); + unsigned int reg_val; + + /* + * Disable 'Free run Time stamp counter mode' to stop counter + * and 'APWM mode' to put APWM output to low + */ + reg_val = readw(pc->mmio_base + ECCTL2); + reg_val &= ~(ECCTL2_TSCTR_FREERUN | ECCTL2_APWM_MODE); + writew(reg_val, pc->mmio_base + ECCTL2); + + /* Disable clock on PWM disable */ + pm_runtime_put_sync(pc->chip.dev); +} + +static void ecap_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + if (test_bit(PWMF_ENABLED, &pwm->flags)) { + dev_warn(chip->dev, "Removing PWM device without disabling\n"); + pm_runtime_put_sync(chip->dev); + } +} + +static const struct pwm_ops ecap_pwm_ops = { + .free = ecap_pwm_free, + .config = ecap_pwm_config, + .enable = ecap_pwm_enable, + .disable = ecap_pwm_disable, + .owner = THIS_MODULE, +}; + +static int __devinit ecap_pwm_probe(struct platform_device *pdev) +{ + int ret; + struct resource *r; + struct clk *clk; + struct ecap_pwm_chip *pc; + + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + clk = devm_clk_get(&pdev->dev, "fck"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); + return PTR_ERR(clk); + } + + pc->clk_rate = clk_get_rate(clk); + if (!pc->clk_rate) { + dev_err(&pdev->dev, "failed to get clock rate\n"); + return -EINVAL; + } + + pc->chip.dev = &pdev->dev; + pc->chip.ops = &ecap_pwm_ops; + pc->chip.base = -1; + pc->chip.npwm = 1; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); + if (!pc->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + return -EADDRNOTAVAIL; + } + + ret = pwmchip_add(&pc->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } + + pm_runtime_enable(&pdev->dev); + platform_set_drvdata(pdev, pc); + return 0; +} + +static int __devexit ecap_pwm_remove(struct platform_device *pdev) +{ + struct ecap_pwm_chip *pc = platform_get_drvdata(pdev); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return pwmchip_remove(&pc->chip); +} + +static struct platform_driver ecap_pwm_driver = { + .driver = { + .name = "ecap", + }, + .probe = ecap_pwm_probe, + .remove = __devexit_p(ecap_pwm_remove), +}; + +module_platform_driver(ecap_pwm_driver); + +MODULE_DESCRIPTION("ECAP PWM driver"); +MODULE_AUTHOR("Texas Instruments"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c new file mode 100644 index 00000000000..010d232cb0c --- /dev/null +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -0,0 +1,411 @@ +/* + * EHRPWM PWM driver + * + * Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.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. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/io.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/pm_runtime.h> + +/* EHRPWM registers and bits definitions */ + +/* Time base module registers */ +#define TBCTL 0x00 +#define TBPRD 0x0A + +#define TBCTL_RUN_MASK (BIT(15) | BIT(14)) +#define TBCTL_STOP_NEXT 0 +#define TBCTL_STOP_ON_CYCLE BIT(14) +#define TBCTL_FREE_RUN (BIT(15) | BIT(14)) +#define TBCTL_PRDLD_MASK BIT(3) +#define TBCTL_PRDLD_SHDW 0 +#define TBCTL_PRDLD_IMDT BIT(3) +#define TBCTL_CLKDIV_MASK (BIT(12) | BIT(11) | BIT(10) | BIT(9) | \ + BIT(8) | BIT(7)) +#define TBCTL_CTRMODE_MASK (BIT(1) | BIT(0)) +#define TBCTL_CTRMODE_UP 0 +#define TBCTL_CTRMODE_DOWN BIT(0) +#define TBCTL_CTRMODE_UPDOWN BIT(1) +#define TBCTL_CTRMODE_FREEZE (BIT(1) | BIT(0)) + +#define TBCTL_HSPCLKDIV_SHIFT 7 +#define TBCTL_CLKDIV_SHIFT 10 + +#define CLKDIV_MAX 7 +#define HSPCLKDIV_MAX 7 +#define PERIOD_MAX 0xFFFF + +/* compare module registers */ +#define CMPA 0x12 +#define CMPB 0x14 + +/* Action qualifier module registers */ +#define AQCTLA 0x16 +#define AQCTLB 0x18 +#define AQSFRC 0x1A +#define AQCSFRC 0x1C + +#define AQCTL_CBU_MASK (BIT(9) | BIT(8)) +#define AQCTL_CBU_FRCLOW BIT(8) +#define AQCTL_CBU_FRCHIGH BIT(9) +#define AQCTL_CBU_FRCTOGGLE (BIT(9) | BIT(8)) +#define AQCTL_CAU_MASK (BIT(5) | BIT(4)) +#define AQCTL_CAU_FRCLOW BIT(4) +#define AQCTL_CAU_FRCHIGH BIT(5) +#define AQCTL_CAU_FRCTOGGLE (BIT(5) | BIT(4)) +#define AQCTL_PRD_MASK (BIT(3) | BIT(2)) +#define AQCTL_PRD_FRCLOW BIT(2) +#define AQCTL_PRD_FRCHIGH BIT(3) +#define AQCTL_PRD_FRCTOGGLE (BIT(3) | BIT(2)) +#define AQCTL_ZRO_MASK (BIT(1) | BIT(0)) +#define AQCTL_ZRO_FRCLOW BIT(0) +#define AQCTL_ZRO_FRCHIGH BIT(1) +#define AQCTL_ZRO_FRCTOGGLE (BIT(1) | BIT(0)) + +#define AQSFRC_RLDCSF_MASK (BIT(7) | BIT(6)) +#define AQSFRC_RLDCSF_ZRO 0 +#define AQSFRC_RLDCSF_PRD BIT(6) +#define AQSFRC_RLDCSF_ZROPRD BIT(7) +#define AQSFRC_RLDCSF_IMDT (BIT(7) | BIT(6)) + +#define AQCSFRC_CSFB_MASK (BIT(3) | BIT(2)) +#define AQCSFRC_CSFB_FRCDIS 0 +#define AQCSFRC_CSFB_FRCLOW BIT(2) +#define AQCSFRC_CSFB_FRCHIGH BIT(3) +#define AQCSFRC_CSFB_DISSWFRC (BIT(3) | BIT(2)) +#define AQCSFRC_CSFA_MASK (BIT(1) | BIT(0)) +#define AQCSFRC_CSFA_FRCDIS 0 +#define AQCSFRC_CSFA_FRCLOW BIT(0) +#define AQCSFRC_CSFA_FRCHIGH BIT(1) +#define AQCSFRC_CSFA_DISSWFRC (BIT(1) | BIT(0)) + +#define NUM_PWM_CHANNEL 2 /* EHRPWM channels */ + +struct ehrpwm_pwm_chip { + struct pwm_chip chip; + unsigned int clk_rate; + void __iomem *mmio_base; +}; + +static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct ehrpwm_pwm_chip, chip); +} + +static void ehrpwm_write(void *base, int offset, unsigned int val) +{ + writew(val & 0xFFFF, base + offset); +} + +static void ehrpwm_modify(void *base, int offset, + unsigned short mask, unsigned short val) +{ + unsigned short regval; + + regval = readw(base + offset); + regval &= ~mask; + regval |= val & mask; + writew(regval, base + offset); +} + +/** + * set_prescale_div - Set up the prescaler divider function + * @rqst_prescaler: prescaler value min + * @prescale_div: prescaler value set + * @tb_clk_div: Time Base Control prescaler bits + */ +static int set_prescale_div(unsigned long rqst_prescaler, + unsigned short *prescale_div, unsigned short *tb_clk_div) +{ + unsigned int clkdiv, hspclkdiv; + + for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) { + for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) { + + /* + * calculations for prescaler value : + * prescale_div = HSPCLKDIVIDER * CLKDIVIDER. + * HSPCLKDIVIDER = 2 ** hspclkdiv + * CLKDIVIDER = (1), if clkdiv == 0 *OR* + * (2 * clkdiv), if clkdiv != 0 + * + * Configure prescale_div value such that period + * register value is less than 65535. + */ + + *prescale_div = (1 << clkdiv) * + (hspclkdiv ? (hspclkdiv * 2) : 1); + if (*prescale_div > rqst_prescaler) { + *tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) | + (hspclkdiv << TBCTL_HSPCLKDIV_SHIFT); + return 0; + } + } + } + return 1; +} + +static void configure_chans(struct ehrpwm_pwm_chip *pc, int chan, + unsigned long duty_cycles) +{ + int cmp_reg, aqctl_reg; + unsigned short aqctl_val, aqctl_mask; + + /* + * Channels can be configured from action qualifier module. + * Channel 0 configured with compare A register and for + * up-counter mode. + * Channel 1 configured with compare B register and for + * up-counter mode. + */ + if (chan == 1) { + aqctl_reg = AQCTLB; + cmp_reg = CMPB; + /* Configure PWM Low from compare B value */ + aqctl_val = AQCTL_CBU_FRCLOW; + aqctl_mask = AQCTL_CBU_MASK; + } else { + cmp_reg = CMPA; + aqctl_reg = AQCTLA; + /* Configure PWM Low from compare A value*/ + aqctl_val = AQCTL_CAU_FRCLOW; + aqctl_mask = AQCTL_CAU_MASK; + } + + /* Configure PWM High from period value and zero value */ + aqctl_val |= AQCTL_PRD_FRCHIGH | AQCTL_ZRO_FRCHIGH; + aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK; + ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val); + + ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles); +} + +/* + * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE + * duty_ns = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE + */ +static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + unsigned long long c; + unsigned long period_cycles, duty_cycles; + unsigned short ps_divval, tb_divval; + + if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC) + return -ERANGE; + + c = pc->clk_rate; + c = c * period_ns; + do_div(c, NSEC_PER_SEC); + period_cycles = (unsigned long)c; + + if (period_cycles < 1) { + period_cycles = 1; + duty_cycles = 1; + } else { + c = pc->clk_rate; + c = c * duty_ns; + do_div(c, NSEC_PER_SEC); + duty_cycles = (unsigned long)c; + } + + /* Configure clock prescaler to support Low frequency PWM wave */ + if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval, + &tb_divval)) { + dev_err(chip->dev, "Unsupported values\n"); + return -EINVAL; + } + + pm_runtime_get_sync(chip->dev); + + /* Update clock prescaler values */ + ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval); + + /* Update period & duty cycle with presacler division */ + period_cycles = period_cycles / ps_divval; + duty_cycles = duty_cycles / ps_divval; + + /* Configure shadow loading on Period register */ + ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW); + + ehrpwm_write(pc->mmio_base, TBPRD, period_cycles); + + /* Configure ehrpwm counter for up-count mode */ + ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK, + TBCTL_CTRMODE_UP); + + /* Configure the channel for duty cycle */ + configure_chans(pc, pwm->hwpwm, duty_cycles); + pm_runtime_put_sync(chip->dev); + return 0; +} + +static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + unsigned short aqcsfrc_val, aqcsfrc_mask; + + /* Leave clock enabled on enabling PWM */ + pm_runtime_get_sync(chip->dev); + + /* Disabling Action Qualifier on PWM output */ + if (pwm->hwpwm) { + aqcsfrc_val = AQCSFRC_CSFB_FRCDIS; + aqcsfrc_mask = AQCSFRC_CSFB_MASK; + } else { + aqcsfrc_val = AQCSFRC_CSFA_FRCDIS; + aqcsfrc_mask = AQCSFRC_CSFA_MASK; + } + + /* Changes to shadow mode */ + ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, + AQSFRC_RLDCSF_ZRO); + + ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); + + /* Enable time counter for free_run */ + ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN); + return 0; +} + +static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip); + unsigned short aqcsfrc_val, aqcsfrc_mask; + + /* Action Qualifier puts PWM output low forcefully */ + if (pwm->hwpwm) { + aqcsfrc_val = AQCSFRC_CSFB_FRCLOW; + aqcsfrc_mask = AQCSFRC_CSFB_MASK; + } else { + aqcsfrc_val = AQCSFRC_CSFA_FRCLOW; + aqcsfrc_mask = AQCSFRC_CSFA_MASK; + } + + /* + * Changes to immediate action on Action Qualifier. This puts + * Action Qualifier control on PWM output from next TBCLK + */ + ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, + AQSFRC_RLDCSF_IMDT); + + ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); + + /* Stop Time base counter */ + ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT); + + /* Disable clock on PWM disable */ + pm_runtime_put_sync(chip->dev); +} + +static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) +{ + if (test_bit(PWMF_ENABLED, &pwm->flags)) { + dev_warn(chip->dev, "Removing PWM device without disabling\n"); + pm_runtime_put_sync(chip->dev); + } +} + +static const struct pwm_ops ehrpwm_pwm_ops = { + .free = ehrpwm_pwm_free, + .config = ehrpwm_pwm_config, + .enable = ehrpwm_pwm_enable, + .disable = ehrpwm_pwm_disable, + .owner = THIS_MODULE, +}; + +static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev) +{ + int ret; + struct resource *r; + struct clk *clk; + struct ehrpwm_pwm_chip *pc; + + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + clk = devm_clk_get(&pdev->dev, "fck"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); + return PTR_ERR(clk); + } + + pc->clk_rate = clk_get_rate(clk); + if (!pc->clk_rate) { + dev_err(&pdev->dev, "failed to get clock rate\n"); + return -EINVAL; + } + + pc->chip.dev = &pdev->dev; + pc->chip.ops = &ehrpwm_pwm_ops; + pc->chip.base = -1; + pc->chip.npwm = NUM_PWM_CHANNEL; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); + if (!pc->mmio_base) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + return -EADDRNOTAVAIL; + } + + ret = pwmchip_add(&pc->chip); + if (ret < 0) { + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); + return ret; + } + + pm_runtime_enable(&pdev->dev); + platform_set_drvdata(pdev, pc); + return 0; +} + +static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev) +{ + struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + return pwmchip_remove(&pc->chip); +} + +static struct platform_driver ehrpwm_pwm_driver = { + .driver = { + .name = "ehrpwm", + }, + .probe = ehrpwm_pwm_probe, + .remove = __devexit_p(ehrpwm_pwm_remove), +}; + +module_platform_driver(ehrpwm_pwm_driver); + +MODULE_DESCRIPTION("EHRPWM PWM driver"); +MODULE_AUTHOR("Texas Instruments"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c new file mode 100644 index 00000000000..548021439f0 --- /dev/null +++ b/drivers/pwm/pwm-vt8500.c @@ -0,0 +1,177 @@ +/* + * drivers/pwm/pwm-vt8500.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/pwm.h> +#include <linux/delay.h> + +#include <asm/div64.h> + +#define VT8500_NR_PWMS 4 + +struct vt8500_chip { + struct pwm_chip chip; + void __iomem *base; +}; + +#define to_vt8500_chip(chip) container_of(chip, struct vt8500_chip, chip) + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) +static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) +{ + int loops = msecs_to_loops(10); + while ((readb(reg) & bitmask) && --loops) + cpu_relax(); + + if (unlikely(!loops)) + pr_warning("Waiting for status bits 0x%x to clear timed out\n", + bitmask); +} + +static int vt8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct vt8500_chip *vt8500 = to_vt8500_chip(chip); + unsigned long long c; + unsigned long period_cycles, prescale, pv, dc; + + c = 25000000/2; /* wild guess --- need to implement clocks */ + c = c * period_ns; + do_div(c, 1000000000); + period_cycles = c; + + if (period_cycles < 1) + period_cycles = 1; + prescale = (period_cycles - 1) / 4096; + pv = period_cycles / (prescale + 1) - 1; + if (pv > 4095) + pv = 4095; + + if (prescale > 1023) + return -EINVAL; + + c = (unsigned long long)pv * duty_ns; + do_div(c, period_ns); + dc = c; + + pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 1)); + writel(prescale, vt8500->base + 0x4 + (pwm->hwpwm << 4)); + + pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 2)); + writel(pv, vt8500->base + 0x8 + (pwm->hwpwm << 4)); + + pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 3)); + writel(dc, vt8500->base + 0xc + (pwm->hwpwm << 4)); + + return 0; +} + +static int vt8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct vt8500_chip *vt8500 = to_vt8500_chip(chip); + + pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); + writel(5, vt8500->base + (pwm->hwpwm << 4)); + return 0; +} + +static void vt8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct vt8500_chip *vt8500 = to_vt8500_chip(chip); + + pwm_busy_wait(vt8500->base + 0x40 + pwm->hwpwm, (1 << 0)); + writel(0, vt8500->base + (pwm->hwpwm << 4)); +} + +static struct pwm_ops vt8500_pwm_ops = { + .enable = vt8500_pwm_enable, + .disable = vt8500_pwm_disable, + .config = vt8500_pwm_config, + .owner = THIS_MODULE, +}; + +static int __devinit pwm_probe(struct platform_device *pdev) +{ + struct vt8500_chip *chip; + struct resource *r; + int ret; + + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (chip == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + chip->chip.dev = &pdev->dev; + chip->chip.ops = &vt8500_pwm_ops; + chip->chip.base = -1; + chip->chip.npwm = VT8500_NR_PWMS; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + + chip->base = devm_request_and_ioremap(&pdev->dev, r); + if (chip->base == NULL) + return -EADDRNOTAVAIL; + + ret = pwmchip_add(&chip->chip); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, chip); + return ret; +} + +static int __devexit pwm_remove(struct platform_device *pdev) +{ + struct vt8500_chip *chip; + + chip = platform_get_drvdata(pdev); + if (chip == NULL) + return -ENODEV; + + return pwmchip_remove(&chip->chip); +} + +static struct platform_driver pwm_driver = { + .driver = { + .name = "vt8500-pwm", + .owner = THIS_MODULE, + }, + .probe = pwm_probe, + .remove = __devexit_p(pwm_remove), +}; + +static int __init pwm_init(void) +{ + return platform_driver_register(&pwm_driver); +} +arch_initcall(pwm_init); + +static void __exit pwm_exit(void) +{ + platform_driver_unregister(&pwm_driver); +} +module_exit(pwm_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f34c3be6c9f..4e932cc695e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -272,7 +272,7 @@ config REGULATOR_S2MPS11 config REGULATOR_S5M8767 tristate "Samsung S5M8767A voltage regulator" - depends on MFD_S5M_CORE + depends on MFD_SEC_CORE help This driver supports a Samsung S5M8767A voltage output regulator via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 13d424fc1c1..10f2f4d4d19 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -848,18 +848,12 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id ab8500_regulator_match[] = { - { .compatible = "stericsson,ab8500-regulator", }, - {} -}; - static struct platform_driver ab8500_regulator_driver = { .probe = ab8500_regulator_probe, .remove = __devexit_p(ab8500_regulator_remove), .driver = { .name = "ab8500-regulator", .owner = THIS_MODULE, - .of_match_table = ab8500_regulator_match, }, }; diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 9dbb491b6ef..359f8d18fc3 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -547,16 +547,10 @@ static int __exit db8500_regulator_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id db8500_prcmu_regulator_match[] = { - { .compatible = "stericsson,db8500-prcmu-regulator", }, - {} -}; - static struct platform_driver db8500_regulator_driver = { .driver = { .name = "db8500-prcmu-regulators", .owner = THIS_MODULE, - .of_match_table = db8500_prcmu_regulator_match, }, .probe = db8500_regulator_probe, .remove = __exit_p(db8500_regulator_remove), diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 102287fa7ec..5a0d18a7aa2 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -19,15 +19,15 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> -#include <linux/mfd/s5m87xx/s5m-core.h> -#include <linux/mfd/s5m87xx/s5m-pmic.h> +#include <linux/mfd/samsung/core.h> +#include <linux/mfd/samsung/s5m8767.h> struct s5m8767_info { struct device *dev; - struct s5m87xx_dev *iodev; + struct sec_pmic_dev *iodev; int num_regulators; struct regulator_dev **rdev; - struct s5m_opmode_data *opmode; + struct sec_opmode_data *opmode; int ramp_delay; bool buck2_ramp; @@ -45,43 +45,43 @@ struct s5m8767_info { int buck_gpioindex; }; -struct s5m_voltage_desc { +struct sec_voltage_desc { int max; int min; int step; }; -static const struct s5m_voltage_desc buck_voltage_val1 = { +static const struct sec_voltage_desc buck_voltage_val1 = { .max = 2225000, .min = 650000, .step = 6250, }; -static const struct s5m_voltage_desc buck_voltage_val2 = { +static const struct sec_voltage_desc buck_voltage_val2 = { .max = 1600000, .min = 600000, .step = 6250, }; -static const struct s5m_voltage_desc buck_voltage_val3 = { +static const struct sec_voltage_desc buck_voltage_val3 = { .max = 3000000, .min = 750000, .step = 12500, }; -static const struct s5m_voltage_desc ldo_voltage_val1 = { +static const struct sec_voltage_desc ldo_voltage_val1 = { .max = 3950000, .min = 800000, .step = 50000, }; -static const struct s5m_voltage_desc ldo_voltage_val2 = { +static const struct sec_voltage_desc ldo_voltage_val2 = { .max = 2375000, .min = 800000, .step = 25000, }; -static const struct s5m_voltage_desc *reg_voltage_map[] = { +static const struct sec_voltage_desc *reg_voltage_map[] = { [S5M8767_LDO1] = &ldo_voltage_val2, [S5M8767_LDO2] = &ldo_voltage_val2, [S5M8767_LDO3] = &ldo_voltage_val1, @@ -213,7 +213,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) else if (ret) return ret; - ret = s5m_reg_read(s5m8767->iodev, reg, &val); + ret = sec_reg_read(s5m8767->iodev, reg, &val); if (ret) return ret; @@ -230,7 +230,7 @@ static int s5m8767_reg_enable(struct regulator_dev *rdev) if (ret) return ret; - return s5m_reg_update(s5m8767->iodev, reg, enable_ctrl, mask); + return sec_reg_update(s5m8767->iodev, reg, enable_ctrl, mask); } static int s5m8767_reg_disable(struct regulator_dev *rdev) @@ -243,7 +243,7 @@ static int s5m8767_reg_disable(struct regulator_dev *rdev) if (ret) return ret; - return s5m_reg_update(s5m8767->iodev, reg, ~mask, mask); + return sec_reg_update(s5m8767->iodev, reg, ~mask, mask); } static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) @@ -305,7 +305,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) mask = (reg_id < S5M8767_BUCK1) ? 0x3f : 0xff; - ret = s5m_reg_read(s5m8767->iodev, reg, &val); + ret = sec_reg_read(s5m8767->iodev, reg, &val); if (ret) return ret; @@ -315,7 +315,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) } static int s5m8767_convert_voltage_to_sel( - const struct s5m_voltage_desc *desc, + const struct sec_voltage_desc *desc, int min_vol, int max_vol) { int selector = 0; @@ -407,7 +407,7 @@ static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, if (ret) return ret; - return s5m_reg_update(s5m8767->iodev, reg, selector, mask); + return sec_reg_update(s5m8767->iodev, reg, selector, mask); } } @@ -416,7 +416,7 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int new_sel) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); - const struct s5m_voltage_desc *desc; + const struct sec_voltage_desc *desc; int reg_id = rdev_get_id(rdev); desc = reg_voltage_map[reg_id]; @@ -501,8 +501,8 @@ static struct regulator_desc regulators[] = { static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) { - struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct s5m_platform_data *pdata = dev_get_platdata(iodev->dev); + struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); struct regulator_config config = { }; struct regulator_dev **rdev; struct s5m8767_info *s5m8767; @@ -671,13 +671,13 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, + sec_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, + sec_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); - s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, + sec_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); } @@ -685,61 +685,61 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) /* Initialize GPIO DVS registers */ for (i = 0; i < 8; i++) { if (s5m8767->buck2_gpiodvs) { - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS1 + i, + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS1 + i, s5m8767->buck2_vol[i]); } if (s5m8767->buck3_gpiodvs) { - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS1 + i, + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS1 + i, s5m8767->buck3_vol[i]); } if (s5m8767->buck4_gpiodvs) { - s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS1 + i, + sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS1 + i, s5m8767->buck4_vol[i]); } } if (s5m8767->buck2_ramp) - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08); + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08); if (s5m8767->buck3_ramp) - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x04, 0x04); + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x04, 0x04); if (s5m8767->buck4_ramp) - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x02, 0x02); + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x02, 0x02); if (s5m8767->buck2_ramp || s5m8767->buck3_ramp || s5m8767->buck4_ramp) { switch (s5m8767->ramp_delay) { case 5: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x40, 0xf0); break; case 10: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x90, 0xf0); break; case 25: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xd0, 0xf0); break; case 50: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xe0, 0xf0); break; case 100: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xf0, 0xf0); break; default: - s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + sec_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x90, 0xf0); } } for (i = 0; i < pdata->num_regulators; i++) { - const struct s5m_voltage_desc *desc; + const struct sec_voltage_desc *desc; int id = pdata->regulators[i].id; desc = reg_voltage_map[id]; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 668da5922d9..fabc99a75c6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -135,6 +135,16 @@ config RTC_DRV_88PM860X This driver can also be built as a module. If so, the module will be called rtc-88pm860x. +config RTC_DRV_88PM80X + tristate "Marvell 88PM80x" + depends on RTC_CLASS && I2C && MFD_88PM800 + help + If you say yes here you get support for RTC function in Marvell + 88PM80x chips. + + This driver can also be built as a module. If so, the module + will be called rtc-88pm80x. + config RTC_DRV_DS1307 tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 2973921c30d..0d5b2b66f90 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,6 +16,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o # Keep the list ordered. obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o +obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c new file mode 100644 index 00000000000..a2f956d90de --- /dev/null +++ b/drivers/rtc/rtc-88pm80x.c @@ -0,0 +1,371 @@ +/* + * Real Time Clock driver for Marvell 88PM80x PMIC + * + * Copyright (c) 2012 Marvell International Ltd. + * Wenzeng Chen<wzch@marvell.com> + * Qiao Zhou <zhouqiao@marvell.com> + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * 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/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/regmap.h> +#include <linux/mfd/core.h> +#include <linux/mfd/88pm80x.h> +#include <linux/rtc.h> + +#define PM800_RTC_COUNTER1 (0xD1) +#define PM800_RTC_COUNTER2 (0xD2) +#define PM800_RTC_COUNTER3 (0xD3) +#define PM800_RTC_COUNTER4 (0xD4) +#define PM800_RTC_EXPIRE1_1 (0xD5) +#define PM800_RTC_EXPIRE1_2 (0xD6) +#define PM800_RTC_EXPIRE1_3 (0xD7) +#define PM800_RTC_EXPIRE1_4 (0xD8) +#define PM800_RTC_TRIM1 (0xD9) +#define PM800_RTC_TRIM2 (0xDA) +#define PM800_RTC_TRIM3 (0xDB) +#define PM800_RTC_TRIM4 (0xDC) +#define PM800_RTC_EXPIRE2_1 (0xDD) +#define PM800_RTC_EXPIRE2_2 (0xDE) +#define PM800_RTC_EXPIRE2_3 (0xDF) +#define PM800_RTC_EXPIRE2_4 (0xE0) + +#define PM800_POWER_DOWN_LOG1 (0xE5) +#define PM800_POWER_DOWN_LOG2 (0xE6) + +struct pm80x_rtc_info { + struct pm80x_chip *chip; + struct regmap *map; + struct rtc_device *rtc_dev; + struct device *dev; + struct delayed_work calib_work; + + int irq; + int vrtc; +}; + +static irqreturn_t rtc_update_handler(int irq, void *data) +{ + struct pm80x_rtc_info *info = (struct pm80x_rtc_info *)data; + int mask; + + mask = PM800_ALARM | PM800_ALARM_WAKEUP; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask | PM800_ALARM1_EN, + mask); + rtc_update_irq(info->rtc_dev, 1, RTC_AF); + return IRQ_HANDLED; +} + +static int pm80x_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + + if (enabled) + regmap_update_bits(info->map, PM800_RTC_CONTROL, + PM800_ALARM1_EN, PM800_ALARM1_EN); + else + regmap_update_bits(info->map, PM800_RTC_CONTROL, + PM800_ALARM1_EN, 0); + return 0; +} + +/* + * Calculate the next alarm time given the requested alarm time mask + * and the current time. + */ +static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, + struct rtc_time *alrm) +{ + unsigned long next_time; + unsigned long now_time; + + next->tm_year = now->tm_year; + next->tm_mon = now->tm_mon; + next->tm_mday = now->tm_mday; + next->tm_hour = alrm->tm_hour; + next->tm_min = alrm->tm_min; + next->tm_sec = alrm->tm_sec; + + rtc_tm_to_time(now, &now_time); + rtc_tm_to_time(next, &next_time); + + if (next_time < now_time) { + /* Advance one day */ + next_time += 60 * 60 * 24; + rtc_time_to_tm(next_time, next); + } +} + +static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + rtc_time_to_tm(ticks, tm); + return 0; +} + +static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + if ((tm->tm_year < 70) || (tm->tm_year > 138)) { + dev_dbg(info->dev, + "Set time %d out of range. Please set time between 1970 to 2038.\n", + 1900 + tm->tm_year); + return -EINVAL; + } + rtc_tm_to_time(tm, &ticks); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + base = ticks - data; + dev_dbg(info->dev, "set base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + buf[0] = base & 0xFF; + buf[1] = (base >> 8) & 0xFF; + buf[2] = (base >> 16) & 0xFF; + buf[3] = (base >> 24) & 0xFF; + regmap_raw_write(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + + return 0; +} + +static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + unsigned char buf[4]; + unsigned long ticks, base, data; + int ret; + + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + regmap_raw_read(info->map, PM800_RTC_EXPIRE1_1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + + rtc_time_to_tm(ticks, &alrm->time); + regmap_read(info->map, PM800_RTC_CONTROL, &ret); + alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0; + alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0; + return 0; +} + +static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct pm80x_rtc_info *info = dev_get_drvdata(dev); + struct rtc_time now_tm, alarm_tm; + unsigned long ticks, base, data; + unsigned char buf[4]; + int mask; + + regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_ALARM1_EN, 0); + + regmap_raw_read(info->map, PM800_RTC_EXPIRE2_1, buf, 4); + base = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + dev_dbg(info->dev, "%x-%x-%x-%x\n", buf[0], buf[1], buf[2], buf[3]); + + /* load 32-bit read-only counter */ + regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4); + data = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + ticks = base + data; + dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n", + base, data, ticks); + + rtc_time_to_tm(ticks, &now_tm); + dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks); + rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time); + /* get new ticks for alarm in 24 hours */ + rtc_tm_to_time(&alarm_tm, &ticks); + dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks); + data = ticks - base; + + buf[0] = data & 0xff; + buf[1] = (data >> 8) & 0xff; + buf[2] = (data >> 16) & 0xff; + buf[3] = (data >> 24) & 0xff; + regmap_raw_write(info->map, PM800_RTC_EXPIRE1_1, buf, 4); + if (alrm->enabled) { + mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask, mask); + } else { + mask = PM800_ALARM | PM800_ALARM_WAKEUP | PM800_ALARM1_EN; + regmap_update_bits(info->map, PM800_RTC_CONTROL, mask, + PM800_ALARM | PM800_ALARM_WAKEUP); + } + return 0; +} + +static const struct rtc_class_ops pm80x_rtc_ops = { + .read_time = pm80x_rtc_read_time, + .set_time = pm80x_rtc_set_time, + .read_alarm = pm80x_rtc_read_alarm, + .set_alarm = pm80x_rtc_set_alarm, + .alarm_irq_enable = pm80x_rtc_alarm_irq_enable, +}; + +#ifdef CONFIG_PM +static int pm80x_rtc_suspend(struct device *dev) +{ + return pm80x_dev_suspend(dev); +} + +static int pm80x_rtc_resume(struct device *dev) +{ + return pm80x_dev_resume(dev); +} +#endif + +static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume); + +static int __devinit pm80x_rtc_probe(struct platform_device *pdev) +{ + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm80x_platform_data *pm80x_pdata; + struct pm80x_rtc_pdata *pdata = NULL; + struct pm80x_rtc_info *info; + struct rtc_time tm; + unsigned long ticks = 0; + int ret; + + pdata = pdev->dev.platform_data; + if (pdata == NULL) + dev_warn(&pdev->dev, "No platform data!\n"); + + info = + devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->irq = platform_get_irq(pdev, 0); + if (info->irq < 0) { + dev_err(&pdev->dev, "No IRQ resource!\n"); + ret = -EINVAL; + goto out; + } + + info->chip = chip; + info->map = chip->regmap; + if (!info->map) { + dev_err(&pdev->dev, "no regmap!\n"); + ret = -EINVAL; + goto out; + } + + info->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, info); + + ret = pm80x_request_irq(chip, info->irq, rtc_update_handler, + IRQF_ONESHOT, "rtc", info); + if (ret < 0) { + dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", + info->irq, ret); + goto out; + } + + ret = pm80x_rtc_read_time(&pdev->dev, &tm); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to read initial time.\n"); + goto out_rtc; + } + if ((tm.tm_year < 70) || (tm.tm_year > 138)) { + tm.tm_year = 70; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + ret = pm80x_rtc_set_time(&pdev->dev, &tm); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to set initial time.\n"); + goto out_rtc; + } + } + rtc_tm_to_time(&tm, &ticks); + + info->rtc_dev = rtc_device_register("88pm80x-rtc", &pdev->dev, + &pm80x_rtc_ops, THIS_MODULE); + ret = PTR_ERR(info->rtc_dev); + if (IS_ERR(info->rtc_dev)) { + dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + goto out_rtc; + } + /* + * enable internal XO instead of internal 3.25MHz clock since it can + * free running in PMIC power-down state. + */ + regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO, + PM800_RTC1_USE_XO); + + if (pdev->dev.parent->platform_data) { + pm80x_pdata = pdev->dev.parent->platform_data; + pdata = pm80x_pdata->rtc; + if (pdata) + info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup; + } + + device_init_wakeup(&pdev->dev, 1); + + return 0; +out_rtc: + pm80x_free_irq(chip, info->irq, info); +out: + devm_kfree(&pdev->dev, info); + return ret; +} + +static int __devexit pm80x_rtc_remove(struct platform_device *pdev) +{ + struct pm80x_rtc_info *info = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + rtc_device_unregister(info->rtc_dev); + pm80x_free_irq(info->chip, info->irq, info); + devm_kfree(&pdev->dev, info); + return 0; +} + +static struct platform_driver pm80x_rtc_driver = { + .driver = { + .name = "88pm80x-rtc", + .owner = THIS_MODULE, + .pm = &pm80x_rtc_pm_ops, + }, + .probe = pm80x_rtc_probe, + .remove = __devexit_p(pm80x_rtc_remove), +}; + +module_platform_driver(pm80x_rtc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Marvell 88PM80x RTC driver"); +MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); +MODULE_ALIAS("platform:88pm80x-rtc"); diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c index 1459055a83a..34e4349611d 100644 --- a/drivers/rtc/rtc-max8925.c +++ b/drivers/rtc/rtc-max8925.c @@ -69,6 +69,7 @@ struct max8925_rtc_info { struct max8925_chip *chip; struct i2c_client *rtc; struct device *dev; + int irq; }; static irqreturn_t rtc_update_handler(int irq, void *data) @@ -250,7 +251,7 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max8925_rtc_info *info; - int irq, ret; + int ret; info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL); if (!info) @@ -258,13 +259,13 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) info->chip = chip; info->rtc = chip->rtc; info->dev = &pdev->dev; - irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0; + info->irq = platform_get_irq(pdev, 0); - ret = request_threaded_irq(irq, NULL, rtc_update_handler, + ret = request_threaded_irq(info->irq, NULL, rtc_update_handler, IRQF_ONESHOT, "rtc-alarm0", info); if (ret < 0) { dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", - irq, ret); + info->irq, ret); goto out_irq; } @@ -285,7 +286,7 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev) return 0; out_rtc: platform_set_drvdata(pdev, NULL); - free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); + free_irq(info->irq, info); out_irq: kfree(info); return ret; @@ -296,7 +297,7 @@ static int __devexit max8925_rtc_remove(struct platform_device *pdev) struct max8925_rtc_info *info = platform_get_drvdata(pdev); if (info) { - free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info); + free_irq(info->irq, info); rtc_device_unregister(info->rtc_dev); kfree(info); } diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4cde4fb0cd6..5f84b5563c2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -144,6 +144,15 @@ config SPI_EP93XX This enables using the Cirrus EP93xx SPI controller in master mode. +config SPI_FALCON + tristate "Falcon SPI controller support" + depends on SOC_FALCON + help + The external bus unit (EBU) found on the FALC-ON SoC has SPI + emulation that is designed for serial flash access. This driver + has only been tested with m25p80 type chips. The hardware has no + support for other types of SPI peripherals. + config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GENERIC_GPIO diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 273f50d1127..3920dcf4c74 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o +obj-$(CONFIG_SPI_FALCON) += spi-falcon.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c new file mode 100644 index 00000000000..8f6aa735a24 --- /dev/null +++ b/drivers/spi/spi-falcon.c @@ -0,0 +1,469 @@ +/* + * 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. + * + * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com> + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> +#include <linux/workqueue.h> +#include <linux/of.h> +#include <linux/of_platform.h> + +#include <lantiq_soc.h> + +#define DRV_NAME "sflash-falcon" + +#define FALCON_SPI_XFER_BEGIN (1 << 0) +#define FALCON_SPI_XFER_END (1 << 1) + +/* Bus Read Configuration Register0 */ +#define BUSRCON0 0x00000010 +/* Bus Write Configuration Register0 */ +#define BUSWCON0 0x00000018 +/* Serial Flash Configuration Register */ +#define SFCON 0x00000080 +/* Serial Flash Time Register */ +#define SFTIME 0x00000084 +/* Serial Flash Status Register */ +#define SFSTAT 0x00000088 +/* Serial Flash Command Register */ +#define SFCMD 0x0000008C +/* Serial Flash Address Register */ +#define SFADDR 0x00000090 +/* Serial Flash Data Register */ +#define SFDATA 0x00000094 +/* Serial Flash I/O Control Register */ +#define SFIO 0x00000098 +/* EBU Clock Control Register */ +#define EBUCC 0x000000C4 + +/* Dummy Phase Length */ +#define SFCMD_DUMLEN_OFFSET 16 +#define SFCMD_DUMLEN_MASK 0x000F0000 +/* Chip Select */ +#define SFCMD_CS_OFFSET 24 +#define SFCMD_CS_MASK 0x07000000 +/* field offset */ +#define SFCMD_ALEN_OFFSET 20 +#define SFCMD_ALEN_MASK 0x00700000 +/* SCK Rise-edge Position */ +#define SFTIME_SCKR_POS_OFFSET 8 +#define SFTIME_SCKR_POS_MASK 0x00000F00 +/* SCK Period */ +#define SFTIME_SCK_PER_OFFSET 0 +#define SFTIME_SCK_PER_MASK 0x0000000F +/* SCK Fall-edge Position */ +#define SFTIME_SCKF_POS_OFFSET 12 +#define SFTIME_SCKF_POS_MASK 0x0000F000 +/* Device Size */ +#define SFCON_DEV_SIZE_A23_0 0x03000000 +#define SFCON_DEV_SIZE_MASK 0x0F000000 +/* Read Data Position */ +#define SFTIME_RD_POS_MASK 0x000F0000 +/* Data Output */ +#define SFIO_UNUSED_WD_MASK 0x0000000F +/* Command Opcode mask */ +#define SFCMD_OPC_MASK 0x000000FF +/* dlen bytes of data to write */ +#define SFCMD_DIR_WRITE 0x00000100 +/* Data Length offset */ +#define SFCMD_DLEN_OFFSET 9 +/* Command Error */ +#define SFSTAT_CMD_ERR 0x20000000 +/* Access Command Pending */ +#define SFSTAT_CMD_PEND 0x00400000 +/* Frequency set to 100MHz. */ +#define EBUCC_EBUDIV_SELF100 0x00000001 +/* Serial Flash */ +#define BUSRCON0_AGEN_SERIAL_FLASH 0xF0000000 +/* 8-bit multiplexed */ +#define BUSRCON0_PORTW_8_BIT_MUX 0x00000000 +/* Serial Flash */ +#define BUSWCON0_AGEN_SERIAL_FLASH 0xF0000000 +/* Chip Select after opcode */ +#define SFCMD_KEEP_CS_KEEP_SELECTED 0x00008000 + +#define CLOCK_100M 100000000 +#define CLOCK_50M 50000000 + +struct falcon_sflash { + u32 sfcmd; /* for caching of opcode, direction, ... */ + struct spi_master *master; +}; + +int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t, + unsigned long flags) +{ + struct device *dev = &spi->dev; + struct falcon_sflash *priv = spi_master_get_devdata(spi->master); + const u8 *txp = t->tx_buf; + u8 *rxp = t->rx_buf; + unsigned int bytelen = ((8 * t->len + 7) / 8); + unsigned int len, alen, dumlen; + u32 val; + enum { + state_init, + state_command_prepare, + state_write, + state_read, + state_disable_cs, + state_end + } state = state_init; + + do { + switch (state) { + case state_init: /* detect phase of upper layer sequence */ + { + /* initial write ? */ + if (flags & FALCON_SPI_XFER_BEGIN) { + if (!txp) { + dev_err(dev, + "BEGIN without tx data!\n"); + return -ENODATA; + } + /* + * Prepare the parts of the sfcmd register, + * which should not change during a sequence! + * Only exception are the length fields, + * especially alen and dumlen. + */ + + priv->sfcmd = ((spi->chip_select + << SFCMD_CS_OFFSET) + & SFCMD_CS_MASK); + priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED; + priv->sfcmd |= *txp; + txp++; + bytelen--; + if (bytelen) { + /* + * more data: + * maybe address and/or dummy + */ + state = state_command_prepare; + break; + } else { + dev_dbg(dev, "write cmd %02X\n", + priv->sfcmd & SFCMD_OPC_MASK); + } + } + /* continued write ? */ + if (txp && bytelen) { + state = state_write; + break; + } + /* read data? */ + if (rxp && bytelen) { + state = state_read; + break; + } + /* end of sequence? */ + if (flags & FALCON_SPI_XFER_END) + state = state_disable_cs; + else + state = state_end; + break; + } + /* collect tx data for address and dummy phase */ + case state_command_prepare: + { + /* txp is valid, already checked */ + val = 0; + alen = 0; + dumlen = 0; + while (bytelen > 0) { + if (alen < 3) { + val = (val << 8) | (*txp++); + alen++; + } else if ((dumlen < 15) && (*txp == 0)) { + /* + * assume dummy bytes are set to 0 + * from upper layer + */ + dumlen++; + txp++; + } else { + break; + } + bytelen--; + } + priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK); + priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) | + (dumlen << SFCMD_DUMLEN_OFFSET); + if (alen > 0) + ltq_ebu_w32(val, SFADDR); + + dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n", + priv->sfcmd & SFCMD_OPC_MASK, + alen, val, dumlen); + + if (bytelen > 0) { + /* continue with write */ + state = state_write; + } else if (flags & FALCON_SPI_XFER_END) { + /* end of sequence? */ + state = state_disable_cs; + } else { + /* + * go to end and expect another + * call (read or write) + */ + state = state_end; + } + break; + } + case state_write: + { + /* txp still valid */ + priv->sfcmd |= SFCMD_DIR_WRITE; + len = 0; + val = 0; + do { + if (bytelen--) + val |= (*txp++) << (8 * len++); + if ((flags & FALCON_SPI_XFER_END) + && (bytelen == 0)) { + priv->sfcmd &= + ~SFCMD_KEEP_CS_KEEP_SELECTED; + } + if ((len == 4) || (bytelen == 0)) { + ltq_ebu_w32(val, SFDATA); + ltq_ebu_w32(priv->sfcmd + | (len<<SFCMD_DLEN_OFFSET), + SFCMD); + len = 0; + val = 0; + priv->sfcmd &= ~(SFCMD_ALEN_MASK + | SFCMD_DUMLEN_MASK); + } + } while (bytelen); + state = state_end; + break; + } + case state_read: + { + /* read data */ + priv->sfcmd &= ~SFCMD_DIR_WRITE; + do { + if ((flags & FALCON_SPI_XFER_END) + && (bytelen <= 4)) { + priv->sfcmd &= + ~SFCMD_KEEP_CS_KEEP_SELECTED; + } + len = (bytelen > 4) ? 4 : bytelen; + bytelen -= len; + ltq_ebu_w32(priv->sfcmd + | (len << SFCMD_DLEN_OFFSET), SFCMD); + priv->sfcmd &= ~(SFCMD_ALEN_MASK + | SFCMD_DUMLEN_MASK); + do { + val = ltq_ebu_r32(SFSTAT); + if (val & SFSTAT_CMD_ERR) { + /* reset error status */ + dev_err(dev, "SFSTAT: CMD_ERR"); + dev_err(dev, " (%x)\n", val); + ltq_ebu_w32(SFSTAT_CMD_ERR, + SFSTAT); + return -EBADE; + } + } while (val & SFSTAT_CMD_PEND); + val = ltq_ebu_r32(SFDATA); + do { + *rxp = (val & 0xFF); + rxp++; + val >>= 8; + len--; + } while (len); + } while (bytelen); + state = state_end; + break; + } + case state_disable_cs: + { + priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED; + ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET), + SFCMD); + val = ltq_ebu_r32(SFSTAT); + if (val & SFSTAT_CMD_ERR) { + /* reset error status */ + dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val); + ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT); + return -EBADE; + } + state = state_end; + break; + } + case state_end: + break; + } + } while (state != state_end); + + return 0; +} + +static int falcon_sflash_setup(struct spi_device *spi) +{ + unsigned int i; + unsigned long flags; + + if (spi->chip_select > 0) + return -ENODEV; + + spin_lock_irqsave(&ebu_lock, flags); + + if (spi->max_speed_hz >= CLOCK_100M) { + /* set EBU clock to 100 MHz */ + ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC); + i = 1; /* divider */ + } else { + /* set EBU clock to 50 MHz */ + ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC); + + /* search for suitable divider */ + for (i = 1; i < 7; i++) { + if (CLOCK_50M / i <= spi->max_speed_hz) + break; + } + } + + /* setup period of serial clock */ + ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK + | SFTIME_SCKR_POS_MASK + | SFTIME_SCK_PER_MASK, + (i << SFTIME_SCKR_POS_OFFSET) + | (i << (SFTIME_SCK_PER_OFFSET + 1)), + SFTIME); + + /* + * set some bits of unused_wd, to not trigger HOLD/WP + * signals on non QUAD flashes + */ + ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO); + + ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX, + BUSRCON0); + ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0); + /* set address wrap around to maximum for 24-bit addresses */ + ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON); + + spin_unlock_irqrestore(&ebu_lock, flags); + + return 0; +} + +static int falcon_sflash_prepare_xfer(struct spi_master *master) +{ + return 0; +} + +static int falcon_sflash_unprepare_xfer(struct spi_master *master) +{ + return 0; +} + +static int falcon_sflash_xfer_one(struct spi_master *master, + struct spi_message *m) +{ + struct falcon_sflash *priv = spi_master_get_devdata(master); + struct spi_transfer *t; + unsigned long spi_flags; + unsigned long flags; + int ret = 0; + + priv->sfcmd = 0; + m->actual_length = 0; + + spi_flags = FALCON_SPI_XFER_BEGIN; + list_for_each_entry(t, &m->transfers, transfer_list) { + if (list_is_last(&t->transfer_list, &m->transfers)) + spi_flags |= FALCON_SPI_XFER_END; + + spin_lock_irqsave(&ebu_lock, flags); + ret = falcon_sflash_xfer(m->spi, t, spi_flags); + spin_unlock_irqrestore(&ebu_lock, flags); + + if (ret) + break; + + m->actual_length += t->len; + + WARN_ON(t->delay_usecs || t->cs_change); + spi_flags = 0; + } + + m->status = ret; + m->complete(m->context); + + return 0; +} + +static int __devinit falcon_sflash_probe(struct platform_device *pdev) +{ + struct falcon_sflash *priv; + struct spi_master *master; + int ret; + + if (ltq_boot_select() != BS_SPI) { + dev_err(&pdev->dev, "invalid bootstrap options\n"); + return -ENODEV; + } + + master = spi_alloc_master(&pdev->dev, sizeof(*priv)); + if (!master) + return -ENOMEM; + + priv = spi_master_get_devdata(master); + priv->master = master; + + master->mode_bits = SPI_MODE_3; + master->num_chipselect = 1; + master->bus_num = -1; + master->setup = falcon_sflash_setup; + master->prepare_transfer_hardware = falcon_sflash_prepare_xfer; + master->transfer_one_message = falcon_sflash_xfer_one; + master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer; + master->dev.of_node = pdev->dev.of_node; + + platform_set_drvdata(pdev, priv); + + ret = spi_register_master(master); + if (ret) + spi_master_put(master); + return ret; +} + +static int __devexit falcon_sflash_remove(struct platform_device *pdev) +{ + struct falcon_sflash *priv = platform_get_drvdata(pdev); + + spi_unregister_master(priv->master); + + return 0; +} + +static const struct of_device_id falcon_sflash_match[] = { + { .compatible = "lantiq,sflash-falcon" }, + {}, +}; +MODULE_DEVICE_TABLE(of, falcon_sflash_match); + +static struct platform_driver falcon_sflash_driver = { + .probe = falcon_sflash_probe, + .remove = __devexit_p(falcon_sflash_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = falcon_sflash_match, + } +}; + +module_platform_driver(falcon_sflash_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver"); diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index e31949c9c87..f15b31b37ca 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -28,6 +28,7 @@ #include <linux/ethtool.h> #include <linux/phy.h> #include <linux/ratelimit.h> +#include <linux/of_mdio.h> #include <net/dst.h> @@ -161,22 +162,23 @@ static void cvm_oct_adjust_link(struct net_device *dev) int cvm_oct_phy_setup_device(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); + struct device_node *phy_node; - int phy_addr = cvmx_helper_board_get_mii_address(priv->port); - if (phy_addr != -1) { - char phy_id[MII_BUS_ID_SIZE + 3]; + if (!priv->of_node) + return 0; - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr); + phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0); + if (!phy_node) + return 0; - priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0, - PHY_INTERFACE_MODE_GMII); + priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, + PHY_INTERFACE_MODE_GMII); + + if (priv->phydev == NULL) + return -ENODEV; + + priv->last_link = 0; + phy_start_aneg(priv->phydev); - if (IS_ERR(priv->phydev)) { - priv->phydev = NULL; - return -1; - } - priv->last_link = 0; - phy_start_aneg(priv->phydev); - } return 0; } diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 18f7a790f73..683bedc74dd 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -24,6 +24,7 @@ * This file may also be available under a different license from Cavium. * Contact Cavium Networks for more information **********************************************************************/ +#include <linux/platform_device.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> @@ -32,6 +33,7 @@ #include <linux/phy.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/of_net.h> #include <net/dst.h> @@ -113,15 +115,6 @@ int rx_napi_weight = 32; module_param(rx_napi_weight, int, 0444); MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); -/* - * The offset from mac_addr_base that should be used for the next port - * that is configured. By convention, if any mgmt ports exist on the - * chip, they get the first mac addresses, The ports controlled by - * this driver are numbered sequencially following any mgmt addresses - * that may exist. - */ -static unsigned int cvm_oct_mac_addr_offset; - /** * cvm_oct_poll_queue - Workqueue for polling operations. */ @@ -176,7 +169,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work) queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ); } -static __init void cvm_oct_configure_common_hw(void) +static __devinit void cvm_oct_configure_common_hw(void) { /* Setup the FPA */ cvmx_fpa_enable(); @@ -396,23 +389,21 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) * Returns Zero on success */ -static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) +static int cvm_oct_set_mac_filter(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); union cvmx_gmxx_prtx_cfg gmx_cfg; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); - memcpy(dev->dev_addr, addr + 2, 6); - if ((interface < 2) && (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { int i; - uint8_t *ptr = addr; + uint8_t *ptr = dev->dev_addr; uint64_t mac = 0; for (i = 0; i < 6; i++) - mac = (mac << 8) | (uint64_t) (ptr[i + 2]); + mac = (mac << 8) | (uint64_t)ptr[i]; gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); @@ -421,17 +412,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), - ptr[2]); + ptr[0]); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), - ptr[3]); + ptr[1]); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), - ptr[4]); + ptr[2]); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), - ptr[5]); + ptr[3]); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), - ptr[6]); + ptr[4]); cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), - ptr[7]); + ptr[5]); cvm_oct_common_set_multicast_list(dev); cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); @@ -439,6 +430,15 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) return 0; } +static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) +{ + int r = eth_mac_addr(dev, addr); + + if (r) + return r; + return cvm_oct_set_mac_filter(dev); +} + /** * cvm_oct_common_init - per network device initialization * @dev: Device to initialize @@ -448,26 +448,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) int cvm_oct_common_init(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); - struct sockaddr sa; - u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) | - ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) | - ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) | - ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) | - ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) | - (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff); - - mac += cvm_oct_mac_addr_offset; - sa.sa_data[0] = (mac >> 40) & 0xff; - sa.sa_data[1] = (mac >> 32) & 0xff; - sa.sa_data[2] = (mac >> 24) & 0xff; - sa.sa_data[3] = (mac >> 16) & 0xff; - sa.sa_data[4] = (mac >> 8) & 0xff; - sa.sa_data[5] = mac & 0xff; - - if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count) - printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:" - " %pM\n", dev->name, sa.sa_data); - cvm_oct_mac_addr_offset++; + const u8 *mac = NULL; + + if (priv->of_node) + mac = of_get_mac_address(priv->of_node); + + if (mac && is_valid_ether_addr(mac)) { + memcpy(dev->dev_addr, mac, ETH_ALEN); + dev->addr_assign_type &= ~NET_ADDR_RANDOM; + } else { + eth_hw_addr_random(dev); + } /* * Force the interface to use the POW send if always_use_pow @@ -488,7 +479,7 @@ int cvm_oct_common_init(struct net_device *dev) SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); cvm_oct_phy_setup_device(dev); - dev->netdev_ops->ndo_set_mac_address(dev, &sa); + cvm_oct_set_mac_filter(dev); dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); /* @@ -595,22 +586,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = { extern void octeon_mdiobus_force_mod_depencency(void); -static int __init cvm_oct_init_module(void) +static struct device_node * __devinit cvm_oct_of_get_child(const struct device_node *parent, + int reg_val) +{ + struct device_node *node = NULL; + int size; + const __be32 *addr; + + for (;;) { + node = of_get_next_child(parent, node); + if (!node) + break; + addr = of_get_property(node, "reg", &size); + if (addr && (be32_to_cpu(*addr) == reg_val)) + break; + } + return node; +} + +static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *pip, + int interface, int port) +{ + struct device_node *ni, *np; + + ni = cvm_oct_of_get_child(pip, interface); + if (!ni) + return NULL; + + np = cvm_oct_of_get_child(ni, port); + of_node_put(ni); + + return np; +} + +static int __devinit cvm_oct_probe(struct platform_device *pdev) { int num_interfaces; int interface; int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int qos; + struct device_node *pip; octeon_mdiobus_force_mod_depencency(); pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); - if (OCTEON_IS_MODEL(OCTEON_CN52XX)) - cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */ - else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) - cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */ - else - cvm_oct_mac_addr_offset = 0; + pip = pdev->dev.of_node; + if (!pip) { + pr_err("Error: No 'pip' in /aliases\n"); + return -EINVAL; + } cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet"); if (cvm_oct_poll_queue == NULL) { @@ -689,10 +713,11 @@ static int __init cvm_oct_init_module(void) cvmx_helper_interface_get_mode(interface); int num_ports = cvmx_helper_ports_on_interface(interface); int port; + int port_index; - for (port = cvmx_helper_get_ipd_port(interface, 0); + for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); - port++) { + port_index++, port++) { struct octeon_ethernet *priv; struct net_device *dev = alloc_etherdev(sizeof(struct octeon_ethernet)); @@ -703,6 +728,7 @@ static int __init cvm_oct_init_module(void) /* Initialize the device private structure. */ priv = netdev_priv(dev); + priv->of_node = cvm_oct_node_for_port(pip, interface, port_index); INIT_DELAYED_WORK(&priv->port_periodic_work, cvm_oct_periodic_worker); @@ -787,7 +813,7 @@ static int __init cvm_oct_init_module(void) return 0; } -static void __exit cvm_oct_cleanup_module(void) +static int __devexit cvm_oct_remove(struct platform_device *pdev) { int port; @@ -835,10 +861,29 @@ static void __exit cvm_oct_cleanup_module(void) if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); + return 0; } +static struct of_device_id cvm_oct_match[] = { + { + .compatible = "cavium,octeon-3860-pip", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, cvm_oct_match); + +static struct platform_driver cvm_oct_driver = { + .probe = cvm_oct_probe, + .remove = __devexit_p(cvm_oct_remove), + .driver = { + .owner = THIS_MODULE, + .name = KBUILD_MODNAME, + .of_match_table = cvm_oct_match, + }, +}; + +module_platform_driver(cvm_oct_driver); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>"); MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver."); -module_init(cvm_oct_init_module); -module_exit(cvm_oct_cleanup_module); diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index d5819256355..9360e22e073 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -31,6 +31,8 @@ #ifndef OCTEON_ETHERNET_H #define OCTEON_ETHERNET_H +#include <linux/of.h> + /** * This is the definition of the Ethernet driver's private * driver state stored in netdev_priv(dev). @@ -59,6 +61,7 @@ struct octeon_ethernet { void (*poll) (struct net_device *dev); struct delayed_work port_periodic_work; struct work_struct port_work; /* may be unused. */ + struct device_node *of_node; }; int cvm_oct_free_work(void *work_queue_entry); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index ec21f4a4a05..bb55eb4a7d4 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -152,14 +152,14 @@ static int omap_ehci_init(struct usb_hcd *hcd) struct ehci_hcd_omap_platform_data *pdata; pdata = hcd->self.controller->platform_data; + + /* Hold PHYs in reset while initializing EHCI controller */ if (pdata->phy_reset) { if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_request_one(pdata->reset_gpio_port[0], - GPIOF_OUT_INIT_LOW, "USB1 PHY reset"); + gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_request_one(pdata->reset_gpio_port[1], - GPIOF_OUT_INIT_LOW, "USB2 PHY reset"); + gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); /* Hold the PHY in RESET for enough time till DIR is high */ udelay(10); diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 2979292650d..cf282763a8d 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -245,7 +245,7 @@ config BACKLIGHT_CARILLO_RANCH config BACKLIGHT_PWM tristate "Generic PWM based Backlight Driver" - depends on HAVE_PWM + depends on PWM help If you have a LCD backlight adjustable by PWM, say Y to enable this driver. diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 342b7d7cbb6..995f0164c9b 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -26,11 +26,13 @@ struct pwm_bl_data { struct device *dev; unsigned int period; unsigned int lth_brightness; + unsigned int *levels; int (*notify)(struct device *, int brightness); void (*notify_after)(struct device *, int brightness); int (*check_fb)(struct device *, struct fb_info *); + void (*exit)(struct device *); }; static int pwm_backlight_update_status(struct backlight_device *bl) @@ -52,9 +54,18 @@ static int pwm_backlight_update_status(struct backlight_device *bl) pwm_config(pb->pwm, 0, pb->period); pwm_disable(pb->pwm); } else { - brightness = pb->lth_brightness + - (brightness * (pb->period - pb->lth_brightness) / max); - pwm_config(pb->pwm, brightness, pb->period); + int duty_cycle; + + if (pb->levels) { + duty_cycle = pb->levels[brightness]; + max = pb->levels[max]; + } else { + duty_cycle = brightness; + } + + duty_cycle = pb->lth_brightness + + (duty_cycle * (pb->period - pb->lth_brightness) / max); + pwm_config(pb->pwm, duty_cycle, pb->period); pwm_enable(pb->pwm); } @@ -83,17 +94,98 @@ static const struct backlight_ops pwm_backlight_ops = { .check_fb = pwm_backlight_check_fb, }; +#ifdef CONFIG_OF +static int pwm_backlight_parse_dt(struct device *dev, + struct platform_pwm_backlight_data *data) +{ + struct device_node *node = dev->of_node; + struct property *prop; + int length; + u32 value; + int ret; + + if (!node) + return -ENODEV; + + memset(data, 0, sizeof(*data)); + + /* determine the number of brightness levels */ + prop = of_find_property(node, "brightness-levels", &length); + if (!prop) + return -EINVAL; + + data->max_brightness = length / sizeof(u32); + + /* read brightness levels from DT property */ + if (data->max_brightness > 0) { + size_t size = sizeof(*data->levels) * data->max_brightness; + + data->levels = devm_kzalloc(dev, size, GFP_KERNEL); + if (!data->levels) + return -ENOMEM; + + ret = of_property_read_u32_array(node, "brightness-levels", + data->levels, + data->max_brightness); + if (ret < 0) + return ret; + + ret = of_property_read_u32(node, "default-brightness-level", + &value); + if (ret < 0) + return ret; + + if (value >= data->max_brightness) { + dev_warn(dev, "invalid default brightness level: %u, using %u\n", + value, data->max_brightness - 1); + value = data->max_brightness - 1; + } + + data->dft_brightness = value; + data->max_brightness--; + } + + /* + * TODO: Most users of this driver use a number of GPIOs to control + * backlight power. Support for specifying these needs to be + * added. + */ + + return 0; +} + +static struct of_device_id pwm_backlight_of_match[] = { + { .compatible = "pwm-backlight" }, + { } +}; + +MODULE_DEVICE_TABLE(of, pwm_backlight_of_match); +#else +static int pwm_backlight_parse_dt(struct device *dev, + struct platform_pwm_backlight_data *data) +{ + return -ENODEV; +} +#endif + static int pwm_backlight_probe(struct platform_device *pdev) { - struct backlight_properties props; struct platform_pwm_backlight_data *data = pdev->dev.platform_data; + struct platform_pwm_backlight_data defdata; + struct backlight_properties props; struct backlight_device *bl; struct pwm_bl_data *pb; + unsigned int max; int ret; if (!data) { - dev_err(&pdev->dev, "failed to find platform data\n"); - return -EINVAL; + ret = pwm_backlight_parse_dt(&pdev->dev, &defdata); + if (ret < 0) { + dev_err(&pdev->dev, "failed to find platform data\n"); + return ret; + } + + data = &defdata; } if (data->init) { @@ -109,21 +201,42 @@ static int pwm_backlight_probe(struct platform_device *pdev) goto err_alloc; } - pb->period = data->pwm_period_ns; + if (data->levels) { + max = data->levels[data->max_brightness]; + pb->levels = data->levels; + } else + max = data->max_brightness; + pb->notify = data->notify; pb->notify_after = data->notify_after; pb->check_fb = data->check_fb; - pb->lth_brightness = data->lth_brightness * - (data->pwm_period_ns / data->max_brightness); + pb->exit = data->exit; pb->dev = &pdev->dev; - pb->pwm = pwm_request(data->pwm_id, "backlight"); + pb->pwm = pwm_get(&pdev->dev, NULL); if (IS_ERR(pb->pwm)) { - dev_err(&pdev->dev, "unable to request PWM for backlight\n"); - ret = PTR_ERR(pb->pwm); - goto err_alloc; - } else - dev_dbg(&pdev->dev, "got pwm for backlight\n"); + dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n"); + + pb->pwm = pwm_request(data->pwm_id, "pwm-backlight"); + if (IS_ERR(pb->pwm)) { + dev_err(&pdev->dev, "unable to request legacy PWM\n"); + ret = PTR_ERR(pb->pwm); + goto err_alloc; + } + } + + dev_dbg(&pdev->dev, "got pwm for backlight\n"); + + /* + * The DT case will set the pwm_period_ns field to 0 and store the + * period, parsed from the DT, in the PWM device. For the non-DT case, + * set the period from platform data. + */ + if (data->pwm_period_ns > 0) + pwm_set_period(pb->pwm, data->pwm_period_ns); + + pb->period = pwm_get_period(pb->pwm); + pb->lth_brightness = data->lth_brightness * (pb->period / max); memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_RAW; @@ -143,7 +256,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) return 0; err_bl: - pwm_free(pb->pwm); + pwm_put(pb->pwm); err_alloc: if (data->exit) data->exit(&pdev->dev); @@ -152,16 +265,15 @@ err_alloc: static int pwm_backlight_remove(struct platform_device *pdev) { - struct platform_pwm_backlight_data *data = pdev->dev.platform_data; struct backlight_device *bl = platform_get_drvdata(pdev); struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev); backlight_device_unregister(bl); pwm_config(pb->pwm, 0, pb->period); pwm_disable(pb->pwm); - pwm_free(pb->pwm); - if (data->exit) - data->exit(&pdev->dev); + pwm_put(pb->pwm); + if (pb->exit) + pb->exit(&pdev->dev); return 0; } @@ -195,11 +307,12 @@ static SIMPLE_DEV_PM_OPS(pwm_backlight_pm_ops, pwm_backlight_suspend, static struct platform_driver pwm_backlight_driver = { .driver = { - .name = "pwm-backlight", - .owner = THIS_MODULE, + .name = "pwm-backlight", + .owner = THIS_MODULE, #ifdef CONFIG_PM - .pm = &pwm_backlight_pm_ops, + .pm = &pwm_backlight_pm_ops, #endif + .of_match_table = of_match_ptr(pwm_backlight_of_match), }, .probe = pwm_backlight_probe, .remove = pwm_backlight_remove, diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h index a6caa0022c9..359fb86ed87 100644 --- a/fs/xfs/xfs_alloc_btree.h +++ b/fs/xfs/xfs_alloc_btree.h @@ -51,20 +51,6 @@ typedef struct xfs_alloc_rec_incore { typedef __be32 xfs_alloc_ptr_t; /* - * Minimum and maximum blocksize and sectorsize. - * The blocksize upper limit is pretty much arbitrary. - * The sectorsize upper limit is due to sizeof(sb_sectsize). - */ -#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ -#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ -#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) -#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) -#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ -#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ -#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) -#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) - -/* * Block numbers in the AG: * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3. */ diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8dad722c004..15052ff916e 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -179,7 +179,7 @@ xfs_finish_ioend( if (atomic_dec_and_test(&ioend->io_remaining)) { struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount; - if (ioend->io_type == IO_UNWRITTEN) + if (ioend->io_type == XFS_IO_UNWRITTEN) queue_work(mp->m_unwritten_workqueue, &ioend->io_work); else if (ioend->io_append_trans) queue_work(mp->m_data_workqueue, &ioend->io_work); @@ -210,7 +210,7 @@ xfs_end_io( * For unwritten extents we need to issue transactions to convert a * range to normal written extens after the data I/O has finished. */ - if (ioend->io_type == IO_UNWRITTEN) { + if (ioend->io_type == XFS_IO_UNWRITTEN) { /* * For buffered I/O we never preallocate a transaction when * doing the unwritten extent conversion, but for direct I/O @@ -312,7 +312,7 @@ xfs_map_blocks( if (XFS_FORCED_SHUTDOWN(mp)) return -XFS_ERROR(EIO); - if (type == IO_UNWRITTEN) + if (type == XFS_IO_UNWRITTEN) bmapi_flags |= XFS_BMAPI_IGSTATE; if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { @@ -323,10 +323,10 @@ xfs_map_blocks( ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || (ip->i_df.if_flags & XFS_IFEXTENTS)); - ASSERT(offset <= mp->m_maxioffset); + ASSERT(offset <= mp->m_super->s_maxbytes); - if (offset + count > mp->m_maxioffset) - count = mp->m_maxioffset - offset; + if (offset + count > mp->m_super->s_maxbytes) + count = mp->m_super->s_maxbytes - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); offset_fsb = XFS_B_TO_FSBT(mp, offset); error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, @@ -336,7 +336,7 @@ xfs_map_blocks( if (error) return -XFS_ERROR(error); - if (type == IO_DELALLOC && + if (type == XFS_IO_DELALLOC && (!nimaps || isnullstartblock(imap->br_startblock))) { error = xfs_iomap_write_allocate(ip, offset, count, imap); if (!error) @@ -345,7 +345,7 @@ xfs_map_blocks( } #ifdef DEBUG - if (type == IO_UNWRITTEN) { + if (type == XFS_IO_UNWRITTEN) { ASSERT(nimaps); ASSERT(imap->br_startblock != HOLESTARTBLOCK); ASSERT(imap->br_startblock != DELAYSTARTBLOCK); @@ -634,11 +634,11 @@ xfs_check_page_type( bh = head = page_buffers(page); do { if (buffer_unwritten(bh)) - acceptable += (type == IO_UNWRITTEN); + acceptable += (type == XFS_IO_UNWRITTEN); else if (buffer_delay(bh)) - acceptable += (type == IO_DELALLOC); + acceptable += (type == XFS_IO_DELALLOC); else if (buffer_dirty(bh) && buffer_mapped(bh)) - acceptable += (type == IO_OVERWRITE); + acceptable += (type == XFS_IO_OVERWRITE); else break; } while ((bh = bh->b_this_page) != head); @@ -721,11 +721,11 @@ xfs_convert_page( if (buffer_unwritten(bh) || buffer_delay(bh) || buffer_mapped(bh)) { if (buffer_unwritten(bh)) - type = IO_UNWRITTEN; + type = XFS_IO_UNWRITTEN; else if (buffer_delay(bh)) - type = IO_DELALLOC; + type = XFS_IO_DELALLOC; else - type = IO_OVERWRITE; + type = XFS_IO_OVERWRITE; if (!xfs_imap_valid(inode, imap, offset)) { done = 1; @@ -733,7 +733,7 @@ xfs_convert_page( } lock_buffer(bh); - if (type != IO_OVERWRITE) + if (type != XFS_IO_OVERWRITE) xfs_map_at_offset(inode, bh, imap, offset); xfs_add_to_ioend(inode, bh, offset, type, ioendp, done); @@ -831,7 +831,7 @@ xfs_aops_discard_page( struct buffer_head *bh, *head; loff_t offset = page_offset(page); - if (!xfs_check_page_type(page, IO_DELALLOC)) + if (!xfs_check_page_type(page, XFS_IO_DELALLOC)) goto out_invalidate; if (XFS_FORCED_SHUTDOWN(ip->i_mount)) @@ -927,11 +927,26 @@ xfs_vm_writepage( end_index = offset >> PAGE_CACHE_SHIFT; last_index = (offset - 1) >> PAGE_CACHE_SHIFT; if (page->index >= end_index) { - if ((page->index >= end_index + 1) || - !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { + unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1); + + /* + * Just skip the page if it is fully outside i_size, e.g. due + * to a truncate operation that is in progress. + */ + if (page->index >= end_index + 1 || offset_into_page == 0) { unlock_page(page); return 0; } + + /* + * The page straddles i_size. It must be zeroed out on each + * and every writepage invocation because it may be mmapped. + * "A file is mapped in multiples of the page size. For a file + * that is not a multiple of the page size, the remaining + * memory is zeroed when mapped, and writes to that region are + * not written out to the file." + */ + zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE); } end_offset = min_t(unsigned long long, @@ -941,7 +956,7 @@ xfs_vm_writepage( bh = head = page_buffers(page); offset = page_offset(page); - type = IO_OVERWRITE; + type = XFS_IO_OVERWRITE; if (wbc->sync_mode == WB_SYNC_NONE) nonblocking = 1; @@ -966,18 +981,18 @@ xfs_vm_writepage( } if (buffer_unwritten(bh)) { - if (type != IO_UNWRITTEN) { - type = IO_UNWRITTEN; + if (type != XFS_IO_UNWRITTEN) { + type = XFS_IO_UNWRITTEN; imap_valid = 0; } } else if (buffer_delay(bh)) { - if (type != IO_DELALLOC) { - type = IO_DELALLOC; + if (type != XFS_IO_DELALLOC) { + type = XFS_IO_DELALLOC; imap_valid = 0; } } else if (buffer_uptodate(bh)) { - if (type != IO_OVERWRITE) { - type = IO_OVERWRITE; + if (type != XFS_IO_OVERWRITE) { + type = XFS_IO_OVERWRITE; imap_valid = 0; } } else { @@ -1013,7 +1028,7 @@ xfs_vm_writepage( } if (imap_valid) { lock_buffer(bh); - if (type != IO_OVERWRITE) + if (type != XFS_IO_OVERWRITE) xfs_map_at_offset(inode, bh, &imap, offset); xfs_add_to_ioend(inode, bh, offset, type, &ioend, new_ioend); @@ -1054,7 +1069,7 @@ xfs_vm_writepage( * Reserve log space if we might write beyond the on-disk * inode size. */ - if (ioend->io_type != IO_UNWRITTEN && + if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) { err = xfs_setfilesize_trans_alloc(ioend); if (err) @@ -1162,9 +1177,9 @@ __xfs_get_blocks( lockmode = xfs_ilock_map_shared(ip); } - ASSERT(offset <= mp->m_maxioffset); - if (offset + size > mp->m_maxioffset) - size = mp->m_maxioffset - offset; + ASSERT(offset <= mp->m_super->s_maxbytes); + if (offset + size > mp->m_super->s_maxbytes) + size = mp->m_super->s_maxbytes - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); offset_fsb = XFS_B_TO_FSBT(mp, offset); @@ -1351,7 +1366,7 @@ xfs_end_io_direct_write( ioend->io_iocb = iocb; ioend->io_result = ret; if (private && size > 0) - ioend->io_type = IO_UNWRITTEN; + ioend->io_type = XFS_IO_UNWRITTEN; if (is_async) { ioend->io_isasync = 1; @@ -1383,7 +1398,7 @@ xfs_vm_direct_IO( * and converts at least on unwritten extent we will cancel * the still clean transaction after the I/O has finished. */ - iocb->private = ioend = xfs_alloc_ioend(inode, IO_DIRECT); + iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT); if (offset + size > XFS_I(inode)->i_d.di_size) { ret = xfs_setfilesize_trans_alloc(ioend); if (ret) diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 84eafbcb0d9..c325abb8d61 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -24,17 +24,17 @@ extern mempool_t *xfs_ioend_pool; * Types of I/O for bmap clustering and I/O completion tracking. */ enum { - IO_DIRECT = 0, /* special case for direct I/O ioends */ - IO_DELALLOC, /* mapping covers delalloc region */ - IO_UNWRITTEN, /* mapping covers allocated but uninitialized data */ - IO_OVERWRITE, /* mapping covers already allocated extent */ + XFS_IO_DIRECT = 0, /* special case for direct I/O ioends */ + XFS_IO_DELALLOC, /* covers delalloc region */ + XFS_IO_UNWRITTEN, /* covers allocated but uninitialized data */ + XFS_IO_OVERWRITE, /* covers already allocated extent */ }; #define XFS_IO_TYPES \ { 0, "" }, \ - { IO_DELALLOC, "delalloc" }, \ - { IO_UNWRITTEN, "unwritten" }, \ - { IO_OVERWRITE, "overwrite" } + { XFS_IO_DELALLOC, "delalloc" }, \ + { XFS_IO_UNWRITTEN, "unwritten" }, \ + { XFS_IO_OVERWRITE, "overwrite" } /* * xfs_ioend struct manages large extent writes for XFS. diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index a17ff01b5ad..0ca1f0be62d 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -893,7 +893,7 @@ STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args) { xfs_inode_t *dp; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int retval, error, committed, forkoff; trace_xfs_attr_leaf_addname(args); @@ -915,11 +915,11 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) */ retval = xfs_attr_leaf_lookup_int(bp, args); if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); return(retval); } else if (retval == EEXIST) { if (args->flags & ATTR_CREATE) { /* pure create op */ - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); return(retval); } @@ -937,7 +937,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * if required. */ retval = xfs_attr_leaf_add(bp, args); - xfs_da_buf_done(bp); if (retval == ENOSPC) { /* * Promote the attribute list to the Btree format, then @@ -1065,8 +1064,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) */ if (committed) xfs_trans_ijoin(args->trans, dp, 0); - } else - xfs_da_buf_done(bp); + } /* * Commit the remove and start the next trans in series. @@ -1092,7 +1090,7 @@ STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args) { xfs_inode_t *dp; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error, committed, forkoff; trace_xfs_attr_leaf_removename(args); @@ -1111,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) ASSERT(bp != NULL); error = xfs_attr_leaf_lookup_int(bp, args); if (error == ENOATTR) { - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); return(error); } @@ -1141,8 +1139,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) */ if (committed) xfs_trans_ijoin(args->trans, dp, 0); - } else - xfs_da_buf_done(bp); + } return(0); } @@ -1155,7 +1152,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) STATIC int xfs_attr_leaf_get(xfs_da_args_t *args) { - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; args->blkno = 0; @@ -1167,11 +1164,11 @@ xfs_attr_leaf_get(xfs_da_args_t *args) error = xfs_attr_leaf_lookup_int(bp, args); if (error != EEXIST) { - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); return(error); } error = xfs_attr_leaf_getvalue(bp, args); - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { error = xfs_attr_rmtval_get(args); } @@ -1186,23 +1183,23 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context) { xfs_attr_leafblock_t *leaf; int error; - xfs_dabuf_t *bp; + struct xfs_buf *bp; context->cursor->blkno = 0; error = xfs_da_read_buf(NULL, context->dp, 0, -1, &bp, XFS_ATTR_FORK); if (error) return XFS_ERROR(error); ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) { XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, context->dp->i_mount, leaf); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return XFS_ERROR(EFSCORRUPTED); } error = xfs_attr_leaf_list_int(bp, context); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return XFS_ERROR(error); } @@ -1489,7 +1486,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) xfs_da_state_t *state; xfs_da_state_blk_t *blk; xfs_inode_t *dp; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int retval, error, committed, forkoff; trace_xfs_attr_node_removename(args); @@ -1601,14 +1598,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) */ ASSERT(state->path.active == 1); ASSERT(state->path.blk[0].bp); - xfs_da_buf_done(state->path.blk[0].bp); state->path.blk[0].bp = NULL; error = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, XFS_ATTR_FORK); if (error) goto out; - ASSERT((((xfs_attr_leafblock_t *)bp->data)->hdr.info.magic) == + ASSERT((((xfs_attr_leafblock_t *)bp->b_addr)->hdr.info.magic) == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { @@ -1635,7 +1631,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) if (committed) xfs_trans_ijoin(args->trans, dp, 0); } else - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); } error = 0; @@ -1665,8 +1661,7 @@ xfs_attr_fillstate(xfs_da_state_t *state) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->bp) { - blk->disk_blkno = xfs_da_blkno(blk->bp); - xfs_da_buf_done(blk->bp); + blk->disk_blkno = XFS_BUF_ADDR(blk->bp); blk->bp = NULL; } else { blk->disk_blkno = 0; @@ -1681,8 +1676,7 @@ xfs_attr_fillstate(xfs_da_state_t *state) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); for (blk = path->blk, level = 0; level < path->active; blk++, level++) { if (blk->bp) { - blk->disk_blkno = xfs_da_blkno(blk->bp); - xfs_da_buf_done(blk->bp); + blk->disk_blkno = XFS_BUF_ADDR(blk->bp); blk->bp = NULL; } else { blk->disk_blkno = 0; @@ -1792,7 +1786,7 @@ xfs_attr_node_get(xfs_da_args_t *args) * If not in a transaction, we have to release all the buffers. */ for (i = 0; i < state->path.active; i++) { - xfs_da_brelse(args->trans, state->path.blk[i].bp); + xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } @@ -1808,7 +1802,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) xfs_da_intnode_t *node; xfs_da_node_entry_t *btree; int error, i; - xfs_dabuf_t *bp; + struct xfs_buf *bp; cursor = context->cursor; cursor->initted = 1; @@ -1825,30 +1819,30 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) if ((error != 0) && (error != EFSCORRUPTED)) return(error); if (bp) { - node = bp->data; + node = bp->b_addr; switch (be16_to_cpu(node->hdr.info.magic)) { case XFS_DA_NODE_MAGIC: trace_xfs_attr_list_wrong_blk(context); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); bp = NULL; break; case XFS_ATTR_LEAF_MAGIC: - leaf = bp->data; + leaf = bp->b_addr; if (cursor->hashval > be32_to_cpu(leaf->entries[ be16_to_cpu(leaf->hdr.count)-1].hashval)) { trace_xfs_attr_list_wrong_blk(context); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); bp = NULL; } else if (cursor->hashval <= be32_to_cpu(leaf->entries[0].hashval)) { trace_xfs_attr_list_wrong_blk(context); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); bp = NULL; } break; default: trace_xfs_attr_list_wrong_blk(context); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); bp = NULL; } } @@ -1873,7 +1867,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) context->dp->i_mount); return(XFS_ERROR(EFSCORRUPTED)); } - node = bp->data; + node = bp->b_addr; if (node->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) break; @@ -1883,7 +1877,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) XFS_ERRLEVEL_LOW, context->dp->i_mount, node); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return(XFS_ERROR(EFSCORRUPTED)); } btree = node->btree; @@ -1898,10 +1892,10 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) } } if (i == be16_to_cpu(node->hdr.count)) { - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return(0); } - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); } } ASSERT(bp != NULL); @@ -1912,24 +1906,24 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) * adding the information. */ for (;;) { - leaf = bp->data; + leaf = bp->b_addr; if (unlikely(leaf->hdr.info.magic != cpu_to_be16(XFS_ATTR_LEAF_MAGIC))) { XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)", XFS_ERRLEVEL_LOW, context->dp->i_mount, leaf); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return(XFS_ERROR(EFSCORRUPTED)); } error = xfs_attr_leaf_list_int(bp, context); if (error) { - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return error; } if (context->seen_enough || leaf->hdr.info.forw == 0) break; cursor->blkno = be32_to_cpu(leaf->hdr.info.forw); - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); error = xfs_da_read_buf(NULL, context->dp, cursor->blkno, -1, &bp, XFS_ATTR_FORK); if (error) @@ -1941,7 +1935,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) return(XFS_ERROR(EFSCORRUPTED)); } } - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return(0); } diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 7d89d800f51..d330111ca73 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -54,10 +54,10 @@ * Routines used for growing the Btree. */ STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block, - xfs_dabuf_t **bpp); -STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, - int freemap_index); -STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer); + struct xfs_buf **bpp); +STATIC int xfs_attr_leaf_add_work(struct xfs_buf *leaf_buffer, + xfs_da_args_t *args, int freemap_index); +STATIC void xfs_attr_leaf_compact(xfs_trans_t *tp, struct xfs_buf *leaf_buffer); STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_state_blk_t *blk2); @@ -71,9 +71,9 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state, * Routines used for shrinking the Btree. */ STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, - xfs_dabuf_t *bp, int level); + struct xfs_buf *bp, int level); STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, - xfs_dabuf_t *bp); + struct xfs_buf *bp); STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dablk_t blkno, int blkcnt); @@ -480,7 +480,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) char *tmpbuffer; int error, i, size; xfs_dablk_t blkno; - xfs_dabuf_t *bp; + struct xfs_buf *bp; xfs_ifork_t *ifp; trace_xfs_attr_sf_to_leaf(args); @@ -550,8 +550,6 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) error = 0; out: - if(bp) - xfs_da_buf_done(bp); kmem_free(tmpbuffer); return(error); } @@ -737,14 +735,16 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context) * a shortform attribute list. */ int -xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) +xfs_attr_shortform_allfit( + struct xfs_buf *bp, + struct xfs_inode *dp) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; xfs_attr_leaf_name_local_t *name_loc; int bytes, i; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); entry = &leaf->entries[0]; @@ -774,7 +774,10 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) * Convert a leaf attribute list to shortform attribute list */ int -xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) +xfs_attr_leaf_to_shortform( + struct xfs_buf *bp, + xfs_da_args_t *args, + int forkoff) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; @@ -791,10 +794,10 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) ASSERT(tmpbuffer != NULL); ASSERT(bp != NULL); - memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); + memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount)); leaf = (xfs_attr_leafblock_t *)tmpbuffer; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); - memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); + memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount)); /* * Clean out the prior contents of the attribute list. @@ -855,7 +858,7 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args) xfs_attr_leafblock_t *leaf; xfs_da_intnode_t *node; xfs_inode_t *dp; - xfs_dabuf_t *bp1, *bp2; + struct xfs_buf *bp1, *bp2; xfs_dablk_t blkno; int error; @@ -877,10 +880,9 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args) if (error) goto out; ASSERT(bp2 != NULL); - memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); - xfs_da_buf_done(bp1); + memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(dp->i_mount)); bp1 = NULL; - xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); + xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); /* * Set up the new root node. @@ -888,21 +890,17 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args) error = xfs_da_node_create(args, 0, 1, &bp1, XFS_ATTR_FORK); if (error) goto out; - node = bp1->data; - leaf = bp2->data; + node = bp1->b_addr; + leaf = bp2->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); /* both on-disk, don't endian-flip twice */ node->btree[0].hashval = leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval; node->btree[0].before = cpu_to_be32(blkno); node->hdr.count = cpu_to_be16(1); - xfs_da_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1); + xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1); error = 0; out: - if (bp1) - xfs_da_buf_done(bp1); - if (bp2) - xfs_da_buf_done(bp2); return(error); } @@ -916,12 +914,15 @@ out: * or a leaf in a node attribute list. */ STATIC int -xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) +xfs_attr_leaf_create( + xfs_da_args_t *args, + xfs_dablk_t blkno, + struct xfs_buf **bpp) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_hdr_t *hdr; xfs_inode_t *dp; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; trace_xfs_attr_leaf_create(args); @@ -933,7 +934,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) if (error) return(error); ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); hdr = &leaf->hdr; hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC); @@ -947,7 +948,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - sizeof(xfs_attr_leaf_hdr_t)); - xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); + xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); *bpp = bp; return(0); @@ -1014,7 +1015,9 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, * Add a name to the leaf attribute list structure. */ int -xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) +xfs_attr_leaf_add( + struct xfs_buf *bp, + struct xfs_da_args *args) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_hdr_t *hdr; @@ -1023,7 +1026,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) trace_xfs_attr_leaf_add(args); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(leaf->hdr.count))); @@ -1085,7 +1088,10 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args) * Add a name to a leaf attribute list structure. */ STATIC int -xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) +xfs_attr_leaf_add_work( + struct xfs_buf *bp, + xfs_da_args_t *args, + int mapindex) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_hdr_t *hdr; @@ -1096,7 +1102,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) xfs_mount_t *mp; int tmp, i; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); hdr = &leaf->hdr; ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE)); @@ -1110,7 +1116,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) tmp = be16_to_cpu(hdr->count) - args->index; tmp *= sizeof(xfs_attr_leaf_entry_t); memmove((char *)(entry+1), (char *)entry, tmp); - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); } be16_add_cpu(&hdr->count, 1); @@ -1142,7 +1148,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) args->index2++; } } - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); ASSERT((args->index == 0) || (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); @@ -1174,7 +1180,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) args->rmtblkno = 1; args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen); } - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), xfs_attr_leaf_entsize(leaf, args->index))); @@ -1198,7 +1204,7 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) } } be16_add_cpu(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index)); - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); return(0); } @@ -1207,7 +1213,9 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex) * Garbage collect a leaf attribute list block by copying it to a new buffer. */ STATIC void -xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp) +xfs_attr_leaf_compact( + struct xfs_trans *trans, + struct xfs_buf *bp) { xfs_attr_leafblock_t *leaf_s, *leaf_d; xfs_attr_leaf_hdr_t *hdr_s, *hdr_d; @@ -1217,14 +1225,14 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp) mp = trans->t_mountp; tmpbuffer = kmem_alloc(XFS_LBSIZE(mp), KM_SLEEP); ASSERT(tmpbuffer != NULL); - memcpy(tmpbuffer, bp->data, XFS_LBSIZE(mp)); - memset(bp->data, 0, XFS_LBSIZE(mp)); + memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(mp)); + memset(bp->b_addr, 0, XFS_LBSIZE(mp)); /* * Copy basic information */ leaf_s = (xfs_attr_leafblock_t *)tmpbuffer; - leaf_d = bp->data; + leaf_d = bp->b_addr; hdr_s = &leaf_s->hdr; hdr_d = &leaf_d->hdr; hdr_d->info = hdr_s->info; /* struct copy */ @@ -1247,7 +1255,7 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp) */ xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0, be16_to_cpu(hdr_s->count), mp); - xfs_da_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); + xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); kmem_free(tmpbuffer); } @@ -1279,8 +1287,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, */ ASSERT(blk1->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; + leaf1 = blk1->bp->b_addr; + leaf2 = blk2->bp->b_addr; ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); args = state->args; @@ -1298,8 +1306,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, tmp_blk = blk1; blk1 = blk2; blk2 = tmp_blk; - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; + leaf1 = blk1->bp->b_addr; + leaf2 = blk2->bp->b_addr; swap = 1; } hdr1 = &leaf1->hdr; @@ -1346,8 +1354,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, leaf2, 0, count, state->mp); - xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); - xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); + xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); + xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); } else if (count > be16_to_cpu(hdr1->count)) { /* * I assert that since all callers pass in an empty @@ -1378,8 +1386,8 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_attr_leaf_moveents(leaf2, 0, leaf1, be16_to_cpu(hdr1->count), count, state->mp); - xfs_da_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); - xfs_da_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); + xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); + xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); } /* @@ -1448,8 +1456,8 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, /* * Set up environment. */ - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; + leaf1 = blk1->bp->b_addr; + leaf2 = blk2->bp->b_addr; hdr1 = &leaf1->hdr; hdr2 = &leaf2->hdr; foundit = 0; @@ -1551,7 +1559,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) xfs_da_blkinfo_t *info; int count, bytes, forward, error, retval, i; xfs_dablk_t blkno; - xfs_dabuf_t *bp; + struct xfs_buf *bp; /* * Check for the degenerate case of the block being over 50% full. @@ -1559,7 +1567,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) * to coalesce with a sibling. */ blk = &state->path.blk[ state->path.active-1 ]; - info = blk->bp->data; + info = blk->bp->b_addr; ASSERT(info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); leaf = (xfs_attr_leafblock_t *)info; count = be16_to_cpu(leaf->hdr.count); @@ -1622,13 +1630,13 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) count = be16_to_cpu(leaf->hdr.count); bytes = state->blocksize - (state->blocksize>>2); bytes -= be16_to_cpu(leaf->hdr.usedbytes); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); count += be16_to_cpu(leaf->hdr.count); bytes -= be16_to_cpu(leaf->hdr.usedbytes); bytes -= count * sizeof(xfs_attr_leaf_entry_t); bytes -= sizeof(xfs_attr_leaf_hdr_t); - xfs_da_brelse(state->args->trans, bp); + xfs_trans_brelse(state->args->trans, bp); if (bytes >= 0) break; /* fits with at least 25% to spare */ } @@ -1666,7 +1674,9 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) * If two leaves are 37% full, when combined they will leave 25% free. */ int -xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) +xfs_attr_leaf_remove( + struct xfs_buf *bp, + xfs_da_args_t *args) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_hdr_t *hdr; @@ -1676,7 +1686,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) int tablesize, tmp, i; xfs_mount_t *mp; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); hdr = &leaf->hdr; mp = args->trans->t_mountp; @@ -1769,7 +1779,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) */ memset(xfs_attr_leaf_name(leaf, args->index), 0, entsize); be16_add_cpu(&hdr->usedbytes, -entsize); - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), entsize)); @@ -1777,7 +1787,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) * sizeof(xfs_attr_leaf_entry_t); memmove((char *)entry, (char *)(entry+1), tmp); be16_add_cpu(&hdr->count, -1); - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); entry = &leaf->entries[be16_to_cpu(hdr->count)]; memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t)); @@ -1807,7 +1817,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args) } else { hdr->holes = 1; /* mark as needing compaction */ } - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); /* @@ -1840,8 +1850,8 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, mp = state->mp; ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC); ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC); - drop_leaf = drop_blk->bp->data; - save_leaf = save_blk->bp->data; + drop_leaf = drop_blk->bp->b_addr; + save_leaf = save_blk->bp->b_addr; ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); drop_hdr = &drop_leaf->hdr; @@ -1906,7 +1916,7 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, kmem_free(tmpbuffer); } - xfs_da_log_buf(state->args->trans, save_blk->bp, 0, + xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, state->blocksize - 1); /* @@ -1934,7 +1944,9 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, * Don't change the args->value unless we find the attribute. */ int -xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) +xfs_attr_leaf_lookup_int( + struct xfs_buf *bp, + xfs_da_args_t *args) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; @@ -1945,7 +1957,7 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) trace_xfs_attr_leaf_lookup(args); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); @@ -2041,7 +2053,9 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args) * list structure. */ int -xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args) +xfs_attr_leaf_getvalue( + struct xfs_buf *bp, + xfs_da_args_t *args) { int valuelen; xfs_attr_leafblock_t *leaf; @@ -2049,7 +2063,7 @@ xfs_attr_leaf_getvalue(xfs_dabuf_t *bp, xfs_da_args_t *args) xfs_attr_leaf_name_local_t *name_loc; xfs_attr_leaf_name_remote_t *name_rmt; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(be16_to_cpu(leaf->hdr.count) < (XFS_LBSIZE(args->dp->i_mount)/8)); @@ -2247,12 +2261,14 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, * Return 0 unless leaf2 should go before leaf1. */ int -xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) +xfs_attr_leaf_order( + struct xfs_buf *leaf1_bp, + struct xfs_buf *leaf2_bp) { xfs_attr_leafblock_t *leaf1, *leaf2; - leaf1 = leaf1_bp->data; - leaf2 = leaf2_bp->data; + leaf1 = leaf1_bp->b_addr; + leaf2 = leaf2_bp->b_addr; ASSERT((leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) && (leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC))); if ((be16_to_cpu(leaf1->hdr.count) > 0) && @@ -2272,11 +2288,13 @@ xfs_attr_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) * Pick up the last hashvalue from a leaf block. */ xfs_dahash_t -xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count) +xfs_attr_leaf_lasthash( + struct xfs_buf *bp, + int *count) { xfs_attr_leafblock_t *leaf; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); if (count) *count = be16_to_cpu(leaf->hdr.count); @@ -2337,7 +2355,9 @@ xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local) * Copy out attribute list entries for attr_list(), for leaf attribute lists. */ int -xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) +xfs_attr_leaf_list_int( + struct xfs_buf *bp, + xfs_attr_list_context_t *context) { attrlist_cursor_kern_t *cursor; xfs_attr_leafblock_t *leaf; @@ -2345,7 +2365,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context) int retval, i; ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; cursor = context->cursor; cursor->initted = 1; @@ -2463,7 +2483,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; xfs_attr_leaf_name_remote_t *name_rmt; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; #ifdef DEBUG xfs_attr_leaf_name_local_t *name_loc; @@ -2482,7 +2502,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) } ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); ASSERT(args->index >= 0); @@ -2505,7 +2525,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) #endif /* DEBUG */ entry->flags &= ~XFS_ATTR_INCOMPLETE; - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); if (args->rmtblkno) { @@ -2513,10 +2533,9 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); name_rmt->valuelen = cpu_to_be32(args->valuelen); - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } - xfs_da_buf_done(bp); /* * Commit the flag value change and start the next trans in series. @@ -2533,7 +2552,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; xfs_attr_leaf_name_remote_t *name_rmt; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; trace_xfs_attr_leaf_setflag(args); @@ -2548,7 +2567,7 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) } ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); ASSERT(args->index >= 0); @@ -2556,16 +2575,15 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0); entry->flags |= XFS_ATTR_INCOMPLETE; - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); if ((entry->flags & XFS_ATTR_LOCAL) == 0) { name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); name_rmt->valueblk = 0; name_rmt->valuelen = 0; - xfs_da_log_buf(args->trans, bp, + xfs_trans_log_buf(args->trans, bp, XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt))); } - xfs_da_buf_done(bp); /* * Commit the flag value change and start the next trans in series. @@ -2586,7 +2604,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) xfs_attr_leafblock_t *leaf1, *leaf2; xfs_attr_leaf_entry_t *entry1, *entry2; xfs_attr_leaf_name_remote_t *name_rmt; - xfs_dabuf_t *bp1, *bp2; + struct xfs_buf *bp1, *bp2; int error; #ifdef DEBUG xfs_attr_leaf_name_local_t *name_loc; @@ -2620,13 +2638,13 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) bp2 = bp1; } - leaf1 = bp1->data; + leaf1 = bp1->b_addr; ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(args->index < be16_to_cpu(leaf1->hdr.count)); ASSERT(args->index >= 0); entry1 = &leaf1->entries[ args->index ]; - leaf2 = bp2->data; + leaf2 = bp2->b_addr; ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count)); ASSERT(args->index2 >= 0); @@ -2660,30 +2678,27 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) ASSERT((entry2->flags & XFS_ATTR_INCOMPLETE) == 0); entry1->flags &= ~XFS_ATTR_INCOMPLETE; - xfs_da_log_buf(args->trans, bp1, + xfs_trans_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1))); if (args->rmtblkno) { ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index); name_rmt->valueblk = cpu_to_be32(args->rmtblkno); name_rmt->valuelen = cpu_to_be32(args->valuelen); - xfs_da_log_buf(args->trans, bp1, + xfs_trans_log_buf(args->trans, bp1, XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt))); } entry2->flags |= XFS_ATTR_INCOMPLETE; - xfs_da_log_buf(args->trans, bp2, + xfs_trans_log_buf(args->trans, bp2, XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2))); if ((entry2->flags & XFS_ATTR_LOCAL) == 0) { name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2); name_rmt->valueblk = 0; name_rmt->valuelen = 0; - xfs_da_log_buf(args->trans, bp2, + xfs_trans_log_buf(args->trans, bp2, XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt))); } - xfs_da_buf_done(bp1); - if (bp1 != bp2) - xfs_da_buf_done(bp2); /* * Commit the flag value change and start the next trans in series. @@ -2706,7 +2721,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) { xfs_da_blkinfo_t *info; xfs_daddr_t blkno; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; /* @@ -2718,20 +2733,20 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) error = xfs_da_read_buf(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK); if (error) return(error); - blkno = xfs_da_blkno(bp); + blkno = XFS_BUF_ADDR(bp); /* * Invalidate the tree, even if the "tree" is only a single leaf block. * This is a depth-first traversal! */ - info = bp->data; + info = bp->b_addr; if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) { error = xfs_attr_node_inactive(trans, dp, bp, 1); } else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) { error = xfs_attr_leaf_inactive(trans, dp, bp); } else { error = XFS_ERROR(EIO); - xfs_da_brelse(*trans, bp); + xfs_trans_brelse(*trans, bp); } if (error) return(error); @@ -2742,7 +2757,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK); if (error) return(error); - xfs_da_binval(*trans, bp); /* remove from cache */ + xfs_trans_binval(*trans, bp); /* remove from cache */ /* * Commit the invalidate and start the next transaction. */ @@ -2756,34 +2771,37 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) * We're doing a depth-first traversal in order to invalidate everything. */ STATIC int -xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, - int level) +xfs_attr_node_inactive( + struct xfs_trans **trans, + struct xfs_inode *dp, + struct xfs_buf *bp, + int level) { xfs_da_blkinfo_t *info; xfs_da_intnode_t *node; xfs_dablk_t child_fsb; xfs_daddr_t parent_blkno, child_blkno; int error, count, i; - xfs_dabuf_t *child_bp; + struct xfs_buf *child_bp; /* * Since this code is recursive (gasp!) we must protect ourselves. */ if (level > XFS_DA_NODE_MAXDEPTH) { - xfs_da_brelse(*trans, bp); /* no locks for later trans */ + xfs_trans_brelse(*trans, bp); /* no locks for later trans */ return(XFS_ERROR(EIO)); } - node = bp->data; + node = bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); - parent_blkno = xfs_da_blkno(bp); /* save for re-read later */ + parent_blkno = XFS_BUF_ADDR(bp); /* save for re-read later */ count = be16_to_cpu(node->hdr.count); if (!count) { - xfs_da_brelse(*trans, bp); + xfs_trans_brelse(*trans, bp); return(0); } child_fsb = be32_to_cpu(node->btree[0].before); - xfs_da_brelse(*trans, bp); /* no locks for later trans */ + xfs_trans_brelse(*trans, bp); /* no locks for later trans */ /* * If this is the node level just above the leaves, simply loop @@ -2803,12 +2821,12 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, return(error); if (child_bp) { /* save for re-read later */ - child_blkno = xfs_da_blkno(child_bp); + child_blkno = XFS_BUF_ADDR(child_bp); /* * Invalidate the subtree, however we have to. */ - info = child_bp->data; + info = child_bp->b_addr; if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) { error = xfs_attr_node_inactive(trans, dp, child_bp, level+1); @@ -2817,7 +2835,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, child_bp); } else { error = XFS_ERROR(EIO); - xfs_da_brelse(*trans, child_bp); + xfs_trans_brelse(*trans, child_bp); } if (error) return(error); @@ -2830,7 +2848,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, &child_bp, XFS_ATTR_FORK); if (error) return(error); - xfs_da_binval(*trans, child_bp); + xfs_trans_binval(*trans, child_bp); } /* @@ -2843,7 +2861,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, if (error) return(error); child_fsb = be32_to_cpu(node->btree[i+1].before); - xfs_da_brelse(*trans, bp); + xfs_trans_brelse(*trans, bp); } /* * Atomically commit the whole invalidate stuff. @@ -2863,7 +2881,10 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp, * caught holding something that the logging code wants to flush to disk. */ STATIC int -xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) +xfs_attr_leaf_inactive( + struct xfs_trans **trans, + struct xfs_inode *dp, + struct xfs_buf *bp) { xfs_attr_leafblock_t *leaf; xfs_attr_leaf_entry_t *entry; @@ -2871,7 +2892,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) xfs_attr_inactive_list_t *list, *lp; int error, count, size, tmp, i; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); /* @@ -2892,7 +2913,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) * If there are no "remote" values, we're done. */ if (count == 0) { - xfs_da_brelse(*trans, bp); + xfs_trans_brelse(*trans, bp); return(0); } @@ -2919,7 +2940,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp) } } } - xfs_da_brelse(*trans, bp); /* unlock for trans. in freextent() */ + xfs_trans_brelse(*trans, bp); /* unlock for trans. in freextent() */ /* * Invalidate each of the "remote" value extents. diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h index 9c7d22fdcf4..dea17722945 100644 --- a/fs/xfs/xfs_attr_leaf.h +++ b/fs/xfs/xfs_attr_leaf.h @@ -31,7 +31,6 @@ struct attrlist; struct attrlist_cursor_kern; struct xfs_attr_list_context; -struct xfs_dabuf; struct xfs_da_args; struct xfs_da_state; struct xfs_da_state_blk; @@ -215,7 +214,7 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args); int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); int xfs_attr_shortform_remove(struct xfs_da_args *args); int xfs_attr_shortform_list(struct xfs_attr_list_context *context); -int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp); +int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); @@ -223,7 +222,7 @@ int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); * Internal routines when attribute fork size == XFS_LBSIZE(mp). */ int xfs_attr_leaf_to_node(struct xfs_da_args *args); -int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp, +int xfs_attr_leaf_to_shortform(struct xfs_buf *bp, struct xfs_da_args *args, int forkoff); int xfs_attr_leaf_clearflag(struct xfs_da_args *args); int xfs_attr_leaf_setflag(struct xfs_da_args *args); @@ -235,14 +234,14 @@ int xfs_attr_leaf_flipflags(xfs_da_args_t *args); int xfs_attr_leaf_split(struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); -int xfs_attr_leaf_lookup_int(struct xfs_dabuf *leaf, +int xfs_attr_leaf_lookup_int(struct xfs_buf *leaf, struct xfs_da_args *args); -int xfs_attr_leaf_getvalue(struct xfs_dabuf *bp, struct xfs_da_args *args); -int xfs_attr_leaf_add(struct xfs_dabuf *leaf_buffer, +int xfs_attr_leaf_getvalue(struct xfs_buf *bp, struct xfs_da_args *args); +int xfs_attr_leaf_add(struct xfs_buf *leaf_buffer, struct xfs_da_args *args); -int xfs_attr_leaf_remove(struct xfs_dabuf *leaf_buffer, +int xfs_attr_leaf_remove(struct xfs_buf *leaf_buffer, struct xfs_da_args *args); -int xfs_attr_leaf_list_int(struct xfs_dabuf *bp, +int xfs_attr_leaf_list_int(struct xfs_buf *bp, struct xfs_attr_list_context *context); /* @@ -257,9 +256,9 @@ int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp); /* * Utility routines. */ -xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_dabuf *bp, int *count); -int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp, - struct xfs_dabuf *leaf2_bp); +xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count); +int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, + struct xfs_buf *leaf2_bp); int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local); #endif /* __XFS_ATTR_LEAF_H__ */ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 58b815ec8c9..848ffa77707 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5517,7 +5517,7 @@ xfs_getbmap( if (xfs_get_extsz_hint(ip) || ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){ prealloced = 1; - fixlen = XFS_MAXIOFFSET(mp); + fixlen = mp->m_super->s_maxbytes; } else { prealloced = 0; fixlen = XFS_ISIZE(ip); diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 269b35c084d..d7a9dd735e1 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -164,14 +164,49 @@ xfs_buf_stale( ASSERT(atomic_read(&bp->b_hold) >= 1); } +static int +xfs_buf_get_maps( + struct xfs_buf *bp, + int map_count) +{ + ASSERT(bp->b_maps == NULL); + bp->b_map_count = map_count; + + if (map_count == 1) { + bp->b_maps = &bp->b_map; + return 0; + } + + bp->b_maps = kmem_zalloc(map_count * sizeof(struct xfs_buf_map), + KM_NOFS); + if (!bp->b_maps) + return ENOMEM; + return 0; +} + +/* + * Frees b_pages if it was allocated. + */ +static void +xfs_buf_free_maps( + struct xfs_buf *bp) +{ + if (bp->b_maps != &bp->b_map) { + kmem_free(bp->b_maps); + bp->b_maps = NULL; + } +} + struct xfs_buf * -xfs_buf_alloc( +_xfs_buf_alloc( struct xfs_buftarg *target, - xfs_daddr_t blkno, - size_t numblks, + struct xfs_buf_map *map, + int nmaps, xfs_buf_flags_t flags) { struct xfs_buf *bp; + int error; + int i; bp = kmem_zone_zalloc(xfs_buf_zone, KM_NOFS); if (unlikely(!bp)) @@ -192,16 +227,28 @@ xfs_buf_alloc( sema_init(&bp->b_sema, 0); /* held, no waiters */ XB_SET_OWNER(bp); bp->b_target = target; + bp->b_flags = flags; /* * Set length and io_length to the same value initially. * I/O routines should use io_length, which will be the same in * most cases but may be reset (e.g. XFS recovery). */ - bp->b_length = numblks; - bp->b_io_length = numblks; - bp->b_flags = flags; - bp->b_bn = blkno; + error = xfs_buf_get_maps(bp, nmaps); + if (error) { + kmem_zone_free(xfs_buf_zone, bp); + return NULL; + } + + bp->b_bn = map[0].bm_bn; + bp->b_length = 0; + for (i = 0; i < nmaps; i++) { + bp->b_maps[i].bm_bn = map[i].bm_bn; + bp->b_maps[i].bm_len = map[i].bm_len; + bp->b_length += map[i].bm_len; + } + bp->b_io_length = bp->b_length; + atomic_set(&bp->b_pin_count, 0); init_waitqueue_head(&bp->b_waiters); @@ -280,6 +327,7 @@ xfs_buf_free( } else if (bp->b_flags & _XBF_KMEM) kmem_free(bp->b_addr); _xfs_buf_free_pages(bp); + xfs_buf_free_maps(bp); kmem_zone_free(xfs_buf_zone, bp); } @@ -327,8 +375,9 @@ xfs_buf_allocate_memory( } use_alloc_page: - start = BBTOB(bp->b_bn) >> PAGE_SHIFT; - end = (BBTOB(bp->b_bn + bp->b_length) + PAGE_SIZE - 1) >> PAGE_SHIFT; + start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT; + end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1) + >> PAGE_SHIFT; page_count = end - start; error = _xfs_buf_get_pages(bp, page_count, flags); if (unlikely(error)) @@ -425,8 +474,8 @@ _xfs_buf_map_pages( xfs_buf_t * _xfs_buf_find( struct xfs_buftarg *btp, - xfs_daddr_t blkno, - size_t numblks, + struct xfs_buf_map *map, + int nmaps, xfs_buf_flags_t flags, xfs_buf_t *new_bp) { @@ -435,7 +484,12 @@ _xfs_buf_find( struct rb_node **rbp; struct rb_node *parent; xfs_buf_t *bp; + xfs_daddr_t blkno = map[0].bm_bn; + int numblks = 0; + int i; + for (i = 0; i < nmaps; i++) + numblks += map[i].bm_len; numbytes = BBTOB(numblks); /* Check for IOs smaller than the sector size / not sector aligned */ @@ -527,31 +581,31 @@ found: * more hits than misses. */ struct xfs_buf * -xfs_buf_get( - xfs_buftarg_t *target, - xfs_daddr_t blkno, - size_t numblks, +xfs_buf_get_map( + struct xfs_buftarg *target, + struct xfs_buf_map *map, + int nmaps, xfs_buf_flags_t flags) { struct xfs_buf *bp; struct xfs_buf *new_bp; int error = 0; - bp = _xfs_buf_find(target, blkno, numblks, flags, NULL); + bp = _xfs_buf_find(target, map, nmaps, flags, NULL); if (likely(bp)) goto found; - new_bp = xfs_buf_alloc(target, blkno, numblks, flags); + new_bp = _xfs_buf_alloc(target, map, nmaps, flags); if (unlikely(!new_bp)) return NULL; error = xfs_buf_allocate_memory(new_bp, flags); if (error) { - kmem_zone_free(xfs_buf_zone, new_bp); + xfs_buf_free(new_bp); return NULL; } - bp = _xfs_buf_find(target, blkno, numblks, flags, new_bp); + bp = _xfs_buf_find(target, map, nmaps, flags, new_bp); if (!bp) { xfs_buf_free(new_bp); return NULL; @@ -560,8 +614,6 @@ xfs_buf_get( if (bp != new_bp) xfs_buf_free(new_bp); - bp->b_io_length = bp->b_length; - found: if (!bp->b_addr) { error = _xfs_buf_map_pages(bp, flags); @@ -584,7 +636,7 @@ _xfs_buf_read( xfs_buf_flags_t flags) { ASSERT(!(flags & XBF_WRITE)); - ASSERT(bp->b_bn != XFS_BUF_DADDR_NULL); + ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL); bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); @@ -596,17 +648,17 @@ _xfs_buf_read( } xfs_buf_t * -xfs_buf_read( - xfs_buftarg_t *target, - xfs_daddr_t blkno, - size_t numblks, +xfs_buf_read_map( + struct xfs_buftarg *target, + struct xfs_buf_map *map, + int nmaps, xfs_buf_flags_t flags) { - xfs_buf_t *bp; + struct xfs_buf *bp; flags |= XBF_READ; - bp = xfs_buf_get(target, blkno, numblks, flags); + bp = xfs_buf_get_map(target, map, nmaps, flags); if (bp) { trace_xfs_buf_read(bp, flags, _RET_IP_); @@ -634,15 +686,15 @@ xfs_buf_read( * safe manner. */ void -xfs_buf_readahead( - xfs_buftarg_t *target, - xfs_daddr_t blkno, - size_t numblks) +xfs_buf_readahead_map( + struct xfs_buftarg *target, + struct xfs_buf_map *map, + int nmaps) { if (bdi_read_congested(target->bt_bdi)) return; - xfs_buf_read(target, blkno, numblks, + xfs_buf_read_map(target, map, nmaps, XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD); } @@ -665,8 +717,10 @@ xfs_buf_read_uncached( return NULL; /* set up the buffer for a read IO */ - XFS_BUF_SET_ADDR(bp, daddr); - XFS_BUF_READ(bp); + ASSERT(bp->b_map_count == 1); + bp->b_bn = daddr; + bp->b_maps[0].bm_bn = daddr; + bp->b_flags |= XBF_READ; xfsbdstrat(target->bt_mount, bp); error = xfs_buf_iowait(bp); @@ -694,7 +748,11 @@ xfs_buf_set_empty( bp->b_addr = NULL; bp->b_length = numblks; bp->b_io_length = numblks; + + ASSERT(bp->b_map_count == 1); bp->b_bn = XFS_BUF_DADDR_NULL; + bp->b_maps[0].bm_bn = XFS_BUF_DADDR_NULL; + bp->b_maps[0].bm_len = bp->b_length; } static inline struct page * @@ -758,9 +816,10 @@ xfs_buf_get_uncached( { unsigned long page_count; int error, i; - xfs_buf_t *bp; + struct xfs_buf *bp; + DEFINE_SINGLE_BUF_MAP(map, XFS_BUF_DADDR_NULL, numblks); - bp = xfs_buf_alloc(target, XFS_BUF_DADDR_NULL, numblks, 0); + bp = _xfs_buf_alloc(target, &map, 1, 0); if (unlikely(bp == NULL)) goto fail; @@ -791,6 +850,7 @@ xfs_buf_get_uncached( __free_page(bp->b_pages[i]); _xfs_buf_free_pages(bp); fail_free_buf: + xfs_buf_free_maps(bp); kmem_zone_free(xfs_buf_zone, bp); fail: return NULL; @@ -1144,36 +1204,39 @@ xfs_buf_bio_end_io( bio_put(bio); } -STATIC void -_xfs_buf_ioapply( - xfs_buf_t *bp) +static void +xfs_buf_ioapply_map( + struct xfs_buf *bp, + int map, + int *buf_offset, + int *count, + int rw) { - int rw, map_i, total_nr_pages, nr_pages; - struct bio *bio; - int offset = bp->b_offset; - int size = BBTOB(bp->b_io_length); - sector_t sector = bp->b_bn; + int page_index; + int total_nr_pages = bp->b_page_count; + int nr_pages; + struct bio *bio; + sector_t sector = bp->b_maps[map].bm_bn; + int size; + int offset; total_nr_pages = bp->b_page_count; - map_i = 0; - if (bp->b_flags & XBF_WRITE) { - if (bp->b_flags & XBF_SYNCIO) - rw = WRITE_SYNC; - else - rw = WRITE; - if (bp->b_flags & XBF_FUA) - rw |= REQ_FUA; - if (bp->b_flags & XBF_FLUSH) - rw |= REQ_FLUSH; - } else if (bp->b_flags & XBF_READ_AHEAD) { - rw = READA; - } else { - rw = READ; + /* skip the pages in the buffer before the start offset */ + page_index = 0; + offset = *buf_offset; + while (offset >= PAGE_SIZE) { + page_index++; + offset -= PAGE_SIZE; } - /* we only use the buffer cache for meta-data */ - rw |= REQ_META; + /* + * Limit the IO size to the length of the current vector, and update the + * remaining IO count for the next time around. + */ + size = min_t(int, BBTOB(bp->b_maps[map].bm_len), *count); + *count -= size; + *buf_offset += size; next_chunk: atomic_inc(&bp->b_io_remaining); @@ -1188,13 +1251,14 @@ next_chunk: bio->bi_private = bp; - for (; size && nr_pages; nr_pages--, map_i++) { + for (; size && nr_pages; nr_pages--, page_index++) { int rbytes, nbytes = PAGE_SIZE - offset; if (nbytes > size) nbytes = size; - rbytes = bio_add_page(bio, bp->b_pages[map_i], nbytes, offset); + rbytes = bio_add_page(bio, bp->b_pages[page_index], nbytes, + offset); if (rbytes < nbytes) break; @@ -1216,6 +1280,54 @@ next_chunk: xfs_buf_ioerror(bp, EIO); bio_put(bio); } + +} + +STATIC void +_xfs_buf_ioapply( + struct xfs_buf *bp) +{ + struct blk_plug plug; + int rw; + int offset; + int size; + int i; + + if (bp->b_flags & XBF_WRITE) { + if (bp->b_flags & XBF_SYNCIO) + rw = WRITE_SYNC; + else + rw = WRITE; + if (bp->b_flags & XBF_FUA) + rw |= REQ_FUA; + if (bp->b_flags & XBF_FLUSH) + rw |= REQ_FLUSH; + } else if (bp->b_flags & XBF_READ_AHEAD) { + rw = READA; + } else { + rw = READ; + } + + /* we only use the buffer cache for meta-data */ + rw |= REQ_META; + + /* + * Walk all the vectors issuing IO on them. Set up the initial offset + * into the buffer and the desired IO size before we start - + * _xfs_buf_ioapply_vec() will modify them appropriately for each + * subsequent call. + */ + offset = bp->b_offset; + size = BBTOB(bp->b_io_length); + blk_start_plug(&plug); + for (i = 0; i < bp->b_map_count; i++) { + xfs_buf_ioapply_map(bp, i, &offset, &size, rw); + if (bp->b_error) + break; + if (size <= 0) + break; /* all done */ + } + blk_finish_plug(&plug); } void @@ -1557,7 +1669,7 @@ xfs_buf_cmp( struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list); xfs_daddr_t diff; - diff = ap->b_bn - bp->b_bn; + diff = ap->b_map.bm_bn - bp->b_map.bm_bn; if (diff < 0) return -1; if (diff > 0) diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 79344c48008..d03b73b9604 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h @@ -58,6 +58,7 @@ typedef enum { #define _XBF_PAGES (1 << 20)/* backed by refcounted pages */ #define _XBF_KMEM (1 << 21)/* backed by heap memory */ #define _XBF_DELWRI_Q (1 << 22)/* buffer on a delwri queue */ +#define _XBF_COMPOUND (1 << 23)/* compound buffer */ typedef unsigned int xfs_buf_flags_t; @@ -75,7 +76,8 @@ typedef unsigned int xfs_buf_flags_t; { XBF_UNMAPPED, "UNMAPPED" }, /* ditto */\ { _XBF_PAGES, "PAGES" }, \ { _XBF_KMEM, "KMEM" }, \ - { _XBF_DELWRI_Q, "DELWRI_Q" } + { _XBF_DELWRI_Q, "DELWRI_Q" }, \ + { _XBF_COMPOUND, "COMPOUND" } typedef struct xfs_buftarg { dev_t bt_dev; @@ -98,6 +100,14 @@ typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); #define XB_PAGES 2 +struct xfs_buf_map { + xfs_daddr_t bm_bn; /* block number for I/O */ + int bm_len; /* size of I/O */ +}; + +#define DEFINE_SINGLE_BUF_MAP(map, blkno, numblk) \ + struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) }; + typedef struct xfs_buf { /* * first cacheline holds all the fields needed for an uncontended cache @@ -107,7 +117,7 @@ typedef struct xfs_buf { * fast-path on locking. */ struct rb_node b_rbnode; /* rbtree node */ - xfs_daddr_t b_bn; /* block number for I/O */ + xfs_daddr_t b_bn; /* block number of buffer */ int b_length; /* size of buffer in BBs */ atomic_t b_hold; /* reference count */ atomic_t b_lru_ref; /* lru reclaim ref count */ @@ -127,12 +137,16 @@ typedef struct xfs_buf { struct xfs_trans *b_transp; struct page **b_pages; /* array of page pointers */ struct page *b_page_array[XB_PAGES]; /* inline pages */ + struct xfs_buf_map *b_maps; /* compound buffer map */ + struct xfs_buf_map b_map; /* inline compound buffer map */ + int b_map_count; int b_io_length; /* IO size in BBs */ atomic_t b_pin_count; /* pin count */ atomic_t b_io_remaining; /* #outstanding I/O requests */ unsigned int b_page_count; /* size of page array */ unsigned int b_offset; /* page offset in first page */ unsigned short b_error; /* error code on I/O */ + #ifdef XFS_BUF_LOCK_TRACKING int b_last_holder; #endif @@ -140,22 +154,78 @@ typedef struct xfs_buf { /* Finding and Reading Buffers */ -struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target, xfs_daddr_t blkno, - size_t numblks, xfs_buf_flags_t flags, - struct xfs_buf *new_bp); -#define xfs_incore(buftarg,blkno,len,lockit) \ - _xfs_buf_find(buftarg, blkno ,len, lockit, NULL) - -struct xfs_buf *xfs_buf_get(struct xfs_buftarg *target, xfs_daddr_t blkno, - size_t numblks, xfs_buf_flags_t flags); -struct xfs_buf *xfs_buf_read(struct xfs_buftarg *target, xfs_daddr_t blkno, - size_t numblks, xfs_buf_flags_t flags); -void xfs_buf_readahead(struct xfs_buftarg *target, xfs_daddr_t blkno, - size_t numblks); +struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + xfs_buf_flags_t flags, struct xfs_buf *new_bp); + +static inline struct xfs_buf * +xfs_incore( + struct xfs_buftarg *target, + xfs_daddr_t blkno, + size_t numblks, + xfs_buf_flags_t flags) +{ + DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); + return _xfs_buf_find(target, &map, 1, flags, NULL); +} + +struct xfs_buf *_xfs_buf_alloc(struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + xfs_buf_flags_t flags); + +static inline struct xfs_buf * +xfs_buf_alloc( + struct xfs_buftarg *target, + xfs_daddr_t blkno, + size_t numblks, + xfs_buf_flags_t flags) +{ + DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); + return _xfs_buf_alloc(target, &map, 1, flags); +} + +struct xfs_buf *xfs_buf_get_map(struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + xfs_buf_flags_t flags); +struct xfs_buf *xfs_buf_read_map(struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + xfs_buf_flags_t flags); +void xfs_buf_readahead_map(struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps); + +static inline struct xfs_buf * +xfs_buf_get( + struct xfs_buftarg *target, + xfs_daddr_t blkno, + size_t numblks, + xfs_buf_flags_t flags) +{ + DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); + return xfs_buf_get_map(target, &map, 1, flags); +} + +static inline struct xfs_buf * +xfs_buf_read( + struct xfs_buftarg *target, + xfs_daddr_t blkno, + size_t numblks, + xfs_buf_flags_t flags) +{ + DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); + return xfs_buf_read_map(target, &map, 1, flags); +} + +static inline void +xfs_buf_readahead( + struct xfs_buftarg *target, + xfs_daddr_t blkno, + size_t numblks) +{ + DEFINE_SINGLE_BUF_MAP(map, blkno, numblks); + return xfs_buf_readahead_map(target, &map, 1); +} struct xfs_buf *xfs_buf_get_empty(struct xfs_buftarg *target, size_t numblks); -struct xfs_buf *xfs_buf_alloc(struct xfs_buftarg *target, xfs_daddr_t blkno, - size_t numblks, xfs_buf_flags_t flags); void xfs_buf_set_empty(struct xfs_buf *bp, size_t numblks); int xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t length); @@ -232,8 +302,18 @@ void xfs_buf_stale(struct xfs_buf *bp); #define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE) #define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE) -#define XFS_BUF_ADDR(bp) ((bp)->b_bn) -#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_bn = (xfs_daddr_t)(bno)) +/* + * These macros use the IO block map rather than b_bn. b_bn is now really + * just for the buffer cache index for cached buffers. As IO does not use b_bn + * anymore, uncached buffers do not use b_bn at all and hence must modify the IO + * map directly. Uncached buffers are not allowed to be discontiguous, so this + * is safe to do. + * + * In future, uncached buffers will pass the block number directly to the io + * request function and hence these macros will go away at that point. + */ +#define XFS_BUF_ADDR(bp) ((bp)->b_map.bm_bn) +#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno)) static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) { diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index d9e451115f9..a8d0ed91119 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -153,33 +153,25 @@ STATIC void xfs_buf_do_callbacks(struct xfs_buf *bp); * If the XFS_BLI_STALE flag has been set, then log nothing. */ STATIC uint -xfs_buf_item_size( - struct xfs_log_item *lip) +xfs_buf_item_size_segment( + struct xfs_buf_log_item *bip, + struct xfs_buf_log_format *blfp) { - struct xfs_buf_log_item *bip = BUF_ITEM(lip); struct xfs_buf *bp = bip->bli_buf; uint nvecs; int next_bit; int last_bit; - ASSERT(atomic_read(&bip->bli_refcount) > 0); - if (bip->bli_flags & XFS_BLI_STALE) { - /* - * The buffer is stale, so all we need to log - * is the buf log format structure with the - * cancel flag in it. - */ - trace_xfs_buf_item_size_stale(bip); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); - return 1; - } + last_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); + if (last_bit == -1) + return 0; + + /* + * initial count for a dirty buffer is 2 vectors - the format structure + * and the first dirty region. + */ + nvecs = 2; - ASSERT(bip->bli_flags & XFS_BLI_LOGGED); - nvecs = 1; - last_bit = xfs_next_bit(bip->bli_format.blf_data_map, - bip->bli_format.blf_map_size, 0); - ASSERT(last_bit != -1); - nvecs++; while (last_bit != -1) { /* * This takes the bit number to start looking from and @@ -187,16 +179,15 @@ xfs_buf_item_size( * if there are no more bits set or the start bit is * beyond the end of the bitmap. */ - next_bit = xfs_next_bit(bip->bli_format.blf_data_map, - bip->bli_format.blf_map_size, - last_bit + 1); + next_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, + last_bit + 1); /* * If we run out of bits, leave the loop, * else if we find a new set of bits bump the number of vecs, * else keep scanning the current set of bits. */ if (next_bit == -1) { - last_bit = -1; + break; } else if (next_bit != last_bit + 1) { last_bit = next_bit; nvecs++; @@ -210,22 +201,73 @@ xfs_buf_item_size( } } - trace_xfs_buf_item_size(bip); return nvecs; } /* - * This is called to fill in the vector of log iovecs for the - * given log buf item. It fills the first entry with a buf log - * format structure, and the rest point to contiguous chunks - * within the buffer. + * This returns the number of log iovecs needed to log the given buf log item. + * + * It calculates this as 1 iovec for the buf log format structure and 1 for each + * stretch of non-contiguous chunks to be logged. Contiguous chunks are logged + * in a single iovec. + * + * Discontiguous buffers need a format structure per region that that is being + * logged. This makes the changes in the buffer appear to log recovery as though + * they came from separate buffers, just like would occur if multiple buffers + * were used instead of a single discontiguous buffer. This enables + * discontiguous buffers to be in-memory constructs, completely transparent to + * what ends up on disk. + * + * If the XFS_BLI_STALE flag has been set, then log nothing but the buf log + * format structures. */ -STATIC void -xfs_buf_item_format( - struct xfs_log_item *lip, - struct xfs_log_iovec *vecp) +STATIC uint +xfs_buf_item_size( + struct xfs_log_item *lip) { struct xfs_buf_log_item *bip = BUF_ITEM(lip); + uint nvecs; + int i; + + ASSERT(atomic_read(&bip->bli_refcount) > 0); + if (bip->bli_flags & XFS_BLI_STALE) { + /* + * The buffer is stale, so all we need to log + * is the buf log format structure with the + * cancel flag in it. + */ + trace_xfs_buf_item_size_stale(bip); + ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); + return bip->bli_format_count; + } + + ASSERT(bip->bli_flags & XFS_BLI_LOGGED); + + /* + * the vector count is based on the number of buffer vectors we have + * dirty bits in. This will only be greater than one when we have a + * compound buffer with more than one segment dirty. Hence for compound + * buffers we need to track which segment the dirty bits correspond to, + * and when we move from one segment to the next increment the vector + * count for the extra buf log format structure that will need to be + * written. + */ + nvecs = 0; + for (i = 0; i < bip->bli_format_count; i++) { + nvecs += xfs_buf_item_size_segment(bip, &bip->bli_formats[i]); + } + + trace_xfs_buf_item_size(bip); + return nvecs; +} + +static struct xfs_log_iovec * +xfs_buf_item_format_segment( + struct xfs_buf_log_item *bip, + struct xfs_log_iovec *vecp, + uint offset, + struct xfs_buf_log_format *blfp) +{ struct xfs_buf *bp = bip->bli_buf; uint base_size; uint nvecs; @@ -235,40 +277,22 @@ xfs_buf_item_format( uint nbits; uint buffer_offset; - ASSERT(atomic_read(&bip->bli_refcount) > 0); - ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || - (bip->bli_flags & XFS_BLI_STALE)); + /* copy the flags across from the base format item */ + blfp->blf_flags = bip->bli_format.blf_flags; /* - * The size of the base structure is the size of the - * declared structure plus the space for the extra words - * of the bitmap. We subtract one from the map size, because - * the first element of the bitmap is accounted for in the - * size of the base structure. + * Base size is the actual size of the ondisk structure - it reflects + * the actual size of the dirty bitmap rather than the size of the in + * memory structure. */ - base_size = - (uint)(sizeof(xfs_buf_log_format_t) + - ((bip->bli_format.blf_map_size - 1) * sizeof(uint))); - vecp->i_addr = &bip->bli_format; + base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + + (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); + vecp->i_addr = blfp; vecp->i_len = base_size; vecp->i_type = XLOG_REG_TYPE_BFORMAT; vecp++; nvecs = 1; - /* - * If it is an inode buffer, transfer the in-memory state to the - * format flags and clear the in-memory state. We do not transfer - * this state if the inode buffer allocation has not yet been committed - * to the log as setting the XFS_BLI_INODE_BUF flag will prevent - * correct replay of the inode allocation. - */ - if (bip->bli_flags & XFS_BLI_INODE_BUF) { - if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && - xfs_log_item_in_current_chkpt(lip))) - bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; - bip->bli_flags &= ~XFS_BLI_INODE_BUF; - } - if (bip->bli_flags & XFS_BLI_STALE) { /* * The buffer is stale, so all we need to log @@ -276,16 +300,15 @@ xfs_buf_item_format( * cancel flag in it. */ trace_xfs_buf_item_format_stale(bip); - ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); - bip->bli_format.blf_size = nvecs; - return; + ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); + blfp->blf_size = nvecs; + return vecp; } /* * Fill in an iovec for each set of contiguous chunks. */ - first_bit = xfs_next_bit(bip->bli_format.blf_data_map, - bip->bli_format.blf_map_size, 0); + first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); ASSERT(first_bit != -1); last_bit = first_bit; nbits = 1; @@ -296,9 +319,8 @@ xfs_buf_item_format( * if there are no more bits set or the start bit is * beyond the end of the bitmap. */ - next_bit = xfs_next_bit(bip->bli_format.blf_data_map, - bip->bli_format.blf_map_size, - (uint)last_bit + 1); + next_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, + (uint)last_bit + 1); /* * If we run out of bits fill in the last iovec and get * out of the loop. @@ -309,14 +331,14 @@ xfs_buf_item_format( * keep counting and scanning. */ if (next_bit == -1) { - buffer_offset = first_bit * XFS_BLF_CHUNK; + buffer_offset = offset + first_bit * XFS_BLF_CHUNK; vecp->i_addr = xfs_buf_offset(bp, buffer_offset); vecp->i_len = nbits * XFS_BLF_CHUNK; vecp->i_type = XLOG_REG_TYPE_BCHUNK; nvecs++; break; } else if (next_bit != last_bit + 1) { - buffer_offset = first_bit * XFS_BLF_CHUNK; + buffer_offset = offset + first_bit * XFS_BLF_CHUNK; vecp->i_addr = xfs_buf_offset(bp, buffer_offset); vecp->i_len = nbits * XFS_BLF_CHUNK; vecp->i_type = XLOG_REG_TYPE_BCHUNK; @@ -325,14 +347,17 @@ xfs_buf_item_format( first_bit = next_bit; last_bit = next_bit; nbits = 1; - } else if (xfs_buf_offset(bp, next_bit << XFS_BLF_SHIFT) != - (xfs_buf_offset(bp, last_bit << XFS_BLF_SHIFT) + + } else if (xfs_buf_offset(bp, offset + + (next_bit << XFS_BLF_SHIFT)) != + (xfs_buf_offset(bp, offset + + (last_bit << XFS_BLF_SHIFT)) + XFS_BLF_CHUNK)) { - buffer_offset = first_bit * XFS_BLF_CHUNK; + buffer_offset = offset + first_bit * XFS_BLF_CHUNK; vecp->i_addr = xfs_buf_offset(bp, buffer_offset); vecp->i_len = nbits * XFS_BLF_CHUNK; vecp->i_type = XLOG_REG_TYPE_BCHUNK; -/* You would think we need to bump the nvecs here too, but we do not +/* + * You would think we need to bump the nvecs here too, but we do not * this number is used by recovery, and it gets confused by the boundary * split here * nvecs++; @@ -347,6 +372,48 @@ xfs_buf_item_format( } } bip->bli_format.blf_size = nvecs; + return vecp; +} + +/* + * This is called to fill in the vector of log iovecs for the + * given log buf item. It fills the first entry with a buf log + * format structure, and the rest point to contiguous chunks + * within the buffer. + */ +STATIC void +xfs_buf_item_format( + struct xfs_log_item *lip, + struct xfs_log_iovec *vecp) +{ + struct xfs_buf_log_item *bip = BUF_ITEM(lip); + struct xfs_buf *bp = bip->bli_buf; + uint offset = 0; + int i; + + ASSERT(atomic_read(&bip->bli_refcount) > 0); + ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || + (bip->bli_flags & XFS_BLI_STALE)); + + /* + * If it is an inode buffer, transfer the in-memory state to the + * format flags and clear the in-memory state. We do not transfer + * this state if the inode buffer allocation has not yet been committed + * to the log as setting the XFS_BLI_INODE_BUF flag will prevent + * correct replay of the inode allocation. + */ + if (bip->bli_flags & XFS_BLI_INODE_BUF) { + if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && + xfs_log_item_in_current_chkpt(lip))) + bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; + bip->bli_flags &= ~XFS_BLI_INODE_BUF; + } + + for (i = 0; i < bip->bli_format_count; i++) { + vecp = xfs_buf_item_format_segment(bip, vecp, offset, + &bip->bli_formats[i]); + offset += bp->b_maps[i].bm_len; + } /* * Check to make sure everything is consistent. @@ -622,6 +689,35 @@ static const struct xfs_item_ops xfs_buf_item_ops = { .iop_committing = xfs_buf_item_committing }; +STATIC int +xfs_buf_item_get_format( + struct xfs_buf_log_item *bip, + int count) +{ + ASSERT(bip->bli_formats == NULL); + bip->bli_format_count = count; + + if (count == 1) { + bip->bli_formats = &bip->bli_format; + return 0; + } + + bip->bli_formats = kmem_zalloc(count * sizeof(struct xfs_buf_log_format), + KM_SLEEP); + if (!bip->bli_formats) + return ENOMEM; + return 0; +} + +STATIC void +xfs_buf_item_free_format( + struct xfs_buf_log_item *bip) +{ + if (bip->bli_formats != &bip->bli_format) { + kmem_free(bip->bli_formats); + bip->bli_formats = NULL; + } +} /* * Allocate a new buf log item to go with the given buffer. @@ -639,6 +735,8 @@ xfs_buf_item_init( xfs_buf_log_item_t *bip; int chunks; int map_size; + int error; + int i; /* * Check to see if there is already a buf log item for @@ -650,25 +748,33 @@ xfs_buf_item_init( if (lip != NULL && lip->li_type == XFS_LI_BUF) return; - /* - * chunks is the number of XFS_BLF_CHUNK size pieces - * the buffer can be divided into. Make sure not to - * truncate any pieces. map_size is the size of the - * bitmap needed to describe the chunks of the buffer. - */ - chunks = (int)((BBTOB(bp->b_length) + (XFS_BLF_CHUNK - 1)) >> - XFS_BLF_SHIFT); - map_size = (int)((chunks + NBWORD) >> BIT_TO_WORD_SHIFT); - - bip = (xfs_buf_log_item_t*)kmem_zone_zalloc(xfs_buf_item_zone, - KM_SLEEP); + bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops); bip->bli_buf = bp; xfs_buf_hold(bp); - bip->bli_format.blf_type = XFS_LI_BUF; - bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); - bip->bli_format.blf_len = (ushort)bp->b_length; - bip->bli_format.blf_map_size = map_size; + + /* + * chunks is the number of XFS_BLF_CHUNK size pieces the buffer + * can be divided into. Make sure not to truncate any pieces. + * map_size is the size of the bitmap needed to describe the + * chunks of the buffer. + * + * Discontiguous buffer support follows the layout of the underlying + * buffer. This makes the implementation as simple as possible. + */ + error = xfs_buf_item_get_format(bip, bp->b_map_count); + ASSERT(error == 0); + + for (i = 0; i < bip->bli_format_count; i++) { + chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), + XFS_BLF_CHUNK); + map_size = DIV_ROUND_UP(chunks, NBWORD); + + bip->bli_formats[i].blf_type = XFS_LI_BUF; + bip->bli_formats[i].blf_blkno = bp->b_maps[i].bm_bn; + bip->bli_formats[i].blf_len = bp->b_maps[i].bm_len; + bip->bli_formats[i].blf_map_size = map_size; + } #ifdef XFS_TRANS_DEBUG /* @@ -699,10 +805,11 @@ xfs_buf_item_init( * item's bitmap. */ void -xfs_buf_item_log( - xfs_buf_log_item_t *bip, +xfs_buf_item_log_segment( + struct xfs_buf_log_item *bip, uint first, - uint last) + uint last, + uint *map) { uint first_bit; uint last_bit; @@ -715,12 +822,6 @@ xfs_buf_item_log( uint mask; /* - * Mark the item as having some dirty data for - * quick reference in xfs_buf_item_dirty. - */ - bip->bli_flags |= XFS_BLI_DIRTY; - - /* * Convert byte offsets to bit numbers. */ first_bit = first >> XFS_BLF_SHIFT; @@ -736,7 +837,7 @@ xfs_buf_item_log( * to set a bit in. */ word_num = first_bit >> BIT_TO_WORD_SHIFT; - wordp = &(bip->bli_format.blf_data_map[word_num]); + wordp = &map[word_num]; /* * Calculate the starting bit in the first word. @@ -783,6 +884,51 @@ xfs_buf_item_log( xfs_buf_item_log_debug(bip, first, last); } +/* + * Mark bytes first through last inclusive as dirty in the buf + * item's bitmap. + */ +void +xfs_buf_item_log( + xfs_buf_log_item_t *bip, + uint first, + uint last) +{ + int i; + uint start; + uint end; + struct xfs_buf *bp = bip->bli_buf; + + /* + * Mark the item as having some dirty data for + * quick reference in xfs_buf_item_dirty. + */ + bip->bli_flags |= XFS_BLI_DIRTY; + + /* + * walk each buffer segment and mark them dirty appropriately. + */ + start = 0; + for (i = 0; i < bip->bli_format_count; i++) { + if (start > last) + break; + end = start + BBTOB(bp->b_maps[i].bm_len); + if (first > end) { + start += BBTOB(bp->b_maps[i].bm_len); + continue; + } + if (first < start) + first = start; + if (end > last) + end = last; + + xfs_buf_item_log_segment(bip, first, end, + &bip->bli_formats[i].blf_data_map[0]); + + start += bp->b_maps[i].bm_len; + } +} + /* * Return 1 if the buffer has some data that has been logged (at any @@ -804,6 +950,7 @@ xfs_buf_item_free( kmem_free(bip->bli_logged); #endif /* XFS_TRANS_DEBUG */ + xfs_buf_item_free_format(bip); kmem_zone_free(xfs_buf_item_zone, bip); } diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index b6ecd2061e7..6850f49f4af 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h @@ -21,23 +21,6 @@ extern kmem_zone_t *xfs_buf_item_zone; /* - * This is the structure used to lay out a buf log item in the - * log. The data map describes which 128 byte chunks of the buffer - * have been logged. - * For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything. - */ -typedef struct xfs_buf_log_format { - unsigned short blf_type; /* buf log item type indicator */ - unsigned short blf_size; /* size of this item */ - ushort blf_flags; /* misc state */ - ushort blf_len; /* number of blocks in this buf */ - __int64_t blf_blkno; /* starting blkno of this buf */ - unsigned int blf_map_size; /* size of data bitmap in words */ - unsigned int blf_data_map[1];/* variable size bitmap of */ - /* regions of buffer in this item */ -} xfs_buf_log_format_t; - -/* * This flag indicates that the buffer contains on disk inodes * and requires special recovery handling. */ @@ -61,6 +44,23 @@ typedef struct xfs_buf_log_format { #define NBWORD (NBBY * sizeof(unsigned int)) /* + * This is the structure used to lay out a buf log item in the + * log. The data map describes which 128 byte chunks of the buffer + * have been logged. + */ +#define XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD) + +typedef struct xfs_buf_log_format { + unsigned short blf_type; /* buf log item type indicator */ + unsigned short blf_size; /* size of this item */ + ushort blf_flags; /* misc state */ + ushort blf_len; /* number of blocks in this buf */ + __int64_t blf_blkno; /* starting blkno of this buf */ + unsigned int blf_map_size; /* used size of data bitmap in words */ + unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */ +} xfs_buf_log_format_t; + +/* * buf log item flags */ #define XFS_BLI_HOLD 0x01 @@ -102,7 +102,9 @@ typedef struct xfs_buf_log_item { char *bli_orig; /* original buffer copy */ char *bli_logged; /* bytes logged (bitmap) */ #endif - xfs_buf_log_format_t bli_format; /* in-log header */ + int bli_format_count; /* count of headers */ + struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */ + struct xfs_buf_log_format bli_format; /* embedded in-log header */ } xfs_buf_log_item_t; void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 015b946c580..7bfb7dd334f 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -83,9 +83,9 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state, /* * Utility routines. */ -STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count); -STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp); -STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps); +STATIC uint xfs_da_node_lasthash(struct xfs_buf *bp, int *count); +STATIC int xfs_da_node_order(struct xfs_buf *node1_bp, + struct xfs_buf *node2_bp); STATIC int xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, xfs_da_state_blk_t *save_blk); @@ -100,10 +100,10 @@ STATIC void xfs_da_state_kill_altpath(xfs_da_state_t *state); */ int xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level, - xfs_dabuf_t **bpp, int whichfork) + struct xfs_buf **bpp, int whichfork) { xfs_da_intnode_t *node; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; xfs_trans_t *tp; @@ -114,7 +114,7 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level, if (error) return(error); ASSERT(bp != NULL); - node = bp->data; + node = bp->b_addr; node->hdr.info.forw = 0; node->hdr.info.back = 0; node->hdr.info.magic = cpu_to_be16(XFS_DA_NODE_MAGIC); @@ -122,7 +122,7 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level, node->hdr.count = 0; node->hdr.level = cpu_to_be16(level); - xfs_da_log_buf(tp, bp, + xfs_trans_log_buf(tp, bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); *bpp = bp; @@ -138,7 +138,7 @@ xfs_da_split(xfs_da_state_t *state) { xfs_da_state_blk_t *oldblk, *newblk, *addblk; xfs_da_intnode_t *node; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int max, action, error, i; trace_xfs_da_split(state->args); @@ -203,7 +203,6 @@ xfs_da_split(xfs_da_state_t *state) case XFS_DA_NODE_MAGIC: error = xfs_da_node_split(state, oldblk, newblk, addblk, max - i, &action); - xfs_da_buf_done(addblk->bp); addblk->bp = NULL; if (error) return(error); /* GROT: dir is inconsistent */ @@ -221,13 +220,6 @@ xfs_da_split(xfs_da_state_t *state) * Update the btree to show the new hashval for this child. */ xfs_da_fixhashpath(state, &state->path); - /* - * If we won't need this block again, it's getting dropped - * from the active path by the loop control, so we need - * to mark it done now. - */ - if (i > 0 || !addblk) - xfs_da_buf_done(oldblk->bp); } if (!addblk) return(0); @@ -239,8 +231,6 @@ xfs_da_split(xfs_da_state_t *state) oldblk = &state->path.blk[0]; error = xfs_da_root_split(state, oldblk, addblk); if (error) { - xfs_da_buf_done(oldblk->bp); - xfs_da_buf_done(addblk->bp); addblk->bp = NULL; return(error); /* GROT: dir is inconsistent */ } @@ -252,7 +242,7 @@ xfs_da_split(xfs_da_state_t *state) * and the original block 0 could be at any position in the list. */ - node = oldblk->bp->data; + node = oldblk->bp->b_addr; if (node->hdr.info.forw) { if (be32_to_cpu(node->hdr.info.forw) == addblk->blkno) { bp = addblk->bp; @@ -260,13 +250,13 @@ xfs_da_split(xfs_da_state_t *state) ASSERT(state->extravalid); bp = state->extrablk.bp; } - node = bp->data; + node = bp->b_addr; node->hdr.info.back = cpu_to_be32(oldblk->blkno); - xfs_da_log_buf(state->args->trans, bp, + xfs_trans_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } - node = oldblk->bp->data; + node = oldblk->bp->b_addr; if (node->hdr.info.back) { if (be32_to_cpu(node->hdr.info.back) == addblk->blkno) { bp = addblk->bp; @@ -274,14 +264,12 @@ xfs_da_split(xfs_da_state_t *state) ASSERT(state->extravalid); bp = state->extrablk.bp; } - node = bp->data; + node = bp->b_addr; node->hdr.info.forw = cpu_to_be32(oldblk->blkno); - xfs_da_log_buf(state->args->trans, bp, + xfs_trans_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } - xfs_da_buf_done(oldblk->bp); - xfs_da_buf_done(addblk->bp); addblk->bp = NULL; return(0); } @@ -298,7 +286,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_intnode_t *node, *oldroot; xfs_da_args_t *args; xfs_dablk_t blkno; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error, size; xfs_inode_t *dp; xfs_trans_t *tp; @@ -323,8 +311,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, if (error) return(error); ASSERT(bp != NULL); - node = bp->data; - oldroot = blk1->bp->data; + node = bp->b_addr; + oldroot = blk1->bp->b_addr; if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) { size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - (char *)oldroot); @@ -335,8 +323,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, (char *)leaf); } memcpy(node, oldroot, size); - xfs_da_log_buf(tp, bp, 0, size - 1); - xfs_da_buf_done(blk1->bp); + xfs_trans_log_buf(tp, bp, 0, size - 1); blk1->bp = bp; blk1->blkno = blkno; @@ -348,7 +335,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); if (error) return(error); - node = bp->data; + node = bp->b_addr; node->btree[0].hashval = cpu_to_be32(blk1->hashval); node->btree[0].before = cpu_to_be32(blk1->blkno); node->btree[1].hashval = cpu_to_be32(blk2->hashval); @@ -365,10 +352,9 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, #endif /* Header is already logged by xfs_da_node_create */ - xfs_da_log_buf(tp, bp, + xfs_trans_log_buf(tp, bp, XFS_DA_LOGRANGE(node, node->btree, sizeof(xfs_da_node_entry_t) * 2)); - xfs_da_buf_done(bp); return(0); } @@ -389,7 +375,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, trace_xfs_da_node_split(state->args); - node = oldblk->bp->data; + node = oldblk->bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); /* @@ -436,7 +422,7 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, * * If we had double-split op below us, then add the extra block too. */ - node = oldblk->bp->data; + node = oldblk->bp->b_addr; if (oldblk->index <= be16_to_cpu(node->hdr.count)) { oldblk->index++; xfs_da_node_add(state, oldblk, addblk); @@ -477,8 +463,8 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, trace_xfs_da_node_rebalance(state->args); - node1 = blk1->bp->data; - node2 = blk2->bp->data; + node1 = blk1->bp->b_addr; + node2 = blk2->bp->b_addr; /* * Figure out how many entries need to move, and in which direction. * Swap the nodes around if that makes it simpler. @@ -532,7 +518,7 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, btree_d = &node1->btree[be16_to_cpu(node1->hdr.count)]; memcpy(btree_d, btree_s, tmp); be16_add_cpu(&node1->hdr.count, count); - xfs_da_log_buf(tp, blk1->bp, + xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, btree_d, tmp)); /* @@ -549,9 +535,9 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, /* * Log header of node 1 and all current bits of node 2. */ - xfs_da_log_buf(tp, blk1->bp, + xfs_trans_log_buf(tp, blk1->bp, XFS_DA_LOGRANGE(node1, &node1->hdr, sizeof(node1->hdr))); - xfs_da_log_buf(tp, blk2->bp, + xfs_trans_log_buf(tp, blk2->bp, XFS_DA_LOGRANGE(node2, &node2->hdr, sizeof(node2->hdr) + sizeof(node2->btree[0]) * be16_to_cpu(node2->hdr.count))); @@ -560,8 +546,8 @@ xfs_da_node_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * Record the last hashval from each block for upward propagation. * (note: don't use the swapped node pointers) */ - node1 = blk1->bp->data; - node2 = blk2->bp->data; + node1 = blk1->bp->b_addr; + node2 = blk2->bp->b_addr; blk1->hashval = be32_to_cpu(node1->btree[be16_to_cpu(node1->hdr.count)-1].hashval); blk2->hashval = be32_to_cpu(node2->btree[be16_to_cpu(node2->hdr.count)-1].hashval); @@ -587,7 +573,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, trace_xfs_da_node_add(state->args); - node = oldblk->bp->data; + node = oldblk->bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); ASSERT(newblk->blkno != 0); @@ -606,10 +592,10 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, } btree->hashval = cpu_to_be32(newblk->hashval); btree->before = cpu_to_be32(newblk->blkno); - xfs_da_log_buf(state->args->trans, oldblk->bp, + xfs_trans_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, btree, tmp + sizeof(*btree))); be16_add_cpu(&node->hdr.count, 1); - xfs_da_log_buf(state->args->trans, oldblk->bp, + xfs_trans_log_buf(state->args->trans, oldblk->bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); /* @@ -735,7 +721,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) xfs_da_intnode_t *oldroot; xfs_da_args_t *args; xfs_dablk_t child; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; trace_xfs_da_root_join(state->args); @@ -743,7 +729,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) args = state->args; ASSERT(args != NULL); ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC); - oldroot = root_blk->bp->data; + oldroot = root_blk->bp->b_addr; ASSERT(oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); ASSERT(!oldroot->hdr.info.forw); ASSERT(!oldroot->hdr.info.back); @@ -765,11 +751,11 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) if (error) return(error); ASSERT(bp != NULL); - xfs_da_blkinfo_onlychild_validate(bp->data, + xfs_da_blkinfo_onlychild_validate(bp->b_addr, be16_to_cpu(oldroot->hdr.level)); - memcpy(root_blk->bp->data, bp->data, state->blocksize); - xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1); + memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize); + xfs_trans_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1); error = xfs_da_shrink_inode(args, child, bp); return(error); } @@ -791,7 +777,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) xfs_da_blkinfo_t *info; int count, forward, error, retval, i; xfs_dablk_t blkno; - xfs_dabuf_t *bp; + struct xfs_buf *bp; /* * Check for the degenerate case of the block being over 50% full. @@ -799,7 +785,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) * to coalesce with a sibling. */ blk = &state->path.blk[ state->path.active-1 ]; - info = blk->bp->data; + info = blk->bp->b_addr; ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); node = (xfs_da_intnode_t *)info; count = be16_to_cpu(node->hdr.count); @@ -859,10 +845,10 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action) count = state->node_ents; count -= state->node_ents >> 2; count -= be16_to_cpu(node->hdr.count); - node = bp->data; + node = bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); count -= be16_to_cpu(node->hdr.count); - xfs_da_brelse(state->args->trans, bp); + xfs_trans_brelse(state->args->trans, bp); if (count >= 0) break; /* fits with at least 25% to spare */ } @@ -934,14 +920,14 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path) break; } for (blk--, level--; level >= 0; blk--, level--) { - node = blk->bp->data; + node = blk->bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); btree = &node->btree[ blk->index ]; if (be32_to_cpu(btree->hashval) == lasthash) break; blk->hashval = lasthash; btree->hashval = cpu_to_be32(lasthash); - xfs_da_log_buf(state->args->trans, blk->bp, + xfs_trans_log_buf(state->args->trans, blk->bp, XFS_DA_LOGRANGE(node, btree, sizeof(*btree))); lasthash = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); @@ -960,7 +946,7 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk) trace_xfs_da_node_remove(state->args); - node = drop_blk->bp->data; + node = drop_blk->bp->b_addr; ASSERT(drop_blk->index < be16_to_cpu(node->hdr.count)); ASSERT(drop_blk->index >= 0); @@ -972,15 +958,15 @@ xfs_da_node_remove(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk) tmp = be16_to_cpu(node->hdr.count) - drop_blk->index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); memmove(btree, btree + 1, tmp); - xfs_da_log_buf(state->args->trans, drop_blk->bp, + xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, btree, tmp)); btree = &node->btree[be16_to_cpu(node->hdr.count)-1]; } memset((char *)btree, 0, sizeof(xfs_da_node_entry_t)); - xfs_da_log_buf(state->args->trans, drop_blk->bp, + xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, btree, sizeof(*btree))); be16_add_cpu(&node->hdr.count, -1); - xfs_da_log_buf(state->args->trans, drop_blk->bp, + xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, sizeof(node->hdr))); /* @@ -1005,8 +991,8 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, trace_xfs_da_node_unbalance(state->args); - drop_node = drop_blk->bp->data; - save_node = save_blk->bp->data; + drop_node = drop_blk->bp->b_addr; + save_node = save_blk->bp->b_addr; ASSERT(drop_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); ASSERT(save_node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); tp = state->args->trans; @@ -1023,13 +1009,13 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, tmp = be16_to_cpu(save_node->hdr.count) * (uint)sizeof(xfs_da_node_entry_t); memmove(btree, &save_node->btree[0], tmp); btree = &save_node->btree[0]; - xfs_da_log_buf(tp, save_blk->bp, + xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, btree, (be16_to_cpu(save_node->hdr.count) + be16_to_cpu(drop_node->hdr.count)) * sizeof(xfs_da_node_entry_t))); } else { btree = &save_node->btree[be16_to_cpu(save_node->hdr.count)]; - xfs_da_log_buf(tp, save_blk->bp, + xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, btree, be16_to_cpu(drop_node->hdr.count) * sizeof(xfs_da_node_entry_t))); @@ -1042,7 +1028,7 @@ xfs_da_node_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, memcpy(btree, &drop_node->btree[0], tmp); be16_add_cpu(&save_node->hdr.count, be16_to_cpu(drop_node->hdr.count)); - xfs_da_log_buf(tp, save_blk->bp, + xfs_trans_log_buf(tp, save_blk->bp, XFS_DA_LOGRANGE(save_node, &save_node->hdr, sizeof(save_node->hdr))); @@ -1100,7 +1086,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) state->path.active--; return(error); } - curr = blk->bp->data; + curr = blk->bp->b_addr; blk->magic = be16_to_cpu(curr->magic); ASSERT(blk->magic == XFS_DA_NODE_MAGIC || blk->magic == XFS_DIR2_LEAFN_MAGIC || @@ -1110,7 +1096,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) * Search an intermediate node for a match. */ if (blk->magic == XFS_DA_NODE_MAGIC) { - node = blk->bp->data; + node = blk->bp->b_addr; max = be16_to_cpu(node->hdr.count); blk->hashval = be32_to_cpu(node->btree[max-1].hashval); @@ -1216,15 +1202,15 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, xfs_da_blkinfo_t *old_info, *new_info, *tmp_info; xfs_da_args_t *args; int before=0, error; - xfs_dabuf_t *bp; + struct xfs_buf *bp; /* * Set up environment. */ args = state->args; ASSERT(args != NULL); - old_info = old_blk->bp->data; - new_info = new_blk->bp->data; + old_info = old_blk->bp->b_addr; + new_info = new_blk->bp->b_addr; ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || old_blk->magic == XFS_DIR2_LEAFN_MAGIC || old_blk->magic == XFS_ATTR_LEAF_MAGIC); @@ -1261,12 +1247,11 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, if (error) return(error); ASSERT(bp != NULL); - tmp_info = bp->data; + tmp_info = bp->b_addr; ASSERT(be16_to_cpu(tmp_info->magic) == be16_to_cpu(old_info->magic)); ASSERT(be32_to_cpu(tmp_info->forw) == old_blk->blkno); tmp_info->forw = cpu_to_be32(new_blk->blkno); - xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); - xfs_da_buf_done(bp); + xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); } old_info->back = cpu_to_be32(new_blk->blkno); } else { @@ -1283,18 +1268,17 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, if (error) return(error); ASSERT(bp != NULL); - tmp_info = bp->data; + tmp_info = bp->b_addr; ASSERT(tmp_info->magic == old_info->magic); ASSERT(be32_to_cpu(tmp_info->back) == old_blk->blkno); tmp_info->back = cpu_to_be32(new_blk->blkno); - xfs_da_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); - xfs_da_buf_done(bp); + xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info)-1); } old_info->forw = cpu_to_be32(new_blk->blkno); } - xfs_da_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1); - xfs_da_log_buf(args->trans, new_blk->bp, 0, sizeof(*tmp_info) - 1); + xfs_trans_log_buf(args->trans, old_blk->bp, 0, sizeof(*tmp_info) - 1); + xfs_trans_log_buf(args->trans, new_blk->bp, 0, sizeof(*tmp_info) - 1); return(0); } @@ -1302,12 +1286,14 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, * Compare two intermediate nodes for "order". */ STATIC int -xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp) +xfs_da_node_order( + struct xfs_buf *node1_bp, + struct xfs_buf *node2_bp) { xfs_da_intnode_t *node1, *node2; - node1 = node1_bp->data; - node2 = node2_bp->data; + node1 = node1_bp->b_addr; + node2 = node2_bp->b_addr; ASSERT(node1->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) && node2->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); if ((be16_to_cpu(node1->hdr.count) > 0) && (be16_to_cpu(node2->hdr.count) > 0) && @@ -1324,11 +1310,13 @@ xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp) * Pick up the last hashvalue from an intermediate node. */ STATIC uint -xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count) +xfs_da_node_lasthash( + struct xfs_buf *bp, + int *count) { xfs_da_intnode_t *node; - node = bp->data; + node = bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); if (count) *count = be16_to_cpu(node->hdr.count); @@ -1346,7 +1334,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, { xfs_da_blkinfo_t *drop_info, *save_info, *tmp_info; xfs_da_args_t *args; - xfs_dabuf_t *bp; + struct xfs_buf *bp; int error; /* @@ -1354,8 +1342,8 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, */ args = state->args; ASSERT(args != NULL); - save_info = save_blk->bp->data; - drop_info = drop_blk->bp->data; + save_info = save_blk->bp->b_addr; + drop_info = drop_blk->bp->b_addr; ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || save_blk->magic == XFS_DIR2_LEAFN_MAGIC || save_blk->magic == XFS_ATTR_LEAF_MAGIC); @@ -1380,13 +1368,12 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, if (error) return(error); ASSERT(bp != NULL); - tmp_info = bp->data; + tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); ASSERT(be32_to_cpu(tmp_info->forw) == drop_blk->blkno); tmp_info->forw = cpu_to_be32(save_blk->blkno); - xfs_da_log_buf(args->trans, bp, 0, + xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); - xfs_da_buf_done(bp); } } else { trace_xfs_da_unlink_forward(args); @@ -1398,17 +1385,16 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, if (error) return(error); ASSERT(bp != NULL); - tmp_info = bp->data; + tmp_info = bp->b_addr; ASSERT(tmp_info->magic == save_info->magic); ASSERT(be32_to_cpu(tmp_info->back) == drop_blk->blkno); tmp_info->back = cpu_to_be32(save_blk->blkno); - xfs_da_log_buf(args->trans, bp, 0, + xfs_trans_log_buf(args->trans, bp, 0, sizeof(*tmp_info) - 1); - xfs_da_buf_done(bp); } } - xfs_da_log_buf(args->trans, save_blk->bp, 0, sizeof(*save_info) - 1); + xfs_trans_log_buf(args->trans, save_blk->bp, 0, sizeof(*save_info) - 1); return(0); } @@ -1443,7 +1429,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, level = (path->active-1) - 1; /* skip bottom layer in path */ for (blk = &path->blk[level]; level >= 0; blk--, level--) { ASSERT(blk->bp != NULL); - node = blk->bp->data; + node = blk->bp->b_addr; ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); if (forward && (blk->index < be16_to_cpu(node->hdr.count)-1)) { blk->index++; @@ -1471,7 +1457,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, * (if it's dirty, trans won't actually let go) */ if (release) - xfs_da_brelse(args->trans, blk->bp); + xfs_trans_brelse(args->trans, blk->bp); /* * Read the next child block. @@ -1482,7 +1468,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, if (error) return(error); ASSERT(blk->bp != NULL); - info = blk->bp->data; + info = blk->bp->b_addr; ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); @@ -1702,11 +1688,13 @@ xfs_da_grow_inode( * a bmap btree split to do that. */ STATIC int -xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, - xfs_dabuf_t **dead_bufp) +xfs_da_swap_lastblock( + xfs_da_args_t *args, + xfs_dablk_t *dead_blknop, + struct xfs_buf **dead_bufp) { xfs_dablk_t dead_blkno, last_blkno, sib_blkno, par_blkno; - xfs_dabuf_t *dead_buf, *last_buf, *sib_buf, *par_buf; + struct xfs_buf *dead_buf, *last_buf, *sib_buf, *par_buf; xfs_fileoff_t lastoff; xfs_inode_t *ip; xfs_trans_t *tp; @@ -1744,9 +1732,9 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, /* * Copy the last block into the dead buffer and log it. */ - memcpy(dead_buf->data, last_buf->data, mp->m_dirblksize); - xfs_da_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1); - dead_info = dead_buf->data; + memcpy(dead_buf->b_addr, last_buf->b_addr, mp->m_dirblksize); + xfs_trans_log_buf(tp, dead_buf, 0, mp->m_dirblksize - 1); + dead_info = dead_buf->b_addr; /* * Get values from the moved block. */ @@ -1767,7 +1755,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, if ((sib_blkno = be32_to_cpu(dead_info->back))) { if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; - sib_info = sib_buf->data; + sib_info = sib_buf->b_addr; if (unlikely( be32_to_cpu(sib_info->forw) != last_blkno || sib_info->magic != dead_info->magic)) { @@ -1777,10 +1765,9 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, goto done; } sib_info->forw = cpu_to_be32(dead_blkno); - xfs_da_log_buf(tp, sib_buf, + xfs_trans_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->forw, sizeof(sib_info->forw))); - xfs_da_buf_done(sib_buf); sib_buf = NULL; } /* @@ -1789,7 +1776,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, if ((sib_blkno = be32_to_cpu(dead_info->forw))) { if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; - sib_info = sib_buf->data; + sib_info = sib_buf->b_addr; if (unlikely( be32_to_cpu(sib_info->back) != last_blkno || sib_info->magic != dead_info->magic)) { @@ -1799,10 +1786,9 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, goto done; } sib_info->back = cpu_to_be32(dead_blkno); - xfs_da_log_buf(tp, sib_buf, + xfs_trans_log_buf(tp, sib_buf, XFS_DA_LOGRANGE(sib_info, &sib_info->back, sizeof(sib_info->back))); - xfs_da_buf_done(sib_buf); sib_buf = NULL; } par_blkno = mp->m_dirleafblk; @@ -1813,7 +1799,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, for (;;) { if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w))) goto done; - par_node = par_buf->data; + par_node = par_buf->b_addr; if (unlikely(par_node->hdr.info.magic != cpu_to_be16(XFS_DA_NODE_MAGIC) || (level >= 0 && level != be16_to_cpu(par_node->hdr.level) + 1))) { @@ -1837,7 +1823,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, par_blkno = be32_to_cpu(par_node->btree[entno].before); if (level == dead_level + 1) break; - xfs_da_brelse(tp, par_buf); + xfs_trans_brelse(tp, par_buf); par_buf = NULL; } /* @@ -1853,7 +1839,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, if (entno < be16_to_cpu(par_node->hdr.count)) break; par_blkno = be32_to_cpu(par_node->hdr.info.forw); - xfs_da_brelse(tp, par_buf); + xfs_trans_brelse(tp, par_buf); par_buf = NULL; if (unlikely(par_blkno == 0)) { XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)", @@ -1863,7 +1849,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, } if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w))) goto done; - par_node = par_buf->data; + par_node = par_buf->b_addr; if (unlikely( be16_to_cpu(par_node->hdr.level) != level || par_node->hdr.info.magic != cpu_to_be16(XFS_DA_NODE_MAGIC))) { @@ -1878,20 +1864,18 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, * Update the parent entry pointing to the moved block. */ par_node->btree[entno].before = cpu_to_be32(dead_blkno); - xfs_da_log_buf(tp, par_buf, + xfs_trans_log_buf(tp, par_buf, XFS_DA_LOGRANGE(par_node, &par_node->btree[entno].before, sizeof(par_node->btree[entno].before))); - xfs_da_buf_done(par_buf); - xfs_da_buf_done(dead_buf); *dead_blknop = last_blkno; *dead_bufp = last_buf; return 0; done: if (par_buf) - xfs_da_brelse(tp, par_buf); + xfs_trans_brelse(tp, par_buf); if (sib_buf) - xfs_da_brelse(tp, sib_buf); - xfs_da_brelse(tp, last_buf); + xfs_trans_brelse(tp, sib_buf); + xfs_trans_brelse(tp, last_buf); return error; } @@ -1899,8 +1883,10 @@ done: * Remove a btree block from a directory or attribute. */ int -xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, - xfs_dabuf_t *dead_buf) +xfs_da_shrink_inode( + xfs_da_args_t *args, + xfs_dablk_t dead_blkno, + struct xfs_buf *dead_buf) { xfs_inode_t *dp; int done, error, w, count; @@ -1935,7 +1921,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, break; } } - xfs_da_binval(tp, dead_buf); + xfs_trans_binval(tp, dead_buf); return error; } @@ -1967,35 +1953,75 @@ xfs_da_map_covers_blocks( } /* - * Make a dabuf. - * Used for get_buf, read_buf, read_bufr, and reada_buf. + * Convert a struct xfs_bmbt_irec to a struct xfs_buf_map. + * + * For the single map case, it is assumed that the caller has provided a pointer + * to a valid xfs_buf_map. For the multiple map case, this function will + * allocate the xfs_buf_map to hold all the maps and replace the caller's single + * map pointer with the allocated map. */ -STATIC int -xfs_da_do_buf( - xfs_trans_t *trans, - xfs_inode_t *dp, - xfs_dablk_t bno, - xfs_daddr_t *mappedbnop, - xfs_dabuf_t **bpp, - int whichfork, - int caller) +static int +xfs_buf_map_from_irec( + struct xfs_mount *mp, + struct xfs_buf_map **mapp, + unsigned int *nmaps, + struct xfs_bmbt_irec *irecs, + unsigned int nirecs) { - xfs_buf_t *bp = NULL; - xfs_buf_t **bplist; - int error=0; - int i; - xfs_bmbt_irec_t map; - xfs_bmbt_irec_t *mapp; - xfs_daddr_t mappedbno; - xfs_mount_t *mp; - int nbplist=0; - int nfsb; - int nmap; - xfs_dabuf_t *rbp; + struct xfs_buf_map *map; + int i; + + ASSERT(*nmaps == 1); + ASSERT(nirecs >= 1); + + if (nirecs > 1) { + map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), KM_SLEEP); + if (!map) + return ENOMEM; + *mapp = map; + } + + *nmaps = nirecs; + map = *mapp; + for (i = 0; i < *nmaps; i++) { + ASSERT(irecs[i].br_startblock != DELAYSTARTBLOCK && + irecs[i].br_startblock != HOLESTARTBLOCK); + map[i].bm_bn = XFS_FSB_TO_DADDR(mp, irecs[i].br_startblock); + map[i].bm_len = XFS_FSB_TO_BB(mp, irecs[i].br_blockcount); + } + return 0; +} + +/* + * Map the block we are given ready for reading. There are three possible return + * values: + * -1 - will be returned if we land in a hole and mappedbno == -2 so the + * caller knows not to execute a subsequent read. + * 0 - if we mapped the block successfully + * >0 - positive error number if there was an error. + */ +static int +xfs_dabuf_map( + struct xfs_trans *trans, + struct xfs_inode *dp, + xfs_dablk_t bno, + xfs_daddr_t mappedbno, + int whichfork, + struct xfs_buf_map **map, + int *nmaps) +{ + struct xfs_mount *mp = dp->i_mount; + int nfsb; + int error = 0; + struct xfs_bmbt_irec irec; + struct xfs_bmbt_irec *irecs = &irec; + int nirecs; + + ASSERT(map && *map); + ASSERT(*nmaps == 1); - mp = dp->i_mount; nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; - mappedbno = *mappedbnop; + /* * Caller doesn't have a mapping. -2 means don't complain * if we land in a hole. @@ -2004,112 +2030,150 @@ xfs_da_do_buf( /* * Optimize the one-block case. */ - if (nfsb == 1) - mapp = ↦ - else - mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP); + if (nfsb != 1) + irecs = kmem_zalloc(sizeof(irec) * nfsb, KM_SLEEP); - nmap = nfsb; - error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, mapp, - &nmap, xfs_bmapi_aflag(whichfork)); + nirecs = nfsb; + error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, irecs, + &nirecs, xfs_bmapi_aflag(whichfork)); if (error) - goto exit0; + goto out; } else { - map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); - map.br_startoff = (xfs_fileoff_t)bno; - map.br_blockcount = nfsb; - mapp = ↦ - nmap = 1; + irecs->br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); + irecs->br_startoff = (xfs_fileoff_t)bno; + irecs->br_blockcount = nfsb; + irecs->br_state = 0; + nirecs = 1; } - if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) { - error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED); + + if (!xfs_da_map_covers_blocks(nirecs, irecs, bno, nfsb)) { + error = mappedbno == -2 ? -1 : XFS_ERROR(EFSCORRUPTED); if (unlikely(error == EFSCORRUPTED)) { if (xfs_error_level >= XFS_ERRLEVEL_LOW) { + int i; xfs_alert(mp, "%s: bno %lld dir: inode %lld", __func__, (long long)bno, (long long)dp->i_ino); - for (i = 0; i < nmap; i++) { + for (i = 0; i < *nmaps; i++) { xfs_alert(mp, "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", i, - (long long)mapp[i].br_startoff, - (long long)mapp[i].br_startblock, - (long long)mapp[i].br_blockcount, - mapp[i].br_state); + (long long)irecs[i].br_startoff, + (long long)irecs[i].br_startblock, + (long long)irecs[i].br_blockcount, + irecs[i].br_state); } } XFS_ERROR_REPORT("xfs_da_do_buf(1)", XFS_ERRLEVEL_LOW, mp); } - goto exit0; + goto out; } - if (caller != 3 && nmap > 1) { - bplist = kmem_alloc(sizeof(*bplist) * nmap, KM_SLEEP); - nbplist = 0; - } else - bplist = NULL; - /* - * Turn the mapping(s) into buffer(s). - */ - for (i = 0; i < nmap; i++) { - int nmapped; - - mappedbno = XFS_FSB_TO_DADDR(mp, mapp[i].br_startblock); - if (i == 0) - *mappedbnop = mappedbno; - nmapped = (int)XFS_FSB_TO_BB(mp, mapp[i].br_blockcount); - switch (caller) { - case 0: - bp = xfs_trans_get_buf(trans, mp->m_ddev_targp, - mappedbno, nmapped, 0); - error = bp ? bp->b_error : XFS_ERROR(EIO); - break; - case 1: - case 2: - bp = NULL; - error = xfs_trans_read_buf(mp, trans, mp->m_ddev_targp, - mappedbno, nmapped, 0, &bp); - break; - case 3: - xfs_buf_readahead(mp->m_ddev_targp, mappedbno, nmapped); + error = xfs_buf_map_from_irec(mp, map, nmaps, irecs, nirecs); +out: + if (irecs != &irec) + kmem_free(irecs); + return error; +} + +/* + * Get a buffer for the dir/attr block. + */ +int +xfs_da_get_buf( + struct xfs_trans *trans, + struct xfs_inode *dp, + xfs_dablk_t bno, + xfs_daddr_t mappedbno, + struct xfs_buf **bpp, + int whichfork) +{ + struct xfs_buf *bp; + struct xfs_buf_map map; + struct xfs_buf_map *mapp; + int nmap; + int error; + + *bpp = NULL; + mapp = ↦ + nmap = 1; + error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, + &mapp, &nmap); + if (error) { + /* mapping a hole is not an error, but we don't continue */ + if (error == -1) error = 0; - bp = NULL; - break; - } - if (error) { - if (bp) - xfs_trans_brelse(trans, bp); - goto exit1; - } - if (!bp) - continue; - if (caller == 1) { - if (whichfork == XFS_ATTR_FORK) - xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); - else - xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); - } - if (bplist) { - bplist[nbplist++] = bp; - } + goto out_free; } - /* - * Build a dabuf structure. - */ - if (bplist) { - rbp = xfs_da_buf_make(nbplist, bplist); - } else if (bp) - rbp = xfs_da_buf_make(1, &bp); + + bp = xfs_trans_get_buf_map(trans, dp->i_mount->m_ddev_targp, + mapp, nmap, 0); + error = bp ? bp->b_error : XFS_ERROR(EIO); + if (error) { + xfs_trans_brelse(trans, bp); + goto out_free; + } + + *bpp = bp; + +out_free: + if (mapp != &map) + kmem_free(mapp); + + return error; +} + +/* + * Get a buffer for the dir/attr block, fill in the contents. + */ +int +xfs_da_read_buf( + struct xfs_trans *trans, + struct xfs_inode *dp, + xfs_dablk_t bno, + xfs_daddr_t mappedbno, + struct xfs_buf **bpp, + int whichfork) +{ + struct xfs_buf *bp; + struct xfs_buf_map map; + struct xfs_buf_map *mapp; + int nmap; + int error; + + *bpp = NULL; + mapp = ↦ + nmap = 1; + error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, + &mapp, &nmap); + if (error) { + /* mapping a hole is not an error, but we don't continue */ + if (error == -1) + error = 0; + goto out_free; + } + + error = xfs_trans_read_buf_map(dp->i_mount, trans, + dp->i_mount->m_ddev_targp, + mapp, nmap, 0, &bp); + if (error) + goto out_free; + + if (whichfork == XFS_ATTR_FORK) + xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); else - rbp = NULL; + xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); + /* - * For read_buf, check the magic number. + * This verification code will be moved to a CRC verification callback + * function so just leave it here unchanged until then. */ - if (caller == 1) { - xfs_dir2_data_hdr_t *hdr = rbp->data; - xfs_dir2_free_t *free = rbp->data; - xfs_da_blkinfo_t *info = rbp->data; + { + xfs_dir2_data_hdr_t *hdr = bp->b_addr; + xfs_dir2_free_t *free = bp->b_addr; + xfs_da_blkinfo_t *info = bp->b_addr; uint magic, magic1; + struct xfs_mount *mp = dp->i_mount; magic = be16_to_cpu(info->magic); magic1 = be32_to_cpu(hdr->magic); @@ -2123,66 +2187,20 @@ xfs_da_do_buf( (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)), mp, XFS_ERRTAG_DA_READ_BUF, XFS_RANDOM_DA_READ_BUF))) { - trace_xfs_da_btree_corrupt(rbp->bps[0], _RET_IP_); + trace_xfs_da_btree_corrupt(bp, _RET_IP_); XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", XFS_ERRLEVEL_LOW, mp, info); error = XFS_ERROR(EFSCORRUPTED); - xfs_da_brelse(trans, rbp); - nbplist = 0; - goto exit1; + xfs_trans_brelse(trans, bp); + goto out_free; } } - if (bplist) { - kmem_free(bplist); - } - if (mapp != &map) { - kmem_free(mapp); - } - if (bpp) - *bpp = rbp; - return 0; -exit1: - if (bplist) { - for (i = 0; i < nbplist; i++) - xfs_trans_brelse(trans, bplist[i]); - kmem_free(bplist); - } -exit0: + *bpp = bp; +out_free: if (mapp != &map) kmem_free(mapp); - if (bpp) - *bpp = NULL; - return error; -} - -/* - * Get a buffer for the dir/attr block. - */ -int -xfs_da_get_buf( - xfs_trans_t *trans, - xfs_inode_t *dp, - xfs_dablk_t bno, - xfs_daddr_t mappedbno, - xfs_dabuf_t **bpp, - int whichfork) -{ - return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0); -} -/* - * Get a buffer for the dir/attr block, fill in the contents. - */ -int -xfs_da_read_buf( - xfs_trans_t *trans, - xfs_inode_t *dp, - xfs_dablk_t bno, - xfs_daddr_t mappedbno, - xfs_dabuf_t **bpp, - int whichfork) -{ - return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1); + return error; } /* @@ -2190,22 +2208,41 @@ xfs_da_read_buf( */ xfs_daddr_t xfs_da_reada_buf( - xfs_trans_t *trans, - xfs_inode_t *dp, - xfs_dablk_t bno, - int whichfork) + struct xfs_trans *trans, + struct xfs_inode *dp, + xfs_dablk_t bno, + int whichfork) { - xfs_daddr_t rval; + xfs_daddr_t mappedbno = -1; + struct xfs_buf_map map; + struct xfs_buf_map *mapp; + int nmap; + int error; + + mapp = ↦ + nmap = 1; + error = xfs_dabuf_map(trans, dp, bno, -1, whichfork, + &mapp, &nmap); + if (error) { + /* mapping a hole is not an error, but we don't continue */ + if (error == -1) + error = 0; + goto out_free; + } - rval = -1; - if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3)) + mappedbno = mapp[0].bm_bn; + xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap); + +out_free: + if (mapp != &map) + kmem_free(mapp); + + if (error) return -1; - else - return rval; + return mappedbno; } kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ -kmem_zone_t *xfs_dabuf_zone; /* dabuf zone */ /* * Allocate a dir-state structure. @@ -2225,13 +2262,8 @@ xfs_da_state_kill_altpath(xfs_da_state_t *state) { int i; - for (i = 0; i < state->altpath.active; i++) { - if (state->altpath.blk[i].bp) { - if (state->altpath.blk[i].bp != state->path.blk[i].bp) - xfs_da_buf_done(state->altpath.blk[i].bp); - state->altpath.blk[i].bp = NULL; - } - } + for (i = 0; i < state->altpath.active; i++) + state->altpath.blk[i].bp = NULL; state->altpath.active = 0; } @@ -2241,204 +2273,9 @@ xfs_da_state_kill_altpath(xfs_da_state_t *state) void xfs_da_state_free(xfs_da_state_t *state) { - int i; - xfs_da_state_kill_altpath(state); - for (i = 0; i < state->path.active; i++) { - if (state->path.blk[i].bp) - xfs_da_buf_done(state->path.blk[i].bp); - } - if (state->extravalid && state->extrablk.bp) - xfs_da_buf_done(state->extrablk.bp); #ifdef DEBUG memset((char *)state, 0, sizeof(*state)); #endif /* DEBUG */ kmem_zone_free(xfs_da_state_zone, state); } - -/* - * Create a dabuf. - */ -/* ARGSUSED */ -STATIC xfs_dabuf_t * -xfs_da_buf_make(int nbuf, xfs_buf_t **bps) -{ - xfs_buf_t *bp; - xfs_dabuf_t *dabuf; - int i; - int off; - - if (nbuf == 1) - dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS); - else - dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS); - dabuf->dirty = 0; - if (nbuf == 1) { - dabuf->nbuf = 1; - bp = bps[0]; - dabuf->bbcount = bp->b_length; - dabuf->data = bp->b_addr; - dabuf->bps[0] = bp; - } else { - dabuf->nbuf = nbuf; - for (i = 0, dabuf->bbcount = 0; i < nbuf; i++) { - dabuf->bps[i] = bp = bps[i]; - dabuf->bbcount += bp->b_length; - } - dabuf->data = kmem_alloc(BBTOB(dabuf->bbcount), KM_SLEEP); - for (i = off = 0; i < nbuf; i++, off += BBTOB(bp->b_length)) { - bp = bps[i]; - memcpy((char *)dabuf->data + off, bp->b_addr, - BBTOB(bp->b_length)); - } - } - return dabuf; -} - -/* - * Un-dirty a dabuf. - */ -STATIC void -xfs_da_buf_clean(xfs_dabuf_t *dabuf) -{ - xfs_buf_t *bp; - int i; - int off; - - if (dabuf->dirty) { - ASSERT(dabuf->nbuf > 1); - dabuf->dirty = 0; - for (i = off = 0; i < dabuf->nbuf; - i++, off += BBTOB(bp->b_length)) { - bp = dabuf->bps[i]; - memcpy(bp->b_addr, dabuf->data + off, - BBTOB(bp->b_length)); - } - } -} - -/* - * Release a dabuf. - */ -void -xfs_da_buf_done(xfs_dabuf_t *dabuf) -{ - ASSERT(dabuf); - ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); - if (dabuf->dirty) - xfs_da_buf_clean(dabuf); - if (dabuf->nbuf > 1) { - kmem_free(dabuf->data); - kmem_free(dabuf); - } else { - kmem_zone_free(xfs_dabuf_zone, dabuf); - } -} - -/* - * Log transaction from a dabuf. - */ -void -xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last) -{ - xfs_buf_t *bp; - uint f; - int i; - uint l; - int off; - - ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); - if (dabuf->nbuf == 1) { - ASSERT(dabuf->data == dabuf->bps[0]->b_addr); - xfs_trans_log_buf(tp, dabuf->bps[0], first, last); - return; - } - dabuf->dirty = 1; - ASSERT(first <= last); - for (i = off = 0; i < dabuf->nbuf; i++, off += BBTOB(bp->b_length)) { - bp = dabuf->bps[i]; - f = off; - l = f + BBTOB(bp->b_length) - 1; - if (f < first) - f = first; - if (l > last) - l = last; - if (f <= l) - xfs_trans_log_buf(tp, bp, f - off, l - off); - /* - * B_DONE is set by xfs_trans_log buf. - * If we don't set it on a new buffer (get not read) - * then if we don't put anything in the buffer it won't - * be set, and at commit it it released into the cache, - * and then a read will fail. - */ - else if (!(XFS_BUF_ISDONE(bp))) - XFS_BUF_DONE(bp); - } - ASSERT(last < off); -} - -/* - * Release dabuf from a transaction. - * Have to free up the dabuf before the buffers are released, - * since the synchronization on the dabuf is really the lock on the buffer. - */ -void -xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf) -{ - xfs_buf_t *bp; - xfs_buf_t **bplist; - int i; - int nbuf; - - ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); - if ((nbuf = dabuf->nbuf) == 1) { - bplist = &bp; - bp = dabuf->bps[0]; - } else { - bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP); - memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist)); - } - xfs_da_buf_done(dabuf); - for (i = 0; i < nbuf; i++) - xfs_trans_brelse(tp, bplist[i]); - if (bplist != &bp) - kmem_free(bplist); -} - -/* - * Invalidate dabuf from a transaction. - */ -void -xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf) -{ - xfs_buf_t *bp; - xfs_buf_t **bplist; - int i; - int nbuf; - - ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); - if ((nbuf = dabuf->nbuf) == 1) { - bplist = &bp; - bp = dabuf->bps[0]; - } else { - bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP); - memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist)); - } - xfs_da_buf_done(dabuf); - for (i = 0; i < nbuf; i++) - xfs_trans_binval(tp, bplist[i]); - if (bplist != &bp) - kmem_free(bplist); -} - -/* - * Get the first daddr from a dabuf. - */ -xfs_daddr_t -xfs_da_blkno(xfs_dabuf_t *dabuf) -{ - ASSERT(dabuf->nbuf); - ASSERT(dabuf->data); - return XFS_BUF_ADDR(dabuf->bps[0]); -} diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index dbf7c074ae7..132adafb041 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h @@ -32,7 +32,7 @@ struct zone; /* * This structure is common to both leaf nodes and non-leaf nodes in the Btree. * - * Is is used to manage a doubly linked list of all blocks at the same + * It is used to manage a doubly linked list of all blocks at the same * level in the Btree, and to identify which type of block this is. */ #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ @@ -133,24 +133,6 @@ typedef struct xfs_da_args { { XFS_DA_OP_CILOOKUP, "CILOOKUP" } /* - * Structure to describe buffer(s) for a block. - * This is needed in the directory version 2 format case, when - * multiple non-contiguous fsblocks might be needed to cover one - * logical directory block. - * If the buffer count is 1 then the data pointer points to the - * same place as the b_addr field for the buffer, else to kmem_alloced memory. - */ -typedef struct xfs_dabuf { - int nbuf; /* number of buffer pointers present */ - short dirty; /* data needs to be copied back */ - short bbcount; /* how large is data in bbs */ - void *data; /* pointer for buffers' data */ - struct xfs_buf *bps[1]; /* actually nbuf of these */ -} xfs_dabuf_t; -#define XFS_DA_BUF_SIZE(n) \ - (sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1)) - -/* * Storage for holding state during Btree searches and split/join ops. * * Only need space for 5 intermediate nodes. With a minimum of 62-way @@ -158,7 +140,7 @@ typedef struct xfs_dabuf { * which is slightly more than enough. */ typedef struct xfs_da_state_blk { - xfs_dabuf_t *bp; /* buffer containing block */ + struct xfs_buf *bp; /* buffer containing block */ xfs_dablk_t blkno; /* filesystem blkno of buffer */ xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */ int index; /* relevant index into block */ @@ -211,7 +193,7 @@ struct xfs_nameops { * Routines used for growing the Btree. */ int xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level, - xfs_dabuf_t **bpp, int whichfork); + struct xfs_buf **bpp, int whichfork); int xfs_da_split(xfs_da_state_t *state); /* @@ -241,14 +223,14 @@ int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno, int count); int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, - xfs_dabuf_t **bp, int whichfork); + struct xfs_buf **bp, int whichfork); int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, xfs_daddr_t mappedbno, - xfs_dabuf_t **bpp, int whichfork); + struct xfs_buf **bpp, int whichfork); xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp, xfs_dablk_t bno, int whichfork); int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, - xfs_dabuf_t *dead_buf); + struct xfs_buf *dead_buf); uint xfs_da_hashname(const __uint8_t *name_string, int name_length); enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, @@ -258,15 +240,7 @@ enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, xfs_da_state_t *xfs_da_state_alloc(void); void xfs_da_state_free(xfs_da_state_t *state); -void xfs_da_buf_done(xfs_dabuf_t *dabuf); -void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first, - uint last); -void xfs_da_brelse(struct xfs_trans *tp, xfs_dabuf_t *dabuf); -void xfs_da_binval(struct xfs_trans *tp, xfs_dabuf_t *dabuf); -xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf); - extern struct kmem_zone *xfs_da_state_zone; -extern struct kmem_zone *xfs_dabuf_zone; extern const struct xfs_nameops xfs_default_nameops; #endif /* __XFS_DA_BTREE_H__ */ diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index a3721633abc..1d9643b3dce 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -33,7 +33,7 @@ typedef struct xfs_timestamp { * variable size the leftover area split into a data and an attribute fork. * The format of the data and attribute fork depends on the format of the * inode as indicated by di_format and di_aformat. To access the data and - * attribute use the XFS_DFORK_PTR, XFS_DFORK_DPTR, and XFS_DFORK_PTR macros + * attribute use the XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR macros * below. * * There is a very similar struct icdinode in xfs_inode which matches the diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 67a250c36d4..b26a50f9921 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -592,7 +592,7 @@ int xfs_dir2_shrink_inode( xfs_da_args_t *args, xfs_dir2_db_t db, - xfs_dabuf_t *bp) + struct xfs_buf *bp) { xfs_fileoff_t bno; /* directory file offset */ xfs_dablk_t da; /* directory file offset */ @@ -634,7 +634,7 @@ xfs_dir2_shrink_inode( /* * Invalidate the buffer from the transaction. */ - xfs_da_binval(tp, bp); + xfs_trans_binval(tp, bp); /* * If it's not a data block, we're done. */ diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 586732f2d80..e93ca8f054f 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -37,10 +37,10 @@ /* * Local function prototypes. */ -static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, xfs_dabuf_t *bp, int first, - int last); -static void xfs_dir2_block_log_tail(xfs_trans_t *tp, xfs_dabuf_t *bp); -static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp, +static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp, + int first, int last); +static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp); +static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp, int *entno); static int xfs_dir2_block_sort(const void *a, const void *b); @@ -66,7 +66,7 @@ xfs_dir2_block_addname( xfs_dir2_data_free_t *bf; /* bestfree table in block */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ - xfs_dabuf_t *bp; /* buffer for block */ + struct xfs_buf *bp; /* buffer for block */ xfs_dir2_block_tail_t *btp; /* block tail */ int compact; /* need to compact leaf ents */ xfs_dir2_data_entry_t *dep; /* block data entry */ @@ -102,14 +102,14 @@ xfs_dir2_block_addname( return error; } ASSERT(bp != NULL); - hdr = bp->data; + hdr = bp->b_addr; /* * Check the magic number, corrupted if wrong. */ if (unlikely(hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))) { XFS_CORRUPTION_ERROR("xfs_dir2_block_addname", XFS_ERRLEVEL_LOW, mp, hdr); - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); return XFS_ERROR(EFSCORRUPTED); } len = xfs_dir2_data_entsize(args->namelen); @@ -212,7 +212,7 @@ xfs_dir2_block_addname( * If this isn't a real add, we're done with the buffer. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); /* * If we don't have space for the new entry & leaf ... */ @@ -228,7 +228,6 @@ xfs_dir2_block_addname( * Then add the new entry in that format. */ error = xfs_dir2_block_to_leaf(args, bp); - xfs_da_buf_done(bp); if (error) return error; return xfs_dir2_leaf_addname(args); @@ -422,7 +421,6 @@ xfs_dir2_block_addname( xfs_dir2_block_log_tail(tp, bp); xfs_dir2_data_log_entry(tp, bp, dep); xfs_dir2_data_check(dp, bp); - xfs_da_buf_done(bp); return 0; } @@ -437,7 +435,7 @@ xfs_dir2_block_getdents( filldir_t filldir) { xfs_dir2_data_hdr_t *hdr; /* block header */ - xfs_dabuf_t *bp; /* buffer for block */ + struct xfs_buf *bp; /* buffer for block */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_dir2_data_unused_t *dup; /* block unused entry */ @@ -469,7 +467,7 @@ xfs_dir2_block_getdents( * We'll skip entries before this. */ wantoff = xfs_dir2_dataptr_to_off(mp, *offset); - hdr = bp->data; + hdr = bp->b_addr; xfs_dir2_data_check(dp, bp); /* * Set up values for the loop. @@ -514,7 +512,7 @@ xfs_dir2_block_getdents( cook & 0x7fffffff, be64_to_cpu(dep->inumber), DT_UNKNOWN)) { *offset = cook & 0x7fffffff; - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return 0; } } @@ -525,7 +523,7 @@ xfs_dir2_block_getdents( */ *offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & 0x7fffffff; - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return 0; } @@ -535,17 +533,17 @@ xfs_dir2_block_getdents( static void xfs_dir2_block_log_leaf( xfs_trans_t *tp, /* transaction structure */ - xfs_dabuf_t *bp, /* block buffer */ + struct xfs_buf *bp, /* block buffer */ int first, /* index of first logged leaf */ int last) /* index of last logged leaf */ { - xfs_dir2_data_hdr_t *hdr = bp->data; + xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_leaf_entry_t *blp; xfs_dir2_block_tail_t *btp; btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr); blp = xfs_dir2_block_leaf_p(btp); - xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), + xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), (uint)((char *)&blp[last + 1] - (char *)hdr - 1)); } @@ -555,13 +553,13 @@ xfs_dir2_block_log_leaf( static void xfs_dir2_block_log_tail( xfs_trans_t *tp, /* transaction structure */ - xfs_dabuf_t *bp) /* block buffer */ + struct xfs_buf *bp) /* block buffer */ { - xfs_dir2_data_hdr_t *hdr = bp->data; + xfs_dir2_data_hdr_t *hdr = bp->b_addr; xfs_dir2_block_tail_t *btp; btp = xfs_dir2_block_tail_p(tp->t_mountp, hdr); - xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), + xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), (uint)((char *)(btp + 1) - (char *)hdr - 1)); } @@ -575,7 +573,7 @@ xfs_dir2_block_lookup( { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ @@ -593,7 +591,7 @@ xfs_dir2_block_lookup( return error; dp = args->dp; mp = dp->i_mount; - hdr = bp->data; + hdr = bp->b_addr; xfs_dir2_data_check(dp, bp); btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); @@ -607,7 +605,7 @@ xfs_dir2_block_lookup( */ args->inumber = be64_to_cpu(dep->inumber); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); - xfs_da_brelse(args->trans, bp); + xfs_trans_brelse(args->trans, bp); return XFS_ERROR(error); } @@ -617,13 +615,13 @@ xfs_dir2_block_lookup( static int /* error */ xfs_dir2_block_lookup_int( xfs_da_args_t *args, /* dir lookup arguments */ - xfs_dabuf_t **bpp, /* returned block buffer */ + struct xfs_buf **bpp, /* returned block buffer */ int *entno) /* returned entry number */ { xfs_dir2_dataptr_t addr; /* data entry address */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ @@ -647,7 +645,7 @@ xfs_dir2_block_lookup_int( return error; } ASSERT(bp != NULL); - hdr = bp->data; + hdr = bp->b_addr; xfs_dir2_data_check(dp, bp); btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); @@ -666,7 +664,7 @@ xfs_dir2_block_lookup_int( high = mid - 1; if (low > high) { ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); return XFS_ERROR(ENOENT); } } @@ -714,7 +712,7 @@ xfs_dir2_block_lookup_int( /* * No match, release the buffer and return ENOENT. */ - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); return XFS_ERROR(ENOENT); } @@ -728,7 +726,7 @@ xfs_dir2_block_removename( { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf pointer */ - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ @@ -753,7 +751,7 @@ xfs_dir2_block_removename( dp = args->dp; tp = args->trans; mp = dp->i_mount; - hdr = bp->data; + hdr = bp->b_addr; btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); /* @@ -790,10 +788,9 @@ xfs_dir2_block_removename( * See if the size as a shortform is good enough. */ size = xfs_dir2_block_sfsize(dp, hdr, &sfh); - if (size > XFS_IFORK_DSIZE(dp)) { - xfs_da_buf_done(bp); + if (size > XFS_IFORK_DSIZE(dp)) return 0; - } + /* * If it works, do the conversion. */ @@ -810,7 +807,7 @@ xfs_dir2_block_replace( { xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail */ xfs_dir2_data_entry_t *dep; /* block data entry */ xfs_inode_t *dp; /* incore inode */ @@ -829,7 +826,7 @@ xfs_dir2_block_replace( } dp = args->dp; mp = dp->i_mount; - hdr = bp->data; + hdr = bp->b_addr; btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); /* @@ -844,7 +841,6 @@ xfs_dir2_block_replace( dep->inumber = cpu_to_be64(args->inumber); xfs_dir2_data_log_entry(args->trans, bp, dep); xfs_dir2_data_check(dp, bp); - xfs_da_buf_done(bp); return 0; } @@ -871,8 +867,8 @@ xfs_dir2_block_sort( int /* error */ xfs_dir2_leaf_to_block( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *lbp, /* leaf buffer */ - xfs_dabuf_t *dbp) /* data buffer */ + struct xfs_buf *lbp, /* leaf buffer */ + struct xfs_buf *dbp) /* data buffer */ { __be16 *bestsp; /* leaf bests table */ xfs_dir2_data_hdr_t *hdr; /* block header */ @@ -898,7 +894,7 @@ xfs_dir2_leaf_to_block( dp = args->dp; tp = args->trans; mp = dp->i_mount; - leaf = lbp->data; + leaf = lbp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); ltp = xfs_dir2_leaf_tail_p(mp, leaf); /* @@ -914,11 +910,9 @@ xfs_dir2_leaf_to_block( if ((error = xfs_dir2_leaf_trim_data(args, lbp, (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) - goto out; - } else { - error = 0; - goto out; - } + return error; + } else + return 0; } /* * Read the data block if we don't already have it, give up if it fails. @@ -926,9 +920,9 @@ xfs_dir2_leaf_to_block( if (dbp == NULL && (error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &dbp, XFS_DATA_FORK))) { - goto out; + return error; } - hdr = dbp->data; + hdr = dbp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); /* * Size of the "leaf" area in the block. @@ -944,10 +938,9 @@ xfs_dir2_leaf_to_block( * If it's not free or is too short we can't do it. */ if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG || - be16_to_cpu(dup->length) < size) { - error = 0; - goto out; - } + be16_to_cpu(dup->length) < size) + return 0; + /* * Start converting it to block form. */ @@ -989,25 +982,17 @@ xfs_dir2_leaf_to_block( * Pitch the old leaf block. */ error = xfs_da_shrink_inode(args, mp->m_dirleafblk, lbp); - lbp = NULL; - if (error) { - goto out; - } + if (error) + return error; + /* * Now see if the resulting block can be shrunken to shortform. */ size = xfs_dir2_block_sfsize(dp, hdr, &sfh); - if (size > XFS_IFORK_DSIZE(dp)) { - error = 0; - goto out; - } + if (size > XFS_IFORK_DSIZE(dp)) + return 0; + return xfs_dir2_block_to_sf(args, dbp, size, &sfh); -out: - if (lbp) - xfs_da_buf_done(lbp); - if (dbp) - xfs_da_buf_done(dbp); - return error; } /* @@ -1020,7 +1005,7 @@ xfs_dir2_sf_to_block( xfs_dir2_db_t blkno; /* dir-relative block # (0) */ xfs_dir2_data_hdr_t *hdr; /* block header */ xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_block_tail_t *btp; /* block tail pointer */ xfs_dir2_data_entry_t *dep; /* data entry pointer */ xfs_inode_t *dp; /* incore directory inode */ @@ -1088,7 +1073,7 @@ xfs_dir2_sf_to_block( kmem_free(sfp); return error; } - hdr = bp->data; + hdr = bp->b_addr; hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); /* * Compute size of block "tail" area. @@ -1217,6 +1202,5 @@ xfs_dir2_sf_to_block( xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); xfs_dir2_block_log_tail(tp, bp); xfs_dir2_data_check(dp, bp); - xfs_da_buf_done(bp); return 0; } diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 2046988e9eb..44ffd4d6bc9 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -42,8 +42,8 @@ xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup); */ void xfs_dir2_data_check( - xfs_inode_t *dp, /* incore inode pointer */ - xfs_dabuf_t *bp) /* data block's buffer */ + struct xfs_inode *dp, /* incore inode pointer */ + struct xfs_buf *bp) /* data block's buffer */ { xfs_dir2_dataptr_t addr; /* addr for leaf lookup */ xfs_dir2_data_free_t *bf; /* bestfree table */ @@ -65,7 +65,7 @@ xfs_dir2_data_check( struct xfs_name name; mp = dp->i_mount; - hdr = bp->data; + hdr = bp->b_addr; bf = hdr->bestfree; p = (char *)(hdr + 1); @@ -389,9 +389,9 @@ int /* error */ xfs_dir2_data_init( xfs_da_args_t *args, /* directory operation args */ xfs_dir2_db_t blkno, /* logical dir block number */ - xfs_dabuf_t **bpp) /* output block buffer */ + struct xfs_buf **bpp) /* output block buffer */ { - xfs_dabuf_t *bp; /* block buffer */ + struct xfs_buf *bp; /* block buffer */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* unused entry pointer */ @@ -417,7 +417,7 @@ xfs_dir2_data_init( /* * Initialize the header. */ - hdr = bp->data; + hdr = bp->b_addr; hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr)); for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { @@ -449,16 +449,16 @@ xfs_dir2_data_init( */ void xfs_dir2_data_log_entry( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* block buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp, xfs_dir2_data_entry_t *dep) /* data entry pointer */ { - xfs_dir2_data_hdr_t *hdr = bp->data; + xfs_dir2_data_hdr_t *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); - xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), + xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) - (char *)hdr - 1)); } @@ -468,15 +468,15 @@ xfs_dir2_data_log_entry( */ void xfs_dir2_data_log_header( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp) /* block buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp) { - xfs_dir2_data_hdr_t *hdr = bp->data; + xfs_dir2_data_hdr_t *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); - xfs_da_log_buf(tp, bp, 0, sizeof(*hdr) - 1); + xfs_trans_log_buf(tp, bp, 0, sizeof(*hdr) - 1); } /* @@ -484,11 +484,11 @@ xfs_dir2_data_log_header( */ void xfs_dir2_data_log_unused( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* block buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp, xfs_dir2_data_unused_t *dup) /* data unused pointer */ { - xfs_dir2_data_hdr_t *hdr = bp->data; + xfs_dir2_data_hdr_t *hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); @@ -496,13 +496,13 @@ xfs_dir2_data_log_unused( /* * Log the first part of the unused entry. */ - xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr), + xfs_trans_log_buf(tp, bp, (uint)((char *)dup - (char *)hdr), (uint)((char *)&dup->length + sizeof(dup->length) - 1 - (char *)hdr)); /* * Log the end (tag) of the unused entry. */ - xfs_da_log_buf(tp, bp, + xfs_trans_log_buf(tp, bp, (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr), (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr + sizeof(xfs_dir2_data_off_t) - 1)); @@ -514,8 +514,8 @@ xfs_dir2_data_log_unused( */ void xfs_dir2_data_make_free( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* block buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, /* starting byte offset */ xfs_dir2_data_aoff_t len, /* length in bytes */ int *needlogp, /* out: log header */ @@ -531,7 +531,7 @@ xfs_dir2_data_make_free( xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ mp = tp->t_mountp; - hdr = bp->data; + hdr = bp->b_addr; /* * Figure out where the end of the data area is. @@ -696,8 +696,8 @@ xfs_dir2_data_make_free( */ void xfs_dir2_data_use_free( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* data block buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp, xfs_dir2_data_unused_t *dup, /* unused entry */ xfs_dir2_data_aoff_t offset, /* starting offset to use */ xfs_dir2_data_aoff_t len, /* length to use */ @@ -713,7 +713,7 @@ xfs_dir2_data_use_free( xfs_dir2_data_unused_t *newdup2; /* another new unused entry */ int oldlen; /* old unused entry's length */ - hdr = bp->data; + hdr = bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 397ffbcbab1..0b296253bd0 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -38,15 +38,15 @@ * Local function declarations. */ #ifdef DEBUG -static void xfs_dir2_leaf_check(xfs_inode_t *dp, xfs_dabuf_t *bp); +static void xfs_dir2_leaf_check(struct xfs_inode *dp, struct xfs_buf *bp); #else #define xfs_dir2_leaf_check(dp, bp) #endif -static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp, - int *indexp, xfs_dabuf_t **dbpp); -static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp, +static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, + int *indexp, struct xfs_buf **dbpp); +static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, int first, int last); -static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp); +static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); /* @@ -55,7 +55,7 @@ static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp); int /* error */ xfs_dir2_block_to_leaf( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *dbp) /* input block's buffer */ + struct xfs_buf *dbp) /* input block's buffer */ { __be16 *bestsp; /* leaf's bestsp entries */ xfs_dablk_t blkno; /* leaf block's bno */ @@ -64,7 +64,7 @@ xfs_dir2_block_to_leaf( xfs_dir2_block_tail_t *btp; /* block's tail */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ - xfs_dabuf_t *lbp; /* leaf block's buffer */ + struct xfs_buf *lbp; /* leaf block's buffer */ xfs_dir2_db_t ldb; /* leaf block's bno */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf's tail */ @@ -95,8 +95,8 @@ xfs_dir2_block_to_leaf( return error; } ASSERT(lbp != NULL); - leaf = lbp->data; - hdr = dbp->data; + leaf = lbp->b_addr; + hdr = dbp->b_addr; xfs_dir2_data_check(dp, dbp); btp = xfs_dir2_block_tail_p(mp, hdr); blp = xfs_dir2_block_leaf_p(btp); @@ -143,7 +143,6 @@ xfs_dir2_block_to_leaf( xfs_dir2_leaf_check(dp, lbp); xfs_dir2_data_check(dp, dbp); xfs_dir2_leaf_log_bests(tp, lbp, 0, 0); - xfs_da_buf_done(lbp); return 0; } @@ -282,7 +281,7 @@ xfs_dir2_leaf_addname( __be16 *bestsp; /* freespace table in leaf */ int compact; /* need to compact leaves */ xfs_dir2_data_hdr_t *hdr; /* data block header */ - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* data unused entry */ @@ -291,7 +290,7 @@ xfs_dir2_leaf_addname( int highstale; /* index of next stale leaf */ int i; /* temporary, index */ int index; /* leaf table position */ - xfs_dabuf_t *lbp; /* leaf's buffer */ + struct xfs_buf *lbp; /* leaf's buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int length; /* length of new entry */ xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ @@ -328,7 +327,7 @@ xfs_dir2_leaf_addname( * But if there are dup hash values the index is of the first of those. */ index = xfs_dir2_leaf_search_hash(args, lbp); - leaf = lbp->data; + leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); bestsp = xfs_dir2_leaf_bests_p(ltp); length = xfs_dir2_data_entsize(args->namelen); @@ -402,14 +401,13 @@ xfs_dir2_leaf_addname( */ if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return XFS_ERROR(ENOSPC); } /* * Convert to node form. */ error = xfs_dir2_leaf_to_node(args, lbp); - xfs_da_buf_done(lbp); if (error) return error; /* @@ -427,7 +425,7 @@ xfs_dir2_leaf_addname( * a new data block. */ if (args->op_flags & XFS_DA_OP_JUSTCHECK) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return use_block == -1 ? XFS_ERROR(ENOSPC) : 0; } /* @@ -435,7 +433,7 @@ xfs_dir2_leaf_addname( * changed anything. */ if (args->total == 0 && use_block == -1) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return XFS_ERROR(ENOSPC); } /* @@ -466,14 +464,14 @@ xfs_dir2_leaf_addname( */ if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &use_block))) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return error; } /* * Initialize the block. */ if ((error = xfs_dir2_data_init(args, use_block, &dbp))) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return error; } /* @@ -493,7 +491,7 @@ xfs_dir2_leaf_addname( */ else xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); - hdr = dbp->data; + hdr = dbp->b_addr; bestsp[use_block] = hdr->bestfree[0].length; grown = 1; } @@ -505,10 +503,10 @@ xfs_dir2_leaf_addname( if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block), -1, &dbp, XFS_DATA_FORK))) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return error; } - hdr = dbp->data; + hdr = dbp->b_addr; grown = 0; } xfs_dir2_data_check(dp, dbp); @@ -570,9 +568,7 @@ xfs_dir2_leaf_addname( xfs_dir2_leaf_log_header(tp, lbp); xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); xfs_dir2_leaf_check(dp, lbp); - xfs_da_buf_done(lbp); xfs_dir2_data_check(dp, dbp); - xfs_da_buf_done(dbp); return 0; } @@ -583,8 +579,8 @@ xfs_dir2_leaf_addname( */ STATIC void xfs_dir2_leaf_check( - xfs_inode_t *dp, /* incore directory inode */ - xfs_dabuf_t *bp) /* leaf's buffer */ + struct xfs_inode *dp, /* incore directory inode */ + struct xfs_buf *bp) /* leaf's buffer */ { int i; /* leaf index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ @@ -592,7 +588,7 @@ xfs_dir2_leaf_check( xfs_mount_t *mp; /* filesystem mount point */ int stale; /* count of stale leaves */ - leaf = bp->data; + leaf = bp->b_addr; mp = dp->i_mount; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); /* @@ -628,14 +624,14 @@ xfs_dir2_leaf_check( void xfs_dir2_leaf_compact( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *bp) /* leaf buffer */ + struct xfs_buf *bp) /* leaf buffer */ { int from; /* source leaf index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ int loglow; /* first leaf entry to log */ int to; /* target leaf index */ - leaf = bp->data; + leaf = bp->b_addr; if (!leaf->hdr.stale) { return; } @@ -677,7 +673,7 @@ xfs_dir2_leaf_compact( */ void xfs_dir2_leaf_compact_x1( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ int *indexp, /* insertion index */ int *lowstalep, /* out: stale entry before us */ int *highstalep, /* out: stale entry after us */ @@ -693,7 +689,7 @@ xfs_dir2_leaf_compact_x1( int newindex=0; /* new insertion index */ int to; /* destination copy index */ - leaf = bp->data; + leaf = bp->b_addr; ASSERT(be16_to_cpu(leaf->hdr.stale) > 1); index = *indexp; @@ -763,6 +759,218 @@ xfs_dir2_leaf_compact_x1( *highstalep = highstale; } +struct xfs_dir2_leaf_map_info { + xfs_extlen_t map_blocks; /* number of fsbs in map */ + xfs_dablk_t map_off; /* last mapped file offset */ + int map_size; /* total entries in *map */ + int map_valid; /* valid entries in *map */ + int nmap; /* mappings to ask xfs_bmapi */ + xfs_dir2_db_t curdb; /* db for current block */ + int ra_current; /* number of read-ahead blks */ + int ra_index; /* *map index for read-ahead */ + int ra_offset; /* map entry offset for ra */ + int ra_want; /* readahead count wanted */ + struct xfs_bmbt_irec map[]; /* map vector for blocks */ +}; + +STATIC int +xfs_dir2_leaf_readbuf( + struct xfs_inode *dp, + size_t bufsize, + struct xfs_dir2_leaf_map_info *mip, + xfs_dir2_off_t *curoff, + struct xfs_buf **bpp) +{ + struct xfs_mount *mp = dp->i_mount; + struct xfs_buf *bp = *bpp; + struct xfs_bmbt_irec *map = mip->map; + int error = 0; + int length; + int i; + int j; + + /* + * If we have a buffer, we need to release it and + * take it out of the mapping. + */ + + if (bp) { + xfs_trans_brelse(NULL, bp); + bp = NULL; + mip->map_blocks -= mp->m_dirblkfsbs; + /* + * Loop to get rid of the extents for the + * directory block. + */ + for (i = mp->m_dirblkfsbs; i > 0; ) { + j = min_t(int, map->br_blockcount, i); + map->br_blockcount -= j; + map->br_startblock += j; + map->br_startoff += j; + /* + * If mapping is done, pitch it from + * the table. + */ + if (!map->br_blockcount && --mip->map_valid) + memmove(&map[0], &map[1], + sizeof(map[0]) * mip->map_valid); + i -= j; + } + } + + /* + * Recalculate the readahead blocks wanted. + */ + mip->ra_want = howmany(bufsize + mp->m_dirblksize, + mp->m_sb.sb_blocksize) - 1; + ASSERT(mip->ra_want >= 0); + + /* + * If we don't have as many as we want, and we haven't + * run out of data blocks, get some more mappings. + */ + if (1 + mip->ra_want > mip->map_blocks && + mip->map_off < xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) { + /* + * Get more bmaps, fill in after the ones + * we already have in the table. + */ + mip->nmap = mip->map_size - mip->map_valid; + error = xfs_bmapi_read(dp, mip->map_off, + xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET) - + mip->map_off, + &map[mip->map_valid], &mip->nmap, 0); + + /* + * Don't know if we should ignore this or try to return an + * error. The trouble with returning errors is that readdir + * will just stop without actually passing the error through. + */ + if (error) + goto out; /* XXX */ + + /* + * If we got all the mappings we asked for, set the final map + * offset based on the last bmap value received. Otherwise, + * we've reached the end. + */ + if (mip->nmap == mip->map_size - mip->map_valid) { + i = mip->map_valid + mip->nmap - 1; + mip->map_off = map[i].br_startoff + map[i].br_blockcount; + } else + mip->map_off = xfs_dir2_byte_to_da(mp, + XFS_DIR2_LEAF_OFFSET); + + /* + * Look for holes in the mapping, and eliminate them. Count up + * the valid blocks. + */ + for (i = mip->map_valid; i < mip->map_valid + mip->nmap; ) { + if (map[i].br_startblock == HOLESTARTBLOCK) { + mip->nmap--; + length = mip->map_valid + mip->nmap - i; + if (length) + memmove(&map[i], &map[i + 1], + sizeof(map[i]) * length); + } else { + mip->map_blocks += map[i].br_blockcount; + i++; + } + } + mip->map_valid += mip->nmap; + } + + /* + * No valid mappings, so no more data blocks. + */ + if (!mip->map_valid) { + *curoff = xfs_dir2_da_to_byte(mp, mip->map_off); + goto out; + } + + /* + * Read the directory block starting at the first mapping. + */ + mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff); + error = xfs_da_read_buf(NULL, dp, map->br_startoff, + map->br_blockcount >= mp->m_dirblkfsbs ? + XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, + &bp, XFS_DATA_FORK); + + /* + * Should just skip over the data block instead of giving up. + */ + if (error) + goto out; /* XXX */ + + /* + * Adjust the current amount of read-ahead: we just read a block that + * was previously ra. + */ + if (mip->ra_current) + mip->ra_current -= mp->m_dirblkfsbs; + + /* + * Do we need more readahead? + */ + for (mip->ra_index = mip->ra_offset = i = 0; + mip->ra_want > mip->ra_current && i < mip->map_blocks; + i += mp->m_dirblkfsbs) { + ASSERT(mip->ra_index < mip->map_valid); + /* + * Read-ahead a contiguous directory block. + */ + if (i > mip->ra_current && + map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) { + xfs_buf_readahead(mp->m_ddev_targp, + XFS_FSB_TO_DADDR(mp, + map[mip->ra_index].br_startblock + + mip->ra_offset), + (int)BTOBB(mp->m_dirblksize)); + mip->ra_current = i; + } + + /* + * Read-ahead a non-contiguous directory block. This doesn't + * use our mapping, but this is a very rare case. + */ + else if (i > mip->ra_current) { + xfs_da_reada_buf(NULL, dp, + map[mip->ra_index].br_startoff + + mip->ra_offset, + XFS_DATA_FORK); + mip->ra_current = i; + } + + /* + * Advance offset through the mapping table. + */ + for (j = 0; j < mp->m_dirblkfsbs; j++) { + /* + * The rest of this extent but not more than a dir + * block. + */ + length = min_t(int, mp->m_dirblkfsbs, + map[mip->ra_index].br_blockcount - + mip->ra_offset); + j += length; + mip->ra_offset += length; + + /* + * Advance to the next mapping if this one is used up. + */ + if (mip->ra_offset == map[mip->ra_index].br_blockcount) { + mip->ra_offset = 0; + mip->ra_index++; + } + } + } + +out: + *bpp = bp; + return error; +} + /* * Getdents (readdir) for leaf and node directories. * This reads the data blocks only, so is the same for both forms. @@ -775,30 +983,18 @@ xfs_dir2_leaf_getdents( xfs_off_t *offset, filldir_t filldir) { - xfs_dabuf_t *bp; /* data block buffer */ - int byteoff; /* offset in current block */ - xfs_dir2_db_t curdb; /* db for current block */ - xfs_dir2_off_t curoff; /* current overall offset */ + struct xfs_buf *bp = NULL; /* data block buffer */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_data_entry_t *dep; /* data entry */ xfs_dir2_data_unused_t *dup; /* unused entry */ int error = 0; /* error return value */ - int i; /* temporary loop index */ - int j; /* temporary loop index */ int length; /* temporary length value */ - xfs_bmbt_irec_t *map; /* map vector for blocks */ - xfs_extlen_t map_blocks; /* number of fsbs in map */ - xfs_dablk_t map_off; /* last mapped file offset */ - int map_size; /* total entries in *map */ - int map_valid; /* valid entries in *map */ xfs_mount_t *mp; /* filesystem mount point */ + int byteoff; /* offset in current block */ + xfs_dir2_off_t curoff; /* current overall offset */ xfs_dir2_off_t newoff; /* new curoff after new blk */ - int nmap; /* mappings to ask xfs_bmapi */ char *ptr = NULL; /* pointer to current data */ - int ra_current; /* number of read-ahead blks */ - int ra_index; /* *map index for read-ahead */ - int ra_offset; /* map entry offset for ra */ - int ra_want; /* readahead count wanted */ + struct xfs_dir2_leaf_map_info *map_info; /* * If the offset is at or past the largest allowed value, @@ -814,10 +1010,12 @@ xfs_dir2_leaf_getdents( * buffer size, the directory block size, and the filesystem * block size. */ - map_size = howmany(bufsize + mp->m_dirblksize, mp->m_sb.sb_blocksize); - map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP); - map_valid = ra_index = ra_offset = ra_current = map_blocks = 0; - bp = NULL; + length = howmany(bufsize + mp->m_dirblksize, + mp->m_sb.sb_blocksize); + map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) + + (length * sizeof(struct xfs_bmbt_irec)), + KM_SLEEP); + map_info->map_size = length; /* * Inside the loop we keep the main offset value as a byte offset @@ -829,7 +1027,9 @@ xfs_dir2_leaf_getdents( * Force this conversion through db so we truncate the offset * down to get the start of the data block. */ - map_off = xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, curoff)); + map_info->map_off = xfs_dir2_db_to_da(mp, + xfs_dir2_byte_to_db(mp, curoff)); + /* * Loop over directory entries until we reach the end offset. * Get more blocks and readahead as necessary. @@ -839,191 +1039,17 @@ xfs_dir2_leaf_getdents( * If we have no buffer, or we're off the end of the * current buffer, need to get another one. */ - if (!bp || ptr >= (char *)bp->data + mp->m_dirblksize) { - /* - * If we have a buffer, we need to release it and - * take it out of the mapping. - */ - if (bp) { - xfs_da_brelse(NULL, bp); - bp = NULL; - map_blocks -= mp->m_dirblkfsbs; - /* - * Loop to get rid of the extents for the - * directory block. - */ - for (i = mp->m_dirblkfsbs; i > 0; ) { - j = MIN((int)map->br_blockcount, i); - map->br_blockcount -= j; - map->br_startblock += j; - map->br_startoff += j; - /* - * If mapping is done, pitch it from - * the table. - */ - if (!map->br_blockcount && --map_valid) - memmove(&map[0], &map[1], - sizeof(map[0]) * - map_valid); - i -= j; - } - } - /* - * Recalculate the readahead blocks wanted. - */ - ra_want = howmany(bufsize + mp->m_dirblksize, - mp->m_sb.sb_blocksize) - 1; - ASSERT(ra_want >= 0); + if (!bp || ptr >= (char *)bp->b_addr + mp->m_dirblksize) { - /* - * If we don't have as many as we want, and we haven't - * run out of data blocks, get some more mappings. - */ - if (1 + ra_want > map_blocks && - map_off < - xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) { - /* - * Get more bmaps, fill in after the ones - * we already have in the table. - */ - nmap = map_size - map_valid; - error = xfs_bmapi_read(dp, map_off, - xfs_dir2_byte_to_da(mp, - XFS_DIR2_LEAF_OFFSET) - map_off, - &map[map_valid], &nmap, 0); - /* - * Don't know if we should ignore this or - * try to return an error. - * The trouble with returning errors - * is that readdir will just stop without - * actually passing the error through. - */ - if (error) - break; /* XXX */ - /* - * If we got all the mappings we asked for, - * set the final map offset based on the - * last bmap value received. - * Otherwise, we've reached the end. - */ - if (nmap == map_size - map_valid) - map_off = - map[map_valid + nmap - 1].br_startoff + - map[map_valid + nmap - 1].br_blockcount; - else - map_off = - xfs_dir2_byte_to_da(mp, - XFS_DIR2_LEAF_OFFSET); - /* - * Look for holes in the mapping, and - * eliminate them. Count up the valid blocks. - */ - for (i = map_valid; i < map_valid + nmap; ) { - if (map[i].br_startblock == - HOLESTARTBLOCK) { - nmap--; - length = map_valid + nmap - i; - if (length) - memmove(&map[i], - &map[i + 1], - sizeof(map[i]) * - length); - } else { - map_blocks += - map[i].br_blockcount; - i++; - } - } - map_valid += nmap; - } - /* - * No valid mappings, so no more data blocks. - */ - if (!map_valid) { - curoff = xfs_dir2_da_to_byte(mp, map_off); + error = xfs_dir2_leaf_readbuf(dp, bufsize, map_info, + &curoff, &bp); + if (error || !map_info->map_valid) break; - } - /* - * Read the directory block starting at the first - * mapping. - */ - curdb = xfs_dir2_da_to_db(mp, map->br_startoff); - error = xfs_da_read_buf(NULL, dp, map->br_startoff, - map->br_blockcount >= mp->m_dirblkfsbs ? - XFS_FSB_TO_DADDR(mp, map->br_startblock) : - -1, - &bp, XFS_DATA_FORK); - /* - * Should just skip over the data block instead - * of giving up. - */ - if (error) - break; /* XXX */ - /* - * Adjust the current amount of read-ahead: we just - * read a block that was previously ra. - */ - if (ra_current) - ra_current -= mp->m_dirblkfsbs; - /* - * Do we need more readahead? - */ - for (ra_index = ra_offset = i = 0; - ra_want > ra_current && i < map_blocks; - i += mp->m_dirblkfsbs) { - ASSERT(ra_index < map_valid); - /* - * Read-ahead a contiguous directory block. - */ - if (i > ra_current && - map[ra_index].br_blockcount >= - mp->m_dirblkfsbs) { - xfs_buf_readahead(mp->m_ddev_targp, - XFS_FSB_TO_DADDR(mp, - map[ra_index].br_startblock + - ra_offset), - (int)BTOBB(mp->m_dirblksize)); - ra_current = i; - } - /* - * Read-ahead a non-contiguous directory block. - * This doesn't use our mapping, but this - * is a very rare case. - */ - else if (i > ra_current) { - (void)xfs_da_reada_buf(NULL, dp, - map[ra_index].br_startoff + - ra_offset, XFS_DATA_FORK); - ra_current = i; - } - /* - * Advance offset through the mapping table. - */ - for (j = 0; j < mp->m_dirblkfsbs; j++) { - /* - * The rest of this extent but not - * more than a dir block. - */ - length = MIN(mp->m_dirblkfsbs, - (int)(map[ra_index].br_blockcount - - ra_offset)); - j += length; - ra_offset += length; - /* - * Advance to the next mapping if - * this one is used up. - */ - if (ra_offset == - map[ra_index].br_blockcount) { - ra_offset = 0; - ra_index++; - } - } - } + /* * Having done a read, we need to set a new offset. */ - newoff = xfs_dir2_db_off_to_byte(mp, curdb, 0); + newoff = xfs_dir2_db_off_to_byte(mp, map_info->curdb, 0); /* * Start of the current block. */ @@ -1034,8 +1060,8 @@ xfs_dir2_leaf_getdents( */ else if (curoff > newoff) ASSERT(xfs_dir2_byte_to_db(mp, curoff) == - curdb); - hdr = bp->data; + map_info->curdb); + hdr = bp->b_addr; xfs_dir2_data_check(dp, bp); /* * Find our position in the block. @@ -1117,9 +1143,9 @@ xfs_dir2_leaf_getdents( *offset = XFS_DIR2_MAX_DATAPTR & 0x7fffffff; else *offset = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; - kmem_free(map); + kmem_free(map_info); if (bp) - xfs_da_brelse(NULL, bp); + xfs_trans_brelse(NULL, bp); return error; } @@ -1130,10 +1156,10 @@ int xfs_dir2_leaf_init( xfs_da_args_t *args, /* operation arguments */ xfs_dir2_db_t bno, /* directory block number */ - xfs_dabuf_t **bpp, /* out: leaf buffer */ + struct xfs_buf **bpp, /* out: leaf buffer */ int magic) /* magic number for block */ { - xfs_dabuf_t *bp; /* leaf buffer */ + struct xfs_buf *bp; /* leaf buffer */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ xfs_dir2_leaf_t *leaf; /* leaf structure */ @@ -1156,7 +1182,7 @@ xfs_dir2_leaf_init( return error; } ASSERT(bp != NULL); - leaf = bp->data; + leaf = bp->b_addr; /* * Initialize the header. */ @@ -1186,7 +1212,7 @@ xfs_dir2_leaf_init( static void xfs_dir2_leaf_log_bests( xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ int first, /* first entry to log */ int last) /* last entry to log */ { @@ -1195,12 +1221,12 @@ xfs_dir2_leaf_log_bests( xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); firstb = xfs_dir2_leaf_bests_p(ltp) + first; lastb = xfs_dir2_leaf_bests_p(ltp) + last; - xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf), + xfs_trans_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf), (uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1)); } @@ -1210,7 +1236,7 @@ xfs_dir2_leaf_log_bests( void xfs_dir2_leaf_log_ents( xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ int first, /* first entry to log */ int last) /* last entry to log */ { @@ -1218,12 +1244,12 @@ xfs_dir2_leaf_log_ents( xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ xfs_dir2_leaf_t *leaf; /* leaf structure */ - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); firstlep = &leaf->ents[first]; lastlep = &leaf->ents[last]; - xfs_da_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), + xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); } @@ -1232,15 +1258,15 @@ xfs_dir2_leaf_log_ents( */ void xfs_dir2_leaf_log_header( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp) /* leaf buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp) { xfs_dir2_leaf_t *leaf; /* leaf structure */ - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); - xfs_da_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), + xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), (uint)(sizeof(leaf->hdr) - 1)); } @@ -1249,18 +1275,18 @@ xfs_dir2_leaf_log_header( */ STATIC void xfs_dir2_leaf_log_tail( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp) /* leaf buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp) { xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ xfs_mount_t *mp; /* filesystem mount point */ mp = tp->t_mountp; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); ltp = xfs_dir2_leaf_tail_p(mp, leaf); - xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), + xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), (uint)(mp->m_dirblksize - 1)); } @@ -1273,12 +1299,12 @@ int xfs_dir2_leaf_lookup( xfs_da_args_t *args) /* operation arguments */ { - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* found entry index */ - xfs_dabuf_t *lbp; /* leaf buffer */ + struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_trans_t *tp; /* transaction pointer */ @@ -1294,7 +1320,7 @@ xfs_dir2_leaf_lookup( tp = args->trans; dp = args->dp; xfs_dir2_leaf_check(dp, lbp); - leaf = lbp->data; + leaf = lbp->b_addr; /* * Get to the leaf entry and contained data entry address. */ @@ -1303,15 +1329,15 @@ xfs_dir2_leaf_lookup( * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) - ((char *)dbp->data + + ((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); /* * Return the found inode number & CI name if appropriate */ args->inumber = be64_to_cpu(dep->inumber); error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); - xfs_da_brelse(tp, dbp); - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, dbp); + xfs_trans_brelse(tp, lbp); return XFS_ERROR(error); } @@ -1324,17 +1350,17 @@ xfs_dir2_leaf_lookup( static int /* error */ xfs_dir2_leaf_lookup_int( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t **lbpp, /* out: leaf buffer */ + struct xfs_buf **lbpp, /* out: leaf buffer */ int *indexp, /* out: index in leaf block */ - xfs_dabuf_t **dbpp) /* out: data buffer */ + struct xfs_buf **dbpp) /* out: data buffer */ { xfs_dir2_db_t curdb = -1; /* current data block number */ - xfs_dabuf_t *dbp = NULL; /* data buffer */ + struct xfs_buf *dbp = NULL; /* data buffer */ xfs_dir2_data_entry_t *dep; /* data entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* index in leaf block */ - xfs_dabuf_t *lbp; /* leaf buffer */ + struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_mount_t *mp; /* filesystem mount point */ @@ -1354,7 +1380,7 @@ xfs_dir2_leaf_lookup_int( if (error) return error; *lbpp = lbp; - leaf = lbp->data; + leaf = lbp->b_addr; xfs_dir2_leaf_check(dp, lbp); /* * Look for the first leaf entry with our hash value. @@ -1382,12 +1408,12 @@ xfs_dir2_leaf_lookup_int( */ if (newdb != curdb) { if (dbp) - xfs_da_brelse(tp, dbp); + xfs_trans_brelse(tp, dbp); error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, newdb), -1, &dbp, XFS_DATA_FORK); if (error) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return error; } xfs_dir2_data_check(dp, dbp); @@ -1396,7 +1422,7 @@ xfs_dir2_leaf_lookup_int( /* * Point to the data entry. */ - dep = (xfs_dir2_data_entry_t *)((char *)dbp->data + + dep = (xfs_dir2_data_entry_t *)((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); /* * Compare name and if it's an exact match, return the index @@ -1424,12 +1450,12 @@ xfs_dir2_leaf_lookup_int( if (args->cmpresult == XFS_CMP_CASE) { ASSERT(cidb != -1); if (cidb != curdb) { - xfs_da_brelse(tp, dbp); + xfs_trans_brelse(tp, dbp); error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, cidb), -1, &dbp, XFS_DATA_FORK); if (error) { - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return error; } } @@ -1441,8 +1467,8 @@ xfs_dir2_leaf_lookup_int( */ ASSERT(cidb == -1); if (dbp) - xfs_da_brelse(tp, dbp); - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, dbp); + xfs_trans_brelse(tp, lbp); return XFS_ERROR(ENOENT); } @@ -1456,13 +1482,13 @@ xfs_dir2_leaf_removename( __be16 *bestsp; /* leaf block best freespace */ xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t db; /* data block number */ - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data entry structure */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ xfs_dir2_db_t i; /* temporary data block # */ int index; /* index into leaf entries */ - xfs_dabuf_t *lbp; /* leaf buffer */ + struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ @@ -1483,8 +1509,8 @@ xfs_dir2_leaf_removename( dp = args->dp; tp = args->trans; mp = dp->i_mount; - leaf = lbp->data; - hdr = dbp->data; + leaf = lbp->b_addr; + hdr = dbp->b_addr; xfs_dir2_data_check(dp, dbp); /* * Point to the leaf entry, use that to point to the data entry. @@ -1541,12 +1567,9 @@ xfs_dir2_leaf_removename( * Just go on, returning success, leaving the * empty block in place. */ - if (error == ENOSPC && args->total == 0) { - xfs_da_buf_done(dbp); + if (error == ENOSPC && args->total == 0) error = 0; - } xfs_dir2_leaf_check(dp, lbp); - xfs_da_buf_done(lbp); return error; } dbp = NULL; @@ -1577,10 +1600,9 @@ xfs_dir2_leaf_removename( /* * If the data block was not the first one, drop it. */ - else if (db != mp->m_dirdatablk && dbp != NULL) { - xfs_da_buf_done(dbp); + else if (db != mp->m_dirdatablk) dbp = NULL; - } + xfs_dir2_leaf_check(dp, lbp); /* * See if we can convert to block form. @@ -1595,12 +1617,12 @@ int /* error */ xfs_dir2_leaf_replace( xfs_da_args_t *args) /* operation arguments */ { - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ int index; /* index of leaf entry */ - xfs_dabuf_t *lbp; /* leaf buffer */ + struct xfs_buf *lbp; /* leaf buffer */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_dir2_leaf_entry_t *lep; /* leaf entry */ xfs_trans_t *tp; /* transaction pointer */ @@ -1614,7 +1636,7 @@ xfs_dir2_leaf_replace( return error; } dp = args->dp; - leaf = lbp->data; + leaf = lbp->b_addr; /* * Point to the leaf entry, get data address from it. */ @@ -1623,7 +1645,7 @@ xfs_dir2_leaf_replace( * Point to the data entry. */ dep = (xfs_dir2_data_entry_t *) - ((char *)dbp->data + + ((char *)dbp->b_addr + xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address))); ASSERT(args->inumber != be64_to_cpu(dep->inumber)); /* @@ -1632,9 +1654,8 @@ xfs_dir2_leaf_replace( dep->inumber = cpu_to_be64(args->inumber); tp = args->trans; xfs_dir2_data_log_entry(tp, dbp, dep); - xfs_da_buf_done(dbp); xfs_dir2_leaf_check(dp, lbp); - xfs_da_brelse(tp, lbp); + xfs_trans_brelse(tp, lbp); return 0; } @@ -1646,7 +1667,7 @@ xfs_dir2_leaf_replace( int /* index value */ xfs_dir2_leaf_search_hash( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *lbp) /* leaf buffer */ + struct xfs_buf *lbp) /* leaf buffer */ { xfs_dahash_t hash=0; /* hash from this entry */ xfs_dahash_t hashwant; /* hash value looking for */ @@ -1656,7 +1677,7 @@ xfs_dir2_leaf_search_hash( xfs_dir2_leaf_entry_t *lep; /* leaf entry */ int mid=0; /* current leaf index */ - leaf = lbp->data; + leaf = lbp->b_addr; #ifndef __KERNEL__ if (!leaf->hdr.count) return 0; @@ -1699,11 +1720,11 @@ xfs_dir2_leaf_search_hash( int /* error */ xfs_dir2_leaf_trim_data( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *lbp, /* leaf buffer */ + struct xfs_buf *lbp, /* leaf buffer */ xfs_dir2_db_t db) /* data block number */ { __be16 *bestsp; /* leaf bests table */ - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ xfs_dir2_leaf_t *leaf; /* leaf structure */ @@ -1722,12 +1743,12 @@ xfs_dir2_leaf_trim_data( return error; } - leaf = lbp->data; + leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); #ifdef DEBUG { - struct xfs_dir2_data_hdr *hdr = dbp->data; + struct xfs_dir2_data_hdr *hdr = dbp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); ASSERT(be16_to_cpu(hdr->bestfree[0].length) == @@ -1741,7 +1762,7 @@ xfs_dir2_leaf_trim_data( */ if ((error = xfs_dir2_shrink_inode(args, db, dbp))) { ASSERT(error != ENOSPC); - xfs_da_brelse(tp, dbp); + xfs_trans_brelse(tp, dbp); return error; } /* @@ -1781,10 +1802,10 @@ xfs_dir2_node_to_leaf( xfs_da_args_t *args; /* operation arguments */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ - xfs_dabuf_t *fbp; /* buffer for freespace block */ + struct xfs_buf *fbp; /* buffer for freespace block */ xfs_fileoff_t fo; /* freespace file offset */ xfs_dir2_free_t *free; /* freespace structure */ - xfs_dabuf_t *lbp; /* buffer for leaf block */ + struct xfs_buf *lbp; /* buffer for leaf block */ xfs_dir2_leaf_tail_t *ltp; /* tail of leaf structure */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_mount_t *mp; /* filesystem mount point */ @@ -1838,7 +1859,7 @@ xfs_dir2_node_to_leaf( if (XFS_FSB_TO_B(mp, fo) > XFS_DIR2_LEAF_OFFSET + mp->m_dirblksize) return 0; lbp = state->path.blk[0].bp; - leaf = lbp->data; + leaf = lbp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); /* * Read the freespace block. @@ -1847,7 +1868,7 @@ xfs_dir2_node_to_leaf( XFS_DATA_FORK))) { return error; } - free = fbp->data; + free = fbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); ASSERT(!free->hdr.firstdb); @@ -1857,7 +1878,7 @@ xfs_dir2_node_to_leaf( */ if (xfs_dir2_leaf_size(&leaf->hdr, be32_to_cpu(free->hdr.nvalid)) > mp->m_dirblksize) { - xfs_da_brelse(tp, fbp); + xfs_trans_brelse(tp, fbp); return 0; } diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index b0f26780449..6c705240660 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -36,20 +36,20 @@ /* * Function declarations. */ -static void xfs_dir2_free_log_header(xfs_trans_t *tp, xfs_dabuf_t *bp); -static int xfs_dir2_leafn_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index); +static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, + int index); #ifdef DEBUG -static void xfs_dir2_leafn_check(xfs_inode_t *dp, xfs_dabuf_t *bp); +static void xfs_dir2_leafn_check(struct xfs_inode *dp, struct xfs_buf *bp); #else #define xfs_dir2_leafn_check(dp, bp) #endif -static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, xfs_dabuf_t *bp_s, - int start_s, xfs_dabuf_t *bp_d, int start_d, - int count); +static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, struct xfs_buf *bp_s, + int start_s, struct xfs_buf *bp_d, + int start_d, int count); static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, xfs_da_state_blk_t *blk2); -static int xfs_dir2_leafn_remove(xfs_da_args_t *args, xfs_dabuf_t *bp, +static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, int index, xfs_da_state_blk_t *dblk, int *rval); static int xfs_dir2_node_addname_int(xfs_da_args_t *args, @@ -60,16 +60,16 @@ static int xfs_dir2_node_addname_int(xfs_da_args_t *args, */ STATIC void xfs_dir2_free_log_bests( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp, /* freespace buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp, int first, /* first entry to log */ int last) /* last entry to log */ { xfs_dir2_free_t *free; /* freespace structure */ - free = bp->data; + free = bp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); - xfs_da_log_buf(tp, bp, + xfs_trans_log_buf(tp, bp, (uint)((char *)&free->bests[first] - (char *)free), (uint)((char *)&free->bests[last] - (char *)free + sizeof(free->bests[0]) - 1)); @@ -80,14 +80,14 @@ xfs_dir2_free_log_bests( */ static void xfs_dir2_free_log_header( - xfs_trans_t *tp, /* transaction pointer */ - xfs_dabuf_t *bp) /* freespace buffer */ + struct xfs_trans *tp, + struct xfs_buf *bp) { xfs_dir2_free_t *free; /* freespace structure */ - free = bp->data; + free = bp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); - xfs_da_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free), + xfs_trans_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free), (uint)(sizeof(xfs_dir2_free_hdr_t) - 1)); } @@ -99,11 +99,11 @@ xfs_dir2_free_log_header( int /* error */ xfs_dir2_leaf_to_node( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *lbp) /* leaf buffer */ + struct xfs_buf *lbp) /* leaf buffer */ { xfs_inode_t *dp; /* incore directory inode */ int error; /* error return value */ - xfs_dabuf_t *fbp; /* freespace buffer */ + struct xfs_buf *fbp; /* freespace buffer */ xfs_dir2_db_t fdb; /* freespace block number */ xfs_dir2_free_t *free; /* freespace structure */ __be16 *from; /* pointer to freespace entry */ @@ -136,8 +136,8 @@ xfs_dir2_leaf_to_node( return error; } ASSERT(fbp != NULL); - free = fbp->data; - leaf = lbp->data; + free = fbp->b_addr; + leaf = lbp->b_addr; ltp = xfs_dir2_leaf_tail_p(mp, leaf); /* * Initialize the freespace block header. @@ -164,7 +164,6 @@ xfs_dir2_leaf_to_node( xfs_dir2_leaf_log_header(tp, lbp); xfs_dir2_free_log_header(tp, fbp); xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1); - xfs_da_buf_done(fbp); xfs_dir2_leafn_check(dp, lbp); return 0; } @@ -175,7 +174,7 @@ xfs_dir2_leaf_to_node( */ static int /* error */ xfs_dir2_leafn_add( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int index) /* insertion pt for new entry */ { @@ -195,7 +194,7 @@ xfs_dir2_leafn_add( dp = args->dp; mp = dp->i_mount; tp = args->trans; - leaf = bp->data; + leaf = bp->b_addr; /* * Quick check just to make sure we are not going to index @@ -261,15 +260,15 @@ xfs_dir2_leafn_add( */ void xfs_dir2_leafn_check( - xfs_inode_t *dp, /* incore directory inode */ - xfs_dabuf_t *bp) /* leaf buffer */ + struct xfs_inode *dp, + struct xfs_buf *bp) { int i; /* leaf index */ xfs_dir2_leaf_t *leaf; /* leaf structure */ xfs_mount_t *mp; /* filesystem mount point */ int stale; /* count of stale leaves */ - leaf = bp->data; + leaf = bp->b_addr; mp = dp->i_mount; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp)); @@ -291,12 +290,12 @@ xfs_dir2_leafn_check( */ xfs_dahash_t /* hash value */ xfs_dir2_leafn_lasthash( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ int *count) /* count of entries in leaf */ { xfs_dir2_leaf_t *leaf; /* leaf structure */ - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); if (count) *count = be16_to_cpu(leaf->hdr.count); @@ -311,12 +310,12 @@ xfs_dir2_leafn_lasthash( */ STATIC int xfs_dir2_leafn_lookup_for_addname( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ { - xfs_dabuf_t *curbp = NULL; /* current data/free buffer */ + struct xfs_buf *curbp = NULL; /* current data/free buffer */ xfs_dir2_db_t curdb = -1; /* current data block number */ xfs_dir2_db_t curfdb = -1; /* current free block number */ xfs_inode_t *dp; /* incore directory inode */ @@ -335,7 +334,7 @@ xfs_dir2_leafn_lookup_for_addname( dp = args->dp; tp = args->trans; mp = dp->i_mount; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); #ifdef __KERNEL__ ASSERT(be16_to_cpu(leaf->hdr.count) > 0); @@ -352,7 +351,7 @@ xfs_dir2_leafn_lookup_for_addname( /* If so, it's a free block buffer, get the block number. */ curbp = state->extrablk.bp; curfdb = state->extrablk.blkno; - free = curbp->data; + free = curbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); } length = xfs_dir2_data_entsize(args->namelen); @@ -394,7 +393,7 @@ xfs_dir2_leafn_lookup_for_addname( * If we had one before, drop it. */ if (curbp) - xfs_da_brelse(tp, curbp); + xfs_trans_brelse(tp, curbp); /* * Read the free block. */ @@ -403,7 +402,7 @@ xfs_dir2_leafn_lookup_for_addname( -1, &curbp, XFS_DATA_FORK); if (error) return error; - free = curbp->data; + free = curbp->b_addr; ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC); ASSERT((be32_to_cpu(free->hdr.firstdb) % @@ -424,7 +423,7 @@ xfs_dir2_leafn_lookup_for_addname( XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", XFS_ERRLEVEL_LOW, mp); if (curfdb != newfdb) - xfs_da_brelse(tp, curbp); + xfs_trans_brelse(tp, curbp); return XFS_ERROR(EFSCORRUPTED); } curfdb = newfdb; @@ -459,12 +458,12 @@ out: */ STATIC int xfs_dir2_leafn_lookup_for_entry( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ { - xfs_dabuf_t *curbp = NULL; /* current data/free buffer */ + struct xfs_buf *curbp = NULL; /* current data/free buffer */ xfs_dir2_db_t curdb = -1; /* current data block number */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ @@ -480,7 +479,7 @@ xfs_dir2_leafn_lookup_for_entry( dp = args->dp; tp = args->trans; mp = dp->i_mount; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); #ifdef __KERNEL__ ASSERT(be16_to_cpu(leaf->hdr.count) > 0); @@ -525,7 +524,7 @@ xfs_dir2_leafn_lookup_for_entry( */ if (curbp && (args->cmpresult == XFS_CMP_DIFFERENT || curdb != state->extrablk.blkno)) - xfs_da_brelse(tp, curbp); + xfs_trans_brelse(tp, curbp); /* * If needing the block that is saved with a CI match, * use it otherwise read in the new data block. @@ -547,7 +546,7 @@ xfs_dir2_leafn_lookup_for_entry( /* * Point to the data entry. */ - dep = (xfs_dir2_data_entry_t *)((char *)curbp->data + + dep = (xfs_dir2_data_entry_t *)((char *)curbp->b_addr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); /* * Compare the entry and if it's an exact match, return @@ -559,7 +558,7 @@ xfs_dir2_leafn_lookup_for_entry( /* If there is a CI match block, drop it */ if (args->cmpresult != XFS_CMP_DIFFERENT && curdb != state->extrablk.blkno) - xfs_da_brelse(tp, state->extrablk.bp); + xfs_trans_brelse(tp, state->extrablk.bp); args->cmpresult = cmp; args->inumber = be64_to_cpu(dep->inumber); *indexp = index; @@ -567,7 +566,7 @@ xfs_dir2_leafn_lookup_for_entry( state->extrablk.bp = curbp; state->extrablk.blkno = curdb; state->extrablk.index = (int)((char *)dep - - (char *)curbp->data); + (char *)curbp->b_addr); state->extrablk.magic = XFS_DIR2_DATA_MAGIC; if (cmp == XFS_CMP_EXACT) return XFS_ERROR(EEXIST); @@ -586,7 +585,7 @@ xfs_dir2_leafn_lookup_for_entry( } else { /* If the curbp is not the CI match block, drop it */ if (state->extrablk.bp != curbp) - xfs_da_brelse(tp, curbp); + xfs_trans_brelse(tp, curbp); } } else { state->extravalid = 0; @@ -602,7 +601,7 @@ xfs_dir2_leafn_lookup_for_entry( */ int xfs_dir2_leafn_lookup_int( - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ xfs_da_args_t *args, /* operation arguments */ int *indexp, /* out: leaf entry index */ xfs_da_state_t *state) /* state to fill in */ @@ -620,9 +619,9 @@ xfs_dir2_leafn_lookup_int( static void xfs_dir2_leafn_moveents( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *bp_s, /* source leaf buffer */ + struct xfs_buf *bp_s, /* source leaf buffer */ int start_s, /* source leaf index */ - xfs_dabuf_t *bp_d, /* destination leaf buffer */ + struct xfs_buf *bp_d, /* destination leaf buffer */ int start_d, /* destination leaf index */ int count) /* count of leaves to copy */ { @@ -640,8 +639,8 @@ xfs_dir2_leafn_moveents( return; } tp = args->trans; - leaf_s = bp_s->data; - leaf_d = bp_d->data; + leaf_s = bp_s->b_addr; + leaf_d = bp_d->b_addr; /* * If the destination index is not the end of the current * destination leaf entries, open up a hole in the destination @@ -702,14 +701,14 @@ xfs_dir2_leafn_moveents( */ int /* sort order */ xfs_dir2_leafn_order( - xfs_dabuf_t *leaf1_bp, /* leaf1 buffer */ - xfs_dabuf_t *leaf2_bp) /* leaf2 buffer */ + struct xfs_buf *leaf1_bp, /* leaf1 buffer */ + struct xfs_buf *leaf2_bp) /* leaf2 buffer */ { xfs_dir2_leaf_t *leaf1; /* leaf1 structure */ xfs_dir2_leaf_t *leaf2; /* leaf2 structure */ - leaf1 = leaf1_bp->data; - leaf2 = leaf2_bp->data; + leaf1 = leaf1_bp->b_addr; + leaf2 = leaf2_bp->b_addr; ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); if (be16_to_cpu(leaf1->hdr.count) > 0 && @@ -757,8 +756,8 @@ xfs_dir2_leafn_rebalance( blk1 = blk2; blk2 = tmp; } - leaf1 = blk1->bp->data; - leaf2 = blk2->bp->data; + leaf1 = blk1->bp->b_addr; + leaf2 = blk2->bp->b_addr; oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count); #ifdef DEBUG oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale); @@ -834,14 +833,14 @@ xfs_dir2_leafn_rebalance( static int /* error */ xfs_dir2_leafn_remove( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *bp, /* leaf buffer */ + struct xfs_buf *bp, /* leaf buffer */ int index, /* leaf entry index */ xfs_da_state_blk_t *dblk, /* data block */ int *rval) /* resulting block needs join */ { xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t db; /* data block number */ - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data block entry */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_leaf_t *leaf; /* leaf structure */ @@ -858,7 +857,7 @@ xfs_dir2_leafn_remove( dp = args->dp; tp = args->trans; mp = dp->i_mount; - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); /* * Point to the entry we're removing. @@ -884,7 +883,7 @@ xfs_dir2_leafn_remove( * in the data block in case it changes. */ dbp = dblk->bp; - hdr = dbp->data; + hdr = dbp->b_addr; dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); longest = be16_to_cpu(hdr->bestfree[0].length); needlog = needscan = 0; @@ -905,7 +904,7 @@ xfs_dir2_leafn_remove( */ if (longest < be16_to_cpu(hdr->bestfree[0].length)) { int error; /* error return value */ - xfs_dabuf_t *fbp; /* freeblock buffer */ + struct xfs_buf *fbp; /* freeblock buffer */ xfs_dir2_db_t fdb; /* freeblock block number */ int findex; /* index in freeblock entries */ xfs_dir2_free_t *free; /* freeblock structure */ @@ -920,7 +919,7 @@ xfs_dir2_leafn_remove( -1, &fbp, XFS_DATA_FORK))) { return error; } - free = fbp->data; + free = fbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); ASSERT(be32_to_cpu(free->hdr.firstdb) == xfs_dir2_free_max_bests(mp) * @@ -948,9 +947,7 @@ xfs_dir2_leafn_remove( * In this case just drop the buffer and some one else * will eventually get rid of the empty block. */ - else if (error == ENOSPC && args->total == 0) - xfs_da_buf_done(dbp); - else + else if (!(error == ENOSPC && args->total == 0)) return error; } /* @@ -1018,11 +1015,6 @@ xfs_dir2_leafn_remove( */ if (logfree) xfs_dir2_free_log_bests(tp, fbp, findex, findex); - /* - * Drop the buffer if we still have it. - */ - if (fbp) - xfs_da_buf_done(fbp); } xfs_dir2_leafn_check(dp, bp); /* @@ -1114,7 +1106,7 @@ xfs_dir2_leafn_toosmall( { xfs_da_state_blk_t *blk; /* leaf block */ xfs_dablk_t blkno; /* leaf block number */ - xfs_dabuf_t *bp; /* leaf buffer */ + struct xfs_buf *bp; /* leaf buffer */ int bytes; /* bytes in use */ int count; /* leaf live entry count */ int error; /* error return value */ @@ -1130,7 +1122,7 @@ xfs_dir2_leafn_toosmall( * to coalesce with a sibling. */ blk = &state->path.blk[state->path.active - 1]; - info = blk->bp->data; + info = blk->bp->b_addr; ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); leaf = (xfs_dir2_leaf_t *)info; count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); @@ -1189,7 +1181,7 @@ xfs_dir2_leafn_toosmall( leaf = (xfs_dir2_leaf_t *)info; count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); bytes = state->blocksize - (state->blocksize >> 2); - leaf = bp->data; + leaf = bp->b_addr; ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); bytes -= count * (uint)sizeof(leaf->ents[0]); @@ -1198,7 +1190,7 @@ xfs_dir2_leafn_toosmall( */ if (bytes >= 0) break; - xfs_da_brelse(state->args->trans, bp); + xfs_trans_brelse(state->args->trans, bp); } /* * Didn't like either block, give up. @@ -1207,11 +1199,7 @@ xfs_dir2_leafn_toosmall( *action = 0; return 0; } - /* - * Done with the sibling leaf block here, drop the dabuf - * so path_shift can get it. - */ - xfs_da_buf_done(bp); + /* * Make altpath point to the block we want to keep (the lower * numbered block) and path point to the block we want to drop. @@ -1247,8 +1235,8 @@ xfs_dir2_leafn_unbalance( args = state->args; ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); - drop_leaf = drop_blk->bp->data; - save_leaf = save_blk->bp->data; + drop_leaf = drop_blk->bp->b_addr; + save_leaf = save_blk->bp->b_addr; ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); /* @@ -1356,13 +1344,13 @@ xfs_dir2_node_addname_int( { xfs_dir2_data_hdr_t *hdr; /* data block header */ xfs_dir2_db_t dbno; /* data block number */ - xfs_dabuf_t *dbp; /* data block buffer */ + struct xfs_buf *dbp; /* data block buffer */ xfs_dir2_data_entry_t *dep; /* data entry pointer */ xfs_inode_t *dp; /* incore directory inode */ xfs_dir2_data_unused_t *dup; /* data unused entry pointer */ int error; /* error return value */ xfs_dir2_db_t fbno; /* freespace block number */ - xfs_dabuf_t *fbp; /* freespace buffer */ + struct xfs_buf *fbp; /* freespace buffer */ int findex; /* freespace entry index */ xfs_dir2_free_t *free=NULL; /* freespace block structure */ xfs_dir2_db_t ifbno; /* initial freespace block no */ @@ -1390,7 +1378,7 @@ xfs_dir2_node_addname_int( * Remember initial freespace block number. */ ifbno = fblk->blkno; - free = fbp->data; + free = fbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); findex = fblk->index; /* @@ -1474,7 +1462,7 @@ xfs_dir2_node_addname_int( if (unlikely(fbp == NULL)) { continue; } - free = fbp->data; + free = fbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); findex = 0; } @@ -1492,7 +1480,7 @@ xfs_dir2_node_addname_int( /* * Drop the block. */ - xfs_da_brelse(tp, fbp); + xfs_trans_brelse(tp, fbp); fbp = NULL; if (fblk && fblk->bp) fblk->bp = NULL; @@ -1507,36 +1495,23 @@ xfs_dir2_node_addname_int( /* * Not allowed to allocate, return failure. */ - if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || - args->total == 0) { - /* - * Drop the freespace buffer unless it came from our - * caller. - */ - if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) - xfs_da_buf_done(fbp); + if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) return XFS_ERROR(ENOSPC); - } + /* * Allocate and initialize the new data block. */ if (unlikely((error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &dbno)) || - (error = xfs_dir2_data_init(args, dbno, &dbp)))) { - /* - * Drop the freespace buffer unless it came from our - * caller. - */ - if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) - xfs_da_buf_done(fbp); + (error = xfs_dir2_data_init(args, dbno, &dbp)))) return error; - } + /* * If (somehow) we have a freespace block, get rid of it. */ if (fbp) - xfs_da_brelse(tp, fbp); + xfs_trans_brelse(tp, fbp); if (fblk && fblk->bp) fblk->bp = NULL; @@ -1547,10 +1522,9 @@ xfs_dir2_node_addname_int( fbno = xfs_dir2_db_to_fdb(mp, dbno); if (unlikely(error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno), -2, &fbp, - XFS_DATA_FORK))) { - xfs_da_buf_done(dbp); + XFS_DATA_FORK))) return error; - } + /* * If there wasn't a freespace block, the read will * return a NULL fbp. Allocate and initialize a new one. @@ -1598,7 +1572,7 @@ xfs_dir2_node_addname_int( * Initialize the new block to be empty, and remember * its first slot as our empty slot. */ - free = fbp->data; + free = fbp->b_addr; free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); free->hdr.firstdb = cpu_to_be32( (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * @@ -1606,7 +1580,7 @@ xfs_dir2_node_addname_int( free->hdr.nvalid = 0; free->hdr.nused = 0; } else { - free = fbp->data; + free = fbp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); } @@ -1639,7 +1613,7 @@ xfs_dir2_node_addname_int( * We haven't allocated the data entry yet so this will * change again. */ - hdr = dbp->data; + hdr = dbp->b_addr; free->bests[findex] = hdr->bestfree[0].length; logfree = 1; } @@ -1650,22 +1624,17 @@ xfs_dir2_node_addname_int( /* * If just checking, we succeeded. */ - if (args->op_flags & XFS_DA_OP_JUSTCHECK) { - if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) - xfs_da_buf_done(fbp); + if (args->op_flags & XFS_DA_OP_JUSTCHECK) return 0; - } + /* * Read the data block in. */ - if (unlikely( - error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno), - -1, &dbp, XFS_DATA_FORK))) { - if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) - xfs_da_buf_done(fbp); + error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno), + -1, &dbp, XFS_DATA_FORK); + if (error) return error; - } - hdr = dbp->data; + hdr = dbp->b_addr; logfree = 0; } ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length); @@ -1714,16 +1683,10 @@ xfs_dir2_node_addname_int( if (logfree) xfs_dir2_free_log_bests(tp, fbp, findex, findex); /* - * If the caller didn't hand us the freespace block, drop it. - */ - if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) - xfs_da_buf_done(fbp); - /* * Return the data block and offset in args, then drop the data block. */ args->blkno = (xfs_dablk_t)dbno; args->index = be16_to_cpu(*tagp); - xfs_da_buf_done(dbp); return 0; } @@ -1761,22 +1724,23 @@ xfs_dir2_node_lookup( /* If a CI match, dup the actual name and return EEXIST */ xfs_dir2_data_entry_t *dep; - dep = (xfs_dir2_data_entry_t *)((char *)state->extrablk.bp-> - data + state->extrablk.index); + dep = (xfs_dir2_data_entry_t *) + ((char *)state->extrablk.bp->b_addr + + state->extrablk.index); rval = xfs_dir_cilookup_result(args, dep->name, dep->namelen); } /* * Release the btree blocks and leaf block. */ for (i = 0; i < state->path.active; i++) { - xfs_da_brelse(args->trans, state->path.blk[i].bp); + xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } /* * Release the data block if we have it. */ if (state->extravalid && state->extrablk.bp) { - xfs_da_brelse(args->trans, state->extrablk.bp); + xfs_trans_brelse(args->trans, state->extrablk.bp); state->extrablk.bp = NULL; } xfs_da_state_free(state); @@ -1893,13 +1857,13 @@ xfs_dir2_node_replace( */ blk = &state->path.blk[state->path.active - 1]; ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); - leaf = blk->bp->data; + leaf = blk->bp->b_addr; lep = &leaf->ents[blk->index]; ASSERT(state->extravalid); /* * Point to the data entry. */ - hdr = state->extrablk.bp->data; + hdr = state->extrablk.bp->b_addr; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC)); dep = (xfs_dir2_data_entry_t *) ((char *)hdr + @@ -1916,14 +1880,14 @@ xfs_dir2_node_replace( * Didn't find it, and we're holding a data block. Drop it. */ else if (state->extravalid) { - xfs_da_brelse(args->trans, state->extrablk.bp); + xfs_trans_brelse(args->trans, state->extrablk.bp); state->extrablk.bp = NULL; } /* * Release all the buffers in the cursor. */ for (i = 0; i < state->path.active; i++) { - xfs_da_brelse(args->trans, state->path.blk[i].bp); + xfs_trans_brelse(args->trans, state->path.blk[i].bp); state->path.blk[i].bp = NULL; } xfs_da_state_free(state); @@ -1940,7 +1904,7 @@ xfs_dir2_node_trim_free( xfs_fileoff_t fo, /* free block number */ int *rvalp) /* out: did something */ { - xfs_dabuf_t *bp; /* freespace buffer */ + struct xfs_buf *bp; /* freespace buffer */ xfs_inode_t *dp; /* incore directory inode */ int error; /* error return code */ xfs_dir2_free_t *free; /* freespace structure */ @@ -1965,13 +1929,13 @@ xfs_dir2_node_trim_free( if (bp == NULL) { return 0; } - free = bp->data; + free = bp->b_addr; ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); /* * If there are used entries, there's nothing to do. */ if (be32_to_cpu(free->hdr.nused) > 0) { - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); *rvalp = 0; return 0; } @@ -1987,7 +1951,7 @@ xfs_dir2_node_trim_free( * pieces. This is the last block of an extent. */ ASSERT(error != ENOSPC); - xfs_da_brelse(tp, bp); + xfs_trans_brelse(tp, bp); return error; } /* diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 067f403ecf8..3523d3e15aa 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h @@ -25,7 +25,7 @@ extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r); extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, xfs_dir2_db_t *dbp); extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, - struct xfs_dabuf *bp); + struct xfs_buf *bp); extern int xfs_dir_cilookup_result(struct xfs_da_args *args, const unsigned char *name, int len); @@ -37,11 +37,11 @@ extern int xfs_dir2_block_lookup(struct xfs_da_args *args); extern int xfs_dir2_block_removename(struct xfs_da_args *args); extern int xfs_dir2_block_replace(struct xfs_da_args *args); extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args, - struct xfs_dabuf *lbp, struct xfs_dabuf *dbp); + struct xfs_buf *lbp, struct xfs_buf *dbp); /* xfs_dir2_data.c */ #ifdef DEBUG -extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp); +extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp); #else #define xfs_dir2_data_check(dp,bp) #endif @@ -51,43 +51,43 @@ xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr, extern void xfs_dir2_data_freescan(struct xfs_mount *mp, struct xfs_dir2_data_hdr *hdr, int *loghead); extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, - struct xfs_dabuf **bpp); -extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp, + struct xfs_buf **bpp); +extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); extern void xfs_dir2_data_log_header(struct xfs_trans *tp, - struct xfs_dabuf *bp); -extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp, + struct xfs_buf *bp); +extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); -extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp, +extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); -extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp, +extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); /* xfs_dir2_leaf.c */ extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args, - struct xfs_dabuf *dbp); + struct xfs_buf *dbp); extern int xfs_dir2_leaf_addname(struct xfs_da_args *args); extern void xfs_dir2_leaf_compact(struct xfs_da_args *args, - struct xfs_dabuf *bp); -extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp, + struct xfs_buf *bp); +extern void xfs_dir2_leaf_compact_x1(struct xfs_buf *bp, int *indexp, int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent, size_t bufsize, xfs_off_t *offset, filldir_t filldir); extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno, - struct xfs_dabuf **bpp, int magic); -extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp, + struct xfs_buf **bpp, int magic); +extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, int first, int last); extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp, - struct xfs_dabuf *bp); + struct xfs_buf *bp); extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); extern int xfs_dir2_leaf_replace(struct xfs_da_args *args); extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args, - struct xfs_dabuf *lbp); + struct xfs_buf *lbp); extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args, - struct xfs_dabuf *lbp, xfs_dir2_db_t db); + struct xfs_buf *lbp, xfs_dir2_db_t db); extern struct xfs_dir2_leaf_entry * xfs_dir2_leaf_find_entry(struct xfs_dir2_leaf *leaf, int index, int compact, int lowstale, int highstale, @@ -96,13 +96,13 @@ extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); /* xfs_dir2_node.c */ extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, - struct xfs_dabuf *lbp); -extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count); -extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp, + struct xfs_buf *lbp); +extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_buf *bp, int *count); +extern int xfs_dir2_leafn_lookup_int(struct xfs_buf *bp, struct xfs_da_args *args, int *indexp, struct xfs_da_state *state); -extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp, - struct xfs_dabuf *leaf2_bp); +extern int xfs_dir2_leafn_order(struct xfs_buf *leaf1_bp, + struct xfs_buf *leaf2_bp); extern int xfs_dir2_leafn_split(struct xfs_da_state *state, struct xfs_da_state_blk *oldblk, struct xfs_da_state_blk *newblk); extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action); @@ -122,7 +122,7 @@ extern xfs_ino_t xfs_dir2_sfe_get_ino(struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep); extern int xfs_dir2_block_sfsize(struct xfs_inode *dp, struct xfs_dir2_data_hdr *block, struct xfs_dir2_sf_hdr *sfhp); -extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp, +extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_buf *bp, int size, xfs_dir2_sf_hdr_t *sfhp); extern int xfs_dir2_sf_addname(struct xfs_da_args *args); extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino); diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 19bf0c5e38f..1b9fc3ec7e4 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -222,7 +222,7 @@ xfs_dir2_block_sfsize( int /* error */ xfs_dir2_block_to_sf( xfs_da_args_t *args, /* operation arguments */ - xfs_dabuf_t *bp, /* block buffer */ + struct xfs_buf *bp, int size, /* shortform directory size */ xfs_dir2_sf_hdr_t *sfhp) /* shortform directory hdr */ { @@ -249,7 +249,7 @@ xfs_dir2_block_to_sf( * and add local data. */ hdr = kmem_alloc(mp->m_dirblksize, KM_SLEEP); - memcpy(hdr, bp->data, mp->m_dirblksize); + memcpy(hdr, bp->b_addr, mp->m_dirblksize); logflags = XFS_ILOG_CORE; if ((error = xfs_dir2_shrink_inode(args, mp->m_dirdatablk, bp))) { ASSERT(error != ENOSPC); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 9f7ec15a652..c4559c6e6f2 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -236,7 +236,6 @@ xfs_file_aio_read( ssize_t ret = 0; int ioflags = 0; xfs_fsize_t n; - unsigned long seg; XFS_STATS_INC(xs_read_calls); @@ -247,19 +246,9 @@ xfs_file_aio_read( if (file->f_mode & FMODE_NOCMTIME) ioflags |= IO_INVIS; - /* START copy & waste from filemap.c */ - for (seg = 0; seg < nr_segs; seg++) { - const struct iovec *iv = &iovp[seg]; - - /* - * If any segment has a negative length, or the cumulative - * length ever wraps negative then return -EINVAL. - */ - size += iv->iov_len; - if (unlikely((ssize_t)(size|iv->iov_len) < 0)) - return XFS_ERROR(-EINVAL); - } - /* END copy & waste from filemap.c */ + ret = generic_segment_checks(iovp, &nr_segs, &size, VERIFY_WRITE); + if (ret < 0) + return ret; if (unlikely(ioflags & IO_ISDIRECT)) { xfs_buftarg_t *target = @@ -273,7 +262,7 @@ xfs_file_aio_read( } } - n = XFS_MAXIOFFSET(mp) - iocb->ki_pos; + n = mp->m_super->s_maxbytes - iocb->ki_pos; if (n <= 0 || size == 0) return 0; diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 177a21a7ac4..21e37b55f7e 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -442,14 +442,13 @@ xfs_ialloc_next_ag( * Select an allocation group to look for a free inode in, based on the parent * inode and then mode. Return the allocation group buffer. */ -STATIC xfs_buf_t * /* allocation group buffer */ +STATIC xfs_agnumber_t xfs_ialloc_ag_select( xfs_trans_t *tp, /* transaction pointer */ xfs_ino_t parent, /* parent directory inode number */ umode_t mode, /* bits set to indicate file type */ int okalloc) /* ok to allocate more space */ { - xfs_buf_t *agbp; /* allocation group header buffer */ xfs_agnumber_t agcount; /* number of ag's in the filesystem */ xfs_agnumber_t agno; /* current ag number */ int flags; /* alloc buffer locking flags */ @@ -459,6 +458,7 @@ xfs_ialloc_ag_select( int needspace; /* file mode implies space allocated */ xfs_perag_t *pag; /* per allocation group data */ xfs_agnumber_t pagno; /* parent (starting) ag number */ + int error; /* * Files of these types need at least one block if length > 0 @@ -474,7 +474,9 @@ xfs_ialloc_ag_select( if (pagno >= agcount) pagno = 0; } + ASSERT(pagno < agcount); + /* * Loop through allocation groups, looking for one with a little * free space in it. Note we don't look for free inodes, exactly. @@ -486,51 +488,45 @@ xfs_ialloc_ag_select( flags = XFS_ALLOC_FLAG_TRYLOCK; for (;;) { pag = xfs_perag_get(mp, agno); + if (!pag->pagi_inodeok) { + xfs_ialloc_next_ag(mp); + goto nextag; + } + if (!pag->pagi_init) { - if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { - agbp = NULL; + error = xfs_ialloc_pagi_init(mp, tp, agno); + if (error) goto nextag; - } - } else - agbp = NULL; + } - if (!pag->pagi_inodeok) { - xfs_ialloc_next_ag(mp); - goto unlock_nextag; + if (pag->pagi_freecount) { + xfs_perag_put(pag); + return agno; } - /* - * Is there enough free space for the file plus a block - * of inodes (if we need to allocate some)? - */ - ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp); - if (ineed && !pag->pagf_init) { - if (agbp == NULL && - xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { - agbp = NULL; + if (!okalloc) + goto nextag; + + if (!pag->pagf_init) { + error = xfs_alloc_pagf_init(mp, tp, agno, flags); + if (error) goto nextag; - } - (void)xfs_alloc_pagf_init(mp, tp, agno, flags); } - if (!ineed || pag->pagf_init) { - if (ineed && !(longest = pag->pagf_longest)) - longest = pag->pagf_flcount > 0; - if (!ineed || - (pag->pagf_freeblks >= needspace + ineed && - longest >= ineed && - okalloc)) { - if (agbp == NULL && - xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { - agbp = NULL; - goto nextag; - } - xfs_perag_put(pag); - return agbp; - } + + /* + * Is there enough free space for the file plus a block of + * inodes? (if we need to allocate some)? + */ + ineed = XFS_IALLOC_BLOCKS(mp); + longest = pag->pagf_longest; + if (!longest) + longest = pag->pagf_flcount > 0; + + if (pag->pagf_freeblks >= needspace + ineed && + longest >= ineed) { + xfs_perag_put(pag); + return agno; } -unlock_nextag: - if (agbp) - xfs_trans_brelse(tp, agbp); nextag: xfs_perag_put(pag); /* @@ -538,13 +534,13 @@ nextag: * down. */ if (XFS_FORCED_SHUTDOWN(mp)) - return NULL; + return NULLAGNUMBER; agno++; if (agno >= agcount) agno = 0; if (agno == pagno) { if (flags == 0) - return NULL; + return NULLAGNUMBER; flags = 0; } } @@ -607,195 +603,39 @@ xfs_ialloc_get_rec( } /* - * Visible inode allocation functions. - */ -/* - * Find a free (set) bit in the inode bitmask. - */ -static inline int xfs_ialloc_find_free(xfs_inofree_t *fp) -{ - return xfs_lowbit64(*fp); -} - -/* - * Allocate an inode on disk. - * Mode is used to tell whether the new inode will need space, and whether - * it is a directory. - * - * The arguments IO_agbp and alloc_done are defined to work within - * the constraint of one allocation per transaction. - * xfs_dialloc() is designed to be called twice if it has to do an - * allocation to make more free inodes. On the first call, - * IO_agbp should be set to NULL. If an inode is available, - * i.e., xfs_dialloc() did not need to do an allocation, an inode - * number is returned. In this case, IO_agbp would be set to the - * current ag_buf and alloc_done set to false. - * If an allocation needed to be done, xfs_dialloc would return - * the current ag_buf in IO_agbp and set alloc_done to true. - * The caller should then commit the current transaction, allocate a new - * transaction, and call xfs_dialloc() again, passing in the previous - * value of IO_agbp. IO_agbp should be held across the transactions. - * Since the agbp is locked across the two calls, the second call is - * guaranteed to have a free inode available. + * Allocate an inode. * - * Once we successfully pick an inode its number is returned and the - * on-disk data structures are updated. The inode itself is not read - * in, since doing so would break ordering constraints with xfs_reclaim. + * The caller selected an AG for us, and made sure that free inodes are + * available. */ -int -xfs_dialloc( - xfs_trans_t *tp, /* transaction pointer */ - xfs_ino_t parent, /* parent inode (directory) */ - umode_t mode, /* mode bits for new inode */ - int okalloc, /* ok to allocate more space */ - xfs_buf_t **IO_agbp, /* in/out ag header's buffer */ - boolean_t *alloc_done, /* true if we needed to replenish - inode freelist */ - xfs_ino_t *inop) /* inode number allocated */ +STATIC int +xfs_dialloc_ag( + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_ino_t parent, + xfs_ino_t *inop) { - xfs_agnumber_t agcount; /* number of allocation groups */ - xfs_buf_t *agbp; /* allocation group header's buffer */ - xfs_agnumber_t agno; /* allocation group number */ - xfs_agi_t *agi; /* allocation group header structure */ - xfs_btree_cur_t *cur; /* inode allocation btree cursor */ - int error; /* error return value */ - int i; /* result code */ - int ialloced; /* inode allocation status */ - int noroom = 0; /* no space for inode blk allocation */ - xfs_ino_t ino; /* fs-relative inode to be returned */ - /* REFERENCED */ - int j; /* result code */ - xfs_mount_t *mp; /* file system mount structure */ - int offset; /* index of inode in chunk */ - xfs_agino_t pagino; /* parent's AG relative inode # */ - xfs_agnumber_t pagno; /* parent's AG number */ - xfs_inobt_rec_incore_t rec; /* inode allocation record */ - xfs_agnumber_t tagno; /* testing allocation group number */ - xfs_btree_cur_t *tcur; /* temp cursor */ - xfs_inobt_rec_incore_t trec; /* temp inode allocation record */ - struct xfs_perag *pag; - - - if (*IO_agbp == NULL) { - /* - * We do not have an agbp, so select an initial allocation - * group for inode allocation. - */ - agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc); - /* - * Couldn't find an allocation group satisfying the - * criteria, give up. - */ - if (!agbp) { - *inop = NULLFSINO; - return 0; - } - agi = XFS_BUF_TO_AGI(agbp); - ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); - } else { - /* - * Continue where we left off before. In this case, we - * know that the allocation group has free inodes. - */ - agbp = *IO_agbp; - agi = XFS_BUF_TO_AGI(agbp); - ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); - ASSERT(be32_to_cpu(agi->agi_freecount) > 0); - } - mp = tp->t_mountp; - agcount = mp->m_sb.sb_agcount; - agno = be32_to_cpu(agi->agi_seqno); - tagno = agno; - pagno = XFS_INO_TO_AGNO(mp, parent); - pagino = XFS_INO_TO_AGINO(mp, parent); - - /* - * If we have already hit the ceiling of inode blocks then clear - * okalloc so we scan all available agi structures for a free - * inode. - */ - - if (mp->m_maxicount && - mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) { - noroom = 1; - okalloc = 0; - } + struct xfs_mount *mp = tp->t_mountp; + struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); + xfs_agnumber_t agno = be32_to_cpu(agi->agi_seqno); + xfs_agnumber_t pagno = XFS_INO_TO_AGNO(mp, parent); + xfs_agino_t pagino = XFS_INO_TO_AGINO(mp, parent); + struct xfs_perag *pag; + struct xfs_btree_cur *cur, *tcur; + struct xfs_inobt_rec_incore rec, trec; + xfs_ino_t ino; + int error; + int offset; + int i, j; - /* - * Loop until we find an allocation group that either has free inodes - * or in which we can allocate some inodes. Iterate through the - * allocation groups upward, wrapping at the end. - */ - *alloc_done = B_FALSE; - while (!agi->agi_freecount) { - /* - * Don't do anything if we're not supposed to allocate - * any blocks, just go on to the next ag. - */ - if (okalloc) { - /* - * Try to allocate some new inodes in the allocation - * group. - */ - if ((error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced))) { - xfs_trans_brelse(tp, agbp); - if (error == ENOSPC) { - *inop = NULLFSINO; - return 0; - } else - return error; - } - if (ialloced) { - /* - * We successfully allocated some inodes, return - * the current context to the caller so that it - * can commit the current transaction and call - * us again where we left off. - */ - ASSERT(be32_to_cpu(agi->agi_freecount) > 0); - *alloc_done = B_TRUE; - *IO_agbp = agbp; - *inop = NULLFSINO; - return 0; - } - } - /* - * If it failed, give up on this ag. - */ - xfs_trans_brelse(tp, agbp); - /* - * Go on to the next ag: get its ag header. - */ -nextag: - if (++tagno == agcount) - tagno = 0; - if (tagno == agno) { - *inop = NULLFSINO; - return noroom ? ENOSPC : 0; - } - pag = xfs_perag_get(mp, tagno); - if (pag->pagi_inodeok == 0) { - xfs_perag_put(pag); - goto nextag; - } - error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp); - xfs_perag_put(pag); - if (error) - goto nextag; - agi = XFS_BUF_TO_AGI(agbp); - ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); - } - /* - * Here with an allocation group that has a free inode. - * Reset agno since we may have chosen a new ag in the - * loop above. - */ - agno = tagno; - *IO_agbp = NULL; pag = xfs_perag_get(mp, agno); + ASSERT(pag->pagi_init); + ASSERT(pag->pagi_inodeok); + ASSERT(pag->pagi_freecount > 0); + restart_pagno: - cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno)); + cur = xfs_inobt_init_cursor(mp, tp, agbp, agno); /* * If pagino is 0 (this is the root inode allocation) use newino. * This must work because we've just allocated some. @@ -995,7 +835,7 @@ newino: } alloc_inode: - offset = xfs_ialloc_find_free(&rec.ir_free); + offset = xfs_lowbit64(rec.ir_free); ASSERT(offset >= 0); ASSERT(offset < XFS_INODES_PER_CHUNK); ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % @@ -1028,6 +868,164 @@ error0: } /* + * Allocate an inode on disk. + * + * Mode is used to tell whether the new inode will need space, and whether it + * is a directory. + * + * This function is designed to be called twice if it has to do an allocation + * to make more free inodes. On the first call, *IO_agbp should be set to NULL. + * If an inode is available without having to performn an allocation, an inode + * number is returned. In this case, *IO_agbp would be NULL. If an allocation + * needes to be done, xfs_dialloc would return the current AGI buffer in + * *IO_agbp. The caller should then commit the current transaction, allocate a + * new transaction, and call xfs_dialloc() again, passing in the previous value + * of *IO_agbp. IO_agbp should be held across the transactions. Since the AGI + * buffer is locked across the two calls, the second call is guaranteed to have + * a free inode available. + * + * Once we successfully pick an inode its number is returned and the on-disk + * data structures are updated. The inode itself is not read in, since doing so + * would break ordering constraints with xfs_reclaim. + */ +int +xfs_dialloc( + struct xfs_trans *tp, + xfs_ino_t parent, + umode_t mode, + int okalloc, + struct xfs_buf **IO_agbp, + xfs_ino_t *inop) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_buf *agbp; + xfs_agnumber_t agno; + int error; + int ialloced; + int noroom = 0; + xfs_agnumber_t start_agno; + struct xfs_perag *pag; + + if (*IO_agbp) { + /* + * If the caller passes in a pointer to the AGI buffer, + * continue where we left off before. In this case, we + * know that the allocation group has free inodes. + */ + agbp = *IO_agbp; + goto out_alloc; + } + + /* + * We do not have an agbp, so select an initial allocation + * group for inode allocation. + */ + start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc); + if (start_agno == NULLAGNUMBER) { + *inop = NULLFSINO; + return 0; + } + + /* + * If we have already hit the ceiling of inode blocks then clear + * okalloc so we scan all available agi structures for a free + * inode. + */ + if (mp->m_maxicount && + mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) { + noroom = 1; + okalloc = 0; + } + + /* + * Loop until we find an allocation group that either has free inodes + * or in which we can allocate some inodes. Iterate through the + * allocation groups upward, wrapping at the end. + */ + agno = start_agno; + for (;;) { + pag = xfs_perag_get(mp, agno); + if (!pag->pagi_inodeok) { + xfs_ialloc_next_ag(mp); + goto nextag; + } + + if (!pag->pagi_init) { + error = xfs_ialloc_pagi_init(mp, tp, agno); + if (error) + goto out_error; + } + + /* + * Do a first racy fast path check if this AG is usable. + */ + if (!pag->pagi_freecount && !okalloc) + goto nextag; + + error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); + if (error) + goto out_error; + + /* + * Once the AGI has been read in we have to recheck + * pagi_freecount with the AGI buffer lock held. + */ + if (pag->pagi_freecount) { + xfs_perag_put(pag); + goto out_alloc; + } + + if (!okalloc) { + xfs_trans_brelse(tp, agbp); + goto nextag; + } + + error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced); + if (error) { + xfs_trans_brelse(tp, agbp); + + if (error != ENOSPC) + goto out_error; + + xfs_perag_put(pag); + *inop = NULLFSINO; + return 0; + } + + if (ialloced) { + /* + * We successfully allocated some inodes, return + * the current context to the caller so that it + * can commit the current transaction and call + * us again where we left off. + */ + ASSERT(pag->pagi_freecount > 0); + xfs_perag_put(pag); + + *IO_agbp = agbp; + *inop = NULLFSINO; + return 0; + } + +nextag: + xfs_perag_put(pag); + if (++agno == mp->m_sb.sb_agcount) + agno = 0; + if (agno == start_agno) { + *inop = NULLFSINO; + return noroom ? ENOSPC : 0; + } + } + +out_alloc: + *IO_agbp = NULL; + return xfs_dialloc_ag(tp, agbp, parent, inop); +out_error: + xfs_perag_put(pag); + return XFS_ERROR(error); +} + +/* * Free disk inode. Carefully avoids touching the incore inode, all * manipulations incore are the caller's responsibility. * The on-disk inode is not changed by this operation, only the diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index 65ac57c8063..1fd6ea4e9c9 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h @@ -75,8 +75,6 @@ xfs_dialloc( umode_t mode, /* mode bits for new inode */ int okalloc, /* ok to allocate more space */ struct xfs_buf **agbp, /* buf for a.g. inode header */ - boolean_t *alloc_done, /* an allocation was done to replenish - the free inodes */ xfs_ino_t *inop); /* inode number allocated */ /* diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 1bb4365e8c2..784a803383e 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -41,17 +41,6 @@ /* - * Define xfs inode iolock lockdep classes. We need to ensure that all active - * inodes are considered the same for lockdep purposes, including inodes that - * are recycled through the XFS_IRECLAIMABLE state. This is the the only way to - * guarantee the locks are considered the same when there are multiple lock - * initialisation siteѕ. Also, define a reclaimable inode class so it is - * obvious in lockdep reports which class the report is against. - */ -static struct lock_class_key xfs_iolock_active; -struct lock_class_key xfs_iolock_reclaimable; - -/* * Allocate and initialise an xfs_inode. */ STATIC struct xfs_inode * @@ -80,8 +69,6 @@ xfs_inode_alloc( ASSERT(ip->i_ino == 0); mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); - lockdep_set_class_and_name(&ip->i_iolock.mr_lock, - &xfs_iolock_active, "xfs_iolock_active"); /* initialise the xfs inode */ ip->i_ino = ino; @@ -250,8 +237,6 @@ xfs_iget_cache_hit( ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); - lockdep_set_class_and_name(&ip->i_iolock.mr_lock, - &xfs_iolock_active, "xfs_iolock_active"); spin_unlock(&ip->i_flags_lock); spin_unlock(&pag->pag_ici_lock); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index a59eea09930..2778258fcfa 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -132,23 +132,28 @@ xfs_inobp_check( #endif /* - * Find the buffer associated with the given inode map - * We do basic validation checks on the buffer once it has been - * retrieved from disk. + * This routine is called to map an inode to the buffer containing the on-disk + * version of the inode. It returns a pointer to the buffer containing the + * on-disk inode in the bpp parameter, and in the dipp parameter it returns a + * pointer to the on-disk inode within that buffer. + * + * If a non-zero error is returned, then the contents of bpp and dipp are + * undefined. */ -STATIC int +int xfs_imap_to_bp( - xfs_mount_t *mp, - xfs_trans_t *tp, - struct xfs_imap *imap, - xfs_buf_t **bpp, - uint buf_flags, - uint iget_flags) + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_imap *imap, + struct xfs_dinode **dipp, + struct xfs_buf **bpp, + uint buf_flags, + uint iget_flags) { - int error; - int i; - int ni; - xfs_buf_t *bp; + struct xfs_buf *bp; + int error; + int i; + int ni; buf_flags |= XBF_UNMAPPED; error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, @@ -189,8 +194,8 @@ xfs_imap_to_bp( xfs_trans_brelse(tp, bp); return XFS_ERROR(EINVAL); } - XFS_CORRUPTION_ERROR("xfs_imap_to_bp", - XFS_ERRLEVEL_HIGH, mp, dip); + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, + mp, dip); #ifdef DEBUG xfs_emerg(mp, "bad inode magic/vsn daddr %lld #%d (magic=%x)", @@ -204,96 +209,9 @@ xfs_imap_to_bp( } xfs_inobp_check(mp, bp); - *bpp = bp; - return 0; -} - -/* - * This routine is called to map an inode number within a file - * system to the buffer containing the on-disk version of the - * inode. It returns a pointer to the buffer containing the - * on-disk inode in the bpp parameter, and in the dip parameter - * it returns a pointer to the on-disk inode within that buffer. - * - * If a non-zero error is returned, then the contents of bpp and - * dipp are undefined. - * - * Use xfs_imap() to determine the size and location of the - * buffer to read from disk. - */ -int -xfs_inotobp( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_ino_t ino, - xfs_dinode_t **dipp, - xfs_buf_t **bpp, - int *offset, - uint imap_flags) -{ - struct xfs_imap imap; - xfs_buf_t *bp; - int error; - - imap.im_blkno = 0; - error = xfs_imap(mp, tp, ino, &imap, imap_flags); - if (error) - return error; - - error = xfs_imap_to_bp(mp, tp, &imap, &bp, 0, imap_flags); - if (error) - return error; - - *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset); - *bpp = bp; - *offset = imap.im_boffset; - return 0; -} - - -/* - * This routine is called to map an inode to the buffer containing - * the on-disk version of the inode. It returns a pointer to the - * buffer containing the on-disk inode in the bpp parameter, and in - * the dip parameter it returns a pointer to the on-disk inode within - * that buffer. - * - * If a non-zero error is returned, then the contents of bpp and - * dipp are undefined. - * - * The inode is expected to already been mapped to its buffer and read - * in once, thus we can use the mapping information stored in the inode - * rather than calling xfs_imap(). This allows us to avoid the overhead - * of looking at the inode btree for small block file systems - * (see xfs_imap()). - */ -int -xfs_itobp( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_inode_t *ip, - xfs_dinode_t **dipp, - xfs_buf_t **bpp, - uint buf_flags) -{ - xfs_buf_t *bp; - int error; - - ASSERT(ip->i_imap.im_blkno != 0); - - error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, buf_flags, 0); - if (error) - return error; - if (!bp) { - ASSERT(buf_flags & XBF_TRYLOCK); - ASSERT(tp == NULL); - *bpp = NULL; - return EAGAIN; - } - - *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); *bpp = bp; + *dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset); return 0; } @@ -796,10 +714,9 @@ xfs_iread( /* * Get pointers to the on-disk inode and the buffer containing it. */ - error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, 0, iget_flags); + error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &bp, 0, iget_flags); if (error) return error; - dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); /* * If we got something that isn't an inode it means someone @@ -876,7 +793,7 @@ xfs_iread( /* * Use xfs_trans_brelse() to release the buffer containing the * on-disk inode, because it was acquired with xfs_trans_read_buf() - * in xfs_itobp() above. If tp is NULL, this is just a normal + * in xfs_imap_to_bp() above. If tp is NULL, this is just a normal * brelse(). If we're within a transaction, then xfs_trans_brelse() * will only release the buffer if it is not dirty within the * transaction. It will be OK to release the buffer in this case, @@ -970,7 +887,6 @@ xfs_ialloc( prid_t prid, int okalloc, xfs_buf_t **ialloc_context, - boolean_t *call_again, xfs_inode_t **ipp) { xfs_ino_t ino; @@ -985,10 +901,10 @@ xfs_ialloc( * the on-disk inode to be allocated. */ error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, - ialloc_context, call_again, &ino); + ialloc_context, &ino); if (error) return error; - if (*call_again || ino == NULLFSINO) { + if (*ialloc_context || ino == NULLFSINO) { *ipp = NULL; return 0; } @@ -1207,7 +1123,9 @@ xfs_itruncate_extents( int error = 0; int done = 0; - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + ASSERT(!atomic_read(&VFS_I(ip)->i_count) || + xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(new_size <= XFS_ISIZE(ip)); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(ip->i_itemp != NULL); @@ -1226,7 +1144,7 @@ xfs_itruncate_extents( * then there is nothing to do. */ first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); - last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + last_block = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); if (first_unmap_block == last_block) return 0; @@ -1355,7 +1273,8 @@ xfs_iunlink( * Here we put the head pointer into our next pointer, * and then we fall through to point the head at us. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, + 0, 0); if (error) return error; @@ -1429,16 +1348,16 @@ xfs_iunlink_remove( if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) { /* - * We're at the head of the list. Get the inode's - * on-disk buffer to see if there is anyone after us - * on the list. Only modify our next pointer if it - * is not already NULLAGINO. This saves us the overhead - * of dealing with the buffer when there is no need to - * change it. + * We're at the head of the list. Get the inode's on-disk + * buffer to see if there is anyone after us on the list. + * Only modify our next pointer if it is not already NULLAGINO. + * This saves us the overhead of dealing with the buffer when + * there is no need to change it. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, + 0, 0); if (error) { - xfs_warn(mp, "%s: xfs_itobp() returned error %d.", + xfs_warn(mp, "%s: xfs_imap_to_bp returned error %d.", __func__, error); return error; } @@ -1472,34 +1391,45 @@ xfs_iunlink_remove( next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); last_ibp = NULL; while (next_agino != agino) { - /* - * If the last inode wasn't the one pointing to - * us, then release its buffer since we're not - * going to do anything with it. - */ - if (last_ibp != NULL) { + struct xfs_imap imap; + + if (last_ibp) xfs_trans_brelse(tp, last_ibp); - } + + imap.im_blkno = 0; next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino); - error = xfs_inotobp(mp, tp, next_ino, &last_dip, - &last_ibp, &last_offset, 0); + + error = xfs_imap(mp, tp, next_ino, &imap, 0); + if (error) { + xfs_warn(mp, + "%s: xfs_imap returned error %d.", + __func__, error); + return error; + } + + error = xfs_imap_to_bp(mp, tp, &imap, &last_dip, + &last_ibp, 0, 0); if (error) { xfs_warn(mp, - "%s: xfs_inotobp() returned error %d.", + "%s: xfs_imap_to_bp returned error %d.", __func__, error); return error; } + + last_offset = imap.im_boffset; next_agino = be32_to_cpu(last_dip->di_next_unlinked); ASSERT(next_agino != NULLAGINO); ASSERT(next_agino != 0); } + /* - * Now last_ibp points to the buffer previous to us on - * the unlinked list. Pull us from the list. + * Now last_ibp points to the buffer previous to us on the + * unlinked list. Pull us from the list. */ - error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); + error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, + 0, 0); if (error) { - xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.", + xfs_warn(mp, "%s: xfs_imap_to_bp(2) returned error %d.", __func__, error); return error; } @@ -1749,7 +1679,8 @@ xfs_ifree( xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0); + error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &dip, &ibp, + 0, 0); if (error) return error; @@ -2428,7 +2359,7 @@ xfs_iflush( /* * For stale inodes we cannot rely on the backing buffer remaining * stale in cache for the remaining life of the stale inode and so - * xfs_itobp() below may give us a buffer that no longer contains + * xfs_imap_to_bp() below may give us a buffer that no longer contains * inodes below. We have to check this after ensuring the inode is * unpinned so that it is safe to reclaim the stale inode after the * flush call. @@ -2454,7 +2385,8 @@ xfs_iflush( /* * Get the buffer containing the on-disk inode. */ - error = xfs_itobp(mp, NULL, ip, &dip, &bp, XBF_TRYLOCK); + error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, + 0); if (error || !bp) { xfs_ifunlock(ip); return error; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 1efff36a75b..94b32f906e7 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -487,8 +487,6 @@ static inline int xfs_isiflocked(struct xfs_inode *ip) #define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT) #define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT) -extern struct lock_class_key xfs_iolock_reclaimable; - /* * For multiple groups support: if S_ISGID bit is set in the parent * directory, group of new file is set to that of the parent, and @@ -517,7 +515,7 @@ void xfs_inode_free(struct xfs_inode *ip); */ int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, umode_t, xfs_nlink_t, xfs_dev_t, prid_t, int, - struct xfs_buf **, boolean_t *, xfs_inode_t **); + struct xfs_buf **, xfs_inode_t **); uint xfs_ip2xflags(struct xfs_inode *); uint xfs_dic2xflags(struct xfs_dinode *); @@ -557,12 +555,9 @@ do { \ #define XFS_IGET_UNTRUSTED 0x2 #define XFS_IGET_DONTCACHE 0x4 -int xfs_inotobp(struct xfs_mount *, struct xfs_trans *, - xfs_ino_t, struct xfs_dinode **, - struct xfs_buf **, int *, uint); -int xfs_itobp(struct xfs_mount *, struct xfs_trans *, - struct xfs_inode *, struct xfs_dinode **, - struct xfs_buf **, uint); +int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, + struct xfs_imap *, struct xfs_dinode **, + struct xfs_buf **, uint, uint); int xfs_iread(struct xfs_mount *, struct xfs_trans *, struct xfs_inode *, uint); void xfs_dinode_to_disk(struct xfs_dinode *, diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index aadfce6681e..915edf6639f 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -285,7 +285,7 @@ xfs_iomap_eof_want_preallocate( * do any speculative allocation. */ start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1))); - count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + count_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); while (count_fsb > 0) { imaps = nimaps; firstblock = NULLFSBLOCK; @@ -416,8 +416,8 @@ retry: * Make sure preallocation does not create extents beyond the range we * actually support in this filesystem. */ - if (last_fsb > XFS_B_TO_FSB(mp, mp->m_maxioffset)) - last_fsb = XFS_B_TO_FSB(mp, mp->m_maxioffset); + if (last_fsb > XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes)) + last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); ASSERT(last_fsb > offset_fsb); diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 9c4340f5c3e..4e00cf091d2 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -897,6 +897,47 @@ xfs_vn_setattr( return -xfs_setattr_nonsize(XFS_I(dentry->d_inode), iattr, 0); } +STATIC int +xfs_vn_update_time( + struct inode *inode, + struct timespec *now, + int flags) +{ + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error; + + trace_xfs_update_time(ip); + + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); + error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + return -error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + if (flags & S_CTIME) { + inode->i_ctime = *now; + ip->i_d.di_ctime.t_sec = (__int32_t)now->tv_sec; + ip->i_d.di_ctime.t_nsec = (__int32_t)now->tv_nsec; + } + if (flags & S_MTIME) { + inode->i_mtime = *now; + ip->i_d.di_mtime.t_sec = (__int32_t)now->tv_sec; + ip->i_d.di_mtime.t_nsec = (__int32_t)now->tv_nsec; + } + if (flags & S_ATIME) { + inode->i_atime = *now; + ip->i_d.di_atime.t_sec = (__int32_t)now->tv_sec; + ip->i_d.di_atime.t_nsec = (__int32_t)now->tv_nsec; + } + xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); + xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP); + return -xfs_trans_commit(tp, 0); +} + #define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) /* @@ -991,6 +1032,7 @@ static const struct inode_operations xfs_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, .fiemap = xfs_vn_fiemap, + .update_time = xfs_vn_update_time, }; static const struct inode_operations xfs_dir_inode_operations = { @@ -1016,6 +1058,7 @@ static const struct inode_operations xfs_dir_inode_operations = { .getxattr = generic_getxattr, .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, + .update_time = xfs_vn_update_time, }; static const struct inode_operations xfs_dir_ci_inode_operations = { @@ -1041,6 +1084,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { .getxattr = generic_getxattr, .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, + .update_time = xfs_vn_update_time, }; static const struct inode_operations xfs_symlink_inode_operations = { @@ -1054,6 +1098,7 @@ static const struct inode_operations xfs_symlink_inode_operations = { .getxattr = generic_getxattr, .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, + .update_time = xfs_vn_update_time, }; STATIC void diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index eff577a9b67..01d10a66e30 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -555,7 +555,7 @@ xfs_bulkstat_single( /* * note that requesting valid inode numbers which are not allocated - * to inodes will most likely cause xfs_itobp to generate warning + * to inodes will most likely cause xfs_imap_to_bp to generate warning * messages about bad magic numbers. This is ok. The fact that * the inode isn't actually an inode is handled by the * error check below. Done this way to make the usual case faster diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index d90d4a38860..7f4f9370d0e 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -45,51 +45,85 @@ xlog_commit_record( struct xlog_in_core **iclog, xfs_lsn_t *commitlsnp); -STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, - xfs_buftarg_t *log_target, - xfs_daddr_t blk_offset, - int num_bblks); +STATIC struct xlog * +xlog_alloc_log( + struct xfs_mount *mp, + struct xfs_buftarg *log_target, + xfs_daddr_t blk_offset, + int num_bblks); STATIC int xlog_space_left( struct xlog *log, atomic64_t *head); -STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); -STATIC void xlog_dealloc_log(xlog_t *log); +STATIC int +xlog_sync( + struct xlog *log, + struct xlog_in_core *iclog); +STATIC void +xlog_dealloc_log( + struct xlog *log); /* local state machine functions */ STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); -STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog); -STATIC int xlog_state_get_iclog_space(xlog_t *log, - int len, - xlog_in_core_t **iclog, - xlog_ticket_t *ticket, - int *continued_write, - int *logoffsetp); -STATIC int xlog_state_release_iclog(xlog_t *log, - xlog_in_core_t *iclog); -STATIC void xlog_state_switch_iclogs(xlog_t *log, - xlog_in_core_t *iclog, - int eventual_size); -STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog); +STATIC void +xlog_state_do_callback( + struct xlog *log, + int aborted, + struct xlog_in_core *iclog); +STATIC int +xlog_state_get_iclog_space( + struct xlog *log, + int len, + struct xlog_in_core **iclog, + struct xlog_ticket *ticket, + int *continued_write, + int *logoffsetp); +STATIC int +xlog_state_release_iclog( + struct xlog *log, + struct xlog_in_core *iclog); +STATIC void +xlog_state_switch_iclogs( + struct xlog *log, + struct xlog_in_core *iclog, + int eventual_size); +STATIC void +xlog_state_want_sync( + struct xlog *log, + struct xlog_in_core *iclog); STATIC void xlog_grant_push_ail( - struct xlog *log, - int need_bytes); -STATIC void xlog_regrant_reserve_log_space(xlog_t *log, - xlog_ticket_t *ticket); -STATIC void xlog_ungrant_log_space(xlog_t *log, - xlog_ticket_t *ticket); + struct xlog *log, + int need_bytes); +STATIC void +xlog_regrant_reserve_log_space( + struct xlog *log, + struct xlog_ticket *ticket); +STATIC void +xlog_ungrant_log_space( + struct xlog *log, + struct xlog_ticket *ticket); #if defined(DEBUG) -STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr); +STATIC void +xlog_verify_dest_ptr( + struct xlog *log, + char *ptr); STATIC void xlog_verify_grant_tail( - struct xlog *log); -STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, - int count, boolean_t syncing); -STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, - xfs_lsn_t tail_lsn); + struct xlog *log); +STATIC void +xlog_verify_iclog( + struct xlog *log, + struct xlog_in_core *iclog, + int count, + boolean_t syncing); +STATIC void +xlog_verify_tail_lsn( + struct xlog *log, + struct xlog_in_core *iclog, + xfs_lsn_t tail_lsn); #else #define xlog_verify_dest_ptr(a,b) #define xlog_verify_grant_tail(a) @@ -97,7 +131,9 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, #define xlog_verify_tail_lsn(a,b,c) #endif -STATIC int xlog_iclogs_empty(xlog_t *log); +STATIC int +xlog_iclogs_empty( + struct xlog *log); static void xlog_grant_sub_space( @@ -684,7 +720,7 @@ xfs_log_mount_finish(xfs_mount_t *mp) int xfs_log_unmount_write(xfs_mount_t *mp) { - xlog_t *log = mp->m_log; + struct xlog *log = mp->m_log; xlog_in_core_t *iclog; #ifdef DEBUG xlog_in_core_t *first_iclog; @@ -893,7 +929,7 @@ int xfs_log_need_covered(xfs_mount_t *mp) { int needed = 0; - xlog_t *log = mp->m_log; + struct xlog *log = mp->m_log; if (!xfs_fs_writable(mp)) return 0; @@ -1024,9 +1060,9 @@ xlog_space_left( void xlog_iodone(xfs_buf_t *bp) { - xlog_in_core_t *iclog = bp->b_fspriv; - xlog_t *l = iclog->ic_log; - int aborted = 0; + struct xlog_in_core *iclog = bp->b_fspriv; + struct xlog *l = iclog->ic_log; + int aborted = 0; /* * Race to shutdown the filesystem if we see an error. @@ -1067,8 +1103,9 @@ xlog_iodone(xfs_buf_t *bp) */ STATIC void -xlog_get_iclog_buffer_size(xfs_mount_t *mp, - xlog_t *log) +xlog_get_iclog_buffer_size( + struct xfs_mount *mp, + struct xlog *log) { int size; int xhdrs; @@ -1129,13 +1166,14 @@ done: * Its primary purpose is to fill in enough, so recovery can occur. However, * some other stuff may be filled in too. */ -STATIC xlog_t * -xlog_alloc_log(xfs_mount_t *mp, - xfs_buftarg_t *log_target, - xfs_daddr_t blk_offset, - int num_bblks) +STATIC struct xlog * +xlog_alloc_log( + struct xfs_mount *mp, + struct xfs_buftarg *log_target, + xfs_daddr_t blk_offset, + int num_bblks) { - xlog_t *log; + struct xlog *log; xlog_rec_header_t *head; xlog_in_core_t **iclogp; xlog_in_core_t *iclog, *prev_iclog=NULL; @@ -1144,7 +1182,7 @@ xlog_alloc_log(xfs_mount_t *mp, int error = ENOMEM; uint log2_size = 0; - log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); + log = kmem_zalloc(sizeof(struct xlog), KM_MAYFAIL); if (!log) { xfs_warn(mp, "Log allocation failed: No memory!"); goto out; @@ -1434,8 +1472,9 @@ xlog_bdstrat( */ STATIC int -xlog_sync(xlog_t *log, - xlog_in_core_t *iclog) +xlog_sync( + struct xlog *log, + struct xlog_in_core *iclog) { xfs_caddr_t dptr; /* pointer to byte sized element */ xfs_buf_t *bp; @@ -1584,7 +1623,8 @@ xlog_sync(xlog_t *log, * Deallocate a log structure */ STATIC void -xlog_dealloc_log(xlog_t *log) +xlog_dealloc_log( + struct xlog *log) { xlog_in_core_t *iclog, *next_iclog; int i; @@ -1616,10 +1656,11 @@ xlog_dealloc_log(xlog_t *log) */ /* ARGSUSED */ static inline void -xlog_state_finish_copy(xlog_t *log, - xlog_in_core_t *iclog, - int record_cnt, - int copy_bytes) +xlog_state_finish_copy( + struct xlog *log, + struct xlog_in_core *iclog, + int record_cnt, + int copy_bytes) { spin_lock(&log->l_icloglock); @@ -2142,7 +2183,8 @@ xlog_write( * State Change: DIRTY -> ACTIVE */ STATIC void -xlog_state_clean_log(xlog_t *log) +xlog_state_clean_log( + struct xlog *log) { xlog_in_core_t *iclog; int changed = 0; @@ -2222,7 +2264,7 @@ xlog_state_clean_log(xlog_t *log) STATIC xfs_lsn_t xlog_get_lowest_lsn( - xlog_t *log) + struct xlog *log) { xlog_in_core_t *lsn_log; xfs_lsn_t lowest_lsn, lsn; @@ -2245,9 +2287,9 @@ xlog_get_lowest_lsn( STATIC void xlog_state_do_callback( - xlog_t *log, - int aborted, - xlog_in_core_t *ciclog) + struct xlog *log, + int aborted, + struct xlog_in_core *ciclog) { xlog_in_core_t *iclog; xlog_in_core_t *first_iclog; /* used to know when we've @@ -2467,7 +2509,7 @@ xlog_state_done_syncing( xlog_in_core_t *iclog, int aborted) { - xlog_t *log = iclog->ic_log; + struct xlog *log = iclog->ic_log; spin_lock(&log->l_icloglock); @@ -2521,12 +2563,13 @@ xlog_state_done_syncing( * is copied. */ STATIC int -xlog_state_get_iclog_space(xlog_t *log, - int len, - xlog_in_core_t **iclogp, - xlog_ticket_t *ticket, - int *continued_write, - int *logoffsetp) +xlog_state_get_iclog_space( + struct xlog *log, + int len, + struct xlog_in_core **iclogp, + struct xlog_ticket *ticket, + int *continued_write, + int *logoffsetp) { int log_offset; xlog_rec_header_t *head; @@ -2631,8 +2674,9 @@ restart: * move grant reservation head forward. */ STATIC void -xlog_regrant_reserve_log_space(xlog_t *log, - xlog_ticket_t *ticket) +xlog_regrant_reserve_log_space( + struct xlog *log, + struct xlog_ticket *ticket) { trace_xfs_log_regrant_reserve_enter(log, ticket); @@ -2677,8 +2721,9 @@ xlog_regrant_reserve_log_space(xlog_t *log, * in the current reservation field. */ STATIC void -xlog_ungrant_log_space(xlog_t *log, - xlog_ticket_t *ticket) +xlog_ungrant_log_space( + struct xlog *log, + struct xlog_ticket *ticket) { int bytes; @@ -2717,8 +2762,8 @@ xlog_ungrant_log_space(xlog_t *log, */ STATIC int xlog_state_release_iclog( - xlog_t *log, - xlog_in_core_t *iclog) + struct xlog *log, + struct xlog_in_core *iclog) { int sync = 0; /* do we sync? */ @@ -2768,9 +2813,10 @@ xlog_state_release_iclog( * that every data block. We have run out of space in this log record. */ STATIC void -xlog_state_switch_iclogs(xlog_t *log, - xlog_in_core_t *iclog, - int eventual_size) +xlog_state_switch_iclogs( + struct xlog *log, + struct xlog_in_core *iclog, + int eventual_size) { ASSERT(iclog->ic_state == XLOG_STATE_ACTIVE); if (!eventual_size) @@ -3114,7 +3160,9 @@ xfs_log_force_lsn( * disk. */ STATIC void -xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) +xlog_state_want_sync( + struct xlog *log, + struct xlog_in_core *iclog) { assert_spin_locked(&log->l_icloglock); @@ -3158,7 +3206,7 @@ xfs_log_ticket_get( /* * Allocate and initialise a new log ticket. */ -xlog_ticket_t * +struct xlog_ticket * xlog_ticket_alloc( struct xlog *log, int unit_bytes, @@ -3346,9 +3394,10 @@ xlog_verify_grant_tail( /* check if it will fit */ STATIC void -xlog_verify_tail_lsn(xlog_t *log, - xlog_in_core_t *iclog, - xfs_lsn_t tail_lsn) +xlog_verify_tail_lsn( + struct xlog *log, + struct xlog_in_core *iclog, + xfs_lsn_t tail_lsn) { int blocks; @@ -3385,10 +3434,11 @@ xlog_verify_tail_lsn(xlog_t *log, * the cycle numbers agree with the current cycle number. */ STATIC void -xlog_verify_iclog(xlog_t *log, - xlog_in_core_t *iclog, - int count, - boolean_t syncing) +xlog_verify_iclog( + struct xlog *log, + struct xlog_in_core *iclog, + int count, + boolean_t syncing) { xlog_op_header_t *ophead; xlog_in_core_t *icptr; @@ -3482,7 +3532,7 @@ xlog_verify_iclog(xlog_t *log, */ STATIC int xlog_state_ioerror( - xlog_t *log) + struct xlog *log) { xlog_in_core_t *iclog, *ic; @@ -3527,7 +3577,7 @@ xfs_log_force_umount( struct xfs_mount *mp, int logerror) { - xlog_t *log; + struct xlog *log; int retval; log = mp->m_log; @@ -3634,7 +3684,8 @@ xfs_log_force_umount( } STATIC int -xlog_iclogs_empty(xlog_t *log) +xlog_iclogs_empty( + struct xlog *log) { xlog_in_core_t *iclog; diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 72eba2201b1..18a801d76a4 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -487,7 +487,7 @@ struct xlog_grant_head { * overflow 31 bits worth of byte offset, so using a byte number will mean * that round off problems won't occur when releasing partial reservations. */ -typedef struct xlog { +struct xlog { /* The following fields don't need locking */ struct xfs_mount *l_mp; /* mount point */ struct xfs_ail *l_ailp; /* AIL log is working with */ @@ -540,7 +540,7 @@ typedef struct xlog { char *l_iclog_bak[XLOG_MAX_ICLOGS]; #endif -} xlog_t; +}; #define XLOG_BUF_CANCEL_BUCKET(log, blkno) \ ((log)->l_buf_cancel_table + ((__uint64_t)blkno % XLOG_BC_TABLE_SIZE)) @@ -548,9 +548,17 @@ typedef struct xlog { #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) /* common routines */ -extern int xlog_recover(xlog_t *log); -extern int xlog_recover_finish(xlog_t *log); -extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); +extern int +xlog_recover( + struct xlog *log); +extern int +xlog_recover_finish( + struct xlog *log); +extern void +xlog_pack_data( + struct xlog *log, + struct xlog_in_core *iclog, + int); extern kmem_zone_t *xfs_log_ticket_zone; struct xlog_ticket * diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index a7be98abd6a..5da3ace352b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -43,10 +43,18 @@ #include "xfs_utils.h" #include "xfs_trace.h" -STATIC int xlog_find_zeroed(xlog_t *, xfs_daddr_t *); -STATIC int xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t); +STATIC int +xlog_find_zeroed( + struct xlog *, + xfs_daddr_t *); +STATIC int +xlog_clear_stale_blocks( + struct xlog *, + xfs_lsn_t); #if defined(DEBUG) -STATIC void xlog_recover_check_summary(xlog_t *); +STATIC void +xlog_recover_check_summary( + struct xlog *); #else #define xlog_recover_check_summary(log) #endif @@ -74,7 +82,7 @@ struct xfs_buf_cancel { static inline int xlog_buf_bbcount_valid( - xlog_t *log, + struct xlog *log, int bbcount) { return bbcount > 0 && bbcount <= log->l_logBBsize; @@ -87,7 +95,7 @@ xlog_buf_bbcount_valid( */ STATIC xfs_buf_t * xlog_get_bp( - xlog_t *log, + struct xlog *log, int nbblks) { struct xfs_buf *bp; @@ -138,10 +146,10 @@ xlog_put_bp( */ STATIC xfs_caddr_t xlog_align( - xlog_t *log, + struct xlog *log, xfs_daddr_t blk_no, int nbblks, - xfs_buf_t *bp) + struct xfs_buf *bp) { xfs_daddr_t offset = blk_no & ((xfs_daddr_t)log->l_sectBBsize - 1); @@ -155,10 +163,10 @@ xlog_align( */ STATIC int xlog_bread_noalign( - xlog_t *log, + struct xlog *log, xfs_daddr_t blk_no, int nbblks, - xfs_buf_t *bp) + struct xfs_buf *bp) { int error; @@ -189,10 +197,10 @@ xlog_bread_noalign( STATIC int xlog_bread( - xlog_t *log, + struct xlog *log, xfs_daddr_t blk_no, int nbblks, - xfs_buf_t *bp, + struct xfs_buf *bp, xfs_caddr_t *offset) { int error; @@ -211,10 +219,10 @@ xlog_bread( */ STATIC int xlog_bread_offset( - xlog_t *log, + struct xlog *log, xfs_daddr_t blk_no, /* block to read from */ int nbblks, /* blocks to read */ - xfs_buf_t *bp, + struct xfs_buf *bp, xfs_caddr_t offset) { xfs_caddr_t orig_offset = bp->b_addr; @@ -241,10 +249,10 @@ xlog_bread_offset( */ STATIC int xlog_bwrite( - xlog_t *log, + struct xlog *log, xfs_daddr_t blk_no, int nbblks, - xfs_buf_t *bp) + struct xfs_buf *bp) { int error; @@ -378,8 +386,8 @@ xlog_recover_iodone( */ STATIC int xlog_find_cycle_start( - xlog_t *log, - xfs_buf_t *bp, + struct xlog *log, + struct xfs_buf *bp, xfs_daddr_t first_blk, xfs_daddr_t *last_blk, uint cycle) @@ -421,7 +429,7 @@ xlog_find_cycle_start( */ STATIC int xlog_find_verify_cycle( - xlog_t *log, + struct xlog *log, xfs_daddr_t start_blk, int nbblks, uint stop_on_cycle_no, @@ -490,7 +498,7 @@ out: */ STATIC int xlog_find_verify_log_record( - xlog_t *log, + struct xlog *log, xfs_daddr_t start_blk, xfs_daddr_t *last_blk, int extra_bblks) @@ -600,7 +608,7 @@ out: */ STATIC int xlog_find_head( - xlog_t *log, + struct xlog *log, xfs_daddr_t *return_head_blk) { xfs_buf_t *bp; @@ -871,7 +879,7 @@ validate_head: */ STATIC int xlog_find_tail( - xlog_t *log, + struct xlog *log, xfs_daddr_t *head_blk, xfs_daddr_t *tail_blk) { @@ -1080,7 +1088,7 @@ done: */ STATIC int xlog_find_zeroed( - xlog_t *log, + struct xlog *log, xfs_daddr_t *blk_no) { xfs_buf_t *bp; @@ -1183,7 +1191,7 @@ bp_err: */ STATIC void xlog_add_record( - xlog_t *log, + struct xlog *log, xfs_caddr_t buf, int cycle, int block, @@ -1205,7 +1213,7 @@ xlog_add_record( STATIC int xlog_write_log_records( - xlog_t *log, + struct xlog *log, int cycle, int start_block, int blocks, @@ -1305,7 +1313,7 @@ xlog_write_log_records( */ STATIC int xlog_clear_stale_blocks( - xlog_t *log, + struct xlog *log, xfs_lsn_t tail_lsn) { int tail_cycle, head_cycle; @@ -2050,11 +2058,11 @@ xfs_qm_dqcheck( */ STATIC void xlog_recover_do_dquot_buffer( - xfs_mount_t *mp, - xlog_t *log, - xlog_recover_item_t *item, - xfs_buf_t *bp, - xfs_buf_log_format_t *buf_f) + struct xfs_mount *mp, + struct xlog *log, + struct xlog_recover_item *item, + struct xfs_buf *bp, + struct xfs_buf_log_format *buf_f) { uint type; @@ -2108,9 +2116,9 @@ xlog_recover_do_dquot_buffer( */ STATIC int xlog_recover_buffer_pass2( - xlog_t *log, - struct list_head *buffer_list, - xlog_recover_item_t *item) + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item) { xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; xfs_mount_t *mp = log->l_mp; @@ -2189,9 +2197,9 @@ xlog_recover_buffer_pass2( STATIC int xlog_recover_inode_pass2( - xlog_t *log, - struct list_head *buffer_list, - xlog_recover_item_t *item) + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item) { xfs_inode_log_format_t *in_f; xfs_mount_t *mp = log->l_mp; @@ -2452,14 +2460,14 @@ error: } /* - * Recover QUOTAOFF records. We simply make a note of it in the xlog_t + * Recover QUOTAOFF records. We simply make a note of it in the xlog * structure, so that we know not to do any dquot item or dquot buffer recovery, * of that type. */ STATIC int xlog_recover_quotaoff_pass1( - xlog_t *log, - xlog_recover_item_t *item) + struct xlog *log, + struct xlog_recover_item *item) { xfs_qoff_logformat_t *qoff_f = item->ri_buf[0].i_addr; ASSERT(qoff_f); @@ -2483,9 +2491,9 @@ xlog_recover_quotaoff_pass1( */ STATIC int xlog_recover_dquot_pass2( - xlog_t *log, - struct list_head *buffer_list, - xlog_recover_item_t *item) + struct xlog *log, + struct list_head *buffer_list, + struct xlog_recover_item *item) { xfs_mount_t *mp = log->l_mp; xfs_buf_t *bp; @@ -2578,9 +2586,9 @@ xlog_recover_dquot_pass2( */ STATIC int xlog_recover_efi_pass2( - xlog_t *log, - xlog_recover_item_t *item, - xfs_lsn_t lsn) + struct xlog *log, + struct xlog_recover_item *item, + xfs_lsn_t lsn) { int error; xfs_mount_t *mp = log->l_mp; @@ -2616,8 +2624,8 @@ xlog_recover_efi_pass2( */ STATIC int xlog_recover_efd_pass2( - xlog_t *log, - xlog_recover_item_t *item) + struct xlog *log, + struct xlog_recover_item *item) { xfs_efd_log_format_t *efd_formatp; xfs_efi_log_item_t *efip = NULL; @@ -2812,9 +2820,9 @@ xlog_recover_unmount_trans( */ STATIC int xlog_recover_process_data( - xlog_t *log, + struct xlog *log, struct hlist_head rhash[], - xlog_rec_header_t *rhead, + struct xlog_rec_header *rhead, xfs_caddr_t dp, int pass) { @@ -2986,7 +2994,7 @@ abort_error: */ STATIC int xlog_recover_process_efis( - xlog_t *log) + struct xlog *log) { xfs_log_item_t *lip; xfs_efi_log_item_t *efip; @@ -3098,7 +3106,7 @@ xlog_recover_process_one_iunlink( /* * Get the on disk inode to find the next inode in the bucket. */ - error = xfs_itobp(mp, NULL, ip, &dip, &ibp, 0); + error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &ibp, 0, 0); if (error) goto fail_iput; @@ -3147,7 +3155,7 @@ xlog_recover_process_one_iunlink( */ STATIC void xlog_recover_process_iunlinks( - xlog_t *log) + struct xlog *log) { xfs_mount_t *mp; xfs_agnumber_t agno; @@ -3209,9 +3217,9 @@ xlog_recover_process_iunlinks( #ifdef DEBUG STATIC void xlog_pack_data_checksum( - xlog_t *log, - xlog_in_core_t *iclog, - int size) + struct xlog *log, + struct xlog_in_core *iclog, + int size) { int i; __be32 *up; @@ -3234,8 +3242,8 @@ xlog_pack_data_checksum( */ void xlog_pack_data( - xlog_t *log, - xlog_in_core_t *iclog, + struct xlog *log, + struct xlog_in_core *iclog, int roundoff) { int i, j, k; @@ -3274,9 +3282,9 @@ xlog_pack_data( STATIC void xlog_unpack_data( - xlog_rec_header_t *rhead, + struct xlog_rec_header *rhead, xfs_caddr_t dp, - xlog_t *log) + struct xlog *log) { int i, j, k; @@ -3299,8 +3307,8 @@ xlog_unpack_data( STATIC int xlog_valid_rec_header( - xlog_t *log, - xlog_rec_header_t *rhead, + struct xlog *log, + struct xlog_rec_header *rhead, xfs_daddr_t blkno) { int hlen; @@ -3343,7 +3351,7 @@ xlog_valid_rec_header( */ STATIC int xlog_do_recovery_pass( - xlog_t *log, + struct xlog *log, xfs_daddr_t head_blk, xfs_daddr_t tail_blk, int pass) @@ -3595,7 +3603,7 @@ xlog_do_recovery_pass( */ STATIC int xlog_do_log_recovery( - xlog_t *log, + struct xlog *log, xfs_daddr_t head_blk, xfs_daddr_t tail_blk) { @@ -3646,7 +3654,7 @@ xlog_do_log_recovery( */ STATIC int xlog_do_recover( - xlog_t *log, + struct xlog *log, xfs_daddr_t head_blk, xfs_daddr_t tail_blk) { @@ -3721,7 +3729,7 @@ xlog_do_recover( */ int xlog_recover( - xlog_t *log) + struct xlog *log) { xfs_daddr_t head_blk, tail_blk; int error; @@ -3767,7 +3775,7 @@ xlog_recover( */ int xlog_recover_finish( - xlog_t *log) + struct xlog *log) { /* * Now we're ready to do the transactions needed for the @@ -3814,7 +3822,7 @@ xlog_recover_finish( */ void xlog_recover_check_summary( - xlog_t *log) + struct xlog *log) { xfs_mount_t *mp; xfs_agf_t *agfp; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 536021fb3d4..711ca51ca3d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1200,8 +1200,6 @@ xfs_mountfs( xfs_set_maxicount(mp); - mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); - error = xfs_uuid_mount(mp); if (error) goto out; @@ -1531,6 +1529,15 @@ xfs_unmountfs( xfs_ail_push_all_sync(mp->m_ail); xfs_wait_buftarg(mp->m_ddev_targp); + /* + * The superblock buffer is uncached and xfsaild_push() will lock and + * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait() + * here but a lock on the superblock buffer will block until iodone() + * has completed. + */ + xfs_buf_lock(mp->m_sb_bp); + xfs_buf_unlock(mp->m_sb_bp); + xfs_log_unmount_write(mp); xfs_log_unmount(mp); xfs_uuid_unmount(mp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 90c1fc9eaea..8724336a9a0 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -176,7 +176,6 @@ typedef struct xfs_mount { uint m_qflags; /* quota status flags */ xfs_trans_reservations_t m_reservations;/* precomputed res values */ __uint64_t m_maxicount; /* maximum inode count */ - __uint64_t m_maxioffset; /* maximum inode offset */ __uint64_t m_resblks; /* total reserved blocks */ __uint64_t m_resblks_avail;/* available reserved blocks */ __uint64_t m_resblks_save; /* reserved blks @ remount,ro */ @@ -297,8 +296,6 @@ xfs_preferred_iosize(xfs_mount_t *mp) PAGE_CACHE_SIZE)); } -#define XFS_MAXIOFFSET(mp) ((mp)->m_maxioffset) - #define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \ ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN) #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 249db198776..2e86fa0cfc0 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -940,7 +940,7 @@ xfs_qm_dqiterate( map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP); lblkno = 0; - maxlblkcnt = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + maxlblkcnt = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); do { nmaps = XFS_DQITER_MAP_SIZE; /* diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 0d9de41a715..bdaf4cb9f4a 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -868,67 +868,14 @@ xfs_fs_inode_init_once( "xfsino", ip->i_ino); } -/* - * This is called by the VFS when dirtying inode metadata. This can happen - * for a few reasons, but we only care about timestamp updates, given that - * we handled the rest ourselves. In theory no other calls should happen, - * but for example generic_write_end() keeps dirtying the inode after - * updating i_size. Thus we check that the flags are exactly I_DIRTY_SYNC, - * and skip this call otherwise. - * - * We'll hopefull get a different method just for updating timestamps soon, - * at which point this hack can go away, and maybe we'll also get real - * error handling here. - */ -STATIC void -xfs_fs_dirty_inode( - struct inode *inode, - int flags) -{ - struct xfs_inode *ip = XFS_I(inode); - struct xfs_mount *mp = ip->i_mount; - struct xfs_trans *tp; - int error; - - if (flags != I_DIRTY_SYNC) - return; - - trace_xfs_dirty_inode(ip); - - tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); - error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); - if (error) { - xfs_trans_cancel(tp, 0); - goto trouble; - } - xfs_ilock(ip, XFS_ILOCK_EXCL); - /* - * Grab all the latest timestamps from the Linux inode. - */ - ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; - ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; - ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec; - ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec; - ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec; - ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec; - - xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP); - error = xfs_trans_commit(tp, 0); - if (error) - goto trouble; - return; - -trouble: - xfs_warn(mp, "failed to update timestamps for inode 0x%llx", ip->i_ino); -} - STATIC void xfs_fs_evict_inode( struct inode *inode) { xfs_inode_t *ip = XFS_I(inode); + ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); + trace_xfs_evict_inode(ip); truncate_inode_pages(&inode->i_data, 0); @@ -937,22 +884,6 @@ xfs_fs_evict_inode( XFS_STATS_INC(vn_remove); XFS_STATS_DEC(vn_active); - /* - * The iolock is used by the file system to coordinate reads, - * writes, and block truncates. Up to this point the lock - * protected concurrent accesses by users of the inode. But - * from here forward we're doing some final processing of the - * inode because we're done with it, and although we reuse the - * iolock for protection it is really a distinct lock class - * (in the lockdep sense) from before. To keep lockdep happy - * (and basically indicate what we are doing), we explicitly - * re-init the iolock here. - */ - ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); - mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); - lockdep_set_class_and_name(&ip->i_iolock.mr_lock, - &xfs_iolock_reclaimable, "xfs_iolock_reclaimable"); - xfs_inactive(ip); } @@ -1436,7 +1367,6 @@ xfs_fs_free_cached_objects( static const struct super_operations xfs_super_operations = { .alloc_inode = xfs_fs_alloc_inode, .destroy_inode = xfs_fs_destroy_inode, - .dirty_inode = xfs_fs_dirty_inode, .evict_inode = xfs_fs_evict_inode, .drop_inode = xfs_fs_drop_inode, .put_super = xfs_fs_put_super, @@ -1491,13 +1421,9 @@ xfs_init_zones(void) if (!xfs_da_state_zone) goto out_destroy_btree_cur_zone; - xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf"); - if (!xfs_dabuf_zone) - goto out_destroy_da_state_zone; - xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork"); if (!xfs_ifork_zone) - goto out_destroy_dabuf_zone; + goto out_destroy_da_state_zone; xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans"); if (!xfs_trans_zone) @@ -1514,9 +1440,8 @@ xfs_init_zones(void) * size possible under XFS. This wastes a little bit of memory, * but it is much faster. */ - xfs_buf_item_zone = kmem_zone_init((sizeof(xfs_buf_log_item_t) + - (((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / - NBWORD) * sizeof(int))), "xfs_buf_item"); + xfs_buf_item_zone = kmem_zone_init(sizeof(struct xfs_buf_log_item), + "xfs_buf_item"); if (!xfs_buf_item_zone) goto out_destroy_log_item_desc_zone; @@ -1561,8 +1486,6 @@ xfs_init_zones(void) kmem_zone_destroy(xfs_trans_zone); out_destroy_ifork_zone: kmem_zone_destroy(xfs_ifork_zone); - out_destroy_dabuf_zone: - kmem_zone_destroy(xfs_dabuf_zone); out_destroy_da_state_zone: kmem_zone_destroy(xfs_da_state_zone); out_destroy_btree_cur_zone: @@ -1590,7 +1513,6 @@ xfs_destroy_zones(void) kmem_zone_destroy(xfs_log_item_desc_zone); kmem_zone_destroy(xfs_trans_zone); kmem_zone_destroy(xfs_ifork_zone); - kmem_zone_destroy(xfs_dabuf_zone); kmem_zone_destroy(xfs_da_state_zone); kmem_zone_destroy(xfs_btree_cur_zone); kmem_zone_destroy(xfs_bmap_free_item_zone); diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 1e9ee064dbb..97304f10e78 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c @@ -359,6 +359,15 @@ xfs_quiesce_attr( * added an item to the AIL, thus flush it again. */ xfs_ail_push_all_sync(mp->m_ail); + + /* + * The superblock buffer is uncached and xfsaild_push() will lock and + * set the XBF_ASYNC flag on the buffer. We cannot do xfs_buf_iowait() + * here but a lock on the superblock buffer will block until iodone() + * has completed. + */ + xfs_buf_lock(mp->m_sb_bp); + xfs_buf_unlock(mp->m_sb_bp); } static void @@ -712,8 +721,8 @@ restart: * Note that xfs_iflush will never block on the inode buffer lock, as * xfs_ifree_cluster() can lock the inode buffer before it locks the * ip->i_lock, and we are doing the exact opposite here. As a result, - * doing a blocking xfs_itobp() to get the cluster buffer would result - * in an ABBA deadlock with xfs_ifree_cluster(). + * doing a blocking xfs_imap_to_bp() to get the cluster buffer would + * result in an ABBA deadlock with xfs_ifree_cluster(). * * As xfs_ifree_cluser() must gather all inodes that are active in the * cache to mark them stale, if we hit this case we don't actually want diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index caf5dabfd55..e5795dd6013 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -578,8 +578,8 @@ DEFINE_INODE_EVENT(xfs_ioctl_setattr); DEFINE_INODE_EVENT(xfs_dir_fsync); DEFINE_INODE_EVENT(xfs_file_fsync); DEFINE_INODE_EVENT(xfs_destroy_inode); -DEFINE_INODE_EVENT(xfs_dirty_inode); DEFINE_INODE_EVENT(xfs_evict_inode); +DEFINE_INODE_EVENT(xfs_update_time); DEFINE_INODE_EVENT(xfs_dquot_dqalloc); DEFINE_INODE_EVENT(xfs_dquot_dqdetach); diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 7c37b533aa8..bc2afd52a0b 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -448,11 +448,51 @@ xfs_trans_t *xfs_trans_dup(xfs_trans_t *); int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, uint, uint); void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t); -struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t, - int, uint); -int xfs_trans_read_buf(struct xfs_mount *, xfs_trans_t *, - struct xfs_buftarg *, xfs_daddr_t, int, uint, - struct xfs_buf **); + +struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp, + struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + uint flags); + +static inline struct xfs_buf * +xfs_trans_get_buf( + struct xfs_trans *tp, + struct xfs_buftarg *target, + xfs_daddr_t blkno, + int numblks, + uint flags) +{ + struct xfs_buf_map map = { + .bm_bn = blkno, + .bm_len = numblks, + }; + return xfs_trans_get_buf_map(tp, target, &map, 1, flags); +} + +int xfs_trans_read_buf_map(struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buftarg *target, + struct xfs_buf_map *map, int nmaps, + xfs_buf_flags_t flags, + struct xfs_buf **bpp); + +static inline int +xfs_trans_read_buf( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buftarg *target, + xfs_daddr_t blkno, + int numblks, + xfs_buf_flags_t flags, + struct xfs_buf **bpp) +{ + struct xfs_buf_map map = { + .bm_bn = blkno, + .bm_len = numblks, + }; + return xfs_trans_read_buf_map(mp, tp, target, &map, 1, flags, bpp); +} + struct xfs_buf *xfs_trans_getsb(xfs_trans_t *, struct xfs_mount *, int); void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *); diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 9c514483e59..6011ee66133 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -383,6 +383,12 @@ xfsaild_push( } spin_lock(&ailp->xa_lock); + + /* barrier matches the xa_target update in xfs_ail_push() */ + smp_rmb(); + target = ailp->xa_target; + ailp->xa_target_prev = target; + lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn); if (!lip) { /* @@ -397,7 +403,6 @@ xfsaild_push( XFS_STATS_INC(xs_push_ail); lsn = lip->li_lsn; - target = ailp->xa_target; while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { int lock_result; @@ -527,8 +532,32 @@ xfsaild( __set_current_state(TASK_KILLABLE); else __set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(tout ? - msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT); + + spin_lock(&ailp->xa_lock); + + /* + * Idle if the AIL is empty and we are not racing with a target + * update. We check the AIL after we set the task to a sleep + * state to guarantee that we either catch an xa_target update + * or that a wake_up resets the state to TASK_RUNNING. + * Otherwise, we run the risk of sleeping indefinitely. + * + * The barrier matches the xa_target update in xfs_ail_push(). + */ + smp_rmb(); + if (!xfs_ail_min(ailp) && + ailp->xa_target == ailp->xa_target_prev) { + spin_unlock(&ailp->xa_lock); + schedule(); + tout = 0; + continue; + } + spin_unlock(&ailp->xa_lock); + + if (tout) + schedule_timeout(msecs_to_jiffies(tout)); + + __set_current_state(TASK_RUNNING); try_to_freeze(); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 21c5a5e3700..6311b99c267 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -41,20 +41,26 @@ STATIC struct xfs_buf * xfs_trans_buf_item_match( struct xfs_trans *tp, struct xfs_buftarg *target, - xfs_daddr_t blkno, - int len) + struct xfs_buf_map *map, + int nmaps) { struct xfs_log_item_desc *lidp; struct xfs_buf_log_item *blip; + int len = 0; + int i; + + for (i = 0; i < nmaps; i++) + len += map[i].bm_len; - len = BBTOB(len); list_for_each_entry(lidp, &tp->t_items, lid_trans) { blip = (struct xfs_buf_log_item *)lidp->lid_item; if (blip->bli_item.li_type == XFS_LI_BUF && blip->bli_buf->b_target == target && - XFS_BUF_ADDR(blip->bli_buf) == blkno && - BBTOB(blip->bli_buf->b_length) == len) + XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && + blip->bli_buf->b_length == len) { + ASSERT(blip->bli_buf->b_map_count == nmaps); return blip->bli_buf; + } } return NULL; @@ -128,21 +134,19 @@ xfs_trans_bjoin( * If the transaction pointer is NULL, make this just a normal * get_buf() call. */ -xfs_buf_t * -xfs_trans_get_buf(xfs_trans_t *tp, - xfs_buftarg_t *target_dev, - xfs_daddr_t blkno, - int len, - uint flags) +struct xfs_buf * +xfs_trans_get_buf_map( + struct xfs_trans *tp, + struct xfs_buftarg *target, + struct xfs_buf_map *map, + int nmaps, + xfs_buf_flags_t flags) { xfs_buf_t *bp; xfs_buf_log_item_t *bip; - /* - * Default to a normal get_buf() call if the tp is NULL. - */ - if (tp == NULL) - return xfs_buf_get(target_dev, blkno, len, flags); + if (!tp) + return xfs_buf_get_map(target, map, nmaps, flags); /* * If we find the buffer in the cache with this transaction @@ -150,7 +154,7 @@ xfs_trans_get_buf(xfs_trans_t *tp, * have it locked. In this case we just increment the lock * recursion count and return the buffer to the caller. */ - bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len); + bp = xfs_trans_buf_item_match(tp, target, map, nmaps); if (bp != NULL) { ASSERT(xfs_buf_islocked(bp)); if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { @@ -167,7 +171,7 @@ xfs_trans_get_buf(xfs_trans_t *tp, return (bp); } - bp = xfs_buf_get(target_dev, blkno, len, flags); + bp = xfs_buf_get_map(target, map, nmaps, flags); if (bp == NULL) { return NULL; } @@ -246,26 +250,22 @@ int xfs_error_mod = 33; * read_buf() call. */ int -xfs_trans_read_buf( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_buftarg_t *target, - xfs_daddr_t blkno, - int len, - uint flags, - xfs_buf_t **bpp) +xfs_trans_read_buf_map( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buftarg *target, + struct xfs_buf_map *map, + int nmaps, + xfs_buf_flags_t flags, + struct xfs_buf **bpp) { xfs_buf_t *bp; xfs_buf_log_item_t *bip; int error; *bpp = NULL; - - /* - * Default to a normal get_buf() call if the tp is NULL. - */ - if (tp == NULL) { - bp = xfs_buf_read(target, blkno, len, flags); + if (!tp) { + bp = xfs_buf_read_map(target, map, nmaps, flags); if (!bp) return (flags & XBF_TRYLOCK) ? EAGAIN : XFS_ERROR(ENOMEM); @@ -303,7 +303,7 @@ xfs_trans_read_buf( * If the buffer is not yet read in, then we read it in, increment * the lock recursion count, and return it to the caller. */ - bp = xfs_trans_buf_item_match(tp, target, blkno, len); + bp = xfs_trans_buf_item_match(tp, target, map, nmaps); if (bp != NULL) { ASSERT(xfs_buf_islocked(bp)); ASSERT(bp->b_transp == tp); @@ -349,7 +349,7 @@ xfs_trans_read_buf( return 0; } - bp = xfs_buf_read(target, blkno, len, flags); + bp = xfs_buf_read_map(target, map, nmaps, flags); if (bp == NULL) { *bpp = NULL; return (flags & XBF_TRYLOCK) ? diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index fb62377d1cb..53b7c9b0f8f 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h @@ -67,6 +67,7 @@ struct xfs_ail { struct task_struct *xa_task; struct list_head xa_ail; xfs_lsn_t xa_target; + xfs_lsn_t xa_target_prev; struct list_head xa_cursors; spinlock_t xa_lock; xfs_lsn_t xa_last_pushed_lsn; diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 398cf681d02..7a41874f4c2 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h @@ -133,6 +133,20 @@ typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */ #define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */ /* + * Minimum and maximum blocksize and sectorsize. + * The blocksize upper limit is pretty much arbitrary. + * The sectorsize upper limit is due to sizeof(sb_sectsize). + */ +#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ +#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ +#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) +#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) +#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ +#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ +#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) +#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) + +/* * Min numbers of data/attr fork btree root pointers. */ #define MINDBTPTRS 3 diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 4e5b9ad5cb9..0025c78ac03 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -65,7 +65,6 @@ xfs_dir_ialloc( xfs_trans_t *ntp; xfs_inode_t *ip; xfs_buf_t *ialloc_context = NULL; - boolean_t call_again = B_FALSE; int code; uint log_res; uint log_count; @@ -91,7 +90,7 @@ xfs_dir_ialloc( * the inode(s) that we've just allocated. */ code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, okalloc, - &ialloc_context, &call_again, &ip); + &ialloc_context, &ip); /* * Return an error if we were unable to allocate a new inode. @@ -102,19 +101,18 @@ xfs_dir_ialloc( *ipp = NULL; return code; } - if (!call_again && (ip == NULL)) { + if (!ialloc_context && !ip) { *ipp = NULL; return XFS_ERROR(ENOSPC); } /* - * If call_again is set, then we were unable to get an + * If the AGI buffer is non-NULL, then we were unable to get an * inode in one operation. We need to commit the current * transaction and call xfs_ialloc() again. It is guaranteed * to succeed the second time. */ - if (call_again) { - + if (ialloc_context) { /* * Normally, xfs_trans_commit releases all the locks. * We call bhold to hang on to the ialloc_context across @@ -195,7 +193,7 @@ xfs_dir_ialloc( * this call should always succeed. */ code = xfs_ialloc(tp, dp, mode, nlink, rdev, prid, - okalloc, &ialloc_context, &call_again, &ip); + okalloc, &ialloc_context, &ip); /* * If we get an error at this point, return to the caller @@ -206,12 +204,11 @@ xfs_dir_ialloc( *ipp = NULL; return code; } - ASSERT ((!call_again) && (ip != NULL)); + ASSERT(!ialloc_context && ip); } else { - if (committed != NULL) { + if (committed != NULL) *committed = 0; - } } *ipp = ip; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b6a82d817a8..2a5c637344b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -146,11 +146,6 @@ xfs_readlink( } /* - * Flags for xfs_free_eofblocks - */ -#define XFS_FREE_EOF_TRYLOCK (1<<0) - -/* * This is called by xfs_inactive to free any blocks beyond eof * when the link count isn't zero and by xfs_dm_punch_hole() when * punching a hole to EOF. @@ -159,7 +154,7 @@ STATIC int xfs_free_eofblocks( xfs_mount_t *mp, xfs_inode_t *ip, - int flags) + bool need_iolock) { xfs_trans_t *tp; int error; @@ -174,7 +169,7 @@ xfs_free_eofblocks( * of the file. If not, then there is nothing to do. */ end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); - last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); if (last_fsb <= end_fsb) return 0; map_len = last_fsb - end_fsb; @@ -201,13 +196,11 @@ xfs_free_eofblocks( */ tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - if (flags & XFS_FREE_EOF_TRYLOCK) { + if (need_iolock) { if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL)) { xfs_trans_cancel(tp, 0); return 0; } - } else { - xfs_ilock(ip, XFS_IOLOCK_EXCL); } error = xfs_trans_reserve(tp, 0, @@ -217,7 +210,8 @@ xfs_free_eofblocks( if (error) { ASSERT(XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + if (need_iolock) + xfs_iunlock(ip, XFS_IOLOCK_EXCL); return error; } @@ -244,7 +238,10 @@ xfs_free_eofblocks( error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); } - xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL); + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (need_iolock) + xfs_iunlock(ip, XFS_IOLOCK_EXCL); } return error; } @@ -282,23 +279,15 @@ xfs_inactive_symlink_rmt( * free them all in one bunmapi call. */ ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); - if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, - XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) { - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp, 0); - *tpp = NULL; - return error; - } + /* * Lock the inode, fix the size, and join it to the transaction. * Hold it so in the normal path, we still have it locked for * the second transaction. In the error paths we need it * held so the cancel won't rele it, see below. */ - xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); size = (int)ip->i_d.di_size; ip->i_d.di_size = 0; - xfs_trans_ijoin(tp, ip, 0); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); /* * Find the block(s) so we can inval and unmap them. @@ -385,114 +374,14 @@ xfs_inactive_symlink_rmt( ASSERT(XFS_FORCED_SHUTDOWN(mp)); goto error0; } - /* - * Return with the inode locked but not joined to the transaction. - */ + + xfs_trans_ijoin(tp, ip, 0); *tpp = tp; return 0; error1: xfs_bmap_cancel(&free_list); error0: - /* - * Have to come here with the inode locked and either - * (held and in the transaction) or (not in the transaction). - * If the inode isn't held then cancel would iput it, but - * that's wrong since this is inactive and the vnode ref - * count is 0 already. - * Cancel won't do anything to the inode if held, but it still - * needs to be locked until the cancel is done, if it was - * joined to the transaction. - */ - xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); - *tpp = NULL; - return error; - -} - -STATIC int -xfs_inactive_symlink_local( - xfs_inode_t *ip, - xfs_trans_t **tpp) -{ - int error; - - ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip)); - /* - * We're freeing a symlink which fit into - * the inode. Just free the memory used - * to hold the old symlink. - */ - error = xfs_trans_reserve(*tpp, 0, - XFS_ITRUNCATE_LOG_RES(ip->i_mount), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_ITRUNCATE_LOG_COUNT); - - if (error) { - xfs_trans_cancel(*tpp, 0); - *tpp = NULL; - return error; - } - xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); - - /* - * Zero length symlinks _can_ exist. - */ - if (ip->i_df.if_bytes > 0) { - xfs_idata_realloc(ip, - -(ip->i_df.if_bytes), - XFS_DATA_FORK); - ASSERT(ip->i_df.if_bytes == 0); - } - return 0; -} - -STATIC int -xfs_inactive_attrs( - xfs_inode_t *ip, - xfs_trans_t **tpp) -{ - xfs_trans_t *tp; - int error; - xfs_mount_t *mp; - - ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); - tp = *tpp; - mp = ip->i_mount; - ASSERT(ip->i_d.di_forkoff != 0); - error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - if (error) - goto error_unlock; - - error = xfs_attr_inactive(ip); - if (error) - goto error_unlock; - - tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - error = xfs_trans_reserve(tp, 0, - XFS_IFREE_LOG_RES(mp), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_INACTIVE_LOG_COUNT); - if (error) - goto error_cancel; - - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); - xfs_idestroy_fork(ip, XFS_ATTR_FORK); - - ASSERT(ip->i_d.di_anextents == 0); - - *tpp = tp; - return 0; - -error_cancel: - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp, 0); -error_unlock: - *tpp = NULL; - xfs_iunlock(ip, XFS_IOLOCK_EXCL); return error; } @@ -574,8 +463,7 @@ xfs_release( if (xfs_iflags_test(ip, XFS_IDIRTY_RELEASE)) return 0; - error = xfs_free_eofblocks(mp, ip, - XFS_FREE_EOF_TRYLOCK); + error = xfs_free_eofblocks(mp, ip, true); if (error) return error; @@ -604,7 +492,7 @@ xfs_inactive( xfs_trans_t *tp; xfs_mount_t *mp; int error; - int truncate; + int truncate = 0; /* * If the inode is already free, then there can be nothing @@ -616,17 +504,6 @@ xfs_inactive( return VN_INACTIVE_CACHE; } - /* - * Only do a truncate if it's a regular file with - * some actual space in it. It's OK to look at the - * inode's fields without the lock because we're the - * only one with a reference to the inode. - */ - truncate = ((ip->i_d.di_nlink == 0) && - ((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 || - (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) && - S_ISREG(ip->i_d.di_mode)); - mp = ip->i_mount; error = 0; @@ -643,99 +520,100 @@ xfs_inactive( (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || ip->i_delayed_blks != 0))) { - error = xfs_free_eofblocks(mp, ip, 0); + error = xfs_free_eofblocks(mp, ip, false); if (error) return VN_INACTIVE_CACHE; } goto out; } - ASSERT(ip->i_d.di_nlink == 0); + if (S_ISREG(ip->i_d.di_mode) && + (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 || + ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0)) + truncate = 1; error = xfs_qm_dqattach(ip, 0); if (error) return VN_INACTIVE_CACHE; tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); - if (truncate) { - xfs_ilock(ip, XFS_IOLOCK_EXCL); - - error = xfs_trans_reserve(tp, 0, - XFS_ITRUNCATE_LOG_RES(mp), - 0, XFS_TRANS_PERM_LOG_RES, - XFS_ITRUNCATE_LOG_COUNT); - if (error) { - /* Don't call itruncate_cleanup */ - ASSERT(XFS_FORCED_SHUTDOWN(mp)); - xfs_trans_cancel(tp, 0); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); - return VN_INACTIVE_CACHE; - } + error = xfs_trans_reserve(tp, 0, + (truncate || S_ISLNK(ip->i_d.di_mode)) ? + XFS_ITRUNCATE_LOG_RES(mp) : + XFS_IFREE_LOG_RES(mp), + 0, + XFS_TRANS_PERM_LOG_RES, + XFS_ITRUNCATE_LOG_COUNT); + if (error) { + ASSERT(XFS_FORCED_SHUTDOWN(mp)); + xfs_trans_cancel(tp, 0); + return VN_INACTIVE_CACHE; + } - xfs_ilock(ip, XFS_ILOCK_EXCL); - xfs_trans_ijoin(tp, ip, 0); + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + if (S_ISLNK(ip->i_d.di_mode)) { + /* + * Zero length symlinks _can_ exist. + */ + if (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) { + error = xfs_inactive_symlink_rmt(ip, &tp); + if (error) + goto out_cancel; + } else if (ip->i_df.if_bytes > 0) { + xfs_idata_realloc(ip, -(ip->i_df.if_bytes), + XFS_DATA_FORK); + ASSERT(ip->i_df.if_bytes == 0); + } + } else if (truncate) { ip->i_d.di_size = 0; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); - if (error) { - xfs_trans_cancel(tp, - XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); - xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); - return VN_INACTIVE_CACHE; - } + if (error) + goto out_cancel; ASSERT(ip->i_d.di_nextents == 0); - } else if (S_ISLNK(ip->i_d.di_mode)) { + } - /* - * If we get an error while cleaning up a - * symlink we bail out. - */ - error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ? - xfs_inactive_symlink_rmt(ip, &tp) : - xfs_inactive_symlink_local(ip, &tp); + /* + * If there are attributes associated with the file then blow them away + * now. The code calls a routine that recursively deconstructs the + * attribute fork. We need to just commit the current transaction + * because we can't use it for xfs_attr_inactive(). + */ + if (ip->i_d.di_anextents > 0) { + ASSERT(ip->i_d.di_forkoff != 0); - if (error) { - ASSERT(tp == NULL); - return VN_INACTIVE_CACHE; - } + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); + if (error) + goto out_unlock; - xfs_trans_ijoin(tp, ip, 0); - } else { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + error = xfs_attr_inactive(ip); + if (error) + goto out; + + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); error = xfs_trans_reserve(tp, 0, XFS_IFREE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, XFS_INACTIVE_LOG_COUNT); if (error) { - ASSERT(XFS_FORCED_SHUTDOWN(mp)); xfs_trans_cancel(tp, 0); - return VN_INACTIVE_CACHE; + goto out; } - xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); + xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); } - /* - * If there are attributes associated with the file - * then blow them away now. The code calls a routine - * that recursively deconstructs the attribute fork. - * We need to just commit the current transaction - * because we can't use it for xfs_attr_inactive(). - */ - if (ip->i_d.di_anextents > 0) { - error = xfs_inactive_attrs(ip, &tp); - /* - * If we got an error, the transaction is already - * cancelled, and the inode is unlocked. Just get out. - */ - if (error) - return VN_INACTIVE_CACHE; - } else if (ip->i_afp) { + if (ip->i_afp) xfs_idestroy_fork(ip, XFS_ATTR_FORK); - } + + ASSERT(ip->i_d.di_anextents == 0); /* * Free the inode. @@ -779,10 +657,13 @@ xfs_inactive( * Release the dquots held by inode, if any. */ xfs_qm_dqdetach(ip); - xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); - - out: +out_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); +out: return VN_INACTIVE_CACHE; +out_cancel: + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); + goto out_unlock; } /* @@ -2262,10 +2143,10 @@ xfs_change_file_space( llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len; - if ( (bf->l_start < 0) - || (bf->l_start > XFS_MAXIOFFSET(mp)) - || (bf->l_start + llen < 0) - || (bf->l_start + llen > XFS_MAXIOFFSET(mp))) + if (bf->l_start < 0 || + bf->l_start > mp->m_super->s_maxbytes || + bf->l_start + llen < 0 || + bf->l_start + llen > mp->m_super->s_maxbytes) return XFS_ERROR(EINVAL); bf->l_whence = 0; diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h index abfb2682de7..2be8a2dbc86 100644 --- a/include/asm-generic/dma-coherent.h +++ b/include/asm-generic/dma-coherent.h @@ -29,6 +29,7 @@ dma_mark_declared_memory_occupied(struct device *dev, #else #define dma_alloc_from_coherent(dev, size, handle, ret) (0) #define dma_release_from_coherent(dev, order, vaddr) (0) +#define dma_mmap_from_coherent(dev, vma, vaddr, order, ret) (0) #endif #endif diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h index 2e248d8924d..de8bf89940f 100644 --- a/include/asm-generic/dma-mapping-common.h +++ b/include/asm-generic/dma-mapping-common.h @@ -176,4 +176,59 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL) #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL) +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size); + +/** + * dma_mmap_attrs - map a coherent DMA allocation into user space + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @vma: vm_area_struct describing requested user mapping + * @cpu_addr: kernel CPU-view address returned from dma_alloc_attrs + * @handle: device-view address returned from dma_alloc_attrs + * @size: size of memory originally requested in dma_alloc_attrs + * @attrs: attributes of mapping properties requested in dma_alloc_attrs + * + * Map a coherent DMA buffer previously allocated by dma_alloc_attrs + * into user space. The coherent DMA buffer must not be freed by the + * driver until the user space mapping has been released. + */ +static inline int +dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, + dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs) +{ + struct dma_map_ops *ops = get_dma_ops(dev); + BUG_ON(!ops); + if (ops->mmap) + return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs); + return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); +} + +#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL) + +static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + DEFINE_DMA_ATTRS(attrs); + dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); + return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs); +} + +int +dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t dma_addr, size_t size); + +static inline int +dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr, + dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs) +{ + struct dma_map_ops *ops = get_dma_ops(dev); + BUG_ON(!ops); + if (ops->get_sgtable) + return ops->get_sgtable(dev, sgt, cpu_addr, dma_addr, size, + attrs); + return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size); +} + +#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, NULL) + #endif diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 68733587e70..c20b0018153 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -107,11 +107,6 @@ struct drm_exynos_vidi_connection { uint64_t edid; }; -struct drm_exynos_plane_set_zpos { - __u32 plane_id; - __s32 zpos; -}; - /* memory type definitions. */ enum e_drm_exynos_gem_mem_type { /* Physically Continuous memory and used as default. */ @@ -164,7 +159,6 @@ struct drm_exynos_g2d_exec { #define DRM_EXYNOS_GEM_MMAP 0x02 /* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */ #define DRM_EXYNOS_GEM_GET 0x04 -#define DRM_EXYNOS_PLANE_SET_ZPOS 0x06 #define DRM_EXYNOS_VIDI_CONNECTION 0x07 /* G2D */ @@ -184,9 +178,6 @@ struct drm_exynos_g2d_exec { #define DRM_IOCTL_EXYNOS_GEM_GET DRM_IOWR(DRM_COMMAND_BASE + \ DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info) -#define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos) - #define DRM_IOCTL_EXYNOS_VIDI_CONNECTION DRM_IOWR(DRM_COMMAND_BASE + \ DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b2b4d2ad710..3ad510b2528 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -190,6 +190,8 @@ extern bool wmi_has_guid(const char *guid); extern long acpi_video_get_capabilities(acpi_handle graphics_dev_handle); extern long acpi_is_video_device(struct acpi_device *device); +extern void acpi_video_dmi_promote_vendor(void); +extern void acpi_video_dmi_demote_vendor(void); extern int acpi_video_backlight_support(void); extern int acpi_video_display_switch_support(void); @@ -205,6 +207,14 @@ static inline long acpi_is_video_device(struct acpi_device *device) return 0; } +static inline void acpi_video_dmi_promote_vendor(void) +{ +} + +static inline void acpi_video_dmi_demote_vendor(void) +{ +} + static inline int acpi_video_backlight_support(void) { return 0; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 98f34b886f9..38d27a10aa5 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -66,14 +66,13 @@ typedef int (*dm_request_endio_fn) (struct dm_target *ti, struct request *clone, int error, union map_info *map_context); -typedef void (*dm_flush_fn) (struct dm_target *ti); typedef void (*dm_presuspend_fn) (struct dm_target *ti); typedef void (*dm_postsuspend_fn) (struct dm_target *ti); typedef int (*dm_preresume_fn) (struct dm_target *ti); typedef void (*dm_resume_fn) (struct dm_target *ti); typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, - char *result, unsigned int maxlen); + unsigned status_flags, char *result, unsigned maxlen); typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); @@ -139,7 +138,6 @@ struct target_type { dm_map_request_fn map_rq; dm_endio_fn end_io; dm_request_endio_fn rq_end_io; - dm_flush_fn flush; dm_presuspend_fn presuspend; dm_postsuspend_fn postsuspend; dm_preresume_fn preresume; @@ -188,8 +186,8 @@ struct dm_target { sector_t begin; sector_t len; - /* Always a power of 2 */ - sector_t split_io; + /* If non-zero, maximum size of I/O submitted to a target. */ + uint32_t max_io_len; /* * A number of zero-length barrier requests that will be submitted @@ -214,15 +212,27 @@ struct dm_target { char *error; /* + * Set if this target needs to receive flushes regardless of + * whether or not its underlying devices have support. + */ + bool flush_supported:1; + + /* * Set if this target needs to receive discards regardless of * whether or not its underlying devices have support. */ - unsigned discards_supported:1; + bool discards_supported:1; + + /* + * Set if the target required discard request to be split + * on max_io_len boundary. + */ + bool split_discard_requests:1; /* * Set if this target does not return zeroes on discarded blocks. */ - unsigned discard_zeroes_data_unsupported:1; + bool discard_zeroes_data_unsupported:1; }; /* Each target can link one of these into the table */ @@ -360,6 +370,11 @@ void dm_table_add_target_callbacks(struct dm_table *t, struct dm_target_callback int dm_table_complete(struct dm_table *t); /* + * Target may require that it is never sent I/O larger than len. + */ +int __must_check dm_set_target_max_io_len(struct dm_target *ti, sector_t len); + +/* * Table reference counting. */ struct dm_table *dm_get_live_table(struct mapped_device *md); diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 75fd5573516..91e3a360f61 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h @@ -267,9 +267,9 @@ enum { #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 22 +#define DM_VERSION_MINOR 23 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2011-10-19)" +#define DM_VERSION_EXTRA "-ioctl (2012-07-25)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ @@ -307,6 +307,8 @@ enum { /* * Set this to suspend without flushing queued ios. + * Also disables flushing uncommitted changes in the thin target before + * generating statistics for DM_TABLE_STATUS and DM_DEV_WAIT. */ #define DM_NOFLUSH_FLAG (1 << 11) /* In */ diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h index 547ab568d3a..f83f793223f 100644 --- a/include/linux/dma-attrs.h +++ b/include/linux/dma-attrs.h @@ -15,6 +15,8 @@ enum dma_attr { DMA_ATTR_WEAK_ORDERING, DMA_ATTR_WRITE_COMBINE, DMA_ATTR_NON_CONSISTENT, + DMA_ATTR_NO_KERNEL_MAPPING, + DMA_ATTR_SKIP_CPU_SYNC, DMA_ATTR_MAX, }; diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index dfc099e56a6..94af4185851 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -18,6 +18,9 @@ struct dma_map_ops { int (*mmap)(struct device *, struct vm_area_struct *, void *, dma_addr_t, size_t, struct dma_attrs *attrs); + int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *, + dma_addr_t, size_t, struct dma_attrs *attrs); + dma_addr_t (*map_page)(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction dir, diff --git a/include/linux/edac.h b/include/linux/edac.h index 91ba3bae42e..bab9f8473dc 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -13,9 +13,11 @@ #define _LINUX_EDAC_H_ #include <linux/atomic.h> +#include <linux/device.h> #include <linux/kobject.h> #include <linux/completion.h> #include <linux/workqueue.h> +#include <linux/debugfs.h> struct device; @@ -49,7 +51,19 @@ static inline void opstate_init(void) #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 -/* memory devices */ +/** + * enum dev_type - describe the type of memory DRAM chips used at the stick + * @DEV_UNKNOWN: Can't be determined, or MC doesn't support detect it + * @DEV_X1: 1 bit for data + * @DEV_X2: 2 bits for data + * @DEV_X4: 4 bits for data + * @DEV_X8: 8 bits for data + * @DEV_X16: 16 bits for data + * @DEV_X32: 32 bits for data + * @DEV_X64: 64 bits for data + * + * Typical values are x4 and x8. + */ enum dev_type { DEV_UNKNOWN = 0, DEV_X1, @@ -167,18 +181,30 @@ enum mem_type { #define MEM_FLAG_DDR3 BIT(MEM_DDR3) #define MEM_FLAG_RDDR3 BIT(MEM_RDDR3) -/* chipset Error Detection and Correction capabilities and mode */ +/** + * enum edac-type - Error Detection and Correction capabilities and mode + * @EDAC_UNKNOWN: Unknown if ECC is available + * @EDAC_NONE: Doesn't support ECC + * @EDAC_RESERVED: Reserved ECC type + * @EDAC_PARITY: Detects parity errors + * @EDAC_EC: Error Checking - no correction + * @EDAC_SECDED: Single bit error correction, Double detection + * @EDAC_S2ECD2ED: Chipkill x2 devices - do these exist? + * @EDAC_S4ECD4ED: Chipkill x4 devices + * @EDAC_S8ECD8ED: Chipkill x8 devices + * @EDAC_S16ECD16ED: Chipkill x16 devices + */ enum edac_type { - EDAC_UNKNOWN = 0, /* Unknown if ECC is available */ - EDAC_NONE, /* Doesn't support ECC */ - EDAC_RESERVED, /* Reserved ECC type */ - EDAC_PARITY, /* Detects parity errors */ - EDAC_EC, /* Error Checking - no correction */ - EDAC_SECDED, /* Single bit error correction, Double detection */ - EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */ - EDAC_S4ECD4ED, /* Chipkill x4 devices */ - EDAC_S8ECD8ED, /* Chipkill x8 devices */ - EDAC_S16ECD16ED, /* Chipkill x16 devices */ + EDAC_UNKNOWN = 0, + EDAC_NONE, + EDAC_RESERVED, + EDAC_PARITY, + EDAC_EC, + EDAC_SECDED, + EDAC_S2ECD2ED, + EDAC_S4ECD4ED, + EDAC_S8ECD8ED, + EDAC_S16ECD16ED, }; #define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN) @@ -191,18 +217,30 @@ enum edac_type { #define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED) #define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED) -/* scrubbing capabilities */ +/** + * enum scrub_type - scrubbing capabilities + * @SCRUB_UNKNOWN Unknown if scrubber is available + * @SCRUB_NONE: No scrubber + * @SCRUB_SW_PROG: SW progressive (sequential) scrubbing + * @SCRUB_SW_SRC: Software scrub only errors + * @SCRUB_SW_PROG_SRC: Progressive software scrub from an error + * @SCRUB_SW_TUNABLE: Software scrub frequency is tunable + * @SCRUB_HW_PROG: HW progressive (sequential) scrubbing + * @SCRUB_HW_SRC: Hardware scrub only errors + * @SCRUB_HW_PROG_SRC: Progressive hardware scrub from an error + * SCRUB_HW_TUNABLE: Hardware scrub frequency is tunable + */ enum scrub_type { - SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */ - SCRUB_NONE, /* No scrubber */ - SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */ - SCRUB_SW_SRC, /* Software scrub only errors */ - SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */ - SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */ - SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */ - SCRUB_HW_SRC, /* Hardware scrub only errors */ - SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */ - SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */ + SCRUB_UNKNOWN = 0, + SCRUB_NONE, + SCRUB_SW_PROG, + SCRUB_SW_SRC, + SCRUB_SW_PROG_SRC, + SCRUB_SW_TUNABLE, + SCRUB_HW_PROG, + SCRUB_HW_SRC, + SCRUB_HW_PROG_SRC, + SCRUB_HW_TUNABLE }; #define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG) @@ -374,23 +412,21 @@ struct edac_mc_layer { #define EDAC_MAX_LAYERS 3 /** - * EDAC_DIMM_PTR - Macro responsible to find a pointer inside a pointer array + * EDAC_DIMM_OFF - Macro responsible to get a pointer offset inside a pointer array * for the element given by [layer0,layer1,layer2] position * * @layers: a struct edac_mc_layer array, describing how many elements * were allocated for each layer - * @var: name of the var where we want to get the pointer - * (like mci->dimms) * @n_layers: Number of layers at the @layers array * @layer0: layer0 position * @layer1: layer1 position. Unused if n_layers < 2 * @layer2: layer2 position. Unused if n_layers < 3 * - * For 1 layer, this macro returns &var[layer0] + * For 1 layer, this macro returns &var[layer0] - &var * For 2 layers, this macro is similar to allocate a bi-dimensional array - * and to return "&var[layer0][layer1]" + * and to return "&var[layer0][layer1] - &var" * For 3 layers, this macro is similar to allocate a tri-dimensional array - * and to return "&var[layer0][layer1][layer2]" + * and to return "&var[layer0][layer1][layer2] - &var" * * A loop could be used here to make it more generic, but, as we only have * 3 layers, this is a little faster. @@ -398,23 +434,52 @@ struct edac_mc_layer { * a NULL is returned, causing an OOPS during the memory allocation routine, * with would point to the developer that he's doing something wrong. */ -#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ - typeof(var) __p; \ +#define EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2) ({ \ + int __i; \ if ((nlayers) == 1) \ - __p = &var[layer0]; \ + __i = layer0; \ else if ((nlayers) == 2) \ - __p = &var[(layer1) + ((layers[1]).size * (layer0))]; \ + __i = (layer1) + ((layers[1]).size * (layer0)); \ else if ((nlayers) == 3) \ - __p = &var[(layer2) + ((layers[2]).size * ((layer1) + \ - ((layers[1]).size * (layer0))))]; \ + __i = (layer2) + ((layers[2]).size * ((layer1) + \ + ((layers[1]).size * (layer0)))); \ else \ + __i = -EINVAL; \ + __i; \ +}) + +/** + * EDAC_DIMM_PTR - Macro responsible to get a pointer inside a pointer array + * for the element given by [layer0,layer1,layer2] position + * + * @layers: a struct edac_mc_layer array, describing how many elements + * were allocated for each layer + * @var: name of the var where we want to get the pointer + * (like mci->dimms) + * @n_layers: Number of layers at the @layers array + * @layer0: layer0 position + * @layer1: layer1 position. Unused if n_layers < 2 + * @layer2: layer2 position. Unused if n_layers < 3 + * + * For 1 layer, this macro returns &var[layer0] + * For 2 layers, this macro is similar to allocate a bi-dimensional array + * and to return "&var[layer0][layer1]" + * For 3 layers, this macro is similar to allocate a tri-dimensional array + * and to return "&var[layer0][layer1][layer2]" + */ +#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ + typeof(*var) __p; \ + int ___i = EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2); \ + if (___i < 0) \ __p = NULL; \ + else \ + __p = (var)[___i]; \ __p; \ }) - -/* FIXME: add the proper per-location error counts */ struct dimm_info { + struct device dev; + char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */ /* Memory location data */ @@ -456,6 +521,8 @@ struct rank_info { }; struct csrow_info { + struct device dev; + /* Used only by edac_mc_find_csrow_by_page() */ unsigned long first_page; /* first page number in csrow */ unsigned long last_page; /* last page number in csrow */ @@ -469,44 +536,26 @@ struct csrow_info { struct mem_ctl_info *mci; /* the parent */ - struct kobject kobj; /* sysfs kobject for this csrow */ - /* channel information for this csrow */ u32 nr_channels; - struct rank_info *channels; + struct rank_info **channels; }; -struct mcidev_sysfs_group { - const char *name; /* group name */ - const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */ -}; - -struct mcidev_sysfs_group_kobj { - struct list_head list; /* list for all instances within a mc */ - - struct kobject kobj; /* kobj for the group */ - - const struct mcidev_sysfs_group *grp; /* group description table */ - struct mem_ctl_info *mci; /* the parent */ -}; - -/* mcidev_sysfs_attribute structure - * used for driver sysfs attributes and in mem_ctl_info - * sysfs top level entries +/* + * struct errcount_attribute - used to store the several error counts */ -struct mcidev_sysfs_attribute { - /* It should use either attr or grp */ - struct attribute attr; - const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */ - - /* Ops for show/store values at the attribute - not used on group */ - ssize_t (*show)(struct mem_ctl_info *,char *); - ssize_t (*store)(struct mem_ctl_info *, const char *,size_t); +struct errcount_attribute_data { + int n_layers; + int pos[EDAC_MAX_LAYERS]; + int layer0, layer1, layer2; }; /* MEMORY controller information structure */ struct mem_ctl_info { + struct device dev; + struct bus_type bus; + struct list_head link; /* for global list of mem_ctl_info structs */ struct module *owner; /* Module owner of this control struct */ @@ -548,10 +597,18 @@ struct mem_ctl_info { unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, unsigned long page); int mc_idx; - struct csrow_info *csrows; + struct csrow_info **csrows; unsigned nr_csrows, num_cschannel; - /* Memory Controller hierarchy */ + /* + * Memory Controller hierarchy + * + * There are basically two types of memory controller: the ones that + * sees memory sticks ("dimms"), and the ones that sees memory ranks. + * All old memory controllers enumerate memories per rank, but most + * of the recent drivers enumerate memories per DIMM, instead. + * When the memory controller is per rank, mem_is_per_rank is true. + */ unsigned n_layers; struct edac_mc_layer *layers; bool mem_is_per_rank; @@ -560,14 +617,14 @@ struct mem_ctl_info { * DIMM info. Will eventually remove the entire csrows_info some day */ unsigned tot_dimms; - struct dimm_info *dimms; + struct dimm_info **dimms; /* * FIXME - what about controllers on other busses? - IDs must be * unique. dev pointer should be sufficiently unique, but * BUS:SLOT.FUNC numbers may not be unique. */ - struct device *dev; + struct device *pdev; const char *mod_name; const char *mod_ver; const char *ctl_name; @@ -586,12 +643,6 @@ struct mem_ctl_info { struct completion complete; - /* edac sysfs device control */ - struct kobject edac_mci_kobj; - - /* list for all grp instances within a mc */ - struct list_head grp_kobj_list; - /* Additional top controller level attributes, but specified * by the low level driver. * @@ -609,6 +660,13 @@ struct mem_ctl_info { /* the internal state of this controller instance */ int op_state; + +#ifdef CONFIG_EDAC_DEBUG + struct dentry *debugfs; + u8 fake_inject_layer[EDAC_MAX_LAYERS]; + u32 fake_inject_ue; + u16 fake_inject_count; +#endif }; #endif diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 7edcf103171..db04ec5121c 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -152,7 +152,7 @@ static inline void fw_card_put(struct fw_card *card) struct fw_attribute_group { struct attribute_group *groups[2]; struct attribute_group group; - struct attribute *attrs[12]; + struct attribute *attrs[13]; }; enum fw_device_state { @@ -321,7 +321,7 @@ struct fw_transaction { struct fw_address_handler { u64 offset; - size_t length; + u64 length; fw_address_callback_t address_callback; void *callback_data; struct list_head link; diff --git a/include/linux/input/edt-ft5x06.h b/include/linux/input/edt-ft5x06.h new file mode 100644 index 00000000000..8a1e0d1a012 --- /dev/null +++ b/include/linux/input/edt-ft5x06.h @@ -0,0 +1,24 @@ +#ifndef _EDT_FT5X06_H +#define _EDT_FT5X06_H + +/* + * Copyright (c) 2012 Simon Budig, <simon.budig@kernelconcepts.de> + * + * 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. + */ + +struct edt_ft5x06_platform_data { + int irq_pin; + int reset_pin; + + /* startup defaults for operational parameters */ + bool use_parameters; + u8 gain; + u8 threshold; + u8 offset; + u8 report_rate; +}; + +#endif /* _EDT_FT5X06_H */ diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 39e3c082c49..f0c651cda7b 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -13,6 +13,7 @@ #define _LINUX_KEY_TYPE_H #include <linux/key.h> +#include <linux/errno.h> #ifdef CONFIG_KEYS diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h new file mode 100644 index 00000000000..4c0306c69b4 --- /dev/null +++ b/include/linux/libfdt.h @@ -0,0 +1,8 @@ +#ifndef _INCLUDE_LIBFDT_H_ +#define _INCLUDE_LIBFDT_H_ + +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt.h" +#include "../../scripts/dtc/libfdt/libfdt.h" + +#endif /* _INCLUDE_LIBFDT_H_ */ diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h new file mode 100644 index 00000000000..01508c7b8c8 --- /dev/null +++ b/include/linux/libfdt_env.h @@ -0,0 +1,13 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H + +#include <linux/string.h> + +#include <asm/byteorder.h> + +#define fdt32_to_cpu(x) be32_to_cpu(x) +#define cpu_to_fdt32(x) cpu_to_be32(x) +#define fdt64_to_cpu(x) be64_to_cpu(x) +#define cpu_to_fdt64(x) cpu_to_be64(x) + +#endif /* _LIBFDT_ENV_H */ diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 4aa42732e47..95b738c7abf 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -215,7 +215,7 @@ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, extern bool init_nodemask_of_mempolicy(nodemask_t *mask); extern bool mempolicy_nodemask_intersects(struct task_struct *tsk, const nodemask_t *mask); -extern unsigned slab_node(struct mempolicy *policy); +extern unsigned slab_node(void); extern enum zone_type policy_zone; diff --git a/include/linux/mfd/88pm80x.h b/include/linux/mfd/88pm80x.h new file mode 100644 index 00000000000..a0ca0dca124 --- /dev/null +++ b/include/linux/mfd/88pm80x.h @@ -0,0 +1,369 @@ +/* + * Marvell 88PM80x Interface + * + * Copyright (C) 2012 Marvell International Ltd. + * Qiao Zhou <zhouqiao@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __LINUX_MFD_88PM80X_H +#define __LINUX_MFD_88PM80X_H + +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/regmap.h> +#include <linux/atomic.h> + +#define PM80X_VERSION_MASK (0xFF) /* 80X chip ID mask */ +enum { + CHIP_INVALID = 0, + CHIP_PM800, + CHIP_PM805, + CHIP_MAX, +}; + +enum { + PM800_ID_BUCK1 = 0, + PM800_ID_BUCK2, + PM800_ID_BUCK3, + PM800_ID_BUCK4, + PM800_ID_BUCK5, + + PM800_ID_LDO1, + PM800_ID_LDO2, + PM800_ID_LDO3, + PM800_ID_LDO4, + PM800_ID_LDO5, + PM800_ID_LDO6, + PM800_ID_LDO7, + PM800_ID_LDO8, + PM800_ID_LDO9, + PM800_ID_LDO10, + PM800_ID_LDO11, + PM800_ID_LDO12, + PM800_ID_LDO13, + PM800_ID_LDO14, + PM800_ID_LDO15, + PM800_ID_LDO16, + PM800_ID_LDO17, + PM800_ID_LDO18, + PM800_ID_LDO19, + + PM800_ID_RG_MAX, +}; +#define PM800_MAX_REGULATOR PM800_ID_RG_MAX /* 5 Bucks, 19 LDOs */ +#define PM800_NUM_BUCK (5) /*5 Bucks */ +#define PM800_NUM_LDO (19) /*19 Bucks */ + +/* page 0 basic: slave adder 0x60 */ + +#define PM800_STATUS_1 (0x01) +#define PM800_ONKEY_STS1 (1 << 0) +#define PM800_EXTON_STS1 (1 << 1) +#define PM800_CHG_STS1 (1 << 2) +#define PM800_BAT_STS1 (1 << 3) +#define PM800_VBUS_STS1 (1 << 4) +#define PM800_LDO_PGOOD_STS1 (1 << 5) +#define PM800_BUCK_PGOOD_STS1 (1 << 6) + +#define PM800_STATUS_2 (0x02) +#define PM800_RTC_ALARM_STS2 (1 << 0) + +/* Wakeup Registers */ +#define PM800_WAKEUP1 (0x0D) + +#define PM800_WAKEUP2 (0x0E) +#define PM800_WAKEUP2_INV_INT (1 << 0) +#define PM800_WAKEUP2_INT_CLEAR (1 << 1) +#define PM800_WAKEUP2_INT_MASK (1 << 2) + +#define PM800_POWER_UP_LOG (0x10) + +/* Referance and low power registers */ +#define PM800_LOW_POWER1 (0x20) +#define PM800_LOW_POWER2 (0x21) +#define PM800_LOW_POWER_CONFIG3 (0x22) +#define PM800_LOW_POWER_CONFIG4 (0x23) + +/* GPIO register */ +#define PM800_GPIO_0_1_CNTRL (0x30) +#define PM800_GPIO0_VAL (1 << 0) +#define PM800_GPIO0_GPIO_MODE(x) (x << 1) +#define PM800_GPIO1_VAL (1 << 4) +#define PM800_GPIO1_GPIO_MODE(x) (x << 5) + +#define PM800_GPIO_2_3_CNTRL (0x31) +#define PM800_GPIO2_VAL (1 << 0) +#define PM800_GPIO2_GPIO_MODE(x) (x << 1) +#define PM800_GPIO3_VAL (1 << 4) +#define PM800_GPIO3_GPIO_MODE(x) (x << 5) +#define PM800_GPIO3_MODE_MASK 0x1F +#define PM800_GPIO3_HEADSET_MODE PM800_GPIO3_GPIO_MODE(6) + +#define PM800_GPIO_4_CNTRL (0x32) +#define PM800_GPIO4_VAL (1 << 0) +#define PM800_GPIO4_GPIO_MODE(x) (x << 1) + +#define PM800_HEADSET_CNTRL (0x38) +#define PM800_HEADSET_DET_EN (1 << 7) +#define PM800_HSDET_SLP (1 << 1) +/* PWM register */ +#define PM800_PWM1 (0x40) +#define PM800_PWM2 (0x41) +#define PM800_PWM3 (0x42) +#define PM800_PWM4 (0x43) + +/* RTC Registers */ +#define PM800_RTC_CONTROL (0xD0) +#define PM800_RTC_MISC1 (0xE1) +#define PM800_RTC_MISC2 (0xE2) +#define PM800_RTC_MISC3 (0xE3) +#define PM800_RTC_MISC4 (0xE4) +#define PM800_RTC_MISC5 (0xE7) +/* bit definitions of RTC Register 1 (0xD0) */ +#define PM800_ALARM1_EN (1 << 0) +#define PM800_ALARM_WAKEUP (1 << 4) +#define PM800_ALARM (1 << 5) +#define PM800_RTC1_USE_XO (1 << 7) + +/* Regulator Control Registers: BUCK1,BUCK5,LDO1 have DVC */ + +/* buck registers */ +#define PM800_SLEEP_BUCK1 (0x30) + +/* BUCK Sleep Mode Register 1: BUCK[1..4] */ +#define PM800_BUCK_SLP1 (0x5A) +#define PM800_BUCK1_SLP1_SHIFT 0 +#define PM800_BUCK1_SLP1_MASK (0x3 << PM800_BUCK1_SLP1_SHIFT) + +/* page 2 GPADC: slave adder 0x02 */ +#define PM800_GPADC_MEAS_EN1 (0x01) +#define PM800_MEAS_EN1_VBAT (1 << 2) +#define PM800_GPADC_MEAS_EN2 (0x02) +#define PM800_MEAS_EN2_RFTMP (1 << 0) +#define PM800_MEAS_GP0_EN (1 << 2) +#define PM800_MEAS_GP1_EN (1 << 3) +#define PM800_MEAS_GP2_EN (1 << 4) +#define PM800_MEAS_GP3_EN (1 << 5) +#define PM800_MEAS_GP4_EN (1 << 6) + +#define PM800_GPADC_MISC_CONFIG1 (0x05) +#define PM800_GPADC_MISC_CONFIG2 (0x06) +#define PM800_GPADC_MISC_GPFSM_EN (1 << 0) +#define PM800_GPADC_SLOW_MODE(x) (x << 3) + +#define PM800_GPADC_MISC_CONFIG3 (0x09) +#define PM800_GPADC_MISC_CONFIG4 (0x0A) + +#define PM800_GPADC_PREBIAS1 (0x0F) +#define PM800_GPADC0_GP_PREBIAS_TIME(x) (x << 0) +#define PM800_GPADC_PREBIAS2 (0x10) + +#define PM800_GP_BIAS_ENA1 (0x14) +#define PM800_GPADC_GP_BIAS_EN0 (1 << 0) +#define PM800_GPADC_GP_BIAS_EN1 (1 << 1) +#define PM800_GPADC_GP_BIAS_EN2 (1 << 2) +#define PM800_GPADC_GP_BIAS_EN3 (1 << 3) + +#define PM800_GP_BIAS_OUT1 (0x15) +#define PM800_BIAS_OUT_GP0 (1 << 0) +#define PM800_BIAS_OUT_GP1 (1 << 1) +#define PM800_BIAS_OUT_GP2 (1 << 2) +#define PM800_BIAS_OUT_GP3 (1 << 3) + +#define PM800_GPADC0_LOW_TH 0x20 +#define PM800_GPADC1_LOW_TH 0x21 +#define PM800_GPADC2_LOW_TH 0x22 +#define PM800_GPADC3_LOW_TH 0x23 +#define PM800_GPADC4_LOW_TH 0x24 + +#define PM800_GPADC0_UPP_TH 0x30 +#define PM800_GPADC1_UPP_TH 0x31 +#define PM800_GPADC2_UPP_TH 0x32 +#define PM800_GPADC3_UPP_TH 0x33 +#define PM800_GPADC4_UPP_TH 0x34 + +#define PM800_VBBAT_MEAS1 0x40 +#define PM800_VBBAT_MEAS2 0x41 +#define PM800_VBAT_MEAS1 0x42 +#define PM800_VBAT_MEAS2 0x43 +#define PM800_VSYS_MEAS1 0x44 +#define PM800_VSYS_MEAS2 0x45 +#define PM800_VCHG_MEAS1 0x46 +#define PM800_VCHG_MEAS2 0x47 +#define PM800_TINT_MEAS1 0x50 +#define PM800_TINT_MEAS2 0x51 +#define PM800_PMOD_MEAS1 0x52 +#define PM800_PMOD_MEAS2 0x53 + +#define PM800_GPADC0_MEAS1 0x54 +#define PM800_GPADC0_MEAS2 0x55 +#define PM800_GPADC1_MEAS1 0x56 +#define PM800_GPADC1_MEAS2 0x57 +#define PM800_GPADC2_MEAS1 0x58 +#define PM800_GPADC2_MEAS2 0x59 +#define PM800_GPADC3_MEAS1 0x5A +#define PM800_GPADC3_MEAS2 0x5B +#define PM800_GPADC4_MEAS1 0x5C +#define PM800_GPADC4_MEAS2 0x5D + +#define PM800_GPADC4_AVG1 0xA8 +#define PM800_GPADC4_AVG2 0xA9 + +/* 88PM805 Registers */ +#define PM805_MAIN_POWERUP (0x01) +#define PM805_INT_STATUS0 (0x02) /* for ena/dis all interrupts */ + +#define PM805_STATUS0_INT_CLEAR (1 << 0) +#define PM805_STATUS0_INV_INT (1 << 1) +#define PM800_STATUS0_INT_MASK (1 << 2) + +#define PM805_INT_STATUS1 (0x03) + +#define PM805_INT1_HP1_SHRT (1 << 0) +#define PM805_INT1_HP2_SHRT (1 << 1) +#define PM805_INT1_MIC_CONFLICT (1 << 2) +#define PM805_INT1_CLIP_FAULT (1 << 3) +#define PM805_INT1_LDO_OFF (1 << 4) +#define PM805_INT1_SRC_DPLL_LOCK (1 << 5) + +#define PM805_INT_STATUS2 (0x04) + +#define PM805_INT2_MIC_DET (1 << 0) +#define PM805_INT2_SHRT_BTN_DET (1 << 1) +#define PM805_INT2_VOLM_BTN_DET (1 << 2) +#define PM805_INT2_VOLP_BTN_DET (1 << 3) +#define PM805_INT2_RAW_PLL_FAULT (1 << 4) +#define PM805_INT2_FINE_PLL_FAULT (1 << 5) + +#define PM805_INT_MASK1 (0x05) +#define PM805_INT_MASK2 (0x06) +#define PM805_SHRT_BTN_DET (1 << 1) + +/* number of status and int reg in a row */ +#define PM805_INT_REG_NUM (2) + +#define PM805_MIC_DET1 (0x07) +#define PM805_MIC_DET_EN_MIC_DET (1 << 0) +#define PM805_MIC_DET2 (0x08) +#define PM805_MIC_DET_STATUS1 (0x09) + +#define PM805_MIC_DET_STATUS3 (0x0A) +#define PM805_AUTO_SEQ_STATUS1 (0x0B) +#define PM805_AUTO_SEQ_STATUS2 (0x0C) + +#define PM805_ADC_SETTING1 (0x10) +#define PM805_ADC_SETTING2 (0x11) +#define PM805_ADC_SETTING3 (0x11) +#define PM805_ADC_GAIN1 (0x12) +#define PM805_ADC_GAIN2 (0x13) +#define PM805_DMIC_SETTING (0x15) +#define PM805_DWS_SETTING (0x16) +#define PM805_MIC_CONFLICT_STS (0x17) + +#define PM805_PDM_SETTING1 (0x20) +#define PM805_PDM_SETTING2 (0x21) +#define PM805_PDM_SETTING3 (0x22) +#define PM805_PDM_CONTROL1 (0x23) +#define PM805_PDM_CONTROL2 (0x24) +#define PM805_PDM_CONTROL3 (0x25) + +#define PM805_HEADPHONE_SETTING (0x26) +#define PM805_HEADPHONE_GAIN_A2A (0x27) +#define PM805_HEADPHONE_SHORT_STATE (0x28) +#define PM805_EARPHONE_SETTING (0x29) +#define PM805_AUTO_SEQ_SETTING (0x2A) + +struct pm80x_rtc_pdata { + int vrtc; + int rtc_wakeup; +}; + +struct pm80x_subchip { + struct i2c_client *power_page; /* chip client for power page */ + struct i2c_client *gpadc_page; /* chip client for gpadc page */ + struct regmap *regmap_power; + struct regmap *regmap_gpadc; + unsigned short power_page_addr; /* power page I2C address */ + unsigned short gpadc_page_addr; /* gpadc page I2C address */ +}; + +struct pm80x_chip { + struct pm80x_subchip *subchip; + struct device *dev; + struct i2c_client *client; + struct i2c_client *companion; + struct regmap *regmap; + struct regmap_irq_chip *regmap_irq_chip; + struct regmap_irq_chip_data *irq_data; + unsigned char version; + int id; + int irq; + int irq_mode; + unsigned long wu_flag; + spinlock_t lock; +}; + +struct pm80x_platform_data { + struct pm80x_rtc_pdata *rtc; + unsigned short power_page_addr; /* power page I2C address */ + unsigned short gpadc_page_addr; /* gpadc page I2C address */ + int irq_mode; /* Clear interrupt by read/write(0/1) */ + int batt_det; /* enable/disable */ + int (*plat_config)(struct pm80x_chip *chip, + struct pm80x_platform_data *pdata); +}; + +extern const struct dev_pm_ops pm80x_pm_ops; +extern const struct regmap_config pm80x_regmap_config; + +static inline int pm80x_request_irq(struct pm80x_chip *pm80x, int irq, + irq_handler_t handler, unsigned long flags, + const char *name, void *data) +{ + if (!pm80x->irq_data) + return -EINVAL; + return request_threaded_irq(regmap_irq_get_virq(pm80x->irq_data, irq), + NULL, handler, flags, name, data); +} + +static inline void pm80x_free_irq(struct pm80x_chip *pm80x, int irq, void *data) +{ + if (!pm80x->irq_data) + return; + free_irq(regmap_irq_get_virq(pm80x->irq_data, irq), data); +} + +#ifdef CONFIG_PM +static inline int pm80x_dev_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + int irq = platform_get_irq(pdev, 0); + + if (device_may_wakeup(dev)) + set_bit((1 << irq), &chip->wu_flag); + + return 0; +} + +static inline int pm80x_dev_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + int irq = platform_get_irq(pdev, 0); + + if (device_may_wakeup(dev)) + clear_bit((1 << irq), &chip->wu_flag); + + return 0; +} +#endif + +extern int pm80x_init(struct i2c_client *client, + const struct i2c_device_id *id) __devinit; +extern int pm80x_deinit(struct i2c_client *client); +#endif /* __LINUX_MFD_88PM80X_H */ diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h index 84d071ade1d..7b24943779f 100644 --- a/include/linux/mfd/88pm860x.h +++ b/include/linux/mfd/88pm860x.h @@ -136,6 +136,7 @@ enum { PM8607_ID_LDO13, PM8607_ID_LDO14, PM8607_ID_LDO15, + PM8606_ID_PREG, PM8607_ID_RG_MAX, }; diff --git a/include/linux/mfd/abx500/ab8500.h b/include/linux/mfd/abx500/ab8500.h index bc9b84b60ec..3764cb6759e 100644 --- a/include/linux/mfd/abx500/ab8500.h +++ b/include/linux/mfd/abx500/ab8500.h @@ -9,6 +9,7 @@ #include <linux/atomic.h> #include <linux/mutex.h> +#include <linux/irqdomain.h> struct device; @@ -227,6 +228,7 @@ enum ab8500_version { * @irq_lock: genirq bus lock * @transfer_ongoing: 0 if no transfer ongoing * @irq: irq line + * @irq_domain: irq domain * @version: chip version id (e.g. ab8500 or ab9540) * @chip_id: chip revision id * @write: register write @@ -247,6 +249,7 @@ struct ab8500 { atomic_t transfer_ongoing; int irq_base; int irq; + struct irq_domain *domain; enum ab8500_version version; u8 chip_id; @@ -338,4 +341,6 @@ static inline int is_ab8500_2p0(struct ab8500 *ab) return (is_ab8500(ab) && (ab->chip_id == AB8500_CUT2P0)); } +int ab8500_irq_get_virq(struct ab8500 *ab8500, int irq); + #endif /* MFD_AB8500_H */ diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h new file mode 100644 index 00000000000..dd231ac0bb1 --- /dev/null +++ b/include/linux/mfd/arizona/core.h @@ -0,0 +1,114 @@ +/* + * Arizona MFD internals + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _WM_ARIZONA_CORE_H +#define _WM_ARIZONA_CORE_H + +#include <linux/interrupt.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/mfd/arizona/pdata.h> + +#define ARIZONA_MAX_CORE_SUPPLIES 3 + +enum arizona_type { + WM5102 = 1, + WM5110 = 2, +}; + +#define ARIZONA_IRQ_GP1 0 +#define ARIZONA_IRQ_GP2 1 +#define ARIZONA_IRQ_GP3 2 +#define ARIZONA_IRQ_GP4 3 +#define ARIZONA_IRQ_GP5_FALL 4 +#define ARIZONA_IRQ_GP5_RISE 5 +#define ARIZONA_IRQ_JD_FALL 6 +#define ARIZONA_IRQ_JD_RISE 7 +#define ARIZONA_IRQ_DSP1_RAM_RDY 8 +#define ARIZONA_IRQ_DSP2_RAM_RDY 9 +#define ARIZONA_IRQ_DSP3_RAM_RDY 10 +#define ARIZONA_IRQ_DSP4_RAM_RDY 11 +#define ARIZONA_IRQ_DSP_IRQ1 12 +#define ARIZONA_IRQ_DSP_IRQ2 13 +#define ARIZONA_IRQ_DSP_IRQ3 14 +#define ARIZONA_IRQ_DSP_IRQ4 15 +#define ARIZONA_IRQ_DSP_IRQ5 16 +#define ARIZONA_IRQ_DSP_IRQ6 17 +#define ARIZONA_IRQ_DSP_IRQ7 18 +#define ARIZONA_IRQ_DSP_IRQ8 19 +#define ARIZONA_IRQ_SPK_SHUTDOWN_WARN 20 +#define ARIZONA_IRQ_SPK_SHUTDOWN 21 +#define ARIZONA_IRQ_MICDET 22 +#define ARIZONA_IRQ_HPDET 23 +#define ARIZONA_IRQ_WSEQ_DONE 24 +#define ARIZONA_IRQ_DRC2_SIG_DET 25 +#define ARIZONA_IRQ_DRC1_SIG_DET 26 +#define ARIZONA_IRQ_ASRC2_LOCK 27 +#define ARIZONA_IRQ_ASRC1_LOCK 28 +#define ARIZONA_IRQ_UNDERCLOCKED 29 +#define ARIZONA_IRQ_OVERCLOCKED 30 +#define ARIZONA_IRQ_FLL2_LOCK 31 +#define ARIZONA_IRQ_FLL1_LOCK 32 +#define ARIZONA_IRQ_CLKGEN_ERR 33 +#define ARIZONA_IRQ_CLKGEN_ERR_ASYNC 34 +#define ARIZONA_IRQ_ASRC_CFG_ERR 35 +#define ARIZONA_IRQ_AIF3_ERR 36 +#define ARIZONA_IRQ_AIF2_ERR 37 +#define ARIZONA_IRQ_AIF1_ERR 38 +#define ARIZONA_IRQ_CTRLIF_ERR 39 +#define ARIZONA_IRQ_MIXER_DROPPED_SAMPLES 40 +#define ARIZONA_IRQ_ASYNC_CLK_ENA_LOW 41 +#define ARIZONA_IRQ_SYSCLK_ENA_LOW 42 +#define ARIZONA_IRQ_ISRC1_CFG_ERR 43 +#define ARIZONA_IRQ_ISRC2_CFG_ERR 44 +#define ARIZONA_IRQ_BOOT_DONE 45 +#define ARIZONA_IRQ_DCS_DAC_DONE 46 +#define ARIZONA_IRQ_DCS_HP_DONE 47 +#define ARIZONA_IRQ_FLL2_CLOCK_OK 48 +#define ARIZONA_IRQ_FLL1_CLOCK_OK 49 + +#define ARIZONA_NUM_IRQ 50 + +struct arizona { + struct regmap *regmap; + struct device *dev; + + enum arizona_type type; + unsigned int rev; + + int num_core_supplies; + struct regulator_bulk_data core_supplies[ARIZONA_MAX_CORE_SUPPLIES]; + struct regulator *dcvdd; + + struct arizona_pdata pdata; + + int irq; + struct irq_domain *virq; + struct regmap_irq_chip_data *aod_irq_chip; + struct regmap_irq_chip_data *irq_chip; + + struct mutex clk_lock; + int clk32k_ref; +}; + +int arizona_clk32k_enable(struct arizona *arizona); +int arizona_clk32k_disable(struct arizona *arizona); + +int arizona_request_irq(struct arizona *arizona, int irq, char *name, + irq_handler_t handler, void *data); +void arizona_free_irq(struct arizona *arizona, int irq, void *data); +int arizona_set_irq_wake(struct arizona *arizona, int irq, int on); + +int wm5102_patch(struct arizona *arizona); +int wm5110_patch(struct arizona *arizona); + +#endif diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h new file mode 100644 index 00000000000..7ab442905a5 --- /dev/null +++ b/include/linux/mfd/arizona/pdata.h @@ -0,0 +1,119 @@ +/* + * Platform data for Arizona devices + * + * Copyright 2012 Wolfson Microelectronics. PLC. + * + * 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 _ARIZONA_PDATA_H +#define _ARIZONA_PDATA_H + +#define ARIZONA_GPN_DIR 0x8000 /* GPN_DIR */ +#define ARIZONA_GPN_DIR_MASK 0x8000 /* GPN_DIR */ +#define ARIZONA_GPN_DIR_SHIFT 15 /* GPN_DIR */ +#define ARIZONA_GPN_DIR_WIDTH 1 /* GPN_DIR */ +#define ARIZONA_GPN_PU 0x4000 /* GPN_PU */ +#define ARIZONA_GPN_PU_MASK 0x4000 /* GPN_PU */ +#define ARIZONA_GPN_PU_SHIFT 14 /* GPN_PU */ +#define ARIZONA_GPN_PU_WIDTH 1 /* GPN_PU */ +#define ARIZONA_GPN_PD 0x2000 /* GPN_PD */ +#define ARIZONA_GPN_PD_MASK 0x2000 /* GPN_PD */ +#define ARIZONA_GPN_PD_SHIFT 13 /* GPN_PD */ +#define ARIZONA_GPN_PD_WIDTH 1 /* GPN_PD */ +#define ARIZONA_GPN_LVL 0x0800 /* GPN_LVL */ +#define ARIZONA_GPN_LVL_MASK 0x0800 /* GPN_LVL */ +#define ARIZONA_GPN_LVL_SHIFT 11 /* GPN_LVL */ +#define ARIZONA_GPN_LVL_WIDTH 1 /* GPN_LVL */ +#define ARIZONA_GPN_POL 0x0400 /* GPN_POL */ +#define ARIZONA_GPN_POL_MASK 0x0400 /* GPN_POL */ +#define ARIZONA_GPN_POL_SHIFT 10 /* GPN_POL */ +#define ARIZONA_GPN_POL_WIDTH 1 /* GPN_POL */ +#define ARIZONA_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */ +#define ARIZONA_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */ +#define ARIZONA_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */ +#define ARIZONA_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */ +#define ARIZONA_GPN_DB 0x0100 /* GPN_DB */ +#define ARIZONA_GPN_DB_MASK 0x0100 /* GPN_DB */ +#define ARIZONA_GPN_DB_SHIFT 8 /* GPN_DB */ +#define ARIZONA_GPN_DB_WIDTH 1 /* GPN_DB */ +#define ARIZONA_GPN_FN_MASK 0x007F /* GPN_FN - [6:0] */ +#define ARIZONA_GPN_FN_SHIFT 0 /* GPN_FN - [6:0] */ +#define ARIZONA_GPN_FN_WIDTH 7 /* GPN_FN - [6:0] */ + +#define ARIZONA_MAX_GPIO 5 + +#define ARIZONA_32KZ_MCLK1 1 +#define ARIZONA_32KZ_MCLK2 2 +#define ARIZONA_32KZ_NONE 3 + +#define ARIZONA_MAX_INPUT 4 + +#define ARIZONA_DMIC_MICVDD 0 +#define ARIZONA_DMIC_MICBIAS1 1 +#define ARIZONA_DMIC_MICBIAS2 2 +#define ARIZONA_DMIC_MICBIAS3 3 + +#define ARIZONA_INMODE_DIFF 0 +#define ARIZONA_INMODE_SE 1 +#define ARIZONA_INMODE_DMIC 2 + +#define ARIZONA_MAX_OUTPUT 6 + +#define ARIZONA_MAX_PDM_SPK 2 + +struct regulator_init_data; + +struct arizona_micd_config { + unsigned int src; + unsigned int bias; + bool gpio; +}; + +struct arizona_pdata { + int reset; /** GPIO controlling /RESET, if any */ + int ldoena; /** GPIO controlling LODENA, if any */ + + /** Regulator configuration for MICVDD */ + struct regulator_init_data *micvdd; + + /** Regulator configuration for LDO1 */ + struct regulator_init_data *ldo1; + + /** If a direct 32kHz clock is provided on an MCLK specify it here */ + int clk32k_src; + + bool irq_active_high; /** IRQ polarity */ + + /* Base GPIO */ + int gpio_base; + + /** Pin state for GPIO pins */ + int gpio_defaults[ARIZONA_MAX_GPIO]; + + /** GPIO for mic detection polarity */ + int micd_pol_gpio; + + /** Headset polarity configurations */ + struct arizona_micd_config *micd_configs; + int num_micd_configs; + + /** Reference voltage for DMIC inputs */ + int dmic_ref[ARIZONA_MAX_INPUT]; + + /** Mode of input structures */ + int inmode[ARIZONA_MAX_INPUT]; + + /** Mode for outputs */ + bool out_mono[ARIZONA_MAX_OUTPUT]; + + /** PDM speaker mute setting */ + unsigned int spk_mute[ARIZONA_MAX_PDM_SPK]; + + /** PDM speaker format */ + unsigned int spk_fmt[ARIZONA_MAX_PDM_SPK]; +}; + +#endif diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h new file mode 100644 index 00000000000..7671a287dfe --- /dev/null +++ b/include/linux/mfd/arizona/registers.h @@ -0,0 +1,6594 @@ +/* + * ARIZONA register definitions + * + * Copyright 2012 Wolfson Microelectronics plc + * + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _ARIZONA_REGISTERS_H +#define _ARIZONA_REGISTERS_H + +/* + * Register values. + */ +#define ARIZONA_SOFTWARE_RESET 0x00 +#define ARIZONA_DEVICE_REVISION 0x01 +#define ARIZONA_CTRL_IF_SPI_CFG_1 0x08 +#define ARIZONA_CTRL_IF_I2C1_CFG_1 0x09 +#define ARIZONA_CTRL_IF_I2C2_CFG_1 0x0A +#define ARIZONA_CTRL_IF_I2C1_CFG_2 0x0B +#define ARIZONA_CTRL_IF_I2C2_CFG_2 0x0C +#define ARIZONA_CTRL_IF_STATUS_1 0x0D +#define ARIZONA_WRITE_SEQUENCER_CTRL_0 0x16 +#define ARIZONA_WRITE_SEQUENCER_CTRL_1 0x17 +#define ARIZONA_WRITE_SEQUENCER_CTRL_2 0x18 +#define ARIZONA_WRITE_SEQUENCER_PROM 0x1A +#define ARIZONA_TONE_GENERATOR_1 0x20 +#define ARIZONA_TONE_GENERATOR_2 0x21 +#define ARIZONA_TONE_GENERATOR_3 0x22 +#define ARIZONA_TONE_GENERATOR_4 0x23 +#define ARIZONA_TONE_GENERATOR_5 0x24 +#define ARIZONA_PWM_DRIVE_1 0x30 +#define ARIZONA_PWM_DRIVE_2 0x31 +#define ARIZONA_PWM_DRIVE_3 0x32 +#define ARIZONA_WAKE_CONTROL 0x40 +#define ARIZONA_SEQUENCE_CONTROL 0x41 +#define ARIZONA_SAMPLE_RATE_SEQUENCE_SELECT_1 0x61 +#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_COMFORT_NOISE_GENERATOR 0x70 +#define ARIZONA_HAPTICS_CONTROL_1 0x90 +#define ARIZONA_HAPTICS_CONTROL_2 0x91 +#define ARIZONA_HAPTICS_PHASE_1_INTENSITY 0x92 +#define ARIZONA_HAPTICS_PHASE_1_DURATION 0x93 +#define ARIZONA_HAPTICS_PHASE_2_INTENSITY 0x94 +#define ARIZONA_HAPTICS_PHASE_2_DURATION 0x95 +#define ARIZONA_HAPTICS_PHASE_3_INTENSITY 0x96 +#define ARIZONA_HAPTICS_PHASE_3_DURATION 0x97 +#define ARIZONA_HAPTICS_STATUS 0x98 +#define ARIZONA_CLOCK_32K_1 0x100 +#define ARIZONA_SYSTEM_CLOCK_1 0x101 +#define ARIZONA_SAMPLE_RATE_1 0x102 +#define ARIZONA_SAMPLE_RATE_2 0x103 +#define ARIZONA_SAMPLE_RATE_3 0x104 +#define ARIZONA_SAMPLE_RATE_1_STATUS 0x10A +#define ARIZONA_SAMPLE_RATE_2_STATUS 0x10B +#define ARIZONA_SAMPLE_RATE_3_STATUS 0x10C +#define ARIZONA_ASYNC_CLOCK_1 0x112 +#define ARIZONA_ASYNC_SAMPLE_RATE_1 0x113 +#define ARIZONA_ASYNC_SAMPLE_RATE_1_STATUS 0x11B +#define ARIZONA_OUTPUT_SYSTEM_CLOCK 0x149 +#define ARIZONA_OUTPUT_ASYNC_CLOCK 0x14A +#define ARIZONA_RATE_ESTIMATOR_1 0x152 +#define ARIZONA_RATE_ESTIMATOR_2 0x153 +#define ARIZONA_RATE_ESTIMATOR_3 0x154 +#define ARIZONA_RATE_ESTIMATOR_4 0x155 +#define ARIZONA_RATE_ESTIMATOR_5 0x156 +#define ARIZONA_FLL1_CONTROL_1 0x171 +#define ARIZONA_FLL1_CONTROL_2 0x172 +#define ARIZONA_FLL1_CONTROL_3 0x173 +#define ARIZONA_FLL1_CONTROL_4 0x174 +#define ARIZONA_FLL1_CONTROL_5 0x175 +#define ARIZONA_FLL1_CONTROL_6 0x176 +#define ARIZONA_FLL1_LOOP_FILTER_TEST_1 0x177 +#define ARIZONA_FLL1_NCO_TEST_0 0x178 +#define ARIZONA_FLL1_SYNCHRONISER_1 0x181 +#define ARIZONA_FLL1_SYNCHRONISER_2 0x182 +#define ARIZONA_FLL1_SYNCHRONISER_3 0x183 +#define ARIZONA_FLL1_SYNCHRONISER_4 0x184 +#define ARIZONA_FLL1_SYNCHRONISER_5 0x185 +#define ARIZONA_FLL1_SYNCHRONISER_6 0x186 +#define ARIZONA_FLL1_SPREAD_SPECTRUM 0x189 +#define ARIZONA_FLL1_GPIO_CLOCK 0x18A +#define ARIZONA_FLL2_CONTROL_1 0x191 +#define ARIZONA_FLL2_CONTROL_2 0x192 +#define ARIZONA_FLL2_CONTROL_3 0x193 +#define ARIZONA_FLL2_CONTROL_4 0x194 +#define ARIZONA_FLL2_CONTROL_5 0x195 +#define ARIZONA_FLL2_CONTROL_6 0x196 +#define ARIZONA_FLL2_LOOP_FILTER_TEST_1 0x197 +#define ARIZONA_FLL2_NCO_TEST_0 0x198 +#define ARIZONA_FLL2_SYNCHRONISER_1 0x1A1 +#define ARIZONA_FLL2_SYNCHRONISER_2 0x1A2 +#define ARIZONA_FLL2_SYNCHRONISER_3 0x1A3 +#define ARIZONA_FLL2_SYNCHRONISER_4 0x1A4 +#define ARIZONA_FLL2_SYNCHRONISER_5 0x1A5 +#define ARIZONA_FLL2_SYNCHRONISER_6 0x1A6 +#define ARIZONA_FLL2_SPREAD_SPECTRUM 0x1A9 +#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA +#define ARIZONA_MIC_CHARGE_PUMP_1 0x200 +#define ARIZONA_LDO1_CONTROL_1 0x210 +#define ARIZONA_LDO2_CONTROL_1 0x213 +#define ARIZONA_MIC_BIAS_CTRL_1 0x218 +#define ARIZONA_MIC_BIAS_CTRL_2 0x219 +#define ARIZONA_MIC_BIAS_CTRL_3 0x21A +#define ARIZONA_ACCESSORY_DETECT_MODE_1 0x293 +#define ARIZONA_HEADPHONE_DETECT_1 0x29B +#define ARIZONA_HEADPHONE_DETECT_2 0x29C +#define ARIZONA_MIC_DETECT_1 0x2A3 +#define ARIZONA_MIC_DETECT_2 0x2A4 +#define ARIZONA_MIC_DETECT_3 0x2A5 +#define ARIZONA_MIC_NOISE_MIX_CONTROL_1 0x2C3 +#define ARIZONA_ISOLATION_CONTROL 0x2CB +#define ARIZONA_JACK_DETECT_ANALOGUE 0x2D3 +#define ARIZONA_INPUT_ENABLES 0x300 +#define ARIZONA_INPUT_ENABLES_STATUS 0x301 +#define ARIZONA_INPUT_RATE 0x308 +#define ARIZONA_INPUT_VOLUME_RAMP 0x309 +#define ARIZONA_IN1L_CONTROL 0x310 +#define ARIZONA_ADC_DIGITAL_VOLUME_1L 0x311 +#define ARIZONA_DMIC1L_CONTROL 0x312 +#define ARIZONA_IN1R_CONTROL 0x314 +#define ARIZONA_ADC_DIGITAL_VOLUME_1R 0x315 +#define ARIZONA_DMIC1R_CONTROL 0x316 +#define ARIZONA_IN2L_CONTROL 0x318 +#define ARIZONA_ADC_DIGITAL_VOLUME_2L 0x319 +#define ARIZONA_DMIC2L_CONTROL 0x31A +#define ARIZONA_IN2R_CONTROL 0x31C +#define ARIZONA_ADC_DIGITAL_VOLUME_2R 0x31D +#define ARIZONA_DMIC2R_CONTROL 0x31E +#define ARIZONA_IN3L_CONTROL 0x320 +#define ARIZONA_ADC_DIGITAL_VOLUME_3L 0x321 +#define ARIZONA_DMIC3L_CONTROL 0x322 +#define ARIZONA_IN3R_CONTROL 0x324 +#define ARIZONA_ADC_DIGITAL_VOLUME_3R 0x325 +#define ARIZONA_DMIC3R_CONTROL 0x326 +#define ARIZONA_IN4L_CONTROL 0x328 +#define ARIZONA_ADC_DIGITAL_VOLUME_4L 0x329 +#define ARIZONA_DMIC4L_CONTROL 0x32A +#define ARIZONA_ADC_DIGITAL_VOLUME_4R 0x32D +#define ARIZONA_DMIC4R_CONTROL 0x32E +#define ARIZONA_OUTPUT_ENABLES_1 0x400 +#define ARIZONA_OUTPUT_STATUS_1 0x401 +#define ARIZONA_RAW_OUTPUT_STATUS_1 0x406 +#define ARIZONA_OUTPUT_RATE_1 0x408 +#define ARIZONA_OUTPUT_VOLUME_RAMP 0x409 +#define ARIZONA_OUTPUT_PATH_CONFIG_1L 0x410 +#define ARIZONA_DAC_DIGITAL_VOLUME_1L 0x411 +#define ARIZONA_DAC_VOLUME_LIMIT_1L 0x412 +#define ARIZONA_NOISE_GATE_SELECT_1L 0x413 +#define ARIZONA_OUTPUT_PATH_CONFIG_1R 0x414 +#define ARIZONA_DAC_DIGITAL_VOLUME_1R 0x415 +#define ARIZONA_DAC_VOLUME_LIMIT_1R 0x416 +#define ARIZONA_NOISE_GATE_SELECT_1R 0x417 +#define ARIZONA_OUTPUT_PATH_CONFIG_2L 0x418 +#define ARIZONA_DAC_DIGITAL_VOLUME_2L 0x419 +#define ARIZONA_DAC_VOLUME_LIMIT_2L 0x41A +#define ARIZONA_NOISE_GATE_SELECT_2L 0x41B +#define ARIZONA_OUTPUT_PATH_CONFIG_2R 0x41C +#define ARIZONA_DAC_DIGITAL_VOLUME_2R 0x41D +#define ARIZONA_DAC_VOLUME_LIMIT_2R 0x41E +#define ARIZONA_NOISE_GATE_SELECT_2R 0x41F +#define ARIZONA_OUTPUT_PATH_CONFIG_3L 0x420 +#define ARIZONA_DAC_DIGITAL_VOLUME_3L 0x421 +#define ARIZONA_DAC_VOLUME_LIMIT_3L 0x422 +#define ARIZONA_NOISE_GATE_SELECT_3L 0x423 +#define ARIZONA_OUTPUT_PATH_CONFIG_3R 0x424 +#define ARIZONA_DAC_DIGITAL_VOLUME_3R 0x425 +#define ARIZONA_DAC_VOLUME_LIMIT_3R 0x426 +#define ARIZONA_NOISE_GATE_SELECT_3R 0x427 +#define ARIZONA_OUTPUT_PATH_CONFIG_4L 0x428 +#define ARIZONA_DAC_DIGITAL_VOLUME_4L 0x429 +#define ARIZONA_OUT_VOLUME_4L 0x42A +#define ARIZONA_NOISE_GATE_SELECT_4L 0x42B +#define ARIZONA_OUTPUT_PATH_CONFIG_4R 0x42C +#define ARIZONA_DAC_DIGITAL_VOLUME_4R 0x42D +#define ARIZONA_OUT_VOLUME_4R 0x42E +#define ARIZONA_NOISE_GATE_SELECT_4R 0x42F +#define ARIZONA_OUTPUT_PATH_CONFIG_5L 0x430 +#define ARIZONA_DAC_DIGITAL_VOLUME_5L 0x431 +#define ARIZONA_DAC_VOLUME_LIMIT_5L 0x432 +#define ARIZONA_NOISE_GATE_SELECT_5L 0x433 +#define ARIZONA_OUTPUT_PATH_CONFIG_5R 0x434 +#define ARIZONA_DAC_DIGITAL_VOLUME_5R 0x435 +#define ARIZONA_DAC_VOLUME_LIMIT_5R 0x436 +#define ARIZONA_NOISE_GATE_SELECT_5R 0x437 +#define ARIZONA_OUTPUT_PATH_CONFIG_6L 0x438 +#define ARIZONA_DAC_DIGITAL_VOLUME_6L 0x439 +#define ARIZONA_DAC_VOLUME_LIMIT_6L 0x43A +#define ARIZONA_NOISE_GATE_SELECT_6L 0x43B +#define ARIZONA_OUTPUT_PATH_CONFIG_6R 0x43C +#define ARIZONA_DAC_DIGITAL_VOLUME_6R 0x43D +#define ARIZONA_DAC_VOLUME_LIMIT_6R 0x43E +#define ARIZONA_NOISE_GATE_SELECT_6R 0x43F +#define ARIZONA_DAC_AEC_CONTROL_1 0x450 +#define ARIZONA_NOISE_GATE_CONTROL 0x458 +#define ARIZONA_PDM_SPK1_CTRL_1 0x490 +#define ARIZONA_PDM_SPK1_CTRL_2 0x491 +#define ARIZONA_PDM_SPK2_CTRL_1 0x492 +#define ARIZONA_PDM_SPK2_CTRL_2 0x493 +#define ARIZONA_DAC_COMP_1 0x4DC +#define ARIZONA_DAC_COMP_2 0x4DD +#define ARIZONA_DAC_COMP_3 0x4DE +#define ARIZONA_DAC_COMP_4 0x4DF +#define ARIZONA_AIF1_BCLK_CTRL 0x500 +#define ARIZONA_AIF1_TX_PIN_CTRL 0x501 +#define ARIZONA_AIF1_RX_PIN_CTRL 0x502 +#define ARIZONA_AIF1_RATE_CTRL 0x503 +#define ARIZONA_AIF1_FORMAT 0x504 +#define ARIZONA_AIF1_TX_BCLK_RATE 0x505 +#define ARIZONA_AIF1_RX_BCLK_RATE 0x506 +#define ARIZONA_AIF1_FRAME_CTRL_1 0x507 +#define ARIZONA_AIF1_FRAME_CTRL_2 0x508 +#define ARIZONA_AIF1_FRAME_CTRL_3 0x509 +#define ARIZONA_AIF1_FRAME_CTRL_4 0x50A +#define ARIZONA_AIF1_FRAME_CTRL_5 0x50B +#define ARIZONA_AIF1_FRAME_CTRL_6 0x50C +#define ARIZONA_AIF1_FRAME_CTRL_7 0x50D +#define ARIZONA_AIF1_FRAME_CTRL_8 0x50E +#define ARIZONA_AIF1_FRAME_CTRL_9 0x50F +#define ARIZONA_AIF1_FRAME_CTRL_10 0x510 +#define ARIZONA_AIF1_FRAME_CTRL_11 0x511 +#define ARIZONA_AIF1_FRAME_CTRL_12 0x512 +#define ARIZONA_AIF1_FRAME_CTRL_13 0x513 +#define ARIZONA_AIF1_FRAME_CTRL_14 0x514 +#define ARIZONA_AIF1_FRAME_CTRL_15 0x515 +#define ARIZONA_AIF1_FRAME_CTRL_16 0x516 +#define ARIZONA_AIF1_FRAME_CTRL_17 0x517 +#define ARIZONA_AIF1_FRAME_CTRL_18 0x518 +#define ARIZONA_AIF1_TX_ENABLES 0x519 +#define ARIZONA_AIF1_RX_ENABLES 0x51A +#define ARIZONA_AIF1_FORCE_WRITE 0x51B +#define ARIZONA_AIF2_BCLK_CTRL 0x540 +#define ARIZONA_AIF2_TX_PIN_CTRL 0x541 +#define ARIZONA_AIF2_RX_PIN_CTRL 0x542 +#define ARIZONA_AIF2_RATE_CTRL 0x543 +#define ARIZONA_AIF2_FORMAT 0x544 +#define ARIZONA_AIF2_TX_BCLK_RATE 0x545 +#define ARIZONA_AIF2_RX_BCLK_RATE 0x546 +#define ARIZONA_AIF2_FRAME_CTRL_1 0x547 +#define ARIZONA_AIF2_FRAME_CTRL_2 0x548 +#define ARIZONA_AIF2_FRAME_CTRL_3 0x549 +#define ARIZONA_AIF2_FRAME_CTRL_4 0x54A +#define ARIZONA_AIF2_FRAME_CTRL_11 0x551 +#define ARIZONA_AIF2_FRAME_CTRL_12 0x552 +#define ARIZONA_AIF2_TX_ENABLES 0x559 +#define ARIZONA_AIF2_RX_ENABLES 0x55A +#define ARIZONA_AIF2_FORCE_WRITE 0x55B +#define ARIZONA_AIF3_BCLK_CTRL 0x580 +#define ARIZONA_AIF3_TX_PIN_CTRL 0x581 +#define ARIZONA_AIF3_RX_PIN_CTRL 0x582 +#define ARIZONA_AIF3_RATE_CTRL 0x583 +#define ARIZONA_AIF3_FORMAT 0x584 +#define ARIZONA_AIF3_TX_BCLK_RATE 0x585 +#define ARIZONA_AIF3_RX_BCLK_RATE 0x586 +#define ARIZONA_AIF3_FRAME_CTRL_1 0x587 +#define ARIZONA_AIF3_FRAME_CTRL_2 0x588 +#define ARIZONA_AIF3_FRAME_CTRL_3 0x589 +#define ARIZONA_AIF3_FRAME_CTRL_4 0x58A +#define ARIZONA_AIF3_FRAME_CTRL_11 0x591 +#define ARIZONA_AIF3_FRAME_CTRL_12 0x592 +#define ARIZONA_AIF3_TX_ENABLES 0x599 +#define ARIZONA_AIF3_RX_ENABLES 0x59A +#define ARIZONA_AIF3_FORCE_WRITE 0x59B +#define ARIZONA_SLIMBUS_FRAMER_REF_GEAR 0x5E3 +#define ARIZONA_SLIMBUS_RATES_1 0x5E5 +#define ARIZONA_SLIMBUS_RATES_2 0x5E6 +#define ARIZONA_SLIMBUS_RATES_3 0x5E7 +#define ARIZONA_SLIMBUS_RATES_4 0x5E8 +#define ARIZONA_SLIMBUS_RATES_5 0x5E9 +#define ARIZONA_SLIMBUS_RATES_6 0x5EA +#define ARIZONA_SLIMBUS_RATES_7 0x5EB +#define ARIZONA_SLIMBUS_RATES_8 0x5EC +#define ARIZONA_SLIMBUS_RX_CHANNEL_ENABLE 0x5F5 +#define ARIZONA_SLIMBUS_TX_CHANNEL_ENABLE 0x5F6 +#define ARIZONA_SLIMBUS_RX_PORT_STATUS 0x5F7 +#define ARIZONA_SLIMBUS_TX_PORT_STATUS 0x5F8 +#define ARIZONA_PWM1MIX_INPUT_1_SOURCE 0x640 +#define ARIZONA_PWM1MIX_INPUT_1_VOLUME 0x641 +#define ARIZONA_PWM1MIX_INPUT_2_SOURCE 0x642 +#define ARIZONA_PWM1MIX_INPUT_2_VOLUME 0x643 +#define ARIZONA_PWM1MIX_INPUT_3_SOURCE 0x644 +#define ARIZONA_PWM1MIX_INPUT_3_VOLUME 0x645 +#define ARIZONA_PWM1MIX_INPUT_4_SOURCE 0x646 +#define ARIZONA_PWM1MIX_INPUT_4_VOLUME 0x647 +#define ARIZONA_PWM2MIX_INPUT_1_SOURCE 0x648 +#define ARIZONA_PWM2MIX_INPUT_1_VOLUME 0x649 +#define ARIZONA_PWM2MIX_INPUT_2_SOURCE 0x64A +#define ARIZONA_PWM2MIX_INPUT_2_VOLUME 0x64B +#define ARIZONA_PWM2MIX_INPUT_3_SOURCE 0x64C +#define ARIZONA_PWM2MIX_INPUT_3_VOLUME 0x64D +#define ARIZONA_PWM2MIX_INPUT_4_SOURCE 0x64E +#define ARIZONA_PWM2MIX_INPUT_4_VOLUME 0x64F +#define ARIZONA_MICMIX_INPUT_1_SOURCE 0x660 +#define ARIZONA_MICMIX_INPUT_1_VOLUME 0x661 +#define ARIZONA_MICMIX_INPUT_2_SOURCE 0x662 +#define ARIZONA_MICMIX_INPUT_2_VOLUME 0x663 +#define ARIZONA_MICMIX_INPUT_3_SOURCE 0x664 +#define ARIZONA_MICMIX_INPUT_3_VOLUME 0x665 +#define ARIZONA_MICMIX_INPUT_4_SOURCE 0x666 +#define ARIZONA_MICMIX_INPUT_4_VOLUME 0x667 +#define ARIZONA_NOISEMIX_INPUT_1_SOURCE 0x668 +#define ARIZONA_NOISEMIX_INPUT_1_VOLUME 0x669 +#define ARIZONA_NOISEMIX_INPUT_2_SOURCE 0x66A +#define ARIZONA_NOISEMIX_INPUT_2_VOLUME 0x66B +#define ARIZONA_NOISEMIX_INPUT_3_SOURCE 0x66C +#define ARIZONA_NOISEMIX_INPUT_3_VOLUME 0x66D +#define ARIZONA_NOISEMIX_INPUT_4_SOURCE 0x66E +#define ARIZONA_NOISEMIX_INPUT_4_VOLUME 0x66F +#define ARIZONA_OUT1LMIX_INPUT_1_SOURCE 0x680 +#define ARIZONA_OUT1LMIX_INPUT_1_VOLUME 0x681 +#define ARIZONA_OUT1LMIX_INPUT_2_SOURCE 0x682 +#define ARIZONA_OUT1LMIX_INPUT_2_VOLUME 0x683 +#define ARIZONA_OUT1LMIX_INPUT_3_SOURCE 0x684 +#define ARIZONA_OUT1LMIX_INPUT_3_VOLUME 0x685 +#define ARIZONA_OUT1LMIX_INPUT_4_SOURCE 0x686 +#define ARIZONA_OUT1LMIX_INPUT_4_VOLUME 0x687 +#define ARIZONA_OUT1RMIX_INPUT_1_SOURCE 0x688 +#define ARIZONA_OUT1RMIX_INPUT_1_VOLUME 0x689 +#define ARIZONA_OUT1RMIX_INPUT_2_SOURCE 0x68A +#define ARIZONA_OUT1RMIX_INPUT_2_VOLUME 0x68B +#define ARIZONA_OUT1RMIX_INPUT_3_SOURCE 0x68C +#define ARIZONA_OUT1RMIX_INPUT_3_VOLUME 0x68D +#define ARIZONA_OUT1RMIX_INPUT_4_SOURCE 0x68E +#define ARIZONA_OUT1RMIX_INPUT_4_VOLUME 0x68F +#define ARIZONA_OUT2LMIX_INPUT_1_SOURCE 0x690 +#define ARIZONA_OUT2LMIX_INPUT_1_VOLUME 0x691 +#define ARIZONA_OUT2LMIX_INPUT_2_SOURCE 0x692 +#define ARIZONA_OUT2LMIX_INPUT_2_VOLUME 0x693 +#define ARIZONA_OUT2LMIX_INPUT_3_SOURCE 0x694 +#define ARIZONA_OUT2LMIX_INPUT_3_VOLUME 0x695 +#define ARIZONA_OUT2LMIX_INPUT_4_SOURCE 0x696 +#define ARIZONA_OUT2LMIX_INPUT_4_VOLUME 0x697 +#define ARIZONA_OUT2RMIX_INPUT_1_SOURCE 0x698 +#define ARIZONA_OUT2RMIX_INPUT_1_VOLUME 0x699 +#define ARIZONA_OUT2RMIX_INPUT_2_SOURCE 0x69A +#define ARIZONA_OUT2RMIX_INPUT_2_VOLUME 0x69B +#define ARIZONA_OUT2RMIX_INPUT_3_SOURCE 0x69C +#define ARIZONA_OUT2RMIX_INPUT_3_VOLUME 0x69D +#define ARIZONA_OUT2RMIX_INPUT_4_SOURCE 0x69E +#define ARIZONA_OUT2RMIX_INPUT_4_VOLUME 0x69F +#define ARIZONA_OUT3LMIX_INPUT_1_SOURCE 0x6A0 +#define ARIZONA_OUT3LMIX_INPUT_1_VOLUME 0x6A1 +#define ARIZONA_OUT3LMIX_INPUT_2_SOURCE 0x6A2 +#define ARIZONA_OUT3LMIX_INPUT_2_VOLUME 0x6A3 +#define ARIZONA_OUT3LMIX_INPUT_3_SOURCE 0x6A4 +#define ARIZONA_OUT3LMIX_INPUT_3_VOLUME 0x6A5 +#define ARIZONA_OUT3LMIX_INPUT_4_SOURCE 0x6A6 +#define ARIZONA_OUT3LMIX_INPUT_4_VOLUME 0x6A7 +#define ARIZONA_OUT3RMIX_INPUT_1_SOURCE 0x6A8 +#define ARIZONA_OUT3RMIX_INPUT_1_VOLUME 0x6A9 +#define ARIZONA_OUT3RMIX_INPUT_2_SOURCE 0x6AA +#define ARIZONA_OUT3RMIX_INPUT_2_VOLUME 0x6AB +#define ARIZONA_OUT3RMIX_INPUT_3_SOURCE 0x6AC +#define ARIZONA_OUT3RMIX_INPUT_3_VOLUME 0x6AD +#define ARIZONA_OUT3RMIX_INPUT_4_SOURCE 0x6AE +#define ARIZONA_OUT3RMIX_INPUT_4_VOLUME 0x6AF +#define ARIZONA_OUT4LMIX_INPUT_1_SOURCE 0x6B0 +#define ARIZONA_OUT4LMIX_INPUT_1_VOLUME 0x6B1 +#define ARIZONA_OUT4LMIX_INPUT_2_SOURCE 0x6B2 +#define ARIZONA_OUT4LMIX_INPUT_2_VOLUME 0x6B3 +#define ARIZONA_OUT4LMIX_INPUT_3_SOURCE 0x6B4 +#define ARIZONA_OUT4LMIX_INPUT_3_VOLUME 0x6B5 +#define ARIZONA_OUT4LMIX_INPUT_4_SOURCE 0x6B6 +#define ARIZONA_OUT4LMIX_INPUT_4_VOLUME 0x6B7 +#define ARIZONA_OUT4RMIX_INPUT_1_SOURCE 0x6B8 +#define ARIZONA_OUT4RMIX_INPUT_1_VOLUME 0x6B9 +#define ARIZONA_OUT4RMIX_INPUT_2_SOURCE 0x6BA +#define ARIZONA_OUT4RMIX_INPUT_2_VOLUME 0x6BB +#define ARIZONA_OUT4RMIX_INPUT_3_SOURCE 0x6BC +#define ARIZONA_OUT4RMIX_INPUT_3_VOLUME 0x6BD +#define ARIZONA_OUT4RMIX_INPUT_4_SOURCE 0x6BE +#define ARIZONA_OUT4RMIX_INPUT_4_VOLUME 0x6BF +#define ARIZONA_OUT5LMIX_INPUT_1_SOURCE 0x6C0 +#define ARIZONA_OUT5LMIX_INPUT_1_VOLUME 0x6C1 +#define ARIZONA_OUT5LMIX_INPUT_2_SOURCE 0x6C2 +#define ARIZONA_OUT5LMIX_INPUT_2_VOLUME 0x6C3 +#define ARIZONA_OUT5LMIX_INPUT_3_SOURCE 0x6C4 +#define ARIZONA_OUT5LMIX_INPUT_3_VOLUME 0x6C5 +#define ARIZONA_OUT5LMIX_INPUT_4_SOURCE 0x6C6 +#define ARIZONA_OUT5LMIX_INPUT_4_VOLUME 0x6C7 +#define ARIZONA_OUT5RMIX_INPUT_1_SOURCE 0x6C8 +#define ARIZONA_OUT5RMIX_INPUT_1_VOLUME 0x6C9 +#define ARIZONA_OUT5RMIX_INPUT_2_SOURCE 0x6CA +#define ARIZONA_OUT5RMIX_INPUT_2_VOLUME 0x6CB +#define ARIZONA_OUT5RMIX_INPUT_3_SOURCE 0x6CC +#define ARIZONA_OUT5RMIX_INPUT_3_VOLUME 0x6CD +#define ARIZONA_OUT5RMIX_INPUT_4_SOURCE 0x6CE +#define ARIZONA_OUT5RMIX_INPUT_4_VOLUME 0x6CF +#define ARIZONA_OUT6LMIX_INPUT_1_SOURCE 0x6D0 +#define ARIZONA_OUT6LMIX_INPUT_1_VOLUME 0x6D1 +#define ARIZONA_OUT6LMIX_INPUT_2_SOURCE 0x6D2 +#define ARIZONA_OUT6LMIX_INPUT_2_VOLUME 0x6D3 +#define ARIZONA_OUT6LMIX_INPUT_3_SOURCE 0x6D4 +#define ARIZONA_OUT6LMIX_INPUT_3_VOLUME 0x6D5 +#define ARIZONA_OUT6LMIX_INPUT_4_SOURCE 0x6D6 +#define ARIZONA_OUT6LMIX_INPUT_4_VOLUME 0x6D7 +#define ARIZONA_OUT6RMIX_INPUT_1_SOURCE 0x6D8 +#define ARIZONA_OUT6RMIX_INPUT_1_VOLUME 0x6D9 +#define ARIZONA_OUT6RMIX_INPUT_2_SOURCE 0x6DA +#define ARIZONA_OUT6RMIX_INPUT_2_VOLUME 0x6DB +#define ARIZONA_OUT6RMIX_INPUT_3_SOURCE 0x6DC +#define ARIZONA_OUT6RMIX_INPUT_3_VOLUME 0x6DD +#define ARIZONA_OUT6RMIX_INPUT_4_SOURCE 0x6DE +#define ARIZONA_OUT6RMIX_INPUT_4_VOLUME 0x6DF +#define ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE 0x700 +#define ARIZONA_AIF1TX1MIX_INPUT_1_VOLUME 0x701 +#define ARIZONA_AIF1TX1MIX_INPUT_2_SOURCE 0x702 +#define ARIZONA_AIF1TX1MIX_INPUT_2_VOLUME 0x703 +#define ARIZONA_AIF1TX1MIX_INPUT_3_SOURCE 0x704 +#define ARIZONA_AIF1TX1MIX_INPUT_3_VOLUME 0x705 +#define ARIZONA_AIF1TX1MIX_INPUT_4_SOURCE 0x706 +#define ARIZONA_AIF1TX1MIX_INPUT_4_VOLUME 0x707 +#define ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE 0x708 +#define ARIZONA_AIF1TX2MIX_INPUT_1_VOLUME 0x709 +#define ARIZONA_AIF1TX2MIX_INPUT_2_SOURCE 0x70A +#define ARIZONA_AIF1TX2MIX_INPUT_2_VOLUME 0x70B +#define ARIZONA_AIF1TX2MIX_INPUT_3_SOURCE 0x70C +#define ARIZONA_AIF1TX2MIX_INPUT_3_VOLUME 0x70D +#define ARIZONA_AIF1TX2MIX_INPUT_4_SOURCE 0x70E +#define ARIZONA_AIF1TX2MIX_INPUT_4_VOLUME 0x70F +#define ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE 0x710 +#define ARIZONA_AIF1TX3MIX_INPUT_1_VOLUME 0x711 +#define ARIZONA_AIF1TX3MIX_INPUT_2_SOURCE 0x712 +#define ARIZONA_AIF1TX3MIX_INPUT_2_VOLUME 0x713 +#define ARIZONA_AIF1TX3MIX_INPUT_3_SOURCE 0x714 +#define ARIZONA_AIF1TX3MIX_INPUT_3_VOLUME 0x715 +#define ARIZONA_AIF1TX3MIX_INPUT_4_SOURCE 0x716 +#define ARIZONA_AIF1TX3MIX_INPUT_4_VOLUME 0x717 +#define ARIZONA_AIF1TX4MIX_INPUT_1_SOURCE 0x718 +#define ARIZONA_AIF1TX4MIX_INPUT_1_VOLUME 0x719 +#define ARIZONA_AIF1TX4MIX_INPUT_2_SOURCE 0x71A +#define ARIZONA_AIF1TX4MIX_INPUT_2_VOLUME 0x71B +#define ARIZONA_AIF1TX4MIX_INPUT_3_SOURCE 0x71C +#define ARIZONA_AIF1TX4MIX_INPUT_3_VOLUME 0x71D +#define ARIZONA_AIF1TX4MIX_INPUT_4_SOURCE 0x71E +#define ARIZONA_AIF1TX4MIX_INPUT_4_VOLUME 0x71F +#define ARIZONA_AIF1TX5MIX_INPUT_1_SOURCE 0x720 +#define ARIZONA_AIF1TX5MIX_INPUT_1_VOLUME 0x721 +#define ARIZONA_AIF1TX5MIX_INPUT_2_SOURCE 0x722 +#define ARIZONA_AIF1TX5MIX_INPUT_2_VOLUME 0x723 +#define ARIZONA_AIF1TX5MIX_INPUT_3_SOURCE 0x724 +#define ARIZONA_AIF1TX5MIX_INPUT_3_VOLUME 0x725 +#define ARIZONA_AIF1TX5MIX_INPUT_4_SOURCE 0x726 +#define ARIZONA_AIF1TX5MIX_INPUT_4_VOLUME 0x727 +#define ARIZONA_AIF1TX6MIX_INPUT_1_SOURCE 0x728 +#define ARIZONA_AIF1TX6MIX_INPUT_1_VOLUME 0x729 +#define ARIZONA_AIF1TX6MIX_INPUT_2_SOURCE 0x72A +#define ARIZONA_AIF1TX6MIX_INPUT_2_VOLUME 0x72B +#define ARIZONA_AIF1TX6MIX_INPUT_3_SOURCE 0x72C +#define ARIZONA_AIF1TX6MIX_INPUT_3_VOLUME 0x72D +#define ARIZONA_AIF1TX6MIX_INPUT_4_SOURCE 0x72E +#define ARIZONA_AIF1TX6MIX_INPUT_4_VOLUME 0x72F +#define ARIZONA_AIF1TX7MIX_INPUT_1_SOURCE 0x730 +#define ARIZONA_AIF1TX7MIX_INPUT_1_VOLUME 0x731 +#define ARIZONA_AIF1TX7MIX_INPUT_2_SOURCE 0x732 +#define ARIZONA_AIF1TX7MIX_INPUT_2_VOLUME 0x733 +#define ARIZONA_AIF1TX7MIX_INPUT_3_SOURCE 0x734 +#define ARIZONA_AIF1TX7MIX_INPUT_3_VOLUME 0x735 +#define ARIZONA_AIF1TX7MIX_INPUT_4_SOURCE 0x736 +#define ARIZONA_AIF1TX7MIX_INPUT_4_VOLUME 0x737 +#define ARIZONA_AIF1TX8MIX_INPUT_1_SOURCE 0x738 +#define ARIZONA_AIF1TX8MIX_INPUT_1_VOLUME 0x739 +#define ARIZONA_AIF1TX8MIX_INPUT_2_SOURCE 0x73A +#define ARIZONA_AIF1TX8MIX_INPUT_2_VOLUME 0x73B +#define ARIZONA_AIF1TX8MIX_INPUT_3_SOURCE 0x73C +#define ARIZONA_AIF1TX8MIX_INPUT_3_VOLUME 0x73D +#define ARIZONA_AIF1TX8MIX_INPUT_4_SOURCE 0x73E +#define ARIZONA_AIF1TX8MIX_INPUT_4_VOLUME 0x73F +#define ARIZONA_AIF2TX1MIX_INPUT_1_SOURCE 0x740 +#define ARIZONA_AIF2TX1MIX_INPUT_1_VOLUME 0x741 +#define ARIZONA_AIF2TX1MIX_INPUT_2_SOURCE 0x742 +#define ARIZONA_AIF2TX1MIX_INPUT_2_VOLUME 0x743 +#define ARIZONA_AIF2TX1MIX_INPUT_3_SOURCE 0x744 +#define ARIZONA_AIF2TX1MIX_INPUT_3_VOLUME 0x745 +#define ARIZONA_AIF2TX1MIX_INPUT_4_SOURCE 0x746 +#define ARIZONA_AIF2TX1MIX_INPUT_4_VOLUME 0x747 +#define ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE 0x748 +#define ARIZONA_AIF2TX2MIX_INPUT_1_VOLUME 0x749 +#define ARIZONA_AIF2TX2MIX_INPUT_2_SOURCE 0x74A +#define ARIZONA_AIF2TX2MIX_INPUT_2_VOLUME 0x74B +#define ARIZONA_AIF2TX2MIX_INPUT_3_SOURCE 0x74C +#define ARIZONA_AIF2TX2MIX_INPUT_3_VOLUME 0x74D +#define ARIZONA_AIF2TX2MIX_INPUT_4_SOURCE 0x74E +#define ARIZONA_AIF2TX2MIX_INPUT_4_VOLUME 0x74F +#define ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE 0x780 +#define ARIZONA_AIF3TX1MIX_INPUT_1_VOLUME 0x781 +#define ARIZONA_AIF3TX1MIX_INPUT_2_SOURCE 0x782 +#define ARIZONA_AIF3TX1MIX_INPUT_2_VOLUME 0x783 +#define ARIZONA_AIF3TX1MIX_INPUT_3_SOURCE 0x784 +#define ARIZONA_AIF3TX1MIX_INPUT_3_VOLUME 0x785 +#define ARIZONA_AIF3TX1MIX_INPUT_4_SOURCE 0x786 +#define ARIZONA_AIF3TX1MIX_INPUT_4_VOLUME 0x787 +#define ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE 0x788 +#define ARIZONA_AIF3TX2MIX_INPUT_1_VOLUME 0x789 +#define ARIZONA_AIF3TX2MIX_INPUT_2_SOURCE 0x78A +#define ARIZONA_AIF3TX2MIX_INPUT_2_VOLUME 0x78B +#define ARIZONA_AIF3TX2MIX_INPUT_3_SOURCE 0x78C +#define ARIZONA_AIF3TX2MIX_INPUT_3_VOLUME 0x78D +#define ARIZONA_AIF3TX2MIX_INPUT_4_SOURCE 0x78E +#define ARIZONA_AIF3TX2MIX_INPUT_4_VOLUME 0x78F +#define ARIZONA_SLIMTX1MIX_INPUT_1_SOURCE 0x7C0 +#define ARIZONA_SLIMTX1MIX_INPUT_1_VOLUME 0x7C1 +#define ARIZONA_SLIMTX1MIX_INPUT_2_SOURCE 0x7C2 +#define ARIZONA_SLIMTX1MIX_INPUT_2_VOLUME 0x7C3 +#define ARIZONA_SLIMTX1MIX_INPUT_3_SOURCE 0x7C4 +#define ARIZONA_SLIMTX1MIX_INPUT_3_VOLUME 0x7C5 +#define ARIZONA_SLIMTX1MIX_INPUT_4_SOURCE 0x7C6 +#define ARIZONA_SLIMTX1MIX_INPUT_4_VOLUME 0x7C7 +#define ARIZONA_SLIMTX2MIX_INPUT_1_SOURCE 0x7C8 +#define ARIZONA_SLIMTX2MIX_INPUT_1_VOLUME 0x7C9 +#define ARIZONA_SLIMTX2MIX_INPUT_2_SOURCE 0x7CA +#define ARIZONA_SLIMTX2MIX_INPUT_2_VOLUME 0x7CB +#define ARIZONA_SLIMTX2MIX_INPUT_3_SOURCE 0x7CC +#define ARIZONA_SLIMTX2MIX_INPUT_3_VOLUME 0x7CD +#define ARIZONA_SLIMTX2MIX_INPUT_4_SOURCE 0x7CE +#define ARIZONA_SLIMTX2MIX_INPUT_4_VOLUME 0x7CF +#define ARIZONA_SLIMTX3MIX_INPUT_1_SOURCE 0x7D0 +#define ARIZONA_SLIMTX3MIX_INPUT_1_VOLUME 0x7D1 +#define ARIZONA_SLIMTX3MIX_INPUT_2_SOURCE 0x7D2 +#define ARIZONA_SLIMTX3MIX_INPUT_2_VOLUME 0x7D3 +#define ARIZONA_SLIMTX3MIX_INPUT_3_SOURCE 0x7D4 +#define ARIZONA_SLIMTX3MIX_INPUT_3_VOLUME 0x7D5 +#define ARIZONA_SLIMTX3MIX_INPUT_4_SOURCE 0x7D6 +#define ARIZONA_SLIMTX3MIX_INPUT_4_VOLUME 0x7D7 +#define ARIZONA_SLIMTX4MIX_INPUT_1_SOURCE 0x7D8 +#define ARIZONA_SLIMTX4MIX_INPUT_1_VOLUME 0x7D9 +#define ARIZONA_SLIMTX4MIX_INPUT_2_SOURCE 0x7DA +#define ARIZONA_SLIMTX4MIX_INPUT_2_VOLUME 0x7DB +#define ARIZONA_SLIMTX4MIX_INPUT_3_SOURCE 0x7DC +#define ARIZONA_SLIMTX4MIX_INPUT_3_VOLUME 0x7DD +#define ARIZONA_SLIMTX4MIX_INPUT_4_SOURCE 0x7DE +#define ARIZONA_SLIMTX4MIX_INPUT_4_VOLUME 0x7DF +#define ARIZONA_SLIMTX5MIX_INPUT_1_SOURCE 0x7E0 +#define ARIZONA_SLIMTX5MIX_INPUT_1_VOLUME 0x7E1 +#define ARIZONA_SLIMTX5MIX_INPUT_2_SOURCE 0x7E2 +#define ARIZONA_SLIMTX5MIX_INPUT_2_VOLUME 0x7E3 +#define ARIZONA_SLIMTX5MIX_INPUT_3_SOURCE 0x7E4 +#define ARIZONA_SLIMTX5MIX_INPUT_3_VOLUME 0x7E5 +#define ARIZONA_SLIMTX5MIX_INPUT_4_SOURCE 0x7E6 +#define ARIZONA_SLIMTX5MIX_INPUT_4_VOLUME 0x7E7 +#define ARIZONA_SLIMTX6MIX_INPUT_1_SOURCE 0x7E8 +#define ARIZONA_SLIMTX6MIX_INPUT_1_VOLUME 0x7E9 +#define ARIZONA_SLIMTX6MIX_INPUT_2_SOURCE 0x7EA +#define ARIZONA_SLIMTX6MIX_INPUT_2_VOLUME 0x7EB +#define ARIZONA_SLIMTX6MIX_INPUT_3_SOURCE 0x7EC +#define ARIZONA_SLIMTX6MIX_INPUT_3_VOLUME 0x7ED +#define ARIZONA_SLIMTX6MIX_INPUT_4_SOURCE 0x7EE +#define ARIZONA_SLIMTX6MIX_INPUT_4_VOLUME 0x7EF +#define ARIZONA_SLIMTX7MIX_INPUT_1_SOURCE 0x7F0 +#define ARIZONA_SLIMTX7MIX_INPUT_1_VOLUME 0x7F1 +#define ARIZONA_SLIMTX7MIX_INPUT_2_SOURCE 0x7F2 +#define ARIZONA_SLIMTX7MIX_INPUT_2_VOLUME 0x7F3 +#define ARIZONA_SLIMTX7MIX_INPUT_3_SOURCE 0x7F4 +#define ARIZONA_SLIMTX7MIX_INPUT_3_VOLUME 0x7F5 +#define ARIZONA_SLIMTX7MIX_INPUT_4_SOURCE 0x7F6 +#define ARIZONA_SLIMTX7MIX_INPUT_4_VOLUME 0x7F7 +#define ARIZONA_SLIMTX8MIX_INPUT_1_SOURCE 0x7F8 +#define ARIZONA_SLIMTX8MIX_INPUT_1_VOLUME 0x7F9 +#define ARIZONA_SLIMTX8MIX_INPUT_2_SOURCE 0x7FA +#define ARIZONA_SLIMTX8MIX_INPUT_2_VOLUME 0x7FB +#define ARIZONA_SLIMTX8MIX_INPUT_3_SOURCE 0x7FC +#define ARIZONA_SLIMTX8MIX_INPUT_3_VOLUME 0x7FD +#define ARIZONA_SLIMTX8MIX_INPUT_4_SOURCE 0x7FE +#define ARIZONA_SLIMTX8MIX_INPUT_4_VOLUME 0x7FF +#define ARIZONA_EQ1MIX_INPUT_1_SOURCE 0x880 +#define ARIZONA_EQ1MIX_INPUT_1_VOLUME 0x881 +#define ARIZONA_EQ1MIX_INPUT_2_SOURCE 0x882 +#define ARIZONA_EQ1MIX_INPUT_2_VOLUME 0x883 +#define ARIZONA_EQ1MIX_INPUT_3_SOURCE 0x884 +#define ARIZONA_EQ1MIX_INPUT_3_VOLUME 0x885 +#define ARIZONA_EQ1MIX_INPUT_4_SOURCE 0x886 +#define ARIZONA_EQ1MIX_INPUT_4_VOLUME 0x887 +#define ARIZONA_EQ2MIX_INPUT_1_SOURCE 0x888 +#define ARIZONA_EQ2MIX_INPUT_1_VOLUME 0x889 +#define ARIZONA_EQ2MIX_INPUT_2_SOURCE 0x88A +#define ARIZONA_EQ2MIX_INPUT_2_VOLUME 0x88B +#define ARIZONA_EQ2MIX_INPUT_3_SOURCE 0x88C +#define ARIZONA_EQ2MIX_INPUT_3_VOLUME 0x88D +#define ARIZONA_EQ2MIX_INPUT_4_SOURCE 0x88E +#define ARIZONA_EQ2MIX_INPUT_4_VOLUME 0x88F +#define ARIZONA_EQ3MIX_INPUT_1_SOURCE 0x890 +#define ARIZONA_EQ3MIX_INPUT_1_VOLUME 0x891 +#define ARIZONA_EQ3MIX_INPUT_2_SOURCE 0x892 +#define ARIZONA_EQ3MIX_INPUT_2_VOLUME 0x893 +#define ARIZONA_EQ3MIX_INPUT_3_SOURCE 0x894 +#define ARIZONA_EQ3MIX_INPUT_3_VOLUME 0x895 +#define ARIZONA_EQ3MIX_INPUT_4_SOURCE 0x896 +#define ARIZONA_EQ3MIX_INPUT_4_VOLUME 0x897 +#define ARIZONA_EQ4MIX_INPUT_1_SOURCE 0x898 +#define ARIZONA_EQ4MIX_INPUT_1_VOLUME 0x899 +#define ARIZONA_EQ4MIX_INPUT_2_SOURCE 0x89A +#define ARIZONA_EQ4MIX_INPUT_2_VOLUME 0x89B +#define ARIZONA_EQ4MIX_INPUT_3_SOURCE 0x89C +#define ARIZONA_EQ4MIX_INPUT_3_VOLUME 0x89D +#define ARIZONA_EQ4MIX_INPUT_4_SOURCE 0x89E +#define ARIZONA_EQ4MIX_INPUT_4_VOLUME 0x89F +#define ARIZONA_DRC1LMIX_INPUT_1_SOURCE 0x8C0 +#define ARIZONA_DRC1LMIX_INPUT_1_VOLUME 0x8C1 +#define ARIZONA_DRC1LMIX_INPUT_2_SOURCE 0x8C2 +#define ARIZONA_DRC1LMIX_INPUT_2_VOLUME 0x8C3 +#define ARIZONA_DRC1LMIX_INPUT_3_SOURCE 0x8C4 +#define ARIZONA_DRC1LMIX_INPUT_3_VOLUME 0x8C5 +#define ARIZONA_DRC1LMIX_INPUT_4_SOURCE 0x8C6 +#define ARIZONA_DRC1LMIX_INPUT_4_VOLUME 0x8C7 +#define ARIZONA_DRC1RMIX_INPUT_1_SOURCE 0x8C8 +#define ARIZONA_DRC1RMIX_INPUT_1_VOLUME 0x8C9 +#define ARIZONA_DRC1RMIX_INPUT_2_SOURCE 0x8CA +#define ARIZONA_DRC1RMIX_INPUT_2_VOLUME 0x8CB +#define ARIZONA_DRC1RMIX_INPUT_3_SOURCE 0x8CC +#define ARIZONA_DRC1RMIX_INPUT_3_VOLUME 0x8CD +#define ARIZONA_DRC1RMIX_INPUT_4_SOURCE 0x8CE +#define ARIZONA_DRC1RMIX_INPUT_4_VOLUME 0x8CF +#define ARIZONA_DRC2LMIX_INPUT_1_SOURCE 0x8D0 +#define ARIZONA_DRC2LMIX_INPUT_1_VOLUME 0x8D1 +#define ARIZONA_DRC2LMIX_INPUT_2_SOURCE 0x8D2 +#define ARIZONA_DRC2LMIX_INPUT_2_VOLUME 0x8D3 +#define ARIZONA_DRC2LMIX_INPUT_3_SOURCE 0x8D4 +#define ARIZONA_DRC2LMIX_INPUT_3_VOLUME 0x8D5 +#define ARIZONA_DRC2LMIX_INPUT_4_SOURCE 0x8D6 +#define ARIZONA_DRC2LMIX_INPUT_4_VOLUME 0x8D7 +#define ARIZONA_DRC2RMIX_INPUT_1_SOURCE 0x8D8 +#define ARIZONA_DRC2RMIX_INPUT_1_VOLUME 0x8D9 +#define ARIZONA_DRC2RMIX_INPUT_2_SOURCE 0x8DA +#define ARIZONA_DRC2RMIX_INPUT_2_VOLUME 0x8DB +#define ARIZONA_DRC2RMIX_INPUT_3_SOURCE 0x8DC +#define ARIZONA_DRC2RMIX_INPUT_3_VOLUME 0x8DD +#define ARIZONA_DRC2RMIX_INPUT_4_SOURCE 0x8DE +#define ARIZONA_DRC2RMIX_INPUT_4_VOLUME 0x8DF +#define ARIZONA_HPLP1MIX_INPUT_1_SOURCE 0x900 +#define ARIZONA_HPLP1MIX_INPUT_1_VOLUME 0x901 +#define ARIZONA_HPLP1MIX_INPUT_2_SOURCE 0x902 +#define ARIZONA_HPLP1MIX_INPUT_2_VOLUME 0x903 +#define ARIZONA_HPLP1MIX_INPUT_3_SOURCE 0x904 +#define ARIZONA_HPLP1MIX_INPUT_3_VOLUME 0x905 +#define ARIZONA_HPLP1MIX_INPUT_4_SOURCE 0x906 +#define ARIZONA_HPLP1MIX_INPUT_4_VOLUME 0x907 +#define ARIZONA_HPLP2MIX_INPUT_1_SOURCE 0x908 +#define ARIZONA_HPLP2MIX_INPUT_1_VOLUME 0x909 +#define ARIZONA_HPLP2MIX_INPUT_2_SOURCE 0x90A +#define ARIZONA_HPLP2MIX_INPUT_2_VOLUME 0x90B +#define ARIZONA_HPLP2MIX_INPUT_3_SOURCE 0x90C +#define ARIZONA_HPLP2MIX_INPUT_3_VOLUME 0x90D +#define ARIZONA_HPLP2MIX_INPUT_4_SOURCE 0x90E +#define ARIZONA_HPLP2MIX_INPUT_4_VOLUME 0x90F +#define ARIZONA_HPLP3MIX_INPUT_1_SOURCE 0x910 +#define ARIZONA_HPLP3MIX_INPUT_1_VOLUME 0x911 +#define ARIZONA_HPLP3MIX_INPUT_2_SOURCE 0x912 +#define ARIZONA_HPLP3MIX_INPUT_2_VOLUME 0x913 +#define ARIZONA_HPLP3MIX_INPUT_3_SOURCE 0x914 +#define ARIZONA_HPLP3MIX_INPUT_3_VOLUME 0x915 +#define ARIZONA_HPLP3MIX_INPUT_4_SOURCE 0x916 +#define ARIZONA_HPLP3MIX_INPUT_4_VOLUME 0x917 +#define ARIZONA_HPLP4MIX_INPUT_1_SOURCE 0x918 +#define ARIZONA_HPLP4MIX_INPUT_1_VOLUME 0x919 +#define ARIZONA_HPLP4MIX_INPUT_2_SOURCE 0x91A +#define ARIZONA_HPLP4MIX_INPUT_2_VOLUME 0x91B +#define ARIZONA_HPLP4MIX_INPUT_3_SOURCE 0x91C +#define ARIZONA_HPLP4MIX_INPUT_3_VOLUME 0x91D +#define ARIZONA_HPLP4MIX_INPUT_4_SOURCE 0x91E +#define ARIZONA_HPLP4MIX_INPUT_4_VOLUME 0x91F +#define ARIZONA_DSP1LMIX_INPUT_1_SOURCE 0x940 +#define ARIZONA_DSP1LMIX_INPUT_1_VOLUME 0x941 +#define ARIZONA_DSP1LMIX_INPUT_2_SOURCE 0x942 +#define ARIZONA_DSP1LMIX_INPUT_2_VOLUME 0x943 +#define ARIZONA_DSP1LMIX_INPUT_3_SOURCE 0x944 +#define ARIZONA_DSP1LMIX_INPUT_3_VOLUME 0x945 +#define ARIZONA_DSP1LMIX_INPUT_4_SOURCE 0x946 +#define ARIZONA_DSP1LMIX_INPUT_4_VOLUME 0x947 +#define ARIZONA_DSP1RMIX_INPUT_1_SOURCE 0x948 +#define ARIZONA_DSP1RMIX_INPUT_1_VOLUME 0x949 +#define ARIZONA_DSP1RMIX_INPUT_2_SOURCE 0x94A +#define ARIZONA_DSP1RMIX_INPUT_2_VOLUME 0x94B +#define ARIZONA_DSP1RMIX_INPUT_3_SOURCE 0x94C +#define ARIZONA_DSP1RMIX_INPUT_3_VOLUME 0x94D +#define ARIZONA_DSP1RMIX_INPUT_4_SOURCE 0x94E +#define ARIZONA_DSP1RMIX_INPUT_4_VOLUME 0x94F +#define ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE 0x950 +#define ARIZONA_DSP1AUX2MIX_INPUT_1_SOURCE 0x958 +#define ARIZONA_DSP1AUX3MIX_INPUT_1_SOURCE 0x960 +#define ARIZONA_DSP1AUX4MIX_INPUT_1_SOURCE 0x968 +#define ARIZONA_DSP1AUX5MIX_INPUT_1_SOURCE 0x970 +#define ARIZONA_DSP1AUX6MIX_INPUT_1_SOURCE 0x978 +#define ARIZONA_DSP2LMIX_INPUT_1_SOURCE 0x980 +#define ARIZONA_DSP2LMIX_INPUT_1_VOLUME 0x981 +#define ARIZONA_DSP2LMIX_INPUT_2_SOURCE 0x982 +#define ARIZONA_DSP2LMIX_INPUT_2_VOLUME 0x983 +#define ARIZONA_DSP2LMIX_INPUT_3_SOURCE 0x984 +#define ARIZONA_DSP2LMIX_INPUT_3_VOLUME 0x985 +#define ARIZONA_DSP2LMIX_INPUT_4_SOURCE 0x986 +#define ARIZONA_DSP2LMIX_INPUT_4_VOLUME 0x987 +#define ARIZONA_DSP2RMIX_INPUT_1_SOURCE 0x988 +#define ARIZONA_DSP2RMIX_INPUT_1_VOLUME 0x989 +#define ARIZONA_DSP2RMIX_INPUT_2_SOURCE 0x98A +#define ARIZONA_DSP2RMIX_INPUT_2_VOLUME 0x98B +#define ARIZONA_DSP2RMIX_INPUT_3_SOURCE 0x98C +#define ARIZONA_DSP2RMIX_INPUT_3_VOLUME 0x98D +#define ARIZONA_DSP2RMIX_INPUT_4_SOURCE 0x98E +#define ARIZONA_DSP2RMIX_INPUT_4_VOLUME 0x98F +#define ARIZONA_DSP2AUX1MIX_INPUT_1_SOURCE 0x990 +#define ARIZONA_DSP2AUX2MIX_INPUT_1_SOURCE 0x998 +#define ARIZONA_DSP2AUX3MIX_INPUT_1_SOURCE 0x9A0 +#define ARIZONA_DSP2AUX4MIX_INPUT_1_SOURCE 0x9A8 +#define ARIZONA_DSP2AUX5MIX_INPUT_1_SOURCE 0x9B0 +#define ARIZONA_DSP2AUX6MIX_INPUT_1_SOURCE 0x9B8 +#define ARIZONA_DSP3LMIX_INPUT_1_SOURCE 0x9C0 +#define ARIZONA_DSP3LMIX_INPUT_1_VOLUME 0x9C1 +#define ARIZONA_DSP3LMIX_INPUT_2_SOURCE 0x9C2 +#define ARIZONA_DSP3LMIX_INPUT_2_VOLUME 0x9C3 +#define ARIZONA_DSP3LMIX_INPUT_3_SOURCE 0x9C4 +#define ARIZONA_DSP3LMIX_INPUT_3_VOLUME 0x9C5 +#define ARIZONA_DSP3LMIX_INPUT_4_SOURCE 0x9C6 +#define ARIZONA_DSP3LMIX_INPUT_4_VOLUME 0x9C7 +#define ARIZONA_DSP3RMIX_INPUT_1_SOURCE 0x9C8 +#define ARIZONA_DSP3RMIX_INPUT_1_VOLUME 0x9C9 +#define ARIZONA_DSP3RMIX_INPUT_2_SOURCE 0x9CA +#define ARIZONA_DSP3RMIX_INPUT_2_VOLUME 0x9CB +#define ARIZONA_DSP3RMIX_INPUT_3_SOURCE 0x9CC +#define ARIZONA_DSP3RMIX_INPUT_3_VOLUME 0x9CD +#define ARIZONA_DSP3RMIX_INPUT_4_SOURCE 0x9CE +#define ARIZONA_DSP3RMIX_INPUT_4_VOLUME 0x9CF +#define ARIZONA_DSP3AUX1MIX_INPUT_1_SOURCE 0x9D0 +#define ARIZONA_DSP3AUX2MIX_INPUT_1_SOURCE 0x9D8 +#define ARIZONA_DSP3AUX3MIX_INPUT_1_SOURCE 0x9E0 +#define ARIZONA_DSP3AUX4MIX_INPUT_1_SOURCE 0x9E8 +#define ARIZONA_DSP3AUX5MIX_INPUT_1_SOURCE 0x9F0 +#define ARIZONA_DSP3AUX6MIX_INPUT_1_SOURCE 0x9F8 +#define ARIZONA_DSP4LMIX_INPUT_1_SOURCE 0xA00 +#define ARIZONA_DSP4LMIX_INPUT_1_VOLUME 0xA01 +#define ARIZONA_DSP4LMIX_INPUT_2_SOURCE 0xA02 +#define ARIZONA_DSP4LMIX_INPUT_2_VOLUME 0xA03 +#define ARIZONA_DSP4LMIX_INPUT_3_SOURCE 0xA04 +#define ARIZONA_DSP4LMIX_INPUT_3_VOLUME 0xA05 +#define ARIZONA_DSP4LMIX_INPUT_4_SOURCE 0xA06 +#define ARIZONA_DSP4LMIX_INPUT_4_VOLUME 0xA07 +#define ARIZONA_DSP4RMIX_INPUT_1_SOURCE 0xA08 +#define ARIZONA_DSP4RMIX_INPUT_1_VOLUME 0xA09 +#define ARIZONA_DSP4RMIX_INPUT_2_SOURCE 0xA0A +#define ARIZONA_DSP4RMIX_INPUT_2_VOLUME 0xA0B +#define ARIZONA_DSP4RMIX_INPUT_3_SOURCE 0xA0C +#define ARIZONA_DSP4RMIX_INPUT_3_VOLUME 0xA0D +#define ARIZONA_DSP4RMIX_INPUT_4_SOURCE 0xA0E +#define ARIZONA_DSP4RMIX_INPUT_4_VOLUME 0xA0F +#define ARIZONA_DSP4AUX1MIX_INPUT_1_SOURCE 0xA10 +#define ARIZONA_DSP4AUX2MIX_INPUT_1_SOURCE 0xA18 +#define ARIZONA_DSP4AUX3MIX_INPUT_1_SOURCE 0xA20 +#define ARIZONA_DSP4AUX4MIX_INPUT_1_SOURCE 0xA28 +#define ARIZONA_DSP4AUX5MIX_INPUT_1_SOURCE 0xA30 +#define ARIZONA_DSP4AUX6MIX_INPUT_1_SOURCE 0xA38 +#define ARIZONA_ASRC1LMIX_INPUT_1_SOURCE 0xA80 +#define ARIZONA_ASRC1RMIX_INPUT_1_SOURCE 0xA88 +#define ARIZONA_ASRC2LMIX_INPUT_1_SOURCE 0xA90 +#define ARIZONA_ASRC2RMIX_INPUT_1_SOURCE 0xA98 +#define ARIZONA_ISRC1DEC1MIX_INPUT_1_SOURCE 0xB00 +#define ARIZONA_ISRC1DEC2MIX_INPUT_1_SOURCE 0xB08 +#define ARIZONA_ISRC1DEC3MIX_INPUT_1_SOURCE 0xB10 +#define ARIZONA_ISRC1DEC4MIX_INPUT_1_SOURCE 0xB18 +#define ARIZONA_ISRC1INT1MIX_INPUT_1_SOURCE 0xB20 +#define ARIZONA_ISRC1INT2MIX_INPUT_1_SOURCE 0xB28 +#define ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 +#define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 +#define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 +#define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 +#define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 +#define ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 +#define ARIZONA_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30 +#define ARIZONA_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38 +#define ARIZONA_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40 +#define ARIZONA_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48 +#define ARIZONA_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50 +#define ARIZONA_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58 +#define ARIZONA_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60 +#define ARIZONA_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68 +#define ARIZONA_ISRC2INT3MIX_INPUT_1_SOURCE 0xB70 +#define ARIZONA_ISRC2INT4MIX_INPUT_1_SOURCE 0xB78 +#define ARIZONA_ISRC3DEC1MIX_INPUT_1_SOURCE 0xB80 +#define ARIZONA_ISRC3DEC2MIX_INPUT_1_SOURCE 0xB88 +#define ARIZONA_ISRC3DEC3MIX_INPUT_1_SOURCE 0xB90 +#define ARIZONA_ISRC3DEC4MIX_INPUT_1_SOURCE 0xB98 +#define ARIZONA_ISRC3INT1MIX_INPUT_1_SOURCE 0xBA0 +#define ARIZONA_ISRC3INT2MIX_INPUT_1_SOURCE 0xBA8 +#define ARIZONA_ISRC3INT3MIX_INPUT_1_SOURCE 0xBB0 +#define ARIZONA_ISRC3INT4MIX_INPUT_1_SOURCE 0xBB8 +#define ARIZONA_GPIO1_CTRL 0xC00 +#define ARIZONA_GPIO2_CTRL 0xC01 +#define ARIZONA_GPIO3_CTRL 0xC02 +#define ARIZONA_GPIO4_CTRL 0xC03 +#define ARIZONA_GPIO5_CTRL 0xC04 +#define ARIZONA_IRQ_CTRL_1 0xC0F +#define ARIZONA_GPIO_DEBOUNCE_CONFIG 0xC10 +#define ARIZONA_MISC_PAD_CTRL_1 0xC20 +#define ARIZONA_MISC_PAD_CTRL_2 0xC21 +#define ARIZONA_MISC_PAD_CTRL_3 0xC22 +#define ARIZONA_MISC_PAD_CTRL_4 0xC23 +#define ARIZONA_MISC_PAD_CTRL_5 0xC24 +#define ARIZONA_MISC_PAD_CTRL_6 0xC25 +#define ARIZONA_MISC_PAD_CTRL_7 0xC30 +#define ARIZONA_MISC_PAD_CTRL_8 0xC31 +#define ARIZONA_MISC_PAD_CTRL_9 0xC32 +#define ARIZONA_MISC_PAD_CTRL_10 0xC33 +#define ARIZONA_MISC_PAD_CTRL_11 0xC34 +#define ARIZONA_MISC_PAD_CTRL_12 0xC35 +#define ARIZONA_MISC_PAD_CTRL_13 0xC36 +#define ARIZONA_MISC_PAD_CTRL_14 0xC37 +#define ARIZONA_MISC_PAD_CTRL_15 0xC38 +#define ARIZONA_MISC_PAD_CTRL_16 0xC39 +#define ARIZONA_MISC_PAD_CTRL_17 0xC3A +#define ARIZONA_MISC_PAD_CTRL_18 0xC3B +#define ARIZONA_INTERRUPT_STATUS_1 0xD00 +#define ARIZONA_INTERRUPT_STATUS_2 0xD01 +#define ARIZONA_INTERRUPT_STATUS_3 0xD02 +#define ARIZONA_INTERRUPT_STATUS_4 0xD03 +#define ARIZONA_INTERRUPT_STATUS_5 0xD04 +#define ARIZONA_INTERRUPT_STATUS_1_MASK 0xD08 +#define ARIZONA_INTERRUPT_STATUS_2_MASK 0xD09 +#define ARIZONA_INTERRUPT_STATUS_3_MASK 0xD0A +#define ARIZONA_INTERRUPT_STATUS_4_MASK 0xD0B +#define ARIZONA_INTERRUPT_STATUS_5_MASK 0xD0C +#define ARIZONA_INTERRUPT_CONTROL 0xD0F +#define ARIZONA_IRQ2_STATUS_1 0xD10 +#define ARIZONA_IRQ2_STATUS_2 0xD11 +#define ARIZONA_IRQ2_STATUS_3 0xD12 +#define ARIZONA_IRQ2_STATUS_4 0xD13 +#define ARIZONA_IRQ2_STATUS_5 0xD14 +#define ARIZONA_IRQ2_STATUS_1_MASK 0xD18 +#define ARIZONA_IRQ2_STATUS_2_MASK 0xD19 +#define ARIZONA_IRQ2_STATUS_3_MASK 0xD1A +#define ARIZONA_IRQ2_STATUS_4_MASK 0xD1B +#define ARIZONA_IRQ2_STATUS_5_MASK 0xD1C +#define ARIZONA_IRQ2_CONTROL 0xD1F +#define ARIZONA_INTERRUPT_RAW_STATUS_2 0xD20 +#define ARIZONA_INTERRUPT_RAW_STATUS_3 0xD21 +#define ARIZONA_INTERRUPT_RAW_STATUS_4 0xD22 +#define ARIZONA_INTERRUPT_RAW_STATUS_5 0xD23 +#define ARIZONA_INTERRUPT_RAW_STATUS_6 0xD24 +#define ARIZONA_INTERRUPT_RAW_STATUS_7 0xD25 +#define ARIZONA_INTERRUPT_RAW_STATUS_8 0xD26 +#define ARIZONA_IRQ_PIN_STATUS 0xD40 +#define ARIZONA_ADSP2_IRQ0 0xD41 +#define ARIZONA_AOD_WKUP_AND_TRIG 0xD50 +#define ARIZONA_AOD_IRQ1 0xD51 +#define ARIZONA_AOD_IRQ2 0xD52 +#define ARIZONA_AOD_IRQ_MASK_IRQ1 0xD53 +#define ARIZONA_AOD_IRQ_MASK_IRQ2 0xD54 +#define ARIZONA_AOD_IRQ_RAW_STATUS 0xD55 +#define ARIZONA_JACK_DETECT_DEBOUNCE 0xD56 +#define ARIZONA_FX_CTRL1 0xE00 +#define ARIZONA_FX_CTRL2 0xE01 +#define ARIZONA_EQ1_1 0xE10 +#define ARIZONA_EQ1_2 0xE11 +#define ARIZONA_EQ1_3 0xE12 +#define ARIZONA_EQ1_4 0xE13 +#define ARIZONA_EQ1_5 0xE14 +#define ARIZONA_EQ1_6 0xE15 +#define ARIZONA_EQ1_7 0xE16 +#define ARIZONA_EQ1_8 0xE17 +#define ARIZONA_EQ1_9 0xE18 +#define ARIZONA_EQ1_10 0xE19 +#define ARIZONA_EQ1_11 0xE1A +#define ARIZONA_EQ1_12 0xE1B +#define ARIZONA_EQ1_13 0xE1C +#define ARIZONA_EQ1_14 0xE1D +#define ARIZONA_EQ1_15 0xE1E +#define ARIZONA_EQ1_16 0xE1F +#define ARIZONA_EQ1_17 0xE20 +#define ARIZONA_EQ1_18 0xE21 +#define ARIZONA_EQ1_19 0xE22 +#define ARIZONA_EQ1_20 0xE23 +#define ARIZONA_EQ1_21 0xE24 +#define ARIZONA_EQ2_1 0xE26 +#define ARIZONA_EQ2_2 0xE27 +#define ARIZONA_EQ2_3 0xE28 +#define ARIZONA_EQ2_4 0xE29 +#define ARIZONA_EQ2_5 0xE2A +#define ARIZONA_EQ2_6 0xE2B +#define ARIZONA_EQ2_7 0xE2C +#define ARIZONA_EQ2_8 0xE2D +#define ARIZONA_EQ2_9 0xE2E +#define ARIZONA_EQ2_10 0xE2F +#define ARIZONA_EQ2_11 0xE30 +#define ARIZONA_EQ2_12 0xE31 +#define ARIZONA_EQ2_13 0xE32 +#define ARIZONA_EQ2_14 0xE33 +#define ARIZONA_EQ2_15 0xE34 +#define ARIZONA_EQ2_16 0xE35 +#define ARIZONA_EQ2_17 0xE36 +#define ARIZONA_EQ2_18 0xE37 +#define ARIZONA_EQ2_19 0xE38 +#define ARIZONA_EQ2_20 0xE39 +#define ARIZONA_EQ2_21 0xE3A +#define ARIZONA_EQ3_1 0xE3C +#define ARIZONA_EQ3_2 0xE3D +#define ARIZONA_EQ3_3 0xE3E +#define ARIZONA_EQ3_4 0xE3F +#define ARIZONA_EQ3_5 0xE40 +#define ARIZONA_EQ3_6 0xE41 +#define ARIZONA_EQ3_7 0xE42 +#define ARIZONA_EQ3_8 0xE43 +#define ARIZONA_EQ3_9 0xE44 +#define ARIZONA_EQ3_10 0xE45 +#define ARIZONA_EQ3_11 0xE46 +#define ARIZONA_EQ3_12 0xE47 +#define ARIZONA_EQ3_13 0xE48 +#define ARIZONA_EQ3_14 0xE49 +#define ARIZONA_EQ3_15 0xE4A +#define ARIZONA_EQ3_16 0xE4B +#define ARIZONA_EQ3_17 0xE4C +#define ARIZONA_EQ3_18 0xE4D +#define ARIZONA_EQ3_19 0xE4E +#define ARIZONA_EQ3_20 0xE4F +#define ARIZONA_EQ3_21 0xE50 +#define ARIZONA_EQ4_1 0xE52 +#define ARIZONA_EQ4_2 0xE53 +#define ARIZONA_EQ4_3 0xE54 +#define ARIZONA_EQ4_4 0xE55 +#define ARIZONA_EQ4_5 0xE56 +#define ARIZONA_EQ4_6 0xE57 +#define ARIZONA_EQ4_7 0xE58 +#define ARIZONA_EQ4_8 0xE59 +#define ARIZONA_EQ4_9 0xE5A +#define ARIZONA_EQ4_10 0xE5B +#define ARIZONA_EQ4_11 0xE5C +#define ARIZONA_EQ4_12 0xE5D +#define ARIZONA_EQ4_13 0xE5E +#define ARIZONA_EQ4_14 0xE5F +#define ARIZONA_EQ4_15 0xE60 +#define ARIZONA_EQ4_16 0xE61 +#define ARIZONA_EQ4_17 0xE62 +#define ARIZONA_EQ4_18 0xE63 +#define ARIZONA_EQ4_19 0xE64 +#define ARIZONA_EQ4_20 0xE65 +#define ARIZONA_EQ4_21 0xE66 +#define ARIZONA_DRC1_CTRL1 0xE80 +#define ARIZONA_DRC1_CTRL2 0xE81 +#define ARIZONA_DRC1_CTRL3 0xE82 +#define ARIZONA_DRC1_CTRL4 0xE83 +#define ARIZONA_DRC1_CTRL5 0xE84 +#define ARIZONA_DRC2_CTRL1 0xE89 +#define ARIZONA_DRC2_CTRL2 0xE8A +#define ARIZONA_DRC2_CTRL3 0xE8B +#define ARIZONA_DRC2_CTRL4 0xE8C +#define ARIZONA_DRC2_CTRL5 0xE8D +#define ARIZONA_HPLPF1_1 0xEC0 +#define ARIZONA_HPLPF1_2 0xEC1 +#define ARIZONA_HPLPF2_1 0xEC4 +#define ARIZONA_HPLPF2_2 0xEC5 +#define ARIZONA_HPLPF3_1 0xEC8 +#define ARIZONA_HPLPF3_2 0xEC9 +#define ARIZONA_HPLPF4_1 0xECC +#define ARIZONA_HPLPF4_2 0xECD +#define ARIZONA_ASRC_ENABLE 0xEE0 +#define ARIZONA_ASRC_STATUS 0xEE1 +#define ARIZONA_ASRC_RATE1 0xEE2 +#define ARIZONA_ASRC_RATE2 0xEE3 +#define ARIZONA_ISRC_1_CTRL_1 0xEF0 +#define ARIZONA_ISRC_1_CTRL_2 0xEF1 +#define ARIZONA_ISRC_1_CTRL_3 0xEF2 +#define ARIZONA_ISRC_2_CTRL_1 0xEF3 +#define ARIZONA_ISRC_2_CTRL_2 0xEF4 +#define ARIZONA_ISRC_2_CTRL_3 0xEF5 +#define ARIZONA_ISRC_3_CTRL_1 0xEF6 +#define ARIZONA_ISRC_3_CTRL_2 0xEF7 +#define ARIZONA_ISRC_3_CTRL_3 0xEF8 +#define ARIZONA_CLOCK_CONTROL 0xF00 +#define ARIZONA_ANC_SRC 0xF01 +#define ARIZONA_DSP_STATUS 0xF02 +#define ARIZONA_DSP1_CONTROL_1 0x1100 +#define ARIZONA_DSP1_CLOCKING_1 0x1101 +#define ARIZONA_DSP1_STATUS_1 0x1104 +#define ARIZONA_DSP1_STATUS_2 0x1105 +#define ARIZONA_DSP2_CONTROL_1 0x1200 +#define ARIZONA_DSP2_CLOCKING_1 0x1201 +#define ARIZONA_DSP2_STATUS_1 0x1204 +#define ARIZONA_DSP2_STATUS_2 0x1205 +#define ARIZONA_DSP3_CONTROL_1 0x1300 +#define ARIZONA_DSP3_CLOCKING_1 0x1301 +#define ARIZONA_DSP3_STATUS_1 0x1304 +#define ARIZONA_DSP3_STATUS_2 0x1305 +#define ARIZONA_DSP4_CONTROL_1 0x1400 +#define ARIZONA_DSP4_CLOCKING_1 0x1401 +#define ARIZONA_DSP4_STATUS_1 0x1404 +#define ARIZONA_DSP4_STATUS_2 0x1405 + +/* + * Field Definitions. + */ + +/* + * R0 (0x00) - software reset + */ +#define ARIZONA_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ +#define ARIZONA_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ +#define ARIZONA_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ + +/* + * R1 (0x01) - Device Revision + */ +#define ARIZONA_DEVICE_REVISION_MASK 0x00FF /* DEVICE_REVISION - [7:0] */ +#define ARIZONA_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [7:0] */ +#define ARIZONA_DEVICE_REVISION_WIDTH 8 /* DEVICE_REVISION - [7:0] */ + +/* + * R8 (0x08) - Ctrl IF SPI CFG 1 + */ +#define ARIZONA_SPI_CFG 0x0010 /* SPI_CFG */ +#define ARIZONA_SPI_CFG_MASK 0x0010 /* SPI_CFG */ +#define ARIZONA_SPI_CFG_SHIFT 4 /* SPI_CFG */ +#define ARIZONA_SPI_CFG_WIDTH 1 /* SPI_CFG */ +#define ARIZONA_SPI_4WIRE 0x0008 /* SPI_4WIRE */ +#define ARIZONA_SPI_4WIRE_MASK 0x0008 /* SPI_4WIRE */ +#define ARIZONA_SPI_4WIRE_SHIFT 3 /* SPI_4WIRE */ +#define ARIZONA_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */ +#define ARIZONA_SPI_AUTO_INC_MASK 0x0003 /* SPI_AUTO_INC - [1:0] */ +#define ARIZONA_SPI_AUTO_INC_SHIFT 0 /* SPI_AUTO_INC - [1:0] */ +#define ARIZONA_SPI_AUTO_INC_WIDTH 2 /* SPI_AUTO_INC - [1:0] */ + +/* + * R9 (0x09) - Ctrl IF I2C1 CFG 1 + */ +#define ARIZONA_I2C1_AUTO_INC_MASK 0x0003 /* I2C1_AUTO_INC - [1:0] */ +#define ARIZONA_I2C1_AUTO_INC_SHIFT 0 /* I2C1_AUTO_INC - [1:0] */ +#define ARIZONA_I2C1_AUTO_INC_WIDTH 2 /* I2C1_AUTO_INC - [1:0] */ + +/* + * R13 (0x0D) - Ctrl IF Status 1 + */ +#define ARIZONA_I2C1_BUSY 0x0020 /* I2C1_BUSY */ +#define ARIZONA_I2C1_BUSY_MASK 0x0020 /* I2C1_BUSY */ +#define ARIZONA_I2C1_BUSY_SHIFT 5 /* I2C1_BUSY */ +#define ARIZONA_I2C1_BUSY_WIDTH 1 /* I2C1_BUSY */ +#define ARIZONA_SPI_BUSY 0x0010 /* SPI_BUSY */ +#define ARIZONA_SPI_BUSY_MASK 0x0010 /* SPI_BUSY */ +#define ARIZONA_SPI_BUSY_SHIFT 4 /* SPI_BUSY */ +#define ARIZONA_SPI_BUSY_WIDTH 1 /* SPI_BUSY */ + +/* + * R22 (0x16) - Write Sequencer Ctrl 0 + */ +#define ARIZONA_WSEQ_ABORT 0x0800 /* WSEQ_ABORT */ +#define ARIZONA_WSEQ_ABORT_MASK 0x0800 /* WSEQ_ABORT */ +#define ARIZONA_WSEQ_ABORT_SHIFT 11 /* WSEQ_ABORT */ +#define ARIZONA_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ +#define ARIZONA_WSEQ_START 0x0400 /* WSEQ_START */ +#define ARIZONA_WSEQ_START_MASK 0x0400 /* WSEQ_START */ +#define ARIZONA_WSEQ_START_SHIFT 10 /* WSEQ_START */ +#define ARIZONA_WSEQ_START_WIDTH 1 /* WSEQ_START */ +#define ARIZONA_WSEQ_ENA 0x0200 /* WSEQ_ENA */ +#define ARIZONA_WSEQ_ENA_MASK 0x0200 /* WSEQ_ENA */ +#define ARIZONA_WSEQ_ENA_SHIFT 9 /* WSEQ_ENA */ +#define ARIZONA_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ +#define ARIZONA_WSEQ_START_INDEX_MASK 0x01FF /* WSEQ_START_INDEX - [8:0] */ +#define ARIZONA_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [8:0] */ +#define ARIZONA_WSEQ_START_INDEX_WIDTH 9 /* WSEQ_START_INDEX - [8:0] */ + +/* + * R23 (0x17) - Write Sequencer Ctrl 1 + */ +#define ARIZONA_WSEQ_BUSY 0x0200 /* WSEQ_BUSY */ +#define ARIZONA_WSEQ_BUSY_MASK 0x0200 /* WSEQ_BUSY */ +#define ARIZONA_WSEQ_BUSY_SHIFT 9 /* WSEQ_BUSY */ +#define ARIZONA_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ +#define ARIZONA_WSEQ_CURRENT_INDEX_MASK 0x01FF /* WSEQ_CURRENT_INDEX - [8:0] */ +#define ARIZONA_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [8:0] */ +#define ARIZONA_WSEQ_CURRENT_INDEX_WIDTH 9 /* WSEQ_CURRENT_INDEX - [8:0] */ + +/* + * R24 (0x18) - Write Sequencer Ctrl 2 + */ +#define ARIZONA_LOAD_DEFAULTS 0x0002 /* LOAD_DEFAULTS */ +#define ARIZONA_LOAD_DEFAULTS_MASK 0x0002 /* LOAD_DEFAULTS */ +#define ARIZONA_LOAD_DEFAULTS_SHIFT 1 /* LOAD_DEFAULTS */ +#define ARIZONA_LOAD_DEFAULTS_WIDTH 1 /* LOAD_DEFAULTS */ +#define ARIZONA_WSEQ_LOAD_MEM 0x0001 /* WSEQ_LOAD_MEM */ +#define ARIZONA_WSEQ_LOAD_MEM_MASK 0x0001 /* WSEQ_LOAD_MEM */ +#define ARIZONA_WSEQ_LOAD_MEM_SHIFT 0 /* WSEQ_LOAD_MEM */ +#define ARIZONA_WSEQ_LOAD_MEM_WIDTH 1 /* WSEQ_LOAD_MEM */ + +/* + * R26 (0x1A) - Write Sequencer PROM + */ +#define ARIZONA_WSEQ_OTP_WRITE 0x0001 /* WSEQ_OTP_WRITE */ +#define ARIZONA_WSEQ_OTP_WRITE_MASK 0x0001 /* WSEQ_OTP_WRITE */ +#define ARIZONA_WSEQ_OTP_WRITE_SHIFT 0 /* WSEQ_OTP_WRITE */ +#define ARIZONA_WSEQ_OTP_WRITE_WIDTH 1 /* WSEQ_OTP_WRITE */ + +/* + * R32 (0x20) - Tone Generator 1 + */ +#define ARIZONA_TONE_RATE_MASK 0x7800 /* TONE_RATE - [14:11] */ +#define ARIZONA_TONE_RATE_SHIFT 11 /* TONE_RATE - [14:11] */ +#define ARIZONA_TONE_RATE_WIDTH 4 /* TONE_RATE - [14:11] */ +#define ARIZONA_TONE_OFFSET_MASK 0x0300 /* TONE_OFFSET - [9:8] */ +#define ARIZONA_TONE_OFFSET_SHIFT 8 /* TONE_OFFSET - [9:8] */ +#define ARIZONA_TONE_OFFSET_WIDTH 2 /* TONE_OFFSET - [9:8] */ +#define ARIZONA_TONE2_OVD 0x0020 /* TONE2_OVD */ +#define ARIZONA_TONE2_OVD_MASK 0x0020 /* TONE2_OVD */ +#define ARIZONA_TONE2_OVD_SHIFT 5 /* TONE2_OVD */ +#define ARIZONA_TONE2_OVD_WIDTH 1 /* TONE2_OVD */ +#define ARIZONA_TONE1_OVD 0x0010 /* TONE1_OVD */ +#define ARIZONA_TONE1_OVD_MASK 0x0010 /* TONE1_OVD */ +#define ARIZONA_TONE1_OVD_SHIFT 4 /* TONE1_OVD */ +#define ARIZONA_TONE1_OVD_WIDTH 1 /* TONE1_OVD */ +#define ARIZONA_TONE2_ENA 0x0002 /* TONE2_ENA */ +#define ARIZONA_TONE2_ENA_MASK 0x0002 /* TONE2_ENA */ +#define ARIZONA_TONE2_ENA_SHIFT 1 /* TONE2_ENA */ +#define ARIZONA_TONE2_ENA_WIDTH 1 /* TONE2_ENA */ +#define ARIZONA_TONE1_ENA 0x0001 /* TONE1_ENA */ +#define ARIZONA_TONE1_ENA_MASK 0x0001 /* TONE1_ENA */ +#define ARIZONA_TONE1_ENA_SHIFT 0 /* TONE1_ENA */ +#define ARIZONA_TONE1_ENA_WIDTH 1 /* TONE1_ENA */ + +/* + * R33 (0x21) - Tone Generator 2 + */ +#define ARIZONA_TONE1_LVL_0_MASK 0xFFFF /* TONE1_LVL - [15:0] */ +#define ARIZONA_TONE1_LVL_0_SHIFT 0 /* TONE1_LVL - [15:0] */ +#define ARIZONA_TONE1_LVL_0_WIDTH 16 /* TONE1_LVL - [15:0] */ + +/* + * R34 (0x22) - Tone Generator 3 + */ +#define ARIZONA_TONE1_LVL_MASK 0x00FF /* TONE1_LVL - [7:0] */ +#define ARIZONA_TONE1_LVL_SHIFT 0 /* TONE1_LVL - [7:0] */ +#define ARIZONA_TONE1_LVL_WIDTH 8 /* TONE1_LVL - [7:0] */ + +/* + * R35 (0x23) - Tone Generator 4 + */ +#define ARIZONA_TONE2_LVL_0_MASK 0xFFFF /* TONE2_LVL - [15:0] */ +#define ARIZONA_TONE2_LVL_0_SHIFT 0 /* TONE2_LVL - [15:0] */ +#define ARIZONA_TONE2_LVL_0_WIDTH 16 /* TONE2_LVL - [15:0] */ + +/* + * R36 (0x24) - Tone Generator 5 + */ +#define ARIZONA_TONE2_LVL_MASK 0x00FF /* TONE2_LVL - [7:0] */ +#define ARIZONA_TONE2_LVL_SHIFT 0 /* TONE2_LVL - [7:0] */ +#define ARIZONA_TONE2_LVL_WIDTH 8 /* TONE2_LVL - [7:0] */ + +/* + * R48 (0x30) - PWM Drive 1 + */ +#define ARIZONA_PWM_RATE_MASK 0x7800 /* PWM_RATE - [14:11] */ +#define ARIZONA_PWM_RATE_SHIFT 11 /* PWM_RATE - [14:11] */ +#define ARIZONA_PWM_RATE_WIDTH 4 /* PWM_RATE - [14:11] */ +#define ARIZONA_PWM_CLK_SEL_MASK 0x0700 /* PWM_CLK_SEL - [10:8] */ +#define ARIZONA_PWM_CLK_SEL_SHIFT 8 /* PWM_CLK_SEL - [10:8] */ +#define ARIZONA_PWM_CLK_SEL_WIDTH 3 /* PWM_CLK_SEL - [10:8] */ +#define ARIZONA_PWM2_OVD 0x0020 /* PWM2_OVD */ +#define ARIZONA_PWM2_OVD_MASK 0x0020 /* PWM2_OVD */ +#define ARIZONA_PWM2_OVD_SHIFT 5 /* PWM2_OVD */ +#define ARIZONA_PWM2_OVD_WIDTH 1 /* PWM2_OVD */ +#define ARIZONA_PWM1_OVD 0x0010 /* PWM1_OVD */ +#define ARIZONA_PWM1_OVD_MASK 0x0010 /* PWM1_OVD */ +#define ARIZONA_PWM1_OVD_SHIFT 4 /* PWM1_OVD */ +#define ARIZONA_PWM1_OVD_WIDTH 1 /* PWM1_OVD */ +#define ARIZONA_PWM2_ENA 0x0002 /* PWM2_ENA */ +#define ARIZONA_PWM2_ENA_MASK 0x0002 /* PWM2_ENA */ +#define ARIZONA_PWM2_ENA_SHIFT 1 /* PWM2_ENA */ +#define ARIZONA_PWM2_ENA_WIDTH 1 /* PWM2_ENA */ +#define ARIZONA_PWM1_ENA 0x0001 /* PWM1_ENA */ +#define ARIZONA_PWM1_ENA_MASK 0x0001 /* PWM1_ENA */ +#define ARIZONA_PWM1_ENA_SHIFT 0 /* PWM1_ENA */ +#define ARIZONA_PWM1_ENA_WIDTH 1 /* PWM1_ENA */ + +/* + * R49 (0x31) - PWM Drive 2 + */ +#define ARIZONA_PWM1_LVL_MASK 0x03FF /* PWM1_LVL - [9:0] */ +#define ARIZONA_PWM1_LVL_SHIFT 0 /* PWM1_LVL - [9:0] */ +#define ARIZONA_PWM1_LVL_WIDTH 10 /* PWM1_LVL - [9:0] */ + +/* + * R50 (0x32) - PWM Drive 3 + */ +#define ARIZONA_PWM2_LVL_MASK 0x03FF /* PWM2_LVL - [9:0] */ +#define ARIZONA_PWM2_LVL_SHIFT 0 /* PWM2_LVL - [9:0] */ +#define ARIZONA_PWM2_LVL_WIDTH 10 /* PWM2_LVL - [9:0] */ + +/* + * R64 (0x40) - Wake control + */ +#define ARIZONA_WKUP_GP5_FALL 0x0020 /* WKUP_GP5_FALL */ +#define ARIZONA_WKUP_GP5_FALL_MASK 0x0020 /* WKUP_GP5_FALL */ +#define ARIZONA_WKUP_GP5_FALL_SHIFT 5 /* WKUP_GP5_FALL */ +#define ARIZONA_WKUP_GP5_FALL_WIDTH 1 /* WKUP_GP5_FALL */ +#define ARIZONA_WKUP_GP5_RISE 0x0010 /* WKUP_GP5_RISE */ +#define ARIZONA_WKUP_GP5_RISE_MASK 0x0010 /* WKUP_GP5_RISE */ +#define ARIZONA_WKUP_GP5_RISE_SHIFT 4 /* WKUP_GP5_RISE */ +#define ARIZONA_WKUP_GP5_RISE_WIDTH 1 /* WKUP_GP5_RISE */ +#define ARIZONA_WKUP_JD1_FALL 0x0008 /* WKUP_JD1_FALL */ +#define ARIZONA_WKUP_JD1_FALL_MASK 0x0008 /* WKUP_JD1_FALL */ +#define ARIZONA_WKUP_JD1_FALL_SHIFT 3 /* WKUP_JD1_FALL */ +#define ARIZONA_WKUP_JD1_FALL_WIDTH 1 /* WKUP_JD1_FALL */ +#define ARIZONA_WKUP_JD1_RISE 0x0004 /* WKUP_JD1_RISE */ +#define ARIZONA_WKUP_JD1_RISE_MASK 0x0004 /* WKUP_JD1_RISE */ +#define ARIZONA_WKUP_JD1_RISE_SHIFT 2 /* WKUP_JD1_RISE */ +#define ARIZONA_WKUP_JD1_RISE_WIDTH 1 /* WKUP_JD1_RISE */ +#define ARIZONA_WKUP_JD2_FALL 0x0002 /* WKUP_JD2_FALL */ +#define ARIZONA_WKUP_JD2_FALL_MASK 0x0002 /* WKUP_JD2_FALL */ +#define ARIZONA_WKUP_JD2_FALL_SHIFT 1 /* WKUP_JD2_FALL */ +#define ARIZONA_WKUP_JD2_FALL_WIDTH 1 /* WKUP_JD2_FALL */ +#define ARIZONA_WKUP_JD2_RISE 0x0001 /* WKUP_JD2_RISE */ +#define ARIZONA_WKUP_JD2_RISE_MASK 0x0001 /* WKUP_JD2_RISE */ +#define ARIZONA_WKUP_JD2_RISE_SHIFT 0 /* WKUP_JD2_RISE */ +#define ARIZONA_WKUP_JD2_RISE_WIDTH 1 /* WKUP_JD2_RISE */ + +/* + * R65 (0x41) - Sequence control + */ +#define ARIZONA_WSEQ_ENA_GP5_FALL 0x0020 /* WSEQ_ENA_GP5_FALL */ +#define ARIZONA_WSEQ_ENA_GP5_FALL_MASK 0x0020 /* WSEQ_ENA_GP5_FALL */ +#define ARIZONA_WSEQ_ENA_GP5_FALL_SHIFT 5 /* WSEQ_ENA_GP5_FALL */ +#define ARIZONA_WSEQ_ENA_GP5_FALL_WIDTH 1 /* WSEQ_ENA_GP5_FALL */ +#define ARIZONA_WSEQ_ENA_GP5_RISE 0x0010 /* WSEQ_ENA_GP5_RISE */ +#define ARIZONA_WSEQ_ENA_GP5_RISE_MASK 0x0010 /* WSEQ_ENA_GP5_RISE */ +#define ARIZONA_WSEQ_ENA_GP5_RISE_SHIFT 4 /* WSEQ_ENA_GP5_RISE */ +#define ARIZONA_WSEQ_ENA_GP5_RISE_WIDTH 1 /* WSEQ_ENA_GP5_RISE */ +#define ARIZONA_WSEQ_ENA_JD1_FALL 0x0008 /* WSEQ_ENA_JD1_FALL */ +#define ARIZONA_WSEQ_ENA_JD1_FALL_MASK 0x0008 /* WSEQ_ENA_JD1_FALL */ +#define ARIZONA_WSEQ_ENA_JD1_FALL_SHIFT 3 /* WSEQ_ENA_JD1_FALL */ +#define ARIZONA_WSEQ_ENA_JD1_FALL_WIDTH 1 /* WSEQ_ENA_JD1_FALL */ +#define ARIZONA_WSEQ_ENA_JD1_RISE 0x0004 /* WSEQ_ENA_JD1_RISE */ +#define ARIZONA_WSEQ_ENA_JD1_RISE_MASK 0x0004 /* WSEQ_ENA_JD1_RISE */ +#define ARIZONA_WSEQ_ENA_JD1_RISE_SHIFT 2 /* WSEQ_ENA_JD1_RISE */ +#define ARIZONA_WSEQ_ENA_JD1_RISE_WIDTH 1 /* WSEQ_ENA_JD1_RISE */ +#define ARIZONA_WSEQ_ENA_JD2_FALL 0x0002 /* WSEQ_ENA_JD2_FALL */ +#define ARIZONA_WSEQ_ENA_JD2_FALL_MASK 0x0002 /* WSEQ_ENA_JD2_FALL */ +#define ARIZONA_WSEQ_ENA_JD2_FALL_SHIFT 1 /* WSEQ_ENA_JD2_FALL */ +#define ARIZONA_WSEQ_ENA_JD2_FALL_WIDTH 1 /* WSEQ_ENA_JD2_FALL */ +#define ARIZONA_WSEQ_ENA_JD2_RISE 0x0001 /* WSEQ_ENA_JD2_RISE */ +#define ARIZONA_WSEQ_ENA_JD2_RISE_MASK 0x0001 /* WSEQ_ENA_JD2_RISE */ +#define ARIZONA_WSEQ_ENA_JD2_RISE_SHIFT 0 /* WSEQ_ENA_JD2_RISE */ +#define ARIZONA_WSEQ_ENA_JD2_RISE_WIDTH 1 /* WSEQ_ENA_JD2_RISE */ + +/* + * R97 (0x61) - Sample Rate Sequence Select 1 + */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR_MASK 0x01FF /* WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR_SHIFT 0 /* WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR_WIDTH 9 /* WSEQ_SAMPLE_RATE_DETECT_A_SEQ_ADDR - [8:0] */ + +/* + * R98 (0x62) - Sample Rate Sequence Select 2 + */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR_MASK 0x01FF /* WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR_SHIFT 0 /* WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR_WIDTH 9 /* WSEQ_SAMPLE_RATE_DETECT_B_SEQ_ADDR - [8:0] */ + +/* + * R99 (0x63) - Sample Rate Sequence Select 3 + */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR_MASK 0x01FF /* WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR_SHIFT 0 /* WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR_WIDTH 9 /* WSEQ_SAMPLE_RATE_DETECT_C_SEQ_ADDR - [8:0] */ + +/* + * R100 (0x64) - Sample Rate Sequence Select 4 + */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR_MASK 0x01FF /* WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR_SHIFT 0 /* WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR_WIDTH 9 /* WSEQ_SAMPLE_RATE_DETECT_D_SEQ_ADDR - [8:0] */ + +/* + * R104 (0x68) - Always On Triggers Sequence Select 1 + */ +#define ARIZONA_WSEQ_GP5_RISE_SEQ_ADDR_MASK 0x01FF /* WSEQ_GP5_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_GP5_RISE_SEQ_ADDR_SHIFT 0 /* WSEQ_GP5_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_GP5_RISE_SEQ_ADDR_WIDTH 9 /* WSEQ_GP5_RISE_SEQ_ADDR - [8:0] */ + +/* + * R105 (0x69) - Always On Triggers Sequence Select 2 + */ +#define ARIZONA_WSEQ_GP5_FALL_SEQ_ADDR_MASK 0x01FF /* WSEQ_GP5_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_GP5_FALL_SEQ_ADDR_SHIFT 0 /* WSEQ_GP5_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_GP5_FALL_SEQ_ADDR_WIDTH 9 /* WSEQ_GP5_FALL_SEQ_ADDR - [8:0] */ + +/* + * R106 (0x6A) - Always On Triggers Sequence Select 3 + */ +#define ARIZONA_WSEQ_JD1_RISE_SEQ_ADDR_MASK 0x01FF /* WSEQ_JD1_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD1_RISE_SEQ_ADDR_SHIFT 0 /* WSEQ_JD1_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD1_RISE_SEQ_ADDR_WIDTH 9 /* WSEQ_JD1_RISE_SEQ_ADDR - [8:0] */ + +/* + * R107 (0x6B) - Always On Triggers Sequence Select 4 + */ +#define ARIZONA_WSEQ_JD1_FALL_SEQ_ADDR_MASK 0x01FF /* WSEQ_JD1_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD1_FALL_SEQ_ADDR_SHIFT 0 /* WSEQ_JD1_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD1_FALL_SEQ_ADDR_WIDTH 9 /* WSEQ_JD1_FALL_SEQ_ADDR - [8:0] */ + +/* + * R108 (0x6C) - Always On Triggers Sequence Select 5 + */ +#define ARIZONA_WSEQ_JD2_RISE_SEQ_ADDR_MASK 0x01FF /* WSEQ_JD2_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD2_RISE_SEQ_ADDR_SHIFT 0 /* WSEQ_JD2_RISE_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD2_RISE_SEQ_ADDR_WIDTH 9 /* WSEQ_JD2_RISE_SEQ_ADDR - [8:0] */ + +/* + * R109 (0x6D) - Always On Triggers Sequence Select 6 + */ +#define ARIZONA_WSEQ_JD2_FALL_SEQ_ADDR_MASK 0x01FF /* WSEQ_JD2_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD2_FALL_SEQ_ADDR_SHIFT 0 /* WSEQ_JD2_FALL_SEQ_ADDR - [8:0] */ +#define ARIZONA_WSEQ_JD2_FALL_SEQ_ADDR_WIDTH 9 /* WSEQ_JD2_FALL_SEQ_ADDR - [8:0] */ + +/* + * R112 (0x70) - Comfort Noise Generator + */ +#define ARIZONA_NOISE_GEN_RATE_MASK 0x7800 /* NOISE_GEN_RATE - [14:11] */ +#define ARIZONA_NOISE_GEN_RATE_SHIFT 11 /* NOISE_GEN_RATE - [14:11] */ +#define ARIZONA_NOISE_GEN_RATE_WIDTH 4 /* NOISE_GEN_RATE - [14:11] */ +#define ARIZONA_NOISE_GEN_ENA 0x0020 /* NOISE_GEN_ENA */ +#define ARIZONA_NOISE_GEN_ENA_MASK 0x0020 /* NOISE_GEN_ENA */ +#define ARIZONA_NOISE_GEN_ENA_SHIFT 5 /* NOISE_GEN_ENA */ +#define ARIZONA_NOISE_GEN_ENA_WIDTH 1 /* NOISE_GEN_ENA */ +#define ARIZONA_NOISE_GEN_GAIN_MASK 0x001F /* NOISE_GEN_GAIN - [4:0] */ +#define ARIZONA_NOISE_GEN_GAIN_SHIFT 0 /* NOISE_GEN_GAIN - [4:0] */ +#define ARIZONA_NOISE_GEN_GAIN_WIDTH 5 /* NOISE_GEN_GAIN - [4:0] */ + +/* + * R144 (0x90) - Haptics Control 1 + */ +#define ARIZONA_HAP_RATE_MASK 0x7800 /* HAP_RATE - [14:11] */ +#define ARIZONA_HAP_RATE_SHIFT 11 /* HAP_RATE - [14:11] */ +#define ARIZONA_HAP_RATE_WIDTH 4 /* HAP_RATE - [14:11] */ +#define ARIZONA_ONESHOT_TRIG 0x0010 /* ONESHOT_TRIG */ +#define ARIZONA_ONESHOT_TRIG_MASK 0x0010 /* ONESHOT_TRIG */ +#define ARIZONA_ONESHOT_TRIG_SHIFT 4 /* ONESHOT_TRIG */ +#define ARIZONA_ONESHOT_TRIG_WIDTH 1 /* ONESHOT_TRIG */ +#define ARIZONA_HAP_CTRL_MASK 0x000C /* HAP_CTRL - [3:2] */ +#define ARIZONA_HAP_CTRL_SHIFT 2 /* HAP_CTRL - [3:2] */ +#define ARIZONA_HAP_CTRL_WIDTH 2 /* HAP_CTRL - [3:2] */ +#define ARIZONA_HAP_ACT 0x0002 /* HAP_ACT */ +#define ARIZONA_HAP_ACT_MASK 0x0002 /* HAP_ACT */ +#define ARIZONA_HAP_ACT_SHIFT 1 /* HAP_ACT */ +#define ARIZONA_HAP_ACT_WIDTH 1 /* HAP_ACT */ + +/* + * R145 (0x91) - Haptics Control 2 + */ +#define ARIZONA_LRA_FREQ_MASK 0x7FFF /* LRA_FREQ - [14:0] */ +#define ARIZONA_LRA_FREQ_SHIFT 0 /* LRA_FREQ - [14:0] */ +#define ARIZONA_LRA_FREQ_WIDTH 15 /* LRA_FREQ - [14:0] */ + +/* + * R146 (0x92) - Haptics phase 1 intensity + */ +#define ARIZONA_PHASE1_INTENSITY_MASK 0x00FF /* PHASE1_INTENSITY - [7:0] */ +#define ARIZONA_PHASE1_INTENSITY_SHIFT 0 /* PHASE1_INTENSITY - [7:0] */ +#define ARIZONA_PHASE1_INTENSITY_WIDTH 8 /* PHASE1_INTENSITY - [7:0] */ + +/* + * R147 (0x93) - Haptics phase 1 duration + */ +#define ARIZONA_PHASE1_DURATION_MASK 0x01FF /* PHASE1_DURATION - [8:0] */ +#define ARIZONA_PHASE1_DURATION_SHIFT 0 /* PHASE1_DURATION - [8:0] */ +#define ARIZONA_PHASE1_DURATION_WIDTH 9 /* PHASE1_DURATION - [8:0] */ + +/* + * R148 (0x94) - Haptics phase 2 intensity + */ +#define ARIZONA_PHASE2_INTENSITY_MASK 0x00FF /* PHASE2_INTENSITY - [7:0] */ +#define ARIZONA_PHASE2_INTENSITY_SHIFT 0 /* PHASE2_INTENSITY - [7:0] */ +#define ARIZONA_PHASE2_INTENSITY_WIDTH 8 /* PHASE2_INTENSITY - [7:0] */ + +/* + * R149 (0x95) - Haptics phase 2 duration + */ +#define ARIZONA_PHASE2_DURATION_MASK 0x07FF /* PHASE2_DURATION - [10:0] */ +#define ARIZONA_PHASE2_DURATION_SHIFT 0 /* PHASE2_DURATION - [10:0] */ +#define ARIZONA_PHASE2_DURATION_WIDTH 11 /* PHASE2_DURATION - [10:0] */ + +/* + * R150 (0x96) - Haptics phase 3 intensity + */ +#define ARIZONA_PHASE3_INTENSITY_MASK 0x00FF /* PHASE3_INTENSITY - [7:0] */ +#define ARIZONA_PHASE3_INTENSITY_SHIFT 0 /* PHASE3_INTENSITY - [7:0] */ +#define ARIZONA_PHASE3_INTENSITY_WIDTH 8 /* PHASE3_INTENSITY - [7:0] */ + +/* + * R151 (0x97) - Haptics phase 3 duration + */ +#define ARIZONA_PHASE3_DURATION_MASK 0x01FF /* PHASE3_DURATION - [8:0] */ +#define ARIZONA_PHASE3_DURATION_SHIFT 0 /* PHASE3_DURATION - [8:0] */ +#define ARIZONA_PHASE3_DURATION_WIDTH 9 /* PHASE3_DURATION - [8:0] */ + +/* + * R152 (0x98) - Haptics Status + */ +#define ARIZONA_ONESHOT_STS 0x0001 /* ONESHOT_STS */ +#define ARIZONA_ONESHOT_STS_MASK 0x0001 /* ONESHOT_STS */ +#define ARIZONA_ONESHOT_STS_SHIFT 0 /* ONESHOT_STS */ +#define ARIZONA_ONESHOT_STS_WIDTH 1 /* ONESHOT_STS */ + +/* + * R256 (0x100) - Clock 32k 1 + */ +#define ARIZONA_CLK_32K_ENA 0x0040 /* CLK_32K_ENA */ +#define ARIZONA_CLK_32K_ENA_MASK 0x0040 /* CLK_32K_ENA */ +#define ARIZONA_CLK_32K_ENA_SHIFT 6 /* CLK_32K_ENA */ +#define ARIZONA_CLK_32K_ENA_WIDTH 1 /* CLK_32K_ENA */ +#define ARIZONA_CLK_32K_SRC_MASK 0x0003 /* CLK_32K_SRC - [1:0] */ +#define ARIZONA_CLK_32K_SRC_SHIFT 0 /* CLK_32K_SRC - [1:0] */ +#define ARIZONA_CLK_32K_SRC_WIDTH 2 /* CLK_32K_SRC - [1:0] */ + +/* + * R257 (0x101) - System Clock 1 + */ +#define ARIZONA_SYSCLK_FRAC 0x8000 /* SYSCLK_FRAC */ +#define ARIZONA_SYSCLK_FRAC_MASK 0x8000 /* SYSCLK_FRAC */ +#define ARIZONA_SYSCLK_FRAC_SHIFT 15 /* SYSCLK_FRAC */ +#define ARIZONA_SYSCLK_FRAC_WIDTH 1 /* SYSCLK_FRAC */ +#define ARIZONA_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */ +#define ARIZONA_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */ +#define ARIZONA_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */ +#define ARIZONA_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */ +#define ARIZONA_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */ +#define ARIZONA_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */ +#define ARIZONA_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */ +#define ARIZONA_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */ +#define ARIZONA_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */ +#define ARIZONA_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */ + +/* + * R258 (0x102) - Sample rate 1 + */ +#define ARIZONA_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */ + +/* + * R259 (0x103) - Sample rate 2 + */ +#define ARIZONA_SAMPLE_RATE_2_MASK 0x001F /* SAMPLE_RATE_2 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_2_SHIFT 0 /* SAMPLE_RATE_2 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_2_WIDTH 5 /* SAMPLE_RATE_2 - [4:0] */ + +/* + * R260 (0x104) - Sample rate 3 + */ +#define ARIZONA_SAMPLE_RATE_3_MASK 0x001F /* SAMPLE_RATE_3 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_3_SHIFT 0 /* SAMPLE_RATE_3 - [4:0] */ +#define ARIZONA_SAMPLE_RATE_3_WIDTH 5 /* SAMPLE_RATE_3 - [4:0] */ + +/* + * R266 (0x10A) - Sample rate 1 status + */ +#define ARIZONA_SAMPLE_RATE_1_STS_MASK 0x001F /* SAMPLE_RATE_1_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_1_STS_SHIFT 0 /* SAMPLE_RATE_1_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_1_STS_WIDTH 5 /* SAMPLE_RATE_1_STS - [4:0] */ + +/* + * R267 (0x10B) - Sample rate 2 status + */ +#define ARIZONA_SAMPLE_RATE_2_STS_MASK 0x001F /* SAMPLE_RATE_2_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_2_STS_SHIFT 0 /* SAMPLE_RATE_2_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_2_STS_WIDTH 5 /* SAMPLE_RATE_2_STS - [4:0] */ + +/* + * R268 (0x10C) - Sample rate 3 status + */ +#define ARIZONA_SAMPLE_RATE_3_STS_MASK 0x001F /* SAMPLE_RATE_3_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_3_STS_SHIFT 0 /* SAMPLE_RATE_3_STS - [4:0] */ +#define ARIZONA_SAMPLE_RATE_3_STS_WIDTH 5 /* SAMPLE_RATE_3_STS - [4:0] */ + +/* + * R274 (0x112) - Async clock 1 + */ +#define ARIZONA_ASYNC_CLK_FREQ_MASK 0x0700 /* ASYNC_CLK_FREQ - [10:8] */ +#define ARIZONA_ASYNC_CLK_FREQ_SHIFT 8 /* ASYNC_CLK_FREQ - [10:8] */ +#define ARIZONA_ASYNC_CLK_FREQ_WIDTH 3 /* ASYNC_CLK_FREQ - [10:8] */ +#define ARIZONA_ASYNC_CLK_ENA 0x0040 /* ASYNC_CLK_ENA */ +#define ARIZONA_ASYNC_CLK_ENA_MASK 0x0040 /* ASYNC_CLK_ENA */ +#define ARIZONA_ASYNC_CLK_ENA_SHIFT 6 /* ASYNC_CLK_ENA */ +#define ARIZONA_ASYNC_CLK_ENA_WIDTH 1 /* ASYNC_CLK_ENA */ +#define ARIZONA_ASYNC_CLK_SRC_MASK 0x000F /* ASYNC_CLK_SRC - [3:0] */ +#define ARIZONA_ASYNC_CLK_SRC_SHIFT 0 /* ASYNC_CLK_SRC - [3:0] */ +#define ARIZONA_ASYNC_CLK_SRC_WIDTH 4 /* ASYNC_CLK_SRC - [3:0] */ + +/* + * R275 (0x113) - Async sample rate 1 + */ +#define ARIZONA_ASYNC_SAMPLE_RATE_MASK 0x001F /* ASYNC_SAMPLE_RATE - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_SHIFT 0 /* ASYNC_SAMPLE_RATE - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_WIDTH 5 /* ASYNC_SAMPLE_RATE - [4:0] */ + +/* + * R283 (0x11B) - Async sample rate 1 status + */ +#define ARIZONA_ASYNC_SAMPLE_RATE_STS_MASK 0x001F /* ASYNC_SAMPLE_RATE_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_STS_SHIFT 0 /* ASYNC_SAMPLE_RATE_STS - [4:0] */ +#define ARIZONA_ASYNC_SAMPLE_RATE_STS_WIDTH 5 /* ASYNC_SAMPLE_RATE_STS - [4:0] */ + +/* + * R329 (0x149) - Output system clock + */ +#define ARIZONA_OPCLK_ENA 0x8000 /* OPCLK_ENA */ +#define ARIZONA_OPCLK_ENA_MASK 0x8000 /* OPCLK_ENA */ +#define ARIZONA_OPCLK_ENA_SHIFT 15 /* OPCLK_ENA */ +#define ARIZONA_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ +#define ARIZONA_OPCLK_DIV_MASK 0x00F8 /* OPCLK_DIV - [7:3] */ +#define ARIZONA_OPCLK_DIV_SHIFT 3 /* OPCLK_DIV - [7:3] */ +#define ARIZONA_OPCLK_DIV_WIDTH 5 /* OPCLK_DIV - [7:3] */ +#define ARIZONA_OPCLK_SEL_MASK 0x0007 /* OPCLK_SEL - [2:0] */ +#define ARIZONA_OPCLK_SEL_SHIFT 0 /* OPCLK_SEL - [2:0] */ +#define ARIZONA_OPCLK_SEL_WIDTH 3 /* OPCLK_SEL - [2:0] */ + +/* + * R330 (0x14A) - Output async clock + */ +#define ARIZONA_OPCLK_ASYNC_ENA 0x8000 /* OPCLK_ASYNC_ENA */ +#define ARIZONA_OPCLK_ASYNC_ENA_MASK 0x8000 /* OPCLK_ASYNC_ENA */ +#define ARIZONA_OPCLK_ASYNC_ENA_SHIFT 15 /* OPCLK_ASYNC_ENA */ +#define ARIZONA_OPCLK_ASYNC_ENA_WIDTH 1 /* OPCLK_ASYNC_ENA */ +#define ARIZONA_OPCLK_ASYNC_DIV_MASK 0x00F8 /* OPCLK_ASYNC_DIV - [7:3] */ +#define ARIZONA_OPCLK_ASYNC_DIV_SHIFT 3 /* OPCLK_ASYNC_DIV - [7:3] */ +#define ARIZONA_OPCLK_ASYNC_DIV_WIDTH 5 /* OPCLK_ASYNC_DIV - [7:3] */ +#define ARIZONA_OPCLK_ASYNC_SEL_MASK 0x0007 /* OPCLK_ASYNC_SEL - [2:0] */ +#define ARIZONA_OPCLK_ASYNC_SEL_SHIFT 0 /* OPCLK_ASYNC_SEL - [2:0] */ +#define ARIZONA_OPCLK_ASYNC_SEL_WIDTH 3 /* OPCLK_ASYNC_SEL - [2:0] */ + +/* + * R338 (0x152) - Rate Estimator 1 + */ +#define ARIZONA_TRIG_ON_STARTUP 0x0010 /* TRIG_ON_STARTUP */ +#define ARIZONA_TRIG_ON_STARTUP_MASK 0x0010 /* TRIG_ON_STARTUP */ +#define ARIZONA_TRIG_ON_STARTUP_SHIFT 4 /* TRIG_ON_STARTUP */ +#define ARIZONA_TRIG_ON_STARTUP_WIDTH 1 /* TRIG_ON_STARTUP */ +#define ARIZONA_LRCLK_SRC_MASK 0x000E /* LRCLK_SRC - [3:1] */ +#define ARIZONA_LRCLK_SRC_SHIFT 1 /* LRCLK_SRC - [3:1] */ +#define ARIZONA_LRCLK_SRC_WIDTH 3 /* LRCLK_SRC - [3:1] */ +#define ARIZONA_RATE_EST_ENA 0x0001 /* RATE_EST_ENA */ +#define ARIZONA_RATE_EST_ENA_MASK 0x0001 /* RATE_EST_ENA */ +#define ARIZONA_RATE_EST_ENA_SHIFT 0 /* RATE_EST_ENA */ +#define ARIZONA_RATE_EST_ENA_WIDTH 1 /* RATE_EST_ENA */ + +/* + * R339 (0x153) - Rate Estimator 2 + */ +#define ARIZONA_SAMPLE_RATE_DETECT_A_MASK 0x001F /* SAMPLE_RATE_DETECT_A - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_A_SHIFT 0 /* SAMPLE_RATE_DETECT_A - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_A_WIDTH 5 /* SAMPLE_RATE_DETECT_A - [4:0] */ + +/* + * R340 (0x154) - Rate Estimator 3 + */ +#define ARIZONA_SAMPLE_RATE_DETECT_B_MASK 0x001F /* SAMPLE_RATE_DETECT_B - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_B_SHIFT 0 /* SAMPLE_RATE_DETECT_B - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_B_WIDTH 5 /* SAMPLE_RATE_DETECT_B - [4:0] */ + +/* + * R341 (0x155) - Rate Estimator 4 + */ +#define ARIZONA_SAMPLE_RATE_DETECT_C_MASK 0x001F /* SAMPLE_RATE_DETECT_C - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_C_SHIFT 0 /* SAMPLE_RATE_DETECT_C - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_C_WIDTH 5 /* SAMPLE_RATE_DETECT_C - [4:0] */ + +/* + * R342 (0x156) - Rate Estimator 5 + */ +#define ARIZONA_SAMPLE_RATE_DETECT_D_MASK 0x001F /* SAMPLE_RATE_DETECT_D - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT 0 /* SAMPLE_RATE_DETECT_D - [4:0] */ +#define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH 5 /* SAMPLE_RATE_DETECT_D - [4:0] */ + +/* + * R369 (0x171) - FLL1 Control 1 + */ +#define ARIZONA_FLL1_FREERUN 0x0002 /* FLL1_FREERUN */ +#define ARIZONA_FLL1_FREERUN_MASK 0x0002 /* FLL1_FREERUN */ +#define ARIZONA_FLL1_FREERUN_SHIFT 1 /* FLL1_FREERUN */ +#define ARIZONA_FLL1_FREERUN_WIDTH 1 /* FLL1_FREERUN */ +#define ARIZONA_FLL1_ENA 0x0001 /* FLL1_ENA */ +#define ARIZONA_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */ +#define ARIZONA_FLL1_ENA_SHIFT 0 /* FLL1_ENA */ +#define ARIZONA_FLL1_ENA_WIDTH 1 /* FLL1_ENA */ + +/* + * R370 (0x172) - FLL1 Control 2 + */ +#define ARIZONA_FLL1_CTRL_UPD 0x8000 /* FLL1_CTRL_UPD */ +#define ARIZONA_FLL1_CTRL_UPD_MASK 0x8000 /* FLL1_CTRL_UPD */ +#define ARIZONA_FLL1_CTRL_UPD_SHIFT 15 /* FLL1_CTRL_UPD */ +#define ARIZONA_FLL1_CTRL_UPD_WIDTH 1 /* FLL1_CTRL_UPD */ +#define ARIZONA_FLL1_N_MASK 0x03FF /* FLL1_N - [9:0] */ +#define ARIZONA_FLL1_N_SHIFT 0 /* FLL1_N - [9:0] */ +#define ARIZONA_FLL1_N_WIDTH 10 /* FLL1_N - [9:0] */ + +/* + * R371 (0x173) - FLL1 Control 3 + */ +#define ARIZONA_FLL1_THETA_MASK 0xFFFF /* FLL1_THETA - [15:0] */ +#define ARIZONA_FLL1_THETA_SHIFT 0 /* FLL1_THETA - [15:0] */ +#define ARIZONA_FLL1_THETA_WIDTH 16 /* FLL1_THETA - [15:0] */ + +/* + * R372 (0x174) - FLL1 Control 4 + */ +#define ARIZONA_FLL1_LAMBDA_MASK 0xFFFF /* FLL1_LAMBDA - [15:0] */ +#define ARIZONA_FLL1_LAMBDA_SHIFT 0 /* FLL1_LAMBDA - [15:0] */ +#define ARIZONA_FLL1_LAMBDA_WIDTH 16 /* FLL1_LAMBDA - [15:0] */ + +/* + * R373 (0x175) - FLL1 Control 5 + */ +#define ARIZONA_FLL1_FRATIO_MASK 0x0700 /* FLL1_FRATIO - [10:8] */ +#define ARIZONA_FLL1_FRATIO_SHIFT 8 /* FLL1_FRATIO - [10:8] */ +#define ARIZONA_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [10:8] */ +#define ARIZONA_FLL1_OUTDIV_MASK 0x000E /* FLL1_OUTDIV - [3:1] */ +#define ARIZONA_FLL1_OUTDIV_SHIFT 1 /* FLL1_OUTDIV - [3:1] */ +#define ARIZONA_FLL1_OUTDIV_WIDTH 3 /* FLL1_OUTDIV - [3:1] */ + +/* + * R374 (0x176) - FLL1 Control 6 + */ +#define ARIZONA_FLL1_CLK_REF_DIV_MASK 0x00C0 /* FLL1_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_REF_DIV_SHIFT 6 /* FLL1_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_REF_DIV_WIDTH 2 /* FLL1_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_REF_SRC_MASK 0x000F /* FLL1_CLK_REF_SRC - [3:0] */ +#define ARIZONA_FLL1_CLK_REF_SRC_SHIFT 0 /* FLL1_CLK_REF_SRC - [3:0] */ +#define ARIZONA_FLL1_CLK_REF_SRC_WIDTH 4 /* FLL1_CLK_REF_SRC - [3:0] */ + +/* + * R375 (0x177) - FLL1 Loop Filter Test 1 + */ +#define ARIZONA_FLL1_FRC_INTEG_UPD 0x8000 /* FLL1_FRC_INTEG_UPD */ +#define ARIZONA_FLL1_FRC_INTEG_UPD_MASK 0x8000 /* FLL1_FRC_INTEG_UPD */ +#define ARIZONA_FLL1_FRC_INTEG_UPD_SHIFT 15 /* FLL1_FRC_INTEG_UPD */ +#define ARIZONA_FLL1_FRC_INTEG_UPD_WIDTH 1 /* FLL1_FRC_INTEG_UPD */ +#define ARIZONA_FLL1_FRC_INTEG_VAL_MASK 0x0FFF /* FLL1_FRC_INTEG_VAL - [11:0] */ +#define ARIZONA_FLL1_FRC_INTEG_VAL_SHIFT 0 /* FLL1_FRC_INTEG_VAL - [11:0] */ +#define ARIZONA_FLL1_FRC_INTEG_VAL_WIDTH 12 /* FLL1_FRC_INTEG_VAL - [11:0] */ + +/* + * R385 (0x181) - FLL1 Synchroniser 1 + */ +#define ARIZONA_FLL1_SYNC_ENA 0x0001 /* FLL1_SYNC_ENA */ +#define ARIZONA_FLL1_SYNC_ENA_MASK 0x0001 /* FLL1_SYNC_ENA */ +#define ARIZONA_FLL1_SYNC_ENA_SHIFT 0 /* FLL1_SYNC_ENA */ +#define ARIZONA_FLL1_SYNC_ENA_WIDTH 1 /* FLL1_SYNC_ENA */ + +/* + * R386 (0x182) - FLL1 Synchroniser 2 + */ +#define ARIZONA_FLL1_SYNC_N_MASK 0x03FF /* FLL1_SYNC_N - [9:0] */ +#define ARIZONA_FLL1_SYNC_N_SHIFT 0 /* FLL1_SYNC_N - [9:0] */ +#define ARIZONA_FLL1_SYNC_N_WIDTH 10 /* FLL1_SYNC_N - [9:0] */ + +/* + * R387 (0x183) - FLL1 Synchroniser 3 + */ +#define ARIZONA_FLL1_SYNC_THETA_MASK 0xFFFF /* FLL1_SYNC_THETA - [15:0] */ +#define ARIZONA_FLL1_SYNC_THETA_SHIFT 0 /* FLL1_SYNC_THETA - [15:0] */ +#define ARIZONA_FLL1_SYNC_THETA_WIDTH 16 /* FLL1_SYNC_THETA - [15:0] */ + +/* + * R388 (0x184) - FLL1 Synchroniser 4 + */ +#define ARIZONA_FLL1_SYNC_LAMBDA_MASK 0xFFFF /* FLL1_SYNC_LAMBDA - [15:0] */ +#define ARIZONA_FLL1_SYNC_LAMBDA_SHIFT 0 /* FLL1_SYNC_LAMBDA - [15:0] */ +#define ARIZONA_FLL1_SYNC_LAMBDA_WIDTH 16 /* FLL1_SYNC_LAMBDA - [15:0] */ + +/* + * R389 (0x185) - FLL1 Synchroniser 5 + */ +#define ARIZONA_FLL1_SYNC_FRATIO_MASK 0x0700 /* FLL1_SYNC_FRATIO - [10:8] */ +#define ARIZONA_FLL1_SYNC_FRATIO_SHIFT 8 /* FLL1_SYNC_FRATIO - [10:8] */ +#define ARIZONA_FLL1_SYNC_FRATIO_WIDTH 3 /* FLL1_SYNC_FRATIO - [10:8] */ + +/* + * R390 (0x186) - FLL1 Synchroniser 6 + */ +#define ARIZONA_FLL1_CLK_SYNC_DIV_MASK 0x00C0 /* FLL1_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_SYNC_DIV_SHIFT 6 /* FLL1_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_SYNC_DIV_WIDTH 2 /* FLL1_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL1_CLK_SYNC_SRC_MASK 0x000F /* FLL1_CLK_SYNC_SRC - [3:0] */ +#define ARIZONA_FLL1_CLK_SYNC_SRC_SHIFT 0 /* FLL1_CLK_SYNC_SRC - [3:0] */ +#define ARIZONA_FLL1_CLK_SYNC_SRC_WIDTH 4 /* FLL1_CLK_SYNC_SRC - [3:0] */ + +/* + * R393 (0x189) - FLL1 Spread Spectrum + */ +#define ARIZONA_FLL1_SS_AMPL_MASK 0x0030 /* FLL1_SS_AMPL - [5:4] */ +#define ARIZONA_FLL1_SS_AMPL_SHIFT 4 /* FLL1_SS_AMPL - [5:4] */ +#define ARIZONA_FLL1_SS_AMPL_WIDTH 2 /* FLL1_SS_AMPL - [5:4] */ +#define ARIZONA_FLL1_SS_FREQ_MASK 0x000C /* FLL1_SS_FREQ - [3:2] */ +#define ARIZONA_FLL1_SS_FREQ_SHIFT 2 /* FLL1_SS_FREQ - [3:2] */ +#define ARIZONA_FLL1_SS_FREQ_WIDTH 2 /* FLL1_SS_FREQ - [3:2] */ +#define ARIZONA_FLL1_SS_SEL_MASK 0x0003 /* FLL1_SS_SEL - [1:0] */ +#define ARIZONA_FLL1_SS_SEL_SHIFT 0 /* FLL1_SS_SEL - [1:0] */ +#define ARIZONA_FLL1_SS_SEL_WIDTH 2 /* FLL1_SS_SEL - [1:0] */ + +/* + * R394 (0x18A) - FLL1 GPIO Clock + */ +#define ARIZONA_FLL1_GPDIV_MASK 0x00FE /* FLL1_GPDIV - [7:1] */ +#define ARIZONA_FLL1_GPDIV_SHIFT 1 /* FLL1_GPDIV - [7:1] */ +#define ARIZONA_FLL1_GPDIV_WIDTH 7 /* FLL1_GPDIV - [7:1] */ +#define ARIZONA_FLL1_GPDIV_ENA 0x0001 /* FLL1_GPDIV_ENA */ +#define ARIZONA_FLL1_GPDIV_ENA_MASK 0x0001 /* FLL1_GPDIV_ENA */ +#define ARIZONA_FLL1_GPDIV_ENA_SHIFT 0 /* FLL1_GPDIV_ENA */ +#define ARIZONA_FLL1_GPDIV_ENA_WIDTH 1 /* FLL1_GPDIV_ENA */ + +/* + * R401 (0x191) - FLL2 Control 1 + */ +#define ARIZONA_FLL2_FREERUN 0x0002 /* FLL2_FREERUN */ +#define ARIZONA_FLL2_FREERUN_MASK 0x0002 /* FLL2_FREERUN */ +#define ARIZONA_FLL2_FREERUN_SHIFT 1 /* FLL2_FREERUN */ +#define ARIZONA_FLL2_FREERUN_WIDTH 1 /* FLL2_FREERUN */ +#define ARIZONA_FLL2_ENA 0x0001 /* FLL2_ENA */ +#define ARIZONA_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */ +#define ARIZONA_FLL2_ENA_SHIFT 0 /* FLL2_ENA */ +#define ARIZONA_FLL2_ENA_WIDTH 1 /* FLL2_ENA */ + +/* + * R402 (0x192) - FLL2 Control 2 + */ +#define ARIZONA_FLL2_CTRL_UPD 0x8000 /* FLL2_CTRL_UPD */ +#define ARIZONA_FLL2_CTRL_UPD_MASK 0x8000 /* FLL2_CTRL_UPD */ +#define ARIZONA_FLL2_CTRL_UPD_SHIFT 15 /* FLL2_CTRL_UPD */ +#define ARIZONA_FLL2_CTRL_UPD_WIDTH 1 /* FLL2_CTRL_UPD */ +#define ARIZONA_FLL2_N_MASK 0x03FF /* FLL2_N - [9:0] */ +#define ARIZONA_FLL2_N_SHIFT 0 /* FLL2_N - [9:0] */ +#define ARIZONA_FLL2_N_WIDTH 10 /* FLL2_N - [9:0] */ + +/* + * R403 (0x193) - FLL2 Control 3 + */ +#define ARIZONA_FLL2_THETA_MASK 0xFFFF /* FLL2_THETA - [15:0] */ +#define ARIZONA_FLL2_THETA_SHIFT 0 /* FLL2_THETA - [15:0] */ +#define ARIZONA_FLL2_THETA_WIDTH 16 /* FLL2_THETA - [15:0] */ + +/* + * R404 (0x194) - FLL2 Control 4 + */ +#define ARIZONA_FLL2_LAMBDA_MASK 0xFFFF /* FLL2_LAMBDA - [15:0] */ +#define ARIZONA_FLL2_LAMBDA_SHIFT 0 /* FLL2_LAMBDA - [15:0] */ +#define ARIZONA_FLL2_LAMBDA_WIDTH 16 /* FLL2_LAMBDA - [15:0] */ + +/* + * R405 (0x195) - FLL2 Control 5 + */ +#define ARIZONA_FLL2_FRATIO_MASK 0x0700 /* FLL2_FRATIO - [10:8] */ +#define ARIZONA_FLL2_FRATIO_SHIFT 8 /* FLL2_FRATIO - [10:8] */ +#define ARIZONA_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [10:8] */ +#define ARIZONA_FLL2_OUTDIV_MASK 0x000E /* FLL2_OUTDIV - [3:1] */ +#define ARIZONA_FLL2_OUTDIV_SHIFT 1 /* FLL2_OUTDIV - [3:1] */ +#define ARIZONA_FLL2_OUTDIV_WIDTH 3 /* FLL2_OUTDIV - [3:1] */ + +/* + * R406 (0x196) - FLL2 Control 6 + */ +#define ARIZONA_FLL2_CLK_REF_DIV_MASK 0x00C0 /* FLL2_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_REF_DIV_SHIFT 6 /* FLL2_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_REF_DIV_WIDTH 2 /* FLL2_CLK_REF_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_REF_SRC_MASK 0x000F /* FLL2_CLK_REF_SRC - [3:0] */ +#define ARIZONA_FLL2_CLK_REF_SRC_SHIFT 0 /* FLL2_CLK_REF_SRC - [3:0] */ +#define ARIZONA_FLL2_CLK_REF_SRC_WIDTH 4 /* FLL2_CLK_REF_SRC - [3:0] */ + +/* + * R407 (0x197) - FLL2 Loop Filter Test 1 + */ +#define ARIZONA_FLL2_FRC_INTEG_UPD 0x8000 /* FLL2_FRC_INTEG_UPD */ +#define ARIZONA_FLL2_FRC_INTEG_UPD_MASK 0x8000 /* FLL2_FRC_INTEG_UPD */ +#define ARIZONA_FLL2_FRC_INTEG_UPD_SHIFT 15 /* FLL2_FRC_INTEG_UPD */ +#define ARIZONA_FLL2_FRC_INTEG_UPD_WIDTH 1 /* FLL2_FRC_INTEG_UPD */ +#define ARIZONA_FLL2_FRC_INTEG_VAL_MASK 0x0FFF /* FLL2_FRC_INTEG_VAL - [11:0] */ +#define ARIZONA_FLL2_FRC_INTEG_VAL_SHIFT 0 /* FLL2_FRC_INTEG_VAL - [11:0] */ +#define ARIZONA_FLL2_FRC_INTEG_VAL_WIDTH 12 /* FLL2_FRC_INTEG_VAL - [11:0] */ + +/* + * R417 (0x1A1) - FLL2 Synchroniser 1 + */ +#define ARIZONA_FLL2_SYNC_ENA 0x0001 /* FLL2_SYNC_ENA */ +#define ARIZONA_FLL2_SYNC_ENA_MASK 0x0001 /* FLL2_SYNC_ENA */ +#define ARIZONA_FLL2_SYNC_ENA_SHIFT 0 /* FLL2_SYNC_ENA */ +#define ARIZONA_FLL2_SYNC_ENA_WIDTH 1 /* FLL2_SYNC_ENA */ + +/* + * R418 (0x1A2) - FLL2 Synchroniser 2 + */ +#define ARIZONA_FLL2_SYNC_N_MASK 0x03FF /* FLL2_SYNC_N - [9:0] */ +#define ARIZONA_FLL2_SYNC_N_SHIFT 0 /* FLL2_SYNC_N - [9:0] */ +#define ARIZONA_FLL2_SYNC_N_WIDTH 10 /* FLL2_SYNC_N - [9:0] */ + +/* + * R419 (0x1A3) - FLL2 Synchroniser 3 + */ +#define ARIZONA_FLL2_SYNC_THETA_MASK 0xFFFF /* FLL2_SYNC_THETA - [15:0] */ +#define ARIZONA_FLL2_SYNC_THETA_SHIFT 0 /* FLL2_SYNC_THETA - [15:0] */ +#define ARIZONA_FLL2_SYNC_THETA_WIDTH 16 /* FLL2_SYNC_THETA - [15:0] */ + +/* + * R420 (0x1A4) - FLL2 Synchroniser 4 + */ +#define ARIZONA_FLL2_SYNC_LAMBDA_MASK 0xFFFF /* FLL2_SYNC_LAMBDA - [15:0] */ +#define ARIZONA_FLL2_SYNC_LAMBDA_SHIFT 0 /* FLL2_SYNC_LAMBDA - [15:0] */ +#define ARIZONA_FLL2_SYNC_LAMBDA_WIDTH 16 /* FLL2_SYNC_LAMBDA - [15:0] */ + +/* + * R421 (0x1A5) - FLL2 Synchroniser 5 + */ +#define ARIZONA_FLL2_SYNC_FRATIO_MASK 0x0700 /* FLL2_SYNC_FRATIO - [10:8] */ +#define ARIZONA_FLL2_SYNC_FRATIO_SHIFT 8 /* FLL2_SYNC_FRATIO - [10:8] */ +#define ARIZONA_FLL2_SYNC_FRATIO_WIDTH 3 /* FLL2_SYNC_FRATIO - [10:8] */ + +/* + * R422 (0x1A6) - FLL2 Synchroniser 6 + */ +#define ARIZONA_FLL2_CLK_SYNC_DIV_MASK 0x00C0 /* FLL2_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_SYNC_DIV_SHIFT 6 /* FLL2_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_SYNC_DIV_WIDTH 2 /* FLL2_CLK_SYNC_DIV - [7:6] */ +#define ARIZONA_FLL2_CLK_SYNC_SRC_MASK 0x000F /* FLL2_CLK_SYNC_SRC - [3:0] */ +#define ARIZONA_FLL2_CLK_SYNC_SRC_SHIFT 0 /* FLL2_CLK_SYNC_SRC - [3:0] */ +#define ARIZONA_FLL2_CLK_SYNC_SRC_WIDTH 4 /* FLL2_CLK_SYNC_SRC - [3:0] */ + +/* + * R425 (0x1A9) - FLL2 Spread Spectrum + */ +#define ARIZONA_FLL2_SS_AMPL_MASK 0x0030 /* FLL2_SS_AMPL - [5:4] */ +#define ARIZONA_FLL2_SS_AMPL_SHIFT 4 /* FLL2_SS_AMPL - [5:4] */ +#define ARIZONA_FLL2_SS_AMPL_WIDTH 2 /* FLL2_SS_AMPL - [5:4] */ +#define ARIZONA_FLL2_SS_FREQ_MASK 0x000C /* FLL2_SS_FREQ - [3:2] */ +#define ARIZONA_FLL2_SS_FREQ_SHIFT 2 /* FLL2_SS_FREQ - [3:2] */ +#define ARIZONA_FLL2_SS_FREQ_WIDTH 2 /* FLL2_SS_FREQ - [3:2] */ +#define ARIZONA_FLL2_SS_SEL_MASK 0x0003 /* FLL2_SS_SEL - [1:0] */ +#define ARIZONA_FLL2_SS_SEL_SHIFT 0 /* FLL2_SS_SEL - [1:0] */ +#define ARIZONA_FLL2_SS_SEL_WIDTH 2 /* FLL2_SS_SEL - [1:0] */ + +/* + * R426 (0x1AA) - FLL2 GPIO Clock + */ +#define ARIZONA_FLL2_GPDIV_MASK 0x00FE /* FLL2_GPDIV - [7:1] */ +#define ARIZONA_FLL2_GPDIV_SHIFT 1 /* FLL2_GPDIV - [7:1] */ +#define ARIZONA_FLL2_GPDIV_WIDTH 7 /* FLL2_GPDIV - [7:1] */ +#define ARIZONA_FLL2_GPDIV_ENA 0x0001 /* FLL2_GPDIV_ENA */ +#define ARIZONA_FLL2_GPDIV_ENA_MASK 0x0001 /* FLL2_GPDIV_ENA */ +#define ARIZONA_FLL2_GPDIV_ENA_SHIFT 0 /* FLL2_GPDIV_ENA */ +#define ARIZONA_FLL2_GPDIV_ENA_WIDTH 1 /* FLL2_GPDIV_ENA */ + +/* + * R512 (0x200) - Mic Charge Pump 1 + */ +#define ARIZONA_CPMIC_DISCH 0x0004 /* CPMIC_DISCH */ +#define ARIZONA_CPMIC_DISCH_MASK 0x0004 /* CPMIC_DISCH */ +#define ARIZONA_CPMIC_DISCH_SHIFT 2 /* CPMIC_DISCH */ +#define ARIZONA_CPMIC_DISCH_WIDTH 1 /* CPMIC_DISCH */ +#define ARIZONA_CPMIC_BYPASS 0x0002 /* CPMIC_BYPASS */ +#define ARIZONA_CPMIC_BYPASS_MASK 0x0002 /* CPMIC_BYPASS */ +#define ARIZONA_CPMIC_BYPASS_SHIFT 1 /* CPMIC_BYPASS */ +#define ARIZONA_CPMIC_BYPASS_WIDTH 1 /* CPMIC_BYPASS */ +#define ARIZONA_CPMIC_ENA 0x0001 /* CPMIC_ENA */ +#define ARIZONA_CPMIC_ENA_MASK 0x0001 /* CPMIC_ENA */ +#define ARIZONA_CPMIC_ENA_SHIFT 0 /* CPMIC_ENA */ +#define ARIZONA_CPMIC_ENA_WIDTH 1 /* CPMIC_ENA */ + +/* + * R528 (0x210) - LDO1 Control 1 + */ +#define ARIZONA_LDO1_VSEL_MASK 0x07E0 /* LDO1_VSEL - [10:5] */ +#define ARIZONA_LDO1_VSEL_SHIFT 5 /* LDO1_VSEL - [10:5] */ +#define ARIZONA_LDO1_VSEL_WIDTH 6 /* LDO1_VSEL - [10:5] */ +#define ARIZONA_LDO1_FAST 0x0010 /* LDO1_FAST */ +#define ARIZONA_LDO1_FAST_MASK 0x0010 /* LDO1_FAST */ +#define ARIZONA_LDO1_FAST_SHIFT 4 /* LDO1_FAST */ +#define ARIZONA_LDO1_FAST_WIDTH 1 /* LDO1_FAST */ +#define ARIZONA_LDO1_DISCH 0x0004 /* LDO1_DISCH */ +#define ARIZONA_LDO1_DISCH_MASK 0x0004 /* LDO1_DISCH */ +#define ARIZONA_LDO1_DISCH_SHIFT 2 /* LDO1_DISCH */ +#define ARIZONA_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */ +#define ARIZONA_LDO1_BYPASS 0x0002 /* LDO1_BYPASS */ +#define ARIZONA_LDO1_BYPASS_MASK 0x0002 /* LDO1_BYPASS */ +#define ARIZONA_LDO1_BYPASS_SHIFT 1 /* LDO1_BYPASS */ +#define ARIZONA_LDO1_BYPASS_WIDTH 1 /* LDO1_BYPASS */ +#define ARIZONA_LDO1_ENA 0x0001 /* LDO1_ENA */ +#define ARIZONA_LDO1_ENA_MASK 0x0001 /* LDO1_ENA */ +#define ARIZONA_LDO1_ENA_SHIFT 0 /* LDO1_ENA */ +#define ARIZONA_LDO1_ENA_WIDTH 1 /* LDO1_ENA */ + +/* + * R531 (0x213) - LDO2 Control 1 + */ +#define ARIZONA_LDO2_VSEL_MASK 0x07E0 /* LDO2_VSEL - [10:5] */ +#define ARIZONA_LDO2_VSEL_SHIFT 5 /* LDO2_VSEL - [10:5] */ +#define ARIZONA_LDO2_VSEL_WIDTH 6 /* LDO2_VSEL - [10:5] */ +#define ARIZONA_LDO2_FAST 0x0010 /* LDO2_FAST */ +#define ARIZONA_LDO2_FAST_MASK 0x0010 /* LDO2_FAST */ +#define ARIZONA_LDO2_FAST_SHIFT 4 /* LDO2_FAST */ +#define ARIZONA_LDO2_FAST_WIDTH 1 /* LDO2_FAST */ +#define ARIZONA_LDO2_DISCH 0x0004 /* LDO2_DISCH */ +#define ARIZONA_LDO2_DISCH_MASK 0x0004 /* LDO2_DISCH */ +#define ARIZONA_LDO2_DISCH_SHIFT 2 /* LDO2_DISCH */ +#define ARIZONA_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */ +#define ARIZONA_LDO2_BYPASS 0x0002 /* LDO2_BYPASS */ +#define ARIZONA_LDO2_BYPASS_MASK 0x0002 /* LDO2_BYPASS */ +#define ARIZONA_LDO2_BYPASS_SHIFT 1 /* LDO2_BYPASS */ +#define ARIZONA_LDO2_BYPASS_WIDTH 1 /* LDO2_BYPASS */ +#define ARIZONA_LDO2_ENA 0x0001 /* LDO2_ENA */ +#define ARIZONA_LDO2_ENA_MASK 0x0001 /* LDO2_ENA */ +#define ARIZONA_LDO2_ENA_SHIFT 0 /* LDO2_ENA */ +#define ARIZONA_LDO2_ENA_WIDTH 1 /* LDO2_ENA */ + +/* + * R536 (0x218) - Mic Bias Ctrl 1 + */ +#define ARIZONA_MICB1_EXT_CAP 0x8000 /* MICB1_EXT_CAP */ +#define ARIZONA_MICB1_EXT_CAP_MASK 0x8000 /* MICB1_EXT_CAP */ +#define ARIZONA_MICB1_EXT_CAP_SHIFT 15 /* MICB1_EXT_CAP */ +#define ARIZONA_MICB1_EXT_CAP_WIDTH 1 /* MICB1_EXT_CAP */ +#define ARIZONA_MICB1_LVL_MASK 0x01E0 /* MICB1_LVL - [8:5] */ +#define ARIZONA_MICB1_LVL_SHIFT 5 /* MICB1_LVL - [8:5] */ +#define ARIZONA_MICB1_LVL_WIDTH 4 /* MICB1_LVL - [8:5] */ +#define ARIZONA_MICB1_FAST 0x0010 /* MICB1_FAST */ +#define ARIZONA_MICB1_FAST_MASK 0x0010 /* MICB1_FAST */ +#define ARIZONA_MICB1_FAST_SHIFT 4 /* MICB1_FAST */ +#define ARIZONA_MICB1_FAST_WIDTH 1 /* MICB1_FAST */ +#define ARIZONA_MICB1_RATE 0x0008 /* MICB1_RATE */ +#define ARIZONA_MICB1_RATE_MASK 0x0008 /* MICB1_RATE */ +#define ARIZONA_MICB1_RATE_SHIFT 3 /* MICB1_RATE */ +#define ARIZONA_MICB1_RATE_WIDTH 1 /* MICB1_RATE */ +#define ARIZONA_MICB1_DISCH 0x0004 /* MICB1_DISCH */ +#define ARIZONA_MICB1_DISCH_MASK 0x0004 /* MICB1_DISCH */ +#define ARIZONA_MICB1_DISCH_SHIFT 2 /* MICB1_DISCH */ +#define ARIZONA_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */ +#define ARIZONA_MICB1_BYPASS 0x0002 /* MICB1_BYPASS */ +#define ARIZONA_MICB1_BYPASS_MASK 0x0002 /* MICB1_BYPASS */ +#define ARIZONA_MICB1_BYPASS_SHIFT 1 /* MICB1_BYPASS */ +#define ARIZONA_MICB1_BYPASS_WIDTH 1 /* MICB1_BYPASS */ +#define ARIZONA_MICB1_ENA 0x0001 /* MICB1_ENA */ +#define ARIZONA_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */ +#define ARIZONA_MICB1_ENA_SHIFT 0 /* MICB1_ENA */ +#define ARIZONA_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ + +/* + * R537 (0x219) - Mic Bias Ctrl 2 + */ +#define ARIZONA_MICB2_EXT_CAP 0x8000 /* MICB2_EXT_CAP */ +#define ARIZONA_MICB2_EXT_CAP_MASK 0x8000 /* MICB2_EXT_CAP */ +#define ARIZONA_MICB2_EXT_CAP_SHIFT 15 /* MICB2_EXT_CAP */ +#define ARIZONA_MICB2_EXT_CAP_WIDTH 1 /* MICB2_EXT_CAP */ +#define ARIZONA_MICB2_LVL_MASK 0x01E0 /* MICB2_LVL - [8:5] */ +#define ARIZONA_MICB2_LVL_SHIFT 5 /* MICB2_LVL - [8:5] */ +#define ARIZONA_MICB2_LVL_WIDTH 4 /* MICB2_LVL - [8:5] */ +#define ARIZONA_MICB2_FAST 0x0010 /* MICB2_FAST */ +#define ARIZONA_MICB2_FAST_MASK 0x0010 /* MICB2_FAST */ +#define ARIZONA_MICB2_FAST_SHIFT 4 /* MICB2_FAST */ +#define ARIZONA_MICB2_FAST_WIDTH 1 /* MICB2_FAST */ +#define ARIZONA_MICB2_RATE 0x0008 /* MICB2_RATE */ +#define ARIZONA_MICB2_RATE_MASK 0x0008 /* MICB2_RATE */ +#define ARIZONA_MICB2_RATE_SHIFT 3 /* MICB2_RATE */ +#define ARIZONA_MICB2_RATE_WIDTH 1 /* MICB2_RATE */ +#define ARIZONA_MICB2_DISCH 0x0004 /* MICB2_DISCH */ +#define ARIZONA_MICB2_DISCH_MASK 0x0004 /* MICB2_DISCH */ +#define ARIZONA_MICB2_DISCH_SHIFT 2 /* MICB2_DISCH */ +#define ARIZONA_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */ +#define ARIZONA_MICB2_BYPASS 0x0002 /* MICB2_BYPASS */ +#define ARIZONA_MICB2_BYPASS_MASK 0x0002 /* MICB2_BYPASS */ +#define ARIZONA_MICB2_BYPASS_SHIFT 1 /* MICB2_BYPASS */ +#define ARIZONA_MICB2_BYPASS_WIDTH 1 /* MICB2_BYPASS */ +#define ARIZONA_MICB2_ENA 0x0001 /* MICB2_ENA */ +#define ARIZONA_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */ +#define ARIZONA_MICB2_ENA_SHIFT 0 /* MICB2_ENA */ +#define ARIZONA_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ + +/* + * R538 (0x21A) - Mic Bias Ctrl 3 + */ +#define ARIZONA_MICB3_EXT_CAP 0x8000 /* MICB3_EXT_CAP */ +#define ARIZONA_MICB3_EXT_CAP_MASK 0x8000 /* MICB3_EXT_CAP */ +#define ARIZONA_MICB3_EXT_CAP_SHIFT 15 /* MICB3_EXT_CAP */ +#define ARIZONA_MICB3_EXT_CAP_WIDTH 1 /* MICB3_EXT_CAP */ +#define ARIZONA_MICB3_LVL_MASK 0x01E0 /* MICB3_LVL - [8:5] */ +#define ARIZONA_MICB3_LVL_SHIFT 5 /* MICB3_LVL - [8:5] */ +#define ARIZONA_MICB3_LVL_WIDTH 4 /* MICB3_LVL - [8:5] */ +#define ARIZONA_MICB3_FAST 0x0010 /* MICB3_FAST */ +#define ARIZONA_MICB3_FAST_MASK 0x0010 /* MICB3_FAST */ +#define ARIZONA_MICB3_FAST_SHIFT 4 /* MICB3_FAST */ +#define ARIZONA_MICB3_FAST_WIDTH 1 /* MICB3_FAST */ +#define ARIZONA_MICB3_RATE 0x0008 /* MICB3_RATE */ +#define ARIZONA_MICB3_RATE_MASK 0x0008 /* MICB3_RATE */ +#define ARIZONA_MICB3_RATE_SHIFT 3 /* MICB3_RATE */ +#define ARIZONA_MICB3_RATE_WIDTH 1 /* MICB3_RATE */ +#define ARIZONA_MICB3_DISCH 0x0004 /* MICB3_DISCH */ +#define ARIZONA_MICB3_DISCH_MASK 0x0004 /* MICB3_DISCH */ +#define ARIZONA_MICB3_DISCH_SHIFT 2 /* MICB3_DISCH */ +#define ARIZONA_MICB3_DISCH_WIDTH 1 /* MICB3_DISCH */ +#define ARIZONA_MICB3_BYPASS 0x0002 /* MICB3_BYPASS */ +#define ARIZONA_MICB3_BYPASS_MASK 0x0002 /* MICB3_BYPASS */ +#define ARIZONA_MICB3_BYPASS_SHIFT 1 /* MICB3_BYPASS */ +#define ARIZONA_MICB3_BYPASS_WIDTH 1 /* MICB3_BYPASS */ +#define ARIZONA_MICB3_ENA 0x0001 /* MICB3_ENA */ +#define ARIZONA_MICB3_ENA_MASK 0x0001 /* MICB3_ENA */ +#define ARIZONA_MICB3_ENA_SHIFT 0 /* MICB3_ENA */ +#define ARIZONA_MICB3_ENA_WIDTH 1 /* MICB3_ENA */ + +/* + * R659 (0x293) - Accessory Detect Mode 1 + */ +#define ARIZONA_ACCDET_SRC 0x2000 /* ACCDET_SRC */ +#define ARIZONA_ACCDET_SRC_MASK 0x2000 /* ACCDET_SRC */ +#define ARIZONA_ACCDET_SRC_SHIFT 13 /* ACCDET_SRC */ +#define ARIZONA_ACCDET_SRC_WIDTH 1 /* ACCDET_SRC */ +#define ARIZONA_ACCDET_MODE_MASK 0x0003 /* ACCDET_MODE - [1:0] */ +#define ARIZONA_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [1:0] */ +#define ARIZONA_ACCDET_MODE_WIDTH 2 /* ACCDET_MODE - [1:0] */ + +/* + * R667 (0x29B) - Headphone Detect 1 + */ +#define ARIZONA_HP_STEP_SIZE 0x0100 /* HP_STEP_SIZE */ +#define ARIZONA_HP_STEP_SIZE_MASK 0x0100 /* HP_STEP_SIZE */ +#define ARIZONA_HP_STEP_SIZE_SHIFT 8 /* HP_STEP_SIZE */ +#define ARIZONA_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */ +#define ARIZONA_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */ +#define ARIZONA_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */ +#define ARIZONA_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */ +#define ARIZONA_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */ +#define ARIZONA_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */ +#define ARIZONA_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */ +#define ARIZONA_HP_IDAC_STEER 0x0004 /* HP_IDAC_STEER */ +#define ARIZONA_HP_IDAC_STEER_MASK 0x0004 /* HP_IDAC_STEER */ +#define ARIZONA_HP_IDAC_STEER_SHIFT 2 /* HP_IDAC_STEER */ +#define ARIZONA_HP_IDAC_STEER_WIDTH 1 /* HP_IDAC_STEER */ +#define ARIZONA_HP_RATE 0x0002 /* HP_RATE */ +#define ARIZONA_HP_RATE_MASK 0x0002 /* HP_RATE */ +#define ARIZONA_HP_RATE_SHIFT 1 /* HP_RATE */ +#define ARIZONA_HP_RATE_WIDTH 1 /* HP_RATE */ +#define ARIZONA_HP_POLL 0x0001 /* HP_POLL */ +#define ARIZONA_HP_POLL_MASK 0x0001 /* HP_POLL */ +#define ARIZONA_HP_POLL_SHIFT 0 /* HP_POLL */ +#define ARIZONA_HP_POLL_WIDTH 1 /* HP_POLL */ + +/* + * R668 (0x29C) - Headphone Detect 2 + */ +#define ARIZONA_HP_DONE 0x0080 /* HP_DONE */ +#define ARIZONA_HP_DONE_MASK 0x0080 /* HP_DONE */ +#define ARIZONA_HP_DONE_SHIFT 7 /* HP_DONE */ +#define ARIZONA_HP_DONE_WIDTH 1 /* HP_DONE */ +#define ARIZONA_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */ +#define ARIZONA_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */ +#define ARIZONA_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */ + +/* + * R675 (0x2A3) - Mic Detect 1 + */ +#define ARIZONA_MICD_BIAS_STARTTIME_MASK 0xF000 /* MICD_BIAS_STARTTIME - [15:12] */ +#define ARIZONA_MICD_BIAS_STARTTIME_SHIFT 12 /* MICD_BIAS_STARTTIME - [15:12] */ +#define ARIZONA_MICD_BIAS_STARTTIME_WIDTH 4 /* MICD_BIAS_STARTTIME - [15:12] */ +#define ARIZONA_MICD_RATE_MASK 0x0F00 /* MICD_RATE - [11:8] */ +#define ARIZONA_MICD_RATE_SHIFT 8 /* MICD_RATE - [11:8] */ +#define ARIZONA_MICD_RATE_WIDTH 4 /* MICD_RATE - [11:8] */ +#define ARIZONA_MICD_BIAS_SRC_MASK 0x0030 /* MICD_BIAS_SRC - [5:4] */ +#define ARIZONA_MICD_BIAS_SRC_SHIFT 4 /* MICD_BIAS_SRC - [5:4] */ +#define ARIZONA_MICD_BIAS_SRC_WIDTH 2 /* MICD_BIAS_SRC - [5:4] */ +#define ARIZONA_MICD_DBTIME 0x0002 /* MICD_DBTIME */ +#define ARIZONA_MICD_DBTIME_MASK 0x0002 /* MICD_DBTIME */ +#define ARIZONA_MICD_DBTIME_SHIFT 1 /* MICD_DBTIME */ +#define ARIZONA_MICD_DBTIME_WIDTH 1 /* MICD_DBTIME */ +#define ARIZONA_MICD_ENA 0x0001 /* MICD_ENA */ +#define ARIZONA_MICD_ENA_MASK 0x0001 /* MICD_ENA */ +#define ARIZONA_MICD_ENA_SHIFT 0 /* MICD_ENA */ +#define ARIZONA_MICD_ENA_WIDTH 1 /* MICD_ENA */ + +/* + * R676 (0x2A4) - Mic Detect 2 + */ +#define ARIZONA_MICD_LVL_SEL_MASK 0x00FF /* MICD_LVL_SEL - [7:0] */ +#define ARIZONA_MICD_LVL_SEL_SHIFT 0 /* MICD_LVL_SEL - [7:0] */ +#define ARIZONA_MICD_LVL_SEL_WIDTH 8 /* MICD_LVL_SEL - [7:0] */ + +/* + * R677 (0x2A5) - Mic Detect 3 + */ +#define ARIZONA_MICD_LVL_MASK 0x07FC /* MICD_LVL - [10:2] */ +#define ARIZONA_MICD_LVL_SHIFT 2 /* MICD_LVL - [10:2] */ +#define ARIZONA_MICD_LVL_WIDTH 9 /* MICD_LVL - [10:2] */ +#define ARIZONA_MICD_VALID 0x0002 /* MICD_VALID */ +#define ARIZONA_MICD_VALID_MASK 0x0002 /* MICD_VALID */ +#define ARIZONA_MICD_VALID_SHIFT 1 /* MICD_VALID */ +#define ARIZONA_MICD_VALID_WIDTH 1 /* MICD_VALID */ +#define ARIZONA_MICD_STS 0x0001 /* MICD_STS */ +#define ARIZONA_MICD_STS_MASK 0x0001 /* MICD_STS */ +#define ARIZONA_MICD_STS_SHIFT 0 /* MICD_STS */ +#define ARIZONA_MICD_STS_WIDTH 1 /* MICD_STS */ + +/* + * R707 (0x2C3) - Mic noise mix control 1 + */ +#define ARIZONA_MICMUTE_RATE_MASK 0x7800 /* MICMUTE_RATE - [14:11] */ +#define ARIZONA_MICMUTE_RATE_SHIFT 11 /* MICMUTE_RATE - [14:11] */ +#define ARIZONA_MICMUTE_RATE_WIDTH 4 /* MICMUTE_RATE - [14:11] */ +#define ARIZONA_MICMUTE_MIX_ENA 0x0040 /* MICMUTE_MIX_ENA */ +#define ARIZONA_MICMUTE_MIX_ENA_MASK 0x0040 /* MICMUTE_MIX_ENA */ +#define ARIZONA_MICMUTE_MIX_ENA_SHIFT 6 /* MICMUTE_MIX_ENA */ +#define ARIZONA_MICMUTE_MIX_ENA_WIDTH 1 /* MICMUTE_MIX_ENA */ + +/* + * R715 (0x2CB) - Isolation control + */ +#define ARIZONA_ISOLATE_DCVDD1 0x0001 /* ISOLATE_DCVDD1 */ +#define ARIZONA_ISOLATE_DCVDD1_MASK 0x0001 /* ISOLATE_DCVDD1 */ +#define ARIZONA_ISOLATE_DCVDD1_SHIFT 0 /* ISOLATE_DCVDD1 */ +#define ARIZONA_ISOLATE_DCVDD1_WIDTH 1 /* ISOLATE_DCVDD1 */ + +/* + * R723 (0x2D3) - Jack detect analogue + */ +#define ARIZONA_JD2_ENA 0x0002 /* JD2_ENA */ +#define ARIZONA_JD2_ENA_MASK 0x0002 /* JD2_ENA */ +#define ARIZONA_JD2_ENA_SHIFT 1 /* JD2_ENA */ +#define ARIZONA_JD2_ENA_WIDTH 1 /* JD2_ENA */ +#define ARIZONA_JD1_ENA 0x0001 /* JD1_ENA */ +#define ARIZONA_JD1_ENA_MASK 0x0001 /* JD1_ENA */ +#define ARIZONA_JD1_ENA_SHIFT 0 /* JD1_ENA */ +#define ARIZONA_JD1_ENA_WIDTH 1 /* JD1_ENA */ + +/* + * R768 (0x300) - Input Enables + */ +#define ARIZONA_IN4L_ENA 0x0080 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_MASK 0x0080 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_SHIFT 7 /* IN4L_ENA */ +#define ARIZONA_IN4L_ENA_WIDTH 1 /* IN4L_ENA */ +#define ARIZONA_IN4R_ENA 0x0040 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_MASK 0x0040 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_SHIFT 6 /* IN4R_ENA */ +#define ARIZONA_IN4R_ENA_WIDTH 1 /* IN4R_ENA */ +#define ARIZONA_IN3L_ENA 0x0020 /* IN3L_ENA */ +#define ARIZONA_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */ +#define ARIZONA_IN3L_ENA_SHIFT 5 /* IN3L_ENA */ +#define ARIZONA_IN3L_ENA_WIDTH 1 /* IN3L_ENA */ +#define ARIZONA_IN3R_ENA 0x0010 /* IN3R_ENA */ +#define ARIZONA_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */ +#define ARIZONA_IN3R_ENA_SHIFT 4 /* IN3R_ENA */ +#define ARIZONA_IN3R_ENA_WIDTH 1 /* IN3R_ENA */ +#define ARIZONA_IN2L_ENA 0x0008 /* IN2L_ENA */ +#define ARIZONA_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */ +#define ARIZONA_IN2L_ENA_SHIFT 3 /* IN2L_ENA */ +#define ARIZONA_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ +#define ARIZONA_IN2R_ENA 0x0004 /* IN2R_ENA */ +#define ARIZONA_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */ +#define ARIZONA_IN2R_ENA_SHIFT 2 /* IN2R_ENA */ +#define ARIZONA_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ +#define ARIZONA_IN1L_ENA 0x0002 /* IN1L_ENA */ +#define ARIZONA_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */ +#define ARIZONA_IN1L_ENA_SHIFT 1 /* IN1L_ENA */ +#define ARIZONA_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ +#define ARIZONA_IN1R_ENA 0x0001 /* IN1R_ENA */ +#define ARIZONA_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */ +#define ARIZONA_IN1R_ENA_SHIFT 0 /* IN1R_ENA */ +#define ARIZONA_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ + +/* + * R776 (0x308) - Input Rate + */ +#define ARIZONA_IN_RATE_MASK 0x7800 /* IN_RATE - [14:11] */ +#define ARIZONA_IN_RATE_SHIFT 11 /* IN_RATE - [14:11] */ +#define ARIZONA_IN_RATE_WIDTH 4 /* IN_RATE - [14:11] */ + +/* + * R777 (0x309) - Input Volume Ramp + */ +#define ARIZONA_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */ +#define ARIZONA_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */ +#define ARIZONA_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */ +#define ARIZONA_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */ +#define ARIZONA_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */ +#define ARIZONA_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */ + +/* + * R784 (0x310) - IN1L Control + */ +#define ARIZONA_IN1_OSR_MASK 0x6000 /* IN1_OSR - [14:13] */ +#define ARIZONA_IN1_OSR_SHIFT 13 /* IN1_OSR - [14:13] */ +#define ARIZONA_IN1_OSR_WIDTH 2 /* IN1_OSR - [14:13] */ +#define ARIZONA_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */ +#define ARIZONA_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */ +#define ARIZONA_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */ +#define ARIZONA_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */ +#define ARIZONA_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */ +#define ARIZONA_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */ +#define ARIZONA_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */ +#define ARIZONA_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */ +#define ARIZONA_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */ + +/* + * R785 (0x311) - ADC Digital Volume 1L + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN1L_MUTE 0x0100 /* IN1L_MUTE */ +#define ARIZONA_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */ +#define ARIZONA_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */ +#define ARIZONA_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ +#define ARIZONA_IN1L_DIG_VOL_MASK 0x00FF /* IN1L_DIG_VOL - [7:0] */ +#define ARIZONA_IN1L_DIG_VOL_SHIFT 0 /* IN1L_DIG_VOL - [7:0] */ +#define ARIZONA_IN1L_DIG_VOL_WIDTH 8 /* IN1L_DIG_VOL - [7:0] */ + +/* + * R786 (0x312) - DMIC1L Control + */ +#define ARIZONA_IN1_DMICL_DLY_MASK 0x003F /* IN1_DMICL_DLY - [5:0] */ +#define ARIZONA_IN1_DMICL_DLY_SHIFT 0 /* IN1_DMICL_DLY - [5:0] */ +#define ARIZONA_IN1_DMICL_DLY_WIDTH 6 /* IN1_DMICL_DLY - [5:0] */ + +/* + * R788 (0x314) - IN1R Control + */ +#define ARIZONA_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */ +#define ARIZONA_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */ +#define ARIZONA_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */ + +/* + * R789 (0x315) - ADC Digital Volume 1R + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN1R_MUTE 0x0100 /* IN1R_MUTE */ +#define ARIZONA_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */ +#define ARIZONA_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */ +#define ARIZONA_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ +#define ARIZONA_IN1R_DIG_VOL_MASK 0x00FF /* IN1R_DIG_VOL - [7:0] */ +#define ARIZONA_IN1R_DIG_VOL_SHIFT 0 /* IN1R_DIG_VOL - [7:0] */ +#define ARIZONA_IN1R_DIG_VOL_WIDTH 8 /* IN1R_DIG_VOL - [7:0] */ + +/* + * R790 (0x316) - DMIC1R Control + */ +#define ARIZONA_IN1_DMICR_DLY_MASK 0x003F /* IN1_DMICR_DLY - [5:0] */ +#define ARIZONA_IN1_DMICR_DLY_SHIFT 0 /* IN1_DMICR_DLY - [5:0] */ +#define ARIZONA_IN1_DMICR_DLY_WIDTH 6 /* IN1_DMICR_DLY - [5:0] */ + +/* + * R792 (0x318) - IN2L Control + */ +#define ARIZONA_IN2_OSR_MASK 0x6000 /* IN2_OSR - [14:13] */ +#define ARIZONA_IN2_OSR_SHIFT 13 /* IN2_OSR - [14:13] */ +#define ARIZONA_IN2_OSR_WIDTH 2 /* IN2_OSR - [14:13] */ +#define ARIZONA_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */ +#define ARIZONA_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */ +#define ARIZONA_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */ +#define ARIZONA_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */ +#define ARIZONA_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */ +#define ARIZONA_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */ +#define ARIZONA_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */ +#define ARIZONA_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */ +#define ARIZONA_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */ + +/* + * R793 (0x319) - ADC Digital Volume 2L + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN2L_MUTE 0x0100 /* IN2L_MUTE */ +#define ARIZONA_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */ +#define ARIZONA_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */ +#define ARIZONA_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ +#define ARIZONA_IN2L_DIG_VOL_MASK 0x00FF /* IN2L_DIG_VOL - [7:0] */ +#define ARIZONA_IN2L_DIG_VOL_SHIFT 0 /* IN2L_DIG_VOL - [7:0] */ +#define ARIZONA_IN2L_DIG_VOL_WIDTH 8 /* IN2L_DIG_VOL - [7:0] */ + +/* + * R794 (0x31A) - DMIC2L Control + */ +#define ARIZONA_IN2_DMICL_DLY_MASK 0x003F /* IN2_DMICL_DLY - [5:0] */ +#define ARIZONA_IN2_DMICL_DLY_SHIFT 0 /* IN2_DMICL_DLY - [5:0] */ +#define ARIZONA_IN2_DMICL_DLY_WIDTH 6 /* IN2_DMICL_DLY - [5:0] */ + +/* + * R796 (0x31C) - IN2R Control + */ +#define ARIZONA_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */ +#define ARIZONA_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */ +#define ARIZONA_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */ + +/* + * R797 (0x31D) - ADC Digital Volume 2R + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN2R_MUTE 0x0100 /* IN2R_MUTE */ +#define ARIZONA_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */ +#define ARIZONA_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */ +#define ARIZONA_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ +#define ARIZONA_IN2R_DIG_VOL_MASK 0x00FF /* IN2R_DIG_VOL - [7:0] */ +#define ARIZONA_IN2R_DIG_VOL_SHIFT 0 /* IN2R_DIG_VOL - [7:0] */ +#define ARIZONA_IN2R_DIG_VOL_WIDTH 8 /* IN2R_DIG_VOL - [7:0] */ + +/* + * R798 (0x31E) - DMIC2R Control + */ +#define ARIZONA_IN2_DMICR_DLY_MASK 0x003F /* IN2_DMICR_DLY - [5:0] */ +#define ARIZONA_IN2_DMICR_DLY_SHIFT 0 /* IN2_DMICR_DLY - [5:0] */ +#define ARIZONA_IN2_DMICR_DLY_WIDTH 6 /* IN2_DMICR_DLY - [5:0] */ + +/* + * R800 (0x320) - IN3L Control + */ +#define ARIZONA_IN3_OSR_MASK 0x6000 /* IN3_OSR - [14:13] */ +#define ARIZONA_IN3_OSR_SHIFT 13 /* IN3_OSR - [14:13] */ +#define ARIZONA_IN3_OSR_WIDTH 2 /* IN3_OSR - [14:13] */ +#define ARIZONA_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */ +#define ARIZONA_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */ +#define ARIZONA_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */ +#define ARIZONA_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */ +#define ARIZONA_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */ +#define ARIZONA_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */ +#define ARIZONA_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */ +#define ARIZONA_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */ +#define ARIZONA_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */ + +/* + * R801 (0x321) - ADC Digital Volume 3L + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN3L_MUTE 0x0100 /* IN3L_MUTE */ +#define ARIZONA_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */ +#define ARIZONA_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */ +#define ARIZONA_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */ +#define ARIZONA_IN3L_DIG_VOL_MASK 0x00FF /* IN3L_DIG_VOL - [7:0] */ +#define ARIZONA_IN3L_DIG_VOL_SHIFT 0 /* IN3L_DIG_VOL - [7:0] */ +#define ARIZONA_IN3L_DIG_VOL_WIDTH 8 /* IN3L_DIG_VOL - [7:0] */ + +/* + * R802 (0x322) - DMIC3L Control + */ +#define ARIZONA_IN3_DMICL_DLY_MASK 0x003F /* IN3_DMICL_DLY - [5:0] */ +#define ARIZONA_IN3_DMICL_DLY_SHIFT 0 /* IN3_DMICL_DLY - [5:0] */ +#define ARIZONA_IN3_DMICL_DLY_WIDTH 6 /* IN3_DMICL_DLY - [5:0] */ + +/* + * R804 (0x324) - IN3R Control + */ +#define ARIZONA_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */ +#define ARIZONA_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */ +#define ARIZONA_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */ + +/* + * R805 (0x325) - ADC Digital Volume 3R + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN3R_MUTE 0x0100 /* IN3R_MUTE */ +#define ARIZONA_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */ +#define ARIZONA_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */ +#define ARIZONA_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */ +#define ARIZONA_IN3R_DIG_VOL_MASK 0x00FF /* IN3R_DIG_VOL - [7:0] */ +#define ARIZONA_IN3R_DIG_VOL_SHIFT 0 /* IN3R_DIG_VOL - [7:0] */ +#define ARIZONA_IN3R_DIG_VOL_WIDTH 8 /* IN3R_DIG_VOL - [7:0] */ + +/* + * R806 (0x326) - DMIC3R Control + */ +#define ARIZONA_IN3_DMICR_DLY_MASK 0x003F /* IN3_DMICR_DLY - [5:0] */ +#define ARIZONA_IN3_DMICR_DLY_SHIFT 0 /* IN3_DMICR_DLY - [5:0] */ +#define ARIZONA_IN3_DMICR_DLY_WIDTH 6 /* IN3_DMICR_DLY - [5:0] */ + +/* + * R808 (0x328) - IN4 Control + */ +#define ARIZONA_IN4_OSR_MASK 0x6000 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_OSR_SHIFT 13 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_OSR_WIDTH 2 /* IN4_OSR - [14:13] */ +#define ARIZONA_IN4_DMIC_SUP_MASK 0x1800 /* IN4_DMIC_SUP - [12:11] */ +#define ARIZONA_IN4_DMIC_SUP_SHIFT 11 /* IN4_DMIC_SUP - [12:11] */ +#define ARIZONA_IN4_DMIC_SUP_WIDTH 2 /* IN4_DMIC_SUP - [12:11] */ + +/* + * R809 (0x329) - ADC Digital Volume 4L + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN4L_MUTE 0x0100 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_MASK 0x0100 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_SHIFT 8 /* IN4L_MUTE */ +#define ARIZONA_IN4L_MUTE_WIDTH 1 /* IN4L_MUTE */ +#define ARIZONA_IN4L_DIG_VOL_MASK 0x00FF /* IN4L_DIG_VOL - [7:0] */ +#define ARIZONA_IN4L_DIG_VOL_SHIFT 0 /* IN4L_DIG_VOL - [7:0] */ +#define ARIZONA_IN4L_DIG_VOL_WIDTH 8 /* IN4L_DIG_VOL - [7:0] */ + +/* + * R810 (0x32A) - DMIC4L Control + */ +#define ARIZONA_IN4L_DMIC_DLY_MASK 0x003F /* IN4L_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4L_DMIC_DLY_SHIFT 0 /* IN4L_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4L_DMIC_DLY_WIDTH 6 /* IN4L_DMIC_DLY - [5:0] */ + +/* + * R813 (0x32D) - ADC Digital Volume 4R + */ +#define ARIZONA_IN_VU 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_MASK 0x0200 /* IN_VU */ +#define ARIZONA_IN_VU_SHIFT 9 /* IN_VU */ +#define ARIZONA_IN_VU_WIDTH 1 /* IN_VU */ +#define ARIZONA_IN4R_MUTE 0x0100 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_MASK 0x0100 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_SHIFT 8 /* IN4R_MUTE */ +#define ARIZONA_IN4R_MUTE_WIDTH 1 /* IN4R_MUTE */ +#define ARIZONA_IN4R_DIG_VOL_MASK 0x00FF /* IN4R_DIG_VOL - [7:0] */ +#define ARIZONA_IN4R_DIG_VOL_SHIFT 0 /* IN4R_DIG_VOL - [7:0] */ +#define ARIZONA_IN4R_DIG_VOL_WIDTH 8 /* IN4R_DIG_VOL - [7:0] */ + +/* + * R814 (0x32E) - DMIC4R Control + */ +#define ARIZONA_IN4R_DMIC_DLY_MASK 0x003F /* IN4R_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4R_DMIC_DLY_SHIFT 0 /* IN4R_DMIC_DLY - [5:0] */ +#define ARIZONA_IN4R_DMIC_DLY_WIDTH 6 /* IN4R_DMIC_DLY - [5:0] */ + +/* + * R1024 (0x400) - Output Enables 1 + */ +#define ARIZONA_OUT6L_ENA 0x0800 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_MASK 0x0800 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_SHIFT 11 /* OUT6L_ENA */ +#define ARIZONA_OUT6L_ENA_WIDTH 1 /* OUT6L_ENA */ +#define ARIZONA_OUT6R_ENA 0x0400 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_MASK 0x0400 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_SHIFT 10 /* OUT6R_ENA */ +#define ARIZONA_OUT6R_ENA_WIDTH 1 /* OUT6R_ENA */ +#define ARIZONA_OUT5L_ENA 0x0200 /* OUT5L_ENA */ +#define ARIZONA_OUT5L_ENA_MASK 0x0200 /* OUT5L_ENA */ +#define ARIZONA_OUT5L_ENA_SHIFT 9 /* OUT5L_ENA */ +#define ARIZONA_OUT5L_ENA_WIDTH 1 /* OUT5L_ENA */ +#define ARIZONA_OUT5R_ENA 0x0100 /* OUT5R_ENA */ +#define ARIZONA_OUT5R_ENA_MASK 0x0100 /* OUT5R_ENA */ +#define ARIZONA_OUT5R_ENA_SHIFT 8 /* OUT5R_ENA */ +#define ARIZONA_OUT5R_ENA_WIDTH 1 /* OUT5R_ENA */ +#define ARIZONA_OUT4L_ENA 0x0080 /* OUT4L_ENA */ +#define ARIZONA_OUT4L_ENA_MASK 0x0080 /* OUT4L_ENA */ +#define ARIZONA_OUT4L_ENA_SHIFT 7 /* OUT4L_ENA */ +#define ARIZONA_OUT4L_ENA_WIDTH 1 /* OUT4L_ENA */ +#define ARIZONA_OUT4R_ENA 0x0040 /* OUT4R_ENA */ +#define ARIZONA_OUT4R_ENA_MASK 0x0040 /* OUT4R_ENA */ +#define ARIZONA_OUT4R_ENA_SHIFT 6 /* OUT4R_ENA */ +#define ARIZONA_OUT4R_ENA_WIDTH 1 /* OUT4R_ENA */ +#define ARIZONA_OUT3L_ENA 0x0020 /* OUT3L_ENA */ +#define ARIZONA_OUT3L_ENA_MASK 0x0020 /* OUT3L_ENA */ +#define ARIZONA_OUT3L_ENA_SHIFT 5 /* OUT3L_ENA */ +#define ARIZONA_OUT3L_ENA_WIDTH 1 /* OUT3L_ENA */ +#define ARIZONA_OUT3R_ENA 0x0010 /* OUT3R_ENA */ +#define ARIZONA_OUT3R_ENA_MASK 0x0010 /* OUT3R_ENA */ +#define ARIZONA_OUT3R_ENA_SHIFT 4 /* OUT3R_ENA */ +#define ARIZONA_OUT3R_ENA_WIDTH 1 /* OUT3R_ENA */ +#define ARIZONA_OUT2L_ENA 0x0008 /* OUT2L_ENA */ +#define ARIZONA_OUT2L_ENA_MASK 0x0008 /* OUT2L_ENA */ +#define ARIZONA_OUT2L_ENA_SHIFT 3 /* OUT2L_ENA */ +#define ARIZONA_OUT2L_ENA_WIDTH 1 /* OUT2L_ENA */ +#define ARIZONA_OUT2R_ENA 0x0004 /* OUT2R_ENA */ +#define ARIZONA_OUT2R_ENA_MASK 0x0004 /* OUT2R_ENA */ +#define ARIZONA_OUT2R_ENA_SHIFT 2 /* OUT2R_ENA */ +#define ARIZONA_OUT2R_ENA_WIDTH 1 /* OUT2R_ENA */ +#define ARIZONA_OUT1L_ENA 0x0002 /* OUT1L_ENA */ +#define ARIZONA_OUT1L_ENA_MASK 0x0002 /* OUT1L_ENA */ +#define ARIZONA_OUT1L_ENA_SHIFT 1 /* OUT1L_ENA */ +#define ARIZONA_OUT1L_ENA_WIDTH 1 /* OUT1L_ENA */ +#define ARIZONA_OUT1R_ENA 0x0001 /* OUT1R_ENA */ +#define ARIZONA_OUT1R_ENA_MASK 0x0001 /* OUT1R_ENA */ +#define ARIZONA_OUT1R_ENA_SHIFT 0 /* OUT1R_ENA */ +#define ARIZONA_OUT1R_ENA_WIDTH 1 /* OUT1R_ENA */ + +/* + * R1025 (0x401) - Output Status 1 + */ +#define ARIZONA_OUT6L_ENA_STS 0x0800 /* OUT6L_ENA_STS */ +#define ARIZONA_OUT6L_ENA_STS_MASK 0x0800 /* OUT6L_ENA_STS */ +#define ARIZONA_OUT6L_ENA_STS_SHIFT 11 /* OUT6L_ENA_STS */ +#define ARIZONA_OUT6L_ENA_STS_WIDTH 1 /* OUT6L_ENA_STS */ +#define ARIZONA_OUT6R_ENA_STS 0x0400 /* OUT6R_ENA_STS */ +#define ARIZONA_OUT6R_ENA_STS_MASK 0x0400 /* OUT6R_ENA_STS */ +#define ARIZONA_OUT6R_ENA_STS_SHIFT 10 /* OUT6R_ENA_STS */ +#define ARIZONA_OUT6R_ENA_STS_WIDTH 1 /* OUT6R_ENA_STS */ +#define ARIZONA_OUT5L_ENA_STS 0x0200 /* OUT5L_ENA_STS */ +#define ARIZONA_OUT5L_ENA_STS_MASK 0x0200 /* OUT5L_ENA_STS */ +#define ARIZONA_OUT5L_ENA_STS_SHIFT 9 /* OUT5L_ENA_STS */ +#define ARIZONA_OUT5L_ENA_STS_WIDTH 1 /* OUT5L_ENA_STS */ +#define ARIZONA_OUT5R_ENA_STS 0x0100 /* OUT5R_ENA_STS */ +#define ARIZONA_OUT5R_ENA_STS_MASK 0x0100 /* OUT5R_ENA_STS */ +#define ARIZONA_OUT5R_ENA_STS_SHIFT 8 /* OUT5R_ENA_STS */ +#define ARIZONA_OUT5R_ENA_STS_WIDTH 1 /* OUT5R_ENA_STS */ +#define ARIZONA_OUT4L_ENA_STS 0x0080 /* OUT4L_ENA_STS */ +#define ARIZONA_OUT4L_ENA_STS_MASK 0x0080 /* OUT4L_ENA_STS */ +#define ARIZONA_OUT4L_ENA_STS_SHIFT 7 /* OUT4L_ENA_STS */ +#define ARIZONA_OUT4L_ENA_STS_WIDTH 1 /* OUT4L_ENA_STS */ +#define ARIZONA_OUT4R_ENA_STS 0x0040 /* OUT4R_ENA_STS */ +#define ARIZONA_OUT4R_ENA_STS_MASK 0x0040 /* OUT4R_ENA_STS */ +#define ARIZONA_OUT4R_ENA_STS_SHIFT 6 /* OUT4R_ENA_STS */ +#define ARIZONA_OUT4R_ENA_STS_WIDTH 1 /* OUT4R_ENA_STS */ + +/* + * R1032 (0x408) - Output Rate 1 + */ +#define ARIZONA_OUT_RATE_MASK 0x7800 /* OUT_RATE - [14:11] */ +#define ARIZONA_OUT_RATE_SHIFT 11 /* OUT_RATE - [14:11] */ +#define ARIZONA_OUT_RATE_WIDTH 4 /* OUT_RATE - [14:11] */ + +/* + * R1033 (0x409) - Output Volume Ramp + */ +#define ARIZONA_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */ +#define ARIZONA_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */ +#define ARIZONA_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */ +#define ARIZONA_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */ +#define ARIZONA_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */ +#define ARIZONA_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */ + +/* + * R1040 (0x410) - Output Path Config 1L + */ +#define ARIZONA_OUT1_LP_MODE 0x8000 /* OUT1_LP_MODE */ +#define ARIZONA_OUT1_LP_MODE_MASK 0x8000 /* OUT1_LP_MODE */ +#define ARIZONA_OUT1_LP_MODE_SHIFT 15 /* OUT1_LP_MODE */ +#define ARIZONA_OUT1_LP_MODE_WIDTH 1 /* OUT1_LP_MODE */ +#define ARIZONA_OUT1_OSR 0x2000 /* OUT1_OSR */ +#define ARIZONA_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */ +#define ARIZONA_OUT1_OSR_SHIFT 13 /* OUT1_OSR */ +#define ARIZONA_OUT1_OSR_WIDTH 1 /* OUT1_OSR */ +#define ARIZONA_OUT1_MONO 0x1000 /* OUT1_MONO */ +#define ARIZONA_OUT1_MONO_MASK 0x1000 /* OUT1_MONO */ +#define ARIZONA_OUT1_MONO_SHIFT 12 /* OUT1_MONO */ +#define ARIZONA_OUT1_MONO_WIDTH 1 /* OUT1_MONO */ +#define ARIZONA_OUT1L_ANC_SRC_MASK 0x0C00 /* OUT1L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1L_ANC_SRC_SHIFT 10 /* OUT1L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1L_ANC_SRC_WIDTH 2 /* OUT1L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */ + +/* + * R1041 (0x411) - DAC Digital Volume 1L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */ +#define ARIZONA_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */ +#define ARIZONA_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */ +#define ARIZONA_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */ +#define ARIZONA_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */ +#define ARIZONA_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */ +#define ARIZONA_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */ + +/* + * R1042 (0x412) - DAC Volume Limit 1L + */ +#define ARIZONA_OUT1L_VOL_LIM_MASK 0x00FF /* OUT1L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT1L_VOL_LIM_SHIFT 0 /* OUT1L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT1L_VOL_LIM_WIDTH 8 /* OUT1L_VOL_LIM - [7:0] */ + +/* + * R1043 (0x413) - Noise Gate Select 1L + */ +#define ARIZONA_OUT1L_NGATE_SRC_MASK 0x0FFF /* OUT1L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT1L_NGATE_SRC_SHIFT 0 /* OUT1L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT1L_NGATE_SRC_WIDTH 12 /* OUT1L_NGATE_SRC - [11:0] */ + +/* + * R1044 (0x414) - Output Path Config 1R + */ +#define ARIZONA_OUT1R_ANC_SRC_MASK 0x0C00 /* OUT1R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1R_ANC_SRC_SHIFT 10 /* OUT1R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1R_ANC_SRC_WIDTH 2 /* OUT1R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */ + +/* + * R1045 (0x415) - DAC Digital Volume 1R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */ +#define ARIZONA_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */ +#define ARIZONA_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */ +#define ARIZONA_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */ +#define ARIZONA_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */ +#define ARIZONA_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */ +#define ARIZONA_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */ + +/* + * R1046 (0x416) - DAC Volume Limit 1R + */ +#define ARIZONA_OUT1R_VOL_LIM_MASK 0x00FF /* OUT1R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT1R_VOL_LIM_SHIFT 0 /* OUT1R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT1R_VOL_LIM_WIDTH 8 /* OUT1R_VOL_LIM - [7:0] */ + +/* + * R1047 (0x417) - Noise Gate Select 1R + */ +#define ARIZONA_OUT1R_NGATE_SRC_MASK 0x0FFF /* OUT1R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT1R_NGATE_SRC_SHIFT 0 /* OUT1R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT1R_NGATE_SRC_WIDTH 12 /* OUT1R_NGATE_SRC - [11:0] */ + +/* + * R1048 (0x418) - Output Path Config 2L + */ +#define ARIZONA_OUT2_LP_MODE 0x8000 /* OUT2_LP_MODE */ +#define ARIZONA_OUT2_LP_MODE_MASK 0x8000 /* OUT2_LP_MODE */ +#define ARIZONA_OUT2_LP_MODE_SHIFT 15 /* OUT2_LP_MODE */ +#define ARIZONA_OUT2_LP_MODE_WIDTH 1 /* OUT2_LP_MODE */ +#define ARIZONA_OUT2_OSR 0x2000 /* OUT2_OSR */ +#define ARIZONA_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */ +#define ARIZONA_OUT2_OSR_SHIFT 13 /* OUT2_OSR */ +#define ARIZONA_OUT2_OSR_WIDTH 1 /* OUT2_OSR */ +#define ARIZONA_OUT2_MONO 0x1000 /* OUT2_MONO */ +#define ARIZONA_OUT2_MONO_MASK 0x1000 /* OUT2_MONO */ +#define ARIZONA_OUT2_MONO_SHIFT 12 /* OUT2_MONO */ +#define ARIZONA_OUT2_MONO_WIDTH 1 /* OUT2_MONO */ +#define ARIZONA_OUT2L_ANC_SRC_MASK 0x0C00 /* OUT2L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2L_ANC_SRC_SHIFT 10 /* OUT2L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2L_ANC_SRC_WIDTH 2 /* OUT2L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2L_PGA_VOL_MASK 0x00FE /* OUT2L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT2L_PGA_VOL_SHIFT 1 /* OUT2L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT2L_PGA_VOL_WIDTH 7 /* OUT2L_PGA_VOL - [7:1] */ + +/* + * R1049 (0x419) - DAC Digital Volume 2L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */ +#define ARIZONA_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */ +#define ARIZONA_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */ +#define ARIZONA_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */ +#define ARIZONA_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */ +#define ARIZONA_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */ +#define ARIZONA_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */ + +/* + * R1050 (0x41A) - DAC Volume Limit 2L + */ +#define ARIZONA_OUT2L_VOL_LIM_MASK 0x00FF /* OUT2L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT2L_VOL_LIM_SHIFT 0 /* OUT2L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT2L_VOL_LIM_WIDTH 8 /* OUT2L_VOL_LIM - [7:0] */ + +/* + * R1051 (0x41B) - Noise Gate Select 2L + */ +#define ARIZONA_OUT2L_NGATE_SRC_MASK 0x0FFF /* OUT2L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT2L_NGATE_SRC_SHIFT 0 /* OUT2L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT2L_NGATE_SRC_WIDTH 12 /* OUT2L_NGATE_SRC - [11:0] */ + +/* + * R1052 (0x41C) - Output Path Config 2R + */ +#define ARIZONA_OUT2R_ANC_SRC_MASK 0x0C00 /* OUT2R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2R_ANC_SRC_SHIFT 10 /* OUT2R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2R_ANC_SRC_WIDTH 2 /* OUT2R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT2R_PGA_VOL_MASK 0x00FE /* OUT2R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT2R_PGA_VOL_SHIFT 1 /* OUT2R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT2R_PGA_VOL_WIDTH 7 /* OUT2R_PGA_VOL - [7:1] */ + +/* + * R1053 (0x41D) - DAC Digital Volume 2R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */ +#define ARIZONA_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */ +#define ARIZONA_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */ +#define ARIZONA_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */ +#define ARIZONA_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */ +#define ARIZONA_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */ +#define ARIZONA_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */ + +/* + * R1054 (0x41E) - DAC Volume Limit 2R + */ +#define ARIZONA_OUT2R_VOL_LIM_MASK 0x00FF /* OUT2R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT2R_VOL_LIM_SHIFT 0 /* OUT2R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT2R_VOL_LIM_WIDTH 8 /* OUT2R_VOL_LIM - [7:0] */ + +/* + * R1055 (0x41F) - Noise Gate Select 2R + */ +#define ARIZONA_OUT2R_NGATE_SRC_MASK 0x0FFF /* OUT2R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT2R_NGATE_SRC_SHIFT 0 /* OUT2R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT2R_NGATE_SRC_WIDTH 12 /* OUT2R_NGATE_SRC - [11:0] */ + +/* + * R1056 (0x420) - Output Path Config 3L + */ +#define ARIZONA_OUT3_LP_MODE 0x8000 /* OUT3_LP_MODE */ +#define ARIZONA_OUT3_LP_MODE_MASK 0x8000 /* OUT3_LP_MODE */ +#define ARIZONA_OUT3_LP_MODE_SHIFT 15 /* OUT3_LP_MODE */ +#define ARIZONA_OUT3_LP_MODE_WIDTH 1 /* OUT3_LP_MODE */ +#define ARIZONA_OUT3_OSR 0x2000 /* OUT3_OSR */ +#define ARIZONA_OUT3_OSR_MASK 0x2000 /* OUT3_OSR */ +#define ARIZONA_OUT3_OSR_SHIFT 13 /* OUT3_OSR */ +#define ARIZONA_OUT3_OSR_WIDTH 1 /* OUT3_OSR */ +#define ARIZONA_OUT3_MONO 0x1000 /* OUT3_MONO */ +#define ARIZONA_OUT3_MONO_MASK 0x1000 /* OUT3_MONO */ +#define ARIZONA_OUT3_MONO_SHIFT 12 /* OUT3_MONO */ +#define ARIZONA_OUT3_MONO_WIDTH 1 /* OUT3_MONO */ +#define ARIZONA_OUT3L_ANC_SRC_MASK 0x0C00 /* OUT3L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3L_ANC_SRC_SHIFT 10 /* OUT3L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3L_ANC_SRC_WIDTH 2 /* OUT3L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3L_PGA_VOL_MASK 0x00FE /* OUT3L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT3L_PGA_VOL_SHIFT 1 /* OUT3L_PGA_VOL - [7:1] */ +#define ARIZONA_OUT3L_PGA_VOL_WIDTH 7 /* OUT3L_PGA_VOL - [7:1] */ + +/* + * R1057 (0x421) - DAC Digital Volume 3L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT3L_MUTE 0x0100 /* OUT3L_MUTE */ +#define ARIZONA_OUT3L_MUTE_MASK 0x0100 /* OUT3L_MUTE */ +#define ARIZONA_OUT3L_MUTE_SHIFT 8 /* OUT3L_MUTE */ +#define ARIZONA_OUT3L_MUTE_WIDTH 1 /* OUT3L_MUTE */ +#define ARIZONA_OUT3L_VOL_MASK 0x00FF /* OUT3L_VOL - [7:0] */ +#define ARIZONA_OUT3L_VOL_SHIFT 0 /* OUT3L_VOL - [7:0] */ +#define ARIZONA_OUT3L_VOL_WIDTH 8 /* OUT3L_VOL - [7:0] */ + +/* + * R1058 (0x422) - DAC Volume Limit 3L + */ +#define ARIZONA_OUT3L_VOL_LIM_MASK 0x00FF /* OUT3L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT3L_VOL_LIM_SHIFT 0 /* OUT3L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT3L_VOL_LIM_WIDTH 8 /* OUT3L_VOL_LIM - [7:0] */ + +/* + * R1059 (0x423) - Noise Gate Select 3L + */ +#define ARIZONA_OUT3_NGATE_SRC_MASK 0x0FFF /* OUT3_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT3_NGATE_SRC_SHIFT 0 /* OUT3_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT3_NGATE_SRC_WIDTH 12 /* OUT3_NGATE_SRC - [11:0] */ + +/* + * R1060 (0x424) - Output Path Config 3R + */ +#define ARIZONA_OUT3R_PGA_VOL_MASK 0x00FE /* OUT3R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT3R_PGA_VOL_SHIFT 1 /* OUT3R_PGA_VOL - [7:1] */ +#define ARIZONA_OUT3R_PGA_VOL_WIDTH 7 /* OUT3R_PGA_VOL - [7:1] */ + +/* + * R1061 (0x425) - DAC Digital Volume 3R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT3R_MUTE 0x0100 /* OUT3R_MUTE */ +#define ARIZONA_OUT3R_MUTE_MASK 0x0100 /* OUT3R_MUTE */ +#define ARIZONA_OUT3R_MUTE_SHIFT 8 /* OUT3R_MUTE */ +#define ARIZONA_OUT3R_MUTE_WIDTH 1 /* OUT3R_MUTE */ +#define ARIZONA_OUT3R_VOL_MASK 0x00FF /* OUT3R_VOL - [7:0] */ +#define ARIZONA_OUT3R_VOL_SHIFT 0 /* OUT3R_VOL - [7:0] */ +#define ARIZONA_OUT3R_VOL_WIDTH 8 /* OUT3R_VOL - [7:0] */ + +/* + * R1062 (0x426) - DAC Volume Limit 3R + */ +#define ARIZONA_OUT3R_ANC_SRC_MASK 0x0C00 /* OUT3R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3R_ANC_SRC_SHIFT 10 /* OUT3R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3R_ANC_SRC_WIDTH 2 /* OUT3R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT3R_VOL_LIM_MASK 0x00FF /* OUT3R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT3R_VOL_LIM_SHIFT 0 /* OUT3R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT3R_VOL_LIM_WIDTH 8 /* OUT3R_VOL_LIM - [7:0] */ + +/* + * R1064 (0x428) - Output Path Config 4L + */ +#define ARIZONA_OUT4_OSR 0x2000 /* OUT4_OSR */ +#define ARIZONA_OUT4_OSR_MASK 0x2000 /* OUT4_OSR */ +#define ARIZONA_OUT4_OSR_SHIFT 13 /* OUT4_OSR */ +#define ARIZONA_OUT4_OSR_WIDTH 1 /* OUT4_OSR */ +#define ARIZONA_OUT4L_ANC_SRC_MASK 0x0C00 /* OUT4L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT4L_ANC_SRC_SHIFT 10 /* OUT4L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT4L_ANC_SRC_WIDTH 2 /* OUT4L_ANC_SRC - [11:10] */ + +/* + * R1065 (0x429) - DAC Digital Volume 4L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT4L_MUTE 0x0100 /* OUT4L_MUTE */ +#define ARIZONA_OUT4L_MUTE_MASK 0x0100 /* OUT4L_MUTE */ +#define ARIZONA_OUT4L_MUTE_SHIFT 8 /* OUT4L_MUTE */ +#define ARIZONA_OUT4L_MUTE_WIDTH 1 /* OUT4L_MUTE */ +#define ARIZONA_OUT4L_VOL_MASK 0x00FF /* OUT4L_VOL - [7:0] */ +#define ARIZONA_OUT4L_VOL_SHIFT 0 /* OUT4L_VOL - [7:0] */ +#define ARIZONA_OUT4L_VOL_WIDTH 8 /* OUT4L_VOL - [7:0] */ + +/* + * R1066 (0x42A) - Out Volume 4L + */ +#define ARIZONA_OUT4L_VOL_LIM_MASK 0x00FF /* OUT4L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT4L_VOL_LIM_SHIFT 0 /* OUT4L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT4L_VOL_LIM_WIDTH 8 /* OUT4L_VOL_LIM - [7:0] */ + +/* + * R1067 (0x42B) - Noise Gate Select 4L + */ +#define ARIZONA_OUT4L_NGATE_SRC_MASK 0x0FFF /* OUT4L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT4L_NGATE_SRC_SHIFT 0 /* OUT4L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT4L_NGATE_SRC_WIDTH 12 /* OUT4L_NGATE_SRC - [11:0] */ + +/* + * R1068 (0x42C) - Output Path Config 4R + */ +#define ARIZONA_OUT4R_ANC_SRC_MASK 0x0C00 /* OUT4R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT4R_ANC_SRC_SHIFT 10 /* OUT4R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT4R_ANC_SRC_WIDTH 2 /* OUT4R_ANC_SRC - [11:10] */ + +/* + * R1069 (0x42D) - DAC Digital Volume 4R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT4R_MUTE 0x0100 /* OUT4R_MUTE */ +#define ARIZONA_OUT4R_MUTE_MASK 0x0100 /* OUT4R_MUTE */ +#define ARIZONA_OUT4R_MUTE_SHIFT 8 /* OUT4R_MUTE */ +#define ARIZONA_OUT4R_MUTE_WIDTH 1 /* OUT4R_MUTE */ +#define ARIZONA_OUT4R_VOL_MASK 0x00FF /* OUT4R_VOL - [7:0] */ +#define ARIZONA_OUT4R_VOL_SHIFT 0 /* OUT4R_VOL - [7:0] */ +#define ARIZONA_OUT4R_VOL_WIDTH 8 /* OUT4R_VOL - [7:0] */ + +/* + * R1070 (0x42E) - Out Volume 4R + */ +#define ARIZONA_OUT4R_VOL_LIM_MASK 0x00FF /* OUT4R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT4R_VOL_LIM_SHIFT 0 /* OUT4R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT4R_VOL_LIM_WIDTH 8 /* OUT4R_VOL_LIM - [7:0] */ + +/* + * R1071 (0x42F) - Noise Gate Select 4R + */ +#define ARIZONA_OUT4R_NGATE_SRC_MASK 0x0FFF /* OUT4R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT4R_NGATE_SRC_SHIFT 0 /* OUT4R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT4R_NGATE_SRC_WIDTH 12 /* OUT4R_NGATE_SRC - [11:0] */ + +/* + * R1072 (0x430) - Output Path Config 5L + */ +#define ARIZONA_OUT5_OSR 0x2000 /* OUT5_OSR */ +#define ARIZONA_OUT5_OSR_MASK 0x2000 /* OUT5_OSR */ +#define ARIZONA_OUT5_OSR_SHIFT 13 /* OUT5_OSR */ +#define ARIZONA_OUT5_OSR_WIDTH 1 /* OUT5_OSR */ +#define ARIZONA_OUT5L_ANC_SRC_MASK 0x0C00 /* OUT5L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT5L_ANC_SRC_SHIFT 10 /* OUT5L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT5L_ANC_SRC_WIDTH 2 /* OUT5L_ANC_SRC - [11:10] */ + +/* + * R1073 (0x431) - DAC Digital Volume 5L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT5L_MUTE 0x0100 /* OUT5L_MUTE */ +#define ARIZONA_OUT5L_MUTE_MASK 0x0100 /* OUT5L_MUTE */ +#define ARIZONA_OUT5L_MUTE_SHIFT 8 /* OUT5L_MUTE */ +#define ARIZONA_OUT5L_MUTE_WIDTH 1 /* OUT5L_MUTE */ +#define ARIZONA_OUT5L_VOL_MASK 0x00FF /* OUT5L_VOL - [7:0] */ +#define ARIZONA_OUT5L_VOL_SHIFT 0 /* OUT5L_VOL - [7:0] */ +#define ARIZONA_OUT5L_VOL_WIDTH 8 /* OUT5L_VOL - [7:0] */ + +/* + * R1074 (0x432) - DAC Volume Limit 5L + */ +#define ARIZONA_OUT5L_VOL_LIM_MASK 0x00FF /* OUT5L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT5L_VOL_LIM_SHIFT 0 /* OUT5L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT5L_VOL_LIM_WIDTH 8 /* OUT5L_VOL_LIM - [7:0] */ + +/* + * R1075 (0x433) - Noise Gate Select 5L + */ +#define ARIZONA_OUT5L_NGATE_SRC_MASK 0x0FFF /* OUT5L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT5L_NGATE_SRC_SHIFT 0 /* OUT5L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT5L_NGATE_SRC_WIDTH 12 /* OUT5L_NGATE_SRC - [11:0] */ + +/* + * R1076 (0x434) - Output Path Config 5R + */ +#define ARIZONA_OUT5R_ANC_SRC_MASK 0x0C00 /* OUT5R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT5R_ANC_SRC_SHIFT 10 /* OUT5R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT5R_ANC_SRC_WIDTH 2 /* OUT5R_ANC_SRC - [11:10] */ + +/* + * R1077 (0x435) - DAC Digital Volume 5R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT5R_MUTE 0x0100 /* OUT5R_MUTE */ +#define ARIZONA_OUT5R_MUTE_MASK 0x0100 /* OUT5R_MUTE */ +#define ARIZONA_OUT5R_MUTE_SHIFT 8 /* OUT5R_MUTE */ +#define ARIZONA_OUT5R_MUTE_WIDTH 1 /* OUT5R_MUTE */ +#define ARIZONA_OUT5R_VOL_MASK 0x00FF /* OUT5R_VOL - [7:0] */ +#define ARIZONA_OUT5R_VOL_SHIFT 0 /* OUT5R_VOL - [7:0] */ +#define ARIZONA_OUT5R_VOL_WIDTH 8 /* OUT5R_VOL - [7:0] */ + +/* + * R1078 (0x436) - DAC Volume Limit 5R + */ +#define ARIZONA_OUT5R_VOL_LIM_MASK 0x00FF /* OUT5R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT5R_VOL_LIM_SHIFT 0 /* OUT5R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT5R_VOL_LIM_WIDTH 8 /* OUT5R_VOL_LIM - [7:0] */ + +/* + * R1079 (0x437) - Noise Gate Select 5R + */ +#define ARIZONA_OUT5R_NGATE_SRC_MASK 0x0FFF /* OUT5R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT5R_NGATE_SRC_SHIFT 0 /* OUT5R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT5R_NGATE_SRC_WIDTH 12 /* OUT5R_NGATE_SRC - [11:0] */ + +/* + * R1080 (0x438) - Output Path Config 6L + */ +#define ARIZONA_OUT6_OSR 0x2000 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_MASK 0x2000 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_SHIFT 13 /* OUT6_OSR */ +#define ARIZONA_OUT6_OSR_WIDTH 1 /* OUT6_OSR */ +#define ARIZONA_OUT6L_ANC_SRC_MASK 0x0C00 /* OUT6L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6L_ANC_SRC_SHIFT 10 /* OUT6L_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6L_ANC_SRC_WIDTH 2 /* OUT6L_ANC_SRC - [11:10] */ + +/* + * R1081 (0x439) - DAC Digital Volume 6L + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT6L_MUTE 0x0100 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_MASK 0x0100 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_SHIFT 8 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_MUTE_WIDTH 1 /* OUT6L_MUTE */ +#define ARIZONA_OUT6L_VOL_MASK 0x00FF /* OUT6L_VOL - [7:0] */ +#define ARIZONA_OUT6L_VOL_SHIFT 0 /* OUT6L_VOL - [7:0] */ +#define ARIZONA_OUT6L_VOL_WIDTH 8 /* OUT6L_VOL - [7:0] */ + +/* + * R1082 (0x43A) - DAC Volume Limit 6L + */ +#define ARIZONA_OUT6L_VOL_LIM_MASK 0x00FF /* OUT6L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6L_VOL_LIM_SHIFT 0 /* OUT6L_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6L_VOL_LIM_WIDTH 8 /* OUT6L_VOL_LIM - [7:0] */ + +/* + * R1083 (0x43B) - Noise Gate Select 6L + */ +#define ARIZONA_OUT6L_NGATE_SRC_MASK 0x0FFF /* OUT6L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6L_NGATE_SRC_SHIFT 0 /* OUT6L_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6L_NGATE_SRC_WIDTH 12 /* OUT6L_NGATE_SRC - [11:0] */ + +/* + * R1084 (0x43C) - Output Path Config 6R + */ +#define ARIZONA_OUT6R_ANC_SRC_MASK 0x0C00 /* OUT6R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6R_ANC_SRC_SHIFT 10 /* OUT6R_ANC_SRC - [11:10] */ +#define ARIZONA_OUT6R_ANC_SRC_WIDTH 2 /* OUT6R_ANC_SRC - [11:10] */ + +/* + * R1085 (0x43D) - DAC Digital Volume 6R + */ +#define ARIZONA_OUT_VU 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_MASK 0x0200 /* OUT_VU */ +#define ARIZONA_OUT_VU_SHIFT 9 /* OUT_VU */ +#define ARIZONA_OUT_VU_WIDTH 1 /* OUT_VU */ +#define ARIZONA_OUT6R_MUTE 0x0100 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_MASK 0x0100 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_SHIFT 8 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_MUTE_WIDTH 1 /* OUT6R_MUTE */ +#define ARIZONA_OUT6R_VOL_MASK 0x00FF /* OUT6R_VOL - [7:0] */ +#define ARIZONA_OUT6R_VOL_SHIFT 0 /* OUT6R_VOL - [7:0] */ +#define ARIZONA_OUT6R_VOL_WIDTH 8 /* OUT6R_VOL - [7:0] */ + +/* + * R1086 (0x43E) - DAC Volume Limit 6R + */ +#define ARIZONA_OUT6R_VOL_LIM_MASK 0x00FF /* OUT6R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6R_VOL_LIM_SHIFT 0 /* OUT6R_VOL_LIM - [7:0] */ +#define ARIZONA_OUT6R_VOL_LIM_WIDTH 8 /* OUT6R_VOL_LIM - [7:0] */ + +/* + * R1087 (0x43F) - Noise Gate Select 6R + */ +#define ARIZONA_OUT6R_NGATE_SRC_MASK 0x0FFF /* OUT6R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6R_NGATE_SRC_SHIFT 0 /* OUT6R_NGATE_SRC - [11:0] */ +#define ARIZONA_OUT6R_NGATE_SRC_WIDTH 12 /* OUT6R_NGATE_SRC - [11:0] */ + +/* + * R1104 (0x450) - DAC AEC Control 1 + */ +#define ARIZONA_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */ +#define ARIZONA_AEC_LOOPBACK_SRC_SHIFT 2 /* AEC_LOOPBACK_SRC - [5:2] */ +#define ARIZONA_AEC_LOOPBACK_SRC_WIDTH 4 /* AEC_LOOPBACK_SRC - [5:2] */ +#define ARIZONA_AEC_ENA_STS 0x0002 /* AEC_ENA_STS */ +#define ARIZONA_AEC_ENA_STS_MASK 0x0002 /* AEC_ENA_STS */ +#define ARIZONA_AEC_ENA_STS_SHIFT 1 /* AEC_ENA_STS */ +#define ARIZONA_AEC_ENA_STS_WIDTH 1 /* AEC_ENA_STS */ +#define ARIZONA_AEC_LOOPBACK_ENA 0x0001 /* AEC_LOOPBACK_ENA */ +#define ARIZONA_AEC_LOOPBACK_ENA_MASK 0x0001 /* AEC_LOOPBACK_ENA */ +#define ARIZONA_AEC_LOOPBACK_ENA_SHIFT 0 /* AEC_LOOPBACK_ENA */ +#define ARIZONA_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */ + +/* + * R1112 (0x458) - Noise Gate Control + */ +#define ARIZONA_NGATE_HOLD_MASK 0x0030 /* NGATE_HOLD - [5:4] */ +#define ARIZONA_NGATE_HOLD_SHIFT 4 /* NGATE_HOLD - [5:4] */ +#define ARIZONA_NGATE_HOLD_WIDTH 2 /* NGATE_HOLD - [5:4] */ +#define ARIZONA_NGATE_THR_MASK 0x000E /* NGATE_THR - [3:1] */ +#define ARIZONA_NGATE_THR_SHIFT 1 /* NGATE_THR - [3:1] */ +#define ARIZONA_NGATE_THR_WIDTH 3 /* NGATE_THR - [3:1] */ +#define ARIZONA_NGATE_ENA 0x0001 /* NGATE_ENA */ +#define ARIZONA_NGATE_ENA_MASK 0x0001 /* NGATE_ENA */ +#define ARIZONA_NGATE_ENA_SHIFT 0 /* NGATE_ENA */ +#define ARIZONA_NGATE_ENA_WIDTH 1 /* NGATE_ENA */ + +/* + * R1168 (0x490) - PDM SPK1 CTRL 1 + */ +#define ARIZONA_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */ +#define ARIZONA_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */ +#define ARIZONA_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */ +#define ARIZONA_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */ +#define ARIZONA_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */ +#define ARIZONA_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */ +#define ARIZONA_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */ +#define ARIZONA_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */ +#define ARIZONA_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */ +#define ARIZONA_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */ +#define ARIZONA_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */ +#define ARIZONA_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */ +#define ARIZONA_SPK1_MUTE_SEQ1_MASK 0x00FF /* SPK1_MUTE_SEQ1 - [7:0] */ +#define ARIZONA_SPK1_MUTE_SEQ1_SHIFT 0 /* SPK1_MUTE_SEQ1 - [7:0] */ +#define ARIZONA_SPK1_MUTE_SEQ1_WIDTH 8 /* SPK1_MUTE_SEQ1 - [7:0] */ + +/* + * R1169 (0x491) - PDM SPK1 CTRL 2 + */ +#define ARIZONA_SPK1_FMT 0x0001 /* SPK1_FMT */ +#define ARIZONA_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */ +#define ARIZONA_SPK1_FMT_SHIFT 0 /* SPK1_FMT */ +#define ARIZONA_SPK1_FMT_WIDTH 1 /* SPK1_FMT */ + +/* + * R1170 (0x492) - PDM SPK2 CTRL 1 + */ +#define ARIZONA_SPK2R_MUTE 0x2000 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_MASK 0x2000 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_SHIFT 13 /* SPK2R_MUTE */ +#define ARIZONA_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */ +#define ARIZONA_SPK2L_MUTE 0x1000 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_MASK 0x1000 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_SHIFT 12 /* SPK2L_MUTE */ +#define ARIZONA_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */ +#define ARIZONA_SPK2_MUTE_ENDIAN 0x0100 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_MASK 0x0100 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_SHIFT 8 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_ENDIAN_WIDTH 1 /* SPK2_MUTE_ENDIAN */ +#define ARIZONA_SPK2_MUTE_SEQ_MASK 0x00FF /* SPK2_MUTE_SEQ - [7:0] */ +#define ARIZONA_SPK2_MUTE_SEQ_SHIFT 0 /* SPK2_MUTE_SEQ - [7:0] */ +#define ARIZONA_SPK2_MUTE_SEQ_WIDTH 8 /* SPK2_MUTE_SEQ - [7:0] */ + +/* + * R1171 (0x493) - PDM SPK2 CTRL 2 + */ +#define ARIZONA_SPK2_FMT 0x0001 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_MASK 0x0001 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_SHIFT 0 /* SPK2_FMT */ +#define ARIZONA_SPK2_FMT_WIDTH 1 /* SPK2_FMT */ + +/* + * R1244 (0x4DC) - DAC comp 1 + */ +#define ARIZONA_OUT_COMP_COEFF_MASK 0xFFFF /* OUT_COMP_COEFF - [15:0] */ +#define ARIZONA_OUT_COMP_COEFF_SHIFT 0 /* OUT_COMP_COEFF - [15:0] */ +#define ARIZONA_OUT_COMP_COEFF_WIDTH 16 /* OUT_COMP_COEFF - [15:0] */ + +/* + * R1245 (0x4DD) - DAC comp 2 + */ +#define ARIZONA_OUT_COMP_COEFF_1 0x0002 /* OUT_COMP_COEFF */ +#define ARIZONA_OUT_COMP_COEFF_1_MASK 0x0002 /* OUT_COMP_COEFF */ +#define ARIZONA_OUT_COMP_COEFF_1_SHIFT 1 /* OUT_COMP_COEFF */ +#define ARIZONA_OUT_COMP_COEFF_1_WIDTH 1 /* OUT_COMP_COEFF */ +#define ARIZONA_OUT_COMP_COEFF_SEL 0x0001 /* OUT_COMP_COEFF_SEL */ +#define ARIZONA_OUT_COMP_COEFF_SEL_MASK 0x0001 /* OUT_COMP_COEFF_SEL */ +#define ARIZONA_OUT_COMP_COEFF_SEL_SHIFT 0 /* OUT_COMP_COEFF_SEL */ +#define ARIZONA_OUT_COMP_COEFF_SEL_WIDTH 1 /* OUT_COMP_COEFF_SEL */ + +/* + * R1246 (0x4DE) - DAC comp 3 + */ +#define ARIZONA_AEC_COMP_COEFF_MASK 0xFFFF /* AEC_COMP_COEFF - [15:0] */ +#define ARIZONA_AEC_COMP_COEFF_SHIFT 0 /* AEC_COMP_COEFF - [15:0] */ +#define ARIZONA_AEC_COMP_COEFF_WIDTH 16 /* AEC_COMP_COEFF - [15:0] */ + +/* + * R1247 (0x4DF) - DAC comp 4 + */ +#define ARIZONA_AEC_COMP_COEFF_1 0x0002 /* AEC_COMP_COEFF */ +#define ARIZONA_AEC_COMP_COEFF_1_MASK 0x0002 /* AEC_COMP_COEFF */ +#define ARIZONA_AEC_COMP_COEFF_1_SHIFT 1 /* AEC_COMP_COEFF */ +#define ARIZONA_AEC_COMP_COEFF_1_WIDTH 1 /* AEC_COMP_COEFF */ +#define ARIZONA_AEC_COMP_COEFF_SEL 0x0001 /* AEC_COMP_COEFF_SEL */ +#define ARIZONA_AEC_COMP_COEFF_SEL_MASK 0x0001 /* AEC_COMP_COEFF_SEL */ +#define ARIZONA_AEC_COMP_COEFF_SEL_SHIFT 0 /* AEC_COMP_COEFF_SEL */ +#define ARIZONA_AEC_COMP_COEFF_SEL_WIDTH 1 /* AEC_COMP_COEFF_SEL */ + +/* + * R1280 (0x500) - AIF1 BCLK Ctrl + */ +#define ARIZONA_AIF1_BCLK_INV 0x0080 /* AIF1_BCLK_INV */ +#define ARIZONA_AIF1_BCLK_INV_MASK 0x0080 /* AIF1_BCLK_INV */ +#define ARIZONA_AIF1_BCLK_INV_SHIFT 7 /* AIF1_BCLK_INV */ +#define ARIZONA_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */ +#define ARIZONA_AIF1_BCLK_FRC 0x0040 /* AIF1_BCLK_FRC */ +#define ARIZONA_AIF1_BCLK_FRC_MASK 0x0040 /* AIF1_BCLK_FRC */ +#define ARIZONA_AIF1_BCLK_FRC_SHIFT 6 /* AIF1_BCLK_FRC */ +#define ARIZONA_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */ +#define ARIZONA_AIF1_BCLK_MSTR 0x0020 /* AIF1_BCLK_MSTR */ +#define ARIZONA_AIF1_BCLK_MSTR_MASK 0x0020 /* AIF1_BCLK_MSTR */ +#define ARIZONA_AIF1_BCLK_MSTR_SHIFT 5 /* AIF1_BCLK_MSTR */ +#define ARIZONA_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */ +#define ARIZONA_AIF1_BCLK_FREQ_MASK 0x001F /* AIF1_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF1_BCLK_FREQ_SHIFT 0 /* AIF1_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF1_BCLK_FREQ_WIDTH 5 /* AIF1_BCLK_FREQ - [4:0] */ + +/* + * R1281 (0x501) - AIF1 Tx Pin Ctrl + */ +#define ARIZONA_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */ +#define ARIZONA_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */ +#define ARIZONA_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */ +#define ARIZONA_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */ +#define ARIZONA_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */ +#define ARIZONA_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */ +#define ARIZONA_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */ +#define ARIZONA_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */ +#define ARIZONA_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */ +#define ARIZONA_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */ +#define ARIZONA_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */ +#define ARIZONA_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */ +#define ARIZONA_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */ +#define ARIZONA_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */ +#define ARIZONA_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */ +#define ARIZONA_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */ +#define ARIZONA_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */ +#define ARIZONA_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */ +#define ARIZONA_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */ +#define ARIZONA_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */ + +/* + * R1282 (0x502) - AIF1 Rx Pin Ctrl + */ +#define ARIZONA_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */ +#define ARIZONA_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */ +#define ARIZONA_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */ +#define ARIZONA_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */ +#define ARIZONA_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */ +#define ARIZONA_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */ +#define ARIZONA_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */ +#define ARIZONA_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */ +#define ARIZONA_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */ +#define ARIZONA_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */ +#define ARIZONA_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */ +#define ARIZONA_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */ + +/* + * R1283 (0x503) - AIF1 Rate Ctrl + */ +#define ARIZONA_AIF1_RATE_MASK 0x7800 /* AIF1_RATE - [14:11] */ +#define ARIZONA_AIF1_RATE_SHIFT 11 /* AIF1_RATE - [14:11] */ +#define ARIZONA_AIF1_RATE_WIDTH 4 /* AIF1_RATE - [14:11] */ +#define ARIZONA_AIF1_TRI 0x0040 /* AIF1_TRI */ +#define ARIZONA_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */ +#define ARIZONA_AIF1_TRI_SHIFT 6 /* AIF1_TRI */ +#define ARIZONA_AIF1_TRI_WIDTH 1 /* AIF1_TRI */ + +/* + * R1284 (0x504) - AIF1 Format + */ +#define ARIZONA_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */ +#define ARIZONA_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */ +#define ARIZONA_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */ + +/* + * R1285 (0x505) - AIF1 Tx BCLK Rate + */ +#define ARIZONA_AIF1TX_BCPF_MASK 0x1FFF /* AIF1TX_BCPF - [12:0] */ +#define ARIZONA_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [12:0] */ +#define ARIZONA_AIF1TX_BCPF_WIDTH 13 /* AIF1TX_BCPF - [12:0] */ + +/* + * R1286 (0x506) - AIF1 Rx BCLK Rate + */ +#define ARIZONA_AIF1RX_BCPF_MASK 0x1FFF /* AIF1RX_BCPF - [12:0] */ +#define ARIZONA_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [12:0] */ +#define ARIZONA_AIF1RX_BCPF_WIDTH 13 /* AIF1RX_BCPF - [12:0] */ + +/* + * R1287 (0x507) - AIF1 Frame Ctrl 1 + */ +#define ARIZONA_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */ +#define ARIZONA_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */ +#define ARIZONA_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */ +#define ARIZONA_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */ + +/* + * R1288 (0x508) - AIF1 Frame Ctrl 2 + */ +#define ARIZONA_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */ +#define ARIZONA_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */ +#define ARIZONA_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */ +#define ARIZONA_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */ + +/* + * R1289 (0x509) - AIF1 Frame Ctrl 3 + */ +#define ARIZONA_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */ +#define ARIZONA_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */ +#define ARIZONA_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */ + +/* + * R1290 (0x50A) - AIF1 Frame Ctrl 4 + */ +#define ARIZONA_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */ +#define ARIZONA_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */ +#define ARIZONA_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */ + +/* + * R1291 (0x50B) - AIF1 Frame Ctrl 5 + */ +#define ARIZONA_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */ +#define ARIZONA_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */ +#define ARIZONA_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */ + +/* + * R1292 (0x50C) - AIF1 Frame Ctrl 6 + */ +#define ARIZONA_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */ +#define ARIZONA_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */ +#define ARIZONA_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */ + +/* + * R1293 (0x50D) - AIF1 Frame Ctrl 7 + */ +#define ARIZONA_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */ +#define ARIZONA_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */ +#define ARIZONA_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */ + +/* + * R1294 (0x50E) - AIF1 Frame Ctrl 8 + */ +#define ARIZONA_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */ +#define ARIZONA_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */ +#define ARIZONA_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */ + +/* + * R1295 (0x50F) - AIF1 Frame Ctrl 9 + */ +#define ARIZONA_AIF1TX7_SLOT_MASK 0x003F /* AIF1TX7_SLOT - [5:0] */ +#define ARIZONA_AIF1TX7_SLOT_SHIFT 0 /* AIF1TX7_SLOT - [5:0] */ +#define ARIZONA_AIF1TX7_SLOT_WIDTH 6 /* AIF1TX7_SLOT - [5:0] */ + +/* + * R1296 (0x510) - AIF1 Frame Ctrl 10 + */ +#define ARIZONA_AIF1TX8_SLOT_MASK 0x003F /* AIF1TX8_SLOT - [5:0] */ +#define ARIZONA_AIF1TX8_SLOT_SHIFT 0 /* AIF1TX8_SLOT - [5:0] */ +#define ARIZONA_AIF1TX8_SLOT_WIDTH 6 /* AIF1TX8_SLOT - [5:0] */ + +/* + * R1297 (0x511) - AIF1 Frame Ctrl 11 + */ +#define ARIZONA_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */ +#define ARIZONA_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */ +#define ARIZONA_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */ + +/* + * R1298 (0x512) - AIF1 Frame Ctrl 12 + */ +#define ARIZONA_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */ +#define ARIZONA_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */ +#define ARIZONA_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */ + +/* + * R1299 (0x513) - AIF1 Frame Ctrl 13 + */ +#define ARIZONA_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */ +#define ARIZONA_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */ +#define ARIZONA_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */ + +/* + * R1300 (0x514) - AIF1 Frame Ctrl 14 + */ +#define ARIZONA_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */ +#define ARIZONA_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */ +#define ARIZONA_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */ + +/* + * R1301 (0x515) - AIF1 Frame Ctrl 15 + */ +#define ARIZONA_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */ +#define ARIZONA_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */ +#define ARIZONA_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */ + +/* + * R1302 (0x516) - AIF1 Frame Ctrl 16 + */ +#define ARIZONA_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */ +#define ARIZONA_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */ +#define ARIZONA_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */ + +/* + * R1303 (0x517) - AIF1 Frame Ctrl 17 + */ +#define ARIZONA_AIF1RX7_SLOT_MASK 0x003F /* AIF1RX7_SLOT - [5:0] */ +#define ARIZONA_AIF1RX7_SLOT_SHIFT 0 /* AIF1RX7_SLOT - [5:0] */ +#define ARIZONA_AIF1RX7_SLOT_WIDTH 6 /* AIF1RX7_SLOT - [5:0] */ + +/* + * R1304 (0x518) - AIF1 Frame Ctrl 18 + */ +#define ARIZONA_AIF1RX8_SLOT_MASK 0x003F /* AIF1RX8_SLOT - [5:0] */ +#define ARIZONA_AIF1RX8_SLOT_SHIFT 0 /* AIF1RX8_SLOT - [5:0] */ +#define ARIZONA_AIF1RX8_SLOT_WIDTH 6 /* AIF1RX8_SLOT - [5:0] */ + +/* + * R1305 (0x519) - AIF1 Tx Enables + */ +#define ARIZONA_AIF1TX8_ENA 0x0080 /* AIF1TX8_ENA */ +#define ARIZONA_AIF1TX8_ENA_MASK 0x0080 /* AIF1TX8_ENA */ +#define ARIZONA_AIF1TX8_ENA_SHIFT 7 /* AIF1TX8_ENA */ +#define ARIZONA_AIF1TX8_ENA_WIDTH 1 /* AIF1TX8_ENA */ +#define ARIZONA_AIF1TX7_ENA 0x0040 /* AIF1TX7_ENA */ +#define ARIZONA_AIF1TX7_ENA_MASK 0x0040 /* AIF1TX7_ENA */ +#define ARIZONA_AIF1TX7_ENA_SHIFT 6 /* AIF1TX7_ENA */ +#define ARIZONA_AIF1TX7_ENA_WIDTH 1 /* AIF1TX7_ENA */ +#define ARIZONA_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */ +#define ARIZONA_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */ +#define ARIZONA_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */ +#define ARIZONA_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */ +#define ARIZONA_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */ +#define ARIZONA_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */ +#define ARIZONA_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */ +#define ARIZONA_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */ +#define ARIZONA_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */ +#define ARIZONA_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */ +#define ARIZONA_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */ +#define ARIZONA_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */ +#define ARIZONA_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */ +#define ARIZONA_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */ +#define ARIZONA_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */ +#define ARIZONA_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */ +#define ARIZONA_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */ +#define ARIZONA_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */ +#define ARIZONA_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */ +#define ARIZONA_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */ +#define ARIZONA_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */ +#define ARIZONA_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */ +#define ARIZONA_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */ +#define ARIZONA_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */ + +/* + * R1306 (0x51A) - AIF1 Rx Enables + */ +#define ARIZONA_AIF1RX8_ENA 0x0080 /* AIF1RX8_ENA */ +#define ARIZONA_AIF1RX8_ENA_MASK 0x0080 /* AIF1RX8_ENA */ +#define ARIZONA_AIF1RX8_ENA_SHIFT 7 /* AIF1RX8_ENA */ +#define ARIZONA_AIF1RX8_ENA_WIDTH 1 /* AIF1RX8_ENA */ +#define ARIZONA_AIF1RX7_ENA 0x0040 /* AIF1RX7_ENA */ +#define ARIZONA_AIF1RX7_ENA_MASK 0x0040 /* AIF1RX7_ENA */ +#define ARIZONA_AIF1RX7_ENA_SHIFT 6 /* AIF1RX7_ENA */ +#define ARIZONA_AIF1RX7_ENA_WIDTH 1 /* AIF1RX7_ENA */ +#define ARIZONA_AIF1RX6_ENA 0x0020 /* AIF1RX6_ENA */ +#define ARIZONA_AIF1RX6_ENA_MASK 0x0020 /* AIF1RX6_ENA */ +#define ARIZONA_AIF1RX6_ENA_SHIFT 5 /* AIF1RX6_ENA */ +#define ARIZONA_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */ +#define ARIZONA_AIF1RX5_ENA 0x0010 /* AIF1RX5_ENA */ +#define ARIZONA_AIF1RX5_ENA_MASK 0x0010 /* AIF1RX5_ENA */ +#define ARIZONA_AIF1RX5_ENA_SHIFT 4 /* AIF1RX5_ENA */ +#define ARIZONA_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */ +#define ARIZONA_AIF1RX4_ENA 0x0008 /* AIF1RX4_ENA */ +#define ARIZONA_AIF1RX4_ENA_MASK 0x0008 /* AIF1RX4_ENA */ +#define ARIZONA_AIF1RX4_ENA_SHIFT 3 /* AIF1RX4_ENA */ +#define ARIZONA_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */ +#define ARIZONA_AIF1RX3_ENA 0x0004 /* AIF1RX3_ENA */ +#define ARIZONA_AIF1RX3_ENA_MASK 0x0004 /* AIF1RX3_ENA */ +#define ARIZONA_AIF1RX3_ENA_SHIFT 2 /* AIF1RX3_ENA */ +#define ARIZONA_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */ +#define ARIZONA_AIF1RX2_ENA 0x0002 /* AIF1RX2_ENA */ +#define ARIZONA_AIF1RX2_ENA_MASK 0x0002 /* AIF1RX2_ENA */ +#define ARIZONA_AIF1RX2_ENA_SHIFT 1 /* AIF1RX2_ENA */ +#define ARIZONA_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */ +#define ARIZONA_AIF1RX1_ENA 0x0001 /* AIF1RX1_ENA */ +#define ARIZONA_AIF1RX1_ENA_MASK 0x0001 /* AIF1RX1_ENA */ +#define ARIZONA_AIF1RX1_ENA_SHIFT 0 /* AIF1RX1_ENA */ +#define ARIZONA_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */ + +/* + * R1307 (0x51B) - AIF1 Force Write + */ +#define ARIZONA_AIF1_FRC_WR 0x0001 /* AIF1_FRC_WR */ +#define ARIZONA_AIF1_FRC_WR_MASK 0x0001 /* AIF1_FRC_WR */ +#define ARIZONA_AIF1_FRC_WR_SHIFT 0 /* AIF1_FRC_WR */ +#define ARIZONA_AIF1_FRC_WR_WIDTH 1 /* AIF1_FRC_WR */ + +/* + * R1344 (0x540) - AIF2 BCLK Ctrl + */ +#define ARIZONA_AIF2_BCLK_INV 0x0080 /* AIF2_BCLK_INV */ +#define ARIZONA_AIF2_BCLK_INV_MASK 0x0080 /* AIF2_BCLK_INV */ +#define ARIZONA_AIF2_BCLK_INV_SHIFT 7 /* AIF2_BCLK_INV */ +#define ARIZONA_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */ +#define ARIZONA_AIF2_BCLK_FRC 0x0040 /* AIF2_BCLK_FRC */ +#define ARIZONA_AIF2_BCLK_FRC_MASK 0x0040 /* AIF2_BCLK_FRC */ +#define ARIZONA_AIF2_BCLK_FRC_SHIFT 6 /* AIF2_BCLK_FRC */ +#define ARIZONA_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */ +#define ARIZONA_AIF2_BCLK_MSTR 0x0020 /* AIF2_BCLK_MSTR */ +#define ARIZONA_AIF2_BCLK_MSTR_MASK 0x0020 /* AIF2_BCLK_MSTR */ +#define ARIZONA_AIF2_BCLK_MSTR_SHIFT 5 /* AIF2_BCLK_MSTR */ +#define ARIZONA_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */ +#define ARIZONA_AIF2_BCLK_FREQ_MASK 0x001F /* AIF2_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF2_BCLK_FREQ_SHIFT 0 /* AIF2_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF2_BCLK_FREQ_WIDTH 5 /* AIF2_BCLK_FREQ - [4:0] */ + +/* + * R1345 (0x541) - AIF2 Tx Pin Ctrl + */ +#define ARIZONA_AIF2TX_DAT_TRI 0x0020 /* AIF2TX_DAT_TRI */ +#define ARIZONA_AIF2TX_DAT_TRI_MASK 0x0020 /* AIF2TX_DAT_TRI */ +#define ARIZONA_AIF2TX_DAT_TRI_SHIFT 5 /* AIF2TX_DAT_TRI */ +#define ARIZONA_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */ +#define ARIZONA_AIF2TX_LRCLK_SRC 0x0008 /* AIF2TX_LRCLK_SRC */ +#define ARIZONA_AIF2TX_LRCLK_SRC_MASK 0x0008 /* AIF2TX_LRCLK_SRC */ +#define ARIZONA_AIF2TX_LRCLK_SRC_SHIFT 3 /* AIF2TX_LRCLK_SRC */ +#define ARIZONA_AIF2TX_LRCLK_SRC_WIDTH 1 /* AIF2TX_LRCLK_SRC */ +#define ARIZONA_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */ +#define ARIZONA_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */ +#define ARIZONA_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */ +#define ARIZONA_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */ +#define ARIZONA_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */ +#define ARIZONA_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */ +#define ARIZONA_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */ +#define ARIZONA_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */ +#define ARIZONA_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */ +#define ARIZONA_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */ +#define ARIZONA_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */ +#define ARIZONA_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */ + +/* + * R1346 (0x542) - AIF2 Rx Pin Ctrl + */ +#define ARIZONA_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */ +#define ARIZONA_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */ +#define ARIZONA_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */ +#define ARIZONA_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */ +#define ARIZONA_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */ +#define ARIZONA_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */ +#define ARIZONA_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */ +#define ARIZONA_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */ +#define ARIZONA_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */ +#define ARIZONA_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */ +#define ARIZONA_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */ +#define ARIZONA_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */ + +/* + * R1347 (0x543) - AIF2 Rate Ctrl + */ +#define ARIZONA_AIF2_RATE_MASK 0x7800 /* AIF2_RATE - [14:11] */ +#define ARIZONA_AIF2_RATE_SHIFT 11 /* AIF2_RATE - [14:11] */ +#define ARIZONA_AIF2_RATE_WIDTH 4 /* AIF2_RATE - [14:11] */ +#define ARIZONA_AIF2_TRI 0x0040 /* AIF2_TRI */ +#define ARIZONA_AIF2_TRI_MASK 0x0040 /* AIF2_TRI */ +#define ARIZONA_AIF2_TRI_SHIFT 6 /* AIF2_TRI */ +#define ARIZONA_AIF2_TRI_WIDTH 1 /* AIF2_TRI */ + +/* + * R1348 (0x544) - AIF2 Format + */ +#define ARIZONA_AIF2_FMT_MASK 0x0007 /* AIF2_FMT - [2:0] */ +#define ARIZONA_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [2:0] */ +#define ARIZONA_AIF2_FMT_WIDTH 3 /* AIF2_FMT - [2:0] */ + +/* + * R1349 (0x545) - AIF2 Tx BCLK Rate + */ +#define ARIZONA_AIF2TX_BCPF_MASK 0x1FFF /* AIF2TX_BCPF - [12:0] */ +#define ARIZONA_AIF2TX_BCPF_SHIFT 0 /* AIF2TX_BCPF - [12:0] */ +#define ARIZONA_AIF2TX_BCPF_WIDTH 13 /* AIF2TX_BCPF - [12:0] */ + +/* + * R1350 (0x546) - AIF2 Rx BCLK Rate + */ +#define ARIZONA_AIF2RX_BCPF_MASK 0x1FFF /* AIF2RX_BCPF - [12:0] */ +#define ARIZONA_AIF2RX_BCPF_SHIFT 0 /* AIF2RX_BCPF - [12:0] */ +#define ARIZONA_AIF2RX_BCPF_WIDTH 13 /* AIF2RX_BCPF - [12:0] */ + +/* + * R1351 (0x547) - AIF2 Frame Ctrl 1 + */ +#define ARIZONA_AIF2TX_WL_MASK 0x3F00 /* AIF2TX_WL - [13:8] */ +#define ARIZONA_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [13:8] */ +#define ARIZONA_AIF2TX_WL_WIDTH 6 /* AIF2TX_WL - [13:8] */ +#define ARIZONA_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */ + +/* + * R1352 (0x548) - AIF2 Frame Ctrl 2 + */ +#define ARIZONA_AIF2RX_WL_MASK 0x3F00 /* AIF2RX_WL - [13:8] */ +#define ARIZONA_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [13:8] */ +#define ARIZONA_AIF2RX_WL_WIDTH 6 /* AIF2RX_WL - [13:8] */ +#define ARIZONA_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */ + +/* + * R1353 (0x549) - AIF2 Frame Ctrl 3 + */ +#define ARIZONA_AIF2TX1_SLOT_MASK 0x003F /* AIF2TX1_SLOT - [5:0] */ +#define ARIZONA_AIF2TX1_SLOT_SHIFT 0 /* AIF2TX1_SLOT - [5:0] */ +#define ARIZONA_AIF2TX1_SLOT_WIDTH 6 /* AIF2TX1_SLOT - [5:0] */ + +/* + * R1354 (0x54A) - AIF2 Frame Ctrl 4 + */ +#define ARIZONA_AIF2TX2_SLOT_MASK 0x003F /* AIF2TX2_SLOT - [5:0] */ +#define ARIZONA_AIF2TX2_SLOT_SHIFT 0 /* AIF2TX2_SLOT - [5:0] */ +#define ARIZONA_AIF2TX2_SLOT_WIDTH 6 /* AIF2TX2_SLOT - [5:0] */ + +/* + * R1361 (0x551) - AIF2 Frame Ctrl 11 + */ +#define ARIZONA_AIF2RX1_SLOT_MASK 0x003F /* AIF2RX1_SLOT - [5:0] */ +#define ARIZONA_AIF2RX1_SLOT_SHIFT 0 /* AIF2RX1_SLOT - [5:0] */ +#define ARIZONA_AIF2RX1_SLOT_WIDTH 6 /* AIF2RX1_SLOT - [5:0] */ + +/* + * R1362 (0x552) - AIF2 Frame Ctrl 12 + */ +#define ARIZONA_AIF2RX2_SLOT_MASK 0x003F /* AIF2RX2_SLOT - [5:0] */ +#define ARIZONA_AIF2RX2_SLOT_SHIFT 0 /* AIF2RX2_SLOT - [5:0] */ +#define ARIZONA_AIF2RX2_SLOT_WIDTH 6 /* AIF2RX2_SLOT - [5:0] */ + +/* + * R1369 (0x559) - AIF2 Tx Enables + */ +#define ARIZONA_AIF2TX2_ENA 0x0002 /* AIF2TX2_ENA */ +#define ARIZONA_AIF2TX2_ENA_MASK 0x0002 /* AIF2TX2_ENA */ +#define ARIZONA_AIF2TX2_ENA_SHIFT 1 /* AIF2TX2_ENA */ +#define ARIZONA_AIF2TX2_ENA_WIDTH 1 /* AIF2TX2_ENA */ +#define ARIZONA_AIF2TX1_ENA 0x0001 /* AIF2TX1_ENA */ +#define ARIZONA_AIF2TX1_ENA_MASK 0x0001 /* AIF2TX1_ENA */ +#define ARIZONA_AIF2TX1_ENA_SHIFT 0 /* AIF2TX1_ENA */ +#define ARIZONA_AIF2TX1_ENA_WIDTH 1 /* AIF2TX1_ENA */ + +/* + * R1370 (0x55A) - AIF2 Rx Enables + */ +#define ARIZONA_AIF2RX2_ENA 0x0002 /* AIF2RX2_ENA */ +#define ARIZONA_AIF2RX2_ENA_MASK 0x0002 /* AIF2RX2_ENA */ +#define ARIZONA_AIF2RX2_ENA_SHIFT 1 /* AIF2RX2_ENA */ +#define ARIZONA_AIF2RX2_ENA_WIDTH 1 /* AIF2RX2_ENA */ +#define ARIZONA_AIF2RX1_ENA 0x0001 /* AIF2RX1_ENA */ +#define ARIZONA_AIF2RX1_ENA_MASK 0x0001 /* AIF2RX1_ENA */ +#define ARIZONA_AIF2RX1_ENA_SHIFT 0 /* AIF2RX1_ENA */ +#define ARIZONA_AIF2RX1_ENA_WIDTH 1 /* AIF2RX1_ENA */ + +/* + * R1371 (0x55B) - AIF2 Force Write + */ +#define ARIZONA_AIF2_FRC_WR 0x0001 /* AIF2_FRC_WR */ +#define ARIZONA_AIF2_FRC_WR_MASK 0x0001 /* AIF2_FRC_WR */ +#define ARIZONA_AIF2_FRC_WR_SHIFT 0 /* AIF2_FRC_WR */ +#define ARIZONA_AIF2_FRC_WR_WIDTH 1 /* AIF2_FRC_WR */ + +/* + * R1408 (0x580) - AIF3 BCLK Ctrl + */ +#define ARIZONA_AIF3_BCLK_INV 0x0080 /* AIF3_BCLK_INV */ +#define ARIZONA_AIF3_BCLK_INV_MASK 0x0080 /* AIF3_BCLK_INV */ +#define ARIZONA_AIF3_BCLK_INV_SHIFT 7 /* AIF3_BCLK_INV */ +#define ARIZONA_AIF3_BCLK_INV_WIDTH 1 /* AIF3_BCLK_INV */ +#define ARIZONA_AIF3_BCLK_FRC 0x0040 /* AIF3_BCLK_FRC */ +#define ARIZONA_AIF3_BCLK_FRC_MASK 0x0040 /* AIF3_BCLK_FRC */ +#define ARIZONA_AIF3_BCLK_FRC_SHIFT 6 /* AIF3_BCLK_FRC */ +#define ARIZONA_AIF3_BCLK_FRC_WIDTH 1 /* AIF3_BCLK_FRC */ +#define ARIZONA_AIF3_BCLK_MSTR 0x0020 /* AIF3_BCLK_MSTR */ +#define ARIZONA_AIF3_BCLK_MSTR_MASK 0x0020 /* AIF3_BCLK_MSTR */ +#define ARIZONA_AIF3_BCLK_MSTR_SHIFT 5 /* AIF3_BCLK_MSTR */ +#define ARIZONA_AIF3_BCLK_MSTR_WIDTH 1 /* AIF3_BCLK_MSTR */ +#define ARIZONA_AIF3_BCLK_FREQ_MASK 0x001F /* AIF3_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF3_BCLK_FREQ_SHIFT 0 /* AIF3_BCLK_FREQ - [4:0] */ +#define ARIZONA_AIF3_BCLK_FREQ_WIDTH 5 /* AIF3_BCLK_FREQ - [4:0] */ + +/* + * R1409 (0x581) - AIF3 Tx Pin Ctrl + */ +#define ARIZONA_AIF3TX_DAT_TRI 0x0020 /* AIF3TX_DAT_TRI */ +#define ARIZONA_AIF3TX_DAT_TRI_MASK 0x0020 /* AIF3TX_DAT_TRI */ +#define ARIZONA_AIF3TX_DAT_TRI_SHIFT 5 /* AIF3TX_DAT_TRI */ +#define ARIZONA_AIF3TX_DAT_TRI_WIDTH 1 /* AIF3TX_DAT_TRI */ +#define ARIZONA_AIF3TX_LRCLK_SRC 0x0008 /* AIF3TX_LRCLK_SRC */ +#define ARIZONA_AIF3TX_LRCLK_SRC_MASK 0x0008 /* AIF3TX_LRCLK_SRC */ +#define ARIZONA_AIF3TX_LRCLK_SRC_SHIFT 3 /* AIF3TX_LRCLK_SRC */ +#define ARIZONA_AIF3TX_LRCLK_SRC_WIDTH 1 /* AIF3TX_LRCLK_SRC */ +#define ARIZONA_AIF3TX_LRCLK_INV 0x0004 /* AIF3TX_LRCLK_INV */ +#define ARIZONA_AIF3TX_LRCLK_INV_MASK 0x0004 /* AIF3TX_LRCLK_INV */ +#define ARIZONA_AIF3TX_LRCLK_INV_SHIFT 2 /* AIF3TX_LRCLK_INV */ +#define ARIZONA_AIF3TX_LRCLK_INV_WIDTH 1 /* AIF3TX_LRCLK_INV */ +#define ARIZONA_AIF3TX_LRCLK_FRC 0x0002 /* AIF3TX_LRCLK_FRC */ +#define ARIZONA_AIF3TX_LRCLK_FRC_MASK 0x0002 /* AIF3TX_LRCLK_FRC */ +#define ARIZONA_AIF3TX_LRCLK_FRC_SHIFT 1 /* AIF3TX_LRCLK_FRC */ +#define ARIZONA_AIF3TX_LRCLK_FRC_WIDTH 1 /* AIF3TX_LRCLK_FRC */ +#define ARIZONA_AIF3TX_LRCLK_MSTR 0x0001 /* AIF3TX_LRCLK_MSTR */ +#define ARIZONA_AIF3TX_LRCLK_MSTR_MASK 0x0001 /* AIF3TX_LRCLK_MSTR */ +#define ARIZONA_AIF3TX_LRCLK_MSTR_SHIFT 0 /* AIF3TX_LRCLK_MSTR */ +#define ARIZONA_AIF3TX_LRCLK_MSTR_WIDTH 1 /* AIF3TX_LRCLK_MSTR */ + +/* + * R1410 (0x582) - AIF3 Rx Pin Ctrl + */ +#define ARIZONA_AIF3RX_LRCLK_INV 0x0004 /* AIF3RX_LRCLK_INV */ +#define ARIZONA_AIF3RX_LRCLK_INV_MASK 0x0004 /* AIF3RX_LRCLK_INV */ +#define ARIZONA_AIF3RX_LRCLK_INV_SHIFT 2 /* AIF3RX_LRCLK_INV */ +#define ARIZONA_AIF3RX_LRCLK_INV_WIDTH 1 /* AIF3RX_LRCLK_INV */ +#define ARIZONA_AIF3RX_LRCLK_FRC 0x0002 /* AIF3RX_LRCLK_FRC */ +#define ARIZONA_AIF3RX_LRCLK_FRC_MASK 0x0002 /* AIF3RX_LRCLK_FRC */ +#define ARIZONA_AIF3RX_LRCLK_FRC_SHIFT 1 /* AIF3RX_LRCLK_FRC */ +#define ARIZONA_AIF3RX_LRCLK_FRC_WIDTH 1 /* AIF3RX_LRCLK_FRC */ +#define ARIZONA_AIF3RX_LRCLK_MSTR 0x0001 /* AIF3RX_LRCLK_MSTR */ +#define ARIZONA_AIF3RX_LRCLK_MSTR_MASK 0x0001 /* AIF3RX_LRCLK_MSTR */ +#define ARIZONA_AIF3RX_LRCLK_MSTR_SHIFT 0 /* AIF3RX_LRCLK_MSTR */ +#define ARIZONA_AIF3RX_LRCLK_MSTR_WIDTH 1 /* AIF3RX_LRCLK_MSTR */ + +/* + * R1411 (0x583) - AIF3 Rate Ctrl + */ +#define ARIZONA_AIF3_RATE_MASK 0x7800 /* AIF3_RATE - [14:11] */ +#define ARIZONA_AIF3_RATE_SHIFT 11 /* AIF3_RATE - [14:11] */ +#define ARIZONA_AIF3_RATE_WIDTH 4 /* AIF3_RATE - [14:11] */ +#define ARIZONA_AIF3_TRI 0x0040 /* AIF3_TRI */ +#define ARIZONA_AIF3_TRI_MASK 0x0040 /* AIF3_TRI */ +#define ARIZONA_AIF3_TRI_SHIFT 6 /* AIF3_TRI */ +#define ARIZONA_AIF3_TRI_WIDTH 1 /* AIF3_TRI */ + +/* + * R1412 (0x584) - AIF3 Format + */ +#define ARIZONA_AIF3_FMT_MASK 0x0007 /* AIF3_FMT - [2:0] */ +#define ARIZONA_AIF3_FMT_SHIFT 0 /* AIF3_FMT - [2:0] */ +#define ARIZONA_AIF3_FMT_WIDTH 3 /* AIF3_FMT - [2:0] */ + +/* + * R1413 (0x585) - AIF3 Tx BCLK Rate + */ +#define ARIZONA_AIF3TX_BCPF_MASK 0x1FFF /* AIF3TX_BCPF - [12:0] */ +#define ARIZONA_AIF3TX_BCPF_SHIFT 0 /* AIF3TX_BCPF - [12:0] */ +#define ARIZONA_AIF3TX_BCPF_WIDTH 13 /* AIF3TX_BCPF - [12:0] */ + +/* + * R1414 (0x586) - AIF3 Rx BCLK Rate + */ +#define ARIZONA_AIF3RX_BCPF_MASK 0x1FFF /* AIF3RX_BCPF - [12:0] */ +#define ARIZONA_AIF3RX_BCPF_SHIFT 0 /* AIF3RX_BCPF - [12:0] */ +#define ARIZONA_AIF3RX_BCPF_WIDTH 13 /* AIF3RX_BCPF - [12:0] */ + +/* + * R1415 (0x587) - AIF3 Frame Ctrl 1 + */ +#define ARIZONA_AIF3TX_WL_MASK 0x3F00 /* AIF3TX_WL - [13:8] */ +#define ARIZONA_AIF3TX_WL_SHIFT 8 /* AIF3TX_WL - [13:8] */ +#define ARIZONA_AIF3TX_WL_WIDTH 6 /* AIF3TX_WL - [13:8] */ +#define ARIZONA_AIF3TX_SLOT_LEN_MASK 0x00FF /* AIF3TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF3TX_SLOT_LEN_SHIFT 0 /* AIF3TX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF3TX_SLOT_LEN_WIDTH 8 /* AIF3TX_SLOT_LEN - [7:0] */ + +/* + * R1416 (0x588) - AIF3 Frame Ctrl 2 + */ +#define ARIZONA_AIF3RX_WL_MASK 0x3F00 /* AIF3RX_WL - [13:8] */ +#define ARIZONA_AIF3RX_WL_SHIFT 8 /* AIF3RX_WL - [13:8] */ +#define ARIZONA_AIF3RX_WL_WIDTH 6 /* AIF3RX_WL - [13:8] */ +#define ARIZONA_AIF3RX_SLOT_LEN_MASK 0x00FF /* AIF3RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF3RX_SLOT_LEN_SHIFT 0 /* AIF3RX_SLOT_LEN - [7:0] */ +#define ARIZONA_AIF3RX_SLOT_LEN_WIDTH 8 /* AIF3RX_SLOT_LEN - [7:0] */ + +/* + * R1417 (0x589) - AIF3 Frame Ctrl 3 + */ +#define ARIZONA_AIF3TX1_SLOT_MASK 0x003F /* AIF3TX1_SLOT - [5:0] */ +#define ARIZONA_AIF3TX1_SLOT_SHIFT 0 /* AIF3TX1_SLOT - [5:0] */ +#define ARIZONA_AIF3TX1_SLOT_WIDTH 6 /* AIF3TX1_SLOT - [5:0] */ + +/* + * R1418 (0x58A) - AIF3 Frame Ctrl 4 + */ +#define ARIZONA_AIF3TX2_SLOT_MASK 0x003F /* AIF3TX2_SLOT - [5:0] */ +#define ARIZONA_AIF3TX2_SLOT_SHIFT 0 /* AIF3TX2_SLOT - [5:0] */ +#define ARIZONA_AIF3TX2_SLOT_WIDTH 6 /* AIF3TX2_SLOT - [5:0] */ + +/* + * R1425 (0x591) - AIF3 Frame Ctrl 11 + */ +#define ARIZONA_AIF3RX1_SLOT_MASK 0x003F /* AIF3RX1_SLOT - [5:0] */ +#define ARIZONA_AIF3RX1_SLOT_SHIFT 0 /* AIF3RX1_SLOT - [5:0] */ +#define ARIZONA_AIF3RX1_SLOT_WIDTH 6 /* AIF3RX1_SLOT - [5:0] */ + +/* + * R1426 (0x592) - AIF3 Frame Ctrl 12 + */ +#define ARIZONA_AIF3RX2_SLOT_MASK 0x003F /* AIF3RX2_SLOT - [5:0] */ +#define ARIZONA_AIF3RX2_SLOT_SHIFT 0 /* AIF3RX2_SLOT - [5:0] */ +#define ARIZONA_AIF3RX2_SLOT_WIDTH 6 /* AIF3RX2_SLOT - [5:0] */ + +/* + * R1433 (0x599) - AIF3 Tx Enables + */ +#define ARIZONA_AIF3TX2_ENA 0x0002 /* AIF3TX2_ENA */ +#define ARIZONA_AIF3TX2_ENA_MASK 0x0002 /* AIF3TX2_ENA */ +#define ARIZONA_AIF3TX2_ENA_SHIFT 1 /* AIF3TX2_ENA */ +#define ARIZONA_AIF3TX2_ENA_WIDTH 1 /* AIF3TX2_ENA */ +#define ARIZONA_AIF3TX1_ENA 0x0001 /* AIF3TX1_ENA */ +#define ARIZONA_AIF3TX1_ENA_MASK 0x0001 /* AIF3TX1_ENA */ +#define ARIZONA_AIF3TX1_ENA_SHIFT 0 /* AIF3TX1_ENA */ +#define ARIZONA_AIF3TX1_ENA_WIDTH 1 /* AIF3TX1_ENA */ + +/* + * R1434 (0x59A) - AIF3 Rx Enables + */ +#define ARIZONA_AIF3RX2_ENA 0x0002 /* AIF3RX2_ENA */ +#define ARIZONA_AIF3RX2_ENA_MASK 0x0002 /* AIF3RX2_ENA */ +#define ARIZONA_AIF3RX2_ENA_SHIFT 1 /* AIF3RX2_ENA */ +#define ARIZONA_AIF3RX2_ENA_WIDTH 1 /* AIF3RX2_ENA */ +#define ARIZONA_AIF3RX1_ENA 0x0001 /* AIF3RX1_ENA */ +#define ARIZONA_AIF3RX1_ENA_MASK 0x0001 /* AIF3RX1_ENA */ +#define ARIZONA_AIF3RX1_ENA_SHIFT 0 /* AIF3RX1_ENA */ +#define ARIZONA_AIF3RX1_ENA_WIDTH 1 /* AIF3RX1_ENA */ + +/* + * R1435 (0x59B) - AIF3 Force Write + */ +#define ARIZONA_AIF3_FRC_WR 0x0001 /* AIF3_FRC_WR */ +#define ARIZONA_AIF3_FRC_WR_MASK 0x0001 /* AIF3_FRC_WR */ +#define ARIZONA_AIF3_FRC_WR_SHIFT 0 /* AIF3_FRC_WR */ +#define ARIZONA_AIF3_FRC_WR_WIDTH 1 /* AIF3_FRC_WR */ + +/* + * R1507 (0x5E3) - SLIMbus Framer Ref Gear + */ +#define ARIZONA_SLIMCLK_SRC 0x0010 /* SLIMCLK_SRC */ +#define ARIZONA_SLIMCLK_SRC_MASK 0x0010 /* SLIMCLK_SRC */ +#define ARIZONA_SLIMCLK_SRC_SHIFT 4 /* SLIMCLK_SRC */ +#define ARIZONA_SLIMCLK_SRC_WIDTH 1 /* SLIMCLK_SRC */ +#define ARIZONA_FRAMER_REF_GEAR_MASK 0x000F /* FRAMER_REF_GEAR - [3:0] */ +#define ARIZONA_FRAMER_REF_GEAR_SHIFT 0 /* FRAMER_REF_GEAR - [3:0] */ +#define ARIZONA_FRAMER_REF_GEAR_WIDTH 4 /* FRAMER_REF_GEAR - [3:0] */ + +/* + * R1509 (0x5E5) - SLIMbus Rates 1 + */ +#define ARIZONA_SLIMRX2_RATE_MASK 0x7800 /* SLIMRX2_RATE - [14:11] */ +#define ARIZONA_SLIMRX2_RATE_SHIFT 11 /* SLIMRX2_RATE - [14:11] */ +#define ARIZONA_SLIMRX2_RATE_WIDTH 4 /* SLIMRX2_RATE - [14:11] */ +#define ARIZONA_SLIMRX1_RATE_MASK 0x0078 /* SLIMRX1_RATE - [6:3] */ +#define ARIZONA_SLIMRX1_RATE_SHIFT 3 /* SLIMRX1_RATE - [6:3] */ +#define ARIZONA_SLIMRX1_RATE_WIDTH 4 /* SLIMRX1_RATE - [6:3] */ + +/* + * R1510 (0x5E6) - SLIMbus Rates 2 + */ +#define ARIZONA_SLIMRX4_RATE_MASK 0x7800 /* SLIMRX4_RATE - [14:11] */ +#define ARIZONA_SLIMRX4_RATE_SHIFT 11 /* SLIMRX4_RATE - [14:11] */ +#define ARIZONA_SLIMRX4_RATE_WIDTH 4 /* SLIMRX4_RATE - [14:11] */ +#define ARIZONA_SLIMRX3_RATE_MASK 0x0078 /* SLIMRX3_RATE - [6:3] */ +#define ARIZONA_SLIMRX3_RATE_SHIFT 3 /* SLIMRX3_RATE - [6:3] */ +#define ARIZONA_SLIMRX3_RATE_WIDTH 4 /* SLIMRX3_RATE - [6:3] */ + +/* + * R1511 (0x5E7) - SLIMbus Rates 3 + */ +#define ARIZONA_SLIMRX6_RATE_MASK 0x7800 /* SLIMRX6_RATE - [14:11] */ +#define ARIZONA_SLIMRX6_RATE_SHIFT 11 /* SLIMRX6_RATE - [14:11] */ +#define ARIZONA_SLIMRX6_RATE_WIDTH 4 /* SLIMRX6_RATE - [14:11] */ +#define ARIZONA_SLIMRX5_RATE_MASK 0x0078 /* SLIMRX5_RATE - [6:3] */ +#define ARIZONA_SLIMRX5_RATE_SHIFT 3 /* SLIMRX5_RATE - [6:3] */ +#define ARIZONA_SLIMRX5_RATE_WIDTH 4 /* SLIMRX5_RATE - [6:3] */ + +/* + * R1512 (0x5E8) - SLIMbus Rates 4 + */ +#define ARIZONA_SLIMRX8_RATE_MASK 0x7800 /* SLIMRX8_RATE - [14:11] */ +#define ARIZONA_SLIMRX8_RATE_SHIFT 11 /* SLIMRX8_RATE - [14:11] */ +#define ARIZONA_SLIMRX8_RATE_WIDTH 4 /* SLIMRX8_RATE - [14:11] */ +#define ARIZONA_SLIMRX7_RATE_MASK 0x0078 /* SLIMRX7_RATE - [6:3] */ +#define ARIZONA_SLIMRX7_RATE_SHIFT 3 /* SLIMRX7_RATE - [6:3] */ +#define ARIZONA_SLIMRX7_RATE_WIDTH 4 /* SLIMRX7_RATE - [6:3] */ + +/* + * R1513 (0x5E9) - SLIMbus Rates 5 + */ +#define ARIZONA_SLIMTX2_RATE_MASK 0x7800 /* SLIMTX2_RATE - [14:11] */ +#define ARIZONA_SLIMTX2_RATE_SHIFT 11 /* SLIMTX2_RATE - [14:11] */ +#define ARIZONA_SLIMTX2_RATE_WIDTH 4 /* SLIMTX2_RATE - [14:11] */ +#define ARIZONA_SLIMTX1_RATE_MASK 0x0078 /* SLIMTX1_RATE - [6:3] */ +#define ARIZONA_SLIMTX1_RATE_SHIFT 3 /* SLIMTX1_RATE - [6:3] */ +#define ARIZONA_SLIMTX1_RATE_WIDTH 4 /* SLIMTX1_RATE - [6:3] */ + +/* + * R1514 (0x5EA) - SLIMbus Rates 6 + */ +#define ARIZONA_SLIMTX4_RATE_MASK 0x7800 /* SLIMTX4_RATE - [14:11] */ +#define ARIZONA_SLIMTX4_RATE_SHIFT 11 /* SLIMTX4_RATE - [14:11] */ +#define ARIZONA_SLIMTX4_RATE_WIDTH 4 /* SLIMTX4_RATE - [14:11] */ +#define ARIZONA_SLIMTX3_RATE_MASK 0x0078 /* SLIMTX3_RATE - [6:3] */ +#define ARIZONA_SLIMTX3_RATE_SHIFT 3 /* SLIMTX3_RATE - [6:3] */ +#define ARIZONA_SLIMTX3_RATE_WIDTH 4 /* SLIMTX3_RATE - [6:3] */ + +/* + * R1515 (0x5EB) - SLIMbus Rates 7 + */ +#define ARIZONA_SLIMTX6_RATE_MASK 0x7800 /* SLIMTX6_RATE - [14:11] */ +#define ARIZONA_SLIMTX6_RATE_SHIFT 11 /* SLIMTX6_RATE - [14:11] */ +#define ARIZONA_SLIMTX6_RATE_WIDTH 4 /* SLIMTX6_RATE - [14:11] */ +#define ARIZONA_SLIMTX5_RATE_MASK 0x0078 /* SLIMTX5_RATE - [6:3] */ +#define ARIZONA_SLIMTX5_RATE_SHIFT 3 /* SLIMTX5_RATE - [6:3] */ +#define ARIZONA_SLIMTX5_RATE_WIDTH 4 /* SLIMTX5_RATE - [6:3] */ + +/* + * R1516 (0x5EC) - SLIMbus Rates 8 + */ +#define ARIZONA_SLIMTX8_RATE_MASK 0x7800 /* SLIMTX8_RATE - [14:11] */ +#define ARIZONA_SLIMTX8_RATE_SHIFT 11 /* SLIMTX8_RATE - [14:11] */ +#define ARIZONA_SLIMTX8_RATE_WIDTH 4 /* SLIMTX8_RATE - [14:11] */ +#define ARIZONA_SLIMTX7_RATE_MASK 0x0078 /* SLIMTX7_RATE - [6:3] */ +#define ARIZONA_SLIMTX7_RATE_SHIFT 3 /* SLIMTX7_RATE - [6:3] */ +#define ARIZONA_SLIMTX7_RATE_WIDTH 4 /* SLIMTX7_RATE - [6:3] */ + +/* + * R1525 (0x5F5) - SLIMbus RX Channel Enable + */ +#define ARIZONA_SLIMRX8_ENA 0x0080 /* SLIMRX8_ENA */ +#define ARIZONA_SLIMRX8_ENA_MASK 0x0080 /* SLIMRX8_ENA */ +#define ARIZONA_SLIMRX8_ENA_SHIFT 7 /* SLIMRX8_ENA */ +#define ARIZONA_SLIMRX8_ENA_WIDTH 1 /* SLIMRX8_ENA */ +#define ARIZONA_SLIMRX7_ENA 0x0040 /* SLIMRX7_ENA */ +#define ARIZONA_SLIMRX7_ENA_MASK 0x0040 /* SLIMRX7_ENA */ +#define ARIZONA_SLIMRX7_ENA_SHIFT 6 /* SLIMRX7_ENA */ +#define ARIZONA_SLIMRX7_ENA_WIDTH 1 /* SLIMRX7_ENA */ +#define ARIZONA_SLIMRX6_ENA 0x0020 /* SLIMRX6_ENA */ +#define ARIZONA_SLIMRX6_ENA_MASK 0x0020 /* SLIMRX6_ENA */ +#define ARIZONA_SLIMRX6_ENA_SHIFT 5 /* SLIMRX6_ENA */ +#define ARIZONA_SLIMRX6_ENA_WIDTH 1 /* SLIMRX6_ENA */ +#define ARIZONA_SLIMRX5_ENA 0x0010 /* SLIMRX5_ENA */ +#define ARIZONA_SLIMRX5_ENA_MASK 0x0010 /* SLIMRX5_ENA */ +#define ARIZONA_SLIMRX5_ENA_SHIFT 4 /* SLIMRX5_ENA */ +#define ARIZONA_SLIMRX5_ENA_WIDTH 1 /* SLIMRX5_ENA */ +#define ARIZONA_SLIMRX4_ENA 0x0008 /* SLIMRX4_ENA */ +#define ARIZONA_SLIMRX4_ENA_MASK 0x0008 /* SLIMRX4_ENA */ +#define ARIZONA_SLIMRX4_ENA_SHIFT 3 /* SLIMRX4_ENA */ +#define ARIZONA_SLIMRX4_ENA_WIDTH 1 /* SLIMRX4_ENA */ +#define ARIZONA_SLIMRX3_ENA 0x0004 /* SLIMRX3_ENA */ +#define ARIZONA_SLIMRX3_ENA_MASK 0x0004 /* SLIMRX3_ENA */ +#define ARIZONA_SLIMRX3_ENA_SHIFT 2 /* SLIMRX3_ENA */ +#define ARIZONA_SLIMRX3_ENA_WIDTH 1 /* SLIMRX3_ENA */ +#define ARIZONA_SLIMRX2_ENA 0x0002 /* SLIMRX2_ENA */ +#define ARIZONA_SLIMRX2_ENA_MASK 0x0002 /* SLIMRX2_ENA */ +#define ARIZONA_SLIMRX2_ENA_SHIFT 1 /* SLIMRX2_ENA */ +#define ARIZONA_SLIMRX2_ENA_WIDTH 1 /* SLIMRX2_ENA */ +#define ARIZONA_SLIMRX1_ENA 0x0001 /* SLIMRX1_ENA */ +#define ARIZONA_SLIMRX1_ENA_MASK 0x0001 /* SLIMRX1_ENA */ +#define ARIZONA_SLIMRX1_ENA_SHIFT 0 /* SLIMRX1_ENA */ +#define ARIZONA_SLIMRX1_ENA_WIDTH 1 /* SLIMRX1_ENA */ + +/* + * R1526 (0x5F6) - SLIMbus TX Channel Enable + */ +#define ARIZONA_SLIMTX8_ENA 0x0080 /* SLIMTX8_ENA */ +#define ARIZONA_SLIMTX8_ENA_MASK 0x0080 /* SLIMTX8_ENA */ +#define ARIZONA_SLIMTX8_ENA_SHIFT 7 /* SLIMTX8_ENA */ +#define ARIZONA_SLIMTX8_ENA_WIDTH 1 /* SLIMTX8_ENA */ +#define ARIZONA_SLIMTX7_ENA 0x0040 /* SLIMTX7_ENA */ +#define ARIZONA_SLIMTX7_ENA_MASK 0x0040 /* SLIMTX7_ENA */ +#define ARIZONA_SLIMTX7_ENA_SHIFT 6 /* SLIMTX7_ENA */ +#define ARIZONA_SLIMTX7_ENA_WIDTH 1 /* SLIMTX7_ENA */ +#define ARIZONA_SLIMTX6_ENA 0x0020 /* SLIMTX6_ENA */ +#define ARIZONA_SLIMTX6_ENA_MASK 0x0020 /* SLIMTX6_ENA */ +#define ARIZONA_SLIMTX6_ENA_SHIFT 5 /* SLIMTX6_ENA */ +#define ARIZONA_SLIMTX6_ENA_WIDTH 1 /* SLIMTX6_ENA */ +#define ARIZONA_SLIMTX5_ENA 0x0010 /* SLIMTX5_ENA */ +#define ARIZONA_SLIMTX5_ENA_MASK 0x0010 /* SLIMTX5_ENA */ +#define ARIZONA_SLIMTX5_ENA_SHIFT 4 /* SLIMTX5_ENA */ +#define ARIZONA_SLIMTX5_ENA_WIDTH 1 /* SLIMTX5_ENA */ +#define ARIZONA_SLIMTX4_ENA 0x0008 /* SLIMTX4_ENA */ +#define ARIZONA_SLIMTX4_ENA_MASK 0x0008 /* SLIMTX4_ENA */ +#define ARIZONA_SLIMTX4_ENA_SHIFT 3 /* SLIMTX4_ENA */ +#define ARIZONA_SLIMTX4_ENA_WIDTH 1 /* SLIMTX4_ENA */ +#define ARIZONA_SLIMTX3_ENA 0x0004 /* SLIMTX3_ENA */ +#define ARIZONA_SLIMTX3_ENA_MASK 0x0004 /* SLIMTX3_ENA */ +#define ARIZONA_SLIMTX3_ENA_SHIFT 2 /* SLIMTX3_ENA */ +#define ARIZONA_SLIMTX3_ENA_WIDTH 1 /* SLIMTX3_ENA */ +#define ARIZONA_SLIMTX2_ENA 0x0002 /* SLIMTX2_ENA */ +#define ARIZONA_SLIMTX2_ENA_MASK 0x0002 /* SLIMTX2_ENA */ +#define ARIZONA_SLIMTX2_ENA_SHIFT 1 /* SLIMTX2_ENA */ +#define ARIZONA_SLIMTX2_ENA_WIDTH 1 /* SLIMTX2_ENA */ +#define ARIZONA_SLIMTX1_ENA 0x0001 /* SLIMTX1_ENA */ +#define ARIZONA_SLIMTX1_ENA_MASK 0x0001 /* SLIMTX1_ENA */ +#define ARIZONA_SLIMTX1_ENA_SHIFT 0 /* SLIMTX1_ENA */ +#define ARIZONA_SLIMTX1_ENA_WIDTH 1 /* SLIMTX1_ENA */ + +/* + * R1527 (0x5F7) - SLIMbus RX Port Status + */ +#define ARIZONA_SLIMRX8_PORT_STS 0x0080 /* SLIMRX8_PORT_STS */ +#define ARIZONA_SLIMRX8_PORT_STS_MASK 0x0080 /* SLIMRX8_PORT_STS */ +#define ARIZONA_SLIMRX8_PORT_STS_SHIFT 7 /* SLIMRX8_PORT_STS */ +#define ARIZONA_SLIMRX8_PORT_STS_WIDTH 1 /* SLIMRX8_PORT_STS */ +#define ARIZONA_SLIMRX7_PORT_STS 0x0040 /* SLIMRX7_PORT_STS */ +#define ARIZONA_SLIMRX7_PORT_STS_MASK 0x0040 /* SLIMRX7_PORT_STS */ +#define ARIZONA_SLIMRX7_PORT_STS_SHIFT 6 /* SLIMRX7_PORT_STS */ +#define ARIZONA_SLIMRX7_PORT_STS_WIDTH 1 /* SLIMRX7_PORT_STS */ +#define ARIZONA_SLIMRX6_PORT_STS 0x0020 /* SLIMRX6_PORT_STS */ +#define ARIZONA_SLIMRX6_PORT_STS_MASK 0x0020 /* SLIMRX6_PORT_STS */ +#define ARIZONA_SLIMRX6_PORT_STS_SHIFT 5 /* SLIMRX6_PORT_STS */ +#define ARIZONA_SLIMRX6_PORT_STS_WIDTH 1 /* SLIMRX6_PORT_STS */ +#define ARIZONA_SLIMRX5_PORT_STS 0x0010 /* SLIMRX5_PORT_STS */ +#define ARIZONA_SLIMRX5_PORT_STS_MASK 0x0010 /* SLIMRX5_PORT_STS */ +#define ARIZONA_SLIMRX5_PORT_STS_SHIFT 4 /* SLIMRX5_PORT_STS */ +#define ARIZONA_SLIMRX5_PORT_STS_WIDTH 1 /* SLIMRX5_PORT_STS */ +#define ARIZONA_SLIMRX4_PORT_STS 0x0008 /* SLIMRX4_PORT_STS */ +#define ARIZONA_SLIMRX4_PORT_STS_MASK 0x0008 /* SLIMRX4_PORT_STS */ +#define ARIZONA_SLIMRX4_PORT_STS_SHIFT 3 /* SLIMRX4_PORT_STS */ +#define ARIZONA_SLIMRX4_PORT_STS_WIDTH 1 /* SLIMRX4_PORT_STS */ +#define ARIZONA_SLIMRX3_PORT_STS 0x0004 /* SLIMRX3_PORT_STS */ +#define ARIZONA_SLIMRX3_PORT_STS_MASK 0x0004 /* SLIMRX3_PORT_STS */ +#define ARIZONA_SLIMRX3_PORT_STS_SHIFT 2 /* SLIMRX3_PORT_STS */ +#define ARIZONA_SLIMRX3_PORT_STS_WIDTH 1 /* SLIMRX3_PORT_STS */ +#define ARIZONA_SLIMRX2_PORT_STS 0x0002 /* SLIMRX2_PORT_STS */ +#define ARIZONA_SLIMRX2_PORT_STS_MASK 0x0002 /* SLIMRX2_PORT_STS */ +#define ARIZONA_SLIMRX2_PORT_STS_SHIFT 1 /* SLIMRX2_PORT_STS */ +#define ARIZONA_SLIMRX2_PORT_STS_WIDTH 1 /* SLIMRX2_PORT_STS */ +#define ARIZONA_SLIMRX1_PORT_STS 0x0001 /* SLIMRX1_PORT_STS */ +#define ARIZONA_SLIMRX1_PORT_STS_MASK 0x0001 /* SLIMRX1_PORT_STS */ +#define ARIZONA_SLIMRX1_PORT_STS_SHIFT 0 /* SLIMRX1_PORT_STS */ +#define ARIZONA_SLIMRX1_PORT_STS_WIDTH 1 /* SLIMRX1_PORT_STS */ + +/* + * R1528 (0x5F8) - SLIMbus TX Port Status + */ +#define ARIZONA_SLIMTX8_PORT_STS 0x0080 /* SLIMTX8_PORT_STS */ +#define ARIZONA_SLIMTX8_PORT_STS_MASK 0x0080 /* SLIMTX8_PORT_STS */ +#define ARIZONA_SLIMTX8_PORT_STS_SHIFT 7 /* SLIMTX8_PORT_STS */ +#define ARIZONA_SLIMTX8_PORT_STS_WIDTH 1 /* SLIMTX8_PORT_STS */ +#define ARIZONA_SLIMTX7_PORT_STS 0x0040 /* SLIMTX7_PORT_STS */ +#define ARIZONA_SLIMTX7_PORT_STS_MASK 0x0040 /* SLIMTX7_PORT_STS */ +#define ARIZONA_SLIMTX7_PORT_STS_SHIFT 6 /* SLIMTX7_PORT_STS */ +#define ARIZONA_SLIMTX7_PORT_STS_WIDTH 1 /* SLIMTX7_PORT_STS */ +#define ARIZONA_SLIMTX6_PORT_STS 0x0020 /* SLIMTX6_PORT_STS */ +#define ARIZONA_SLIMTX6_PORT_STS_MASK 0x0020 /* SLIMTX6_PORT_STS */ +#define ARIZONA_SLIMTX6_PORT_STS_SHIFT 5 /* SLIMTX6_PORT_STS */ +#define ARIZONA_SLIMTX6_PORT_STS_WIDTH 1 /* SLIMTX6_PORT_STS */ +#define ARIZONA_SLIMTX5_PORT_STS 0x0010 /* SLIMTX5_PORT_STS */ +#define ARIZONA_SLIMTX5_PORT_STS_MASK 0x0010 /* SLIMTX5_PORT_STS */ +#define ARIZONA_SLIMTX5_PORT_STS_SHIFT 4 /* SLIMTX5_PORT_STS */ +#define ARIZONA_SLIMTX5_PORT_STS_WIDTH 1 /* SLIMTX5_PORT_STS */ +#define ARIZONA_SLIMTX4_PORT_STS 0x0008 /* SLIMTX4_PORT_STS */ +#define ARIZONA_SLIMTX4_PORT_STS_MASK 0x0008 /* SLIMTX4_PORT_STS */ +#define ARIZONA_SLIMTX4_PORT_STS_SHIFT 3 /* SLIMTX4_PORT_STS */ +#define ARIZONA_SLIMTX4_PORT_STS_WIDTH 1 /* SLIMTX4_PORT_STS */ +#define ARIZONA_SLIMTX3_PORT_STS 0x0004 /* SLIMTX3_PORT_STS */ +#define ARIZONA_SLIMTX3_PORT_STS_MASK 0x0004 /* SLIMTX3_PORT_STS */ +#define ARIZONA_SLIMTX3_PORT_STS_SHIFT 2 /* SLIMTX3_PORT_STS */ +#define ARIZONA_SLIMTX3_PORT_STS_WIDTH 1 /* SLIMTX3_PORT_STS */ +#define ARIZONA_SLIMTX2_PORT_STS 0x0002 /* SLIMTX2_PORT_STS */ +#define ARIZONA_SLIMTX2_PORT_STS_MASK 0x0002 /* SLIMTX2_PORT_STS */ +#define ARIZONA_SLIMTX2_PORT_STS_SHIFT 1 /* SLIMTX2_PORT_STS */ +#define ARIZONA_SLIMTX2_PORT_STS_WIDTH 1 /* SLIMTX2_PORT_STS */ +#define ARIZONA_SLIMTX1_PORT_STS 0x0001 /* SLIMTX1_PORT_STS */ +#define ARIZONA_SLIMTX1_PORT_STS_MASK 0x0001 /* SLIMTX1_PORT_STS */ +#define ARIZONA_SLIMTX1_PORT_STS_SHIFT 0 /* SLIMTX1_PORT_STS */ +#define ARIZONA_SLIMTX1_PORT_STS_WIDTH 1 /* SLIMTX1_PORT_STS */ + +/* + * R3087 (0xC0F) - IRQ CTRL 1 + */ +#define ARIZONA_IRQ_POL 0x0400 /* IRQ_POL */ +#define ARIZONA_IRQ_POL_MASK 0x0400 /* IRQ_POL */ +#define ARIZONA_IRQ_POL_SHIFT 10 /* IRQ_POL */ +#define ARIZONA_IRQ_POL_WIDTH 1 /* IRQ_POL */ +#define ARIZONA_IRQ_OP_CFG 0x0200 /* IRQ_OP_CFG */ +#define ARIZONA_IRQ_OP_CFG_MASK 0x0200 /* IRQ_OP_CFG */ +#define ARIZONA_IRQ_OP_CFG_SHIFT 9 /* IRQ_OP_CFG */ +#define ARIZONA_IRQ_OP_CFG_WIDTH 1 /* IRQ_OP_CFG */ + +/* + * R3088 (0xC10) - GPIO Debounce Config + */ +#define ARIZONA_GP_DBTIME_MASK 0xF000 /* GP_DBTIME - [15:12] */ +#define ARIZONA_GP_DBTIME_SHIFT 12 /* GP_DBTIME - [15:12] */ +#define ARIZONA_GP_DBTIME_WIDTH 4 /* GP_DBTIME - [15:12] */ + +/* + * R3104 (0xC20) - Misc Pad Ctrl 1 + */ +#define ARIZONA_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */ +#define ARIZONA_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */ +#define ARIZONA_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */ +#define ARIZONA_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */ +#define ARIZONA_MCLK2_PD 0x2000 /* MCLK2_PD */ +#define ARIZONA_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */ +#define ARIZONA_MCLK2_PD_SHIFT 13 /* MCLK2_PD */ +#define ARIZONA_MCLK2_PD_WIDTH 1 /* MCLK2_PD */ +#define ARIZONA_RSTB_PU 0x0002 /* RSTB_PU */ +#define ARIZONA_RSTB_PU_MASK 0x0002 /* RSTB_PU */ +#define ARIZONA_RSTB_PU_SHIFT 1 /* RSTB_PU */ +#define ARIZONA_RSTB_PU_WIDTH 1 /* RSTB_PU */ + +/* + * R3105 (0xC21) - Misc Pad Ctrl 2 + */ +#define ARIZONA_MCLK1_PD 0x1000 /* MCLK1_PD */ +#define ARIZONA_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */ +#define ARIZONA_MCLK1_PD_SHIFT 12 /* MCLK1_PD */ +#define ARIZONA_MCLK1_PD_WIDTH 1 /* MCLK1_PD */ +#define ARIZONA_MICD_PD 0x0100 /* MICD_PD */ +#define ARIZONA_MICD_PD_MASK 0x0100 /* MICD_PD */ +#define ARIZONA_MICD_PD_SHIFT 8 /* MICD_PD */ +#define ARIZONA_MICD_PD_WIDTH 1 /* MICD_PD */ +#define ARIZONA_ADDR_PD 0x0001 /* ADDR_PD */ +#define ARIZONA_ADDR_PD_MASK 0x0001 /* ADDR_PD */ +#define ARIZONA_ADDR_PD_SHIFT 0 /* ADDR_PD */ +#define ARIZONA_ADDR_PD_WIDTH 1 /* ADDR_PD */ + +/* + * R3106 (0xC22) - Misc Pad Ctrl 3 + */ +#define ARIZONA_DMICDAT4_PD 0x0008 /* DMICDAT4_PD */ +#define ARIZONA_DMICDAT4_PD_MASK 0x0008 /* DMICDAT4_PD */ +#define ARIZONA_DMICDAT4_PD_SHIFT 3 /* DMICDAT4_PD */ +#define ARIZONA_DMICDAT4_PD_WIDTH 1 /* DMICDAT4_PD */ +#define ARIZONA_DMICDAT3_PD 0x0004 /* DMICDAT3_PD */ +#define ARIZONA_DMICDAT3_PD_MASK 0x0004 /* DMICDAT3_PD */ +#define ARIZONA_DMICDAT3_PD_SHIFT 2 /* DMICDAT3_PD */ +#define ARIZONA_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */ +#define ARIZONA_DMICDAT2_PD 0x0002 /* DMICDAT2_PD */ +#define ARIZONA_DMICDAT2_PD_MASK 0x0002 /* DMICDAT2_PD */ +#define ARIZONA_DMICDAT2_PD_SHIFT 1 /* DMICDAT2_PD */ +#define ARIZONA_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */ +#define ARIZONA_DMICDAT1_PD 0x0001 /* DMICDAT1_PD */ +#define ARIZONA_DMICDAT1_PD_MASK 0x0001 /* DMICDAT1_PD */ +#define ARIZONA_DMICDAT1_PD_SHIFT 0 /* DMICDAT1_PD */ +#define ARIZONA_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */ + +/* + * R3107 (0xC23) - Misc Pad Ctrl 4 + */ +#define ARIZONA_AIF1RXLRCLK_PU 0x0020 /* AIF1RXLRCLK_PU */ +#define ARIZONA_AIF1RXLRCLK_PU_MASK 0x0020 /* AIF1RXLRCLK_PU */ +#define ARIZONA_AIF1RXLRCLK_PU_SHIFT 5 /* AIF1RXLRCLK_PU */ +#define ARIZONA_AIF1RXLRCLK_PU_WIDTH 1 /* AIF1RXLRCLK_PU */ +#define ARIZONA_AIF1RXLRCLK_PD 0x0010 /* AIF1RXLRCLK_PD */ +#define ARIZONA_AIF1RXLRCLK_PD_MASK 0x0010 /* AIF1RXLRCLK_PD */ +#define ARIZONA_AIF1RXLRCLK_PD_SHIFT 4 /* AIF1RXLRCLK_PD */ +#define ARIZONA_AIF1RXLRCLK_PD_WIDTH 1 /* AIF1RXLRCLK_PD */ +#define ARIZONA_AIF1BCLK_PU 0x0008 /* AIF1BCLK_PU */ +#define ARIZONA_AIF1BCLK_PU_MASK 0x0008 /* AIF1BCLK_PU */ +#define ARIZONA_AIF1BCLK_PU_SHIFT 3 /* AIF1BCLK_PU */ +#define ARIZONA_AIF1BCLK_PU_WIDTH 1 /* AIF1BCLK_PU */ +#define ARIZONA_AIF1BCLK_PD 0x0004 /* AIF1BCLK_PD */ +#define ARIZONA_AIF1BCLK_PD_MASK 0x0004 /* AIF1BCLK_PD */ +#define ARIZONA_AIF1BCLK_PD_SHIFT 2 /* AIF1BCLK_PD */ +#define ARIZONA_AIF1BCLK_PD_WIDTH 1 /* AIF1BCLK_PD */ +#define ARIZONA_AIF1RXDAT_PU 0x0002 /* AIF1RXDAT_PU */ +#define ARIZONA_AIF1RXDAT_PU_MASK 0x0002 /* AIF1RXDAT_PU */ +#define ARIZONA_AIF1RXDAT_PU_SHIFT 1 /* AIF1RXDAT_PU */ +#define ARIZONA_AIF1RXDAT_PU_WIDTH 1 /* AIF1RXDAT_PU */ +#define ARIZONA_AIF1RXDAT_PD 0x0001 /* AIF1RXDAT_PD */ +#define ARIZONA_AIF1RXDAT_PD_MASK 0x0001 /* AIF1RXDAT_PD */ +#define ARIZONA_AIF1RXDAT_PD_SHIFT 0 /* AIF1RXDAT_PD */ +#define ARIZONA_AIF1RXDAT_PD_WIDTH 1 /* AIF1RXDAT_PD */ + +/* + * R3108 (0xC24) - Misc Pad Ctrl 5 + */ +#define ARIZONA_AIF2RXLRCLK_PU 0x0020 /* AIF2RXLRCLK_PU */ +#define ARIZONA_AIF2RXLRCLK_PU_MASK 0x0020 /* AIF2RXLRCLK_PU */ +#define ARIZONA_AIF2RXLRCLK_PU_SHIFT 5 /* AIF2RXLRCLK_PU */ +#define ARIZONA_AIF2RXLRCLK_PU_WIDTH 1 /* AIF2RXLRCLK_PU */ +#define ARIZONA_AIF2RXLRCLK_PD 0x0010 /* AIF2RXLRCLK_PD */ +#define ARIZONA_AIF2RXLRCLK_PD_MASK 0x0010 /* AIF2RXLRCLK_PD */ +#define ARIZONA_AIF2RXLRCLK_PD_SHIFT 4 /* AIF2RXLRCLK_PD */ +#define ARIZONA_AIF2RXLRCLK_PD_WIDTH 1 /* AIF2RXLRCLK_PD */ +#define ARIZONA_AIF2BCLK_PU 0x0008 /* AIF2BCLK_PU */ +#define ARIZONA_AIF2BCLK_PU_MASK 0x0008 /* AIF2BCLK_PU */ +#define ARIZONA_AIF2BCLK_PU_SHIFT 3 /* AIF2BCLK_PU */ +#define ARIZONA_AIF2BCLK_PU_WIDTH 1 /* AIF2BCLK_PU */ +#define ARIZONA_AIF2BCLK_PD 0x0004 /* AIF2BCLK_PD */ +#define ARIZONA_AIF2BCLK_PD_MASK 0x0004 /* AIF2BCLK_PD */ +#define ARIZONA_AIF2BCLK_PD_SHIFT 2 /* AIF2BCLK_PD */ +#define ARIZONA_AIF2BCLK_PD_WIDTH 1 /* AIF2BCLK_PD */ +#define ARIZONA_AIF2RXDAT_PU 0x0002 /* AIF2RXDAT_PU */ +#define ARIZONA_AIF2RXDAT_PU_MASK 0x0002 /* AIF2RXDAT_PU */ +#define ARIZONA_AIF2RXDAT_PU_SHIFT 1 /* AIF2RXDAT_PU */ +#define ARIZONA_AIF2RXDAT_PU_WIDTH 1 /* AIF2RXDAT_PU */ +#define ARIZONA_AIF2RXDAT_PD 0x0001 /* AIF2RXDAT_PD */ +#define ARIZONA_AIF2RXDAT_PD_MASK 0x0001 /* AIF2RXDAT_PD */ +#define ARIZONA_AIF2RXDAT_PD_SHIFT 0 /* AIF2RXDAT_PD */ +#define ARIZONA_AIF2RXDAT_PD_WIDTH 1 /* AIF2RXDAT_PD */ + +/* + * R3109 (0xC25) - Misc Pad Ctrl 6 + */ +#define ARIZONA_AIF3RXLRCLK_PU 0x0020 /* AIF3RXLRCLK_PU */ +#define ARIZONA_AIF3RXLRCLK_PU_MASK 0x0020 /* AIF3RXLRCLK_PU */ +#define ARIZONA_AIF3RXLRCLK_PU_SHIFT 5 /* AIF3RXLRCLK_PU */ +#define ARIZONA_AIF3RXLRCLK_PU_WIDTH 1 /* AIF3RXLRCLK_PU */ +#define ARIZONA_AIF3RXLRCLK_PD 0x0010 /* AIF3RXLRCLK_PD */ +#define ARIZONA_AIF3RXLRCLK_PD_MASK 0x0010 /* AIF3RXLRCLK_PD */ +#define ARIZONA_AIF3RXLRCLK_PD_SHIFT 4 /* AIF3RXLRCLK_PD */ +#define ARIZONA_AIF3RXLRCLK_PD_WIDTH 1 /* AIF3RXLRCLK_PD */ +#define ARIZONA_AIF3BCLK_PU 0x0008 /* AIF3BCLK_PU */ +#define ARIZONA_AIF3BCLK_PU_MASK 0x0008 /* AIF3BCLK_PU */ +#define ARIZONA_AIF3BCLK_PU_SHIFT 3 /* AIF3BCLK_PU */ +#define ARIZONA_AIF3BCLK_PU_WIDTH 1 /* AIF3BCLK_PU */ +#define ARIZONA_AIF3BCLK_PD 0x0004 /* AIF3BCLK_PD */ +#define ARIZONA_AIF3BCLK_PD_MASK 0x0004 /* AIF3BCLK_PD */ +#define ARIZONA_AIF3BCLK_PD_SHIFT 2 /* AIF3BCLK_PD */ +#define ARIZONA_AIF3BCLK_PD_WIDTH 1 /* AIF3BCLK_PD */ +#define ARIZONA_AIF3RXDAT_PU 0x0002 /* AIF3RXDAT_PU */ +#define ARIZONA_AIF3RXDAT_PU_MASK 0x0002 /* AIF3RXDAT_PU */ +#define ARIZONA_AIF3RXDAT_PU_SHIFT 1 /* AIF3RXDAT_PU */ +#define ARIZONA_AIF3RXDAT_PU_WIDTH 1 /* AIF3RXDAT_PU */ +#define ARIZONA_AIF3RXDAT_PD 0x0001 /* AIF3RXDAT_PD */ +#define ARIZONA_AIF3RXDAT_PD_MASK 0x0001 /* AIF3RXDAT_PD */ +#define ARIZONA_AIF3RXDAT_PD_SHIFT 0 /* AIF3RXDAT_PD */ +#define ARIZONA_AIF3RXDAT_PD_WIDTH 1 /* AIF3RXDAT_PD */ + +/* + * R3328 (0xD00) - Interrupt Status 1 + */ +#define ARIZONA_GP4_EINT1 0x0008 /* GP4_EINT1 */ +#define ARIZONA_GP4_EINT1_MASK 0x0008 /* GP4_EINT1 */ +#define ARIZONA_GP4_EINT1_SHIFT 3 /* GP4_EINT1 */ +#define ARIZONA_GP4_EINT1_WIDTH 1 /* GP4_EINT1 */ +#define ARIZONA_GP3_EINT1 0x0004 /* GP3_EINT1 */ +#define ARIZONA_GP3_EINT1_MASK 0x0004 /* GP3_EINT1 */ +#define ARIZONA_GP3_EINT1_SHIFT 2 /* GP3_EINT1 */ +#define ARIZONA_GP3_EINT1_WIDTH 1 /* GP3_EINT1 */ +#define ARIZONA_GP2_EINT1 0x0002 /* GP2_EINT1 */ +#define ARIZONA_GP2_EINT1_MASK 0x0002 /* GP2_EINT1 */ +#define ARIZONA_GP2_EINT1_SHIFT 1 /* GP2_EINT1 */ +#define ARIZONA_GP2_EINT1_WIDTH 1 /* GP2_EINT1 */ +#define ARIZONA_GP1_EINT1 0x0001 /* GP1_EINT1 */ +#define ARIZONA_GP1_EINT1_MASK 0x0001 /* GP1_EINT1 */ +#define ARIZONA_GP1_EINT1_SHIFT 0 /* GP1_EINT1 */ +#define ARIZONA_GP1_EINT1_WIDTH 1 /* GP1_EINT1 */ + +/* + * R3329 (0xD01) - Interrupt Status 2 + */ +#define ARIZONA_DSP4_RAM_RDY_EINT1 0x0800 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_MASK 0x0800 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_SHIFT 11 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP4_RAM_RDY_EINT1_WIDTH 1 /* DSP4_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1 0x0400 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_MASK 0x0400 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_SHIFT 10 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP3_RAM_RDY_EINT1_WIDTH 1 /* DSP3_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1 0x0200 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_MASK 0x0200 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_SHIFT 9 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP2_RAM_RDY_EINT1_WIDTH 1 /* DSP2_RAM_RDY_EINT1 */ +#define ARIZONA_DSP1_RAM_RDY_EINT1 0x0100 /* DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_DSP1_RAM_RDY_EINT1_MASK 0x0100 /* DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_DSP1_RAM_RDY_EINT1_SHIFT 8 /* DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_DSP1_RAM_RDY_EINT1_WIDTH 1 /* DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1 0x0080 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_MASK 0x0080 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_SHIFT 7 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ8_EINT1_WIDTH 1 /* DSP_IRQ8_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1 0x0040 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_MASK 0x0040 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_SHIFT 6 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ7_EINT1_WIDTH 1 /* DSP_IRQ7_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1 0x0020 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_MASK 0x0020 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_SHIFT 5 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ6_EINT1_WIDTH 1 /* DSP_IRQ6_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1 0x0010 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_MASK 0x0010 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_SHIFT 4 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ5_EINT1_WIDTH 1 /* DSP_IRQ5_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1 0x0008 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_MASK 0x0008 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_SHIFT 3 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ4_EINT1_WIDTH 1 /* DSP_IRQ4_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1 0x0004 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_MASK 0x0004 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_SHIFT 2 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ3_EINT1_WIDTH 1 /* DSP_IRQ3_EINT1 */ +#define ARIZONA_DSP_IRQ2_EINT1 0x0002 /* DSP_IRQ2_EINT1 */ +#define ARIZONA_DSP_IRQ2_EINT1_MASK 0x0002 /* DSP_IRQ2_EINT1 */ +#define ARIZONA_DSP_IRQ2_EINT1_SHIFT 1 /* DSP_IRQ2_EINT1 */ +#define ARIZONA_DSP_IRQ2_EINT1_WIDTH 1 /* DSP_IRQ2_EINT1 */ +#define ARIZONA_DSP_IRQ1_EINT1 0x0001 /* DSP_IRQ1_EINT1 */ +#define ARIZONA_DSP_IRQ1_EINT1_MASK 0x0001 /* DSP_IRQ1_EINT1 */ +#define ARIZONA_DSP_IRQ1_EINT1_SHIFT 0 /* DSP_IRQ1_EINT1 */ +#define ARIZONA_DSP_IRQ1_EINT1_WIDTH 1 /* DSP_IRQ1_EINT1 */ + +/* + * R3330 (0xD02) - Interrupt Status 3 + */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT1 0x8000 /* SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT1_MASK 0x8000 /* SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT1_SHIFT 15 /* SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT1_WIDTH 1 /* SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_EINT1 0x4000 /* SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_EINT1_MASK 0x4000 /* SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_EINT1_SHIFT 14 /* SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_SPK_SHUTDOWN_EINT1_WIDTH 1 /* SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_HPDET_EINT1 0x2000 /* HPDET_EINT1 */ +#define ARIZONA_HPDET_EINT1_MASK 0x2000 /* HPDET_EINT1 */ +#define ARIZONA_HPDET_EINT1_SHIFT 13 /* HPDET_EINT1 */ +#define ARIZONA_HPDET_EINT1_WIDTH 1 /* HPDET_EINT1 */ +#define ARIZONA_MICDET_EINT1 0x1000 /* MICDET_EINT1 */ +#define ARIZONA_MICDET_EINT1_MASK 0x1000 /* MICDET_EINT1 */ +#define ARIZONA_MICDET_EINT1_SHIFT 12 /* MICDET_EINT1 */ +#define ARIZONA_MICDET_EINT1_WIDTH 1 /* MICDET_EINT1 */ +#define ARIZONA_WSEQ_DONE_EINT1 0x0800 /* WSEQ_DONE_EINT1 */ +#define ARIZONA_WSEQ_DONE_EINT1_MASK 0x0800 /* WSEQ_DONE_EINT1 */ +#define ARIZONA_WSEQ_DONE_EINT1_SHIFT 11 /* WSEQ_DONE_EINT1 */ +#define ARIZONA_WSEQ_DONE_EINT1_WIDTH 1 /* WSEQ_DONE_EINT1 */ +#define ARIZONA_DRC2_SIG_DET_EINT1 0x0400 /* DRC2_SIG_DET_EINT1 */ +#define ARIZONA_DRC2_SIG_DET_EINT1_MASK 0x0400 /* DRC2_SIG_DET_EINT1 */ +#define ARIZONA_DRC2_SIG_DET_EINT1_SHIFT 10 /* DRC2_SIG_DET_EINT1 */ +#define ARIZONA_DRC2_SIG_DET_EINT1_WIDTH 1 /* DRC2_SIG_DET_EINT1 */ +#define ARIZONA_DRC1_SIG_DET_EINT1 0x0200 /* DRC1_SIG_DET_EINT1 */ +#define ARIZONA_DRC1_SIG_DET_EINT1_MASK 0x0200 /* DRC1_SIG_DET_EINT1 */ +#define ARIZONA_DRC1_SIG_DET_EINT1_SHIFT 9 /* DRC1_SIG_DET_EINT1 */ +#define ARIZONA_DRC1_SIG_DET_EINT1_WIDTH 1 /* DRC1_SIG_DET_EINT1 */ +#define ARIZONA_ASRC2_LOCK_EINT1 0x0100 /* ASRC2_LOCK_EINT1 */ +#define ARIZONA_ASRC2_LOCK_EINT1_MASK 0x0100 /* ASRC2_LOCK_EINT1 */ +#define ARIZONA_ASRC2_LOCK_EINT1_SHIFT 8 /* ASRC2_LOCK_EINT1 */ +#define ARIZONA_ASRC2_LOCK_EINT1_WIDTH 1 /* ASRC2_LOCK_EINT1 */ +#define ARIZONA_ASRC1_LOCK_EINT1 0x0080 /* ASRC1_LOCK_EINT1 */ +#define ARIZONA_ASRC1_LOCK_EINT1_MASK 0x0080 /* ASRC1_LOCK_EINT1 */ +#define ARIZONA_ASRC1_LOCK_EINT1_SHIFT 7 /* ASRC1_LOCK_EINT1 */ +#define ARIZONA_ASRC1_LOCK_EINT1_WIDTH 1 /* ASRC1_LOCK_EINT1 */ +#define ARIZONA_UNDERCLOCKED_EINT1 0x0040 /* UNDERCLOCKED_EINT1 */ +#define ARIZONA_UNDERCLOCKED_EINT1_MASK 0x0040 /* UNDERCLOCKED_EINT1 */ +#define ARIZONA_UNDERCLOCKED_EINT1_SHIFT 6 /* UNDERCLOCKED_EINT1 */ +#define ARIZONA_UNDERCLOCKED_EINT1_WIDTH 1 /* UNDERCLOCKED_EINT1 */ +#define ARIZONA_OVERCLOCKED_EINT1 0x0020 /* OVERCLOCKED_EINT1 */ +#define ARIZONA_OVERCLOCKED_EINT1_MASK 0x0020 /* OVERCLOCKED_EINT1 */ +#define ARIZONA_OVERCLOCKED_EINT1_SHIFT 5 /* OVERCLOCKED_EINT1 */ +#define ARIZONA_OVERCLOCKED_EINT1_WIDTH 1 /* OVERCLOCKED_EINT1 */ +#define ARIZONA_FLL2_LOCK_EINT1 0x0008 /* FLL2_LOCK_EINT1 */ +#define ARIZONA_FLL2_LOCK_EINT1_MASK 0x0008 /* FLL2_LOCK_EINT1 */ +#define ARIZONA_FLL2_LOCK_EINT1_SHIFT 3 /* FLL2_LOCK_EINT1 */ +#define ARIZONA_FLL2_LOCK_EINT1_WIDTH 1 /* FLL2_LOCK_EINT1 */ +#define ARIZONA_FLL1_LOCK_EINT1 0x0004 /* FLL1_LOCK_EINT1 */ +#define ARIZONA_FLL1_LOCK_EINT1_MASK 0x0004 /* FLL1_LOCK_EINT1 */ +#define ARIZONA_FLL1_LOCK_EINT1_SHIFT 2 /* FLL1_LOCK_EINT1 */ +#define ARIZONA_FLL1_LOCK_EINT1_WIDTH 1 /* FLL1_LOCK_EINT1 */ +#define ARIZONA_CLKGEN_ERR_EINT1 0x0002 /* CLKGEN_ERR_EINT1 */ +#define ARIZONA_CLKGEN_ERR_EINT1_MASK 0x0002 /* CLKGEN_ERR_EINT1 */ +#define ARIZONA_CLKGEN_ERR_EINT1_SHIFT 1 /* CLKGEN_ERR_EINT1 */ +#define ARIZONA_CLKGEN_ERR_EINT1_WIDTH 1 /* CLKGEN_ERR_EINT1 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT1 0x0001 /* CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT1_MASK 0x0001 /* CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT1_SHIFT 0 /* CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT1_WIDTH 1 /* CLKGEN_ERR_ASYNC_EINT1 */ + +/* + * R3331 (0xD03) - Interrupt Status 4 + */ +#define ARIZONA_ASRC_CFG_ERR_EINT1 0x8000 /* ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_ASRC_CFG_ERR_EINT1_MASK 0x8000 /* ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_ASRC_CFG_ERR_EINT1_SHIFT 15 /* ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_ASRC_CFG_ERR_EINT1_WIDTH 1 /* ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_AIF3_ERR_EINT1 0x4000 /* AIF3_ERR_EINT1 */ +#define ARIZONA_AIF3_ERR_EINT1_MASK 0x4000 /* AIF3_ERR_EINT1 */ +#define ARIZONA_AIF3_ERR_EINT1_SHIFT 14 /* AIF3_ERR_EINT1 */ +#define ARIZONA_AIF3_ERR_EINT1_WIDTH 1 /* AIF3_ERR_EINT1 */ +#define ARIZONA_AIF2_ERR_EINT1 0x2000 /* AIF2_ERR_EINT1 */ +#define ARIZONA_AIF2_ERR_EINT1_MASK 0x2000 /* AIF2_ERR_EINT1 */ +#define ARIZONA_AIF2_ERR_EINT1_SHIFT 13 /* AIF2_ERR_EINT1 */ +#define ARIZONA_AIF2_ERR_EINT1_WIDTH 1 /* AIF2_ERR_EINT1 */ +#define ARIZONA_AIF1_ERR_EINT1 0x1000 /* AIF1_ERR_EINT1 */ +#define ARIZONA_AIF1_ERR_EINT1_MASK 0x1000 /* AIF1_ERR_EINT1 */ +#define ARIZONA_AIF1_ERR_EINT1_SHIFT 12 /* AIF1_ERR_EINT1 */ +#define ARIZONA_AIF1_ERR_EINT1_WIDTH 1 /* AIF1_ERR_EINT1 */ +#define ARIZONA_CTRLIF_ERR_EINT1 0x0800 /* CTRLIF_ERR_EINT1 */ +#define ARIZONA_CTRLIF_ERR_EINT1_MASK 0x0800 /* CTRLIF_ERR_EINT1 */ +#define ARIZONA_CTRLIF_ERR_EINT1_SHIFT 11 /* CTRLIF_ERR_EINT1 */ +#define ARIZONA_CTRLIF_ERR_EINT1_WIDTH 1 /* CTRLIF_ERR_EINT1 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT1 0x0400 /* MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT1_MASK 0x0400 /* MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT1_SHIFT 10 /* MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT1_WIDTH 1 /* MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT1 0x0200 /* ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT1_MASK 0x0200 /* ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT1_SHIFT 9 /* ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT1_WIDTH 1 /* ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT1 0x0100 /* SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT1_MASK 0x0100 /* SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT1_SHIFT 8 /* SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT1_WIDTH 1 /* SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT1 0x0080 /* ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT1_MASK 0x0080 /* ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT1_SHIFT 7 /* ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT1_WIDTH 1 /* ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT1 0x0040 /* ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT1_MASK 0x0040 /* ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT1_SHIFT 6 /* ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT1_WIDTH 1 /* ISRC2_CFG_ERR_EINT1 */ + +/* + * R3332 (0xD04) - Interrupt Status 5 + */ +#define ARIZONA_BOOT_DONE_EINT1 0x0100 /* BOOT_DONE_EINT1 */ +#define ARIZONA_BOOT_DONE_EINT1_MASK 0x0100 /* BOOT_DONE_EINT1 */ +#define ARIZONA_BOOT_DONE_EINT1_SHIFT 8 /* BOOT_DONE_EINT1 */ +#define ARIZONA_BOOT_DONE_EINT1_WIDTH 1 /* BOOT_DONE_EINT1 */ +#define ARIZONA_DCS_DAC_DONE_EINT1 0x0080 /* DCS_DAC_DONE_EINT1 */ +#define ARIZONA_DCS_DAC_DONE_EINT1_MASK 0x0080 /* DCS_DAC_DONE_EINT1 */ +#define ARIZONA_DCS_DAC_DONE_EINT1_SHIFT 7 /* DCS_DAC_DONE_EINT1 */ +#define ARIZONA_DCS_DAC_DONE_EINT1_WIDTH 1 /* DCS_DAC_DONE_EINT1 */ +#define ARIZONA_DCS_HP_DONE_EINT1 0x0040 /* DCS_HP_DONE_EINT1 */ +#define ARIZONA_DCS_HP_DONE_EINT1_MASK 0x0040 /* DCS_HP_DONE_EINT1 */ +#define ARIZONA_DCS_HP_DONE_EINT1_SHIFT 6 /* DCS_HP_DONE_EINT1 */ +#define ARIZONA_DCS_HP_DONE_EINT1_WIDTH 1 /* DCS_HP_DONE_EINT1 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT1 0x0002 /* FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT1_MASK 0x0002 /* FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT1_SHIFT 1 /* FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT1_WIDTH 1 /* FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT1 0x0001 /* FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT1_MASK 0x0001 /* FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT1_SHIFT 0 /* FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT1_WIDTH 1 /* FLL1_CLOCK_OK_EINT1 */ + +/* + * R3336 (0xD08) - Interrupt Status 1 Mask + */ +#define ARIZONA_IM_GP4_EINT1 0x0008 /* IM_GP4_EINT1 */ +#define ARIZONA_IM_GP4_EINT1_MASK 0x0008 /* IM_GP4_EINT1 */ +#define ARIZONA_IM_GP4_EINT1_SHIFT 3 /* IM_GP4_EINT1 */ +#define ARIZONA_IM_GP4_EINT1_WIDTH 1 /* IM_GP4_EINT1 */ +#define ARIZONA_IM_GP3_EINT1 0x0004 /* IM_GP3_EINT1 */ +#define ARIZONA_IM_GP3_EINT1_MASK 0x0004 /* IM_GP3_EINT1 */ +#define ARIZONA_IM_GP3_EINT1_SHIFT 2 /* IM_GP3_EINT1 */ +#define ARIZONA_IM_GP3_EINT1_WIDTH 1 /* IM_GP3_EINT1 */ +#define ARIZONA_IM_GP2_EINT1 0x0002 /* IM_GP2_EINT1 */ +#define ARIZONA_IM_GP2_EINT1_MASK 0x0002 /* IM_GP2_EINT1 */ +#define ARIZONA_IM_GP2_EINT1_SHIFT 1 /* IM_GP2_EINT1 */ +#define ARIZONA_IM_GP2_EINT1_WIDTH 1 /* IM_GP2_EINT1 */ +#define ARIZONA_IM_GP1_EINT1 0x0001 /* IM_GP1_EINT1 */ +#define ARIZONA_IM_GP1_EINT1_MASK 0x0001 /* IM_GP1_EINT1 */ +#define ARIZONA_IM_GP1_EINT1_SHIFT 0 /* IM_GP1_EINT1 */ +#define ARIZONA_IM_GP1_EINT1_WIDTH 1 /* IM_GP1_EINT1 */ + +/* + * R3337 (0xD09) - Interrupt Status 2 Mask + */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT1 0x0100 /* IM_DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT1_MASK 0x0100 /* IM_DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT1_SHIFT 8 /* IM_DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT1_WIDTH 1 /* IM_DSP1_RAM_RDY_EINT1 */ +#define ARIZONA_IM_DSP_IRQ2_EINT1 0x0002 /* IM_DSP_IRQ2_EINT1 */ +#define ARIZONA_IM_DSP_IRQ2_EINT1_MASK 0x0002 /* IM_DSP_IRQ2_EINT1 */ +#define ARIZONA_IM_DSP_IRQ2_EINT1_SHIFT 1 /* IM_DSP_IRQ2_EINT1 */ +#define ARIZONA_IM_DSP_IRQ2_EINT1_WIDTH 1 /* IM_DSP_IRQ2_EINT1 */ +#define ARIZONA_IM_DSP_IRQ1_EINT1 0x0001 /* IM_DSP_IRQ1_EINT1 */ +#define ARIZONA_IM_DSP_IRQ1_EINT1_MASK 0x0001 /* IM_DSP_IRQ1_EINT1 */ +#define ARIZONA_IM_DSP_IRQ1_EINT1_SHIFT 0 /* IM_DSP_IRQ1_EINT1 */ +#define ARIZONA_IM_DSP_IRQ1_EINT1_WIDTH 1 /* IM_DSP_IRQ1_EINT1 */ + +/* + * R3338 (0xD0A) - Interrupt Status 3 Mask + */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT1 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT1_MASK 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT1_SHIFT 15 /* IM_SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT1_WIDTH 1 /* IM_SPK_SHUTDOWN_WARN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT1 0x4000 /* IM_SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT1_MASK 0x4000 /* IM_SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT1_SHIFT 14 /* IM_SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT1_WIDTH 1 /* IM_SPK_SHUTDOWN_EINT1 */ +#define ARIZONA_IM_HPDET_EINT1 0x2000 /* IM_HPDET_EINT1 */ +#define ARIZONA_IM_HPDET_EINT1_MASK 0x2000 /* IM_HPDET_EINT1 */ +#define ARIZONA_IM_HPDET_EINT1_SHIFT 13 /* IM_HPDET_EINT1 */ +#define ARIZONA_IM_HPDET_EINT1_WIDTH 1 /* IM_HPDET_EINT1 */ +#define ARIZONA_IM_MICDET_EINT1 0x1000 /* IM_MICDET_EINT1 */ +#define ARIZONA_IM_MICDET_EINT1_MASK 0x1000 /* IM_MICDET_EINT1 */ +#define ARIZONA_IM_MICDET_EINT1_SHIFT 12 /* IM_MICDET_EINT1 */ +#define ARIZONA_IM_MICDET_EINT1_WIDTH 1 /* IM_MICDET_EINT1 */ +#define ARIZONA_IM_WSEQ_DONE_EINT1 0x0800 /* IM_WSEQ_DONE_EINT1 */ +#define ARIZONA_IM_WSEQ_DONE_EINT1_MASK 0x0800 /* IM_WSEQ_DONE_EINT1 */ +#define ARIZONA_IM_WSEQ_DONE_EINT1_SHIFT 11 /* IM_WSEQ_DONE_EINT1 */ +#define ARIZONA_IM_WSEQ_DONE_EINT1_WIDTH 1 /* IM_WSEQ_DONE_EINT1 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT1 0x0400 /* IM_DRC2_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT1_MASK 0x0400 /* IM_DRC2_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT1_SHIFT 10 /* IM_DRC2_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT1_WIDTH 1 /* IM_DRC2_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT1 0x0200 /* IM_DRC1_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT1_MASK 0x0200 /* IM_DRC1_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT1_SHIFT 9 /* IM_DRC1_SIG_DET_EINT1 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT1_WIDTH 1 /* IM_DRC1_SIG_DET_EINT1 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT1 0x0100 /* IM_ASRC2_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT1_MASK 0x0100 /* IM_ASRC2_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT1_SHIFT 8 /* IM_ASRC2_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT1_WIDTH 1 /* IM_ASRC2_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT1 0x0080 /* IM_ASRC1_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT1_MASK 0x0080 /* IM_ASRC1_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT1_SHIFT 7 /* IM_ASRC1_LOCK_EINT1 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT1_WIDTH 1 /* IM_ASRC1_LOCK_EINT1 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT1 0x0040 /* IM_UNDERCLOCKED_EINT1 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT1_MASK 0x0040 /* IM_UNDERCLOCKED_EINT1 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT1_SHIFT 6 /* IM_UNDERCLOCKED_EINT1 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT1_WIDTH 1 /* IM_UNDERCLOCKED_EINT1 */ +#define ARIZONA_IM_OVERCLOCKED_EINT1 0x0020 /* IM_OVERCLOCKED_EINT1 */ +#define ARIZONA_IM_OVERCLOCKED_EINT1_MASK 0x0020 /* IM_OVERCLOCKED_EINT1 */ +#define ARIZONA_IM_OVERCLOCKED_EINT1_SHIFT 5 /* IM_OVERCLOCKED_EINT1 */ +#define ARIZONA_IM_OVERCLOCKED_EINT1_WIDTH 1 /* IM_OVERCLOCKED_EINT1 */ +#define ARIZONA_IM_FLL2_LOCK_EINT1 0x0008 /* IM_FLL2_LOCK_EINT1 */ +#define ARIZONA_IM_FLL2_LOCK_EINT1_MASK 0x0008 /* IM_FLL2_LOCK_EINT1 */ +#define ARIZONA_IM_FLL2_LOCK_EINT1_SHIFT 3 /* IM_FLL2_LOCK_EINT1 */ +#define ARIZONA_IM_FLL2_LOCK_EINT1_WIDTH 1 /* IM_FLL2_LOCK_EINT1 */ +#define ARIZONA_IM_FLL1_LOCK_EINT1 0x0004 /* IM_FLL1_LOCK_EINT1 */ +#define ARIZONA_IM_FLL1_LOCK_EINT1_MASK 0x0004 /* IM_FLL1_LOCK_EINT1 */ +#define ARIZONA_IM_FLL1_LOCK_EINT1_SHIFT 2 /* IM_FLL1_LOCK_EINT1 */ +#define ARIZONA_IM_FLL1_LOCK_EINT1_WIDTH 1 /* IM_FLL1_LOCK_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT1 0x0002 /* IM_CLKGEN_ERR_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT1_MASK 0x0002 /* IM_CLKGEN_ERR_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT1_SHIFT 1 /* IM_CLKGEN_ERR_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT1_WIDTH 1 /* IM_CLKGEN_ERR_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT1 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT1_MASK 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT1_SHIFT 0 /* IM_CLKGEN_ERR_ASYNC_EINT1 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT1_WIDTH 1 /* IM_CLKGEN_ERR_ASYNC_EINT1 */ + +/* + * R3339 (0xD0B) - Interrupt Status 4 Mask + */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT1 0x8000 /* IM_ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT1_MASK 0x8000 /* IM_ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT1_SHIFT 15 /* IM_ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT1_WIDTH 1 /* IM_ASRC_CFG_ERR_EINT1 */ +#define ARIZONA_IM_AIF3_ERR_EINT1 0x4000 /* IM_AIF3_ERR_EINT1 */ +#define ARIZONA_IM_AIF3_ERR_EINT1_MASK 0x4000 /* IM_AIF3_ERR_EINT1 */ +#define ARIZONA_IM_AIF3_ERR_EINT1_SHIFT 14 /* IM_AIF3_ERR_EINT1 */ +#define ARIZONA_IM_AIF3_ERR_EINT1_WIDTH 1 /* IM_AIF3_ERR_EINT1 */ +#define ARIZONA_IM_AIF2_ERR_EINT1 0x2000 /* IM_AIF2_ERR_EINT1 */ +#define ARIZONA_IM_AIF2_ERR_EINT1_MASK 0x2000 /* IM_AIF2_ERR_EINT1 */ +#define ARIZONA_IM_AIF2_ERR_EINT1_SHIFT 13 /* IM_AIF2_ERR_EINT1 */ +#define ARIZONA_IM_AIF2_ERR_EINT1_WIDTH 1 /* IM_AIF2_ERR_EINT1 */ +#define ARIZONA_IM_AIF1_ERR_EINT1 0x1000 /* IM_AIF1_ERR_EINT1 */ +#define ARIZONA_IM_AIF1_ERR_EINT1_MASK 0x1000 /* IM_AIF1_ERR_EINT1 */ +#define ARIZONA_IM_AIF1_ERR_EINT1_SHIFT 12 /* IM_AIF1_ERR_EINT1 */ +#define ARIZONA_IM_AIF1_ERR_EINT1_WIDTH 1 /* IM_AIF1_ERR_EINT1 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT1 0x0800 /* IM_CTRLIF_ERR_EINT1 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT1_MASK 0x0800 /* IM_CTRLIF_ERR_EINT1 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT1_SHIFT 11 /* IM_CTRLIF_ERR_EINT1 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT1_WIDTH 1 /* IM_CTRLIF_ERR_EINT1 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT1 0x0400 /* IM_MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT1_MASK 0x0400 /* IM_MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT1_SHIFT 10 /* IM_MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT1_WIDTH 1 /* IM_MIXER_DROPPED_SAMPLE_EINT1 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT1 0x0200 /* IM_ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT1_MASK 0x0200 /* IM_ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT1_SHIFT 9 /* IM_ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT1_WIDTH 1 /* IM_ASYNC_CLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT1 0x0100 /* IM_SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT1_MASK 0x0100 /* IM_SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT1_SHIFT 8 /* IM_SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT1_WIDTH 1 /* IM_SYSCLK_ENA_LOW_EINT1 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT1 0x0080 /* IM_ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT1_MASK 0x0080 /* IM_ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT1_SHIFT 7 /* IM_ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT1_WIDTH 1 /* IM_ISRC1_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT1 0x0040 /* IM_ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT1_MASK 0x0040 /* IM_ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT1_SHIFT 6 /* IM_ISRC2_CFG_ERR_EINT1 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT1_WIDTH 1 /* IM_ISRC2_CFG_ERR_EINT1 */ + +/* + * R3340 (0xD0C) - Interrupt Status 5 Mask + */ +#define ARIZONA_IM_BOOT_DONE_EINT1 0x0100 /* IM_BOOT_DONE_EINT1 */ +#define ARIZONA_IM_BOOT_DONE_EINT1_MASK 0x0100 /* IM_BOOT_DONE_EINT1 */ +#define ARIZONA_IM_BOOT_DONE_EINT1_SHIFT 8 /* IM_BOOT_DONE_EINT1 */ +#define ARIZONA_IM_BOOT_DONE_EINT1_WIDTH 1 /* IM_BOOT_DONE_EINT1 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT1 0x0080 /* IM_DCS_DAC_DONE_EINT1 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT1_MASK 0x0080 /* IM_DCS_DAC_DONE_EINT1 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT1_SHIFT 7 /* IM_DCS_DAC_DONE_EINT1 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT1_WIDTH 1 /* IM_DCS_DAC_DONE_EINT1 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT1 0x0040 /* IM_DCS_HP_DONE_EINT1 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT1_MASK 0x0040 /* IM_DCS_HP_DONE_EINT1 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT1_SHIFT 6 /* IM_DCS_HP_DONE_EINT1 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT1_WIDTH 1 /* IM_DCS_HP_DONE_EINT1 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT1 0x0002 /* IM_FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT1_MASK 0x0002 /* IM_FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT1_SHIFT 1 /* IM_FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT1_WIDTH 1 /* IM_FLL2_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT1 0x0001 /* IM_FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT1_MASK 0x0001 /* IM_FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT1_SHIFT 0 /* IM_FLL1_CLOCK_OK_EINT1 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT1_WIDTH 1 /* IM_FLL1_CLOCK_OK_EINT1 */ + +/* + * R3343 (0xD0F) - Interrupt Control + */ +#define ARIZONA_IM_IRQ1 0x0001 /* IM_IRQ1 */ +#define ARIZONA_IM_IRQ1_MASK 0x0001 /* IM_IRQ1 */ +#define ARIZONA_IM_IRQ1_SHIFT 0 /* IM_IRQ1 */ +#define ARIZONA_IM_IRQ1_WIDTH 1 /* IM_IRQ1 */ + +/* + * R3344 (0xD10) - IRQ2 Status 1 + */ +#define ARIZONA_GP4_EINT2 0x0008 /* GP4_EINT2 */ +#define ARIZONA_GP4_EINT2_MASK 0x0008 /* GP4_EINT2 */ +#define ARIZONA_GP4_EINT2_SHIFT 3 /* GP4_EINT2 */ +#define ARIZONA_GP4_EINT2_WIDTH 1 /* GP4_EINT2 */ +#define ARIZONA_GP3_EINT2 0x0004 /* GP3_EINT2 */ +#define ARIZONA_GP3_EINT2_MASK 0x0004 /* GP3_EINT2 */ +#define ARIZONA_GP3_EINT2_SHIFT 2 /* GP3_EINT2 */ +#define ARIZONA_GP3_EINT2_WIDTH 1 /* GP3_EINT2 */ +#define ARIZONA_GP2_EINT2 0x0002 /* GP2_EINT2 */ +#define ARIZONA_GP2_EINT2_MASK 0x0002 /* GP2_EINT2 */ +#define ARIZONA_GP2_EINT2_SHIFT 1 /* GP2_EINT2 */ +#define ARIZONA_GP2_EINT2_WIDTH 1 /* GP2_EINT2 */ +#define ARIZONA_GP1_EINT2 0x0001 /* GP1_EINT2 */ +#define ARIZONA_GP1_EINT2_MASK 0x0001 /* GP1_EINT2 */ +#define ARIZONA_GP1_EINT2_SHIFT 0 /* GP1_EINT2 */ +#define ARIZONA_GP1_EINT2_WIDTH 1 /* GP1_EINT2 */ + +/* + * R3345 (0xD11) - IRQ2 Status 2 + */ +#define ARIZONA_DSP1_RAM_RDY_EINT2 0x0100 /* DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_DSP1_RAM_RDY_EINT2_MASK 0x0100 /* DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_DSP1_RAM_RDY_EINT2_SHIFT 8 /* DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_DSP1_RAM_RDY_EINT2_WIDTH 1 /* DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_DSP_IRQ2_EINT2 0x0002 /* DSP_IRQ2_EINT2 */ +#define ARIZONA_DSP_IRQ2_EINT2_MASK 0x0002 /* DSP_IRQ2_EINT2 */ +#define ARIZONA_DSP_IRQ2_EINT2_SHIFT 1 /* DSP_IRQ2_EINT2 */ +#define ARIZONA_DSP_IRQ2_EINT2_WIDTH 1 /* DSP_IRQ2_EINT2 */ +#define ARIZONA_DSP_IRQ1_EINT2 0x0001 /* DSP_IRQ1_EINT2 */ +#define ARIZONA_DSP_IRQ1_EINT2_MASK 0x0001 /* DSP_IRQ1_EINT2 */ +#define ARIZONA_DSP_IRQ1_EINT2_SHIFT 0 /* DSP_IRQ1_EINT2 */ +#define ARIZONA_DSP_IRQ1_EINT2_WIDTH 1 /* DSP_IRQ1_EINT2 */ + +/* + * R3346 (0xD12) - IRQ2 Status 3 + */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT2 0x8000 /* SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT2_MASK 0x8000 /* SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT2_SHIFT 15 /* SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_WARN_EINT2_WIDTH 1 /* SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_EINT2 0x4000 /* SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_EINT2_MASK 0x4000 /* SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_EINT2_SHIFT 14 /* SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_SPK_SHUTDOWN_EINT2_WIDTH 1 /* SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_HPDET_EINT2 0x2000 /* HPDET_EINT2 */ +#define ARIZONA_HPDET_EINT2_MASK 0x2000 /* HPDET_EINT2 */ +#define ARIZONA_HPDET_EINT2_SHIFT 13 /* HPDET_EINT2 */ +#define ARIZONA_HPDET_EINT2_WIDTH 1 /* HPDET_EINT2 */ +#define ARIZONA_MICDET_EINT2 0x1000 /* MICDET_EINT2 */ +#define ARIZONA_MICDET_EINT2_MASK 0x1000 /* MICDET_EINT2 */ +#define ARIZONA_MICDET_EINT2_SHIFT 12 /* MICDET_EINT2 */ +#define ARIZONA_MICDET_EINT2_WIDTH 1 /* MICDET_EINT2 */ +#define ARIZONA_WSEQ_DONE_EINT2 0x0800 /* WSEQ_DONE_EINT2 */ +#define ARIZONA_WSEQ_DONE_EINT2_MASK 0x0800 /* WSEQ_DONE_EINT2 */ +#define ARIZONA_WSEQ_DONE_EINT2_SHIFT 11 /* WSEQ_DONE_EINT2 */ +#define ARIZONA_WSEQ_DONE_EINT2_WIDTH 1 /* WSEQ_DONE_EINT2 */ +#define ARIZONA_DRC2_SIG_DET_EINT2 0x0400 /* DRC2_SIG_DET_EINT2 */ +#define ARIZONA_DRC2_SIG_DET_EINT2_MASK 0x0400 /* DRC2_SIG_DET_EINT2 */ +#define ARIZONA_DRC2_SIG_DET_EINT2_SHIFT 10 /* DRC2_SIG_DET_EINT2 */ +#define ARIZONA_DRC2_SIG_DET_EINT2_WIDTH 1 /* DRC2_SIG_DET_EINT2 */ +#define ARIZONA_DRC1_SIG_DET_EINT2 0x0200 /* DRC1_SIG_DET_EINT2 */ +#define ARIZONA_DRC1_SIG_DET_EINT2_MASK 0x0200 /* DRC1_SIG_DET_EINT2 */ +#define ARIZONA_DRC1_SIG_DET_EINT2_SHIFT 9 /* DRC1_SIG_DET_EINT2 */ +#define ARIZONA_DRC1_SIG_DET_EINT2_WIDTH 1 /* DRC1_SIG_DET_EINT2 */ +#define ARIZONA_ASRC2_LOCK_EINT2 0x0100 /* ASRC2_LOCK_EINT2 */ +#define ARIZONA_ASRC2_LOCK_EINT2_MASK 0x0100 /* ASRC2_LOCK_EINT2 */ +#define ARIZONA_ASRC2_LOCK_EINT2_SHIFT 8 /* ASRC2_LOCK_EINT2 */ +#define ARIZONA_ASRC2_LOCK_EINT2_WIDTH 1 /* ASRC2_LOCK_EINT2 */ +#define ARIZONA_ASRC1_LOCK_EINT2 0x0080 /* ASRC1_LOCK_EINT2 */ +#define ARIZONA_ASRC1_LOCK_EINT2_MASK 0x0080 /* ASRC1_LOCK_EINT2 */ +#define ARIZONA_ASRC1_LOCK_EINT2_SHIFT 7 /* ASRC1_LOCK_EINT2 */ +#define ARIZONA_ASRC1_LOCK_EINT2_WIDTH 1 /* ASRC1_LOCK_EINT2 */ +#define ARIZONA_UNDERCLOCKED_EINT2 0x0040 /* UNDERCLOCKED_EINT2 */ +#define ARIZONA_UNDERCLOCKED_EINT2_MASK 0x0040 /* UNDERCLOCKED_EINT2 */ +#define ARIZONA_UNDERCLOCKED_EINT2_SHIFT 6 /* UNDERCLOCKED_EINT2 */ +#define ARIZONA_UNDERCLOCKED_EINT2_WIDTH 1 /* UNDERCLOCKED_EINT2 */ +#define ARIZONA_OVERCLOCKED_EINT2 0x0020 /* OVERCLOCKED_EINT2 */ +#define ARIZONA_OVERCLOCKED_EINT2_MASK 0x0020 /* OVERCLOCKED_EINT2 */ +#define ARIZONA_OVERCLOCKED_EINT2_SHIFT 5 /* OVERCLOCKED_EINT2 */ +#define ARIZONA_OVERCLOCKED_EINT2_WIDTH 1 /* OVERCLOCKED_EINT2 */ +#define ARIZONA_FLL2_LOCK_EINT2 0x0008 /* FLL2_LOCK_EINT2 */ +#define ARIZONA_FLL2_LOCK_EINT2_MASK 0x0008 /* FLL2_LOCK_EINT2 */ +#define ARIZONA_FLL2_LOCK_EINT2_SHIFT 3 /* FLL2_LOCK_EINT2 */ +#define ARIZONA_FLL2_LOCK_EINT2_WIDTH 1 /* FLL2_LOCK_EINT2 */ +#define ARIZONA_FLL1_LOCK_EINT2 0x0004 /* FLL1_LOCK_EINT2 */ +#define ARIZONA_FLL1_LOCK_EINT2_MASK 0x0004 /* FLL1_LOCK_EINT2 */ +#define ARIZONA_FLL1_LOCK_EINT2_SHIFT 2 /* FLL1_LOCK_EINT2 */ +#define ARIZONA_FLL1_LOCK_EINT2_WIDTH 1 /* FLL1_LOCK_EINT2 */ +#define ARIZONA_CLKGEN_ERR_EINT2 0x0002 /* CLKGEN_ERR_EINT2 */ +#define ARIZONA_CLKGEN_ERR_EINT2_MASK 0x0002 /* CLKGEN_ERR_EINT2 */ +#define ARIZONA_CLKGEN_ERR_EINT2_SHIFT 1 /* CLKGEN_ERR_EINT2 */ +#define ARIZONA_CLKGEN_ERR_EINT2_WIDTH 1 /* CLKGEN_ERR_EINT2 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT2 0x0001 /* CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT2_MASK 0x0001 /* CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT2_SHIFT 0 /* CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_CLKGEN_ERR_ASYNC_EINT2_WIDTH 1 /* CLKGEN_ERR_ASYNC_EINT2 */ + +/* + * R3347 (0xD13) - IRQ2 Status 4 + */ +#define ARIZONA_ASRC_CFG_ERR_EINT2 0x8000 /* ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_ASRC_CFG_ERR_EINT2_MASK 0x8000 /* ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_ASRC_CFG_ERR_EINT2_SHIFT 15 /* ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_ASRC_CFG_ERR_EINT2_WIDTH 1 /* ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_AIF3_ERR_EINT2 0x4000 /* AIF3_ERR_EINT2 */ +#define ARIZONA_AIF3_ERR_EINT2_MASK 0x4000 /* AIF3_ERR_EINT2 */ +#define ARIZONA_AIF3_ERR_EINT2_SHIFT 14 /* AIF3_ERR_EINT2 */ +#define ARIZONA_AIF3_ERR_EINT2_WIDTH 1 /* AIF3_ERR_EINT2 */ +#define ARIZONA_AIF2_ERR_EINT2 0x2000 /* AIF2_ERR_EINT2 */ +#define ARIZONA_AIF2_ERR_EINT2_MASK 0x2000 /* AIF2_ERR_EINT2 */ +#define ARIZONA_AIF2_ERR_EINT2_SHIFT 13 /* AIF2_ERR_EINT2 */ +#define ARIZONA_AIF2_ERR_EINT2_WIDTH 1 /* AIF2_ERR_EINT2 */ +#define ARIZONA_AIF1_ERR_EINT2 0x1000 /* AIF1_ERR_EINT2 */ +#define ARIZONA_AIF1_ERR_EINT2_MASK 0x1000 /* AIF1_ERR_EINT2 */ +#define ARIZONA_AIF1_ERR_EINT2_SHIFT 12 /* AIF1_ERR_EINT2 */ +#define ARIZONA_AIF1_ERR_EINT2_WIDTH 1 /* AIF1_ERR_EINT2 */ +#define ARIZONA_CTRLIF_ERR_EINT2 0x0800 /* CTRLIF_ERR_EINT2 */ +#define ARIZONA_CTRLIF_ERR_EINT2_MASK 0x0800 /* CTRLIF_ERR_EINT2 */ +#define ARIZONA_CTRLIF_ERR_EINT2_SHIFT 11 /* CTRLIF_ERR_EINT2 */ +#define ARIZONA_CTRLIF_ERR_EINT2_WIDTH 1 /* CTRLIF_ERR_EINT2 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT2 0x0400 /* MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT2_MASK 0x0400 /* MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT2_SHIFT 10 /* MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_EINT2_WIDTH 1 /* MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT2 0x0200 /* ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT2_MASK 0x0200 /* ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT2_SHIFT 9 /* ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_EINT2_WIDTH 1 /* ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT2 0x0100 /* SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT2_MASK 0x0100 /* SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT2_SHIFT 8 /* SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_SYSCLK_ENA_LOW_EINT2_WIDTH 1 /* SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT2 0x0080 /* ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT2_MASK 0x0080 /* ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT2_SHIFT 7 /* ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC1_CFG_ERR_EINT2_WIDTH 1 /* ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT2 0x0040 /* ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT2_MASK 0x0040 /* ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT2_SHIFT 6 /* ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_ISRC2_CFG_ERR_EINT2_WIDTH 1 /* ISRC2_CFG_ERR_EINT2 */ + +/* + * R3348 (0xD14) - IRQ2 Status 5 + */ +#define ARIZONA_BOOT_DONE_EINT2 0x0100 /* BOOT_DONE_EINT2 */ +#define ARIZONA_BOOT_DONE_EINT2_MASK 0x0100 /* BOOT_DONE_EINT2 */ +#define ARIZONA_BOOT_DONE_EINT2_SHIFT 8 /* BOOT_DONE_EINT2 */ +#define ARIZONA_BOOT_DONE_EINT2_WIDTH 1 /* BOOT_DONE_EINT2 */ +#define ARIZONA_DCS_DAC_DONE_EINT2 0x0080 /* DCS_DAC_DONE_EINT2 */ +#define ARIZONA_DCS_DAC_DONE_EINT2_MASK 0x0080 /* DCS_DAC_DONE_EINT2 */ +#define ARIZONA_DCS_DAC_DONE_EINT2_SHIFT 7 /* DCS_DAC_DONE_EINT2 */ +#define ARIZONA_DCS_DAC_DONE_EINT2_WIDTH 1 /* DCS_DAC_DONE_EINT2 */ +#define ARIZONA_DCS_HP_DONE_EINT2 0x0040 /* DCS_HP_DONE_EINT2 */ +#define ARIZONA_DCS_HP_DONE_EINT2_MASK 0x0040 /* DCS_HP_DONE_EINT2 */ +#define ARIZONA_DCS_HP_DONE_EINT2_SHIFT 6 /* DCS_HP_DONE_EINT2 */ +#define ARIZONA_DCS_HP_DONE_EINT2_WIDTH 1 /* DCS_HP_DONE_EINT2 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT2 0x0002 /* FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT2_MASK 0x0002 /* FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT2_SHIFT 1 /* FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL2_CLOCK_OK_EINT2_WIDTH 1 /* FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT2 0x0001 /* FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT2_MASK 0x0001 /* FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT2_SHIFT 0 /* FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_FLL1_CLOCK_OK_EINT2_WIDTH 1 /* FLL1_CLOCK_OK_EINT2 */ + +/* + * R3352 (0xD18) - IRQ2 Status 1 Mask + */ +#define ARIZONA_IM_GP4_EINT2 0x0008 /* IM_GP4_EINT2 */ +#define ARIZONA_IM_GP4_EINT2_MASK 0x0008 /* IM_GP4_EINT2 */ +#define ARIZONA_IM_GP4_EINT2_SHIFT 3 /* IM_GP4_EINT2 */ +#define ARIZONA_IM_GP4_EINT2_WIDTH 1 /* IM_GP4_EINT2 */ +#define ARIZONA_IM_GP3_EINT2 0x0004 /* IM_GP3_EINT2 */ +#define ARIZONA_IM_GP3_EINT2_MASK 0x0004 /* IM_GP3_EINT2 */ +#define ARIZONA_IM_GP3_EINT2_SHIFT 2 /* IM_GP3_EINT2 */ +#define ARIZONA_IM_GP3_EINT2_WIDTH 1 /* IM_GP3_EINT2 */ +#define ARIZONA_IM_GP2_EINT2 0x0002 /* IM_GP2_EINT2 */ +#define ARIZONA_IM_GP2_EINT2_MASK 0x0002 /* IM_GP2_EINT2 */ +#define ARIZONA_IM_GP2_EINT2_SHIFT 1 /* IM_GP2_EINT2 */ +#define ARIZONA_IM_GP2_EINT2_WIDTH 1 /* IM_GP2_EINT2 */ +#define ARIZONA_IM_GP1_EINT2 0x0001 /* IM_GP1_EINT2 */ +#define ARIZONA_IM_GP1_EINT2_MASK 0x0001 /* IM_GP1_EINT2 */ +#define ARIZONA_IM_GP1_EINT2_SHIFT 0 /* IM_GP1_EINT2 */ +#define ARIZONA_IM_GP1_EINT2_WIDTH 1 /* IM_GP1_EINT2 */ + +/* + * R3353 (0xD19) - IRQ2 Status 2 Mask + */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT2 0x0100 /* IM_DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT2_MASK 0x0100 /* IM_DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT2_SHIFT 8 /* IM_DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_IM_DSP1_RAM_RDY_EINT2_WIDTH 1 /* IM_DSP1_RAM_RDY_EINT2 */ +#define ARIZONA_IM_DSP_IRQ2_EINT2 0x0002 /* IM_DSP_IRQ2_EINT2 */ +#define ARIZONA_IM_DSP_IRQ2_EINT2_MASK 0x0002 /* IM_DSP_IRQ2_EINT2 */ +#define ARIZONA_IM_DSP_IRQ2_EINT2_SHIFT 1 /* IM_DSP_IRQ2_EINT2 */ +#define ARIZONA_IM_DSP_IRQ2_EINT2_WIDTH 1 /* IM_DSP_IRQ2_EINT2 */ +#define ARIZONA_IM_DSP_IRQ1_EINT2 0x0001 /* IM_DSP_IRQ1_EINT2 */ +#define ARIZONA_IM_DSP_IRQ1_EINT2_MASK 0x0001 /* IM_DSP_IRQ1_EINT2 */ +#define ARIZONA_IM_DSP_IRQ1_EINT2_SHIFT 0 /* IM_DSP_IRQ1_EINT2 */ +#define ARIZONA_IM_DSP_IRQ1_EINT2_WIDTH 1 /* IM_DSP_IRQ1_EINT2 */ + +/* + * R3354 (0xD1A) - IRQ2 Status 3 Mask + */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT2 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT2_MASK 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT2_SHIFT 15 /* IM_SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_WARN_EINT2_WIDTH 1 /* IM_SPK_SHUTDOWN_WARN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT2 0x4000 /* IM_SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT2_MASK 0x4000 /* IM_SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT2_SHIFT 14 /* IM_SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_IM_SPK_SHUTDOWN_EINT2_WIDTH 1 /* IM_SPK_SHUTDOWN_EINT2 */ +#define ARIZONA_IM_HPDET_EINT2 0x2000 /* IM_HPDET_EINT2 */ +#define ARIZONA_IM_HPDET_EINT2_MASK 0x2000 /* IM_HPDET_EINT2 */ +#define ARIZONA_IM_HPDET_EINT2_SHIFT 13 /* IM_HPDET_EINT2 */ +#define ARIZONA_IM_HPDET_EINT2_WIDTH 1 /* IM_HPDET_EINT2 */ +#define ARIZONA_IM_MICDET_EINT2 0x1000 /* IM_MICDET_EINT2 */ +#define ARIZONA_IM_MICDET_EINT2_MASK 0x1000 /* IM_MICDET_EINT2 */ +#define ARIZONA_IM_MICDET_EINT2_SHIFT 12 /* IM_MICDET_EINT2 */ +#define ARIZONA_IM_MICDET_EINT2_WIDTH 1 /* IM_MICDET_EINT2 */ +#define ARIZONA_IM_WSEQ_DONE_EINT2 0x0800 /* IM_WSEQ_DONE_EINT2 */ +#define ARIZONA_IM_WSEQ_DONE_EINT2_MASK 0x0800 /* IM_WSEQ_DONE_EINT2 */ +#define ARIZONA_IM_WSEQ_DONE_EINT2_SHIFT 11 /* IM_WSEQ_DONE_EINT2 */ +#define ARIZONA_IM_WSEQ_DONE_EINT2_WIDTH 1 /* IM_WSEQ_DONE_EINT2 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT2 0x0400 /* IM_DRC2_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT2_MASK 0x0400 /* IM_DRC2_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT2_SHIFT 10 /* IM_DRC2_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC2_SIG_DET_EINT2_WIDTH 1 /* IM_DRC2_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT2 0x0200 /* IM_DRC1_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT2_MASK 0x0200 /* IM_DRC1_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT2_SHIFT 9 /* IM_DRC1_SIG_DET_EINT2 */ +#define ARIZONA_IM_DRC1_SIG_DET_EINT2_WIDTH 1 /* IM_DRC1_SIG_DET_EINT2 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT2 0x0100 /* IM_ASRC2_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT2_MASK 0x0100 /* IM_ASRC2_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT2_SHIFT 8 /* IM_ASRC2_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC2_LOCK_EINT2_WIDTH 1 /* IM_ASRC2_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT2 0x0080 /* IM_ASRC1_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT2_MASK 0x0080 /* IM_ASRC1_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT2_SHIFT 7 /* IM_ASRC1_LOCK_EINT2 */ +#define ARIZONA_IM_ASRC1_LOCK_EINT2_WIDTH 1 /* IM_ASRC1_LOCK_EINT2 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT2 0x0040 /* IM_UNDERCLOCKED_EINT2 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT2_MASK 0x0040 /* IM_UNDERCLOCKED_EINT2 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT2_SHIFT 6 /* IM_UNDERCLOCKED_EINT2 */ +#define ARIZONA_IM_UNDERCLOCKED_EINT2_WIDTH 1 /* IM_UNDERCLOCKED_EINT2 */ +#define ARIZONA_IM_OVERCLOCKED_EINT2 0x0020 /* IM_OVERCLOCKED_EINT2 */ +#define ARIZONA_IM_OVERCLOCKED_EINT2_MASK 0x0020 /* IM_OVERCLOCKED_EINT2 */ +#define ARIZONA_IM_OVERCLOCKED_EINT2_SHIFT 5 /* IM_OVERCLOCKED_EINT2 */ +#define ARIZONA_IM_OVERCLOCKED_EINT2_WIDTH 1 /* IM_OVERCLOCKED_EINT2 */ +#define ARIZONA_IM_FLL2_LOCK_EINT2 0x0008 /* IM_FLL2_LOCK_EINT2 */ +#define ARIZONA_IM_FLL2_LOCK_EINT2_MASK 0x0008 /* IM_FLL2_LOCK_EINT2 */ +#define ARIZONA_IM_FLL2_LOCK_EINT2_SHIFT 3 /* IM_FLL2_LOCK_EINT2 */ +#define ARIZONA_IM_FLL2_LOCK_EINT2_WIDTH 1 /* IM_FLL2_LOCK_EINT2 */ +#define ARIZONA_IM_FLL1_LOCK_EINT2 0x0004 /* IM_FLL1_LOCK_EINT2 */ +#define ARIZONA_IM_FLL1_LOCK_EINT2_MASK 0x0004 /* IM_FLL1_LOCK_EINT2 */ +#define ARIZONA_IM_FLL1_LOCK_EINT2_SHIFT 2 /* IM_FLL1_LOCK_EINT2 */ +#define ARIZONA_IM_FLL1_LOCK_EINT2_WIDTH 1 /* IM_FLL1_LOCK_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT2 0x0002 /* IM_CLKGEN_ERR_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT2_MASK 0x0002 /* IM_CLKGEN_ERR_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT2_SHIFT 1 /* IM_CLKGEN_ERR_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_EINT2_WIDTH 1 /* IM_CLKGEN_ERR_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT2 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT2_MASK 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT2_SHIFT 0 /* IM_CLKGEN_ERR_ASYNC_EINT2 */ +#define ARIZONA_IM_CLKGEN_ERR_ASYNC_EINT2_WIDTH 1 /* IM_CLKGEN_ERR_ASYNC_EINT2 */ + +/* + * R3355 (0xD1B) - IRQ2 Status 4 Mask + */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT2 0x8000 /* IM_ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT2_MASK 0x8000 /* IM_ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT2_SHIFT 15 /* IM_ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ASRC_CFG_ERR_EINT2_WIDTH 1 /* IM_ASRC_CFG_ERR_EINT2 */ +#define ARIZONA_IM_AIF3_ERR_EINT2 0x4000 /* IM_AIF3_ERR_EINT2 */ +#define ARIZONA_IM_AIF3_ERR_EINT2_MASK 0x4000 /* IM_AIF3_ERR_EINT2 */ +#define ARIZONA_IM_AIF3_ERR_EINT2_SHIFT 14 /* IM_AIF3_ERR_EINT2 */ +#define ARIZONA_IM_AIF3_ERR_EINT2_WIDTH 1 /* IM_AIF3_ERR_EINT2 */ +#define ARIZONA_IM_AIF2_ERR_EINT2 0x2000 /* IM_AIF2_ERR_EINT2 */ +#define ARIZONA_IM_AIF2_ERR_EINT2_MASK 0x2000 /* IM_AIF2_ERR_EINT2 */ +#define ARIZONA_IM_AIF2_ERR_EINT2_SHIFT 13 /* IM_AIF2_ERR_EINT2 */ +#define ARIZONA_IM_AIF2_ERR_EINT2_WIDTH 1 /* IM_AIF2_ERR_EINT2 */ +#define ARIZONA_IM_AIF1_ERR_EINT2 0x1000 /* IM_AIF1_ERR_EINT2 */ +#define ARIZONA_IM_AIF1_ERR_EINT2_MASK 0x1000 /* IM_AIF1_ERR_EINT2 */ +#define ARIZONA_IM_AIF1_ERR_EINT2_SHIFT 12 /* IM_AIF1_ERR_EINT2 */ +#define ARIZONA_IM_AIF1_ERR_EINT2_WIDTH 1 /* IM_AIF1_ERR_EINT2 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT2 0x0800 /* IM_CTRLIF_ERR_EINT2 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT2_MASK 0x0800 /* IM_CTRLIF_ERR_EINT2 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT2_SHIFT 11 /* IM_CTRLIF_ERR_EINT2 */ +#define ARIZONA_IM_CTRLIF_ERR_EINT2_WIDTH 1 /* IM_CTRLIF_ERR_EINT2 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT2 0x0400 /* IM_MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT2_MASK 0x0400 /* IM_MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT2_SHIFT 10 /* IM_MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_IM_MIXER_DROPPED_SAMPLE_EINT2_WIDTH 1 /* IM_MIXER_DROPPED_SAMPLE_EINT2 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT2 0x0200 /* IM_ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT2_MASK 0x0200 /* IM_ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT2_SHIFT 9 /* IM_ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_ASYNC_CLK_ENA_LOW_EINT2_WIDTH 1 /* IM_ASYNC_CLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT2 0x0100 /* IM_SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT2_MASK 0x0100 /* IM_SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT2_SHIFT 8 /* IM_SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_SYSCLK_ENA_LOW_EINT2_WIDTH 1 /* IM_SYSCLK_ENA_LOW_EINT2 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT2 0x0080 /* IM_ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT2_MASK 0x0080 /* IM_ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT2_SHIFT 7 /* IM_ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC1_CFG_ERR_EINT2_WIDTH 1 /* IM_ISRC1_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT2 0x0040 /* IM_ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT2_MASK 0x0040 /* IM_ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT2_SHIFT 6 /* IM_ISRC2_CFG_ERR_EINT2 */ +#define ARIZONA_IM_ISRC2_CFG_ERR_EINT2_WIDTH 1 /* IM_ISRC2_CFG_ERR_EINT2 */ + +/* + * R3356 (0xD1C) - IRQ2 Status 5 Mask + */ + +#define ARIZONA_IM_BOOT_DONE_EINT2 0x0100 /* IM_BOOT_DONE_EINT2 */ +#define ARIZONA_IM_BOOT_DONE_EINT2_MASK 0x0100 /* IM_BOOT_DONE_EINT2 */ +#define ARIZONA_IM_BOOT_DONE_EINT2_SHIFT 8 /* IM_BOOT_DONE_EINT2 */ +#define ARIZONA_IM_BOOT_DONE_EINT2_WIDTH 1 /* IM_BOOT_DONE_EINT2 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT2 0x0080 /* IM_DCS_DAC_DONE_EINT2 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT2_MASK 0x0080 /* IM_DCS_DAC_DONE_EINT2 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT2_SHIFT 7 /* IM_DCS_DAC_DONE_EINT2 */ +#define ARIZONA_IM_DCS_DAC_DONE_EINT2_WIDTH 1 /* IM_DCS_DAC_DONE_EINT2 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT2 0x0040 /* IM_DCS_HP_DONE_EINT2 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT2_MASK 0x0040 /* IM_DCS_HP_DONE_EINT2 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT2_SHIFT 6 /* IM_DCS_HP_DONE_EINT2 */ +#define ARIZONA_IM_DCS_HP_DONE_EINT2_WIDTH 1 /* IM_DCS_HP_DONE_EINT2 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT2 0x0002 /* IM_FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT2_MASK 0x0002 /* IM_FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT2_SHIFT 1 /* IM_FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL2_CLOCK_OK_EINT2_WIDTH 1 /* IM_FLL2_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT2 0x0001 /* IM_FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT2_MASK 0x0001 /* IM_FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT2_SHIFT 0 /* IM_FLL1_CLOCK_OK_EINT2 */ +#define ARIZONA_IM_FLL1_CLOCK_OK_EINT2_WIDTH 1 /* IM_FLL1_CLOCK_OK_EINT2 */ + +/* + * R3359 (0xD1F) - IRQ2 Control + */ +#define ARIZONA_IM_IRQ2 0x0001 /* IM_IRQ2 */ +#define ARIZONA_IM_IRQ2_MASK 0x0001 /* IM_IRQ2 */ +#define ARIZONA_IM_IRQ2_SHIFT 0 /* IM_IRQ2 */ +#define ARIZONA_IM_IRQ2_WIDTH 1 /* IM_IRQ2 */ + +/* + * R3360 (0xD20) - Interrupt Raw Status 2 + */ +#define ARIZONA_DSP1_RAM_RDY_STS 0x0100 /* DSP1_RAM_RDY_STS */ +#define ARIZONA_DSP1_RAM_RDY_STS_MASK 0x0100 /* DSP1_RAM_RDY_STS */ +#define ARIZONA_DSP1_RAM_RDY_STS_SHIFT 8 /* DSP1_RAM_RDY_STS */ +#define ARIZONA_DSP1_RAM_RDY_STS_WIDTH 1 /* DSP1_RAM_RDY_STS */ +#define ARIZONA_DSP_IRQ2_STS 0x0002 /* DSP_IRQ2_STS */ +#define ARIZONA_DSP_IRQ2_STS_MASK 0x0002 /* DSP_IRQ2_STS */ +#define ARIZONA_DSP_IRQ2_STS_SHIFT 1 /* DSP_IRQ2_STS */ +#define ARIZONA_DSP_IRQ2_STS_WIDTH 1 /* DSP_IRQ2_STS */ +#define ARIZONA_DSP_IRQ1_STS 0x0001 /* DSP_IRQ1_STS */ +#define ARIZONA_DSP_IRQ1_STS_MASK 0x0001 /* DSP_IRQ1_STS */ +#define ARIZONA_DSP_IRQ1_STS_SHIFT 0 /* DSP_IRQ1_STS */ +#define ARIZONA_DSP_IRQ1_STS_WIDTH 1 /* DSP_IRQ1_STS */ + +/* + * R3361 (0xD21) - Interrupt Raw Status 3 + */ +#define ARIZONA_SPK_SHUTDOWN_WARN_STS 0x8000 /* SPK_SHUTDOWN_WARN_STS */ +#define ARIZONA_SPK_SHUTDOWN_WARN_STS_MASK 0x8000 /* SPK_SHUTDOWN_WARN_STS */ +#define ARIZONA_SPK_SHUTDOWN_WARN_STS_SHIFT 15 /* SPK_SHUTDOWN_WARN_STS */ +#define ARIZONA_SPK_SHUTDOWN_WARN_STS_WIDTH 1 /* SPK_SHUTDOWN_WARN_STS */ +#define ARIZONA_SPK_SHUTDOWN_STS 0x4000 /* SPK_SHUTDOWN_STS */ +#define ARIZONA_SPK_SHUTDOWN_STS_MASK 0x4000 /* SPK_SHUTDOWN_STS */ +#define ARIZONA_SPK_SHUTDOWN_STS_SHIFT 14 /* SPK_SHUTDOWN_STS */ +#define ARIZONA_SPK_SHUTDOWN_STS_WIDTH 1 /* SPK_SHUTDOWN_STS */ +#define ARIZONA_HPDET_STS 0x2000 /* HPDET_STS */ +#define ARIZONA_HPDET_STS_MASK 0x2000 /* HPDET_STS */ +#define ARIZONA_HPDET_STS_SHIFT 13 /* HPDET_STS */ +#define ARIZONA_HPDET_STS_WIDTH 1 /* HPDET_STS */ +#define ARIZONA_MICDET_STS 0x1000 /* MICDET_STS */ +#define ARIZONA_MICDET_STS_MASK 0x1000 /* MICDET_STS */ +#define ARIZONA_MICDET_STS_SHIFT 12 /* MICDET_STS */ +#define ARIZONA_MICDET_STS_WIDTH 1 /* MICDET_STS */ +#define ARIZONA_WSEQ_DONE_STS 0x0800 /* WSEQ_DONE_STS */ +#define ARIZONA_WSEQ_DONE_STS_MASK 0x0800 /* WSEQ_DONE_STS */ +#define ARIZONA_WSEQ_DONE_STS_SHIFT 11 /* WSEQ_DONE_STS */ +#define ARIZONA_WSEQ_DONE_STS_WIDTH 1 /* WSEQ_DONE_STS */ +#define ARIZONA_DRC2_SIG_DET_STS 0x0400 /* DRC2_SIG_DET_STS */ +#define ARIZONA_DRC2_SIG_DET_STS_MASK 0x0400 /* DRC2_SIG_DET_STS */ +#define ARIZONA_DRC2_SIG_DET_STS_SHIFT 10 /* DRC2_SIG_DET_STS */ +#define ARIZONA_DRC2_SIG_DET_STS_WIDTH 1 /* DRC2_SIG_DET_STS */ +#define ARIZONA_DRC1_SIG_DET_STS 0x0200 /* DRC1_SIG_DET_STS */ +#define ARIZONA_DRC1_SIG_DET_STS_MASK 0x0200 /* DRC1_SIG_DET_STS */ +#define ARIZONA_DRC1_SIG_DET_STS_SHIFT 9 /* DRC1_SIG_DET_STS */ +#define ARIZONA_DRC1_SIG_DET_STS_WIDTH 1 /* DRC1_SIG_DET_STS */ +#define ARIZONA_ASRC2_LOCK_STS 0x0100 /* ASRC2_LOCK_STS */ +#define ARIZONA_ASRC2_LOCK_STS_MASK 0x0100 /* ASRC2_LOCK_STS */ +#define ARIZONA_ASRC2_LOCK_STS_SHIFT 8 /* ASRC2_LOCK_STS */ +#define ARIZONA_ASRC2_LOCK_STS_WIDTH 1 /* ASRC2_LOCK_STS */ +#define ARIZONA_ASRC1_LOCK_STS 0x0080 /* ASRC1_LOCK_STS */ +#define ARIZONA_ASRC1_LOCK_STS_MASK 0x0080 /* ASRC1_LOCK_STS */ +#define ARIZONA_ASRC1_LOCK_STS_SHIFT 7 /* ASRC1_LOCK_STS */ +#define ARIZONA_ASRC1_LOCK_STS_WIDTH 1 /* ASRC1_LOCK_STS */ +#define ARIZONA_UNDERCLOCKED_STS 0x0040 /* UNDERCLOCKED_STS */ +#define ARIZONA_UNDERCLOCKED_STS_MASK 0x0040 /* UNDERCLOCKED_STS */ +#define ARIZONA_UNDERCLOCKED_STS_SHIFT 6 /* UNDERCLOCKED_STS */ +#define ARIZONA_UNDERCLOCKED_STS_WIDTH 1 /* UNDERCLOCKED_STS */ +#define ARIZONA_OVERCLOCKED_STS 0x0020 /* OVERCLOCKED_STS */ +#define ARIZONA_OVERCLOCKED_STS_MASK 0x0020 /* OVERCLOCKED_STS */ +#define ARIZONA_OVERCLOCKED_STS_SHIFT 5 /* OVERCLOCKED_STS */ +#define ARIZONA_OVERCLOCKED_STS_WIDTH 1 /* OVERCLOCKED_STS */ +#define ARIZONA_FLL2_LOCK_STS 0x0008 /* FLL2_LOCK_STS */ +#define ARIZONA_FLL2_LOCK_STS_MASK 0x0008 /* FLL2_LOCK_STS */ +#define ARIZONA_FLL2_LOCK_STS_SHIFT 3 /* FLL2_LOCK_STS */ +#define ARIZONA_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */ +#define ARIZONA_FLL1_LOCK_STS 0x0004 /* FLL1_LOCK_STS */ +#define ARIZONA_FLL1_LOCK_STS_MASK 0x0004 /* FLL1_LOCK_STS */ +#define ARIZONA_FLL1_LOCK_STS_SHIFT 2 /* FLL1_LOCK_STS */ +#define ARIZONA_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */ +#define ARIZONA_CLKGEN_ERR_STS 0x0002 /* CLKGEN_ERR_STS */ +#define ARIZONA_CLKGEN_ERR_STS_MASK 0x0002 /* CLKGEN_ERR_STS */ +#define ARIZONA_CLKGEN_ERR_STS_SHIFT 1 /* CLKGEN_ERR_STS */ +#define ARIZONA_CLKGEN_ERR_STS_WIDTH 1 /* CLKGEN_ERR_STS */ +#define ARIZONA_CLKGEN_ERR_ASYNC_STS 0x0001 /* CLKGEN_ERR_ASYNC_STS */ +#define ARIZONA_CLKGEN_ERR_ASYNC_STS_MASK 0x0001 /* CLKGEN_ERR_ASYNC_STS */ +#define ARIZONA_CLKGEN_ERR_ASYNC_STS_SHIFT 0 /* CLKGEN_ERR_ASYNC_STS */ +#define ARIZONA_CLKGEN_ERR_ASYNC_STS_WIDTH 1 /* CLKGEN_ERR_ASYNC_STS */ + +/* + * R3362 (0xD22) - Interrupt Raw Status 4 + */ +#define ARIZONA_ASRC_CFG_ERR_STS 0x8000 /* ASRC_CFG_ERR_STS */ +#define ARIZONA_ASRC_CFG_ERR_STS_MASK 0x8000 /* ASRC_CFG_ERR_STS */ +#define ARIZONA_ASRC_CFG_ERR_STS_SHIFT 15 /* ASRC_CFG_ERR_STS */ +#define ARIZONA_ASRC_CFG_ERR_STS_WIDTH 1 /* ASRC_CFG_ERR_STS */ +#define ARIZONA_AIF3_ERR_STS 0x4000 /* AIF3_ERR_STS */ +#define ARIZONA_AIF3_ERR_STS_MASK 0x4000 /* AIF3_ERR_STS */ +#define ARIZONA_AIF3_ERR_STS_SHIFT 14 /* AIF3_ERR_STS */ +#define ARIZONA_AIF3_ERR_STS_WIDTH 1 /* AIF3_ERR_STS */ +#define ARIZONA_AIF2_ERR_STS 0x2000 /* AIF2_ERR_STS */ +#define ARIZONA_AIF2_ERR_STS_MASK 0x2000 /* AIF2_ERR_STS */ +#define ARIZONA_AIF2_ERR_STS_SHIFT 13 /* AIF2_ERR_STS */ +#define ARIZONA_AIF2_ERR_STS_WIDTH 1 /* AIF2_ERR_STS */ +#define ARIZONA_AIF1_ERR_STS 0x1000 /* AIF1_ERR_STS */ +#define ARIZONA_AIF1_ERR_STS_MASK 0x1000 /* AIF1_ERR_STS */ +#define ARIZONA_AIF1_ERR_STS_SHIFT 12 /* AIF1_ERR_STS */ +#define ARIZONA_AIF1_ERR_STS_WIDTH 1 /* AIF1_ERR_STS */ +#define ARIZONA_CTRLIF_ERR_STS 0x0800 /* CTRLIF_ERR_STS */ +#define ARIZONA_CTRLIF_ERR_STS_MASK 0x0800 /* CTRLIF_ERR_STS */ +#define ARIZONA_CTRLIF_ERR_STS_SHIFT 11 /* CTRLIF_ERR_STS */ +#define ARIZONA_CTRLIF_ERR_STS_WIDTH 1 /* CTRLIF_ERR_STS */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_STS 0x0400 /* MIXER_DROPPED_SAMPLE_STS */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_STS_MASK 0x0400 /* MIXER_DROPPED_SAMPLE_STS */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_STS_SHIFT 10 /* MIXER_DROPPED_SAMPLE_STS */ +#define ARIZONA_MIXER_DROPPED_SAMPLE_STS_WIDTH 1 /* MIXER_DROPPED_SAMPLE_STS */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_STS 0x0200 /* ASYNC_CLK_ENA_LOW_STS */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_STS_MASK 0x0200 /* ASYNC_CLK_ENA_LOW_STS */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_STS_SHIFT 9 /* ASYNC_CLK_ENA_LOW_STS */ +#define ARIZONA_ASYNC_CLK_ENA_LOW_STS_WIDTH 1 /* ASYNC_CLK_ENA_LOW_STS */ +#define ARIZONA_SYSCLK_ENA_LOW_STS 0x0100 /* SYSCLK_ENA_LOW_STS */ +#define ARIZONA_SYSCLK_ENA_LOW_STS_MASK 0x0100 /* SYSCLK_ENA_LOW_STS */ +#define ARIZONA_SYSCLK_ENA_LOW_STS_SHIFT 8 /* SYSCLK_ENA_LOW_STS */ +#define ARIZONA_SYSCLK_ENA_LOW_STS_WIDTH 1 /* SYSCLK_ENA_LOW_STS */ +#define ARIZONA_ISRC1_CFG_ERR_STS 0x0080 /* ISRC1_CFG_ERR_STS */ +#define ARIZONA_ISRC1_CFG_ERR_STS_MASK 0x0080 /* ISRC1_CFG_ERR_STS */ +#define ARIZONA_ISRC1_CFG_ERR_STS_SHIFT 7 /* ISRC1_CFG_ERR_STS */ +#define ARIZONA_ISRC1_CFG_ERR_STS_WIDTH 1 /* ISRC1_CFG_ERR_STS */ +#define ARIZONA_ISRC2_CFG_ERR_STS 0x0040 /* ISRC2_CFG_ERR_STS */ +#define ARIZONA_ISRC2_CFG_ERR_STS_MASK 0x0040 /* ISRC2_CFG_ERR_STS */ +#define ARIZONA_ISRC2_CFG_ERR_STS_SHIFT 6 /* ISRC2_CFG_ERR_STS */ +#define ARIZONA_ISRC2_CFG_ERR_STS_WIDTH 1 /* ISRC2_CFG_ERR_STS */ + +/* + * R3363 (0xD23) - Interrupt Raw Status 5 + */ +#define ARIZONA_BOOT_DONE_STS 0x0100 /* BOOT_DONE_STS */ +#define ARIZONA_BOOT_DONE_STS_MASK 0x0100 /* BOOT_DONE_STS */ +#define ARIZONA_BOOT_DONE_STS_SHIFT 8 /* BOOT_DONE_STS */ +#define ARIZONA_BOOT_DONE_STS_WIDTH 1 /* BOOT_DONE_STS */ +#define ARIZONA_DCS_DAC_DONE_STS 0x0080 /* DCS_DAC_DONE_STS */ +#define ARIZONA_DCS_DAC_DONE_STS_MASK 0x0080 /* DCS_DAC_DONE_STS */ +#define ARIZONA_DCS_DAC_DONE_STS_SHIFT 7 /* DCS_DAC_DONE_STS */ +#define ARIZONA_DCS_DAC_DONE_STS_WIDTH 1 /* DCS_DAC_DONE_STS */ +#define ARIZONA_DCS_HP_DONE_STS 0x0040 /* DCS_HP_DONE_STS */ +#define ARIZONA_DCS_HP_DONE_STS_MASK 0x0040 /* DCS_HP_DONE_STS */ +#define ARIZONA_DCS_HP_DONE_STS_SHIFT 6 /* DCS_HP_DONE_STS */ +#define ARIZONA_DCS_HP_DONE_STS_WIDTH 1 /* DCS_HP_DONE_STS */ +#define ARIZONA_FLL2_CLOCK_OK_STS 0x0002 /* FLL2_CLOCK_OK_STS */ +#define ARIZONA_FLL2_CLOCK_OK_STS_MASK 0x0002 /* FLL2_CLOCK_OK_STS */ +#define ARIZONA_FLL2_CLOCK_OK_STS_SHIFT 1 /* FLL2_CLOCK_OK_STS */ +#define ARIZONA_FLL2_CLOCK_OK_STS_WIDTH 1 /* FLL2_CLOCK_OK_STS */ +#define ARIZONA_FLL1_CLOCK_OK_STS 0x0001 /* FLL1_CLOCK_OK_STS */ +#define ARIZONA_FLL1_CLOCK_OK_STS_MASK 0x0001 /* FLL1_CLOCK_OK_STS */ +#define ARIZONA_FLL1_CLOCK_OK_STS_SHIFT 0 /* FLL1_CLOCK_OK_STS */ +#define ARIZONA_FLL1_CLOCK_OK_STS_WIDTH 1 /* FLL1_CLOCK_OK_STS */ + +/* + * R3364 (0xD24) - Interrupt Raw Status 6 + */ +#define ARIZONA_PWM_OVERCLOCKED_STS 0x2000 /* PWM_OVERCLOCKED_STS */ +#define ARIZONA_PWM_OVERCLOCKED_STS_MASK 0x2000 /* PWM_OVERCLOCKED_STS */ +#define ARIZONA_PWM_OVERCLOCKED_STS_SHIFT 13 /* PWM_OVERCLOCKED_STS */ +#define ARIZONA_PWM_OVERCLOCKED_STS_WIDTH 1 /* PWM_OVERCLOCKED_STS */ +#define ARIZONA_FX_CORE_OVERCLOCKED_STS 0x1000 /* FX_CORE_OVERCLOCKED_STS */ +#define ARIZONA_FX_CORE_OVERCLOCKED_STS_MASK 0x1000 /* FX_CORE_OVERCLOCKED_STS */ +#define ARIZONA_FX_CORE_OVERCLOCKED_STS_SHIFT 12 /* FX_CORE_OVERCLOCKED_STS */ +#define ARIZONA_FX_CORE_OVERCLOCKED_STS_WIDTH 1 /* FX_CORE_OVERCLOCKED_STS */ +#define ARIZONA_DAC_SYS_OVERCLOCKED_STS 0x0400 /* DAC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_DAC_SYS_OVERCLOCKED_STS_MASK 0x0400 /* DAC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_DAC_SYS_OVERCLOCKED_STS_SHIFT 10 /* DAC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_DAC_SYS_OVERCLOCKED_STS_WIDTH 1 /* DAC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_DAC_WARP_OVERCLOCKED_STS 0x0200 /* DAC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_DAC_WARP_OVERCLOCKED_STS_MASK 0x0200 /* DAC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_DAC_WARP_OVERCLOCKED_STS_SHIFT 9 /* DAC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_DAC_WARP_OVERCLOCKED_STS_WIDTH 1 /* DAC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ADC_OVERCLOCKED_STS 0x0100 /* ADC_OVERCLOCKED_STS */ +#define ARIZONA_ADC_OVERCLOCKED_STS_MASK 0x0100 /* ADC_OVERCLOCKED_STS */ +#define ARIZONA_ADC_OVERCLOCKED_STS_SHIFT 8 /* ADC_OVERCLOCKED_STS */ +#define ARIZONA_ADC_OVERCLOCKED_STS_WIDTH 1 /* ADC_OVERCLOCKED_STS */ +#define ARIZONA_MIXER_OVERCLOCKED_STS 0x0080 /* MIXER_OVERCLOCKED_STS */ +#define ARIZONA_MIXER_OVERCLOCKED_STS_MASK 0x0080 /* MIXER_OVERCLOCKED_STS */ +#define ARIZONA_MIXER_OVERCLOCKED_STS_SHIFT 7 /* MIXER_OVERCLOCKED_STS */ +#define ARIZONA_MIXER_OVERCLOCKED_STS_WIDTH 1 /* MIXER_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_ASYNC_OVERCLOCKED_STS 0x0040 /* AIF3_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_ASYNC_OVERCLOCKED_STS_MASK 0x0040 /* AIF3_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_ASYNC_OVERCLOCKED_STS_SHIFT 6 /* AIF3_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_ASYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF3_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_ASYNC_OVERCLOCKED_STS 0x0020 /* AIF2_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_ASYNC_OVERCLOCKED_STS_MASK 0x0020 /* AIF2_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_ASYNC_OVERCLOCKED_STS_SHIFT 5 /* AIF2_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_ASYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF2_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_ASYNC_OVERCLOCKED_STS 0x0010 /* AIF1_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_ASYNC_OVERCLOCKED_STS_MASK 0x0010 /* AIF1_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_ASYNC_OVERCLOCKED_STS_SHIFT 4 /* AIF1_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_ASYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF1_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_SYNC_OVERCLOCKED_STS 0x0008 /* AIF3_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_SYNC_OVERCLOCKED_STS_MASK 0x0008 /* AIF3_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_SYNC_OVERCLOCKED_STS_SHIFT 3 /* AIF3_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF3_SYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF3_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_SYNC_OVERCLOCKED_STS 0x0004 /* AIF2_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_SYNC_OVERCLOCKED_STS_MASK 0x0004 /* AIF2_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_SYNC_OVERCLOCKED_STS_SHIFT 2 /* AIF2_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF2_SYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF2_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_SYNC_OVERCLOCKED_STS 0x0002 /* AIF1_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_SYNC_OVERCLOCKED_STS_MASK 0x0002 /* AIF1_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_SYNC_OVERCLOCKED_STS_SHIFT 1 /* AIF1_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_AIF1_SYNC_OVERCLOCKED_STS_WIDTH 1 /* AIF1_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_PAD_CTRL_OVERCLOCKED_STS 0x0001 /* PAD_CTRL_OVERCLOCKED_STS */ +#define ARIZONA_PAD_CTRL_OVERCLOCKED_STS_MASK 0x0001 /* PAD_CTRL_OVERCLOCKED_STS */ +#define ARIZONA_PAD_CTRL_OVERCLOCKED_STS_SHIFT 0 /* PAD_CTRL_OVERCLOCKED_STS */ +#define ARIZONA_PAD_CTRL_OVERCLOCKED_STS_WIDTH 1 /* PAD_CTRL_OVERCLOCKED_STS */ + +/* + * R3365 (0xD25) - Interrupt Raw Status 7 + */ +#define ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS 0x8000 /* SLIMBUS_SUBSYS_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS_MASK 0x8000 /* SLIMBUS_SUBSYS_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS_SHIFT 15 /* SLIMBUS_SUBSYS_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SUBSYS_OVERCLOCKED_STS_WIDTH 1 /* SLIMBUS_SUBSYS_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS 0x4000 /* SLIMBUS_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS_MASK 0x4000 /* SLIMBUS_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS_SHIFT 14 /* SLIMBUS_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_ASYNC_OVERCLOCKED_STS_WIDTH 1 /* SLIMBUS_ASYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS 0x2000 /* SLIMBUS_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS_MASK 0x2000 /* SLIMBUS_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS_SHIFT 13 /* SLIMBUS_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_SLIMBUS_SYNC_OVERCLOCKED_STS_WIDTH 1 /* SLIMBUS_SYNC_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS 0x1000 /* ASRC_ASYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS_MASK 0x1000 /* ASRC_ASYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS_SHIFT 12 /* ASRC_ASYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_SYS_OVERCLOCKED_STS_WIDTH 1 /* ASRC_ASYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS 0x0800 /* ASRC_ASYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS_MASK 0x0800 /* ASRC_ASYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS_SHIFT 11 /* ASRC_ASYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_ASYNC_WARP_OVERCLOCKED_STS_WIDTH 1 /* ASRC_ASYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS 0x0400 /* ASRC_SYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS_MASK 0x0400 /* ASRC_SYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS_SHIFT 10 /* ASRC_SYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_SYS_OVERCLOCKED_STS_WIDTH 1 /* ASRC_SYNC_SYS_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS 0x0200 /* ASRC_SYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS_MASK 0x0200 /* ASRC_SYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS_SHIFT 9 /* ASRC_SYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ASRC_SYNC_WARP_OVERCLOCKED_STS_WIDTH 1 /* ASRC_SYNC_WARP_OVERCLOCKED_STS */ +#define ARIZONA_ADSP2_1_OVERCLOCKED_STS 0x0008 /* ADSP2_1_OVERCLOCKED_STS */ +#define ARIZONA_ADSP2_1_OVERCLOCKED_STS_MASK 0x0008 /* ADSP2_1_OVERCLOCKED_STS */ +#define ARIZONA_ADSP2_1_OVERCLOCKED_STS_SHIFT 3 /* ADSP2_1_OVERCLOCKED_STS */ +#define ARIZONA_ADSP2_1_OVERCLOCKED_STS_WIDTH 1 /* ADSP2_1_OVERCLOCKED_STS */ +#define ARIZONA_ISRC2_OVERCLOCKED_STS 0x0002 /* ISRC2_OVERCLOCKED_STS */ +#define ARIZONA_ISRC2_OVERCLOCKED_STS_MASK 0x0002 /* ISRC2_OVERCLOCKED_STS */ +#define ARIZONA_ISRC2_OVERCLOCKED_STS_SHIFT 1 /* ISRC2_OVERCLOCKED_STS */ +#define ARIZONA_ISRC2_OVERCLOCKED_STS_WIDTH 1 /* ISRC2_OVERCLOCKED_STS */ +#define ARIZONA_ISRC1_OVERCLOCKED_STS 0x0001 /* ISRC1_OVERCLOCKED_STS */ +#define ARIZONA_ISRC1_OVERCLOCKED_STS_MASK 0x0001 /* ISRC1_OVERCLOCKED_STS */ +#define ARIZONA_ISRC1_OVERCLOCKED_STS_SHIFT 0 /* ISRC1_OVERCLOCKED_STS */ +#define ARIZONA_ISRC1_OVERCLOCKED_STS_WIDTH 1 /* ISRC1_OVERCLOCKED_STS */ + +/* + * R3366 (0xD26) - Interrupt Raw Status 8 + */ +#define ARIZONA_AIF3_UNDERCLOCKED_STS 0x0400 /* AIF3_UNDERCLOCKED_STS */ +#define ARIZONA_AIF3_UNDERCLOCKED_STS_MASK 0x0400 /* AIF3_UNDERCLOCKED_STS */ +#define ARIZONA_AIF3_UNDERCLOCKED_STS_SHIFT 10 /* AIF3_UNDERCLOCKED_STS */ +#define ARIZONA_AIF3_UNDERCLOCKED_STS_WIDTH 1 /* AIF3_UNDERCLOCKED_STS */ +#define ARIZONA_AIF2_UNDERCLOCKED_STS 0x0200 /* AIF2_UNDERCLOCKED_STS */ +#define ARIZONA_AIF2_UNDERCLOCKED_STS_MASK 0x0200 /* AIF2_UNDERCLOCKED_STS */ +#define ARIZONA_AIF2_UNDERCLOCKED_STS_SHIFT 9 /* AIF2_UNDERCLOCKED_STS */ +#define ARIZONA_AIF2_UNDERCLOCKED_STS_WIDTH 1 /* AIF2_UNDERCLOCKED_STS */ +#define ARIZONA_AIF1_UNDERCLOCKED_STS 0x0100 /* AIF1_UNDERCLOCKED_STS */ +#define ARIZONA_AIF1_UNDERCLOCKED_STS_MASK 0x0100 /* AIF1_UNDERCLOCKED_STS */ +#define ARIZONA_AIF1_UNDERCLOCKED_STS_SHIFT 8 /* AIF1_UNDERCLOCKED_STS */ +#define ARIZONA_AIF1_UNDERCLOCKED_STS_WIDTH 1 /* AIF1_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC2_UNDERCLOCKED_STS 0x0040 /* ISRC2_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC2_UNDERCLOCKED_STS_MASK 0x0040 /* ISRC2_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC2_UNDERCLOCKED_STS_SHIFT 6 /* ISRC2_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC2_UNDERCLOCKED_STS_WIDTH 1 /* ISRC2_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC1_UNDERCLOCKED_STS 0x0020 /* ISRC1_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC1_UNDERCLOCKED_STS_MASK 0x0020 /* ISRC1_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC1_UNDERCLOCKED_STS_SHIFT 5 /* ISRC1_UNDERCLOCKED_STS */ +#define ARIZONA_ISRC1_UNDERCLOCKED_STS_WIDTH 1 /* ISRC1_UNDERCLOCKED_STS */ +#define ARIZONA_FX_UNDERCLOCKED_STS 0x0010 /* FX_UNDERCLOCKED_STS */ +#define ARIZONA_FX_UNDERCLOCKED_STS_MASK 0x0010 /* FX_UNDERCLOCKED_STS */ +#define ARIZONA_FX_UNDERCLOCKED_STS_SHIFT 4 /* FX_UNDERCLOCKED_STS */ +#define ARIZONA_FX_UNDERCLOCKED_STS_WIDTH 1 /* FX_UNDERCLOCKED_STS */ +#define ARIZONA_ASRC_UNDERCLOCKED_STS 0x0008 /* ASRC_UNDERCLOCKED_STS */ +#define ARIZONA_ASRC_UNDERCLOCKED_STS_MASK 0x0008 /* ASRC_UNDERCLOCKED_STS */ +#define ARIZONA_ASRC_UNDERCLOCKED_STS_SHIFT 3 /* ASRC_UNDERCLOCKED_STS */ +#define ARIZONA_ASRC_UNDERCLOCKED_STS_WIDTH 1 /* ASRC_UNDERCLOCKED_STS */ +#define ARIZONA_DAC_UNDERCLOCKED_STS 0x0004 /* DAC_UNDERCLOCKED_STS */ +#define ARIZONA_DAC_UNDERCLOCKED_STS_MASK 0x0004 /* DAC_UNDERCLOCKED_STS */ +#define ARIZONA_DAC_UNDERCLOCKED_STS_SHIFT 2 /* DAC_UNDERCLOCKED_STS */ +#define ARIZONA_DAC_UNDERCLOCKED_STS_WIDTH 1 /* DAC_UNDERCLOCKED_STS */ +#define ARIZONA_ADC_UNDERCLOCKED_STS 0x0002 /* ADC_UNDERCLOCKED_STS */ +#define ARIZONA_ADC_UNDERCLOCKED_STS_MASK 0x0002 /* ADC_UNDERCLOCKED_STS */ +#define ARIZONA_ADC_UNDERCLOCKED_STS_SHIFT 1 /* ADC_UNDERCLOCKED_STS */ +#define ARIZONA_ADC_UNDERCLOCKED_STS_WIDTH 1 /* ADC_UNDERCLOCKED_STS */ +#define ARIZONA_MIXER_UNDERCLOCKED_STS 0x0001 /* MIXER_UNDERCLOCKED_STS */ +#define ARIZONA_MIXER_UNDERCLOCKED_STS_MASK 0x0001 /* MIXER_UNDERCLOCKED_STS */ +#define ARIZONA_MIXER_UNDERCLOCKED_STS_SHIFT 0 /* MIXER_UNDERCLOCKED_STS */ +#define ARIZONA_MIXER_UNDERCLOCKED_STS_WIDTH 1 /* MIXER_UNDERCLOCKED_STS */ + +/* + * R3392 (0xD40) - IRQ Pin Status + */ +#define ARIZONA_IRQ2_STS 0x0002 /* IRQ2_STS */ +#define ARIZONA_IRQ2_STS_MASK 0x0002 /* IRQ2_STS */ +#define ARIZONA_IRQ2_STS_SHIFT 1 /* IRQ2_STS */ +#define ARIZONA_IRQ2_STS_WIDTH 1 /* IRQ2_STS */ +#define ARIZONA_IRQ1_STS 0x0001 /* IRQ1_STS */ +#define ARIZONA_IRQ1_STS_MASK 0x0001 /* IRQ1_STS */ +#define ARIZONA_IRQ1_STS_SHIFT 0 /* IRQ1_STS */ +#define ARIZONA_IRQ1_STS_WIDTH 1 /* IRQ1_STS */ + +/* + * R3393 (0xD41) - ADSP2 IRQ0 + */ +#define ARIZONA_DSP_IRQ2 0x0002 /* DSP_IRQ2 */ +#define ARIZONA_DSP_IRQ2_MASK 0x0002 /* DSP_IRQ2 */ +#define ARIZONA_DSP_IRQ2_SHIFT 1 /* DSP_IRQ2 */ +#define ARIZONA_DSP_IRQ2_WIDTH 1 /* DSP_IRQ2 */ +#define ARIZONA_DSP_IRQ1 0x0001 /* DSP_IRQ1 */ +#define ARIZONA_DSP_IRQ1_MASK 0x0001 /* DSP_IRQ1 */ +#define ARIZONA_DSP_IRQ1_SHIFT 0 /* DSP_IRQ1 */ +#define ARIZONA_DSP_IRQ1_WIDTH 1 /* DSP_IRQ1 */ + +/* + * R3408 (0xD50) - AOD wkup and trig + */ +#define ARIZONA_GP5_FALL_TRIG_STS 0x0020 /* GP5_FALL_TRIG_STS */ +#define ARIZONA_GP5_FALL_TRIG_STS_MASK 0x0020 /* GP5_FALL_TRIG_STS */ +#define ARIZONA_GP5_FALL_TRIG_STS_SHIFT 5 /* GP5_FALL_TRIG_STS */ +#define ARIZONA_GP5_FALL_TRIG_STS_WIDTH 1 /* GP5_FALL_TRIG_STS */ +#define ARIZONA_GP5_RISE_TRIG_STS 0x0010 /* GP5_RISE_TRIG_STS */ +#define ARIZONA_GP5_RISE_TRIG_STS_MASK 0x0010 /* GP5_RISE_TRIG_STS */ +#define ARIZONA_GP5_RISE_TRIG_STS_SHIFT 4 /* GP5_RISE_TRIG_STS */ +#define ARIZONA_GP5_RISE_TRIG_STS_WIDTH 1 /* GP5_RISE_TRIG_STS */ +#define ARIZONA_JD1_FALL_TRIG_STS 0x0008 /* JD1_FALL_TRIG_STS */ +#define ARIZONA_JD1_FALL_TRIG_STS_MASK 0x0008 /* JD1_FALL_TRIG_STS */ +#define ARIZONA_JD1_FALL_TRIG_STS_SHIFT 3 /* JD1_FALL_TRIG_STS */ +#define ARIZONA_JD1_FALL_TRIG_STS_WIDTH 1 /* JD1_FALL_TRIG_STS */ +#define ARIZONA_JD1_RISE_TRIG_STS 0x0004 /* JD1_RISE_TRIG_STS */ +#define ARIZONA_JD1_RISE_TRIG_STS_MASK 0x0004 /* JD1_RISE_TRIG_STS */ +#define ARIZONA_JD1_RISE_TRIG_STS_SHIFT 2 /* JD1_RISE_TRIG_STS */ +#define ARIZONA_JD1_RISE_TRIG_STS_WIDTH 1 /* JD1_RISE_TRIG_STS */ +#define ARIZONA_JD2_FALL_TRIG_STS 0x0002 /* JD2_FALL_TRIG_STS */ +#define ARIZONA_JD2_FALL_TRIG_STS_MASK 0x0002 /* JD2_FALL_TRIG_STS */ +#define ARIZONA_JD2_FALL_TRIG_STS_SHIFT 1 /* JD2_FALL_TRIG_STS */ +#define ARIZONA_JD2_FALL_TRIG_STS_WIDTH 1 /* JD2_FALL_TRIG_STS */ +#define ARIZONA_JD2_RISE_TRIG_STS 0x0001 /* JD2_RISE_TRIG_STS */ +#define ARIZONA_JD2_RISE_TRIG_STS_MASK 0x0001 /* JD2_RISE_TRIG_STS */ +#define ARIZONA_JD2_RISE_TRIG_STS_SHIFT 0 /* JD2_RISE_TRIG_STS */ +#define ARIZONA_JD2_RISE_TRIG_STS_WIDTH 1 /* JD2_RISE_TRIG_STS */ + +/* + * R3409 (0xD51) - AOD IRQ1 + */ +#define ARIZONA_GP5_FALL_EINT1 0x0020 /* GP5_FALL_EINT1 */ +#define ARIZONA_GP5_FALL_EINT1_MASK 0x0020 /* GP5_FALL_EINT1 */ +#define ARIZONA_GP5_FALL_EINT1_SHIFT 5 /* GP5_FALL_EINT1 */ +#define ARIZONA_GP5_FALL_EINT1_WIDTH 1 /* GP5_FALL_EINT1 */ +#define ARIZONA_GP5_RISE_EINT1 0x0010 /* GP5_RISE_EINT1 */ +#define ARIZONA_GP5_RISE_EINT1_MASK 0x0010 /* GP5_RISE_EINT1 */ +#define ARIZONA_GP5_RISE_EINT1_SHIFT 4 /* GP5_RISE_EINT1 */ +#define ARIZONA_GP5_RISE_EINT1_WIDTH 1 /* GP5_RISE_EINT1 */ +#define ARIZONA_JD1_FALL_EINT1 0x0008 /* JD1_FALL_EINT1 */ +#define ARIZONA_JD1_FALL_EINT1_MASK 0x0008 /* JD1_FALL_EINT1 */ +#define ARIZONA_JD1_FALL_EINT1_SHIFT 3 /* JD1_FALL_EINT1 */ +#define ARIZONA_JD1_FALL_EINT1_WIDTH 1 /* JD1_FALL_EINT1 */ +#define ARIZONA_JD1_RISE_EINT1 0x0004 /* JD1_RISE_EINT1 */ +#define ARIZONA_JD1_RISE_EINT1_MASK 0x0004 /* JD1_RISE_EINT1 */ +#define ARIZONA_JD1_RISE_EINT1_SHIFT 2 /* JD1_RISE_EINT1 */ +#define ARIZONA_JD1_RISE_EINT1_WIDTH 1 /* JD1_RISE_EINT1 */ +#define ARIZONA_JD2_FALL_EINT1 0x0002 /* JD2_FALL_EINT1 */ +#define ARIZONA_JD2_FALL_EINT1_MASK 0x0002 /* JD2_FALL_EINT1 */ +#define ARIZONA_JD2_FALL_EINT1_SHIFT 1 /* JD2_FALL_EINT1 */ +#define ARIZONA_JD2_FALL_EINT1_WIDTH 1 /* JD2_FALL_EINT1 */ +#define ARIZONA_JD2_RISE_EINT1 0x0001 /* JD2_RISE_EINT1 */ +#define ARIZONA_JD2_RISE_EINT1_MASK 0x0001 /* JD2_RISE_EINT1 */ +#define ARIZONA_JD2_RISE_EINT1_SHIFT 0 /* JD2_RISE_EINT1 */ +#define ARIZONA_JD2_RISE_EINT1_WIDTH 1 /* JD2_RISE_EINT1 */ + +/* + * R3410 (0xD52) - AOD IRQ2 + */ +#define ARIZONA_GP5_FALL_EINT2 0x0020 /* GP5_FALL_EINT2 */ +#define ARIZONA_GP5_FALL_EINT2_MASK 0x0020 /* GP5_FALL_EINT2 */ +#define ARIZONA_GP5_FALL_EINT2_SHIFT 5 /* GP5_FALL_EINT2 */ +#define ARIZONA_GP5_FALL_EINT2_WIDTH 1 /* GP5_FALL_EINT2 */ +#define ARIZONA_GP5_RISE_EINT2 0x0010 /* GP5_RISE_EINT2 */ +#define ARIZONA_GP5_RISE_EINT2_MASK 0x0010 /* GP5_RISE_EINT2 */ +#define ARIZONA_GP5_RISE_EINT2_SHIFT 4 /* GP5_RISE_EINT2 */ +#define ARIZONA_GP5_RISE_EINT2_WIDTH 1 /* GP5_RISE_EINT2 */ +#define ARIZONA_JD1_FALL_EINT2 0x0008 /* JD1_FALL_EINT2 */ +#define ARIZONA_JD1_FALL_EINT2_MASK 0x0008 /* JD1_FALL_EINT2 */ +#define ARIZONA_JD1_FALL_EINT2_SHIFT 3 /* JD1_FALL_EINT2 */ +#define ARIZONA_JD1_FALL_EINT2_WIDTH 1 /* JD1_FALL_EINT2 */ +#define ARIZONA_JD1_RISE_EINT2 0x0004 /* JD1_RISE_EINT2 */ +#define ARIZONA_JD1_RISE_EINT2_MASK 0x0004 /* JD1_RISE_EINT2 */ +#define ARIZONA_JD1_RISE_EINT2_SHIFT 2 /* JD1_RISE_EINT2 */ +#define ARIZONA_JD1_RISE_EINT2_WIDTH 1 /* JD1_RISE_EINT2 */ +#define ARIZONA_JD2_FALL_EINT2 0x0002 /* JD2_FALL_EINT2 */ +#define ARIZONA_JD2_FALL_EINT2_MASK 0x0002 /* JD2_FALL_EINT2 */ +#define ARIZONA_JD2_FALL_EINT2_SHIFT 1 /* JD2_FALL_EINT2 */ +#define ARIZONA_JD2_FALL_EINT2_WIDTH 1 /* JD2_FALL_EINT2 */ +#define ARIZONA_JD2_RISE_EINT2 0x0001 /* JD2_RISE_EINT2 */ +#define ARIZONA_JD2_RISE_EINT2_MASK 0x0001 /* JD2_RISE_EINT2 */ +#define ARIZONA_JD2_RISE_EINT2_SHIFT 0 /* JD2_RISE_EINT2 */ +#define ARIZONA_JD2_RISE_EINT2_WIDTH 1 /* JD2_RISE_EINT2 */ + +/* + * R3411 (0xD53) - AOD IRQ Mask IRQ1 + */ +#define ARIZONA_IM_GP5_FALL_EINT1 0x0020 /* IM_GP5_FALL_EINT1 */ +#define ARIZONA_IM_GP5_FALL_EINT1_MASK 0x0020 /* IM_GP5_FALL_EINT1 */ +#define ARIZONA_IM_GP5_FALL_EINT1_SHIFT 5 /* IM_GP5_FALL_EINT1 */ +#define ARIZONA_IM_GP5_FALL_EINT1_WIDTH 1 /* IM_GP5_FALL_EINT1 */ +#define ARIZONA_IM_GP5_RISE_EINT1 0x0010 /* IM_GP5_RISE_EINT1 */ +#define ARIZONA_IM_GP5_RISE_EINT1_MASK 0x0010 /* IM_GP5_RISE_EINT1 */ +#define ARIZONA_IM_GP5_RISE_EINT1_SHIFT 4 /* IM_GP5_RISE_EINT1 */ +#define ARIZONA_IM_GP5_RISE_EINT1_WIDTH 1 /* IM_GP5_RISE_EINT1 */ +#define ARIZONA_IM_JD1_FALL_EINT1 0x0008 /* IM_JD1_FALL_EINT1 */ +#define ARIZONA_IM_JD1_FALL_EINT1_MASK 0x0008 /* IM_JD1_FALL_EINT1 */ +#define ARIZONA_IM_JD1_FALL_EINT1_SHIFT 3 /* IM_JD1_FALL_EINT1 */ +#define ARIZONA_IM_JD1_FALL_EINT1_WIDTH 1 /* IM_JD1_FALL_EINT1 */ +#define ARIZONA_IM_JD1_RISE_EINT1 0x0004 /* IM_JD1_RISE_EINT1 */ +#define ARIZONA_IM_JD1_RISE_EINT1_MASK 0x0004 /* IM_JD1_RISE_EINT1 */ +#define ARIZONA_IM_JD1_RISE_EINT1_SHIFT 2 /* IM_JD1_RISE_EINT1 */ +#define ARIZONA_IM_JD1_RISE_EINT1_WIDTH 1 /* IM_JD1_RISE_EINT1 */ +#define ARIZONA_IM_JD2_FALL_EINT1 0x0002 /* IM_JD2_FALL_EINT1 */ +#define ARIZONA_IM_JD2_FALL_EINT1_MASK 0x0002 /* IM_JD2_FALL_EINT1 */ +#define ARIZONA_IM_JD2_FALL_EINT1_SHIFT 1 /* IM_JD2_FALL_EINT1 */ +#define ARIZONA_IM_JD2_FALL_EINT1_WIDTH 1 /* IM_JD2_FALL_EINT1 */ +#define ARIZONA_IM_JD2_RISE_EINT1 0x0001 /* IM_JD2_RISE_EINT1 */ +#define ARIZONA_IM_JD2_RISE_EINT1_MASK 0x0001 /* IM_JD2_RISE_EINT1 */ +#define ARIZONA_IM_JD2_RISE_EINT1_SHIFT 0 /* IM_JD2_RISE_EINT1 */ +#define ARIZONA_IM_JD2_RISE_EINT1_WIDTH 1 /* IM_JD2_RISE_EINT1 */ + +/* + * R3412 (0xD54) - AOD IRQ Mask IRQ2 + */ +#define ARIZONA_IM_GP5_FALL_EINT2 0x0020 /* IM_GP5_FALL_EINT2 */ +#define ARIZONA_IM_GP5_FALL_EINT2_MASK 0x0020 /* IM_GP5_FALL_EINT2 */ +#define ARIZONA_IM_GP5_FALL_EINT2_SHIFT 5 /* IM_GP5_FALL_EINT2 */ +#define ARIZONA_IM_GP5_FALL_EINT2_WIDTH 1 /* IM_GP5_FALL_EINT2 */ +#define ARIZONA_IM_GP5_RISE_EINT2 0x0010 /* IM_GP5_RISE_EINT2 */ +#define ARIZONA_IM_GP5_RISE_EINT2_MASK 0x0010 /* IM_GP5_RISE_EINT2 */ +#define ARIZONA_IM_GP5_RISE_EINT2_SHIFT 4 /* IM_GP5_RISE_EINT2 */ +#define ARIZONA_IM_GP5_RISE_EINT2_WIDTH 1 /* IM_GP5_RISE_EINT2 */ +#define ARIZONA_IM_JD1_FALL_EINT2 0x0008 /* IM_JD1_FALL_EINT2 */ +#define ARIZONA_IM_JD1_FALL_EINT2_MASK 0x0008 /* IM_JD1_FALL_EINT2 */ +#define ARIZONA_IM_JD1_FALL_EINT2_SHIFT 3 /* IM_JD1_FALL_EINT2 */ +#define ARIZONA_IM_JD1_FALL_EINT2_WIDTH 1 /* IM_JD1_FALL_EINT2 */ +#define ARIZONA_IM_JD1_RISE_EINT2 0x0004 /* IM_JD1_RISE_EINT2 */ +#define ARIZONA_IM_JD1_RISE_EINT2_MASK 0x0004 /* IM_JD1_RISE_EINT2 */ +#define ARIZONA_IM_JD1_RISE_EINT2_SHIFT 2 /* IM_JD1_RISE_EINT2 */ +#define ARIZONA_IM_JD1_RISE_EINT2_WIDTH 1 /* IM_JD1_RISE_EINT2 */ +#define ARIZONA_IM_JD2_FALL_EINT2 0x0002 /* IM_JD2_FALL_EINT2 */ +#define ARIZONA_IM_JD2_FALL_EINT2_MASK 0x0002 /* IM_JD2_FALL_EINT2 */ +#define ARIZONA_IM_JD2_FALL_EINT2_SHIFT 1 /* IM_JD2_FALL_EINT2 */ +#define ARIZONA_IM_JD2_FALL_EINT2_WIDTH 1 /* IM_JD2_FALL_EINT2 */ +#define ARIZONA_IM_JD2_RISE_EINT2 0x0001 /* IM_JD2_RISE_EINT2 */ +#define ARIZONA_IM_JD2_RISE_EINT2_MASK 0x0001 /* IM_JD2_RISE_EINT2 */ +#define ARIZONA_IM_JD2_RISE_EINT2_SHIFT 0 /* IM_JD2_RISE_EINT2 */ +#define ARIZONA_IM_JD2_RISE_EINT2_WIDTH 1 /* IM_JD2_RISE_EINT2 */ + +/* + * R3413 (0xD55) - AOD IRQ Raw Status + */ +#define ARIZONA_GP5_STS 0x0004 /* GP5_STS */ +#define ARIZONA_GP5_STS_MASK 0x0004 /* GP5_STS */ +#define ARIZONA_GP5_STS_SHIFT 2 /* GP5_STS */ +#define ARIZONA_GP5_STS_WIDTH 1 /* GP5_STS */ +#define ARIZONA_JD2_STS 0x0002 /* JD2_STS */ +#define ARIZONA_JD2_STS_MASK 0x0002 /* JD2_STS */ +#define ARIZONA_JD2_STS_SHIFT 1 /* JD2_STS */ +#define ARIZONA_JD2_STS_WIDTH 1 /* JD2_STS */ +#define ARIZONA_JD1_STS 0x0001 /* JD1_STS */ +#define ARIZONA_JD1_STS_MASK 0x0001 /* JD1_STS */ +#define ARIZONA_JD1_STS_SHIFT 0 /* JD1_STS */ +#define ARIZONA_JD1_STS_WIDTH 1 /* JD1_STS */ + +/* + * R3414 (0xD56) - Jack detect debounce + */ +#define ARIZONA_JD2_DB 0x0002 /* JD2_DB */ +#define ARIZONA_JD2_DB_MASK 0x0002 /* JD2_DB */ +#define ARIZONA_JD2_DB_SHIFT 1 /* JD2_DB */ +#define ARIZONA_JD2_DB_WIDTH 1 /* JD2_DB */ +#define ARIZONA_JD1_DB 0x0001 /* JD1_DB */ +#define ARIZONA_JD1_DB_MASK 0x0001 /* JD1_DB */ +#define ARIZONA_JD1_DB_SHIFT 0 /* JD1_DB */ +#define ARIZONA_JD1_DB_WIDTH 1 /* JD1_DB */ + +/* + * R3584 (0xE00) - FX_Ctrl1 + */ +#define ARIZONA_FX_RATE_MASK 0x7800 /* FX_RATE - [14:11] */ +#define ARIZONA_FX_RATE_SHIFT 11 /* FX_RATE - [14:11] */ +#define ARIZONA_FX_RATE_WIDTH 4 /* FX_RATE - [14:11] */ + +/* + * R3585 (0xE01) - FX_Ctrl2 + */ +#define ARIZONA_FX_STS_MASK 0xFFF0 /* FX_STS - [15:4] */ +#define ARIZONA_FX_STS_SHIFT 4 /* FX_STS - [15:4] */ +#define ARIZONA_FX_STS_WIDTH 12 /* FX_STS - [15:4] */ + +/* + * R3600 (0xE10) - EQ1_1 + */ +#define ARIZONA_EQ1_B1_GAIN_MASK 0xF800 /* EQ1_B1_GAIN - [15:11] */ +#define ARIZONA_EQ1_B1_GAIN_SHIFT 11 /* EQ1_B1_GAIN - [15:11] */ +#define ARIZONA_EQ1_B1_GAIN_WIDTH 5 /* EQ1_B1_GAIN - [15:11] */ +#define ARIZONA_EQ1_B2_GAIN_MASK 0x07C0 /* EQ1_B2_GAIN - [10:6] */ +#define ARIZONA_EQ1_B2_GAIN_SHIFT 6 /* EQ1_B2_GAIN - [10:6] */ +#define ARIZONA_EQ1_B2_GAIN_WIDTH 5 /* EQ1_B2_GAIN - [10:6] */ +#define ARIZONA_EQ1_B3_GAIN_MASK 0x003E /* EQ1_B3_GAIN - [5:1] */ +#define ARIZONA_EQ1_B3_GAIN_SHIFT 1 /* EQ1_B3_GAIN - [5:1] */ +#define ARIZONA_EQ1_B3_GAIN_WIDTH 5 /* EQ1_B3_GAIN - [5:1] */ +#define ARIZONA_EQ1_ENA 0x0001 /* EQ1_ENA */ +#define ARIZONA_EQ1_ENA_MASK 0x0001 /* EQ1_ENA */ +#define ARIZONA_EQ1_ENA_SHIFT 0 /* EQ1_ENA */ +#define ARIZONA_EQ1_ENA_WIDTH 1 /* EQ1_ENA */ + +/* + * R3601 (0xE11) - EQ1_2 + */ +#define ARIZONA_EQ1_B4_GAIN_MASK 0xF800 /* EQ1_B4_GAIN - [15:11] */ +#define ARIZONA_EQ1_B4_GAIN_SHIFT 11 /* EQ1_B4_GAIN - [15:11] */ +#define ARIZONA_EQ1_B4_GAIN_WIDTH 5 /* EQ1_B4_GAIN - [15:11] */ +#define ARIZONA_EQ1_B5_GAIN_MASK 0x07C0 /* EQ1_B5_GAIN - [10:6] */ +#define ARIZONA_EQ1_B5_GAIN_SHIFT 6 /* EQ1_B5_GAIN - [10:6] */ +#define ARIZONA_EQ1_B5_GAIN_WIDTH 5 /* EQ1_B5_GAIN - [10:6] */ +#define ARIZONA_EQ1_B1_MODE 0x0001 /* EQ1_B1_MODE */ +#define ARIZONA_EQ1_B1_MODE_MASK 0x0001 /* EQ1_B1_MODE */ +#define ARIZONA_EQ1_B1_MODE_SHIFT 0 /* EQ1_B1_MODE */ +#define ARIZONA_EQ1_B1_MODE_WIDTH 1 /* EQ1_B1_MODE */ + +/* + * R3602 (0xE12) - EQ1_3 + */ +#define ARIZONA_EQ1_B1_A_MASK 0xFFFF /* EQ1_B1_A - [15:0] */ +#define ARIZONA_EQ1_B1_A_SHIFT 0 /* EQ1_B1_A - [15:0] */ +#define ARIZONA_EQ1_B1_A_WIDTH 16 /* EQ1_B1_A - [15:0] */ + +/* + * R3603 (0xE13) - EQ1_4 + */ +#define ARIZONA_EQ1_B1_B_MASK 0xFFFF /* EQ1_B1_B - [15:0] */ +#define ARIZONA_EQ1_B1_B_SHIFT 0 /* EQ1_B1_B - [15:0] */ +#define ARIZONA_EQ1_B1_B_WIDTH 16 /* EQ1_B1_B - [15:0] */ + +/* + * R3604 (0xE14) - EQ1_5 + */ +#define ARIZONA_EQ1_B1_PG_MASK 0xFFFF /* EQ1_B1_PG - [15:0] */ +#define ARIZONA_EQ1_B1_PG_SHIFT 0 /* EQ1_B1_PG - [15:0] */ +#define ARIZONA_EQ1_B1_PG_WIDTH 16 /* EQ1_B1_PG - [15:0] */ + +/* + * R3605 (0xE15) - EQ1_6 + */ +#define ARIZONA_EQ1_B2_A_MASK 0xFFFF /* EQ1_B2_A - [15:0] */ +#define ARIZONA_EQ1_B2_A_SHIFT 0 /* EQ1_B2_A - [15:0] */ +#define ARIZONA_EQ1_B2_A_WIDTH 16 /* EQ1_B2_A - [15:0] */ + +/* + * R3606 (0xE16) - EQ1_7 + */ +#define ARIZONA_EQ1_B2_B_MASK 0xFFFF /* EQ1_B2_B - [15:0] */ +#define ARIZONA_EQ1_B2_B_SHIFT 0 /* EQ1_B2_B - [15:0] */ +#define ARIZONA_EQ1_B2_B_WIDTH 16 /* EQ1_B2_B - [15:0] */ + +/* + * R3607 (0xE17) - EQ1_8 + */ +#define ARIZONA_EQ1_B2_C_MASK 0xFFFF /* EQ1_B2_C - [15:0] */ +#define ARIZONA_EQ1_B2_C_SHIFT 0 /* EQ1_B2_C - [15:0] */ +#define ARIZONA_EQ1_B2_C_WIDTH 16 /* EQ1_B2_C - [15:0] */ + +/* + * R3608 (0xE18) - EQ1_9 + */ +#define ARIZONA_EQ1_B2_PG_MASK 0xFFFF /* EQ1_B2_PG - [15:0] */ +#define ARIZONA_EQ1_B2_PG_SHIFT 0 /* EQ1_B2_PG - [15:0] */ +#define ARIZONA_EQ1_B2_PG_WIDTH 16 /* EQ1_B2_PG - [15:0] */ + +/* + * R3609 (0xE19) - EQ1_10 + */ +#define ARIZONA_EQ1_B3_A_MASK 0xFFFF /* EQ1_B3_A - [15:0] */ +#define ARIZONA_EQ1_B3_A_SHIFT 0 /* EQ1_B3_A - [15:0] */ +#define ARIZONA_EQ1_B3_A_WIDTH 16 /* EQ1_B3_A - [15:0] */ + +/* + * R3610 (0xE1A) - EQ1_11 + */ +#define ARIZONA_EQ1_B3_B_MASK 0xFFFF /* EQ1_B3_B - [15:0] */ +#define ARIZONA_EQ1_B3_B_SHIFT 0 /* EQ1_B3_B - [15:0] */ +#define ARIZONA_EQ1_B3_B_WIDTH 16 /* EQ1_B3_B - [15:0] */ + +/* + * R3611 (0xE1B) - EQ1_12 + */ +#define ARIZONA_EQ1_B3_C_MASK 0xFFFF /* EQ1_B3_C - [15:0] */ +#define ARIZONA_EQ1_B3_C_SHIFT 0 /* EQ1_B3_C - [15:0] */ +#define ARIZONA_EQ1_B3_C_WIDTH 16 /* EQ1_B3_C - [15:0] */ + +/* + * R3612 (0xE1C) - EQ1_13 + */ +#define ARIZONA_EQ1_B3_PG_MASK 0xFFFF /* EQ1_B3_PG - [15:0] */ +#define ARIZONA_EQ1_B3_PG_SHIFT 0 /* EQ1_B3_PG - [15:0] */ +#define ARIZONA_EQ1_B3_PG_WIDTH 16 /* EQ1_B3_PG - [15:0] */ + +/* + * R3613 (0xE1D) - EQ1_14 + */ +#define ARIZONA_EQ1_B4_A_MASK 0xFFFF /* EQ1_B4_A - [15:0] */ +#define ARIZONA_EQ1_B4_A_SHIFT 0 /* EQ1_B4_A - [15:0] */ +#define ARIZONA_EQ1_B4_A_WIDTH 16 /* EQ1_B4_A - [15:0] */ + +/* + * R3614 (0xE1E) - EQ1_15 + */ +#define ARIZONA_EQ1_B4_B_MASK 0xFFFF /* EQ1_B4_B - [15:0] */ +#define ARIZONA_EQ1_B4_B_SHIFT 0 /* EQ1_B4_B - [15:0] */ +#define ARIZONA_EQ1_B4_B_WIDTH 16 /* EQ1_B4_B - [15:0] */ + +/* + * R3615 (0xE1F) - EQ1_16 + */ +#define ARIZONA_EQ1_B4_C_MASK 0xFFFF /* EQ1_B4_C - [15:0] */ +#define ARIZONA_EQ1_B4_C_SHIFT 0 /* EQ1_B4_C - [15:0] */ +#define ARIZONA_EQ1_B4_C_WIDTH 16 /* EQ1_B4_C - [15:0] */ + +/* + * R3616 (0xE20) - EQ1_17 + */ +#define ARIZONA_EQ1_B4_PG_MASK 0xFFFF /* EQ1_B4_PG - [15:0] */ +#define ARIZONA_EQ1_B4_PG_SHIFT 0 /* EQ1_B4_PG - [15:0] */ +#define ARIZONA_EQ1_B4_PG_WIDTH 16 /* EQ1_B4_PG - [15:0] */ + +/* + * R3617 (0xE21) - EQ1_18 + */ +#define ARIZONA_EQ1_B5_A_MASK 0xFFFF /* EQ1_B5_A - [15:0] */ +#define ARIZONA_EQ1_B5_A_SHIFT 0 /* EQ1_B5_A - [15:0] */ +#define ARIZONA_EQ1_B5_A_WIDTH 16 /* EQ1_B5_A - [15:0] */ + +/* + * R3618 (0xE22) - EQ1_19 + */ +#define ARIZONA_EQ1_B5_B_MASK 0xFFFF /* EQ1_B5_B - [15:0] */ +#define ARIZONA_EQ1_B5_B_SHIFT 0 /* EQ1_B5_B - [15:0] */ +#define ARIZONA_EQ1_B5_B_WIDTH 16 /* EQ1_B5_B - [15:0] */ + +/* + * R3619 (0xE23) - EQ1_20 + */ +#define ARIZONA_EQ1_B5_PG_MASK 0xFFFF /* EQ1_B5_PG - [15:0] */ +#define ARIZONA_EQ1_B5_PG_SHIFT 0 /* EQ1_B5_PG - [15:0] */ +#define ARIZONA_EQ1_B5_PG_WIDTH 16 /* EQ1_B5_PG - [15:0] */ + +/* + * R3620 (0xE24) - EQ1_21 + */ +#define ARIZONA_EQ1_B1_C_MASK 0xFFFF /* EQ1_B1_C - [15:0] */ +#define ARIZONA_EQ1_B1_C_SHIFT 0 /* EQ1_B1_C - [15:0] */ +#define ARIZONA_EQ1_B1_C_WIDTH 16 /* EQ1_B1_C - [15:0] */ + +/* + * R3622 (0xE26) - EQ2_1 + */ +#define ARIZONA_EQ2_B1_GAIN_MASK 0xF800 /* EQ2_B1_GAIN - [15:11] */ +#define ARIZONA_EQ2_B1_GAIN_SHIFT 11 /* EQ2_B1_GAIN - [15:11] */ +#define ARIZONA_EQ2_B1_GAIN_WIDTH 5 /* EQ2_B1_GAIN - [15:11] */ +#define ARIZONA_EQ2_B2_GAIN_MASK 0x07C0 /* EQ2_B2_GAIN - [10:6] */ +#define ARIZONA_EQ2_B2_GAIN_SHIFT 6 /* EQ2_B2_GAIN - [10:6] */ +#define ARIZONA_EQ2_B2_GAIN_WIDTH 5 /* EQ2_B2_GAIN - [10:6] */ +#define ARIZONA_EQ2_B3_GAIN_MASK 0x003E /* EQ2_B3_GAIN - [5:1] */ +#define ARIZONA_EQ2_B3_GAIN_SHIFT 1 /* EQ2_B3_GAIN - [5:1] */ +#define ARIZONA_EQ2_B3_GAIN_WIDTH 5 /* EQ2_B3_GAIN - [5:1] */ +#define ARIZONA_EQ2_ENA 0x0001 /* EQ2_ENA */ +#define ARIZONA_EQ2_ENA_MASK 0x0001 /* EQ2_ENA */ +#define ARIZONA_EQ2_ENA_SHIFT 0 /* EQ2_ENA */ +#define ARIZONA_EQ2_ENA_WIDTH 1 /* EQ2_ENA */ + +/* + * R3623 (0xE27) - EQ2_2 + */ +#define ARIZONA_EQ2_B4_GAIN_MASK 0xF800 /* EQ2_B4_GAIN - [15:11] */ +#define ARIZONA_EQ2_B4_GAIN_SHIFT 11 /* EQ2_B4_GAIN - [15:11] */ +#define ARIZONA_EQ2_B4_GAIN_WIDTH 5 /* EQ2_B4_GAIN - [15:11] */ +#define ARIZONA_EQ2_B5_GAIN_MASK 0x07C0 /* EQ2_B5_GAIN - [10:6] */ +#define ARIZONA_EQ2_B5_GAIN_SHIFT 6 /* EQ2_B5_GAIN - [10:6] */ +#define ARIZONA_EQ2_B5_GAIN_WIDTH 5 /* EQ2_B5_GAIN - [10:6] */ +#define ARIZONA_EQ2_B1_MODE 0x0001 /* EQ2_B1_MODE */ +#define ARIZONA_EQ2_B1_MODE_MASK 0x0001 /* EQ2_B1_MODE */ +#define ARIZONA_EQ2_B1_MODE_SHIFT 0 /* EQ2_B1_MODE */ +#define ARIZONA_EQ2_B1_MODE_WIDTH 1 /* EQ2_B1_MODE */ + +/* + * R3624 (0xE28) - EQ2_3 + */ +#define ARIZONA_EQ2_B1_A_MASK 0xFFFF /* EQ2_B1_A - [15:0] */ +#define ARIZONA_EQ2_B1_A_SHIFT 0 /* EQ2_B1_A - [15:0] */ +#define ARIZONA_EQ2_B1_A_WIDTH 16 /* EQ2_B1_A - [15:0] */ + +/* + * R3625 (0xE29) - EQ2_4 + */ +#define ARIZONA_EQ2_B1_B_MASK 0xFFFF /* EQ2_B1_B - [15:0] */ +#define ARIZONA_EQ2_B1_B_SHIFT 0 /* EQ2_B1_B - [15:0] */ +#define ARIZONA_EQ2_B1_B_WIDTH 16 /* EQ2_B1_B - [15:0] */ + +/* + * R3626 (0xE2A) - EQ2_5 + */ +#define ARIZONA_EQ2_B1_PG_MASK 0xFFFF /* EQ2_B1_PG - [15:0] */ +#define ARIZONA_EQ2_B1_PG_SHIFT 0 /* EQ2_B1_PG - [15:0] */ +#define ARIZONA_EQ2_B1_PG_WIDTH 16 /* EQ2_B1_PG - [15:0] */ + +/* + * R3627 (0xE2B) - EQ2_6 + */ +#define ARIZONA_EQ2_B2_A_MASK 0xFFFF /* EQ2_B2_A - [15:0] */ +#define ARIZONA_EQ2_B2_A_SHIFT 0 /* EQ2_B2_A - [15:0] */ +#define ARIZONA_EQ2_B2_A_WIDTH 16 /* EQ2_B2_A - [15:0] */ + +/* + * R3628 (0xE2C) - EQ2_7 + */ +#define ARIZONA_EQ2_B2_B_MASK 0xFFFF /* EQ2_B2_B - [15:0] */ +#define ARIZONA_EQ2_B2_B_SHIFT 0 /* EQ2_B2_B - [15:0] */ +#define ARIZONA_EQ2_B2_B_WIDTH 16 /* EQ2_B2_B - [15:0] */ + +/* + * R3629 (0xE2D) - EQ2_8 + */ +#define ARIZONA_EQ2_B2_C_MASK 0xFFFF /* EQ2_B2_C - [15:0] */ +#define ARIZONA_EQ2_B2_C_SHIFT 0 /* EQ2_B2_C - [15:0] */ +#define ARIZONA_EQ2_B2_C_WIDTH 16 /* EQ2_B2_C - [15:0] */ + +/* + * R3630 (0xE2E) - EQ2_9 + */ +#define ARIZONA_EQ2_B2_PG_MASK 0xFFFF /* EQ2_B2_PG - [15:0] */ +#define ARIZONA_EQ2_B2_PG_SHIFT 0 /* EQ2_B2_PG - [15:0] */ +#define ARIZONA_EQ2_B2_PG_WIDTH 16 /* EQ2_B2_PG - [15:0] */ + +/* + * R3631 (0xE2F) - EQ2_10 + */ +#define ARIZONA_EQ2_B3_A_MASK 0xFFFF /* EQ2_B3_A - [15:0] */ +#define ARIZONA_EQ2_B3_A_SHIFT 0 /* EQ2_B3_A - [15:0] */ +#define ARIZONA_EQ2_B3_A_WIDTH 16 /* EQ2_B3_A - [15:0] */ + +/* + * R3632 (0xE30) - EQ2_11 + */ +#define ARIZONA_EQ2_B3_B_MASK 0xFFFF /* EQ2_B3_B - [15:0] */ +#define ARIZONA_EQ2_B3_B_SHIFT 0 /* EQ2_B3_B - [15:0] */ +#define ARIZONA_EQ2_B3_B_WIDTH 16 /* EQ2_B3_B - [15:0] */ + +/* + * R3633 (0xE31) - EQ2_12 + */ +#define ARIZONA_EQ2_B3_C_MASK 0xFFFF /* EQ2_B3_C - [15:0] */ +#define ARIZONA_EQ2_B3_C_SHIFT 0 /* EQ2_B3_C - [15:0] */ +#define ARIZONA_EQ2_B3_C_WIDTH 16 /* EQ2_B3_C - [15:0] */ + +/* + * R3634 (0xE32) - EQ2_13 + */ +#define ARIZONA_EQ2_B3_PG_MASK 0xFFFF /* EQ2_B3_PG - [15:0] */ +#define ARIZONA_EQ2_B3_PG_SHIFT 0 /* EQ2_B3_PG - [15:0] */ +#define ARIZONA_EQ2_B3_PG_WIDTH 16 /* EQ2_B3_PG - [15:0] */ + +/* + * R3635 (0xE33) - EQ2_14 + */ +#define ARIZONA_EQ2_B4_A_MASK 0xFFFF /* EQ2_B4_A - [15:0] */ +#define ARIZONA_EQ2_B4_A_SHIFT 0 /* EQ2_B4_A - [15:0] */ +#define ARIZONA_EQ2_B4_A_WIDTH 16 /* EQ2_B4_A - [15:0] */ + +/* + * R3636 (0xE34) - EQ2_15 + */ +#define ARIZONA_EQ2_B4_B_MASK 0xFFFF /* EQ2_B4_B - [15:0] */ +#define ARIZONA_EQ2_B4_B_SHIFT 0 /* EQ2_B4_B - [15:0] */ +#define ARIZONA_EQ2_B4_B_WIDTH 16 /* EQ2_B4_B - [15:0] */ + +/* + * R3637 (0xE35) - EQ2_16 + */ +#define ARIZONA_EQ2_B4_C_MASK 0xFFFF /* EQ2_B4_C - [15:0] */ +#define ARIZONA_EQ2_B4_C_SHIFT 0 /* EQ2_B4_C - [15:0] */ +#define ARIZONA_EQ2_B4_C_WIDTH 16 /* EQ2_B4_C - [15:0] */ + +/* + * R3638 (0xE36) - EQ2_17 + */ +#define ARIZONA_EQ2_B4_PG_MASK 0xFFFF /* EQ2_B4_PG - [15:0] */ +#define ARIZONA_EQ2_B4_PG_SHIFT 0 /* EQ2_B4_PG - [15:0] */ +#define ARIZONA_EQ2_B4_PG_WIDTH 16 /* EQ2_B4_PG - [15:0] */ + +/* + * R3639 (0xE37) - EQ2_18 + */ +#define ARIZONA_EQ2_B5_A_MASK 0xFFFF /* EQ2_B5_A - [15:0] */ +#define ARIZONA_EQ2_B5_A_SHIFT 0 /* EQ2_B5_A - [15:0] */ +#define ARIZONA_EQ2_B5_A_WIDTH 16 /* EQ2_B5_A - [15:0] */ + +/* + * R3640 (0xE38) - EQ2_19 + */ +#define ARIZONA_EQ2_B5_B_MASK 0xFFFF /* EQ2_B5_B - [15:0] */ +#define ARIZONA_EQ2_B5_B_SHIFT 0 /* EQ2_B5_B - [15:0] */ +#define ARIZONA_EQ2_B5_B_WIDTH 16 /* EQ2_B5_B - [15:0] */ + +/* + * R3641 (0xE39) - EQ2_20 + */ +#define ARIZONA_EQ2_B5_PG_MASK 0xFFFF /* EQ2_B5_PG - [15:0] */ +#define ARIZONA_EQ2_B5_PG_SHIFT 0 /* EQ2_B5_PG - [15:0] */ +#define ARIZONA_EQ2_B5_PG_WIDTH 16 /* EQ2_B5_PG - [15:0] */ + +/* + * R3642 (0xE3A) - EQ2_21 + */ +#define ARIZONA_EQ2_B1_C_MASK 0xFFFF /* EQ2_B1_C - [15:0] */ +#define ARIZONA_EQ2_B1_C_SHIFT 0 /* EQ2_B1_C - [15:0] */ +#define ARIZONA_EQ2_B1_C_WIDTH 16 /* EQ2_B1_C - [15:0] */ + +/* + * R3644 (0xE3C) - EQ3_1 + */ +#define ARIZONA_EQ3_B1_GAIN_MASK 0xF800 /* EQ3_B1_GAIN - [15:11] */ +#define ARIZONA_EQ3_B1_GAIN_SHIFT 11 /* EQ3_B1_GAIN - [15:11] */ +#define ARIZONA_EQ3_B1_GAIN_WIDTH 5 /* EQ3_B1_GAIN - [15:11] */ +#define ARIZONA_EQ3_B2_GAIN_MASK 0x07C0 /* EQ3_B2_GAIN - [10:6] */ +#define ARIZONA_EQ3_B2_GAIN_SHIFT 6 /* EQ3_B2_GAIN - [10:6] */ +#define ARIZONA_EQ3_B2_GAIN_WIDTH 5 /* EQ3_B2_GAIN - [10:6] */ +#define ARIZONA_EQ3_B3_GAIN_MASK 0x003E /* EQ3_B3_GAIN - [5:1] */ +#define ARIZONA_EQ3_B3_GAIN_SHIFT 1 /* EQ3_B3_GAIN - [5:1] */ +#define ARIZONA_EQ3_B3_GAIN_WIDTH 5 /* EQ3_B3_GAIN - [5:1] */ +#define ARIZONA_EQ3_ENA 0x0001 /* EQ3_ENA */ +#define ARIZONA_EQ3_ENA_MASK 0x0001 /* EQ3_ENA */ +#define ARIZONA_EQ3_ENA_SHIFT 0 /* EQ3_ENA */ +#define ARIZONA_EQ3_ENA_WIDTH 1 /* EQ3_ENA */ + +/* + * R3645 (0xE3D) - EQ3_2 + */ +#define ARIZONA_EQ3_B4_GAIN_MASK 0xF800 /* EQ3_B4_GAIN - [15:11] */ +#define ARIZONA_EQ3_B4_GAIN_SHIFT 11 /* EQ3_B4_GAIN - [15:11] */ +#define ARIZONA_EQ3_B4_GAIN_WIDTH 5 /* EQ3_B4_GAIN - [15:11] */ +#define ARIZONA_EQ3_B5_GAIN_MASK 0x07C0 /* EQ3_B5_GAIN - [10:6] */ +#define ARIZONA_EQ3_B5_GAIN_SHIFT 6 /* EQ3_B5_GAIN - [10:6] */ +#define ARIZONA_EQ3_B5_GAIN_WIDTH 5 /* EQ3_B5_GAIN - [10:6] */ +#define ARIZONA_EQ3_B1_MODE 0x0001 /* EQ3_B1_MODE */ +#define ARIZONA_EQ3_B1_MODE_MASK 0x0001 /* EQ3_B1_MODE */ +#define ARIZONA_EQ3_B1_MODE_SHIFT 0 /* EQ3_B1_MODE */ +#define ARIZONA_EQ3_B1_MODE_WIDTH 1 /* EQ3_B1_MODE */ + +/* + * R3646 (0xE3E) - EQ3_3 + */ +#define ARIZONA_EQ3_B1_A_MASK 0xFFFF /* EQ3_B1_A - [15:0] */ +#define ARIZONA_EQ3_B1_A_SHIFT 0 /* EQ3_B1_A - [15:0] */ +#define ARIZONA_EQ3_B1_A_WIDTH 16 /* EQ3_B1_A - [15:0] */ + +/* + * R3647 (0xE3F) - EQ3_4 + */ +#define ARIZONA_EQ3_B1_B_MASK 0xFFFF /* EQ3_B1_B - [15:0] */ +#define ARIZONA_EQ3_B1_B_SHIFT 0 /* EQ3_B1_B - [15:0] */ +#define ARIZONA_EQ3_B1_B_WIDTH 16 /* EQ3_B1_B - [15:0] */ + +/* + * R3648 (0xE40) - EQ3_5 + */ +#define ARIZONA_EQ3_B1_PG_MASK 0xFFFF /* EQ3_B1_PG - [15:0] */ +#define ARIZONA_EQ3_B1_PG_SHIFT 0 /* EQ3_B1_PG - [15:0] */ +#define ARIZONA_EQ3_B1_PG_WIDTH 16 /* EQ3_B1_PG - [15:0] */ + +/* + * R3649 (0xE41) - EQ3_6 + */ +#define ARIZONA_EQ3_B2_A_MASK 0xFFFF /* EQ3_B2_A - [15:0] */ +#define ARIZONA_EQ3_B2_A_SHIFT 0 /* EQ3_B2_A - [15:0] */ +#define ARIZONA_EQ3_B2_A_WIDTH 16 /* EQ3_B2_A - [15:0] */ + +/* + * R3650 (0xE42) - EQ3_7 + */ +#define ARIZONA_EQ3_B2_B_MASK 0xFFFF /* EQ3_B2_B - [15:0] */ +#define ARIZONA_EQ3_B2_B_SHIFT 0 /* EQ3_B2_B - [15:0] */ +#define ARIZONA_EQ3_B2_B_WIDTH 16 /* EQ3_B2_B - [15:0] */ + +/* + * R3651 (0xE43) - EQ3_8 + */ +#define ARIZONA_EQ3_B2_C_MASK 0xFFFF /* EQ3_B2_C - [15:0] */ +#define ARIZONA_EQ3_B2_C_SHIFT 0 /* EQ3_B2_C - [15:0] */ +#define ARIZONA_EQ3_B2_C_WIDTH 16 /* EQ3_B2_C - [15:0] */ + +/* + * R3652 (0xE44) - EQ3_9 + */ +#define ARIZONA_EQ3_B2_PG_MASK 0xFFFF /* EQ3_B2_PG - [15:0] */ +#define ARIZONA_EQ3_B2_PG_SHIFT 0 /* EQ3_B2_PG - [15:0] */ +#define ARIZONA_EQ3_B2_PG_WIDTH 16 /* EQ3_B2_PG - [15:0] */ + +/* + * R3653 (0xE45) - EQ3_10 + */ +#define ARIZONA_EQ3_B3_A_MASK 0xFFFF /* EQ3_B3_A - [15:0] */ +#define ARIZONA_EQ3_B3_A_SHIFT 0 /* EQ3_B3_A - [15:0] */ +#define ARIZONA_EQ3_B3_A_WIDTH 16 /* EQ3_B3_A - [15:0] */ + +/* + * R3654 (0xE46) - EQ3_11 + */ +#define ARIZONA_EQ3_B3_B_MASK 0xFFFF /* EQ3_B3_B - [15:0] */ +#define ARIZONA_EQ3_B3_B_SHIFT 0 /* EQ3_B3_B - [15:0] */ +#define ARIZONA_EQ3_B3_B_WIDTH 16 /* EQ3_B3_B - [15:0] */ + +/* + * R3655 (0xE47) - EQ3_12 + */ +#define ARIZONA_EQ3_B3_C_MASK 0xFFFF /* EQ3_B3_C - [15:0] */ +#define ARIZONA_EQ3_B3_C_SHIFT 0 /* EQ3_B3_C - [15:0] */ +#define ARIZONA_EQ3_B3_C_WIDTH 16 /* EQ3_B3_C - [15:0] */ + +/* + * R3656 (0xE48) - EQ3_13 + */ +#define ARIZONA_EQ3_B3_PG_MASK 0xFFFF /* EQ3_B3_PG - [15:0] */ +#define ARIZONA_EQ3_B3_PG_SHIFT 0 /* EQ3_B3_PG - [15:0] */ +#define ARIZONA_EQ3_B3_PG_WIDTH 16 /* EQ3_B3_PG - [15:0] */ + +/* + * R3657 (0xE49) - EQ3_14 + */ +#define ARIZONA_EQ3_B4_A_MASK 0xFFFF /* EQ3_B4_A - [15:0] */ +#define ARIZONA_EQ3_B4_A_SHIFT 0 /* EQ3_B4_A - [15:0] */ +#define ARIZONA_EQ3_B4_A_WIDTH 16 /* EQ3_B4_A - [15:0] */ + +/* + * R3658 (0xE4A) - EQ3_15 + */ +#define ARIZONA_EQ3_B4_B_MASK 0xFFFF /* EQ3_B4_B - [15:0] */ +#define ARIZONA_EQ3_B4_B_SHIFT 0 /* EQ3_B4_B - [15:0] */ +#define ARIZONA_EQ3_B4_B_WIDTH 16 /* EQ3_B4_B - [15:0] */ + +/* + * R3659 (0xE4B) - EQ3_16 + */ +#define ARIZONA_EQ3_B4_C_MASK 0xFFFF /* EQ3_B4_C - [15:0] */ +#define ARIZONA_EQ3_B4_C_SHIFT 0 /* EQ3_B4_C - [15:0] */ +#define ARIZONA_EQ3_B4_C_WIDTH 16 /* EQ3_B4_C - [15:0] */ + +/* + * R3660 (0xE4C) - EQ3_17 + */ +#define ARIZONA_EQ3_B4_PG_MASK 0xFFFF /* EQ3_B4_PG - [15:0] */ +#define ARIZONA_EQ3_B4_PG_SHIFT 0 /* EQ3_B4_PG - [15:0] */ +#define ARIZONA_EQ3_B4_PG_WIDTH 16 /* EQ3_B4_PG - [15:0] */ + +/* + * R3661 (0xE4D) - EQ3_18 + */ +#define ARIZONA_EQ3_B5_A_MASK 0xFFFF /* EQ3_B5_A - [15:0] */ +#define ARIZONA_EQ3_B5_A_SHIFT 0 /* EQ3_B5_A - [15:0] */ +#define ARIZONA_EQ3_B5_A_WIDTH 16 /* EQ3_B5_A - [15:0] */ + +/* + * R3662 (0xE4E) - EQ3_19 + */ +#define ARIZONA_EQ3_B5_B_MASK 0xFFFF /* EQ3_B5_B - [15:0] */ +#define ARIZONA_EQ3_B5_B_SHIFT 0 /* EQ3_B5_B - [15:0] */ +#define ARIZONA_EQ3_B5_B_WIDTH 16 /* EQ3_B5_B - [15:0] */ + +/* + * R3663 (0xE4F) - EQ3_20 + */ +#define ARIZONA_EQ3_B5_PG_MASK 0xFFFF /* EQ3_B5_PG - [15:0] */ +#define ARIZONA_EQ3_B5_PG_SHIFT 0 /* EQ3_B5_PG - [15:0] */ +#define ARIZONA_EQ3_B5_PG_WIDTH 16 /* EQ3_B5_PG - [15:0] */ + +/* + * R3664 (0xE50) - EQ3_21 + */ +#define ARIZONA_EQ3_B1_C_MASK 0xFFFF /* EQ3_B1_C - [15:0] */ +#define ARIZONA_EQ3_B1_C_SHIFT 0 /* EQ3_B1_C - [15:0] */ +#define ARIZONA_EQ3_B1_C_WIDTH 16 /* EQ3_B1_C - [15:0] */ + +/* + * R3666 (0xE52) - EQ4_1 + */ +#define ARIZONA_EQ4_B1_GAIN_MASK 0xF800 /* EQ4_B1_GAIN - [15:11] */ +#define ARIZONA_EQ4_B1_GAIN_SHIFT 11 /* EQ4_B1_GAIN - [15:11] */ +#define ARIZONA_EQ4_B1_GAIN_WIDTH 5 /* EQ4_B1_GAIN - [15:11] */ +#define ARIZONA_EQ4_B2_GAIN_MASK 0x07C0 /* EQ4_B2_GAIN - [10:6] */ +#define ARIZONA_EQ4_B2_GAIN_SHIFT 6 /* EQ4_B2_GAIN - [10:6] */ +#define ARIZONA_EQ4_B2_GAIN_WIDTH 5 /* EQ4_B2_GAIN - [10:6] */ +#define ARIZONA_EQ4_B3_GAIN_MASK 0x003E /* EQ4_B3_GAIN - [5:1] */ +#define ARIZONA_EQ4_B3_GAIN_SHIFT 1 /* EQ4_B3_GAIN - [5:1] */ +#define ARIZONA_EQ4_B3_GAIN_WIDTH 5 /* EQ4_B3_GAIN - [5:1] */ +#define ARIZONA_EQ4_ENA 0x0001 /* EQ4_ENA */ +#define ARIZONA_EQ4_ENA_MASK 0x0001 /* EQ4_ENA */ +#define ARIZONA_EQ4_ENA_SHIFT 0 /* EQ4_ENA */ +#define ARIZONA_EQ4_ENA_WIDTH 1 /* EQ4_ENA */ + +/* + * R3667 (0xE53) - EQ4_2 + */ +#define ARIZONA_EQ4_B4_GAIN_MASK 0xF800 /* EQ4_B4_GAIN - [15:11] */ +#define ARIZONA_EQ4_B4_GAIN_SHIFT 11 /* EQ4_B4_GAIN - [15:11] */ +#define ARIZONA_EQ4_B4_GAIN_WIDTH 5 /* EQ4_B4_GAIN - [15:11] */ +#define ARIZONA_EQ4_B5_GAIN_MASK 0x07C0 /* EQ4_B5_GAIN - [10:6] */ +#define ARIZONA_EQ4_B5_GAIN_SHIFT 6 /* EQ4_B5_GAIN - [10:6] */ +#define ARIZONA_EQ4_B5_GAIN_WIDTH 5 /* EQ4_B5_GAIN - [10:6] */ +#define ARIZONA_EQ4_B1_MODE 0x0001 /* EQ4_B1_MODE */ +#define ARIZONA_EQ4_B1_MODE_MASK 0x0001 /* EQ4_B1_MODE */ +#define ARIZONA_EQ4_B1_MODE_SHIFT 0 /* EQ4_B1_MODE */ +#define ARIZONA_EQ4_B1_MODE_WIDTH 1 /* EQ4_B1_MODE */ + +/* + * R3668 (0xE54) - EQ4_3 + */ +#define ARIZONA_EQ4_B1_A_MASK 0xFFFF /* EQ4_B1_A - [15:0] */ +#define ARIZONA_EQ4_B1_A_SHIFT 0 /* EQ4_B1_A - [15:0] */ +#define ARIZONA_EQ4_B1_A_WIDTH 16 /* EQ4_B1_A - [15:0] */ + +/* + * R3669 (0xE55) - EQ4_4 + */ +#define ARIZONA_EQ4_B1_B_MASK 0xFFFF /* EQ4_B1_B - [15:0] */ +#define ARIZONA_EQ4_B1_B_SHIFT 0 /* EQ4_B1_B - [15:0] */ +#define ARIZONA_EQ4_B1_B_WIDTH 16 /* EQ4_B1_B - [15:0] */ + +/* + * R3670 (0xE56) - EQ4_5 + */ +#define ARIZONA_EQ4_B1_PG_MASK 0xFFFF /* EQ4_B1_PG - [15:0] */ +#define ARIZONA_EQ4_B1_PG_SHIFT 0 /* EQ4_B1_PG - [15:0] */ +#define ARIZONA_EQ4_B1_PG_WIDTH 16 /* EQ4_B1_PG - [15:0] */ + +/* + * R3671 (0xE57) - EQ4_6 + */ +#define ARIZONA_EQ4_B2_A_MASK 0xFFFF /* EQ4_B2_A - [15:0] */ +#define ARIZONA_EQ4_B2_A_SHIFT 0 /* EQ4_B2_A - [15:0] */ +#define ARIZONA_EQ4_B2_A_WIDTH 16 /* EQ4_B2_A - [15:0] */ + +/* + * R3672 (0xE58) - EQ4_7 + */ +#define ARIZONA_EQ4_B2_B_MASK 0xFFFF /* EQ4_B2_B - [15:0] */ +#define ARIZONA_EQ4_B2_B_SHIFT 0 /* EQ4_B2_B - [15:0] */ +#define ARIZONA_EQ4_B2_B_WIDTH 16 /* EQ4_B2_B - [15:0] */ + +/* + * R3673 (0xE59) - EQ4_8 + */ +#define ARIZONA_EQ4_B2_C_MASK 0xFFFF /* EQ4_B2_C - [15:0] */ +#define ARIZONA_EQ4_B2_C_SHIFT 0 /* EQ4_B2_C - [15:0] */ +#define ARIZONA_EQ4_B2_C_WIDTH 16 /* EQ4_B2_C - [15:0] */ + +/* + * R3674 (0xE5A) - EQ4_9 + */ +#define ARIZONA_EQ4_B2_PG_MASK 0xFFFF /* EQ4_B2_PG - [15:0] */ +#define ARIZONA_EQ4_B2_PG_SHIFT 0 /* EQ4_B2_PG - [15:0] */ +#define ARIZONA_EQ4_B2_PG_WIDTH 16 /* EQ4_B2_PG - [15:0] */ + +/* + * R3675 (0xE5B) - EQ4_10 + */ +#define ARIZONA_EQ4_B3_A_MASK 0xFFFF /* EQ4_B3_A - [15:0] */ +#define ARIZONA_EQ4_B3_A_SHIFT 0 /* EQ4_B3_A - [15:0] */ +#define ARIZONA_EQ4_B3_A_WIDTH 16 /* EQ4_B3_A - [15:0] */ + +/* + * R3676 (0xE5C) - EQ4_11 + */ +#define ARIZONA_EQ4_B3_B_MASK 0xFFFF /* EQ4_B3_B - [15:0] */ +#define ARIZONA_EQ4_B3_B_SHIFT 0 /* EQ4_B3_B - [15:0] */ +#define ARIZONA_EQ4_B3_B_WIDTH 16 /* EQ4_B3_B - [15:0] */ + +/* + * R3677 (0xE5D) - EQ4_12 + */ +#define ARIZONA_EQ4_B3_C_MASK 0xFFFF /* EQ4_B3_C - [15:0] */ +#define ARIZONA_EQ4_B3_C_SHIFT 0 /* EQ4_B3_C - [15:0] */ +#define ARIZONA_EQ4_B3_C_WIDTH 16 /* EQ4_B3_C - [15:0] */ + +/* + * R3678 (0xE5E) - EQ4_13 + */ +#define ARIZONA_EQ4_B3_PG_MASK 0xFFFF /* EQ4_B3_PG - [15:0] */ +#define ARIZONA_EQ4_B3_PG_SHIFT 0 /* EQ4_B3_PG - [15:0] */ +#define ARIZONA_EQ4_B3_PG_WIDTH 16 /* EQ4_B3_PG - [15:0] */ + +/* + * R3679 (0xE5F) - EQ4_14 + */ +#define ARIZONA_EQ4_B4_A_MASK 0xFFFF /* EQ4_B4_A - [15:0] */ +#define ARIZONA_EQ4_B4_A_SHIFT 0 /* EQ4_B4_A - [15:0] */ +#define ARIZONA_EQ4_B4_A_WIDTH 16 /* EQ4_B4_A - [15:0] */ + +/* + * R3680 (0xE60) - EQ4_15 + */ +#define ARIZONA_EQ4_B4_B_MASK 0xFFFF /* EQ4_B4_B - [15:0] */ +#define ARIZONA_EQ4_B4_B_SHIFT 0 /* EQ4_B4_B - [15:0] */ +#define ARIZONA_EQ4_B4_B_WIDTH 16 /* EQ4_B4_B - [15:0] */ + +/* + * R3681 (0xE61) - EQ4_16 + */ +#define ARIZONA_EQ4_B4_C_MASK 0xFFFF /* EQ4_B4_C - [15:0] */ +#define ARIZONA_EQ4_B4_C_SHIFT 0 /* EQ4_B4_C - [15:0] */ +#define ARIZONA_EQ4_B4_C_WIDTH 16 /* EQ4_B4_C - [15:0] */ + +/* + * R3682 (0xE62) - EQ4_17 + */ +#define ARIZONA_EQ4_B4_PG_MASK 0xFFFF /* EQ4_B4_PG - [15:0] */ +#define ARIZONA_EQ4_B4_PG_SHIFT 0 /* EQ4_B4_PG - [15:0] */ +#define ARIZONA_EQ4_B4_PG_WIDTH 16 /* EQ4_B4_PG - [15:0] */ + +/* + * R3683 (0xE63) - EQ4_18 + */ +#define ARIZONA_EQ4_B5_A_MASK 0xFFFF /* EQ4_B5_A - [15:0] */ +#define ARIZONA_EQ4_B5_A_SHIFT 0 /* EQ4_B5_A - [15:0] */ +#define ARIZONA_EQ4_B5_A_WIDTH 16 /* EQ4_B5_A - [15:0] */ + +/* + * R3684 (0xE64) - EQ4_19 + */ +#define ARIZONA_EQ4_B5_B_MASK 0xFFFF /* EQ4_B5_B - [15:0] */ +#define ARIZONA_EQ4_B5_B_SHIFT 0 /* EQ4_B5_B - [15:0] */ +#define ARIZONA_EQ4_B5_B_WIDTH 16 /* EQ4_B5_B - [15:0] */ + +/* + * R3685 (0xE65) - EQ4_20 + */ +#define ARIZONA_EQ4_B5_PG_MASK 0xFFFF /* EQ4_B5_PG - [15:0] */ +#define ARIZONA_EQ4_B5_PG_SHIFT 0 /* EQ4_B5_PG - [15:0] */ +#define ARIZONA_EQ4_B5_PG_WIDTH 16 /* EQ4_B5_PG - [15:0] */ + +/* + * R3686 (0xE66) - EQ4_21 + */ +#define ARIZONA_EQ4_B1_C_MASK 0xFFFF /* EQ4_B1_C - [15:0] */ +#define ARIZONA_EQ4_B1_C_SHIFT 0 /* EQ4_B1_C - [15:0] */ +#define ARIZONA_EQ4_B1_C_WIDTH 16 /* EQ4_B1_C - [15:0] */ + +/* + * R3712 (0xE80) - DRC1 ctrl1 + */ +#define ARIZONA_DRC1_SIG_DET_RMS_MASK 0xF800 /* DRC1_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC1_SIG_DET_RMS_SHIFT 11 /* DRC1_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC1_SIG_DET_RMS_WIDTH 5 /* DRC1_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC1_SIG_DET_PK_MASK 0x0600 /* DRC1_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC1_SIG_DET_PK_SHIFT 9 /* DRC1_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC1_SIG_DET_PK_WIDTH 2 /* DRC1_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC1_NG_ENA 0x0100 /* DRC1_NG_ENA */ +#define ARIZONA_DRC1_NG_ENA_MASK 0x0100 /* DRC1_NG_ENA */ +#define ARIZONA_DRC1_NG_ENA_SHIFT 8 /* DRC1_NG_ENA */ +#define ARIZONA_DRC1_NG_ENA_WIDTH 1 /* DRC1_NG_ENA */ +#define ARIZONA_DRC1_SIG_DET_MODE 0x0080 /* DRC1_SIG_DET_MODE */ +#define ARIZONA_DRC1_SIG_DET_MODE_MASK 0x0080 /* DRC1_SIG_DET_MODE */ +#define ARIZONA_DRC1_SIG_DET_MODE_SHIFT 7 /* DRC1_SIG_DET_MODE */ +#define ARIZONA_DRC1_SIG_DET_MODE_WIDTH 1 /* DRC1_SIG_DET_MODE */ +#define ARIZONA_DRC1_SIG_DET 0x0040 /* DRC1_SIG_DET */ +#define ARIZONA_DRC1_SIG_DET_MASK 0x0040 /* DRC1_SIG_DET */ +#define ARIZONA_DRC1_SIG_DET_SHIFT 6 /* DRC1_SIG_DET */ +#define ARIZONA_DRC1_SIG_DET_WIDTH 1 /* DRC1_SIG_DET */ +#define ARIZONA_DRC1_KNEE2_OP_ENA 0x0020 /* DRC1_KNEE2_OP_ENA */ +#define ARIZONA_DRC1_KNEE2_OP_ENA_MASK 0x0020 /* DRC1_KNEE2_OP_ENA */ +#define ARIZONA_DRC1_KNEE2_OP_ENA_SHIFT 5 /* DRC1_KNEE2_OP_ENA */ +#define ARIZONA_DRC1_KNEE2_OP_ENA_WIDTH 1 /* DRC1_KNEE2_OP_ENA */ +#define ARIZONA_DRC1_QR 0x0010 /* DRC1_QR */ +#define ARIZONA_DRC1_QR_MASK 0x0010 /* DRC1_QR */ +#define ARIZONA_DRC1_QR_SHIFT 4 /* DRC1_QR */ +#define ARIZONA_DRC1_QR_WIDTH 1 /* DRC1_QR */ +#define ARIZONA_DRC1_ANTICLIP 0x0008 /* DRC1_ANTICLIP */ +#define ARIZONA_DRC1_ANTICLIP_MASK 0x0008 /* DRC1_ANTICLIP */ +#define ARIZONA_DRC1_ANTICLIP_SHIFT 3 /* DRC1_ANTICLIP */ +#define ARIZONA_DRC1_ANTICLIP_WIDTH 1 /* DRC1_ANTICLIP */ +#define ARIZONA_DRC1L_ENA 0x0002 /* DRC1L_ENA */ +#define ARIZONA_DRC1L_ENA_MASK 0x0002 /* DRC1L_ENA */ +#define ARIZONA_DRC1L_ENA_SHIFT 1 /* DRC1L_ENA */ +#define ARIZONA_DRC1L_ENA_WIDTH 1 /* DRC1L_ENA */ +#define ARIZONA_DRC1R_ENA 0x0001 /* DRC1R_ENA */ +#define ARIZONA_DRC1R_ENA_MASK 0x0001 /* DRC1R_ENA */ +#define ARIZONA_DRC1R_ENA_SHIFT 0 /* DRC1R_ENA */ +#define ARIZONA_DRC1R_ENA_WIDTH 1 /* DRC1R_ENA */ + +/* + * R3713 (0xE81) - DRC1 ctrl2 + */ +#define ARIZONA_DRC1_ATK_MASK 0x1E00 /* DRC1_ATK - [12:9] */ +#define ARIZONA_DRC1_ATK_SHIFT 9 /* DRC1_ATK - [12:9] */ +#define ARIZONA_DRC1_ATK_WIDTH 4 /* DRC1_ATK - [12:9] */ +#define ARIZONA_DRC1_DCY_MASK 0x01E0 /* DRC1_DCY - [8:5] */ +#define ARIZONA_DRC1_DCY_SHIFT 5 /* DRC1_DCY - [8:5] */ +#define ARIZONA_DRC1_DCY_WIDTH 4 /* DRC1_DCY - [8:5] */ +#define ARIZONA_DRC1_MINGAIN_MASK 0x001C /* DRC1_MINGAIN - [4:2] */ +#define ARIZONA_DRC1_MINGAIN_SHIFT 2 /* DRC1_MINGAIN - [4:2] */ +#define ARIZONA_DRC1_MINGAIN_WIDTH 3 /* DRC1_MINGAIN - [4:2] */ +#define ARIZONA_DRC1_MAXGAIN_MASK 0x0003 /* DRC1_MAXGAIN - [1:0] */ +#define ARIZONA_DRC1_MAXGAIN_SHIFT 0 /* DRC1_MAXGAIN - [1:0] */ +#define ARIZONA_DRC1_MAXGAIN_WIDTH 2 /* DRC1_MAXGAIN - [1:0] */ + +/* + * R3714 (0xE82) - DRC1 ctrl3 + */ +#define ARIZONA_DRC1_NG_MINGAIN_MASK 0xF000 /* DRC1_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC1_NG_MINGAIN_SHIFT 12 /* DRC1_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC1_NG_MINGAIN_WIDTH 4 /* DRC1_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC1_NG_EXP_MASK 0x0C00 /* DRC1_NG_EXP - [11:10] */ +#define ARIZONA_DRC1_NG_EXP_SHIFT 10 /* DRC1_NG_EXP - [11:10] */ +#define ARIZONA_DRC1_NG_EXP_WIDTH 2 /* DRC1_NG_EXP - [11:10] */ +#define ARIZONA_DRC1_QR_THR_MASK 0x0300 /* DRC1_QR_THR - [9:8] */ +#define ARIZONA_DRC1_QR_THR_SHIFT 8 /* DRC1_QR_THR - [9:8] */ +#define ARIZONA_DRC1_QR_THR_WIDTH 2 /* DRC1_QR_THR - [9:8] */ +#define ARIZONA_DRC1_QR_DCY_MASK 0x00C0 /* DRC1_QR_DCY - [7:6] */ +#define ARIZONA_DRC1_QR_DCY_SHIFT 6 /* DRC1_QR_DCY - [7:6] */ +#define ARIZONA_DRC1_QR_DCY_WIDTH 2 /* DRC1_QR_DCY - [7:6] */ +#define ARIZONA_DRC1_HI_COMP_MASK 0x0038 /* DRC1_HI_COMP - [5:3] */ +#define ARIZONA_DRC1_HI_COMP_SHIFT 3 /* DRC1_HI_COMP - [5:3] */ +#define ARIZONA_DRC1_HI_COMP_WIDTH 3 /* DRC1_HI_COMP - [5:3] */ +#define ARIZONA_DRC1_LO_COMP_MASK 0x0007 /* DRC1_LO_COMP - [2:0] */ +#define ARIZONA_DRC1_LO_COMP_SHIFT 0 /* DRC1_LO_COMP - [2:0] */ +#define ARIZONA_DRC1_LO_COMP_WIDTH 3 /* DRC1_LO_COMP - [2:0] */ + +/* + * R3715 (0xE83) - DRC1 ctrl4 + */ +#define ARIZONA_DRC1_KNEE_IP_MASK 0x07E0 /* DRC1_KNEE_IP - [10:5] */ +#define ARIZONA_DRC1_KNEE_IP_SHIFT 5 /* DRC1_KNEE_IP - [10:5] */ +#define ARIZONA_DRC1_KNEE_IP_WIDTH 6 /* DRC1_KNEE_IP - [10:5] */ +#define ARIZONA_DRC1_KNEE_OP_MASK 0x001F /* DRC1_KNEE_OP - [4:0] */ +#define ARIZONA_DRC1_KNEE_OP_SHIFT 0 /* DRC1_KNEE_OP - [4:0] */ +#define ARIZONA_DRC1_KNEE_OP_WIDTH 5 /* DRC1_KNEE_OP - [4:0] */ + +/* + * R3716 (0xE84) - DRC1 ctrl5 + */ +#define ARIZONA_DRC1_KNEE2_IP_MASK 0x03E0 /* DRC1_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC1_KNEE2_IP_SHIFT 5 /* DRC1_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC1_KNEE2_IP_WIDTH 5 /* DRC1_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC1_KNEE2_OP_MASK 0x001F /* DRC1_KNEE2_OP - [4:0] */ +#define ARIZONA_DRC1_KNEE2_OP_SHIFT 0 /* DRC1_KNEE2_OP - [4:0] */ +#define ARIZONA_DRC1_KNEE2_OP_WIDTH 5 /* DRC1_KNEE2_OP - [4:0] */ + +/* + * R3721 (0xE89) - DRC2 ctrl1 + */ +#define ARIZONA_DRC2_SIG_DET_RMS_MASK 0xF800 /* DRC2_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC2_SIG_DET_RMS_SHIFT 11 /* DRC2_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC2_SIG_DET_RMS_WIDTH 5 /* DRC2_SIG_DET_RMS - [15:11] */ +#define ARIZONA_DRC2_SIG_DET_PK_MASK 0x0600 /* DRC2_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC2_SIG_DET_PK_SHIFT 9 /* DRC2_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC2_SIG_DET_PK_WIDTH 2 /* DRC2_SIG_DET_PK - [10:9] */ +#define ARIZONA_DRC2_NG_ENA 0x0100 /* DRC2_NG_ENA */ +#define ARIZONA_DRC2_NG_ENA_MASK 0x0100 /* DRC2_NG_ENA */ +#define ARIZONA_DRC2_NG_ENA_SHIFT 8 /* DRC2_NG_ENA */ +#define ARIZONA_DRC2_NG_ENA_WIDTH 1 /* DRC2_NG_ENA */ +#define ARIZONA_DRC2_SIG_DET_MODE 0x0080 /* DRC2_SIG_DET_MODE */ +#define ARIZONA_DRC2_SIG_DET_MODE_MASK 0x0080 /* DRC2_SIG_DET_MODE */ +#define ARIZONA_DRC2_SIG_DET_MODE_SHIFT 7 /* DRC2_SIG_DET_MODE */ +#define ARIZONA_DRC2_SIG_DET_MODE_WIDTH 1 /* DRC2_SIG_DET_MODE */ +#define ARIZONA_DRC2_SIG_DET 0x0040 /* DRC2_SIG_DET */ +#define ARIZONA_DRC2_SIG_DET_MASK 0x0040 /* DRC2_SIG_DET */ +#define ARIZONA_DRC2_SIG_DET_SHIFT 6 /* DRC2_SIG_DET */ +#define ARIZONA_DRC2_SIG_DET_WIDTH 1 /* DRC2_SIG_DET */ +#define ARIZONA_DRC2_KNEE2_OP_ENA 0x0020 /* DRC2_KNEE2_OP_ENA */ +#define ARIZONA_DRC2_KNEE2_OP_ENA_MASK 0x0020 /* DRC2_KNEE2_OP_ENA */ +#define ARIZONA_DRC2_KNEE2_OP_ENA_SHIFT 5 /* DRC2_KNEE2_OP_ENA */ +#define ARIZONA_DRC2_KNEE2_OP_ENA_WIDTH 1 /* DRC2_KNEE2_OP_ENA */ +#define ARIZONA_DRC2_QR 0x0010 /* DRC2_QR */ +#define ARIZONA_DRC2_QR_MASK 0x0010 /* DRC2_QR */ +#define ARIZONA_DRC2_QR_SHIFT 4 /* DRC2_QR */ +#define ARIZONA_DRC2_QR_WIDTH 1 /* DRC2_QR */ +#define ARIZONA_DRC2_ANTICLIP 0x0008 /* DRC2_ANTICLIP */ +#define ARIZONA_DRC2_ANTICLIP_MASK 0x0008 /* DRC2_ANTICLIP */ +#define ARIZONA_DRC2_ANTICLIP_SHIFT 3 /* DRC2_ANTICLIP */ +#define ARIZONA_DRC2_ANTICLIP_WIDTH 1 /* DRC2_ANTICLIP */ +#define ARIZONA_DRC2L_ENA 0x0002 /* DRC2L_ENA */ +#define ARIZONA_DRC2L_ENA_MASK 0x0002 /* DRC2L_ENA */ +#define ARIZONA_DRC2L_ENA_SHIFT 1 /* DRC2L_ENA */ +#define ARIZONA_DRC2L_ENA_WIDTH 1 /* DRC2L_ENA */ +#define ARIZONA_DRC2R_ENA 0x0001 /* DRC2R_ENA */ +#define ARIZONA_DRC2R_ENA_MASK 0x0001 /* DRC2R_ENA */ +#define ARIZONA_DRC2R_ENA_SHIFT 0 /* DRC2R_ENA */ +#define ARIZONA_DRC2R_ENA_WIDTH 1 /* DRC2R_ENA */ + +/* + * R3722 (0xE8A) - DRC2 ctrl2 + */ +#define ARIZONA_DRC2_ATK_MASK 0x1E00 /* DRC2_ATK - [12:9] */ +#define ARIZONA_DRC2_ATK_SHIFT 9 /* DRC2_ATK - [12:9] */ +#define ARIZONA_DRC2_ATK_WIDTH 4 /* DRC2_ATK - [12:9] */ +#define ARIZONA_DRC2_DCY_MASK 0x01E0 /* DRC2_DCY - [8:5] */ +#define ARIZONA_DRC2_DCY_SHIFT 5 /* DRC2_DCY - [8:5] */ +#define ARIZONA_DRC2_DCY_WIDTH 4 /* DRC2_DCY - [8:5] */ +#define ARIZONA_DRC2_MINGAIN_MASK 0x001C /* DRC2_MINGAIN - [4:2] */ +#define ARIZONA_DRC2_MINGAIN_SHIFT 2 /* DRC2_MINGAIN - [4:2] */ +#define ARIZONA_DRC2_MINGAIN_WIDTH 3 /* DRC2_MINGAIN - [4:2] */ +#define ARIZONA_DRC2_MAXGAIN_MASK 0x0003 /* DRC2_MAXGAIN - [1:0] */ +#define ARIZONA_DRC2_MAXGAIN_SHIFT 0 /* DRC2_MAXGAIN - [1:0] */ +#define ARIZONA_DRC2_MAXGAIN_WIDTH 2 /* DRC2_MAXGAIN - [1:0] */ + +/* + * R3723 (0xE8B) - DRC2 ctrl3 + */ +#define ARIZONA_DRC2_NG_MINGAIN_MASK 0xF000 /* DRC2_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC2_NG_MINGAIN_SHIFT 12 /* DRC2_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC2_NG_MINGAIN_WIDTH 4 /* DRC2_NG_MINGAIN - [15:12] */ +#define ARIZONA_DRC2_NG_EXP_MASK 0x0C00 /* DRC2_NG_EXP - [11:10] */ +#define ARIZONA_DRC2_NG_EXP_SHIFT 10 /* DRC2_NG_EXP - [11:10] */ +#define ARIZONA_DRC2_NG_EXP_WIDTH 2 /* DRC2_NG_EXP - [11:10] */ +#define ARIZONA_DRC2_QR_THR_MASK 0x0300 /* DRC2_QR_THR - [9:8] */ +#define ARIZONA_DRC2_QR_THR_SHIFT 8 /* DRC2_QR_THR - [9:8] */ +#define ARIZONA_DRC2_QR_THR_WIDTH 2 /* DRC2_QR_THR - [9:8] */ +#define ARIZONA_DRC2_QR_DCY_MASK 0x00C0 /* DRC2_QR_DCY - [7:6] */ +#define ARIZONA_DRC2_QR_DCY_SHIFT 6 /* DRC2_QR_DCY - [7:6] */ +#define ARIZONA_DRC2_QR_DCY_WIDTH 2 /* DRC2_QR_DCY - [7:6] */ +#define ARIZONA_DRC2_HI_COMP_MASK 0x0038 /* DRC2_HI_COMP - [5:3] */ +#define ARIZONA_DRC2_HI_COMP_SHIFT 3 /* DRC2_HI_COMP - [5:3] */ +#define ARIZONA_DRC2_HI_COMP_WIDTH 3 /* DRC2_HI_COMP - [5:3] */ +#define ARIZONA_DRC2_LO_COMP_MASK 0x0007 /* DRC2_LO_COMP - [2:0] */ +#define ARIZONA_DRC2_LO_COMP_SHIFT 0 /* DRC2_LO_COMP - [2:0] */ +#define ARIZONA_DRC2_LO_COMP_WIDTH 3 /* DRC2_LO_COMP - [2:0] */ + +/* + * R3724 (0xE8C) - DRC2 ctrl4 + */ +#define ARIZONA_DRC2_KNEE_IP_MASK 0x07E0 /* DRC2_KNEE_IP - [10:5] */ +#define ARIZONA_DRC2_KNEE_IP_SHIFT 5 /* DRC2_KNEE_IP - [10:5] */ +#define ARIZONA_DRC2_KNEE_IP_WIDTH 6 /* DRC2_KNEE_IP - [10:5] */ +#define ARIZONA_DRC2_KNEE_OP_MASK 0x001F /* DRC2_KNEE_OP - [4:0] */ +#define ARIZONA_DRC2_KNEE_OP_SHIFT 0 /* DRC2_KNEE_OP - [4:0] */ +#define ARIZONA_DRC2_KNEE_OP_WIDTH 5 /* DRC2_KNEE_OP - [4:0] */ + +/* + * R3725 (0xE8D) - DRC2 ctrl5 + */ +#define ARIZONA_DRC2_KNEE2_IP_MASK 0x03E0 /* DRC2_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC2_KNEE2_IP_SHIFT 5 /* DRC2_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC2_KNEE2_IP_WIDTH 5 /* DRC2_KNEE2_IP - [9:5] */ +#define ARIZONA_DRC2_KNEE2_OP_MASK 0x001F /* DRC2_KNEE2_OP - [4:0] */ +#define ARIZONA_DRC2_KNEE2_OP_SHIFT 0 /* DRC2_KNEE2_OP - [4:0] */ +#define ARIZONA_DRC2_KNEE2_OP_WIDTH 5 /* DRC2_KNEE2_OP - [4:0] */ + +/* + * R3776 (0xEC0) - HPLPF1_1 + */ +#define ARIZONA_LHPF1_MODE 0x0002 /* LHPF1_MODE */ +#define ARIZONA_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */ +#define ARIZONA_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */ +#define ARIZONA_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */ +#define ARIZONA_LHPF1_ENA 0x0001 /* LHPF1_ENA */ +#define ARIZONA_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */ +#define ARIZONA_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */ +#define ARIZONA_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */ + +/* + * R3777 (0xEC1) - HPLPF1_2 + */ +#define ARIZONA_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */ +#define ARIZONA_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */ +#define ARIZONA_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */ + +/* + * R3780 (0xEC4) - HPLPF2_1 + */ +#define ARIZONA_LHPF2_MODE 0x0002 /* LHPF2_MODE */ +#define ARIZONA_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */ +#define ARIZONA_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */ +#define ARIZONA_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */ +#define ARIZONA_LHPF2_ENA 0x0001 /* LHPF2_ENA */ +#define ARIZONA_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */ +#define ARIZONA_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */ +#define ARIZONA_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */ + +/* + * R3781 (0xEC5) - HPLPF2_2 + */ +#define ARIZONA_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */ +#define ARIZONA_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */ +#define ARIZONA_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */ + +/* + * R3784 (0xEC8) - HPLPF3_1 + */ +#define ARIZONA_LHPF3_MODE 0x0002 /* LHPF3_MODE */ +#define ARIZONA_LHPF3_MODE_MASK 0x0002 /* LHPF3_MODE */ +#define ARIZONA_LHPF3_MODE_SHIFT 1 /* LHPF3_MODE */ +#define ARIZONA_LHPF3_MODE_WIDTH 1 /* LHPF3_MODE */ +#define ARIZONA_LHPF3_ENA 0x0001 /* LHPF3_ENA */ +#define ARIZONA_LHPF3_ENA_MASK 0x0001 /* LHPF3_ENA */ +#define ARIZONA_LHPF3_ENA_SHIFT 0 /* LHPF3_ENA */ +#define ARIZONA_LHPF3_ENA_WIDTH 1 /* LHPF3_ENA */ + +/* + * R3785 (0xEC9) - HPLPF3_2 + */ +#define ARIZONA_LHPF3_COEFF_MASK 0xFFFF /* LHPF3_COEFF - [15:0] */ +#define ARIZONA_LHPF3_COEFF_SHIFT 0 /* LHPF3_COEFF - [15:0] */ +#define ARIZONA_LHPF3_COEFF_WIDTH 16 /* LHPF3_COEFF - [15:0] */ + +/* + * R3788 (0xECC) - HPLPF4_1 + */ +#define ARIZONA_LHPF4_MODE 0x0002 /* LHPF4_MODE */ +#define ARIZONA_LHPF4_MODE_MASK 0x0002 /* LHPF4_MODE */ +#define ARIZONA_LHPF4_MODE_SHIFT 1 /* LHPF4_MODE */ +#define ARIZONA_LHPF4_MODE_WIDTH 1 /* LHPF4_MODE */ +#define ARIZONA_LHPF4_ENA 0x0001 /* LHPF4_ENA */ +#define ARIZONA_LHPF4_ENA_MASK 0x0001 /* LHPF4_ENA */ +#define ARIZONA_LHPF4_ENA_SHIFT 0 /* LHPF4_ENA */ +#define ARIZONA_LHPF4_ENA_WIDTH 1 /* LHPF4_ENA */ + +/* + * R3789 (0xECD) - HPLPF4_2 + */ +#define ARIZONA_LHPF4_COEFF_MASK 0xFFFF /* LHPF4_COEFF - [15:0] */ +#define ARIZONA_LHPF4_COEFF_SHIFT 0 /* LHPF4_COEFF - [15:0] */ +#define ARIZONA_LHPF4_COEFF_WIDTH 16 /* LHPF4_COEFF - [15:0] */ + +/* + * R3808 (0xEE0) - ASRC_ENABLE + */ +#define ARIZONA_ASRC2L_ENA 0x0008 /* ASRC2L_ENA */ +#define ARIZONA_ASRC2L_ENA_MASK 0x0008 /* ASRC2L_ENA */ +#define ARIZONA_ASRC2L_ENA_SHIFT 3 /* ASRC2L_ENA */ +#define ARIZONA_ASRC2L_ENA_WIDTH 1 /* ASRC2L_ENA */ +#define ARIZONA_ASRC2R_ENA 0x0004 /* ASRC2R_ENA */ +#define ARIZONA_ASRC2R_ENA_MASK 0x0004 /* ASRC2R_ENA */ +#define ARIZONA_ASRC2R_ENA_SHIFT 2 /* ASRC2R_ENA */ +#define ARIZONA_ASRC2R_ENA_WIDTH 1 /* ASRC2R_ENA */ +#define ARIZONA_ASRC1L_ENA 0x0002 /* ASRC1L_ENA */ +#define ARIZONA_ASRC1L_ENA_MASK 0x0002 /* ASRC1L_ENA */ +#define ARIZONA_ASRC1L_ENA_SHIFT 1 /* ASRC1L_ENA */ +#define ARIZONA_ASRC1L_ENA_WIDTH 1 /* ASRC1L_ENA */ +#define ARIZONA_ASRC1R_ENA 0x0001 /* ASRC1R_ENA */ +#define ARIZONA_ASRC1R_ENA_MASK 0x0001 /* ASRC1R_ENA */ +#define ARIZONA_ASRC1R_ENA_SHIFT 0 /* ASRC1R_ENA */ +#define ARIZONA_ASRC1R_ENA_WIDTH 1 /* ASRC1R_ENA */ + +/* + * R3810 (0xEE2) - ASRC_RATE1 + */ +#define ARIZONA_ASRC_RATE1_MASK 0x7800 /* ASRC_RATE1 - [14:11] */ +#define ARIZONA_ASRC_RATE1_SHIFT 11 /* ASRC_RATE1 - [14:11] */ +#define ARIZONA_ASRC_RATE1_WIDTH 4 /* ASRC_RATE1 - [14:11] */ + +/* + * R3811 (0xEE3) - ASRC_RATE2 + */ +#define ARIZONA_ASRC_RATE2_MASK 0x7800 /* ASRC_RATE2 - [14:11] */ +#define ARIZONA_ASRC_RATE2_SHIFT 11 /* ASRC_RATE2 - [14:11] */ +#define ARIZONA_ASRC_RATE2_WIDTH 4 /* ASRC_RATE2 - [14:11] */ + +/* + * R3824 (0xEF0) - ISRC 1 CTRL 1 + */ +#define ARIZONA_ISRC1_FSH_MASK 0x7800 /* ISRC1_FSH - [14:11] */ +#define ARIZONA_ISRC1_FSH_SHIFT 11 /* ISRC1_FSH - [14:11] */ +#define ARIZONA_ISRC1_FSH_WIDTH 4 /* ISRC1_FSH - [14:11] */ +#define ARIZONA_ISRC1_CLK_SEL_MASK 0x0700 /* ISRC1_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC1_CLK_SEL_SHIFT 8 /* ISRC1_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC1_CLK_SEL_WIDTH 3 /* ISRC1_CLK_SEL - [10:8] */ + +/* + * R3825 (0xEF1) - ISRC 1 CTRL 2 + */ +#define ARIZONA_ISRC1_FSL_MASK 0x7800 /* ISRC1_FSL - [14:11] */ +#define ARIZONA_ISRC1_FSL_SHIFT 11 /* ISRC1_FSL - [14:11] */ +#define ARIZONA_ISRC1_FSL_WIDTH 4 /* ISRC1_FSL - [14:11] */ + +/* + * R3826 (0xEF2) - ISRC 1 CTRL 3 + */ +#define ARIZONA_ISRC1_INT0_ENA 0x8000 /* ISRC1_INT0_ENA */ +#define ARIZONA_ISRC1_INT0_ENA_MASK 0x8000 /* ISRC1_INT0_ENA */ +#define ARIZONA_ISRC1_INT0_ENA_SHIFT 15 /* ISRC1_INT0_ENA */ +#define ARIZONA_ISRC1_INT0_ENA_WIDTH 1 /* ISRC1_INT0_ENA */ +#define ARIZONA_ISRC1_INT1_ENA 0x4000 /* ISRC1_INT1_ENA */ +#define ARIZONA_ISRC1_INT1_ENA_MASK 0x4000 /* ISRC1_INT1_ENA */ +#define ARIZONA_ISRC1_INT1_ENA_SHIFT 14 /* ISRC1_INT1_ENA */ +#define ARIZONA_ISRC1_INT1_ENA_WIDTH 1 /* ISRC1_INT1_ENA */ +#define ARIZONA_ISRC1_INT2_ENA 0x2000 /* ISRC1_INT2_ENA */ +#define ARIZONA_ISRC1_INT2_ENA_MASK 0x2000 /* ISRC1_INT2_ENA */ +#define ARIZONA_ISRC1_INT2_ENA_SHIFT 13 /* ISRC1_INT2_ENA */ +#define ARIZONA_ISRC1_INT2_ENA_WIDTH 1 /* ISRC1_INT2_ENA */ +#define ARIZONA_ISRC1_INT3_ENA 0x1000 /* ISRC1_INT3_ENA */ +#define ARIZONA_ISRC1_INT3_ENA_MASK 0x1000 /* ISRC1_INT3_ENA */ +#define ARIZONA_ISRC1_INT3_ENA_SHIFT 12 /* ISRC1_INT3_ENA */ +#define ARIZONA_ISRC1_INT3_ENA_WIDTH 1 /* ISRC1_INT3_ENA */ +#define ARIZONA_ISRC1_DEC0_ENA 0x0200 /* ISRC1_DEC0_ENA */ +#define ARIZONA_ISRC1_DEC0_ENA_MASK 0x0200 /* ISRC1_DEC0_ENA */ +#define ARIZONA_ISRC1_DEC0_ENA_SHIFT 9 /* ISRC1_DEC0_ENA */ +#define ARIZONA_ISRC1_DEC0_ENA_WIDTH 1 /* ISRC1_DEC0_ENA */ +#define ARIZONA_ISRC1_DEC1_ENA 0x0100 /* ISRC1_DEC1_ENA */ +#define ARIZONA_ISRC1_DEC1_ENA_MASK 0x0100 /* ISRC1_DEC1_ENA */ +#define ARIZONA_ISRC1_DEC1_ENA_SHIFT 8 /* ISRC1_DEC1_ENA */ +#define ARIZONA_ISRC1_DEC1_ENA_WIDTH 1 /* ISRC1_DEC1_ENA */ +#define ARIZONA_ISRC1_DEC2_ENA 0x0080 /* ISRC1_DEC2_ENA */ +#define ARIZONA_ISRC1_DEC2_ENA_MASK 0x0080 /* ISRC1_DEC2_ENA */ +#define ARIZONA_ISRC1_DEC2_ENA_SHIFT 7 /* ISRC1_DEC2_ENA */ +#define ARIZONA_ISRC1_DEC2_ENA_WIDTH 1 /* ISRC1_DEC2_ENA */ +#define ARIZONA_ISRC1_DEC3_ENA 0x0040 /* ISRC1_DEC3_ENA */ +#define ARIZONA_ISRC1_DEC3_ENA_MASK 0x0040 /* ISRC1_DEC3_ENA */ +#define ARIZONA_ISRC1_DEC3_ENA_SHIFT 6 /* ISRC1_DEC3_ENA */ +#define ARIZONA_ISRC1_DEC3_ENA_WIDTH 1 /* ISRC1_DEC3_ENA */ +#define ARIZONA_ISRC1_NOTCH_ENA 0x0001 /* ISRC1_NOTCH_ENA */ +#define ARIZONA_ISRC1_NOTCH_ENA_MASK 0x0001 /* ISRC1_NOTCH_ENA */ +#define ARIZONA_ISRC1_NOTCH_ENA_SHIFT 0 /* ISRC1_NOTCH_ENA */ +#define ARIZONA_ISRC1_NOTCH_ENA_WIDTH 1 /* ISRC1_NOTCH_ENA */ + +/* + * R3827 (0xEF3) - ISRC 2 CTRL 1 + */ +#define ARIZONA_ISRC2_FSH_MASK 0x7800 /* ISRC2_FSH - [14:11] */ +#define ARIZONA_ISRC2_FSH_SHIFT 11 /* ISRC2_FSH - [14:11] */ +#define ARIZONA_ISRC2_FSH_WIDTH 4 /* ISRC2_FSH - [14:11] */ +#define ARIZONA_ISRC2_CLK_SEL_MASK 0x0700 /* ISRC2_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC2_CLK_SEL_SHIFT 8 /* ISRC2_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC2_CLK_SEL_WIDTH 3 /* ISRC2_CLK_SEL - [10:8] */ + +/* + * R3828 (0xEF4) - ISRC 2 CTRL 2 + */ +#define ARIZONA_ISRC2_FSL_MASK 0x7800 /* ISRC2_FSL - [14:11] */ +#define ARIZONA_ISRC2_FSL_SHIFT 11 /* ISRC2_FSL - [14:11] */ +#define ARIZONA_ISRC2_FSL_WIDTH 4 /* ISRC2_FSL - [14:11] */ + +/* + * R3829 (0xEF5) - ISRC 2 CTRL 3 + */ +#define ARIZONA_ISRC2_INT0_ENA 0x8000 /* ISRC2_INT0_ENA */ +#define ARIZONA_ISRC2_INT0_ENA_MASK 0x8000 /* ISRC2_INT0_ENA */ +#define ARIZONA_ISRC2_INT0_ENA_SHIFT 15 /* ISRC2_INT0_ENA */ +#define ARIZONA_ISRC2_INT0_ENA_WIDTH 1 /* ISRC2_INT0_ENA */ +#define ARIZONA_ISRC2_INT1_ENA 0x4000 /* ISRC2_INT1_ENA */ +#define ARIZONA_ISRC2_INT1_ENA_MASK 0x4000 /* ISRC2_INT1_ENA */ +#define ARIZONA_ISRC2_INT1_ENA_SHIFT 14 /* ISRC2_INT1_ENA */ +#define ARIZONA_ISRC2_INT1_ENA_WIDTH 1 /* ISRC2_INT1_ENA */ +#define ARIZONA_ISRC2_INT2_ENA 0x2000 /* ISRC2_INT2_ENA */ +#define ARIZONA_ISRC2_INT2_ENA_MASK 0x2000 /* ISRC2_INT2_ENA */ +#define ARIZONA_ISRC2_INT2_ENA_SHIFT 13 /* ISRC2_INT2_ENA */ +#define ARIZONA_ISRC2_INT2_ENA_WIDTH 1 /* ISRC2_INT2_ENA */ +#define ARIZONA_ISRC2_INT3_ENA 0x1000 /* ISRC2_INT3_ENA */ +#define ARIZONA_ISRC2_INT3_ENA_MASK 0x1000 /* ISRC2_INT3_ENA */ +#define ARIZONA_ISRC2_INT3_ENA_SHIFT 12 /* ISRC2_INT3_ENA */ +#define ARIZONA_ISRC2_INT3_ENA_WIDTH 1 /* ISRC2_INT3_ENA */ +#define ARIZONA_ISRC2_DEC0_ENA 0x0200 /* ISRC2_DEC0_ENA */ +#define ARIZONA_ISRC2_DEC0_ENA_MASK 0x0200 /* ISRC2_DEC0_ENA */ +#define ARIZONA_ISRC2_DEC0_ENA_SHIFT 9 /* ISRC2_DEC0_ENA */ +#define ARIZONA_ISRC2_DEC0_ENA_WIDTH 1 /* ISRC2_DEC0_ENA */ +#define ARIZONA_ISRC2_DEC1_ENA 0x0100 /* ISRC2_DEC1_ENA */ +#define ARIZONA_ISRC2_DEC1_ENA_MASK 0x0100 /* ISRC2_DEC1_ENA */ +#define ARIZONA_ISRC2_DEC1_ENA_SHIFT 8 /* ISRC2_DEC1_ENA */ +#define ARIZONA_ISRC2_DEC1_ENA_WIDTH 1 /* ISRC2_DEC1_ENA */ +#define ARIZONA_ISRC2_DEC2_ENA 0x0080 /* ISRC2_DEC2_ENA */ +#define ARIZONA_ISRC2_DEC2_ENA_MASK 0x0080 /* ISRC2_DEC2_ENA */ +#define ARIZONA_ISRC2_DEC2_ENA_SHIFT 7 /* ISRC2_DEC2_ENA */ +#define ARIZONA_ISRC2_DEC2_ENA_WIDTH 1 /* ISRC2_DEC2_ENA */ +#define ARIZONA_ISRC2_DEC3_ENA 0x0040 /* ISRC2_DEC3_ENA */ +#define ARIZONA_ISRC2_DEC3_ENA_MASK 0x0040 /* ISRC2_DEC3_ENA */ +#define ARIZONA_ISRC2_DEC3_ENA_SHIFT 6 /* ISRC2_DEC3_ENA */ +#define ARIZONA_ISRC2_DEC3_ENA_WIDTH 1 /* ISRC2_DEC3_ENA */ +#define ARIZONA_ISRC2_NOTCH_ENA 0x0001 /* ISRC2_NOTCH_ENA */ +#define ARIZONA_ISRC2_NOTCH_ENA_MASK 0x0001 /* ISRC2_NOTCH_ENA */ +#define ARIZONA_ISRC2_NOTCH_ENA_SHIFT 0 /* ISRC2_NOTCH_ENA */ +#define ARIZONA_ISRC2_NOTCH_ENA_WIDTH 1 /* ISRC2_NOTCH_ENA */ + +/* + * R3830 (0xEF6) - ISRC 3 CTRL 1 + */ +#define ARIZONA_ISRC3_FSH_MASK 0x7800 /* ISRC3_FSH - [14:11] */ +#define ARIZONA_ISRC3_FSH_SHIFT 11 /* ISRC3_FSH - [14:11] */ +#define ARIZONA_ISRC3_FSH_WIDTH 4 /* ISRC3_FSH - [14:11] */ +#define ARIZONA_ISRC3_CLK_SEL_MASK 0x0700 /* ISRC3_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC3_CLK_SEL_SHIFT 8 /* ISRC3_CLK_SEL - [10:8] */ +#define ARIZONA_ISRC3_CLK_SEL_WIDTH 3 /* ISRC3_CLK_SEL - [10:8] */ + +/* + * R3831 (0xEF7) - ISRC 3 CTRL 2 + */ +#define ARIZONA_ISRC3_FSL_MASK 0x7800 /* ISRC3_FSL - [14:11] */ +#define ARIZONA_ISRC3_FSL_SHIFT 11 /* ISRC3_FSL - [14:11] */ +#define ARIZONA_ISRC3_FSL_WIDTH 4 /* ISRC3_FSL - [14:11] */ + +/* + * R3832 (0xEF8) - ISRC 3 CTRL 3 + */ +#define ARIZONA_ISRC3_INT0_ENA 0x8000 /* ISRC3_INT0_ENA */ +#define ARIZONA_ISRC3_INT0_ENA_MASK 0x8000 /* ISRC3_INT0_ENA */ +#define ARIZONA_ISRC3_INT0_ENA_SHIFT 15 /* ISRC3_INT0_ENA */ +#define ARIZONA_ISRC3_INT0_ENA_WIDTH 1 /* ISRC3_INT0_ENA */ +#define ARIZONA_ISRC3_INT1_ENA 0x4000 /* ISRC3_INT1_ENA */ +#define ARIZONA_ISRC3_INT1_ENA_MASK 0x4000 /* ISRC3_INT1_ENA */ +#define ARIZONA_ISRC3_INT1_ENA_SHIFT 14 /* ISRC3_INT1_ENA */ +#define ARIZONA_ISRC3_INT1_ENA_WIDTH 1 /* ISRC3_INT1_ENA */ +#define ARIZONA_ISRC3_INT2_ENA 0x2000 /* ISRC3_INT2_ENA */ +#define ARIZONA_ISRC3_INT2_ENA_MASK 0x2000 /* ISRC3_INT2_ENA */ +#define ARIZONA_ISRC3_INT2_ENA_SHIFT 13 /* ISRC3_INT2_ENA */ +#define ARIZONA_ISRC3_INT2_ENA_WIDTH 1 /* ISRC3_INT2_ENA */ +#define ARIZONA_ISRC3_INT3_ENA 0x1000 /* ISRC3_INT3_ENA */ +#define ARIZONA_ISRC3_INT3_ENA_MASK 0x1000 /* ISRC3_INT3_ENA */ +#define ARIZONA_ISRC3_INT3_ENA_SHIFT 12 /* ISRC3_INT3_ENA */ +#define ARIZONA_ISRC3_INT3_ENA_WIDTH 1 /* ISRC3_INT3_ENA */ +#define ARIZONA_ISRC3_DEC0_ENA 0x0200 /* ISRC3_DEC0_ENA */ +#define ARIZONA_ISRC3_DEC0_ENA_MASK 0x0200 /* ISRC3_DEC0_ENA */ +#define ARIZONA_ISRC3_DEC0_ENA_SHIFT 9 /* ISRC3_DEC0_ENA */ +#define ARIZONA_ISRC3_DEC0_ENA_WIDTH 1 /* ISRC3_DEC0_ENA */ +#define ARIZONA_ISRC3_DEC1_ENA 0x0100 /* ISRC3_DEC1_ENA */ +#define ARIZONA_ISRC3_DEC1_ENA_MASK 0x0100 /* ISRC3_DEC1_ENA */ +#define ARIZONA_ISRC3_DEC1_ENA_SHIFT 8 /* ISRC3_DEC1_ENA */ +#define ARIZONA_ISRC3_DEC1_ENA_WIDTH 1 /* ISRC3_DEC1_ENA */ +#define ARIZONA_ISRC3_DEC2_ENA 0x0080 /* ISRC3_DEC2_ENA */ +#define ARIZONA_ISRC3_DEC2_ENA_MASK 0x0080 /* ISRC3_DEC2_ENA */ +#define ARIZONA_ISRC3_DEC2_ENA_SHIFT 7 /* ISRC3_DEC2_ENA */ +#define ARIZONA_ISRC3_DEC2_ENA_WIDTH 1 /* ISRC3_DEC2_ENA */ +#define ARIZONA_ISRC3_DEC3_ENA 0x0040 /* ISRC3_DEC3_ENA */ +#define ARIZONA_ISRC3_DEC3_ENA_MASK 0x0040 /* ISRC3_DEC3_ENA */ +#define ARIZONA_ISRC3_DEC3_ENA_SHIFT 6 /* ISRC3_DEC3_ENA */ +#define ARIZONA_ISRC3_DEC3_ENA_WIDTH 1 /* ISRC3_DEC3_ENA */ +#define ARIZONA_ISRC3_NOTCH_ENA 0x0001 /* ISRC3_NOTCH_ENA */ +#define ARIZONA_ISRC3_NOTCH_ENA_MASK 0x0001 /* ISRC3_NOTCH_ENA */ +#define ARIZONA_ISRC3_NOTCH_ENA_SHIFT 0 /* ISRC3_NOTCH_ENA */ +#define ARIZONA_ISRC3_NOTCH_ENA_WIDTH 1 /* ISRC3_NOTCH_ENA */ + +/* + * R4352 (0x1100) - DSP1 Control 1 + */ +#define ARIZONA_DSP1_RATE_MASK 0x7800 /* DSP1_RATE - [14:11] */ +#define ARIZONA_DSP1_RATE_SHIFT 11 /* DSP1_RATE - [14:11] */ +#define ARIZONA_DSP1_RATE_WIDTH 4 /* DSP1_RATE - [14:11] */ +#define ARIZONA_DSP1_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ +#define ARIZONA_DSP1_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ +#define ARIZONA_DSP1_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ +#define ARIZONA_DSP1_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ +#define ARIZONA_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ +#define ARIZONA_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ +#define ARIZONA_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ +#define ARIZONA_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ +#define ARIZONA_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ +#define ARIZONA_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ +#define ARIZONA_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ +#define ARIZONA_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ +#define ARIZONA_DSP1_START 0x0001 /* DSP1_START */ +#define ARIZONA_DSP1_START_MASK 0x0001 /* DSP1_START */ +#define ARIZONA_DSP1_START_SHIFT 0 /* DSP1_START */ +#define ARIZONA_DSP1_START_WIDTH 1 /* DSP1_START */ + +/* + * R4353 (0x1101) - DSP1 Clocking 1 + */ +#define ARIZONA_DSP1_CLK_SEL_MASK 0x0007 /* DSP1_CLK_SEL - [2:0] */ +#define ARIZONA_DSP1_CLK_SEL_SHIFT 0 /* DSP1_CLK_SEL - [2:0] */ +#define ARIZONA_DSP1_CLK_SEL_WIDTH 3 /* DSP1_CLK_SEL - [2:0] */ + +/* + * R4356 (0x1104) - DSP1 Status 1 + */ +#define ARIZONA_DSP1_RAM_RDY 0x0001 /* DSP1_RAM_RDY */ +#define ARIZONA_DSP1_RAM_RDY_MASK 0x0001 /* DSP1_RAM_RDY */ +#define ARIZONA_DSP1_RAM_RDY_SHIFT 0 /* DSP1_RAM_RDY */ +#define ARIZONA_DSP1_RAM_RDY_WIDTH 1 /* DSP1_RAM_RDY */ + +/* + * R4357 (0x1105) - DSP1 Status 2 + */ +#define ARIZONA_DSP1_PING_FULL 0x8000 /* DSP1_PING_FULL */ +#define ARIZONA_DSP1_PING_FULL_MASK 0x8000 /* DSP1_PING_FULL */ +#define ARIZONA_DSP1_PING_FULL_SHIFT 15 /* DSP1_PING_FULL */ +#define ARIZONA_DSP1_PING_FULL_WIDTH 1 /* DSP1_PING_FULL */ +#define ARIZONA_DSP1_PONG_FULL 0x4000 /* DSP1_PONG_FULL */ +#define ARIZONA_DSP1_PONG_FULL_MASK 0x4000 /* DSP1_PONG_FULL */ +#define ARIZONA_DSP1_PONG_FULL_SHIFT 14 /* DSP1_PONG_FULL */ +#define ARIZONA_DSP1_PONG_FULL_WIDTH 1 /* DSP1_PONG_FULL */ +#define ARIZONA_DSP1_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ +#define ARIZONA_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ +#define ARIZONA_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */ + +#endif diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 4e76163dd86..3a8435a8058 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -36,6 +36,11 @@ struct mfd_cell { /* platform data passed to the sub devices drivers */ void *platform_data; size_t pdata_size; + /* + * Device Tree compatible string + * See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details + */ + const char *of_compatible; /* * These resources can be specified relative to the parent device. diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index b3a43b1263f..b82f6ee66a0 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -530,7 +530,7 @@ int db8500_prcmu_stop_temp_sense(void); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); -void prcmu_ac_wake_req(void); +int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); void db8500_prcmu_modem_reset(void); @@ -680,7 +680,10 @@ static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) return -ENOSYS; } -static inline void prcmu_ac_wake_req(void) {} +static inline int prcmu_ac_wake_req(void) +{ + return 0; +} static inline void prcmu_ac_sleep_req(void) {} diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 5a13f93d8f1..5b90e94399e 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -345,7 +345,7 @@ static inline u16 prcmu_get_reset_code(void) return db8500_prcmu_get_reset_code(); } -void prcmu_ac_wake_req(void); +int prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); static inline void prcmu_modem_reset(void) { @@ -533,7 +533,10 @@ static inline u16 prcmu_get_reset_code(void) return 0; } -static inline void prcmu_ac_wake_req(void) {} +static inline int prcmu_ac_wake_req(void) +{ + return 0; +} static inline void prcmu_ac_sleep_req(void) {} diff --git a/include/linux/mfd/max77686-private.h b/include/linux/mfd/max77686-private.h new file mode 100644 index 00000000000..d327d4971e4 --- /dev/null +++ b/include/linux/mfd/max77686-private.h @@ -0,0 +1,246 @@ +/* + * max77686.h - Voltage regulator driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electrnoics + * Chiwoong Byun <woong.byun@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#ifndef __LINUX_MFD_MAX77686_PRIV_H +#define __LINUX_MFD_MAX77686_PRIV_H + +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/module.h> + +#define MAX77686_REG_INVALID (0xff) + +enum max77686_pmic_reg { + MAX77686_REG_DEVICE_ID = 0x00, + MAX77686_REG_INTSRC = 0x01, + MAX77686_REG_INT1 = 0x02, + MAX77686_REG_INT2 = 0x03, + + MAX77686_REG_INT1MSK = 0x04, + MAX77686_REG_INT2MSK = 0x05, + + MAX77686_REG_STATUS1 = 0x06, + MAX77686_REG_STATUS2 = 0x07, + + MAX77686_REG_PWRON = 0x08, + MAX77686_REG_ONOFF_DELAY = 0x09, + MAX77686_REG_MRSTB = 0x0A, + /* Reserved: 0x0B-0x0F */ + + MAX77686_REG_BUCK1CTRL = 0x10, + MAX77686_REG_BUCK1OUT = 0x11, + MAX77686_REG_BUCK2CTRL1 = 0x12, + MAX77686_REG_BUCK234FREQ = 0x13, + MAX77686_REG_BUCK2DVS1 = 0x14, + MAX77686_REG_BUCK2DVS2 = 0x15, + MAX77686_REG_BUCK2DVS3 = 0x16, + MAX77686_REG_BUCK2DVS4 = 0x17, + MAX77686_REG_BUCK2DVS5 = 0x18, + MAX77686_REG_BUCK2DVS6 = 0x19, + MAX77686_REG_BUCK2DVS7 = 0x1A, + MAX77686_REG_BUCK2DVS8 = 0x1B, + MAX77686_REG_BUCK3CTRL1 = 0x1C, + /* Reserved: 0x1D */ + MAX77686_REG_BUCK3DVS1 = 0x1E, + MAX77686_REG_BUCK3DVS2 = 0x1F, + MAX77686_REG_BUCK3DVS3 = 0x20, + MAX77686_REG_BUCK3DVS4 = 0x21, + MAX77686_REG_BUCK3DVS5 = 0x22, + MAX77686_REG_BUCK3DVS6 = 0x23, + MAX77686_REG_BUCK3DVS7 = 0x24, + MAX77686_REG_BUCK3DVS8 = 0x25, + MAX77686_REG_BUCK4CTRL1 = 0x26, + /* Reserved: 0x27 */ + MAX77686_REG_BUCK4DVS1 = 0x28, + MAX77686_REG_BUCK4DVS2 = 0x29, + MAX77686_REG_BUCK4DVS3 = 0x2A, + MAX77686_REG_BUCK4DVS4 = 0x2B, + MAX77686_REG_BUCK4DVS5 = 0x2C, + MAX77686_REG_BUCK4DVS6 = 0x2D, + MAX77686_REG_BUCK4DVS7 = 0x2E, + MAX77686_REG_BUCK4DVS8 = 0x2F, + MAX77686_REG_BUCK5CTRL = 0x30, + MAX77686_REG_BUCK5OUT = 0x31, + MAX77686_REG_BUCK6CTRL = 0x32, + MAX77686_REG_BUCK6OUT = 0x33, + MAX77686_REG_BUCK7CTRL = 0x34, + MAX77686_REG_BUCK7OUT = 0x35, + MAX77686_REG_BUCK8CTRL = 0x36, + MAX77686_REG_BUCK8OUT = 0x37, + MAX77686_REG_BUCK9CTRL = 0x38, + MAX77686_REG_BUCK9OUT = 0x39, + /* Reserved: 0x3A-0x3F */ + + MAX77686_REG_LDO1CTRL1 = 0x40, + MAX77686_REG_LDO2CTRL1 = 0x41, + MAX77686_REG_LDO3CTRL1 = 0x42, + MAX77686_REG_LDO4CTRL1 = 0x43, + MAX77686_REG_LDO5CTRL1 = 0x44, + MAX77686_REG_LDO6CTRL1 = 0x45, + MAX77686_REG_LDO7CTRL1 = 0x46, + MAX77686_REG_LDO8CTRL1 = 0x47, + MAX77686_REG_LDO9CTRL1 = 0x48, + MAX77686_REG_LDO10CTRL1 = 0x49, + MAX77686_REG_LDO11CTRL1 = 0x4A, + MAX77686_REG_LDO12CTRL1 = 0x4B, + MAX77686_REG_LDO13CTRL1 = 0x4C, + MAX77686_REG_LDO14CTRL1 = 0x4D, + MAX77686_REG_LDO15CTRL1 = 0x4E, + MAX77686_REG_LDO16CTRL1 = 0x4F, + MAX77686_REG_LDO17CTRL1 = 0x50, + MAX77686_REG_LDO18CTRL1 = 0x51, + MAX77686_REG_LDO19CTRL1 = 0x52, + MAX77686_REG_LDO20CTRL1 = 0x53, + MAX77686_REG_LDO21CTRL1 = 0x54, + MAX77686_REG_LDO22CTRL1 = 0x55, + MAX77686_REG_LDO23CTRL1 = 0x56, + MAX77686_REG_LDO24CTRL1 = 0x57, + MAX77686_REG_LDO25CTRL1 = 0x58, + MAX77686_REG_LDO26CTRL1 = 0x59, + /* Reserved: 0x5A-0x5F */ + MAX77686_REG_LDO1CTRL2 = 0x60, + MAX77686_REG_LDO2CTRL2 = 0x61, + MAX77686_REG_LDO3CTRL2 = 0x62, + MAX77686_REG_LDO4CTRL2 = 0x63, + MAX77686_REG_LDO5CTRL2 = 0x64, + MAX77686_REG_LDO6CTRL2 = 0x65, + MAX77686_REG_LDO7CTRL2 = 0x66, + MAX77686_REG_LDO8CTRL2 = 0x67, + MAX77686_REG_LDO9CTRL2 = 0x68, + MAX77686_REG_LDO10CTRL2 = 0x69, + MAX77686_REG_LDO11CTRL2 = 0x6A, + MAX77686_REG_LDO12CTRL2 = 0x6B, + MAX77686_REG_LDO13CTRL2 = 0x6C, + MAX77686_REG_LDO14CTRL2 = 0x6D, + MAX77686_REG_LDO15CTRL2 = 0x6E, + MAX77686_REG_LDO16CTRL2 = 0x6F, + MAX77686_REG_LDO17CTRL2 = 0x70, + MAX77686_REG_LDO18CTRL2 = 0x71, + MAX77686_REG_LDO19CTRL2 = 0x72, + MAX77686_REG_LDO20CTRL2 = 0x73, + MAX77686_REG_LDO21CTRL2 = 0x74, + MAX77686_REG_LDO22CTRL2 = 0x75, + MAX77686_REG_LDO23CTRL2 = 0x76, + MAX77686_REG_LDO24CTRL2 = 0x77, + MAX77686_REG_LDO25CTRL2 = 0x78, + MAX77686_REG_LDO26CTRL2 = 0x79, + /* Reserved: 0x7A-0x7D */ + + MAX77686_REG_BBAT_CHG = 0x7E, + MAX77686_REG_32KHZ = 0x7F, + + MAX77686_REG_PMIC_END = 0x80, +}; + +enum max77686_rtc_reg { + MAX77686_RTC_INT = 0x00, + MAX77686_RTC_INTM = 0x01, + MAX77686_RTC_CONTROLM = 0x02, + MAX77686_RTC_CONTROL = 0x03, + MAX77686_RTC_UPDATE0 = 0x04, + /* Reserved: 0x5 */ + MAX77686_WTSR_SMPL_CNTL = 0x06, + MAX77686_RTC_SEC = 0x07, + MAX77686_RTC_MIN = 0x08, + MAX77686_RTC_HOUR = 0x09, + MAX77686_RTC_WEEKDAY = 0x0A, + MAX77686_RTC_MONTH = 0x0B, + MAX77686_RTC_YEAR = 0x0C, + MAX77686_RTC_DATE = 0x0D, + MAX77686_ALARM1_SEC = 0x0E, + MAX77686_ALARM1_MIN = 0x0F, + MAX77686_ALARM1_HOUR = 0x10, + MAX77686_ALARM1_WEEKDAY = 0x11, + MAX77686_ALARM1_MONTH = 0x12, + MAX77686_ALARM1_YEAR = 0x13, + MAX77686_ALARM1_DATE = 0x14, + MAX77686_ALARM2_SEC = 0x15, + MAX77686_ALARM2_MIN = 0x16, + MAX77686_ALARM2_HOUR = 0x17, + MAX77686_ALARM2_WEEKDAY = 0x18, + MAX77686_ALARM2_MONTH = 0x19, + MAX77686_ALARM2_YEAR = 0x1A, + MAX77686_ALARM2_DATE = 0x1B, +}; + +#define MAX77686_IRQSRC_PMIC (0) +#define MAX77686_IRQSRC_RTC (1 << 0) + +enum max77686_irq_source { + PMIC_INT1 = 0, + PMIC_INT2, + RTC_INT, + + MAX77686_IRQ_GROUP_NR, +}; + +enum max77686_irq { + MAX77686_PMICIRQ_PWRONF, + MAX77686_PMICIRQ_PWRONR, + MAX77686_PMICIRQ_JIGONBF, + MAX77686_PMICIRQ_JIGONBR, + MAX77686_PMICIRQ_ACOKBF, + MAX77686_PMICIRQ_ACOKBR, + MAX77686_PMICIRQ_ONKEY1S, + MAX77686_PMICIRQ_MRSTB, + + MAX77686_PMICIRQ_140C, + MAX77686_PMICIRQ_120C, + + MAX77686_RTCIRQ_RTC60S, + MAX77686_RTCIRQ_RTCA1, + MAX77686_RTCIRQ_RTCA2, + MAX77686_RTCIRQ_SMPL, + MAX77686_RTCIRQ_RTC1S, + MAX77686_RTCIRQ_WTSR, + + MAX77686_IRQ_NR, +}; + +struct max77686_dev { + struct device *dev; + struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */ + struct i2c_client *rtc; /* slave addr 0x0c */ + + int type; + + struct regmap *regmap; /* regmap for mfd */ + struct regmap *rtc_regmap; /* regmap for rtc */ + + struct irq_domain *irq_domain; + + int irq; + int irq_gpio; + bool wakeup; + struct mutex irqlock; + int irq_masks_cur[MAX77686_IRQ_GROUP_NR]; + int irq_masks_cache[MAX77686_IRQ_GROUP_NR]; +}; + +enum max77686_types { + TYPE_MAX77686, +}; + +extern int max77686_irq_init(struct max77686_dev *max77686); +extern void max77686_irq_exit(struct max77686_dev *max77686); +extern int max77686_irq_resume(struct max77686_dev *max77686); + +#endif /* __LINUX_MFD_MAX77686_PRIV_H */ diff --git a/include/linux/mfd/max77686.h b/include/linux/mfd/max77686.h new file mode 100644 index 00000000000..3d7ae4d7fd3 --- /dev/null +++ b/include/linux/mfd/max77686.h @@ -0,0 +1,114 @@ +/* + * max77686.h - Driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electrnoics + * Chiwoong Byun <woong.byun@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + * + * This driver is based on max8997.h + * + * MAX77686 has PMIC, RTC devices. + * The devices share the same I2C bus and included in + * this mfd driver. + */ + +#ifndef __LINUX_MFD_MAX77686_H +#define __LINUX_MFD_MAX77686_H + +#include <linux/regulator/consumer.h> + +/* MAX77686 regulator IDs */ +enum max77686_regulators { + MAX77686_LDO1 = 0, + MAX77686_LDO2, + MAX77686_LDO3, + MAX77686_LDO4, + MAX77686_LDO5, + MAX77686_LDO6, + MAX77686_LDO7, + MAX77686_LDO8, + MAX77686_LDO9, + MAX77686_LDO10, + MAX77686_LDO11, + MAX77686_LDO12, + MAX77686_LDO13, + MAX77686_LDO14, + MAX77686_LDO15, + MAX77686_LDO16, + MAX77686_LDO17, + MAX77686_LDO18, + MAX77686_LDO19, + MAX77686_LDO20, + MAX77686_LDO21, + MAX77686_LDO22, + MAX77686_LDO23, + MAX77686_LDO24, + MAX77686_LDO25, + MAX77686_LDO26, + MAX77686_BUCK1, + MAX77686_BUCK2, + MAX77686_BUCK3, + MAX77686_BUCK4, + MAX77686_BUCK5, + MAX77686_BUCK6, + MAX77686_BUCK7, + MAX77686_BUCK8, + MAX77686_BUCK9, + + MAX77686_REG_MAX, +}; + +struct max77686_regulator_data { + int id; + struct regulator_init_data *initdata; +}; + +enum max77686_opmode { + MAX77686_OPMODE_NORMAL, + MAX77686_OPMODE_LP, + MAX77686_OPMODE_STANDBY, +}; + +struct max77686_opmode_data { + int id; + int mode; +}; + +struct max77686_platform_data { + /* IRQ */ + int irq_gpio; + int ono; + int wakeup; + + /* ---- PMIC ---- */ + struct max77686_regulator_data *regulators; + int num_regulators; + + struct max77686_opmode_data *opmode_data; + + /* + * GPIO-DVS feature is not enabled with the current version of + * MAX77686 driver. Buck2/3/4_voltages[0] is used as the default + * voltage at probe. DVS/SELB gpios are set as OUTPUT-LOW. + */ + int buck234_gpio_dvs[3]; /* GPIO of [0]DVS1, [1]DVS2, [2]DVS3 */ + int buck234_gpio_selb[3]; /* [0]SELB2, [1]SELB3, [2]SELB4 */ + unsigned int buck2_voltage[8]; /* buckx_voltage in uV */ + unsigned int buck3_voltage[8]; + unsigned int buck4_voltage[8]; +}; + +#endif /* __LINUX_MFD_MAX77686_H */ diff --git a/include/linux/mfd/max77693-private.h b/include/linux/mfd/max77693-private.h index 68263c5fa53..1eeae5c0791 100644 --- a/include/linux/mfd/max77693-private.h +++ b/include/linux/mfd/max77693-private.h @@ -190,7 +190,6 @@ struct max77693_dev { struct i2c_client *i2c; /* 0xCC , PMIC, Charger, Flash LED */ struct i2c_client *muic; /* 0x4A , MUIC */ struct i2c_client *haptic; /* 0x90 , Haptic */ - struct mutex iolock; int type; diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h index 3f4deb62d6b..830152cfae3 100644 --- a/include/linux/mfd/max8997-private.h +++ b/include/linux/mfd/max8997-private.h @@ -23,6 +23,8 @@ #define __LINUX_MFD_MAX8997_PRIV_H #include <linux/i2c.h> +#include <linux/export.h> +#include <linux/irqdomain.h> #define MAX8997_REG_INVALID (0xff) @@ -325,7 +327,7 @@ struct max8997_dev { int irq; int ono; - int irq_base; + struct irq_domain *irq_domain; struct mutex irqlock; int irq_masks_cur[MAX8997_IRQ_GROUP_NR]; int irq_masks_cache[MAX8997_IRQ_GROUP_NR]; diff --git a/include/linux/mfd/max8997.h b/include/linux/mfd/max8997.h index b40c08cd30b..328d8e24b53 100644 --- a/include/linux/mfd/max8997.h +++ b/include/linux/mfd/max8997.h @@ -181,7 +181,6 @@ struct max8997_led_platform_data { struct max8997_platform_data { /* IRQ */ - int irq_base; int ono; int wakeup; diff --git a/include/linux/mfd/s5m87xx/s5m-core.h b/include/linux/mfd/s5m87xx/s5m-core.h deleted file mode 100644 index 0b2e0ed309f..00000000000 --- a/include/linux/mfd/s5m87xx/s5m-core.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - * s5m-core.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef __LINUX_MFD_S5M_CORE_H -#define __LINUX_MFD_S5M_CORE_H - -#define NUM_IRQ_REGS 4 - -enum s5m_device_type { - S5M8751X, - S5M8763X, - S5M8767X, -}; - -/* S5M8767 registers */ -enum s5m8767_reg { - S5M8767_REG_ID, - S5M8767_REG_INT1, - S5M8767_REG_INT2, - S5M8767_REG_INT3, - S5M8767_REG_INT1M, - S5M8767_REG_INT2M, - S5M8767_REG_INT3M, - S5M8767_REG_STATUS1, - S5M8767_REG_STATUS2, - S5M8767_REG_STATUS3, - S5M8767_REG_CTRL1, - S5M8767_REG_CTRL2, - S5M8767_REG_LOWBAT1, - S5M8767_REG_LOWBAT2, - S5M8767_REG_BUCHG, - S5M8767_REG_DVSRAMP, - S5M8767_REG_DVSTIMER2 = 0x10, - S5M8767_REG_DVSTIMER3, - S5M8767_REG_DVSTIMER4, - S5M8767_REG_LDO1, - S5M8767_REG_LDO2, - S5M8767_REG_LDO3, - S5M8767_REG_LDO4, - S5M8767_REG_LDO5, - S5M8767_REG_LDO6, - S5M8767_REG_LDO7, - S5M8767_REG_LDO8, - S5M8767_REG_LDO9, - S5M8767_REG_LDO10, - S5M8767_REG_LDO11, - S5M8767_REG_LDO12, - S5M8767_REG_LDO13, - S5M8767_REG_LDO14 = 0x20, - S5M8767_REG_LDO15, - S5M8767_REG_LDO16, - S5M8767_REG_LDO17, - S5M8767_REG_LDO18, - S5M8767_REG_LDO19, - S5M8767_REG_LDO20, - S5M8767_REG_LDO21, - S5M8767_REG_LDO22, - S5M8767_REG_LDO23, - S5M8767_REG_LDO24, - S5M8767_REG_LDO25, - S5M8767_REG_LDO26, - S5M8767_REG_LDO27, - S5M8767_REG_LDO28, - S5M8767_REG_UVLO = 0x31, - S5M8767_REG_BUCK1CTRL1, - S5M8767_REG_BUCK1CTRL2, - S5M8767_REG_BUCK2CTRL, - S5M8767_REG_BUCK2DVS1, - S5M8767_REG_BUCK2DVS2, - S5M8767_REG_BUCK2DVS3, - S5M8767_REG_BUCK2DVS4, - S5M8767_REG_BUCK2DVS5, - S5M8767_REG_BUCK2DVS6, - S5M8767_REG_BUCK2DVS7, - S5M8767_REG_BUCK2DVS8, - S5M8767_REG_BUCK3CTRL, - S5M8767_REG_BUCK3DVS1, - S5M8767_REG_BUCK3DVS2, - S5M8767_REG_BUCK3DVS3, - S5M8767_REG_BUCK3DVS4, - S5M8767_REG_BUCK3DVS5, - S5M8767_REG_BUCK3DVS6, - S5M8767_REG_BUCK3DVS7, - S5M8767_REG_BUCK3DVS8, - S5M8767_REG_BUCK4CTRL, - S5M8767_REG_BUCK4DVS1, - S5M8767_REG_BUCK4DVS2, - S5M8767_REG_BUCK4DVS3, - S5M8767_REG_BUCK4DVS4, - S5M8767_REG_BUCK4DVS5, - S5M8767_REG_BUCK4DVS6, - S5M8767_REG_BUCK4DVS7, - S5M8767_REG_BUCK4DVS8, - S5M8767_REG_BUCK5CTRL1, - S5M8767_REG_BUCK5CTRL2, - S5M8767_REG_BUCK5CTRL3, - S5M8767_REG_BUCK5CTRL4, - S5M8767_REG_BUCK5CTRL5, - S5M8767_REG_BUCK6CTRL1, - S5M8767_REG_BUCK6CTRL2, - S5M8767_REG_BUCK7CTRL1, - S5M8767_REG_BUCK7CTRL2, - S5M8767_REG_BUCK8CTRL1, - S5M8767_REG_BUCK8CTRL2, - S5M8767_REG_BUCK9CTRL1, - S5M8767_REG_BUCK9CTRL2, - S5M8767_REG_LDO1CTRL, - S5M8767_REG_LDO2_1CTRL, - S5M8767_REG_LDO2_2CTRL, - S5M8767_REG_LDO2_3CTRL, - S5M8767_REG_LDO2_4CTRL, - S5M8767_REG_LDO3CTRL, - S5M8767_REG_LDO4CTRL, - S5M8767_REG_LDO5CTRL, - S5M8767_REG_LDO6CTRL, - S5M8767_REG_LDO7CTRL, - S5M8767_REG_LDO8CTRL, - S5M8767_REG_LDO9CTRL, - S5M8767_REG_LDO10CTRL, - S5M8767_REG_LDO11CTRL, - S5M8767_REG_LDO12CTRL, - S5M8767_REG_LDO13CTRL, - S5M8767_REG_LDO14CTRL, - S5M8767_REG_LDO15CTRL, - S5M8767_REG_LDO16CTRL, - S5M8767_REG_LDO17CTRL, - S5M8767_REG_LDO18CTRL, - S5M8767_REG_LDO19CTRL, - S5M8767_REG_LDO20CTRL, - S5M8767_REG_LDO21CTRL, - S5M8767_REG_LDO22CTRL, - S5M8767_REG_LDO23CTRL, - S5M8767_REG_LDO24CTRL, - S5M8767_REG_LDO25CTRL, - S5M8767_REG_LDO26CTRL, - S5M8767_REG_LDO27CTRL, - S5M8767_REG_LDO28CTRL, -}; - -/* S5M8763 registers */ -enum s5m8763_reg { - S5M8763_REG_IRQ1, - S5M8763_REG_IRQ2, - S5M8763_REG_IRQ3, - S5M8763_REG_IRQ4, - S5M8763_REG_IRQM1, - S5M8763_REG_IRQM2, - S5M8763_REG_IRQM3, - S5M8763_REG_IRQM4, - S5M8763_REG_STATUS1, - S5M8763_REG_STATUS2, - S5M8763_REG_STATUSM1, - S5M8763_REG_STATUSM2, - S5M8763_REG_CHGR1, - S5M8763_REG_CHGR2, - S5M8763_REG_LDO_ACTIVE_DISCHARGE1, - S5M8763_REG_LDO_ACTIVE_DISCHARGE2, - S5M8763_REG_BUCK_ACTIVE_DISCHARGE3, - S5M8763_REG_ONOFF1, - S5M8763_REG_ONOFF2, - S5M8763_REG_ONOFF3, - S5M8763_REG_ONOFF4, - S5M8763_REG_BUCK1_VOLTAGE1, - S5M8763_REG_BUCK1_VOLTAGE2, - S5M8763_REG_BUCK1_VOLTAGE3, - S5M8763_REG_BUCK1_VOLTAGE4, - S5M8763_REG_BUCK2_VOLTAGE1, - S5M8763_REG_BUCK2_VOLTAGE2, - S5M8763_REG_BUCK3, - S5M8763_REG_BUCK4, - S5M8763_REG_LDO1_LDO2, - S5M8763_REG_LDO3, - S5M8763_REG_LDO4, - S5M8763_REG_LDO5, - S5M8763_REG_LDO6, - S5M8763_REG_LDO7, - S5M8763_REG_LDO7_LDO8, - S5M8763_REG_LDO9_LDO10, - S5M8763_REG_LDO11, - S5M8763_REG_LDO12, - S5M8763_REG_LDO13, - S5M8763_REG_LDO14, - S5M8763_REG_LDO15, - S5M8763_REG_LDO16, - S5M8763_REG_BKCHR, - S5M8763_REG_LBCNFG1, - S5M8763_REG_LBCNFG2, -}; - -enum s5m8767_irq { - S5M8767_IRQ_PWRR, - S5M8767_IRQ_PWRF, - S5M8767_IRQ_PWR1S, - S5M8767_IRQ_JIGR, - S5M8767_IRQ_JIGF, - S5M8767_IRQ_LOWBAT2, - S5M8767_IRQ_LOWBAT1, - - S5M8767_IRQ_MRB, - S5M8767_IRQ_DVSOK2, - S5M8767_IRQ_DVSOK3, - S5M8767_IRQ_DVSOK4, - - S5M8767_IRQ_RTC60S, - S5M8767_IRQ_RTCA1, - S5M8767_IRQ_RTCA2, - S5M8767_IRQ_SMPL, - S5M8767_IRQ_RTC1S, - S5M8767_IRQ_WTSR, - - S5M8767_IRQ_NR, -}; - -#define S5M8767_IRQ_PWRR_MASK (1 << 0) -#define S5M8767_IRQ_PWRF_MASK (1 << 1) -#define S5M8767_IRQ_PWR1S_MASK (1 << 3) -#define S5M8767_IRQ_JIGR_MASK (1 << 4) -#define S5M8767_IRQ_JIGF_MASK (1 << 5) -#define S5M8767_IRQ_LOWBAT2_MASK (1 << 6) -#define S5M8767_IRQ_LOWBAT1_MASK (1 << 7) - -#define S5M8767_IRQ_MRB_MASK (1 << 2) -#define S5M8767_IRQ_DVSOK2_MASK (1 << 3) -#define S5M8767_IRQ_DVSOK3_MASK (1 << 4) -#define S5M8767_IRQ_DVSOK4_MASK (1 << 5) - -#define S5M8767_IRQ_RTC60S_MASK (1 << 0) -#define S5M8767_IRQ_RTCA1_MASK (1 << 1) -#define S5M8767_IRQ_RTCA2_MASK (1 << 2) -#define S5M8767_IRQ_SMPL_MASK (1 << 3) -#define S5M8767_IRQ_RTC1S_MASK (1 << 4) -#define S5M8767_IRQ_WTSR_MASK (1 << 5) - -enum s5m8763_irq { - S5M8763_IRQ_DCINF, - S5M8763_IRQ_DCINR, - S5M8763_IRQ_JIGF, - S5M8763_IRQ_JIGR, - S5M8763_IRQ_PWRONF, - S5M8763_IRQ_PWRONR, - - S5M8763_IRQ_WTSREVNT, - S5M8763_IRQ_SMPLEVNT, - S5M8763_IRQ_ALARM1, - S5M8763_IRQ_ALARM0, - - S5M8763_IRQ_ONKEY1S, - S5M8763_IRQ_TOPOFFR, - S5M8763_IRQ_DCINOVPR, - S5M8763_IRQ_CHGRSTF, - S5M8763_IRQ_DONER, - S5M8763_IRQ_CHGFAULT, - - S5M8763_IRQ_LOBAT1, - S5M8763_IRQ_LOBAT2, - - S5M8763_IRQ_NR, -}; - -#define S5M8763_IRQ_DCINF_MASK (1 << 2) -#define S5M8763_IRQ_DCINR_MASK (1 << 3) -#define S5M8763_IRQ_JIGF_MASK (1 << 4) -#define S5M8763_IRQ_JIGR_MASK (1 << 5) -#define S5M8763_IRQ_PWRONF_MASK (1 << 6) -#define S5M8763_IRQ_PWRONR_MASK (1 << 7) - -#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0) -#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1) -#define S5M8763_IRQ_ALARM1_MASK (1 << 2) -#define S5M8763_IRQ_ALARM0_MASK (1 << 3) - -#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0) -#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2) -#define S5M8763_IRQ_DCINOVPR_MASK (1 << 3) -#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4) -#define S5M8763_IRQ_DONER_MASK (1 << 5) -#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7) - -#define S5M8763_IRQ_LOBAT1_MASK (1 << 0) -#define S5M8763_IRQ_LOBAT2_MASK (1 << 1) - -#define S5M8763_ENRAMP (1 << 4) - -/** - * struct s5m87xx_dev - s5m87xx master device for sub-drivers - * @dev: master device of the chip (can be used to access platform data) - * @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 s5m87xx, 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 s5m87xx_dev { - struct device *dev; - struct regmap *regmap; - struct i2c_client *i2c; - struct i2c_client *rtc; - struct mutex iolock; - struct mutex irqlock; - - int device_type; - int irq_base; - int irq; - int ono; - u8 irq_masks_cur[NUM_IRQ_REGS]; - u8 irq_masks_cache[NUM_IRQ_REGS]; - int type; - bool wakeup; -}; - -int s5m_irq_init(struct s5m87xx_dev *s5m87xx); -void s5m_irq_exit(struct s5m87xx_dev *s5m87xx); -int s5m_irq_resume(struct s5m87xx_dev *s5m87xx); - -extern int s5m_reg_read(struct s5m87xx_dev *s5m87xx, u8 reg, void *dest); -extern int s5m_bulk_read(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf); -extern int s5m_reg_write(struct s5m87xx_dev *s5m87xx, u8 reg, u8 value); -extern int s5m_bulk_write(struct s5m87xx_dev *s5m87xx, u8 reg, int count, u8 *buf); -extern int s5m_reg_update(struct s5m87xx_dev *s5m87xx, u8 reg, u8 val, u8 mask); - -struct s5m_platform_data { - struct s5m_regulator_data *regulators; - struct s5m_opmode_data *opmode; - int device_type; - int num_regulators; - - int irq_base; - int (*cfg_pmic_irq)(void); - - int ono; - bool wakeup; - bool buck_voltage_lock; - - int buck_gpios[3]; - int buck_ds[3]; - int buck2_voltage[8]; - bool buck2_gpiodvs; - int buck3_voltage[8]; - bool buck3_gpiodvs; - int buck4_voltage[8]; - bool buck4_gpiodvs; - - int buck_set1; - int buck_set2; - int buck_set3; - int buck2_enable; - int buck3_enable; - int buck4_enable; - int buck_default_idx; - int buck2_default_idx; - int buck3_default_idx; - int buck4_default_idx; - - int buck_ramp_delay; - bool buck2_ramp_enable; - bool buck3_ramp_enable; - bool buck4_ramp_enable; - - int buck2_init; - int buck3_init; - int buck4_init; -}; - -#endif /* __LINUX_MFD_S5M_CORE_H */ diff --git a/include/linux/mfd/s5m87xx/s5m-pmic.h b/include/linux/mfd/s5m87xx/s5m-pmic.h deleted file mode 100644 index 7c719f20f58..00000000000 --- a/include/linux/mfd/s5m87xx/s5m-pmic.h +++ /dev/null @@ -1,129 +0,0 @@ -/* s5m87xx.h - * - * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __LINUX_MFD_S5M_PMIC_H -#define __LINUX_MFD_S5M_PMIC_H - -#include <linux/regulator/machine.h> - -/* S5M8767 regulator ids */ -enum s5m8767_regulators { - S5M8767_LDO1, - S5M8767_LDO2, - S5M8767_LDO3, - S5M8767_LDO4, - S5M8767_LDO5, - S5M8767_LDO6, - S5M8767_LDO7, - S5M8767_LDO8, - S5M8767_LDO9, - S5M8767_LDO10, - S5M8767_LDO11, - S5M8767_LDO12, - S5M8767_LDO13, - S5M8767_LDO14, - S5M8767_LDO15, - S5M8767_LDO16, - S5M8767_LDO17, - S5M8767_LDO18, - S5M8767_LDO19, - S5M8767_LDO20, - S5M8767_LDO21, - S5M8767_LDO22, - S5M8767_LDO23, - S5M8767_LDO24, - S5M8767_LDO25, - S5M8767_LDO26, - S5M8767_LDO27, - S5M8767_LDO28, - S5M8767_BUCK1, - S5M8767_BUCK2, - S5M8767_BUCK3, - S5M8767_BUCK4, - S5M8767_BUCK5, - S5M8767_BUCK6, - S5M8767_BUCK7, - S5M8767_BUCK8, - S5M8767_BUCK9, - S5M8767_AP_EN32KHZ, - S5M8767_CP_EN32KHZ, - - S5M8767_REG_MAX, -}; - -#define S5M8767_ENCTRL_SHIFT 6 - -/* S5M8763 regulator ids */ -enum s5m8763_regulators { - S5M8763_LDO1, - S5M8763_LDO2, - S5M8763_LDO3, - S5M8763_LDO4, - S5M8763_LDO5, - S5M8763_LDO6, - S5M8763_LDO7, - S5M8763_LDO8, - S5M8763_LDO9, - S5M8763_LDO10, - S5M8763_LDO11, - S5M8763_LDO12, - S5M8763_LDO13, - S5M8763_LDO14, - S5M8763_LDO15, - S5M8763_LDO16, - S5M8763_BUCK1, - S5M8763_BUCK2, - S5M8763_BUCK3, - S5M8763_BUCK4, - S5M8763_AP_EN32KHZ, - S5M8763_CP_EN32KHZ, - S5M8763_ENCHGVI, - S5M8763_ESAFEUSB1, - S5M8763_ESAFEUSB2, -}; - -/** - * s5m87xx_regulator_data - regulator data - * @id: regulator id - * @initdata: regulator init data (contraints, supplies, ...) - */ -struct s5m_regulator_data { - int id; - struct regulator_init_data *initdata; -}; - -/* - * s5m_opmode_data - regulator operation mode data - * @id: regulator id - * @mode: regulator operation mode - */ -struct s5m_opmode_data { - int id; - int mode; -}; - -/* - * s5m regulator operation mode - * S5M_OPMODE_OFF Regulator always OFF - * S5M_OPMODE_ON Regulator always ON - * S5M_OPMODE_LOWPOWER Regulator is on in low-power mode - * S5M_OPMODE_SUSPEND Regulator is changed by PWREN pin - * If PWREN is high, regulator is on - * If PWREN is low, regulator is off - */ - -enum s5m_opmode { - S5M_OPMODE_OFF, - S5M_OPMODE_ON, - S5M_OPMODE_LOWPOWER, - S5M_OPMODE_SUSPEND, -}; - -#endif /* __LINUX_MFD_S5M_PMIC_H */ diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h new file mode 100644 index 00000000000..b50c38f8bc4 --- /dev/null +++ b/include/linux/mfd/samsung/core.h @@ -0,0 +1,159 @@ +/* + * core.h + * + * copyright (c) 2011 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_SEC_CORE_H +#define __LINUX_MFD_SEC_CORE_H + +#define NUM_IRQ_REGS 4 + +enum sec_device_type { + S5M8751X, + S5M8763X, + S5M8767X, + S2MPS11X, +}; + +/** + * struct sec_pmic_dev - s5m87xx master device for sub-drivers + * @dev: master device of the chip (can be used to access platform data) + * @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 { + struct device *dev; + struct regmap *regmap; + struct i2c_client *i2c; + struct i2c_client *rtc; + struct mutex iolock; + struct mutex irqlock; + + int device_type; + int irq_base; + int irq; + struct regmap_irq_chip_data *irq_data; + + int ono; + u8 irq_masks_cur[NUM_IRQ_REGS]; + u8 irq_masks_cache[NUM_IRQ_REGS]; + int type; + bool wakeup; +}; + +int sec_irq_init(struct sec_pmic_dev *sec_pmic); +void sec_irq_exit(struct sec_pmic_dev *sec_pmic); +int sec_irq_resume(struct sec_pmic_dev *sec_pmic); + +extern int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest); +extern int sec_bulk_read(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf); +extern int sec_reg_write(struct sec_pmic_dev *sec_pmic, u8 reg, u8 value); +extern int sec_bulk_write(struct sec_pmic_dev *sec_pmic, u8 reg, int count, u8 *buf); +extern int sec_reg_update(struct sec_pmic_dev *sec_pmic, u8 reg, u8 val, u8 mask); + +struct sec_platform_data { + struct sec_regulator_data *regulators; + struct sec_opmode_data *opmode; + int device_type; + int num_regulators; + + int irq_base; + int (*cfg_pmic_irq)(void); + + int ono; + bool wakeup; + bool buck_voltage_lock; + + int buck_gpios[3]; + int buck_ds[3]; + int buck2_voltage[8]; + bool buck2_gpiodvs; + int buck3_voltage[8]; + bool buck3_gpiodvs; + int buck4_voltage[8]; + bool buck4_gpiodvs; + + int buck_set1; + int buck_set2; + int buck_set3; + int buck2_enable; + int buck3_enable; + int buck4_enable; + int buck_default_idx; + int buck2_default_idx; + int buck3_default_idx; + int buck4_default_idx; + + int buck_ramp_delay; + + int buck2_ramp_delay; + int buck34_ramp_delay; + int buck5_ramp_delay; + int buck16_ramp_delay; + int buck7810_ramp_delay; + int buck9_ramp_delay; + + bool buck2_ramp_enable; + bool buck3_ramp_enable; + bool buck4_ramp_enable; + bool buck6_ramp_enable; + + int buck2_init; + int buck3_init; + int buck4_init; +}; + +/** + * sec_regulator_data - regulator data + * @id: regulator id + * @initdata: regulator init data (contraints, supplies, ...) + */ +struct sec_regulator_data { + int id; + struct regulator_init_data *initdata; +}; + +/* + * sec_opmode_data - regulator operation mode data + * @id: regulator id + * @mode: regulator operation mode + */ +struct sec_opmode_data { + int id; + int mode; +}; + +/* + * samsung regulator operation mode + * SEC_OPMODE_OFF Regulator always OFF + * SEC_OPMODE_ON Regulator always ON + * SEC_OPMODE_LOWPOWER Regulator is on in low-power mode + * SEC_OPMODE_SUSPEND Regulator is changed by PWREN pin + * If PWREN is high, regulator is on + * If PWREN is low, regulator is off + */ + +enum sec_opmode { + SEC_OPMODE_OFF, + SEC_OPMODE_ON, + SEC_OPMODE_LOWPOWER, + SEC_OPMODE_SUSPEND, +}; + +#endif /* __LINUX_MFD_SEC_CORE_H */ diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h new file mode 100644 index 00000000000..d43b4f9e7fb --- /dev/null +++ b/include/linux/mfd/samsung/irq.h @@ -0,0 +1,152 @@ +/* irq.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_SEC_IRQ_H +#define __LINUX_MFD_SEC_IRQ_H + +enum s2mps11_irq { + S2MPS11_IRQ_PWRONF, + S2MPS11_IRQ_PWRONR, + S2MPS11_IRQ_JIGONBF, + S2MPS11_IRQ_JIGONBR, + S2MPS11_IRQ_ACOKBF, + S2MPS11_IRQ_ACOKBR, + S2MPS11_IRQ_PWRON1S, + S2MPS11_IRQ_MRB, + + S2MPS11_IRQ_RTC60S, + S2MPS11_IRQ_RTCA1, + S2MPS11_IRQ_RTCA2, + S2MPS11_IRQ_SMPL, + S2MPS11_IRQ_RTC1S, + S2MPS11_IRQ_WTSR, + + S2MPS11_IRQ_INT120C, + S2MPS11_IRQ_INT140C, + + S2MPS11_IRQ_NR, +}; + +#define S2MPS11_IRQ_PWRONF_MASK (1 << 0) +#define S2MPS11_IRQ_PWRONR_MASK (1 << 1) +#define S2MPS11_IRQ_JIGONBF_MASK (1 << 2) +#define S2MPS11_IRQ_JIGONBR_MASK (1 << 3) +#define S2MPS11_IRQ_ACOKBF_MASK (1 << 4) +#define S2MPS11_IRQ_ACOKBR_MASK (1 << 5) +#define S2MPS11_IRQ_PWRON1S_MASK (1 << 6) +#define S2MPS11_IRQ_MRB_MASK (1 << 7) + +#define S2MPS11_IRQ_RTC60S_MASK (1 << 0) +#define S2MPS11_IRQ_RTCA1_MASK (1 << 1) +#define S2MPS11_IRQ_RTCA2_MASK (1 << 2) +#define S2MPS11_IRQ_SMPL_MASK (1 << 3) +#define S2MPS11_IRQ_RTC1S_MASK (1 << 4) +#define S2MPS11_IRQ_WTSR_MASK (1 << 5) + +#define S2MPS11_IRQ_INT120C_MASK (1 << 0) +#define S2MPS11_IRQ_INT140C_MASK (1 << 1) + +enum s5m8767_irq { + S5M8767_IRQ_PWRR, + S5M8767_IRQ_PWRF, + S5M8767_IRQ_PWR1S, + S5M8767_IRQ_JIGR, + S5M8767_IRQ_JIGF, + S5M8767_IRQ_LOWBAT2, + S5M8767_IRQ_LOWBAT1, + + S5M8767_IRQ_MRB, + S5M8767_IRQ_DVSOK2, + S5M8767_IRQ_DVSOK3, + S5M8767_IRQ_DVSOK4, + + S5M8767_IRQ_RTC60S, + S5M8767_IRQ_RTCA1, + S5M8767_IRQ_RTCA2, + S5M8767_IRQ_SMPL, + S5M8767_IRQ_RTC1S, + S5M8767_IRQ_WTSR, + + S5M8767_IRQ_NR, +}; + +#define S5M8767_IRQ_PWRR_MASK (1 << 0) +#define S5M8767_IRQ_PWRF_MASK (1 << 1) +#define S5M8767_IRQ_PWR1S_MASK (1 << 3) +#define S5M8767_IRQ_JIGR_MASK (1 << 4) +#define S5M8767_IRQ_JIGF_MASK (1 << 5) +#define S5M8767_IRQ_LOWBAT2_MASK (1 << 6) +#define S5M8767_IRQ_LOWBAT1_MASK (1 << 7) + +#define S5M8767_IRQ_MRB_MASK (1 << 2) +#define S5M8767_IRQ_DVSOK2_MASK (1 << 3) +#define S5M8767_IRQ_DVSOK3_MASK (1 << 4) +#define S5M8767_IRQ_DVSOK4_MASK (1 << 5) + +#define S5M8767_IRQ_RTC60S_MASK (1 << 0) +#define S5M8767_IRQ_RTCA1_MASK (1 << 1) +#define S5M8767_IRQ_RTCA2_MASK (1 << 2) +#define S5M8767_IRQ_SMPL_MASK (1 << 3) +#define S5M8767_IRQ_RTC1S_MASK (1 << 4) +#define S5M8767_IRQ_WTSR_MASK (1 << 5) + +enum s5m8763_irq { + S5M8763_IRQ_DCINF, + S5M8763_IRQ_DCINR, + S5M8763_IRQ_JIGF, + S5M8763_IRQ_JIGR, + S5M8763_IRQ_PWRONF, + S5M8763_IRQ_PWRONR, + + S5M8763_IRQ_WTSREVNT, + S5M8763_IRQ_SMPLEVNT, + S5M8763_IRQ_ALARM1, + S5M8763_IRQ_ALARM0, + + S5M8763_IRQ_ONKEY1S, + S5M8763_IRQ_TOPOFFR, + S5M8763_IRQ_DCINOVPR, + S5M8763_IRQ_CHGRSTF, + S5M8763_IRQ_DONER, + S5M8763_IRQ_CHGFAULT, + + S5M8763_IRQ_LOBAT1, + S5M8763_IRQ_LOBAT2, + + S5M8763_IRQ_NR, +}; + +#define S5M8763_IRQ_DCINF_MASK (1 << 2) +#define S5M8763_IRQ_DCINR_MASK (1 << 3) +#define S5M8763_IRQ_JIGF_MASK (1 << 4) +#define S5M8763_IRQ_JIGR_MASK (1 << 5) +#define S5M8763_IRQ_PWRONF_MASK (1 << 6) +#define S5M8763_IRQ_PWRONR_MASK (1 << 7) + +#define S5M8763_IRQ_WTSREVNT_MASK (1 << 0) +#define S5M8763_IRQ_SMPLEVNT_MASK (1 << 1) +#define S5M8763_IRQ_ALARM1_MASK (1 << 2) +#define S5M8763_IRQ_ALARM0_MASK (1 << 3) + +#define S5M8763_IRQ_ONKEY1S_MASK (1 << 0) +#define S5M8763_IRQ_TOPOFFR_MASK (1 << 2) +#define S5M8763_IRQ_DCINOVPR_MASK (1 << 3) +#define S5M8763_IRQ_CHGRSTF_MASK (1 << 4) +#define S5M8763_IRQ_DONER_MASK (1 << 5) +#define S5M8763_IRQ_CHGFAULT_MASK (1 << 7) + +#define S5M8763_IRQ_LOBAT1_MASK (1 << 0) +#define S5M8763_IRQ_LOBAT2_MASK (1 << 1) + +#define S5M8763_ENRAMP (1 << 4) + +#endif /* __LINUX_MFD_SEC_IRQ_H */ diff --git a/include/linux/mfd/s5m87xx/s5m-rtc.h b/include/linux/mfd/samsung/rtc.h index 6ce8da264ce..71597e20cdd 100644 --- a/include/linux/mfd/s5m87xx/s5m-rtc.h +++ b/include/linux/mfd/samsung/rtc.h @@ -1,5 +1,4 @@ -/* - * s5m-rtc.h +/* rtc.h * * Copyright (c) 2011 Samsung Electronics Co., Ltd * http://www.samsung.com @@ -11,39 +10,39 @@ * */ -#ifndef __LINUX_MFD_S5M_RTC_H -#define __LINUX_MFD_S5M_RTC_H +#ifndef __LINUX_MFD_SEC_RTC_H +#define __LINUX_MFD_SEC_RTC_H -enum s5m87xx_rtc_reg { - S5M87XX_RTC_SEC, - S5M87XX_RTC_MIN, - S5M87XX_RTC_HOUR, - S5M87XX_RTC_WEEKDAY, - S5M87XX_RTC_DATE, - S5M87XX_RTC_MONTH, - S5M87XX_RTC_YEAR1, - S5M87XX_RTC_YEAR2, - S5M87XX_ALARM0_SEC, - S5M87XX_ALARM0_MIN, - S5M87XX_ALARM0_HOUR, - S5M87XX_ALARM0_WEEKDAY, - S5M87XX_ALARM0_DATE, - S5M87XX_ALARM0_MONTH, - S5M87XX_ALARM0_YEAR1, - S5M87XX_ALARM0_YEAR2, - S5M87XX_ALARM1_SEC, - S5M87XX_ALARM1_MIN, - S5M87XX_ALARM1_HOUR, - S5M87XX_ALARM1_WEEKDAY, - S5M87XX_ALARM1_DATE, - S5M87XX_ALARM1_MONTH, - S5M87XX_ALARM1_YEAR1, - S5M87XX_ALARM1_YEAR2, - S5M87XX_ALARM0_CONF, - S5M87XX_ALARM1_CONF, - S5M87XX_RTC_STATUS, - S5M87XX_WTSR_SMPL_CNTL, - S5M87XX_RTC_UDR_CON, +enum sec_rtc_reg { + SEC_RTC_SEC, + SEC_RTC_MIN, + SEC_RTC_HOUR, + SEC_RTC_WEEKDAY, + SEC_RTC_DATE, + SEC_RTC_MONTH, + SEC_RTC_YEAR1, + SEC_RTC_YEAR2, + SEC_ALARM0_SEC, + SEC_ALARM0_MIN, + SEC_ALARM0_HOUR, + SEC_ALARM0_WEEKDAY, + SEC_ALARM0_DATE, + SEC_ALARM0_MONTH, + SEC_ALARM0_YEAR1, + SEC_ALARM0_YEAR2, + SEC_ALARM1_SEC, + SEC_ALARM1_MIN, + SEC_ALARM1_HOUR, + SEC_ALARM1_WEEKDAY, + SEC_ALARM1_DATE, + SEC_ALARM1_MONTH, + SEC_ALARM1_YEAR1, + SEC_ALARM1_YEAR2, + SEC_ALARM0_CONF, + SEC_ALARM1_CONF, + SEC_RTC_STATUS, + SEC_WTSR_SMPL_CNTL, + SEC_RTC_UDR_CON, }; #define RTC_I2C_ADDR (0x0C >> 1) @@ -81,4 +80,4 @@ enum { RTC_YEAR2, }; -#endif /* __LINUX_MFD_S5M_RTC_H */ +#endif /* __LINUX_MFD_SEC_RTC_H */ diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h new file mode 100644 index 00000000000..ad2252f239d --- /dev/null +++ b/include/linux/mfd/samsung/s2mps11.h @@ -0,0 +1,196 @@ +/* + * s2mps11.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_S2MPS11_H +#define __LINUX_MFD_S2MPS11_H + +/* S2MPS11 registers */ +enum s2mps11_reg { + S2MPS11_REG_ID, + S2MPS11_REG_INT1, + S2MPS11_REG_INT2, + S2MPS11_REG_INT3, + S2MPS11_REG_INT1M, + S2MPS11_REG_INT2M, + S2MPS11_REG_INT3M, + S2MPS11_REG_ST1, + S2MPS11_REG_ST2, + S2MPS11_REG_OFFSRC, + S2MPS11_REG_PWRONSRC, + S2MPS11_REG_RTC_CTRL, + S2MPS11_REG_CTRL1, + S2MPS11_REG_ETC_TEST, + S2MPS11_REG_RSVD3, + S2MPS11_REG_BU_CHG, + S2MPS11_REG_RAMP, + S2MPS11_REG_RAMP_BUCK, + S2MPS11_REG_LDO1_8, + S2MPS11_REG_LDO9_16, + S2MPS11_REG_LDO17_24, + S2MPS11_REG_LDO25_32, + S2MPS11_REG_LDO33_38, + S2MPS11_REG_LDO1_8_1, + S2MPS11_REG_LDO9_16_1, + S2MPS11_REG_LDO17_24_1, + S2MPS11_REG_LDO25_32_1, + S2MPS11_REG_LDO33_38_1, + S2MPS11_REG_OTP_ADRL, + S2MPS11_REG_OTP_ADRH, + S2MPS11_REG_OTP_DATA, + S2MPS11_REG_MON1SEL, + S2MPS11_REG_MON2SEL, + S2MPS11_REG_LEE, + S2MPS11_REG_RSVD_NO, + S2MPS11_REG_UVLO, + S2MPS11_REG_LEE_NO, + S2MPS11_REG_B1CTRL1, + S2MPS11_REG_B1CTRL2, + S2MPS11_REG_B2CTRL1, + S2MPS11_REG_B2CTRL2, + S2MPS11_REG_B3CTRL1, + S2MPS11_REG_B3CTRL2, + S2MPS11_REG_B4CTRL1, + S2MPS11_REG_B4CTRL2, + S2MPS11_REG_B5CTRL1, + S2MPS11_REG_BUCK5_SW, + S2MPS11_REG_B5CTRL2, + S2MPS11_REG_B5CTRL3, + S2MPS11_REG_B5CTRL4, + S2MPS11_REG_B5CTRL5, + S2MPS11_REG_B6CTRL1, + S2MPS11_REG_B6CTRL2, + S2MPS11_REG_B7CTRL1, + S2MPS11_REG_B7CTRL2, + S2MPS11_REG_B8CTRL1, + S2MPS11_REG_B8CTRL2, + S2MPS11_REG_B9CTRL1, + S2MPS11_REG_B9CTRL2, + S2MPS11_REG_B10CTRL1, + S2MPS11_REG_B10CTRL2, + S2MPS11_REG_L1CTRL, + S2MPS11_REG_L2CTRL, + S2MPS11_REG_L3CTRL, + S2MPS11_REG_L4CTRL, + S2MPS11_REG_L5CTRL, + S2MPS11_REG_L6CTRL, + S2MPS11_REG_L7CTRL, + S2MPS11_REG_L8CTRL, + S2MPS11_REG_L9CTRL, + S2MPS11_REG_L10CTRL, + S2MPS11_REG_L11CTRL, + S2MPS11_REG_L12CTRL, + S2MPS11_REG_L13CTRL, + S2MPS11_REG_L14CTRL, + S2MPS11_REG_L15CTRL, + S2MPS11_REG_L16CTRL, + S2MPS11_REG_L17CTRL, + S2MPS11_REG_L18CTRL, + S2MPS11_REG_L19CTRL, + S2MPS11_REG_L20CTRL, + S2MPS11_REG_L21CTRL, + S2MPS11_REG_L22CTRL, + S2MPS11_REG_L23CTRL, + S2MPS11_REG_L24CTRL, + S2MPS11_REG_L25CTRL, + S2MPS11_REG_L26CTRL, + S2MPS11_REG_L27CTRL, + S2MPS11_REG_L28CTRL, + S2MPS11_REG_L29CTRL, + S2MPS11_REG_L30CTRL, + S2MPS11_REG_L31CTRL, + S2MPS11_REG_L32CTRL, + S2MPS11_REG_L33CTRL, + S2MPS11_REG_L34CTRL, + S2MPS11_REG_L35CTRL, + S2MPS11_REG_L36CTRL, + S2MPS11_REG_L37CTRL, + S2MPS11_REG_L38CTRL, +}; + +/* S2MPS11 regulator ids */ +enum s2mps11_regulators { + S2MPS11_LDO1, + S2MPS11_LDO2, + S2MPS11_LDO3, + S2MPS11_LDO4, + S2MPS11_LDO5, + S2MPS11_LDO6, + S2MPS11_LDO7, + S2MPS11_LDO8, + S2MPS11_LDO9, + S2MPS11_LDO10, + S2MPS11_LDO11, + S2MPS11_LDO12, + S2MPS11_LDO13, + S2MPS11_LDO14, + S2MPS11_LDO15, + S2MPS11_LDO16, + S2MPS11_LDO17, + S2MPS11_LDO18, + S2MPS11_LDO19, + S2MPS11_LDO20, + S2MPS11_LDO21, + S2MPS11_LDO22, + S2MPS11_LDO23, + S2MPS11_LDO24, + S2MPS11_LDO25, + S2MPS11_LDO26, + S2MPS11_LDO27, + S2MPS11_LDO28, + S2MPS11_LDO29, + S2MPS11_LDO30, + S2MPS11_LDO31, + S2MPS11_LDO32, + S2MPS11_LDO33, + S2MPS11_LDO34, + S2MPS11_LDO35, + S2MPS11_LDO36, + S2MPS11_LDO37, + S2MPS11_LDO38, + S2MPS11_BUCK1, + S2MPS11_BUCK2, + S2MPS11_BUCK3, + S2MPS11_BUCK4, + S2MPS11_BUCK5, + S2MPS11_BUCK6, + S2MPS11_BUCK7, + S2MPS11_BUCK8, + S2MPS11_BUCK9, + S2MPS11_BUCK10, + S2MPS11_AP_EN32KHZ, + S2MPS11_CP_EN32KHZ, + S2MPS11_BT_EN32KHZ, + + S2MPS11_REG_MAX, +}; + +#define S2MPS11_BUCK_MIN1 600000 +#define S2MPS11_BUCK_MIN2 750000 +#define S2MPS11_BUCK_MIN3 3000000 +#define S2MPS11_LDO_MIN 800000 +#define S2MPS11_BUCK_STEP1 6250 +#define S2MPS11_BUCK_STEP2 12500 +#define S2MPS11_BUCK_STEP3 25000 +#define S2MPS11_LDO_STEP1 50000 +#define S2MPS11_LDO_STEP2 25000 +#define S2MPS11_LDO_VSEL_MASK 0x3F +#define S2MPS11_BUCK_VSEL_MASK 0xFF +#define S2MPS11_ENABLE_MASK (0x03 << S2MPS11_ENABLE_SHIFT) +#define S2MPS11_ENABLE_SHIFT 0x06 +#define S2MPS11_LDO_N_VOLTAGES (S2MPS11_LDO_VSEL_MASK + 1) +#define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) + +#define S2MPS11_PMIC_EN_SHIFT 6 +#define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3) + +#endif /* __LINUX_MFD_S2MPS11_H */ diff --git a/include/linux/mfd/samsung/s5m8763.h b/include/linux/mfd/samsung/s5m8763.h new file mode 100644 index 00000000000..e025418e558 --- /dev/null +++ b/include/linux/mfd/samsung/s5m8763.h @@ -0,0 +1,96 @@ +/* s5m8763.h + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_S5M8763_H +#define __LINUX_MFD_S5M8763_H + +/* S5M8763 registers */ +enum s5m8763_reg { + S5M8763_REG_IRQ1, + S5M8763_REG_IRQ2, + S5M8763_REG_IRQ3, + S5M8763_REG_IRQ4, + S5M8763_REG_IRQM1, + S5M8763_REG_IRQM2, + S5M8763_REG_IRQM3, + S5M8763_REG_IRQM4, + S5M8763_REG_STATUS1, + S5M8763_REG_STATUS2, + S5M8763_REG_STATUSM1, + S5M8763_REG_STATUSM2, + S5M8763_REG_CHGR1, + S5M8763_REG_CHGR2, + S5M8763_REG_LDO_ACTIVE_DISCHARGE1, + S5M8763_REG_LDO_ACTIVE_DISCHARGE2, + S5M8763_REG_BUCK_ACTIVE_DISCHARGE3, + S5M8763_REG_ONOFF1, + S5M8763_REG_ONOFF2, + S5M8763_REG_ONOFF3, + S5M8763_REG_ONOFF4, + S5M8763_REG_BUCK1_VOLTAGE1, + S5M8763_REG_BUCK1_VOLTAGE2, + S5M8763_REG_BUCK1_VOLTAGE3, + S5M8763_REG_BUCK1_VOLTAGE4, + S5M8763_REG_BUCK2_VOLTAGE1, + S5M8763_REG_BUCK2_VOLTAGE2, + S5M8763_REG_BUCK3, + S5M8763_REG_BUCK4, + S5M8763_REG_LDO1_LDO2, + S5M8763_REG_LDO3, + S5M8763_REG_LDO4, + S5M8763_REG_LDO5, + S5M8763_REG_LDO6, + S5M8763_REG_LDO7, + S5M8763_REG_LDO7_LDO8, + S5M8763_REG_LDO9_LDO10, + S5M8763_REG_LDO11, + S5M8763_REG_LDO12, + S5M8763_REG_LDO13, + S5M8763_REG_LDO14, + S5M8763_REG_LDO15, + S5M8763_REG_LDO16, + S5M8763_REG_BKCHR, + S5M8763_REG_LBCNFG1, + S5M8763_REG_LBCNFG2, +}; + +/* S5M8763 regulator ids */ +enum s5m8763_regulators { + S5M8763_LDO1, + S5M8763_LDO2, + S5M8763_LDO3, + S5M8763_LDO4, + S5M8763_LDO5, + S5M8763_LDO6, + S5M8763_LDO7, + S5M8763_LDO8, + S5M8763_LDO9, + S5M8763_LDO10, + S5M8763_LDO11, + S5M8763_LDO12, + S5M8763_LDO13, + S5M8763_LDO14, + S5M8763_LDO15, + S5M8763_LDO16, + S5M8763_BUCK1, + S5M8763_BUCK2, + S5M8763_BUCK3, + S5M8763_BUCK4, + S5M8763_AP_EN32KHZ, + S5M8763_CP_EN32KHZ, + S5M8763_ENCHGVI, + S5M8763_ESAFEUSB1, + S5M8763_ESAFEUSB2, +}; + +#define S5M8763_ENRAMP (1 << 4) +#endif /* __LINUX_MFD_S5M8763_H */ diff --git a/include/linux/mfd/samsung/s5m8767.h b/include/linux/mfd/samsung/s5m8767.h new file mode 100644 index 00000000000..306a95fc558 --- /dev/null +++ b/include/linux/mfd/samsung/s5m8767.h @@ -0,0 +1,188 @@ +/* s5m8767.h + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __LINUX_MFD_S5M8767_H +#define __LINUX_MFD_S5M8767_H + +/* S5M8767 registers */ +enum s5m8767_reg { + S5M8767_REG_ID, + S5M8767_REG_INT1, + S5M8767_REG_INT2, + S5M8767_REG_INT3, + S5M8767_REG_INT1M, + S5M8767_REG_INT2M, + S5M8767_REG_INT3M, + S5M8767_REG_STATUS1, + S5M8767_REG_STATUS2, + S5M8767_REG_STATUS3, + S5M8767_REG_CTRL1, + S5M8767_REG_CTRL2, + S5M8767_REG_LOWBAT1, + S5M8767_REG_LOWBAT2, + S5M8767_REG_BUCHG, + S5M8767_REG_DVSRAMP, + S5M8767_REG_DVSTIMER2 = 0x10, + S5M8767_REG_DVSTIMER3, + S5M8767_REG_DVSTIMER4, + S5M8767_REG_LDO1, + S5M8767_REG_LDO2, + S5M8767_REG_LDO3, + S5M8767_REG_LDO4, + S5M8767_REG_LDO5, + S5M8767_REG_LDO6, + S5M8767_REG_LDO7, + S5M8767_REG_LDO8, + S5M8767_REG_LDO9, + S5M8767_REG_LDO10, + S5M8767_REG_LDO11, + S5M8767_REG_LDO12, + S5M8767_REG_LDO13, + S5M8767_REG_LDO14 = 0x20, + S5M8767_REG_LDO15, + S5M8767_REG_LDO16, + S5M8767_REG_LDO17, + S5M8767_REG_LDO18, + S5M8767_REG_LDO19, + S5M8767_REG_LDO20, + S5M8767_REG_LDO21, + S5M8767_REG_LDO22, + S5M8767_REG_LDO23, + S5M8767_REG_LDO24, + S5M8767_REG_LDO25, + S5M8767_REG_LDO26, + S5M8767_REG_LDO27, + S5M8767_REG_LDO28, + S5M8767_REG_UVLO = 0x31, + S5M8767_REG_BUCK1CTRL1, + S5M8767_REG_BUCK1CTRL2, + S5M8767_REG_BUCK2CTRL, + S5M8767_REG_BUCK2DVS1, + S5M8767_REG_BUCK2DVS2, + S5M8767_REG_BUCK2DVS3, + S5M8767_REG_BUCK2DVS4, + S5M8767_REG_BUCK2DVS5, + S5M8767_REG_BUCK2DVS6, + S5M8767_REG_BUCK2DVS7, + S5M8767_REG_BUCK2DVS8, + S5M8767_REG_BUCK3CTRL, + S5M8767_REG_BUCK3DVS1, + S5M8767_REG_BUCK3DVS2, + S5M8767_REG_BUCK3DVS3, + S5M8767_REG_BUCK3DVS4, + S5M8767_REG_BUCK3DVS5, + S5M8767_REG_BUCK3DVS6, + S5M8767_REG_BUCK3DVS7, + S5M8767_REG_BUCK3DVS8, + S5M8767_REG_BUCK4CTRL, + S5M8767_REG_BUCK4DVS1, + S5M8767_REG_BUCK4DVS2, + S5M8767_REG_BUCK4DVS3, + S5M8767_REG_BUCK4DVS4, + S5M8767_REG_BUCK4DVS5, + S5M8767_REG_BUCK4DVS6, + S5M8767_REG_BUCK4DVS7, + S5M8767_REG_BUCK4DVS8, + S5M8767_REG_BUCK5CTRL1, + S5M8767_REG_BUCK5CTRL2, + S5M8767_REG_BUCK5CTRL3, + S5M8767_REG_BUCK5CTRL4, + S5M8767_REG_BUCK5CTRL5, + S5M8767_REG_BUCK6CTRL1, + S5M8767_REG_BUCK6CTRL2, + S5M8767_REG_BUCK7CTRL1, + S5M8767_REG_BUCK7CTRL2, + S5M8767_REG_BUCK8CTRL1, + S5M8767_REG_BUCK8CTRL2, + S5M8767_REG_BUCK9CTRL1, + S5M8767_REG_BUCK9CTRL2, + S5M8767_REG_LDO1CTRL, + S5M8767_REG_LDO2_1CTRL, + S5M8767_REG_LDO2_2CTRL, + S5M8767_REG_LDO2_3CTRL, + S5M8767_REG_LDO2_4CTRL, + S5M8767_REG_LDO3CTRL, + S5M8767_REG_LDO4CTRL, + S5M8767_REG_LDO5CTRL, + S5M8767_REG_LDO6CTRL, + S5M8767_REG_LDO7CTRL, + S5M8767_REG_LDO8CTRL, + S5M8767_REG_LDO9CTRL, + S5M8767_REG_LDO10CTRL, + S5M8767_REG_LDO11CTRL, + S5M8767_REG_LDO12CTRL, + S5M8767_REG_LDO13CTRL, + S5M8767_REG_LDO14CTRL, + S5M8767_REG_LDO15CTRL, + S5M8767_REG_LDO16CTRL, + S5M8767_REG_LDO17CTRL, + S5M8767_REG_LDO18CTRL, + S5M8767_REG_LDO19CTRL, + S5M8767_REG_LDO20CTRL, + S5M8767_REG_LDO21CTRL, + S5M8767_REG_LDO22CTRL, + S5M8767_REG_LDO23CTRL, + S5M8767_REG_LDO24CTRL, + S5M8767_REG_LDO25CTRL, + S5M8767_REG_LDO26CTRL, + S5M8767_REG_LDO27CTRL, + S5M8767_REG_LDO28CTRL, +}; + +/* S5M8767 regulator ids */ +enum s5m8767_regulators { + S5M8767_LDO1, + S5M8767_LDO2, + S5M8767_LDO3, + S5M8767_LDO4, + S5M8767_LDO5, + S5M8767_LDO6, + S5M8767_LDO7, + S5M8767_LDO8, + S5M8767_LDO9, + S5M8767_LDO10, + S5M8767_LDO11, + S5M8767_LDO12, + S5M8767_LDO13, + S5M8767_LDO14, + S5M8767_LDO15, + S5M8767_LDO16, + S5M8767_LDO17, + S5M8767_LDO18, + S5M8767_LDO19, + S5M8767_LDO20, + S5M8767_LDO21, + S5M8767_LDO22, + S5M8767_LDO23, + S5M8767_LDO24, + S5M8767_LDO25, + S5M8767_LDO26, + S5M8767_LDO27, + S5M8767_LDO28, + S5M8767_BUCK1, + S5M8767_BUCK2, + S5M8767_BUCK3, + S5M8767_BUCK4, + S5M8767_BUCK5, + S5M8767_BUCK6, + S5M8767_BUCK7, + S5M8767_BUCK8, + S5M8767_BUCK9, + S5M8767_AP_EN32KHZ, + S5M8767_CP_EN32KHZ, + + S5M8767_REG_MAX, +}; + +#define S5M8767_ENCTRL_SHIFT 6 + +#endif /* __LINUX_MFD_S5M8767_H */ diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 6c4c478e21a..9bf8767818b 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -807,6 +807,7 @@ struct tps65910_board { int irq_base; int vmbch_threshold; int vmbch2_threshold; + bool en_ck32k_xtal; bool en_dev_slp; struct tps65910_sleep_keepon_data *slp_keepon; bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 6659487c31e..eaad49f7c13 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -161,8 +161,9 @@ #define TWL6040_CELLS 2 #define TWL6040_REV_ES1_0 0x00 -#define TWL6040_REV_ES1_1 0x01 -#define TWL6040_REV_ES1_2 0x02 +#define TWL6040_REV_ES1_1 0x01 /* Rev ES1.1 and ES1.2 */ +#define TWL6040_REV_ES1_3 0x02 +#define TWL6041_REV_ES2_0 0x10 #define TWL6040_IRQ_TH 0 #define TWL6040_IRQ_PLUG 1 @@ -206,7 +207,6 @@ struct twl6040 { struct regmap *regmap; struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */ struct mutex mutex; - struct mutex io_mutex; struct mutex irq_mutex; struct mfd_cell cells[TWL6040_CELLS]; struct completion ready; diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index 9192b6404a7..509481d9cf1 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h @@ -17,6 +17,7 @@ #include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/completion.h> +#include <linux/regmap.h> #include <linux/mfd/wm8350/audio.h> #include <linux/mfd/wm8350/gpio.h> @@ -66,6 +67,9 @@ #define WM8350_MAX_REGISTER 0xFF +#define WM8350_UNLOCK_KEY 0x0013 +#define WM8350_LOCK_KEY 0x0000 + /* * Field Definitions. */ @@ -582,27 +586,9 @@ #define WM8350_NUM_IRQ_REGS 7 -struct wm8350_reg_access { - u16 readable; /* Mask of readable bits */ - u16 writable; /* Mask of writable bits */ - u16 vol; /* Mask of volatile bits */ -}; -extern const struct wm8350_reg_access wm8350_reg_io_map[]; -extern const u16 wm8350_mode0_defaults[]; -extern const u16 wm8350_mode1_defaults[]; -extern const u16 wm8350_mode2_defaults[]; -extern const u16 wm8350_mode3_defaults[]; -extern const u16 wm8351_mode0_defaults[]; -extern const u16 wm8351_mode1_defaults[]; -extern const u16 wm8351_mode2_defaults[]; -extern const u16 wm8351_mode3_defaults[]; -extern const u16 wm8352_mode0_defaults[]; -extern const u16 wm8352_mode1_defaults[]; -extern const u16 wm8352_mode2_defaults[]; -extern const u16 wm8352_mode3_defaults[]; +extern const struct regmap_config wm8350_regmap; struct wm8350; -struct regmap; struct wm8350_hwmon { struct platform_device *pdev; @@ -614,7 +600,7 @@ struct wm8350 { /* device IO */ struct regmap *regmap; - u16 *reg_cache; + bool unlocked; struct mutex auxadc_mutex; struct completion auxadc_done; diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 893267bb622..f0361c03192 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h @@ -141,6 +141,7 @@ struct wm8994_pdata { struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO]; int irq_base; /** Base IRQ number for WM8994, required for IRQs */ + unsigned long irq_flags; /** user irq flags */ int num_drc_cfgs; struct wm8994_drc_cfg *drc_cfgs; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 704a626d94a..074eb98fe15 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -53,7 +53,7 @@ struct page { struct { union { pgoff_t index; /* Our offset within mapping. */ - void *freelist; /* slub first free object */ + void *freelist; /* slub/slob first free object */ }; union { @@ -91,11 +91,12 @@ struct page { */ atomic_t _mapcount; - struct { + struct { /* SLUB */ unsigned inuse:16; unsigned objects:15; unsigned frozen:1; }; + int units; /* SLOB */ }; atomic_t _count; /* Usage count, see below. */ }; @@ -117,6 +118,12 @@ struct page { short int pobjects; #endif }; + + struct list_head list; /* slobs list of pages */ + struct { /* slab fields */ + struct kmem_cache *slab_cache; + struct slab *slab_page; + }; }; /* Remainder is not double word aligned */ diff --git a/include/linux/of.h b/include/linux/of.h index 0e9cf9eec08..42c2a58328c 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -386,6 +386,13 @@ static inline int of_property_read_u64(const struct device_node *np, return -ENOSYS; } +static inline int of_property_match_string(struct device_node *np, + const char *propname, + const char *string) +{ + return -ENOSYS; +} + static inline struct device_node *of_parse_phandle(struct device_node *np, const char *phandle_name, int index) @@ -393,6 +400,15 @@ static inline struct device_node *of_parse_phandle(struct device_node *np, return NULL; } +static inline int of_parse_phandle_with_args(struct device_node *np, + const char *list_name, + const char *cells_name, + int index, + struct of_phandle_args *out_args) +{ + return -ENOSYS; +} + static inline int of_alias_get_id(struct device_node *np, const char *stem) { return -ENOSYS; diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7c775751392..21d076c5089 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -1,7 +1,10 @@ #ifndef __LINUX_PWM_H #define __LINUX_PWM_H +#include <linux/of.h> + struct pwm_device; +struct seq_file; /* * pwm_request - request a PWM device @@ -28,4 +31,118 @@ int pwm_enable(struct pwm_device *pwm); */ void pwm_disable(struct pwm_device *pwm); +#ifdef CONFIG_PWM +struct pwm_chip; + +enum { + PWMF_REQUESTED = 1 << 0, + PWMF_ENABLED = 1 << 1, +}; + +struct pwm_device { + const char *label; + unsigned long flags; + unsigned int hwpwm; + unsigned int pwm; + struct pwm_chip *chip; + void *chip_data; + + unsigned int period; /* in nanoseconds */ +}; + +static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period) +{ + if (pwm) + pwm->period = period; +} + +static inline unsigned int pwm_get_period(struct pwm_device *pwm) +{ + return pwm ? pwm->period : 0; +} + +/** + * struct pwm_ops - PWM controller operations + * @request: optional hook for requesting a PWM + * @free: optional hook for freeing a PWM + * @config: configure duty cycles and period length for this PWM + * @enable: enable PWM output toggling + * @disable: disable PWM output toggling + * @dbg_show: optional routine to show contents in debugfs + * @owner: helps prevent removal of modules exporting active PWMs + */ +struct pwm_ops { + int (*request)(struct pwm_chip *chip, + struct pwm_device *pwm); + void (*free)(struct pwm_chip *chip, + struct pwm_device *pwm); + int (*config)(struct pwm_chip *chip, + struct pwm_device *pwm, + int duty_ns, int period_ns); + int (*enable)(struct pwm_chip *chip, + struct pwm_device *pwm); + void (*disable)(struct pwm_chip *chip, + struct pwm_device *pwm); +#ifdef CONFIG_DEBUG_FS + void (*dbg_show)(struct pwm_chip *chip, + struct seq_file *s); +#endif + struct module *owner; +}; + +/** + * struct pwm_chip - abstract a PWM controller + * @dev: device providing the PWMs + * @list: list node for internal use + * @ops: callbacks for this PWM controller + * @base: number of first PWM controlled by this chip + * @npwm: number of PWMs controlled by this chip + * @pwms: array of PWM devices allocated by the framework + */ +struct pwm_chip { + struct device *dev; + struct list_head list; + const struct pwm_ops *ops; + int base; + unsigned int npwm; + + struct pwm_device *pwms; + + struct pwm_device * (*of_xlate)(struct pwm_chip *pc, + const struct of_phandle_args *args); + unsigned int of_pwm_n_cells; +}; + +int pwm_set_chip_data(struct pwm_device *pwm, void *data); +void *pwm_get_chip_data(struct pwm_device *pwm); + +int pwmchip_add(struct pwm_chip *chip); +int pwmchip_remove(struct pwm_chip *chip); +struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, + unsigned int index, + const char *label); + +struct pwm_device *pwm_get(struct device *dev, const char *consumer); +void pwm_put(struct pwm_device *pwm); + +struct pwm_lookup { + struct list_head list; + const char *provider; + unsigned int index; + const char *dev_id; + const char *con_id; +}; + +#define PWM_LOOKUP(_provider, _index, _dev_id, _con_id) \ + { \ + .provider = _provider, \ + .index = _index, \ + .dev_id = _dev_id, \ + .con_id = _con_id, \ + } + +void pwm_add_table(struct pwm_lookup *table, size_t num); + +#endif + #endif /* __LINUX_PWM_H */ diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h index 63d2df43e61..56f4a866539 100644 --- a/include/linux/pwm_backlight.h +++ b/include/linux/pwm_backlight.h @@ -12,6 +12,7 @@ struct platform_pwm_backlight_data { unsigned int dft_brightness; unsigned int lth_brightness; unsigned int pwm_period_ns; + unsigned int *levels; int (*init)(struct device *dev); int (*notify)(struct device *dev, int brightness); void (*notify_after)(struct device *dev, int brightness); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index ac9586dadfa..7b600da9a63 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *); int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, sg_alloc_fn *); int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); +int sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int n_pages, + unsigned long offset, unsigned long size, + gfp_t gfp_mask); size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen); diff --git a/include/linux/slab.h b/include/linux/slab.h index 67d5d94b783..0dd2dfa7bec 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -93,6 +93,30 @@ (unsigned long)ZERO_SIZE_PTR) /* + * Common fields provided in kmem_cache by all slab allocators + * This struct is either used directly by the allocator (SLOB) + * or the allocator must include definitions for all fields + * provided in kmem_cache_common in their definition of kmem_cache. + * + * Once we can do anonymous structs (C11 standard) we could put a + * anonymous struct definition in these allocators so that the + * separate allocations in the kmem_cache structure of SLAB and + * SLUB is no longer needed. + */ +#ifdef CONFIG_SLOB +struct kmem_cache { + unsigned int object_size;/* The original size of the object */ + unsigned int size; /* The aligned/padded/added on size */ + unsigned int align; /* Alignment as calculated */ + unsigned long flags; /* Active flags on the slab */ + const char *name; /* Slab name for sysfs */ + int refcount; /* Use counter */ + void (*ctor)(void *); /* Called on object slot creation */ + struct list_head list; /* List of all slab caches on the system */ +}; +#endif + +/* * struct kmem_cache related prototypes */ void __init kmem_cache_init(void); diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index fbd1117fdfd..0c634fa376c 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -27,7 +27,7 @@ struct kmem_cache { unsigned int limit; unsigned int shared; - unsigned int buffer_size; + unsigned int size; u32 reciprocal_buffer_size; /* 2) touched by every alloc & free from the backend */ @@ -39,7 +39,7 @@ struct kmem_cache { unsigned int gfporder; /* force GFP flags, e.g. GFP_DMA */ - gfp_t gfpflags; + gfp_t allocflags; size_t colour; /* cache colouring range */ unsigned int colour_off; /* colour offset */ @@ -52,7 +52,10 @@ struct kmem_cache { /* 4) cache creation/removal */ const char *name; - struct list_head next; + struct list_head list; + int refcount; + int object_size; + int align; /* 5) statistics */ #ifdef CONFIG_DEBUG_SLAB @@ -73,12 +76,11 @@ struct kmem_cache { /* * If debugging is enabled, then the allocator can add additional - * fields and/or padding to every object. buffer_size contains the total + * fields and/or padding to every object. size contains the total * object size including these internal fields, the following two * variables contain the offset to the user object and its size. */ int obj_offset; - int obj_size; #endif /* CONFIG_DEBUG_SLAB */ /* 6) per-cpu/per-node data, touched during every alloc/free */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index c2f8c8bc56e..df448adb728 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -48,7 +48,6 @@ struct kmem_cache_cpu { unsigned long tid; /* Globally unique transaction id */ struct page *page; /* The slab from which we are allocating */ struct page *partial; /* Partially allocated frozen slabs */ - int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS unsigned stat[NR_SLUB_STAT_ITEMS]; #endif @@ -83,7 +82,7 @@ struct kmem_cache { unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ - int objsize; /* The size of an object without meta data */ + int object_size; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ int cpu_partial; /* Number of per cpu partial objects to keep around */ struct kmem_cache_order_objects oo; diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h index e0edb40ca7a..6d8e61c4856 100644 --- a/include/linux/virtio_blk.h +++ b/include/linux/virtio_blk.h @@ -37,8 +37,14 @@ #define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ #define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ -#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */ +#define VIRTIO_BLK_F_WCE 9 /* Writeback mode enabled after reset */ #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ +#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */ + +#ifndef __KERNEL__ +/* Old (deprecated) name for VIRTIO_BLK_F_WCE. */ +#define VIRTIO_BLK_F_FLUSH VIRTIO_BLK_F_WCE +#endif #define VIRTIO_BLK_ID_BYTES 20 /* ID string length */ @@ -69,6 +75,8 @@ struct virtio_blk_config { /* optimal sustained I/O size in logical blocks. */ __u32 opt_io_size; + /* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */ + __u8 wce; } __attribute__((packed)); /* diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h index 7529b854b7f..270fb22c581 100644 --- a/include/linux/virtio_ids.h +++ b/include/linux/virtio_ids.h @@ -32,7 +32,7 @@ #define VIRTIO_ID_NET 1 /* virtio net */ #define VIRTIO_ID_BLOCK 2 /* virtio block */ #define VIRTIO_ID_CONSOLE 3 /* virtio console */ -#define VIRTIO_ID_RNG 4 /* virtio ring */ +#define VIRTIO_ID_RNG 4 /* virtio rng */ #define VIRTIO_ID_BALLOON 5 /* virtio balloon */ #define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */ #define VIRTIO_ID_SCSI 8 /* virtio scsi */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index dcdfc2bda92..6071e911c7f 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -32,7 +32,7 @@ struct vm_struct { struct page **pages; unsigned int nr_pages; phys_addr_t phys_addr; - void *caller; + const void *caller; }; /* @@ -62,7 +62,7 @@ extern void *vmalloc_32_user(unsigned long size); extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); extern void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long start, unsigned long end, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller); + pgprot_t prot, int node, const void *caller); extern void vfree(const void *addr); extern void *vmap(struct page **pages, unsigned int count, @@ -85,14 +85,15 @@ static inline size_t get_vm_area_size(const struct vm_struct *area) extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags); extern struct vm_struct *get_vm_area_caller(unsigned long size, - unsigned long flags, void *caller); + unsigned long flags, const void *caller); extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end); extern struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags, unsigned long start, unsigned long end, - void *caller); + const void *caller); extern struct vm_struct *remove_vm_area(const void *addr); +extern struct vm_struct *find_vm_area(const void *addr); extern int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages); diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h new file mode 100644 index 00000000000..260470e7248 --- /dev/null +++ b/include/ras/ras_event.h @@ -0,0 +1,102 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ras +#define TRACE_INCLUDE_FILE ras_event + +#if !defined(_TRACE_HW_EVENT_MC_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_HW_EVENT_MC_H + +#include <linux/tracepoint.h> +#include <linux/edac.h> +#include <linux/ktime.h> + +/* + * Hardware Events Report + * + * Those events are generated when hardware detected a corrected or + * uncorrected event, and are meant to replace the current API to report + * errors defined on both EDAC and MCE subsystems. + * + * FIXME: Add events for handling memory errors originated from the + * MCE subsystem. + */ + +/* + * Hardware-independent Memory Controller specific events + */ + +/* + * Default error mechanisms for Memory Controller errors (CE and UE) + */ +TRACE_EVENT(mc_event, + + TP_PROTO(const unsigned int err_type, + const char *error_msg, + const char *label, + const int error_count, + const u8 mc_index, + const s8 top_layer, + const s8 mid_layer, + const s8 low_layer, + unsigned long address, + const u8 grain_bits, + unsigned long syndrome, + const char *driver_detail), + + TP_ARGS(err_type, error_msg, label, error_count, mc_index, + top_layer, mid_layer, low_layer, address, grain_bits, + syndrome, driver_detail), + + TP_STRUCT__entry( + __field( unsigned int, error_type ) + __string( msg, error_msg ) + __string( label, label ) + __field( u16, error_count ) + __field( u8, mc_index ) + __field( s8, top_layer ) + __field( s8, middle_layer ) + __field( s8, lower_layer ) + __field( long, address ) + __field( u8, grain_bits ) + __field( long, syndrome ) + __string( driver_detail, driver_detail ) + ), + + TP_fast_assign( + __entry->error_type = err_type; + __assign_str(msg, error_msg); + __assign_str(label, label); + __entry->error_count = error_count; + __entry->mc_index = mc_index; + __entry->top_layer = top_layer; + __entry->middle_layer = mid_layer; + __entry->lower_layer = low_layer; + __entry->address = address; + __entry->grain_bits = grain_bits; + __entry->syndrome = syndrome; + __assign_str(driver_detail, driver_detail); + ), + + TP_printk("%d %s error%s:%s%s on %s (mc:%d location:%d:%d:%d address:0x%08lx grain:%d syndrome:0x%08lx%s%s)", + __entry->error_count, + (__entry->error_type == HW_EVENT_ERR_CORRECTED) ? "Corrected" : + ((__entry->error_type == HW_EVENT_ERR_FATAL) ? + "Fatal" : "Uncorrected"), + __entry->error_count > 1 ? "s" : "", + ((char *)__get_str(msg))[0] ? " " : "", + __get_str(msg), + __get_str(label), + __entry->mc_index, + __entry->top_layer, + __entry->middle_layer, + __entry->lower_layer, + __entry->address, + 1 << __entry->grain_bits, + __entry->syndrome, + ((char *)__get_str(driver_detail))[0] ? " " : "", + __get_str(driver_detail)) +); + +#endif /* _TRACE_HW_EVENT_MC_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/lib/Kconfig b/lib/Kconfig index 72c1d469306..bb94c1ba616 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -390,4 +390,10 @@ config SIGNATURE Digital signature verification. Currently only RSA is supported. Implementation is done using GnuPG MPI library +# +# libfdt files, only selected if needed. +# +config LIBFDT + bool + endmenu diff --git a/lib/Makefile b/lib/Makefile index 1054de86ae8..9cb4104f47d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -135,6 +135,11 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +$(foreach file, $(libfdt_files), \ + $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) +lib-$(CONFIG_LIBFDT) += $(libfdt_files) + hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/fdt.c b/lib/fdt.c new file mode 100644 index 00000000000..97f20069fc3 --- /dev/null +++ b/lib/fdt.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt.c" diff --git a/lib/fdt_ro.c b/lib/fdt_ro.c new file mode 100644 index 00000000000..f73c04ea7be --- /dev/null +++ b/lib/fdt_ro.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_ro.c" diff --git a/lib/fdt_rw.c b/lib/fdt_rw.c new file mode 100644 index 00000000000..0c1f0f4a4b1 --- /dev/null +++ b/lib/fdt_rw.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_rw.c" diff --git a/lib/fdt_strerror.c b/lib/fdt_strerror.c new file mode 100644 index 00000000000..8713e3ff470 --- /dev/null +++ b/lib/fdt_strerror.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_strerror.c" diff --git a/lib/fdt_sw.c b/lib/fdt_sw.c new file mode 100644 index 00000000000..9ac7e50c76c --- /dev/null +++ b/lib/fdt_sw.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_sw.c" diff --git a/lib/fdt_wip.c b/lib/fdt_wip.c new file mode 100644 index 00000000000..45b3fc3d3ba --- /dev/null +++ b/lib/fdt_wip.c @@ -0,0 +1,2 @@ +#include <linux/libfdt_env.h> +#include "../scripts/dtc/libfdt/fdt_wip.c" diff --git a/lib/scatterlist.c b/lib/scatterlist.c index d09bdd8b40c..fadae774a20 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -311,6 +311,70 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) EXPORT_SYMBOL(sg_alloc_table); /** + * sg_alloc_table_from_pages - Allocate and initialize an sg table from + * an array of pages + * @sgt: The sg table header to use + * @pages: Pointer to an array of page pointers + * @n_pages: Number of pages in the pages array + * @offset: Offset from start of the first page to the start of a buffer + * @size: Number of valid bytes in the buffer (after offset) + * @gfp_mask: GFP allocation mask + * + * Description: + * Allocate and initialize an sg table from a list of pages. Contiguous + * ranges of the pages are squashed into a single scatterlist node. A user + * may provide an offset at a start and a size of valid data in a buffer + * specified by the page array. The returned sg table is released by + * sg_free_table. + * + * Returns: + * 0 on success, negative error on failure + */ +int sg_alloc_table_from_pages(struct sg_table *sgt, + struct page **pages, unsigned int n_pages, + unsigned long offset, unsigned long size, + gfp_t gfp_mask) +{ + unsigned int chunks; + unsigned int i; + unsigned int cur_page; + int ret; + struct scatterlist *s; + + /* compute number of contiguous chunks */ + chunks = 1; + for (i = 1; i < n_pages; ++i) + if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1) + ++chunks; + + ret = sg_alloc_table(sgt, chunks, gfp_mask); + if (unlikely(ret)) + return ret; + + /* merging chunks and putting them into the scatterlist */ + cur_page = 0; + for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { + unsigned long chunk_size; + unsigned int j; + + /* look for the end of the current chunk */ + for (j = cur_page + 1; j < n_pages; ++j) + if (page_to_pfn(pages[j]) != + page_to_pfn(pages[j - 1]) + 1) + break; + + chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; + sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); + size -= chunk_size; + offset = 0; + cur_page = j; + } + + return 0; +} +EXPORT_SYMBOL(sg_alloc_table_from_pages); + +/** * sg_miter_start - start mapping iteration over a sg list * @miter: sg mapping iter to be started * @sgl: sg list to iterate over diff --git a/mm/Makefile b/mm/Makefile index 2e2fbbefb99..8e81fe263c9 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -16,7 +16,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ page_isolation.o mm_init.o mmu_context.o percpu.o \ - compaction.o $(mmu-y) + compaction.o slab_common.o $(mmu-y) + obj-y += init-mm.o ifdef CONFIG_NO_BOOTMEM diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1d771e4200d..bd92431d4c4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1602,8 +1602,14 @@ static unsigned interleave_nodes(struct mempolicy *policy) * task can change it's policy. The system default policy requires no * such protection. */ -unsigned slab_node(struct mempolicy *policy) +unsigned slab_node(void) { + struct mempolicy *policy; + + if (in_interrupt()) + return numa_node_id(); + + policy = current->mempolicy; if (!policy || policy->flags & MPOL_F_LOCAL) return numa_node_id(); diff --git a/mm/slab.c b/mm/slab.c index e901a36e252..1fcf3ac94b6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -68,7 +68,7 @@ * Further notes from the original documentation: * * 11 April '97. Started multi-threading - markhe - * The global cache-chain is protected by the mutex 'cache_chain_mutex'. + * The global cache-chain is protected by the mutex 'slab_mutex'. * The sem is only needed when accessing/extending the cache-chain, which * can never happen inside an interrupt (kmem_cache_create(), * kmem_cache_shrink() and kmem_cache_reap()). @@ -87,6 +87,7 @@ */ #include <linux/slab.h> +#include "slab.h" #include <linux/mm.h> #include <linux/poison.h> #include <linux/swap.h> @@ -424,8 +425,8 @@ static void kmem_list3_init(struct kmem_list3 *parent) * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1: * redzone word. * cachep->obj_offset: The real object. - * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] - * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address + * cachep->size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->size - 1* BYTES_PER_WORD: last caller address * [BYTES_PER_WORD long] */ static int obj_offset(struct kmem_cache *cachep) @@ -433,11 +434,6 @@ static int obj_offset(struct kmem_cache *cachep) return cachep->obj_offset; } -static int obj_size(struct kmem_cache *cachep) -{ - return cachep->obj_size; -} - static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); @@ -449,23 +445,22 @@ static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long long *)(objp + cachep->buffer_size - + return (unsigned long long *)(objp + cachep->size - sizeof(unsigned long long) - REDZONE_ALIGN); - return (unsigned long long *) (objp + cachep->buffer_size - + return (unsigned long long *) (objp + cachep->size - sizeof(unsigned long long)); } static void **dbg_userword(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD); + return (void **)(objp + cachep->size - BYTES_PER_WORD); } #else #define obj_offset(x) 0 -#define obj_size(cachep) (cachep->buffer_size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) @@ -475,7 +470,7 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) #ifdef CONFIG_TRACING size_t slab_buffer_size(struct kmem_cache *cachep) { - return cachep->buffer_size; + return cachep->size; } EXPORT_SYMBOL(slab_buffer_size); #endif @@ -489,56 +484,37 @@ EXPORT_SYMBOL(slab_buffer_size); static int slab_max_order = SLAB_MAX_ORDER_LO; static bool slab_max_order_set __initdata; -/* - * Functions for storing/retrieving the cachep and or slab from the page - * allocator. These are used to find the slab an obj belongs to. With kfree(), - * these are used to find the cache which an obj belongs to. - */ -static inline void page_set_cache(struct page *page, struct kmem_cache *cache) -{ - page->lru.next = (struct list_head *)cache; -} - static inline struct kmem_cache *page_get_cache(struct page *page) { page = compound_head(page); BUG_ON(!PageSlab(page)); - return (struct kmem_cache *)page->lru.next; -} - -static inline void page_set_slab(struct page *page, struct slab *slab) -{ - page->lru.prev = (struct list_head *)slab; -} - -static inline struct slab *page_get_slab(struct page *page) -{ - BUG_ON(!PageSlab(page)); - return (struct slab *)page->lru.prev; + return page->slab_cache; } static inline struct kmem_cache *virt_to_cache(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_cache(page); + return page->slab_cache; } static inline struct slab *virt_to_slab(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_slab(page); + + VM_BUG_ON(!PageSlab(page)); + return page->slab_page; } static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab, unsigned int idx) { - return slab->s_mem + cache->buffer_size * idx; + return slab->s_mem + cache->size * idx; } /* - * We want to avoid an expensive divide : (offset / cache->buffer_size) - * Using the fact that buffer_size is a constant for a particular cache, - * we can replace (offset / cache->buffer_size) by + * We want to avoid an expensive divide : (offset / cache->size) + * Using the fact that size is a constant for a particular cache, + * we can replace (offset / cache->size) by * reciprocal_divide(offset, cache->reciprocal_buffer_size) */ static inline unsigned int obj_to_index(const struct kmem_cache *cache, @@ -584,33 +560,12 @@ static struct kmem_cache cache_cache = { .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, - .buffer_size = sizeof(struct kmem_cache), + .size = sizeof(struct kmem_cache), .name = "kmem_cache", }; #define BAD_ALIEN_MAGIC 0x01020304ul -/* - * chicken and egg problem: delay the per-cpu array allocation - * until the general caches are up. - */ -static enum { - NONE, - PARTIAL_AC, - PARTIAL_L3, - EARLY, - LATE, - FULL -} g_cpucache_up; - -/* - * used by boot code to determine if it can use slab based allocator - */ -int slab_is_available(void) -{ - return g_cpucache_up >= EARLY; -} - #ifdef CONFIG_LOCKDEP /* @@ -676,7 +631,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up < LATE) + if (slab_state < UP) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -716,12 +671,6 @@ static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep) } #endif -/* - * Guard access to the cache-chain. - */ -static DEFINE_MUTEX(cache_chain_mutex); -static struct list_head cache_chain; - static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -1145,7 +1094,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) * When hotplugging memory or a cpu, existing nodelists are not replaced if * already in use. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int init_cache_nodelists_node(int node) { @@ -1153,7 +1102,7 @@ static int init_cache_nodelists_node(int node) struct kmem_list3 *l3; const int memsize = sizeof(struct kmem_list3); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { /* * Set up the size64 kmemlist for cpu before we can * begin anything. Make sure some other cpu on this @@ -1169,7 +1118,7 @@ static int init_cache_nodelists_node(int node) /* * The l3s don't come and go as CPUs come and - * go. cache_chain_mutex is sufficient + * go. slab_mutex is sufficient * protection here. */ cachep->nodelists[node] = l3; @@ -1191,7 +1140,7 @@ static void __cpuinit cpuup_canceled(long cpu) int node = cpu_to_mem(cpu); const struct cpumask *mask = cpumask_of_node(node); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared; struct array_cache **alien; @@ -1241,7 +1190,7 @@ free_array_cache: * the respective cache's slabs, now we can go ahead and * shrink each nodelist to its limit. */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { l3 = cachep->nodelists[node]; if (!l3) continue; @@ -1270,7 +1219,7 @@ static int __cpuinit cpuup_prepare(long cpu) * Now we can go ahead with allocating the shared arrays and * array caches */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared = NULL; struct array_cache **alien = NULL; @@ -1338,9 +1287,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); err = cpuup_prepare(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: @@ -1350,7 +1299,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: /* - * Shutdown cache reaper. Note that the cache_chain_mutex is + * Shutdown cache reaper. Note that the slab_mutex is * held so that if cache_reap() is invoked it cannot do * anything expensive but will only modify reap_work * and reschedule the timer. @@ -1377,9 +1326,9 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, #endif case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); cpuup_canceled(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; } return notifier_from_errno(err); @@ -1395,14 +1344,14 @@ static struct notifier_block __cpuinitdata cpucache_notifier = { * Returns -EBUSY if all objects cannot be drained so that the node is not * removed. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int __meminit drain_cache_nodelists_node(int node) { struct kmem_cache *cachep; int ret = 0; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct kmem_list3 *l3; l3 = cachep->nodelists[node]; @@ -1433,14 +1382,14 @@ static int __meminit slab_memory_callback(struct notifier_block *self, switch (action) { case MEM_GOING_ONLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = init_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_GOING_OFFLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = drain_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_ONLINE: case MEM_OFFLINE: @@ -1544,8 +1493,8 @@ void __init kmem_cache_init(void) node = numa_mem_id(); /* 1) create the cache_cache */ - INIT_LIST_HEAD(&cache_chain); - list_add(&cache_cache.next, &cache_chain); + INIT_LIST_HEAD(&slab_caches); + list_add(&cache_cache.list, &slab_caches); cache_cache.colour_off = cache_line_size(); cache_cache.array[smp_processor_id()] = &initarray_cache.cache; cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; @@ -1553,18 +1502,16 @@ void __init kmem_cache_init(void) /* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + + cache_cache.size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + nr_node_ids * sizeof(struct kmem_list3 *); -#if DEBUG - cache_cache.obj_size = cache_cache.buffer_size; -#endif - cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, + cache_cache.object_size = cache_cache.size; + cache_cache.size = ALIGN(cache_cache.size, cache_line_size()); cache_cache.reciprocal_buffer_size = - reciprocal_value(cache_cache.buffer_size); + reciprocal_value(cache_cache.size); for (order = 0; order < MAX_ORDER; order++) { - cache_estimate(order, cache_cache.buffer_size, + cache_estimate(order, cache_cache.size, cache_line_size(), 0, &left_over, &cache_cache.num); if (cache_cache.num) break; @@ -1585,7 +1532,7 @@ void __init kmem_cache_init(void) * bug. */ - sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name, + sizes[INDEX_AC].cs_cachep = __kmem_cache_create(names[INDEX_AC].name, sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, @@ -1593,7 +1540,7 @@ void __init kmem_cache_init(void) if (INDEX_AC != INDEX_L3) { sizes[INDEX_L3].cs_cachep = - kmem_cache_create(names[INDEX_L3].name, + __kmem_cache_create(names[INDEX_L3].name, sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, @@ -1611,14 +1558,14 @@ void __init kmem_cache_init(void) * allow tighter packing of the smaller caches. */ if (!sizes->cs_cachep) { - sizes->cs_cachep = kmem_cache_create(names->name, + sizes->cs_cachep = __kmem_cache_create(names->name, sizes->cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, NULL); } #ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = kmem_cache_create( + sizes->cs_dmacachep = __kmem_cache_create( names->name_dma, sizes->cs_size, ARCH_KMALLOC_MINALIGN, @@ -1676,27 +1623,27 @@ void __init kmem_cache_init(void) } } - g_cpucache_up = EARLY; + slab_state = UP; } void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; - g_cpucache_up = LATE; + slab_state = UP; /* Annotate slab for lockdep -- annotate the malloc caches */ init_lock_keys(); /* 6) resize the head arrays to their final sizes */ - mutex_lock(&cache_chain_mutex); - list_for_each_entry(cachep, &cache_chain, next) + mutex_lock(&slab_mutex); + list_for_each_entry(cachep, &slab_caches, list) if (enable_cpucache(cachep, GFP_NOWAIT)) BUG(); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); /* Done! */ - g_cpucache_up = FULL; + slab_state = FULL; /* * Register a cpu startup notifier callback that initializes @@ -1727,6 +1674,9 @@ static int __init cpucache_init(void) */ for_each_online_cpu(cpu) start_cpu_timer(cpu); + + /* Done! */ + slab_state = FULL; return 0; } __initcall(cpucache_init); @@ -1743,7 +1693,7 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid) "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n", nodeid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, order: %d\n", - cachep->name, cachep->buffer_size, cachep->gfporder); + cachep->name, cachep->size, cachep->gfporder); for_each_online_node(node) { unsigned long active_objs = 0, num_objs = 0, free_objects = 0; @@ -1798,7 +1748,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) flags |= __GFP_COMP; #endif - flags |= cachep->gfpflags; + flags |= cachep->allocflags; if (cachep->flags & SLAB_RECLAIM_ACCOUNT) flags |= __GFP_RECLAIMABLE; @@ -1874,7 +1824,7 @@ static void kmem_rcu_free(struct rcu_head *head) static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, unsigned long caller) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)]; @@ -1906,7 +1856,7 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = &((char *)addr)[obj_offset(cachep)]; memset(addr, val, size); @@ -1966,7 +1916,7 @@ static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines) printk("\n"); } realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size && lines; i += 16, lines--) { int limit; limit = 16; @@ -1983,7 +1933,7 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) int lines = 0; realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size; i++) { char exp = POISON_FREE; @@ -2047,10 +1997,10 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slab if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if (cachep->buffer_size % PAGE_SIZE == 0 && + if (cachep->size % PAGE_SIZE == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -2194,10 +2144,10 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) { - if (g_cpucache_up == FULL) + if (slab_state >= FULL) return enable_cpucache(cachep, gfp); - if (g_cpucache_up == NONE) { + if (slab_state == DOWN) { /* * Note: the first kmem_cache_create must create the cache * that's used by kmalloc(24), otherwise the creation of @@ -2212,16 +2162,16 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) */ set_up_list3s(cachep, SIZE_AC); if (INDEX_AC == INDEX_L3) - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; else - g_cpucache_up = PARTIAL_AC; + slab_state = PARTIAL_ARRAYCACHE; } else { cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init), gfp); - if (g_cpucache_up == PARTIAL_AC) { + if (slab_state == PARTIAL_ARRAYCACHE) { set_up_list3s(cachep, SIZE_L3); - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; } else { int node; for_each_online_node(node) { @@ -2247,7 +2197,7 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) } /** - * kmem_cache_create - Create a cache. + * __kmem_cache_create - Create a cache. * @name: A string which is used in /proc/slabinfo to identify this cache. * @size: The size of objects to be created in this cache. * @align: The required alignment for the objects. @@ -2274,59 +2224,14 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) * as davem. */ struct kmem_cache * -kmem_cache_create (const char *name, size_t size, size_t align, +__kmem_cache_create (const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { size_t left_over, slab_size, ralign; - struct kmem_cache *cachep = NULL, *pc; + struct kmem_cache *cachep = NULL; gfp_t gfp; - /* - * Sanity checks... these are all serious usage bugs. - */ - if (!name || in_interrupt() || (size < BYTES_PER_WORD) || - size > KMALLOC_MAX_SIZE) { - printk(KERN_ERR "%s: Early error in slab %s\n", __func__, - name); - BUG(); - } - - /* - * We use cache_chain_mutex to ensure a consistent view of - * cpu_online_mask as well. Please see cpuup_callback - */ - if (slab_is_available()) { - get_online_cpus(); - mutex_lock(&cache_chain_mutex); - } - - list_for_each_entry(pc, &cache_chain, next) { - char tmp; - int res; - - /* - * This happens when the module gets unloaded and doesn't - * destroy its slab cache and no-one else reuses the vmalloc - * area of the module. Print a warning. - */ - res = probe_kernel_address(pc->name, tmp); - if (res) { - printk(KERN_ERR - "SLAB: cache with size %d has lost its name\n", - pc->buffer_size); - continue; - } - - if (!strcmp(pc->name, name)) { - printk(KERN_ERR - "kmem_cache_create: duplicate cache %s\n", name); - dump_stack(); - goto oops; - } - } - #if DEBUG - WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #if FORCED_DEBUG /* * Enable redzoning and last user accounting, except for caches with @@ -2415,11 +2320,12 @@ kmem_cache_create (const char *name, size_t size, size_t align, /* Get cache's description obj. */ cachep = kmem_cache_zalloc(&cache_cache, gfp); if (!cachep) - goto oops; + return NULL; cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; + cachep->object_size = size; + cachep->align = align; #if DEBUG - cachep->obj_size = size; /* * Both debugging options require word-alignment which is calculated @@ -2442,7 +2348,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { + && cachep->object_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { cachep->obj_offset += PAGE_SIZE - ALIGN(size, align); size = PAGE_SIZE; } @@ -2471,8 +2377,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, printk(KERN_ERR "kmem_cache_create: couldn't create cache %s.\n", name); kmem_cache_free(&cache_cache, cachep); - cachep = NULL; - goto oops; + return NULL; } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab), align); @@ -2508,10 +2413,10 @@ kmem_cache_create (const char *name, size_t size, size_t align, cachep->colour = left_over / cachep->colour_off; cachep->slab_size = slab_size; cachep->flags = flags; - cachep->gfpflags = 0; + cachep->allocflags = 0; if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA)) - cachep->gfpflags |= GFP_DMA; - cachep->buffer_size = size; + cachep->allocflags |= GFP_DMA; + cachep->size = size; cachep->reciprocal_buffer_size = reciprocal_value(size); if (flags & CFLGS_OFF_SLAB) { @@ -2530,8 +2435,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (setup_cpu_cache(cachep, gfp)) { __kmem_cache_destroy(cachep); - cachep = NULL; - goto oops; + return NULL; } if (flags & SLAB_DEBUG_OBJECTS) { @@ -2545,18 +2449,9 @@ kmem_cache_create (const char *name, size_t size, size_t align, } /* cache setup completed, link it into the list */ - list_add(&cachep->next, &cache_chain); -oops: - if (!cachep && (flags & SLAB_PANIC)) - panic("kmem_cache_create(): failed to create slab `%s'\n", - name); - if (slab_is_available()) { - mutex_unlock(&cache_chain_mutex); - put_online_cpus(); - } + list_add(&cachep->list, &slab_caches); return cachep; } -EXPORT_SYMBOL(kmem_cache_create); #if DEBUG static void check_irq_off(void) @@ -2671,7 +2566,7 @@ out: return nr_freed; } -/* Called with cache_chain_mutex held to protect against cpu hotplug */ +/* Called with slab_mutex held to protect against cpu hotplug */ static int __cache_shrink(struct kmem_cache *cachep) { int ret = 0, i = 0; @@ -2706,9 +2601,9 @@ int kmem_cache_shrink(struct kmem_cache *cachep) BUG_ON(!cachep || in_interrupt()); get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = __cache_shrink(cachep); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); return ret; } @@ -2736,15 +2631,15 @@ void kmem_cache_destroy(struct kmem_cache *cachep) /* Find the cache in the chain of caches. */ get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); /* * the chain is never empty, cache_cache is never destroyed */ - list_del(&cachep->next); + list_del(&cachep->list); if (__cache_shrink(cachep)) { slab_error(cachep, "Can't free all objects"); - list_add(&cachep->next, &cache_chain); - mutex_unlock(&cache_chain_mutex); + list_add(&cachep->list, &slab_caches); + mutex_unlock(&slab_mutex); put_online_cpus(); return; } @@ -2753,7 +2648,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep) rcu_barrier(); __kmem_cache_destroy(cachep); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); } EXPORT_SYMBOL(kmem_cache_destroy); @@ -2840,10 +2735,10 @@ static void cache_init_objs(struct kmem_cache *cachep, slab_error(cachep, "constructor overwrote the" " start of an object"); } - if ((cachep->buffer_size % PAGE_SIZE) == 0 && + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); #else if (cachep->ctor) cachep->ctor(objp); @@ -2857,9 +2752,9 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) { if (CONFIG_ZONE_DMA_FLAG) { if (flags & GFP_DMA) - BUG_ON(!(cachep->gfpflags & GFP_DMA)); + BUG_ON(!(cachep->allocflags & GFP_DMA)); else - BUG_ON(cachep->gfpflags & GFP_DMA); + BUG_ON(cachep->allocflags & GFP_DMA); } } @@ -2918,8 +2813,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab, nr_pages <<= cache->gfporder; do { - page_set_cache(page, cache); - page_set_slab(page, slab); + page->slab_cache = cache; + page->slab_page = slab; page++; } while (--nr_pages); } @@ -3057,7 +2952,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, kfree_debugcheck(objp); page = virt_to_head_page(objp); - slabp = page_get_slab(page); + slabp = page->slab_page; if (cachep->flags & SLAB_RED_ZONE) { verify_redzone_free(cachep, objp); @@ -3077,10 +2972,10 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, #endif if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { + if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { store_stackinfo(cachep, objp, (unsigned long)caller); kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); } else { poison_obj(cachep, objp, POISON_FREE); } @@ -3230,9 +3125,9 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, return objp; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -3261,8 +3156,8 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, struct slab *slabp; unsigned objnr; - slabp = page_get_slab(virt_to_head_page(objp)); - objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; + slabp = virt_to_head_page(objp)->slab_page; + objnr = (unsigned)(objp - slabp->s_mem) / cachep->size; slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE; } #endif @@ -3285,7 +3180,7 @@ static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) if (cachep == &cache_cache) return false; - return should_failslab(obj_size(cachep), flags, cachep->flags); + return should_failslab(cachep->object_size, flags, cachep->flags); } static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) @@ -3336,7 +3231,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD)) nid_alloc = cpuset_slab_spread_node(); else if (current->mempolicy) - nid_alloc = slab_node(current->mempolicy); + nid_alloc = slab_node(); if (nid_alloc != nid_here) return ____cache_alloc_node(cachep, flags, nid_alloc); return NULL; @@ -3368,7 +3263,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) retry_cpuset: cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); retry: /* @@ -3545,14 +3440,14 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, out: local_irq_restore(save_flags); ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller); - kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags, flags); if (likely(ptr)) - kmemcheck_slab_alloc(cachep, flags, ptr, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && ptr)) - memset(ptr, 0, obj_size(cachep)); + memset(ptr, 0, cachep->object_size); return ptr; } @@ -3607,15 +3502,15 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) objp = __do_cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller); - kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags, flags); prefetchw(objp); if (likely(objp)) - kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && objp)) - memset(objp, 0, obj_size(cachep)); + memset(objp, 0, cachep->object_size); return objp; } @@ -3731,7 +3626,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, kmemleak_free_recursive(objp, cachep->flags); objp = cache_free_debugcheck(cachep, objp, caller); - kmemcheck_slab_free(cachep, objp, obj_size(cachep)); + kmemcheck_slab_free(cachep, objp, cachep->object_size); /* * Skip calling cache_free_alien() when the platform is not numa. @@ -3766,7 +3661,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); trace_kmem_cache_alloc(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, flags); + cachep->object_size, cachep->size, flags); return ret; } @@ -3794,7 +3689,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) __builtin_return_address(0)); trace_kmem_cache_alloc_node(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, + cachep->object_size, cachep->size, flags, nodeid); return ret; @@ -3876,7 +3771,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, ret = __cache_alloc(cachep, flags, caller); trace_kmalloc((unsigned long) caller, ret, - size, cachep->buffer_size, flags); + size, cachep->size, flags); return ret; } @@ -3916,9 +3811,9 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) unsigned long flags; local_irq_save(flags); - debug_check_no_locks_freed(objp, obj_size(cachep)); + debug_check_no_locks_freed(objp, cachep->object_size); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(objp, obj_size(cachep)); + debug_check_no_obj_freed(objp, cachep->object_size); __cache_free(cachep, objp, __builtin_return_address(0)); local_irq_restore(flags); @@ -3947,8 +3842,9 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); - debug_check_no_locks_freed(objp, obj_size(c)); - debug_check_no_obj_freed(objp, obj_size(c)); + debug_check_no_locks_freed(objp, c->object_size); + + debug_check_no_obj_freed(objp, c->object_size); __cache_free(c, (void *)objp, __builtin_return_address(0)); local_irq_restore(flags); } @@ -3956,7 +3852,7 @@ EXPORT_SYMBOL(kfree); unsigned int kmem_cache_size(struct kmem_cache *cachep) { - return obj_size(cachep); + return cachep->object_size; } EXPORT_SYMBOL(kmem_cache_size); @@ -4030,7 +3926,7 @@ static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp) return 0; fail: - if (!cachep->next.next) { + if (!cachep->list.next) { /* Cache is not active yet. Roll back what we did */ node--; while (node >= 0) { @@ -4065,7 +3961,7 @@ static void do_ccupdate_local(void *info) new->new[smp_processor_id()] = old; } -/* Always called with the cache_chain_mutex held */ +/* Always called with the slab_mutex held */ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared, gfp_t gfp) { @@ -4109,7 +4005,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, return alloc_kmemlist(cachep, gfp); } -/* Called with cache_chain_mutex held always */ +/* Called with slab_mutex held always */ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) { int err; @@ -4124,13 +4020,13 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * The numbers are guessed, we should auto-tune as described by * Bonwick. */ - if (cachep->buffer_size > 131072) + if (cachep->size > 131072) limit = 1; - else if (cachep->buffer_size > PAGE_SIZE) + else if (cachep->size > PAGE_SIZE) limit = 8; - else if (cachep->buffer_size > 1024) + else if (cachep->size > 1024) limit = 24; - else if (cachep->buffer_size > 256) + else if (cachep->size > 256) limit = 54; else limit = 120; @@ -4145,7 +4041,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * to a larger limit. Thus disabled by default. */ shared = 0; - if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1) + if (cachep->size <= PAGE_SIZE && num_possible_cpus() > 1) shared = 8; #if DEBUG @@ -4211,11 +4107,11 @@ static void cache_reap(struct work_struct *w) int node = numa_mem_id(); struct delayed_work *work = to_delayed_work(w); - if (!mutex_trylock(&cache_chain_mutex)) + if (!mutex_trylock(&slab_mutex)) /* Give up. Setup the next iteration. */ goto out; - list_for_each_entry(searchp, &cache_chain, next) { + list_for_each_entry(searchp, &slab_caches, list) { check_irq_on(); /* @@ -4253,7 +4149,7 @@ next: cond_resched(); } check_irq_on(); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); next_reap_node(); out: /* Set up the next iteration */ @@ -4289,26 +4185,26 @@ static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); - return seq_list_start(&cache_chain, *pos); + return seq_list_start(&slab_caches, *pos); } static void *s_next(struct seq_file *m, void *p, loff_t *pos) { - return seq_list_next(p, &cache_chain, pos); + return seq_list_next(p, &slab_caches, pos); } static void s_stop(struct seq_file *m, void *p) { - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) { - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; @@ -4364,7 +4260,7 @@ static int s_show(struct seq_file *m, void *p) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", - name, active_objs, num_objs, cachep->buffer_size, + name, active_objs, num_objs, cachep->size, cachep->num, (1 << cachep->gfporder)); seq_printf(m, " : tunables %4u %4u %4u", cachep->limit, cachep->batchcount, cachep->shared); @@ -4454,9 +4350,9 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, return -EINVAL; /* Find the cache in the chain of caches. */ - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); res = -EINVAL; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4469,7 +4365,7 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, break; } } - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); if (res >= 0) res = count; return res; @@ -4492,8 +4388,8 @@ static const struct file_operations proc_slabinfo_operations = { static void *leaks_start(struct seq_file *m, loff_t *pos) { - mutex_lock(&cache_chain_mutex); - return seq_list_start(&cache_chain, *pos); + mutex_lock(&slab_mutex); + return seq_list_start(&slab_caches, *pos); } static inline int add_caller(unsigned long *n, unsigned long v) @@ -4532,7 +4428,7 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s) int i; if (n[0] == n[1]) return; - for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) { + for (i = 0, p = s->s_mem; i < c->num; i++, p += c->size) { if (slab_bufctl(s)[i] != BUFCTL_ACTIVE) continue; if (!add_caller(n, (unsigned long)*dbg_userword(c, p))) @@ -4558,7 +4454,7 @@ static void show_symbol(struct seq_file *m, unsigned long address) static int leaks_show(struct seq_file *m, void *p) { - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; struct kmem_list3 *l3; const char *name; @@ -4592,17 +4488,17 @@ static int leaks_show(struct seq_file *m, void *p) name = cachep->name; if (n[0] == n[1]) { /* Increase the buffer size */ - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL); if (!m->private) { /* Too bad, we are really out */ m->private = n; - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); return -ENOMEM; } *(unsigned long *)m->private = n[0] * 2; kfree(n); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); /* Now make sure this entry will be retried */ m->count = m->size; return 0; @@ -4677,6 +4573,6 @@ size_t ksize(const void *objp) if (unlikely(objp == ZERO_SIZE_PTR)) return 0; - return obj_size(virt_to_cache(objp)); + return virt_to_cache(objp)->object_size; } EXPORT_SYMBOL(ksize); diff --git a/mm/slab.h b/mm/slab.h new file mode 100644 index 00000000000..db7848caaa2 --- /dev/null +++ b/mm/slab.h @@ -0,0 +1,33 @@ +#ifndef MM_SLAB_H +#define MM_SLAB_H +/* + * Internal slab definitions + */ + +/* + * State of the slab allocator. + * + * This is used to describe the states of the allocator during bootup. + * Allocators use this to gradually bootstrap themselves. Most allocators + * have the problem that the structures used for managing slab caches are + * allocated from slab caches themselves. + */ +enum slab_state { + DOWN, /* No slab functionality yet */ + PARTIAL, /* SLUB: kmem_cache_node available */ + PARTIAL_ARRAYCACHE, /* SLAB: kmalloc size for arraycache available */ + PARTIAL_L3, /* SLAB: kmalloc size for l3 struct available */ + UP, /* Slab caches usable but not all extras yet */ + FULL /* Everything is working */ +}; + +extern enum slab_state slab_state; + +/* The slab cache mutex protects the management structures during changes */ +extern struct mutex slab_mutex; +extern struct list_head slab_caches; + +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)); + +#endif diff --git a/mm/slab_common.c b/mm/slab_common.c new file mode 100644 index 00000000000..aa3ca5bb01b --- /dev/null +++ b/mm/slab_common.c @@ -0,0 +1,120 @@ +/* + * Slab allocator functions that are independent of the allocator strategy + * + * (C) 2012 Christoph Lameter <cl@linux.com> + */ +#include <linux/slab.h> + +#include <linux/mm.h> +#include <linux/poison.h> +#include <linux/interrupt.h> +#include <linux/memory.h> +#include <linux/compiler.h> +#include <linux/module.h> +#include <linux/cpu.h> +#include <linux/uaccess.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> +#include <asm/page.h> + +#include "slab.h" + +enum slab_state slab_state; +LIST_HEAD(slab_caches); +DEFINE_MUTEX(slab_mutex); + +/* + * kmem_cache_create - Create a cache. + * @name: A string which is used in /proc/slabinfo to identify this cache. + * @size: The size of objects to be created in this cache. + * @align: The required alignment for the objects. + * @flags: SLAB flags + * @ctor: A constructor for the objects. + * + * Returns a ptr to the cache on success, NULL on failure. + * Cannot be called within a interrupt, but can be interrupted. + * The @ctor is run when new pages are allocated by the cache. + * + * The flags are + * + * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) + * to catch references to uninitialised memory. + * + * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check + * for buffer overruns. + * + * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware + * cacheline. This can be beneficial if you're counting cycles as closely + * as davem. + */ + +struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, + unsigned long flags, void (*ctor)(void *)) +{ + struct kmem_cache *s = NULL; + +#ifdef CONFIG_DEBUG_VM + if (!name || in_interrupt() || size < sizeof(void *) || + size > KMALLOC_MAX_SIZE) { + printk(KERN_ERR "kmem_cache_create(%s) integrity check" + " failed\n", name); + goto out; + } +#endif + + get_online_cpus(); + mutex_lock(&slab_mutex); + +#ifdef CONFIG_DEBUG_VM + list_for_each_entry(s, &slab_caches, list) { + char tmp; + int res; + + /* + * This happens when the module gets unloaded and doesn't + * destroy its slab cache and no-one else reuses the vmalloc + * area of the module. Print a warning. + */ + res = probe_kernel_address(s->name, tmp); + if (res) { + printk(KERN_ERR + "Slab cache with size %d has lost its name\n", + s->object_size); + continue; + } + + if (!strcmp(s->name, name)) { + printk(KERN_ERR "kmem_cache_create(%s): Cache name" + " already exists.\n", + name); + dump_stack(); + s = NULL; + goto oops; + } + } + + WARN_ON(strchr(name, ' ')); /* It confuses parsers */ +#endif + + s = __kmem_cache_create(name, size, align, flags, ctor); + +#ifdef CONFIG_DEBUG_VM +oops: +#endif + mutex_unlock(&slab_mutex); + put_online_cpus(); + +#ifdef CONFIG_DEBUG_VM +out: +#endif + if (!s && (flags & SLAB_PANIC)) + panic("kmem_cache_create: Failed to create slab '%s'\n", name); + + return s; +} +EXPORT_SYMBOL(kmem_cache_create); + +int slab_is_available(void) +{ + return slab_state >= UP; +} diff --git a/mm/slob.c b/mm/slob.c index 8105be42cad..45d4ca79933 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -59,6 +59,8 @@ #include <linux/kernel.h> #include <linux/slab.h> +#include "slab.h" + #include <linux/mm.h> #include <linux/swap.h> /* struct reclaim_state */ #include <linux/cache.h> @@ -92,36 +94,6 @@ struct slob_block { typedef struct slob_block slob_t; /* - * We use struct page fields to manage some slob allocation aspects, - * however to avoid the horrible mess in include/linux/mm_types.h, we'll - * just define our own struct page type variant here. - */ -struct slob_page { - union { - struct { - unsigned long flags; /* mandatory */ - atomic_t _count; /* mandatory */ - slobidx_t units; /* free units left in page */ - unsigned long pad[2]; - slob_t *free; /* first free slob_t in page */ - struct list_head list; /* linked list of free pages */ - }; - struct page page; - }; -}; -static inline void struct_slob_page_wrong_size(void) -{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); } - -/* - * free_slob_page: call before a slob_page is returned to the page allocator. - */ -static inline void free_slob_page(struct slob_page *sp) -{ - reset_page_mapcount(&sp->page); - sp->page.mapping = NULL; -} - -/* * All partially free slob pages go on these lists. */ #define SLOB_BREAK1 256 @@ -131,46 +103,23 @@ static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); /* - * is_slob_page: True for all slob pages (false for bigblock pages) - */ -static inline int is_slob_page(struct slob_page *sp) -{ - return PageSlab((struct page *)sp); -} - -static inline void set_slob_page(struct slob_page *sp) -{ - __SetPageSlab((struct page *)sp); -} - -static inline void clear_slob_page(struct slob_page *sp) -{ - __ClearPageSlab((struct page *)sp); -} - -static inline struct slob_page *slob_page(const void *addr) -{ - return (struct slob_page *)virt_to_page(addr); -} - -/* * slob_page_free: true for pages on free_slob_pages list. */ -static inline int slob_page_free(struct slob_page *sp) +static inline int slob_page_free(struct page *sp) { - return PageSlobFree((struct page *)sp); + return PageSlobFree(sp); } -static void set_slob_page_free(struct slob_page *sp, struct list_head *list) +static void set_slob_page_free(struct page *sp, struct list_head *list) { list_add(&sp->list, list); - __SetPageSlobFree((struct page *)sp); + __SetPageSlobFree(sp); } -static inline void clear_slob_page_free(struct slob_page *sp) +static inline void clear_slob_page_free(struct page *sp) { list_del(&sp->list); - __ClearPageSlobFree((struct page *)sp); + __ClearPageSlobFree(sp); } #define SLOB_UNIT sizeof(slob_t) @@ -267,12 +216,12 @@ static void slob_free_pages(void *b, int order) /* * Allocate a slob block within a given slob_page sp. */ -static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) +static void *slob_page_alloc(struct page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); - for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { + for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur); if (align) { @@ -296,12 +245,12 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) if (prev) set_slob(prev, slob_units(prev), next); else - sp->free = next; + sp->freelist = next; } else { /* fragment */ if (prev) set_slob(prev, slob_units(prev), cur + units); else - sp->free = cur + units; + sp->freelist = cur + units; set_slob(cur + units, avail - units, next); } @@ -320,7 +269,7 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { - struct slob_page *sp; + struct page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; @@ -341,7 +290,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ - if (node != -1 && page_to_nid(&sp->page) != node) + if (node != -1 && page_to_nid(sp) != node) continue; #endif /* Enough room on this page? */ @@ -369,12 +318,12 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; - sp = slob_page(b); - set_slob_page(sp); + sp = virt_to_page(b); + __SetPageSlab(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); - sp->free = b; + sp->freelist = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); @@ -392,7 +341,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) */ static void slob_free(void *block, int size) { - struct slob_page *sp; + struct page *sp; slob_t *prev, *next, *b = (slob_t *)block; slobidx_t units; unsigned long flags; @@ -402,7 +351,7 @@ static void slob_free(void *block, int size) return; BUG_ON(!size); - sp = slob_page(block); + sp = virt_to_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); @@ -412,8 +361,8 @@ static void slob_free(void *block, int size) if (slob_page_free(sp)) clear_slob_page_free(sp); spin_unlock_irqrestore(&slob_lock, flags); - clear_slob_page(sp); - free_slob_page(sp); + __ClearPageSlab(sp); + reset_page_mapcount(sp); slob_free_pages(b, 0); return; } @@ -421,7 +370,7 @@ static void slob_free(void *block, int size) if (!slob_page_free(sp)) { /* This slob page is about to become partially free. Easy! */ sp->units = units; - sp->free = b; + sp->freelist = b; set_slob(b, units, (void *)((unsigned long)(b + SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); @@ -441,15 +390,15 @@ static void slob_free(void *block, int size) */ sp->units += units; - if (b < sp->free) { - if (b + units == sp->free) { - units += slob_units(sp->free); - sp->free = slob_next(sp->free); + if (b < (slob_t *)sp->freelist) { + if (b + units == sp->freelist) { + units += slob_units(sp->freelist); + sp->freelist = slob_next(sp->freelist); } - set_slob(b, units, sp->free); - sp->free = b; + set_slob(b, units, sp->freelist); + sp->freelist = b; } else { - prev = sp->free; + prev = sp->freelist; next = slob_next(prev); while (b > next) { prev = next; @@ -522,7 +471,7 @@ EXPORT_SYMBOL(__kmalloc_node); void kfree(const void *block) { - struct slob_page *sp; + struct page *sp; trace_kfree(_RET_IP_, block); @@ -530,43 +479,36 @@ void kfree(const void *block) return; kmemleak_free(block); - sp = slob_page(block); - if (is_slob_page(sp)) { + sp = virt_to_page(block); + if (PageSlab(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); } else - put_page(&sp->page); + put_page(sp); } EXPORT_SYMBOL(kfree); /* can't use ksize for kmem_cache_alloc memory, only kmalloc */ size_t ksize(const void *block) { - struct slob_page *sp; + struct page *sp; BUG_ON(!block); if (unlikely(block == ZERO_SIZE_PTR)) return 0; - sp = slob_page(block); - if (is_slob_page(sp)) { + sp = virt_to_page(block); + if (PageSlab(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); return SLOB_UNITS(*m) * SLOB_UNIT; } else - return sp->page.private; + return sp->private; } EXPORT_SYMBOL(ksize); -struct kmem_cache { - unsigned int size, align; - unsigned long flags; - const char *name; - void (*ctor)(void *); -}; - -struct kmem_cache *kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *c; @@ -589,13 +531,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, c->align = ARCH_SLAB_MINALIGN; if (c->align < align) c->align = align; - } else if (flags & SLAB_PANIC) - panic("Cannot create slab cache %s\n", name); - kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + c->refcount = 1; + } return c; } -EXPORT_SYMBOL(kmem_cache_create); void kmem_cache_destroy(struct kmem_cache *c) { @@ -678,19 +619,12 @@ int kmem_cache_shrink(struct kmem_cache *d) } EXPORT_SYMBOL(kmem_cache_shrink); -static unsigned int slob_ready __read_mostly; - -int slab_is_available(void) -{ - return slob_ready; -} - void __init kmem_cache_init(void) { - slob_ready = 1; + slab_state = UP; } void __init kmem_cache_init_late(void) { - /* Nothing to do */ + slab_state = FULL; } diff --git a/mm/slub.c b/mm/slub.c index 8c691fa1cf3..e517d435e5d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/bitops.h> #include <linux/slab.h> +#include "slab.h" #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/kmemcheck.h> @@ -35,13 +36,13 @@ /* * Lock order: - * 1. slub_lock (Global Semaphore) + * 1. slab_mutex (Global Mutex) * 2. node->list_lock * 3. slab_lock(page) (Only on some arches and for debugging) * - * slub_lock + * slab_mutex * - * The role of the slub_lock is to protect the list of all the slabs + * The role of the slab_mutex is to protect the list of all the slabs * and to synchronize major metadata changes to slab cache structures. * * The slab_lock is only used for debugging and on arches that do not @@ -182,17 +183,6 @@ static int kmem_size = sizeof(struct kmem_cache); static struct notifier_block slab_notifier; #endif -static enum { - DOWN, /* No slab functionality available */ - PARTIAL, /* Kmem_cache_node works */ - UP, /* Everything works but does not show up in sysfs */ - SYSFS /* Sysfs up */ -} slab_state = DOWN; - -/* A list of all slab caches on the system */ -static DECLARE_RWSEM(slub_lock); -static LIST_HEAD(slab_caches); - /* * Tracking user of a slab. */ @@ -237,11 +227,6 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si) * Core slab cache functions *******************************************************************/ -int slab_is_available(void) -{ - return slab_state >= UP; -} - static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node) { return s->node[node]; @@ -311,7 +296,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s) * and whatever may come after it. */ if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->objsize; + return s->object_size; #endif /* @@ -609,11 +594,11 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) if (p > addr + 16) print_section("Bytes b4 ", p - 16, 16); - print_section("Object ", p, min_t(unsigned long, s->objsize, + print_section("Object ", p, min_t(unsigned long, s->object_size, PAGE_SIZE)); if (s->flags & SLAB_RED_ZONE) - print_section("Redzone ", p + s->objsize, - s->inuse - s->objsize); + print_section("Redzone ", p + s->object_size, + s->inuse - s->object_size); if (s->offset) off = s->offset + sizeof(void *); @@ -655,12 +640,12 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) u8 *p = object; if (s->flags & __OBJECT_POISON) { - memset(p, POISON_FREE, s->objsize - 1); - p[s->objsize - 1] = POISON_END; + memset(p, POISON_FREE, s->object_size - 1); + p[s->object_size - 1] = POISON_END; } if (s->flags & SLAB_RED_ZONE) - memset(p + s->objsize, val, s->inuse - s->objsize); + memset(p + s->object_size, val, s->inuse - s->object_size); } static void restore_bytes(struct kmem_cache *s, char *message, u8 data, @@ -705,10 +690,10 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * Poisoning uses 0x6b (POISON_FREE) and the last byte is * 0xa5 (POISON_END) * - * object + s->objsize + * object + s->object_size * Padding to reach word boundary. This is also used for Redzoning. * Padding is extended by another word if Redzoning is enabled and - * objsize == inuse. + * object_size == inuse. * * We fill with 0xbb (RED_INACTIVE) for inactive objects and with * 0xcc (RED_ACTIVE) for objects in use. @@ -727,7 +712,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * object + s->size * Nothing is used beyond s->size. * - * If slabcaches are merged then the objsize and inuse boundaries are mostly + * If slabcaches are merged then the object_size and inuse boundaries are mostly * ignored. And therefore no slab options that rely on these boundaries * may be used with merged slabcaches. */ @@ -787,25 +772,25 @@ static int check_object(struct kmem_cache *s, struct page *page, void *object, u8 val) { u8 *p = object; - u8 *endobject = object + s->objsize; + u8 *endobject = object + s->object_size; if (s->flags & SLAB_RED_ZONE) { if (!check_bytes_and_report(s, page, object, "Redzone", - endobject, val, s->inuse - s->objsize)) + endobject, val, s->inuse - s->object_size)) return 0; } else { - if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) { + if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) { check_bytes_and_report(s, page, p, "Alignment padding", - endobject, POISON_INUSE, s->inuse - s->objsize); + endobject, POISON_INUSE, s->inuse - s->object_size); } } if (s->flags & SLAB_POISON) { if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) && (!check_bytes_and_report(s, page, p, "Poison", p, - POISON_FREE, s->objsize - 1) || + POISON_FREE, s->object_size - 1) || !check_bytes_and_report(s, page, p, "Poison", - p + s->objsize - 1, POISON_END, 1))) + p + s->object_size - 1, POISON_END, 1))) return 0; /* * check_pad_bytes cleans up on its own. @@ -926,7 +911,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object, page->freelist); if (!alloc) - print_section("Object ", (void *)object, s->objsize); + print_section("Object ", (void *)object, s->object_size); dump_stack(); } @@ -942,14 +927,14 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) lockdep_trace_alloc(flags); might_sleep_if(flags & __GFP_WAIT); - return should_failslab(s->objsize, flags, s->flags); + return should_failslab(s->object_size, flags, s->flags); } static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; kmemcheck_slab_alloc(s, flags, object, slab_ksize(s)); - kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags); + kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags); } static inline void slab_free_hook(struct kmem_cache *s, void *x) @@ -966,13 +951,13 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) unsigned long flags; local_irq_save(flags); - kmemcheck_slab_free(s, x, s->objsize); - debug_check_no_locks_freed(x, s->objsize); + kmemcheck_slab_free(s, x, s->object_size); + debug_check_no_locks_freed(x, s->object_size); local_irq_restore(flags); } #endif if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(x, s->objsize); + debug_check_no_obj_freed(x, s->object_size); } /* @@ -1207,7 +1192,7 @@ out: __setup("slub_debug", setup_slub_debug); -static unsigned long kmem_cache_flags(unsigned long objsize, +static unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1237,7 +1222,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page, static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} static inline void remove_full(struct kmem_cache *s, struct page *page) {} -static inline unsigned long kmem_cache_flags(unsigned long objsize, +static inline unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1314,13 +1299,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) stat(s, ORDER_FALLBACK); } - if (flags & __GFP_WAIT) - local_irq_disable(); - - if (!page) - return NULL; - - if (kmemcheck_enabled + if (kmemcheck_enabled && page && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) { int pages = 1 << oo_order(oo); @@ -1336,6 +1315,11 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) kmemcheck_mark_unallocated_pages(page, pages); } + if (flags & __GFP_WAIT) + local_irq_disable(); + if (!page) + return NULL; + page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? @@ -1490,12 +1474,12 @@ static inline void remove_partial(struct kmem_cache_node *n, } /* - * Lock slab, remove from the partial list and put the object into the - * per cpu freelist. + * Remove slab from the partial list, freeze it and + * return the pointer to the freelist. * * Returns a list of objects or NULL if it fails. * - * Must hold list_lock. + * Must hold list_lock since we modify the partial list. */ static inline void *acquire_slab(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page, @@ -1510,26 +1494,27 @@ static inline void *acquire_slab(struct kmem_cache *s, * The old freelist is the list of objects for the * per cpu allocation list. */ - do { - freelist = page->freelist; - counters = page->counters; - new.counters = counters; - if (mode) { - new.inuse = page->objects; - new.freelist = NULL; - } else { - new.freelist = freelist; - } + freelist = page->freelist; + counters = page->counters; + new.counters = counters; + if (mode) { + new.inuse = page->objects; + new.freelist = NULL; + } else { + new.freelist = freelist; + } - VM_BUG_ON(new.frozen); - new.frozen = 1; + VM_BUG_ON(new.frozen); + new.frozen = 1; - } while (!__cmpxchg_double_slab(s, page, + if (!__cmpxchg_double_slab(s, page, freelist, counters, new.freelist, new.counters, - "lock and freeze")); + "acquire_slab")) + return NULL; remove_partial(n, page); + WARN_ON(!freelist); return freelist; } @@ -1563,7 +1548,6 @@ static void *get_partial_node(struct kmem_cache *s, if (!object) { c->page = page; - c->node = page_to_nid(page); stat(s, ALLOC_FROM_PARTIAL); object = t; available = page->objects - page->inuse; @@ -1617,7 +1601,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags, do { cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { struct kmem_cache_node *n; @@ -1731,14 +1715,12 @@ void init_kmem_cache_cpus(struct kmem_cache *s) /* * Remove the cpu slab */ -static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) +static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist) { enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; - struct page *page = c->page; struct kmem_cache_node *n = get_node(s, page_to_nid(page)); int lock = 0; enum slab_modes l = M_NONE, m = M_NONE; - void *freelist; void *nextfree; int tail = DEACTIVATE_TO_HEAD; struct page new; @@ -1749,11 +1731,6 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) tail = DEACTIVATE_TO_TAIL; } - c->tid = next_tid(c->tid); - c->page = NULL; - freelist = c->freelist; - c->freelist = NULL; - /* * Stage one: Free all available per cpu objects back * to the page freelist while it is still frozen. Leave the @@ -1879,21 +1856,31 @@ redo: } } -/* Unfreeze all the cpu partial slabs */ +/* + * Unfreeze all the cpu partial slabs. + * + * This function must be called with interrupt disabled. + */ static void unfreeze_partials(struct kmem_cache *s) { - struct kmem_cache_node *n = NULL; + struct kmem_cache_node *n = NULL, *n2 = NULL; struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); struct page *page, *discard_page = NULL; while ((page = c->partial)) { - enum slab_modes { M_PARTIAL, M_FREE }; - enum slab_modes l, m; struct page new; struct page old; c->partial = page->next; - l = M_FREE; + + n2 = get_node(s, page_to_nid(page)); + if (n != n2) { + if (n) + spin_unlock(&n->list_lock); + + n = n2; + spin_lock(&n->list_lock); + } do { @@ -1906,43 +1893,17 @@ static void unfreeze_partials(struct kmem_cache *s) new.frozen = 0; - if (!new.inuse && (!n || n->nr_partial > s->min_partial)) - m = M_FREE; - else { - struct kmem_cache_node *n2 = get_node(s, - page_to_nid(page)); - - m = M_PARTIAL; - if (n != n2) { - if (n) - spin_unlock(&n->list_lock); - - n = n2; - spin_lock(&n->list_lock); - } - } - - if (l != m) { - if (l == M_PARTIAL) { - remove_partial(n, page); - stat(s, FREE_REMOVE_PARTIAL); - } else { - add_partial(n, page, - DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); - } - - l = m; - } - - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, old.freelist, old.counters, new.freelist, new.counters, "unfreezing slab")); - if (m == M_FREE) { + if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) { page->next = discard_page; discard_page = page; + } else { + add_partial(n, page, DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); } } @@ -2011,7 +1972,11 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { stat(s, CPUSLAB_FLUSH); - deactivate_slab(s, c); + deactivate_slab(s, c->page, c->freelist); + + c->tid = next_tid(c->tid); + c->page = NULL; + c->freelist = NULL; } /* @@ -2055,10 +2020,10 @@ static void flush_all(struct kmem_cache *s) * Check if the objects in a per cpu structure fit numa * locality expectations. */ -static inline int node_match(struct kmem_cache_cpu *c, int node) +static inline int node_match(struct page *page, int node) { #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE && c->node != node) + if (node != NUMA_NO_NODE && page_to_nid(page) != node) return 0; #endif return 1; @@ -2101,10 +2066,10 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) "SLUB: Unable to allocate memory on node %d (gfp=0x%x)\n", nid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, buffer size: %d, " - "default order: %d, min order: %d\n", s->name, s->objsize, + "default order: %d, min order: %d\n", s->name, s->object_size, s->size, oo_order(s->oo), oo_order(s->min)); - if (oo_order(s->min) > get_order(s->objsize)) + if (oo_order(s->min) > get_order(s->object_size)) printk(KERN_WARNING " %s debugging increased min order, use " "slub_debug=O to disable.\n", s->name); @@ -2130,10 +2095,16 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { - void *object; - struct kmem_cache_cpu *c; - struct page *page = new_slab(s, flags, node); + void *freelist; + struct kmem_cache_cpu *c = *pc; + struct page *page; + + freelist = get_partial(s, flags, node, c); + if (freelist) + return freelist; + + page = new_slab(s, flags, node); if (page) { c = __this_cpu_ptr(s->cpu_slab); if (c->page) @@ -2143,17 +2114,16 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * No other reference to the page yet so we can * muck around with it freely without cmpxchg */ - object = page->freelist; + freelist = page->freelist; page->freelist = NULL; stat(s, ALLOC_SLAB); - c->node = page_to_nid(page); c->page = page; *pc = c; } else - object = NULL; + freelist = NULL; - return object; + return freelist; } /* @@ -2163,6 +2133,8 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * The page is still frozen if the return value is not NULL. * * If this function returns NULL then the page has been unfrozen. + * + * This function must be called with interrupt disabled. */ static inline void *get_freelist(struct kmem_cache *s, struct page *page) { @@ -2173,13 +2145,14 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) do { freelist = page->freelist; counters = page->counters; + new.counters = counters; VM_BUG_ON(!new.frozen); new.inuse = page->objects; new.frozen = freelist != NULL; - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, freelist, counters, NULL, new.counters, "get_freelist")); @@ -2206,7 +2179,8 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { - void **object; + void *freelist; + struct page *page; unsigned long flags; local_irq_save(flags); @@ -2219,25 +2193,29 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, c = this_cpu_ptr(s->cpu_slab); #endif - if (!c->page) + page = c->page; + if (!page) goto new_slab; redo: - if (unlikely(!node_match(c, node))) { + + if (unlikely(!node_match(page, node))) { stat(s, ALLOC_NODE_MISMATCH); - deactivate_slab(s, c); + deactivate_slab(s, page, c->freelist); + c->page = NULL; + c->freelist = NULL; goto new_slab; } /* must check again c->freelist in case of cpu migration or IRQ */ - object = c->freelist; - if (object) + freelist = c->freelist; + if (freelist) goto load_freelist; stat(s, ALLOC_SLOWPATH); - object = get_freelist(s, c->page); + freelist = get_freelist(s, page); - if (!object) { + if (!freelist) { c->page = NULL; stat(s, DEACTIVATE_BYPASS); goto new_slab; @@ -2246,50 +2224,50 @@ redo: stat(s, ALLOC_REFILL); load_freelist: - c->freelist = get_freepointer(s, object); + /* + * freelist is pointing to the list of objects to be used. + * page is pointing to the page from which the objects are obtained. + * That page must be frozen for per cpu allocations to work. + */ + VM_BUG_ON(!c->page->frozen); + c->freelist = get_freepointer(s, freelist); c->tid = next_tid(c->tid); local_irq_restore(flags); - return object; + return freelist; new_slab: if (c->partial) { - c->page = c->partial; - c->partial = c->page->next; - c->node = page_to_nid(c->page); + page = c->page = c->partial; + c->partial = page->next; stat(s, CPU_PARTIAL_ALLOC); c->freelist = NULL; goto redo; } - /* Then do expensive stuff like retrieving pages from the partial lists */ - object = get_partial(s, gfpflags, node, c); + freelist = new_slab_objects(s, gfpflags, node, &c); - if (unlikely(!object)) { + if (unlikely(!freelist)) { + if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) + slab_out_of_memory(s, gfpflags, node); - object = new_slab_objects(s, gfpflags, node, &c); - - if (unlikely(!object)) { - if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) - slab_out_of_memory(s, gfpflags, node); - - local_irq_restore(flags); - return NULL; - } + local_irq_restore(flags); + return NULL; } + page = c->page; if (likely(!kmem_cache_debug(s))) goto load_freelist; /* Only entered in the debug case */ - if (!alloc_debug_processing(s, c->page, object, addr)) + if (!alloc_debug_processing(s, page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - c->freelist = get_freepointer(s, object); - deactivate_slab(s, c); - c->node = NUMA_NO_NODE; + deactivate_slab(s, page, get_freepointer(s, freelist)); + c->page = NULL; + c->freelist = NULL; local_irq_restore(flags); - return object; + return freelist; } /* @@ -2307,6 +2285,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, { void **object; struct kmem_cache_cpu *c; + struct page *page; unsigned long tid; if (slab_pre_alloc_hook(s, gfpflags)) @@ -2332,7 +2311,8 @@ redo: barrier(); object = c->freelist; - if (unlikely(!object || !node_match(c, node))) + page = c->page; + if (unlikely(!object || !node_match(page, node))) object = __slab_alloc(s, gfpflags, node, addr, c); @@ -2364,7 +2344,7 @@ redo: } if (unlikely(gfpflags & __GFP_ZERO) && object) - memset(object, 0, s->objsize); + memset(object, 0, s->object_size); slab_post_alloc_hook(s, gfpflags, object); @@ -2375,7 +2355,7 @@ void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) { void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); - trace_kmem_cache_alloc(_RET_IP_, ret, s->objsize, s->size, gfpflags); + trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags); return ret; } @@ -2405,7 +2385,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); trace_kmem_cache_alloc_node(_RET_IP_, ret, - s->objsize, s->size, gfpflags, node); + s->object_size, s->size, gfpflags, node); return ret; } @@ -2900,7 +2880,7 @@ static void set_min_partial(struct kmem_cache *s, unsigned long min) static int calculate_sizes(struct kmem_cache *s, int forced_order) { unsigned long flags = s->flags; - unsigned long size = s->objsize; + unsigned long size = s->object_size; unsigned long align = s->align; int order; @@ -2929,7 +2909,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * end of the object and the free pointer. If not then add an * additional word to have some bytes to store Redzone information. */ - if ((flags & SLAB_RED_ZONE) && size == s->objsize) + if ((flags & SLAB_RED_ZONE) && size == s->object_size) size += sizeof(void *); #endif @@ -2977,7 +2957,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * user specified and the dynamic determination of cache line size * on bootup. */ - align = calculate_alignment(flags, align, s->objsize); + align = calculate_alignment(flags, align, s->object_size); s->align = align; /* @@ -3025,7 +3005,7 @@ static int kmem_cache_open(struct kmem_cache *s, memset(s, 0, kmem_size); s->name = name; s->ctor = ctor; - s->objsize = size; + s->object_size = size; s->align = align; s->flags = kmem_cache_flags(size, flags, name, ctor); s->reserved = 0; @@ -3040,7 +3020,7 @@ static int kmem_cache_open(struct kmem_cache *s, * Disable debugging flags that store metadata if the min slab * order increased. */ - if (get_order(s->size) > get_order(s->objsize)) { + if (get_order(s->size) > get_order(s->object_size)) { s->flags &= ~DEBUG_METADATA_FLAGS; s->offset = 0; if (!calculate_sizes(s, -1)) @@ -3114,7 +3094,7 @@ error: */ unsigned int kmem_cache_size(struct kmem_cache *s) { - return s->objsize; + return s->object_size; } EXPORT_SYMBOL(kmem_cache_size); @@ -3192,11 +3172,11 @@ static inline int kmem_cache_close(struct kmem_cache *s) */ void kmem_cache_destroy(struct kmem_cache *s) { - down_write(&slub_lock); + mutex_lock(&slab_mutex); s->refcount--; if (!s->refcount) { list_del(&s->list); - up_write(&slub_lock); + mutex_unlock(&slab_mutex); if (kmem_cache_close(s)) { printk(KERN_ERR "SLUB %s: %s called for cache that " "still has objects.\n", s->name, __func__); @@ -3206,7 +3186,7 @@ void kmem_cache_destroy(struct kmem_cache *s) rcu_barrier(); sysfs_slab_remove(s); } else - up_write(&slub_lock); + mutex_unlock(&slab_mutex); } EXPORT_SYMBOL(kmem_cache_destroy); @@ -3268,7 +3248,7 @@ static struct kmem_cache *__init create_kmalloc_cache(const char *name, /* * This function is called with IRQs disabled during early-boot on - * single CPU so there's no need to take slub_lock here. + * single CPU so there's no need to take slab_mutex here. */ if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, flags, NULL)) @@ -3553,10 +3533,10 @@ static int slab_mem_going_offline_callback(void *arg) { struct kmem_cache *s; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) kmem_cache_shrink(s); - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return 0; } @@ -3577,7 +3557,7 @@ static void slab_mem_offline_callback(void *arg) if (offline_node < 0) return; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { n = get_node(s, offline_node); if (n) { @@ -3593,7 +3573,7 @@ static void slab_mem_offline_callback(void *arg) kmem_cache_free(kmem_cache_node, n); } } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); } static int slab_mem_going_online_callback(void *arg) @@ -3616,7 +3596,7 @@ static int slab_mem_going_online_callback(void *arg) * allocate a kmem_cache_node structure in order to bring the node * online. */ - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { /* * XXX: kmem_cache_alloc_node will fallback to other nodes @@ -3632,7 +3612,7 @@ static int slab_mem_going_online_callback(void *arg) s->node[nid] = n; } out: - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return ret; } @@ -3843,11 +3823,11 @@ void __init kmem_cache_init(void) if (s && s->size) { char *name = kasprintf(GFP_NOWAIT, - "dma-kmalloc-%d", s->objsize); + "dma-kmalloc-%d", s->object_size); BUG_ON(!name); kmalloc_dma_caches[i] = create_kmalloc_cache(name, - s->objsize, SLAB_CACHE_DMA); + s->object_size, SLAB_CACHE_DMA); } } #endif @@ -3924,16 +3904,12 @@ static struct kmem_cache *find_mergeable(size_t size, return NULL; } -struct kmem_cache *kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s; char *n; - if (WARN_ON(!name)) - return NULL; - - down_write(&slub_lock); s = find_mergeable(size, align, flags, name, ctor); if (s) { s->refcount++; @@ -3941,49 +3917,42 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, * Adjust the object sizes so that we clear * the complete object on kzalloc. */ - s->objsize = max(s->objsize, (int)size); + s->object_size = max(s->object_size, (int)size); s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); if (sysfs_slab_alias(s, name)) { s->refcount--; - goto err; + return NULL; } - up_write(&slub_lock); return s; } n = kstrdup(name, GFP_KERNEL); if (!n) - goto err; + return NULL; s = kmalloc(kmem_size, GFP_KERNEL); if (s) { if (kmem_cache_open(s, n, size, align, flags, ctor)) { + int r; + list_add(&s->list, &slab_caches); - up_write(&slub_lock); - if (sysfs_slab_add(s)) { - down_write(&slub_lock); - list_del(&s->list); - kfree(n); - kfree(s); - goto err; - } - return s; + mutex_unlock(&slab_mutex); + r = sysfs_slab_add(s); + mutex_lock(&slab_mutex); + + if (!r) + return s; + + list_del(&s->list); + kmem_cache_close(s); } kfree(s); } kfree(n); -err: - up_write(&slub_lock); - - if (flags & SLAB_PANIC) - panic("Cannot create slabcache %s\n", name); - else - s = NULL; - return s; + return NULL; } -EXPORT_SYMBOL(kmem_cache_create); #ifdef CONFIG_SMP /* @@ -4002,13 +3971,13 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { local_irq_save(flags); __flush_cpu_slab(s, cpu); local_irq_restore(flags); } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); break; default: break; @@ -4500,30 +4469,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, for_each_possible_cpu(cpu) { struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); - int node = ACCESS_ONCE(c->node); + int node; struct page *page; - if (node < 0) - continue; page = ACCESS_ONCE(c->page); - if (page) { - if (flags & SO_TOTAL) - x = page->objects; - else if (flags & SO_OBJECTS) - x = page->inuse; - else - x = 1; + if (!page) + continue; - total += x; - nodes[node] += x; - } - page = c->partial; + node = page_to_nid(page); + if (flags & SO_TOTAL) + x = page->objects; + else if (flags & SO_OBJECTS) + x = page->inuse; + else + x = 1; + total += x; + nodes[node] += x; + + page = ACCESS_ONCE(c->partial); if (page) { x = page->pobjects; total += x; nodes[node] += x; } + per_cpu[node]++; } } @@ -4623,7 +4593,7 @@ SLAB_ATTR_RO(align); static ssize_t object_size_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->objsize); + return sprintf(buf, "%d\n", s->object_size); } SLAB_ATTR_RO(object_size); @@ -5286,7 +5256,7 @@ static int sysfs_slab_add(struct kmem_cache *s) const char *name; int unmergeable; - if (slab_state < SYSFS) + if (slab_state < FULL) /* Defer until later */ return 0; @@ -5331,7 +5301,7 @@ static int sysfs_slab_add(struct kmem_cache *s) static void sysfs_slab_remove(struct kmem_cache *s) { - if (slab_state < SYSFS) + if (slab_state < FULL) /* * Sysfs has not been setup yet so no need to remove the * cache from sysfs. @@ -5359,7 +5329,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; - if (slab_state == SYSFS) { + if (slab_state == FULL) { /* * If we have a leftover link then remove it. */ @@ -5383,16 +5353,16 @@ static int __init slab_sysfs_init(void) struct kmem_cache *s; int err; - down_write(&slub_lock); + mutex_lock(&slab_mutex); slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); if (!slab_kset) { - up_write(&slub_lock); + mutex_unlock(&slab_mutex); printk(KERN_ERR "Cannot register slab subsystem.\n"); return -ENOSYS; } - slab_state = SYSFS; + slab_state = FULL; list_for_each_entry(s, &slab_caches, list) { err = sysfs_slab_add(s); @@ -5408,11 +5378,11 @@ static int __init slab_sysfs_init(void) err = sysfs_slab_alias(al->s, al->name); if (err) printk(KERN_ERR "SLUB: Unable to add boot slab alias" - " %s to sysfs\n", s->name); + " %s to sysfs\n", al->name); kfree(al); } - up_write(&slub_lock); + mutex_unlock(&slab_mutex); resiliency_test(); return 0; } @@ -5427,7 +5397,7 @@ __initcall(slab_sysfs_init); static void print_slabinfo_header(struct seq_file *m) { seq_puts(m, "slabinfo - version: 2.1\n"); - seq_puts(m, "# name <active_objs> <num_objs> <objsize> " + seq_puts(m, "# name <active_objs> <num_objs> <object_size> " "<objperslab> <pagesperslab>"); seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); @@ -5438,7 +5408,7 @@ static void *s_start(struct seq_file *m, loff_t *pos) { loff_t n = *pos; - down_read(&slub_lock); + mutex_lock(&slab_mutex); if (!n) print_slabinfo_header(m); @@ -5452,7 +5422,7 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos) static void s_stop(struct seq_file *m, void *p) { - up_read(&slub_lock); + mutex_unlock(&slab_mutex); } static int s_show(struct seq_file *m, void *p) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index c7ac8e1b3ac..e03f4c7307a 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1280,7 +1280,7 @@ DEFINE_RWLOCK(vmlist_lock); struct vm_struct *vmlist; static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, - unsigned long flags, void *caller) + unsigned long flags, const void *caller) { vm->flags = flags; vm->addr = (void *)va->va_start; @@ -1306,7 +1306,7 @@ static void insert_vmalloc_vmlist(struct vm_struct *vm) } static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, - unsigned long flags, void *caller) + unsigned long flags, const void *caller) { setup_vmalloc_vm(vm, va, flags, caller); insert_vmalloc_vmlist(vm); @@ -1314,7 +1314,7 @@ static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long align, unsigned long flags, unsigned long start, - unsigned long end, int node, gfp_t gfp_mask, void *caller) + unsigned long end, int node, gfp_t gfp_mask, const void *caller) { struct vmap_area *va; struct vm_struct *area; @@ -1375,7 +1375,7 @@ EXPORT_SYMBOL_GPL(__get_vm_area); struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags, unsigned long start, unsigned long end, - void *caller) + const void *caller) { return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL, caller); @@ -1397,13 +1397,21 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags) } struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags, - void *caller) + const void *caller) { return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END, -1, GFP_KERNEL, caller); } -static struct vm_struct *find_vm_area(const void *addr) +/** + * find_vm_area - find a continuous kernel virtual area + * @addr: base address + * + * Search for the kernel VM area starting at @addr, and return it. + * It is up to the caller to do all required locking to keep the returned + * pointer valid. + */ +struct vm_struct *find_vm_area(const void *addr) { struct vmap_area *va; @@ -1568,9 +1576,9 @@ EXPORT_SYMBOL(vmap); static void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, pgprot_t prot, - int node, void *caller); + int node, const void *caller); static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller) + pgprot_t prot, int node, const void *caller) { const int order = 0; struct page **pages; @@ -1643,7 +1651,7 @@ fail: */ void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long start, unsigned long end, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller) + pgprot_t prot, int node, const void *caller) { struct vm_struct *area; void *addr; @@ -1699,7 +1707,7 @@ fail: */ static void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, pgprot_t prot, - int node, void *caller) + int node, const void *caller) { return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END, gfp_mask, prot, node, caller); diff --git a/scripts/coccinelle/iterators/use_after_iter.cocci b/scripts/coccinelle/iterators/use_after_iter.cocci new file mode 100644 index 00000000000..06284c57a95 --- /dev/null +++ b/scripts/coccinelle/iterators/use_after_iter.cocci @@ -0,0 +1,147 @@ +/// If list_for_each_entry, etc complete a traversal of the list, the iterator +/// variable ends up pointing to an address at an offset from the list head, +/// and not a meaningful structure. Thus this value should not be used after +/// the end of the iterator. +//#False positives arise when there is a goto in the iterator and the +//#reported reference is at the label of this goto. Some flag tests +//#may also cause a report to be a false positive. +/// +// Confidence: Moderate +// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2. +// Copyright: (C) 2012 Gilles Muller, INRIA/LIP6. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: -no_includes -include_headers + +virtual context +virtual org +virtual report + +@r exists@ +identifier c,member; +expression E,x; +iterator name list_for_each_entry; +iterator name list_for_each_entry_reverse; +iterator name list_for_each_entry_continue; +iterator name list_for_each_entry_continue_reverse; +iterator name list_for_each_entry_from; +iterator name list_for_each_entry_safe; +iterator name list_for_each_entry_safe_continue; +iterator name list_for_each_entry_safe_from; +iterator name list_for_each_entry_safe_reverse; +iterator name hlist_for_each_entry; +iterator name hlist_for_each_entry_continue; +iterator name hlist_for_each_entry_from; +iterator name hlist_for_each_entry_safe; +statement S; +position p1,p2; +@@ + +( +list_for_each_entry@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_reverse@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_continue@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_continue_reverse@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_from@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_safe@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_safe_continue@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_safe_from@p1(c,...,member) { ... when != break; + when forall + when strict +} +| +list_for_each_entry_safe_reverse@p1(c,...,member) { ... when != break; + when forall + when strict +} +) +... +( +list_for_each_entry(c,...) S +| +list_for_each_entry_reverse(c,...) S +| +list_for_each_entry_continue(c,...) S +| +list_for_each_entry_continue_reverse(c,...) S +| +list_for_each_entry_from(c,...) S +| +list_for_each_entry_safe(c,...) S +| +list_for_each_entry_safe(x,c,...) S +| +list_for_each_entry_safe_continue(c,...) S +| +list_for_each_entry_safe_continue(x,c,...) S +| +list_for_each_entry_safe_from(c,...) S +| +list_for_each_entry_safe_from(x,c,...) S +| +list_for_each_entry_safe_reverse(c,...) S +| +list_for_each_entry_safe_reverse(x,c,...) S +| +hlist_for_each_entry(c,...) S +| +hlist_for_each_entry_continue(c,...) S +| +hlist_for_each_entry_from(c,...) S +| +hlist_for_each_entry_safe(c,...) S +| +list_remove_head(x,c,...) +| +sizeof(<+...c...+>) +| +&c->member +| +c = E +| +*c@p2 +) + +@script:python depends on org@ +p1 << r.p1; +p2 << r.p2; +@@ + +cocci.print_main("invalid iterator index reference",p2) +cocci.print_secs("iterator",p1) + +@script:python depends on report@ +p1 << r.p1; +p2 << r.p2; +@@ + +msg = "ERROR: invalid reference to the index variable of the iterator on line %s" % (p1[0].line) +coccilib.report.print_report(p2[0], msg) diff --git a/scripts/coccinelle/misc/irqf_oneshot.cocci b/scripts/coccinelle/misc/irqf_oneshot.cocci new file mode 100644 index 00000000000..6cfde94be0e --- /dev/null +++ b/scripts/coccinelle/misc/irqf_oneshot.cocci @@ -0,0 +1,65 @@ +/// Make sure threaded IRQs without a primary handler are always request with +/// IRQF_ONESHOT +/// +// +// Confidence: Good +// Comments: +// Options: --no-includes + +virtual patch +virtual context +virtual org +virtual report + +@r1@ +expression irq; +expression thread_fn; +expression flags; +position p; +@@ +request_threaded_irq@p(irq, NULL, thread_fn, +( +flags | IRQF_ONESHOT +| +IRQF_ONESHOT +) +, ...) + +@depends on patch@ +expression irq; +expression thread_fn; +expression flags; +position p != r1.p; +@@ +request_threaded_irq@p(irq, NULL, thread_fn, +( +-0 ++IRQF_ONESHOT +| +-flags ++flags | IRQF_ONESHOT +) +, ...) + +@depends on context@ +position p != r1.p; +@@ +*request_threaded_irq@p(...) + +@match depends on report || org@ +expression irq; +position p != r1.p; +@@ +request_threaded_irq@p(irq, NULL, ...) + +@script:python depends on org@ +p << match.p; +@@ +msg = "ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT" +coccilib.org.print_todo(p[0],msg) + +@script:python depends on report@ +p << match.p; +@@ +msg = "ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT" +coccilib.report.print_report(p[0],msg) diff --git a/scripts/config b/scripts/config index ed6653ef970..ee355394f4e 100755 --- a/scripts/config +++ b/scripts/config @@ -1,6 +1,9 @@ #!/bin/bash # Manipulate options in a .config file from the command line +# If no prefix forced, use the default CONFIG_ +CONFIG_="${CONFIG_-CONFIG_}" + usage() { cat >&2 <<EOL Manipulate options in a .config file from the command line. @@ -14,6 +17,7 @@ commands: Set option to "string" --set-val option value Set option to value + --undefine|-u option Undefine option --state|-s option Print state of option (n,y,m,undef) --enable-after|-E beforeopt option @@ -26,10 +30,17 @@ commands: commands can be repeated multiple times options: - --file .config file to change (default .config) + --file config-file .config file to change (default .config) + --keep-case|-k Keep next symbols' case (dont' upper-case it) config doesn't check the validity of the .config file. This is done at next - make time. +make time. + +By default, config will upper-case the given symbol. Use --keep-case to keep +the case of all following symbols unchanged. + +config uses 'CONFIG_' as the default symbol prefix. Set the environment +variable CONFIG_ to the prefix to use. Eg.: CONFIG_="FOO_" config ... EOL exit 1 } @@ -40,11 +51,13 @@ checkarg() { usage fi case "$ARG" in - CONFIG_*) - ARG="${ARG/CONFIG_/}" + ${CONFIG_}*) + ARG="${ARG/${CONFIG_}/}" ;; esac - ARG="`echo $ARG | tr a-z A-Z`" + if [ "$MUNGE_CASE" = "yes" ] ; then + ARG="`echo $ARG | tr a-z A-Z`" + fi } set_var() { @@ -61,6 +74,12 @@ set_var() { fi } +undef_var() { + local name=$1 + + sed -ri "/^($name=|# $name is not set)/d" "$FN" +} + if [ "$1" = "--file" ]; then FN="$2" if [ "$FN" = "" ] ; then @@ -75,10 +94,16 @@ if [ "$1" = "" ] ; then usage fi +MUNGE_CASE=yes while [ "$1" != "" ] ; do CMD="$1" shift case "$CMD" in + --keep-case|-k) + MUNGE_CASE=no + shift + continue + ;; --refresh) ;; --*-after) @@ -95,55 +120,58 @@ while [ "$1" != "" ] ; do esac case "$CMD" in --enable|-e) - set_var "CONFIG_$ARG" "CONFIG_$ARG=y" + set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=y" ;; --disable|-d) - set_var "CONFIG_$ARG" "# CONFIG_$ARG is not set" + set_var "${CONFIG_}$ARG" "# ${CONFIG_}$ARG is not set" ;; --module|-m) - set_var "CONFIG_$ARG" "CONFIG_$ARG=m" + set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=m" ;; --set-str) # sed swallows one level of escaping, so we need double-escaping - set_var "CONFIG_$ARG" "CONFIG_$ARG=\"${1//\"/\\\\\"}\"" + set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=\"${1//\"/\\\\\"}\"" shift ;; --set-val) - set_var "CONFIG_$ARG" "CONFIG_$ARG=$1" + set_var "${CONFIG_}$ARG" "${CONFIG_}$ARG=$1" shift ;; + --undefine|-u) + undef_var "${CONFIG_}$ARG" + ;; --state|-s) - if grep -q "# CONFIG_$ARG is not set" $FN ; then + if grep -q "# ${CONFIG_}$ARG is not set" $FN ; then echo n else - V="$(grep "^CONFIG_$ARG=" $FN)" + V="$(grep "^${CONFIG_}$ARG=" $FN)" if [ $? != 0 ] ; then echo undef else - V="${V/#CONFIG_$ARG=/}" + V="${V/#${CONFIG_}$ARG=/}" V="${V/#\"/}" V="${V/%\"/}" - V="${V/\\\"/\"}" + V="${V//\\\"/\"}" echo "${V}" fi fi ;; --enable-after|-E) - set_var "CONFIG_$B" "CONFIG_$B=y" "CONFIG_$A" + set_var "${CONFIG_}$B" "${CONFIG_}$B=y" "${CONFIG_}$A" ;; --disable-after|-D) - set_var "CONFIG_$B" "# CONFIG_$B is not set" "CONFIG_$A" + set_var "${CONFIG_}$B" "# ${CONFIG_}$B is not set" "${CONFIG_}$A" ;; --module-after|-M) - set_var "CONFIG_$B" "CONFIG_$B=m" "CONFIG_$A" + set_var "${CONFIG_}$B" "${CONFIG_}$B=m" "${CONFIG_}$A" ;; # undocumented because it ignores --file (fixme) diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore index ee120d44156..be603c4fef6 100644 --- a/scripts/kconfig/.gitignore +++ b/scripts/kconfig/.gitignore @@ -7,7 +7,6 @@ config* *.tab.h zconf.hash.c *.moc -lkc_defs.h gconf.glade.h *.pot *.mo diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 79662658fb9..77d53999ffb 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -114,7 +114,7 @@ help: @echo ' alldefconfig - New config with all symbols set to default' @echo ' randconfig - New config with random answer to all options' @echo ' listnewconfig - List new options' - @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)' + @echo ' oldnoconfig - Same as silentoldconfig but sets new symbols to their default value' # lxdialog stuff check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh @@ -234,12 +234,12 @@ $(obj)/.tmp_qtcheck: if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ done; \ if [ -z "$$dir" ]; then \ - echo "*"; \ - echo "* Unable to find any QT installation. Please make sure that"; \ - echo "* the QT4 or QT3 development package is correctly installed and"; \ - echo "* either qmake can be found or install pkg-config or set"; \ - echo "* the QTDIR environment variable to the correct location."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* Unable to find any QT installation. Please make sure that"; \ + echo >&2 "* the QT4 or QT3 development package is correctly installed and"; \ + echo >&2 "* either qmake can be found or install pkg-config or set"; \ + echo >&2 "* the QTDIR environment variable to the correct location."; \ + echo >&2 "*"; \ false; \ fi; \ libpath=$$dir/lib; lib=qt; osdir=""; \ @@ -260,8 +260,8 @@ $(obj)/.tmp_qtcheck: else \ cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ - binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \ - moc="$$binpath/bin/moc"; \ + moc="\$$(shell pkg-config QtCore --variable=moc_location)"; \ + [ -n "$$moc" ] || moc="\$$(shell pkg-config QtCore --variable=prefix)/bin/moc"; \ fi; \ echo "KC_QT_CFLAGS=$$cflags" > $@; \ echo "KC_QT_LIBS=$$libs" >> $@; \ @@ -279,17 +279,17 @@ $(obj)/.tmp_gtkcheck: if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ touch $@; \ else \ - echo "*"; \ - echo "* GTK+ is present but version >= 2.0.0 is required."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* GTK+ is present but version >= 2.0.0 is required."; \ + echo >&2 "*"; \ false; \ fi \ else \ - echo "*"; \ - echo "* Unable to find the GTK+ installation. Please make sure that"; \ - echo "* the GTK+ 2.0 development package is correctly installed..."; \ - echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ - echo "*"; \ + echo >&2 "*"; \ + echo >&2 "* Unable to find the GTK+ installation. Please make sure that"; \ + echo >&2 "* the GTK+ 2.0 development package is correctly installed..."; \ + echo >&2 "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo >&2 "*"; \ false; \ fi endif @@ -298,8 +298,11 @@ $(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c $(obj)/qconf.o: $(obj)/qconf.moc -$(obj)/%.moc: $(src)/%.h - $(KC_QT_MOC) -i $< -o $@ +quiet_cmd_moc = MOC $@ + cmd_moc = $(KC_QT_MOC) -i $< -o $@ + +$(obj)/%.moc: $(src)/%.h $(obj)/.tmp_qtcheck + $(call cmd,moc) # Extract gconf menu items for I18N support $(obj)/gconf.glade.h: $(obj)/gconf.glade diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 52577f052bc..13ddf1126c2 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -182,10 +182,66 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) return 0; } +#define LINE_GROWTH 16 +static int add_byte(int c, char **lineptr, size_t slen, size_t *n) +{ + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; +} + +static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) +{ + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + /* fall through */ + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } + +e_out: + line[slen-1] = '\0'; + *lineptr = line; + return -1; +} + int conf_read_simple(const char *name, int def) { FILE *in = NULL; - char line[1024]; + char *line = NULL; + size_t line_asize = 0; char *p, *p2; struct symbol *sym; int i, def_flags; @@ -247,7 +303,7 @@ load: } } - while (fgets(line, sizeof(line), in)) { + while (compat_getline(&line, &line_asize, in) != -1) { conf_lineno++; sym = NULL; if (line[0] == '#') { @@ -335,6 +391,7 @@ setsym: cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); } } + free(line); fclose(in); if (modules_sym) diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 82cc3a85e7f..e3b12c01041 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -4,7 +4,7 @@ # What library to link ldflags() { - for ext in so a dylib ; do + for ext in so a dll.a dylib ; do for lib in ncursesw ncurses curses ; do $cc -print-file-name=lib${lib}.${ext} | grep -q / if [ $? -eq 0 ]; then @@ -19,12 +19,12 @@ ldflags() # Where is ncurses.h? ccflags() { - if [ -f /usr/include/ncurses/ncurses.h ]; then + if [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"' + elif [ -f /usr/include/ncurses/ncurses.h ]; then echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"' elif [ -f /usr/include/ncurses/curses.h ]; then echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"' - elif [ -f /usr/include/ncursesw/curses.h ]; then - echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"' elif [ -f /usr/include/ncurses.h ]; then echo '-DCURSES_LOC="<ncurses.h>"' else diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index 154c2dd245b..4e5de60a0c0 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c @@ -129,6 +129,7 @@ do_resize: case 'e': case 'X': case 'x': + case 'q': delwin(box); delwin(dialog); return 0; @@ -190,6 +191,7 @@ do_resize: break; case 'B': /* Previous page */ case 'b': + case 'u': case KEY_PPAGE: if (begin_reached) break; @@ -214,6 +216,7 @@ do_resize: break; case KEY_NPAGE: /* Next page */ case ' ': + case 'd': if (end_reached) break; diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index f606738d421..f584a281bb4 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -105,10 +105,10 @@ static const char mconf_readme[] = N_( "Text Box (Help Window)\n" "--------\n" "o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n" -" who are familiar with less and lynx.\n" +" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for \n" +" those who are familiar with less and lynx.\n" "\n" -"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n" +"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n" "\n" "\n" "Alternate Configuration Files\n" diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 8c0eb65978c..1704a8562a5 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -83,10 +83,10 @@ static const char nconf_readme[] = N_( "Text Box (Help Window)\n" "--------\n" "o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do <SPACE BAR> for those\n" -" who are familiar with less and lynx.\n" +" keys h,j,k,l function here as do <u>, <d> and <SPACE BAR> for\n" +" those who are familiar with less and lynx.\n" "\n" -"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n" +"o Press <Enter>, <F1>, <F5>, <F9>, <q> or <Esc> to exit.\n" "\n" "\n" "Alternate Configuration Files\n" @@ -1503,7 +1503,11 @@ int main(int ac, char **av) } notimeout(stdscr, FALSE); +#if NCURSES_REENTRANT + set_escdelay(1); +#else ESCDELAY = 1; +#endif /* set btns menu */ curses_menu = new_menu(curses_menu_items); diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c index 3b18dd83966..379003c7a2b 100644 --- a/scripts/kconfig/nconf.gui.c +++ b/scripts/kconfig/nconf.gui.c @@ -604,9 +604,11 @@ void show_scroll_win(WINDOW *main_window, switch (res) { case KEY_NPAGE: case ' ': + case 'd': start_y += text_lines-2; break; case KEY_PPAGE: + case 'u': start_y -= text_lines+2; break; case KEY_HOME: @@ -632,10 +634,10 @@ void show_scroll_win(WINDOW *main_window, start_x++; break; } - if (res == 10 || res == 27 || res == 'q' - || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { + if (res == 10 || res == 27 || res == 'q' || + res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) break; - } if (start_y < 0) start_y = 0; if (start_y >= total_lines-text_lines) diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index bccf07ddd0b..2fbbbc1ddea 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -45,6 +45,16 @@ use strict; use Getopt::Long; +# set the environment variable LOCALMODCONFIG_DEBUG to get +# debug output. +my $debugprint = 0; +$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG})); + +sub dprint { + return if (!$debugprint); + print STDERR @_; +} + my $config = ".config"; my $uname = `uname -r`; @@ -113,6 +123,10 @@ sub find_config { find_config; +# Read in the entire config file into config_file +my @config_file = <CIN>; +close CIN; + # Parse options my $localmodconfig = 0; my $localyesconfig = 0; @@ -186,6 +200,7 @@ sub read_kconfig { $state = "NEW"; $config = $2; + # Add depends for 'if' nesting for (my $i = 0; $i < $iflevel; $i++) { if ($i) { $depends{$config} .= " " . $ifdeps[$i]; @@ -204,10 +219,11 @@ sub read_kconfig { # Get the configs that select this config } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { - if (defined($selects{$1})) { - $selects{$1} .= " " . $config; + my $conf = $1; + if (defined($selects{$conf})) { + $selects{$conf} .= " " . $config; } else { - $selects{$1} = $config; + $selects{$conf} = $config; } # configs without prompts must be selected @@ -250,6 +266,7 @@ if ($kconfig) { read_kconfig($kconfig); } +# Makefiles can use variables to define their dependencies sub convert_vars { my ($line, %vars) = @_; @@ -293,6 +310,7 @@ foreach my $makefile (@makefiles) { my $objs; + # Convert variables in a line (could define configs) $_ = convert_vars($_, %make_vars); # collect objects after obj-$(CONFIG_FOO_BAR) @@ -373,13 +391,15 @@ while (<LIN>) { close (LIN); # add to the configs hash all configs that are needed to enable -# a loaded module. +# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o +# where we know we need bar.o so we add FOO to the list. my %configs; foreach my $module (keys(%modules)) { if (defined($objects{$module})) { my @arr = @{$objects{$module}}; foreach my $conf (@arr) { $configs{$conf} = $module; + dprint "$conf added by direct ($module)\n"; } } else { # Most likely, someone has a custom (binary?) module loaded. @@ -387,9 +407,24 @@ foreach my $module (keys(%modules)) { } } +# Read the current config, and see what is enabled. We want to +# ignore configs that we would not enable anyway. + +my %orig_configs; my $valid = "A-Za-z_0-9"; + +foreach my $line (@config_file) { + $_ = $line; + + if (/(CONFIG_[$valid]*)=(m|y)/) { + $orig_configs{$1} = $2; + } +} + my $repeat = 1; +my $depconfig; + # # Note, we do not care about operands (like: &&, ||, !) we want to add any # config that is in the depend list of another config. This script does @@ -398,7 +433,7 @@ my $repeat = 1; # to keep on. If A was on in the original config, B would not have been # and B would not be turned on by this script. # -sub parse_config_dep_select +sub parse_config_depends { my ($p) = @_; @@ -409,10 +444,16 @@ sub parse_config_dep_select $p =~ s/^[^$valid]*[$valid]+//; + # We only need to process if the depend config is a module + if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") { + next; + } + if (!defined($configs{$conf})) { # We must make sure that this config has its # dependencies met. $repeat = 1; # do again + dprint "$conf selected by depend $depconfig\n"; $configs{$conf} = 1; } } else { @@ -421,31 +462,132 @@ sub parse_config_dep_select } } -while ($repeat) { - $repeat = 0; +# Select is treated a bit differently than depends. We call this +# when a config has no prompt and requires another config to be +# selected. We use to just select all configs that selected this +# config, but found that that can balloon into enabling hundreds +# of configs that we do not care about. +# +# The idea is we look at all the configs that select it. If one +# is already in our list of configs to enable, then there's nothing +# else to do. If there isn't, we pick the first config that was +# enabled in the orignal config and use that. +sub parse_config_selects +{ + my ($config, $p) = @_; - foreach my $config (keys %configs) { - $config =~ s/^CONFIG_//; + my $next_config; + + while ($p =~ /[$valid]/) { - if (defined($depends{$config})) { - # This config has dependencies. Make sure they are also included - parse_config_dep_select $depends{$config}; + if ($p =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $p =~ s/^[^$valid]*[$valid]+//; + + # Make sure that this config exists in the current .config file + if (!defined($orig_configs{$conf})) { + dprint "$conf not set for $config select\n"; + next; + } + + # Check if something other than a module selects this config + if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") { + dprint "$conf (non module) selects config, we are good\n"; + # we are good with this + return; + } + if (defined($configs{$conf})) { + dprint "$conf selects $config so we are good\n"; + # A set config selects this config, we are good + return; + } + # Set this config to be selected + if (!defined($next_config)) { + $next_config = $conf; + } + } else { + die "this should never happen"; } + } - if (defined($prompts{$config}) || !defined($selects{$config})) { - next; + # If no possible config selected this, then something happened. + if (!defined($next_config)) { + print STDERR "WARNING: $config is required, but nothing in the\n"; + print STDERR " current config selects it.\n"; + return; + } + + # If we are here, then we found no config that is set and + # selects this config. Repeat. + $repeat = 1; + # Make this config need to be selected + $configs{$next_config} = 1; + dprint "$next_config selected by select $config\n"; +} + +my %process_selects; + +# loop through all configs, select their dependencies. +sub loop_depend { + $repeat = 1; + + while ($repeat) { + $repeat = 0; + + forloop: + foreach my $config (keys %configs) { + + # If this config is not a module, we do not need to process it + if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") { + next forloop; + } + + $config =~ s/^CONFIG_//; + $depconfig = $config; + + if (defined($depends{$config})) { + # This config has dependencies. Make sure they are also included + parse_config_depends $depends{$config}; + } + + # If the config has no prompt, then we need to check if a config + # that is enabled selected it. Or if we need to enable one. + if (!defined($prompts{$config}) && defined($selects{$config})) { + $process_selects{$config} = 1; + } } + } +} + +sub loop_select { + + foreach my $config (keys %process_selects) { + $config =~ s/^CONFIG_//; + + dprint "Process select $config\n"; # config has no prompt and must be selected. - parse_config_dep_select $selects{$config}; + parse_config_selects $config, $selects{$config}; } } +while ($repeat) { + # Get the first set of configs and their dependencies. + loop_depend; + + $repeat = 0; + + # Now we need to see if we have to check selects; + loop_select; +} + my %setconfigs; # Finally, read the .config file and turn off any module enabled that # we could not find a reason to keep enabled. -while(<CIN>) { +foreach my $line (@config_file) { + $_ = $line; if (/CONFIG_IKCONFIG/) { if (/# CONFIG_IKCONFIG is not set/) { @@ -473,7 +615,6 @@ while(<CIN>) { } print; } -close(CIN); # Integrity check, make sure all modules that we want enabled do # indeed have their configs set. diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index cd9c6c6bb4c..4629038c9e5 100644 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -210,8 +210,8 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then mksysmap ${kallsyms_vmlinux} .tmp_System.map if ! cmp -s System.map .tmp_System.map; then - echo Inconsistent kallsyms data - echo echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround + echo >&2 Inconsistent kallsyms data + echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround cleanup exit 1 fi diff --git a/scripts/package/builddeb b/scripts/package/builddeb index c95fdda5841..acb86507828 100644 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -92,7 +92,7 @@ rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" mkdir -m 755 -p "$tmpdir/DEBIAN" mkdir -p "$tmpdir/lib" "$tmpdir/boot" "$tmpdir/usr/share/doc/$packagename" mkdir -m 755 -p "$fwdir/DEBIAN" -mkdir -p "$fwdir/lib" "$fwdir/usr/share/doc/$fwpackagename" +mkdir -p "$fwdir/lib/firmware/$version/" "$fwdir/usr/share/doc/$fwpackagename" mkdir -m 755 -p "$libc_headers_dir/DEBIAN" mkdir -p "$libc_headers_dir/usr/share/doc/$libc_headers_packagename" mkdir -m 755 -p "$kernel_headers_dir/DEBIAN" @@ -243,7 +243,7 @@ EOF fi # Build header package -(cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") +(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles") (cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles") (cd $objtree; find arch/$SRCARCH/include .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles") destdir=$kernel_headers_dir/usr/src/linux-headers-$version @@ -267,7 +267,8 @@ EOF # Do we have firmware? Move it out of the way and build it into a package. if [ -e "$tmpdir/lib/firmware" ]; then - mv "$tmpdir/lib/firmware" "$fwdir/lib/" + mv "$tmpdir/lib/firmware"/* "$fwdir/lib/firmware/$version/" + rmdir "$tmpdir/lib/firmware" cat <<EOF >> debian/control diff --git a/scripts/tags.sh b/scripts/tags.sh index cf7b12fee57..cff8faad73d 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -153,7 +153,8 @@ exuberant() --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' + --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ + --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' all_kconfigs | xargs $1 -a \ --langdef=kconfig --language-force=kconfig \ @@ -195,7 +196,8 @@ emacs() --regex='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ - --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' + --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ + --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' all_kconfigs | xargs $1 -a \ --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ec43760a8a0..6c77f63c759 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2791,11 +2791,16 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, /* We strip a nul only if it is at the end, otherwise the * context contains a nul and we should audit that */ - str = value; - if (str[size - 1] == '\0') - audit_size = size - 1; - else - audit_size = size; + if (value) { + str = value; + if (str[size - 1] == '\0') + audit_size = size - 1; + else + audit_size = size; + } else { + str = ""; + audit_size = 0; + } ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); audit_log_format(ab, "op=setxattr invalid_context="); audit_log_n_untrustedstring(ab, value, audit_size); diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index d31e6d957c2..b1b768e4049 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -323,11 +323,11 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule, int datalen; int rc = -1; - /* - * This is probably inefficient, but safe. - */ + /* This is inefficient */ datalen = strlen(data); - subject = kzalloc(datalen, GFP_KERNEL); + + /* Our first element can be 64 + \0 with no spaces */ + subject = kzalloc(datalen + 1, GFP_KERNEL); if (subject == NULL) return -1; object = kzalloc(datalen, GFP_KERNEL); diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 0ff1e70b777..c084c549942 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -653,7 +653,7 @@ int twl6040_get_hs_step_size(struct snd_soc_codec *codec) { struct twl6040 *twl6040 = codec->control_data; - if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2) + if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_3) /* For ES under ES_1.3 HS step is 2 mV */ return 2; else diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 292b13ad03f..52b7959cd51 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -52,6 +52,7 @@ my %default = ( "STOP_AFTER_SUCCESS" => 10, "STOP_AFTER_FAILURE" => 60, "STOP_TEST_AFTER" => 600, + "MAX_MONITOR_WAIT" => 1800, # required, and we will ask users if they don't have them but we keep the default # value something that is common. @@ -77,6 +78,11 @@ my $output_config; my $test_type; my $build_type; my $build_options; +my $final_post_ktest; +my $pre_ktest; +my $post_ktest; +my $pre_test; +my $post_test; my $pre_build; my $post_build; my $pre_build_die; @@ -93,6 +99,7 @@ my $reboot_on_success; my $die_on_failure; my $powercycle_after_reboot; my $poweroff_after_halt; +my $max_monitor_wait; my $ssh_exec; my $scp_to_target; my $scp_to_target_install; @@ -101,6 +108,7 @@ my $grub_menu; my $grub_number; my $target; my $make; +my $pre_install; my $post_install; my $no_install; my $noclean; @@ -167,6 +175,7 @@ my $bisect_check; my $config_bisect; my $config_bisect_type; +my $config_bisect_check; my $patchcheck_type; my $patchcheck_start; @@ -182,6 +191,9 @@ my $newconfig = 0; my %entered_configs; my %config_help; my %variable; + +# force_config is the list of configs that we force enabled (or disabled) +# in a .config file. The MIN_CONFIG and ADD_CONFIG configs. my %force_config; # do not force reboots on config problems @@ -197,6 +209,10 @@ my %option_map = ( "OUTPUT_DIR" => \$outputdir, "BUILD_DIR" => \$builddir, "TEST_TYPE" => \$test_type, + "PRE_KTEST" => \$pre_ktest, + "POST_KTEST" => \$post_ktest, + "PRE_TEST" => \$pre_test, + "POST_TEST" => \$post_test, "BUILD_TYPE" => \$build_type, "BUILD_OPTIONS" => \$build_options, "PRE_BUILD" => \$pre_build, @@ -216,6 +232,7 @@ my %option_map = ( "ADD_CONFIG" => \$addconfig, "REBOOT_TYPE" => \$reboot_type, "GRUB_MENU" => \$grub_menu, + "PRE_INSTALL" => \$pre_install, "POST_INSTALL" => \$post_install, "NO_INSTALL" => \$no_install, "REBOOT_SCRIPT" => \$reboot_script, @@ -228,6 +245,7 @@ my %option_map = ( "POWER_OFF" => \$power_off, "POWERCYCLE_AFTER_REBOOT" => \$powercycle_after_reboot, "POWEROFF_AFTER_HALT" => \$poweroff_after_halt, + "MAX_MONITOR_WAIT" => \$max_monitor_wait, "SLEEP_TIME" => \$sleep_time, "BISECT_SLEEP_TIME" => \$bisect_sleep_time, "PATCHCHECK_SLEEP_TIME" => \$patchcheck_sleep_time, @@ -272,6 +290,7 @@ my %option_map = ( "CONFIG_BISECT" => \$config_bisect, "CONFIG_BISECT_TYPE" => \$config_bisect_type, + "CONFIG_BISECT_CHECK" => \$config_bisect_check, "PATCHCHECK_TYPE" => \$patchcheck_type, "PATCHCHECK_START" => \$patchcheck_start, @@ -604,6 +623,10 @@ sub process_compare { return $lval eq $rval; } elsif ($cmp eq "!=") { return $lval ne $rval; + } elsif ($cmp eq "=~") { + return $lval =~ m/$rval/; + } elsif ($cmp eq "!~") { + return $lval !~ m/$rval/; } my $statement = "$lval $cmp $rval"; @@ -659,7 +682,7 @@ sub process_expression { } } - if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) { + if ($val =~ /(.*)(==|\!=|>=|<=|>|<|=~|\!~)(.*)/) { my $ret = process_compare($1, $2, $3); if ($ret < 0) { die "$name: $.: Unable to process comparison\n"; @@ -1117,7 +1140,11 @@ sub reboot { } if (defined($time)) { - wait_for_monitor($time, $reboot_success_line); + if (wait_for_monitor($time, $reboot_success_line)) { + # reboot got stuck? + doprint "Reboot did not finish. Forcing power cycle\n"; + run_command "$power_cycle"; + } end_monitor; } } @@ -1212,6 +1239,11 @@ sub wait_for_monitor { my $full_line = ""; my $line; my $booted = 0; + my $start_time = time; + my $skip_call_trace = 0; + my $bug = 0; + my $bug_ignored = 0; + my $now; doprint "** Wait for monitor to settle down **\n"; @@ -1227,11 +1259,39 @@ sub wait_for_monitor { $booted = 1; } + if ($full_line =~ /\[ backtrace testing \]/) { + $skip_call_trace = 1; + } + + if ($full_line =~ /call trace:/i) { + if (!$bug && !$skip_call_trace) { + if ($ignore_errors) { + $bug_ignored = 1; + } else { + $bug = 1; + } + } + } + + if ($full_line =~ /\[ end of backtrace testing \]/) { + $skip_call_trace = 0; + } + + if ($full_line =~ /Kernel panic -/) { + $bug = 1; + } + if ($line =~ /\n/) { $full_line = ""; } + $now = time; + if ($now - $start_time >= $max_monitor_wait) { + doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n"; + return 1; + } } print "** Monitor flushed **\n"; + return $bug; } sub save_logs { @@ -1273,6 +1333,10 @@ sub save_logs { sub fail { + if (defined($post_test)) { + run_command $post_test; + } + if ($die_on_failure) { dodie @_; } @@ -1656,6 +1720,12 @@ sub install { return if ($no_install); + if (defined($pre_install)) { + my $cp_pre_install = eval_kernel_version $pre_install; + run_command "$cp_pre_install" or + dodie "Failed to run pre install"; + } + my $cp_target = eval_kernel_version $target_image; run_scp_install "$outputdir/$build_target", "$cp_target" or @@ -1814,6 +1884,7 @@ sub make_oldconfig { sub load_force_config { my ($config) = @_; + doprint "Loading force configs from $config\n"; open(IN, $config) or dodie "failed to read $config"; while (<IN>) { @@ -1937,6 +2008,10 @@ sub halt { sub success { my ($i) = @_; + if (defined($post_test)) { + run_command $post_test; + } + $successes++; my $name = ""; @@ -2003,6 +2078,7 @@ sub do_run_test { my $line; my $full_line; my $bug = 0; + my $bug_ignored = 0; wait_for_monitor 1; @@ -2027,7 +2103,11 @@ sub do_run_test { doprint $line; if ($full_line =~ /call trace:/i) { - $bug = 1; + if ($ignore_errors) { + $bug_ignored = 1; + } else { + $bug = 1; + } } if ($full_line =~ /Kernel panic -/) { @@ -2040,6 +2120,10 @@ sub do_run_test { } } while (!$child_done && !$bug); + if (!$bug && $bug_ignored) { + doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n"; + } + if ($bug) { my $failure_start = time; my $now; @@ -2362,9 +2446,24 @@ sub bisect { success $i; } +# config_ignore holds the configs that were set (or unset) for +# a good config and we will ignore these configs for the rest +# of a config bisect. These configs stay as they were. my %config_ignore; + +# config_set holds what all configs were set as. my %config_set; +# config_off holds the set of configs that the bad config had disabled. +# We need to record them and set them in the .config when running +# oldnoconfig, because oldnoconfig does not turn off new symbols, but +# instead just keeps the defaults. +my %config_off; + +# config_off_tmp holds a set of configs to turn off for now +my @config_off_tmp; + +# config_list is the set of configs that are being tested my %config_list; my %null_config; @@ -2443,12 +2542,21 @@ sub create_config { } } + # turn off configs to keep off + foreach my $config (keys %config_off) { + print OUT "# $config is not set\n"; + } + + # turn off configs that should be off for now + foreach my $config (@config_off_tmp) { + print OUT "# $config is not set\n"; + } + foreach my $config (keys %config_ignore) { print OUT "$config_ignore{$config}\n"; } close(OUT); -# exit; make_oldconfig; } @@ -2525,6 +2633,13 @@ sub run_config_bisect { do { my @tophalf = @start_list[0 .. $half]; + # keep the bottom half off + if ($half < $#start_list) { + @config_off_tmp = @start_list[$half + 1 .. $#start_list]; + } else { + @config_off_tmp = (); + } + create_config @tophalf; read_current_config \%current_config; @@ -2541,7 +2656,11 @@ sub run_config_bisect { if (!$found) { # try the other half doprint "Top half produced no set configs, trying bottom half\n"; + + # keep the top half off + @config_off_tmp = @tophalf; @tophalf = @start_list[$half + 1 .. $#start_list]; + create_config @tophalf; read_current_config \%current_config; foreach my $config (@tophalf) { @@ -2679,6 +2798,10 @@ sub config_bisect { $added_configs{$2} = $1; $config_list{$2} = $1; } + } elsif (/^# ((CONFIG\S*).*)/) { + # Keep these configs disabled + $config_set{$2} = $1; + $config_off{$2} = $1; } } close(IN); @@ -2701,6 +2824,8 @@ sub config_bisect { my %config_test; my $once = 0; + @config_off_tmp = (); + # Sometimes kconfig does weird things. We must make sure # that the config we autocreate has everything we need # to test, otherwise we may miss testing configs, or @@ -2719,6 +2844,18 @@ sub config_bisect { } } my $ret; + + if (defined($config_bisect_check) && $config_bisect_check) { + doprint " Checking to make sure bad config with min config fails\n"; + create_config keys %config_list; + $ret = run_config_bisect_test $config_bisect_type; + if ($ret) { + doprint " FAILED! Bad config with min config boots fine\n"; + return -1; + } + doprint " Bad config with min config fails as expected\n"; + } + do { $ret = run_config_bisect; } while (!$ret); @@ -3510,6 +3647,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $iteration = $i; + undef %force_config; + my $makecmd = set_test_option("MAKE_CMD", $i); # Load all the options into their mapped variable names @@ -3519,6 +3658,18 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $start_minconfig_defined = 1; + # The first test may override the PRE_KTEST option + if (defined($pre_ktest) && $i == 1) { + doprint "\n"; + run_command $pre_ktest; + } + + # Any test can override the POST_KTEST option + # The last test takes precedence. + if (defined($post_ktest)) { + $final_post_ktest = $post_ktest; + } + if (!defined($start_minconfig)) { $start_minconfig_defined = 0; $start_minconfig = $minconfig; @@ -3573,6 +3724,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "\n\n"; doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n"; + if (defined($pre_test)) { + run_command $pre_test; + } + unlink $dmesg; unlink $buildlog; unlink $testlog; @@ -3638,6 +3793,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { success $i; } +if (defined($final_post_ktest)) { + run_command $final_post_ktest; +} + if ($opt{"POWEROFF_ON_SUCCESS"}) { halt; } elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) { diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index cf362b3d1ec..de28a0a3b8f 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -376,6 +376,24 @@ # DEFAULTS # DEFAULTS SKIP +# If you want to execute some command before the first test runs +# you can set this option. Note, it can be set as a default option +# or an option in the first test case. All other test cases will +# ignore it. If both the default and first test have this option +# set, then the first test will take precedence. +# +# default (undefined) +#PRE_KTEST = ${SSH} ~/set_up_test + +# If you want to execute some command after all the tests have +# completed, you can set this option. Note, it can be set as a +# default or any test case can override it. If multiple test cases +# set this option, then the last test case that set it will take +# precedence +# +# default (undefined) +#POST_KTEST = ${SSH} ~/dismantle_test + # The default test type (default test) # The test types may be: # build - only build the kernel, do nothing else @@ -408,6 +426,14 @@ # (default "") #BUILD_OPTIONS = -j20 +# If you need to do some special handling before installing +# you can add a script with this option. +# The environment variable KERNEL_VERSION will be set to the +# kernel version that is used. +# +# default (undefined) +#PRE_INSTALL = ssh user@target rm -rf '/lib/modules/*-test*' + # If you need an initrd, you can add a script or code here to install # it. The environment variable KERNEL_VERSION will be set to the # kernel version that is used. Remember to add the initrd line @@ -426,6 +452,18 @@ # (default 0) #NO_INSTALL = 1 +# If there is a command that you want to run before the individual test +# case executes, then you can set this option +# +# default (undefined) +#PRE_TEST = ${SSH} reboot_to_special_kernel + +# If there is a command you want to run after the individual test case +# completes, then you can set this option. +# +# default (undefined) +#POST_TEST = cd ${BUILD_DIR}; git reset --hard + # If there is a script that you require to run before the build is done # you can specify it with PRE_BUILD. # @@ -657,6 +695,14 @@ # (default 60) #BISECT_SLEEP_TIME = 60 +# The max wait time (in seconds) for waiting for the console to finish. +# If for some reason, the console is outputting content without +# ever finishing, this will cause ktest to get stuck. This +# option is the max time ktest will wait for the monitor (console) +# to settle down before continuing. +# (default 1800) +#MAX_MONITOR_WAIT + # The time in between patch checks to sleep (in seconds) # (default 60) #PATCHCHECK_SLEEP_TIME = 60 @@ -1039,6 +1085,12 @@ # can specify it with CONFIG_BISECT_GOOD. Otherwise # the MIN_CONFIG is the base. # +# CONFIG_BISECT_CHECK (optional) +# Set this to 1 if you want to confirm that the config ktest +# generates (the bad config with the min config) is still bad. +# It may be that the min config fixes what broke the bad config +# and the test will not return a result. +# # Example: # TEST_START # TEST_TYPE = config_bisect diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c index 164cbcf6110..808d5a9d5dc 100644 --- a/tools/vm/slabinfo.c +++ b/tools/vm/slabinfo.c @@ -437,34 +437,34 @@ static void slab_stats(struct slabinfo *s) printf("Fastpath %8lu %8lu %3lu %3lu\n", s->alloc_fastpath, s->free_fastpath, s->alloc_fastpath * 100 / total_alloc, - s->free_fastpath * 100 / total_free); + total_free ? s->free_fastpath * 100 / total_free : 0); printf("Slowpath %8lu %8lu %3lu %3lu\n", total_alloc - s->alloc_fastpath, s->free_slowpath, (total_alloc - s->alloc_fastpath) * 100 / total_alloc, - s->free_slowpath * 100 / total_free); + total_free ? s->free_slowpath * 100 / total_free : 0); printf("Page Alloc %8lu %8lu %3lu %3lu\n", s->alloc_slab, s->free_slab, s->alloc_slab * 100 / total_alloc, - s->free_slab * 100 / total_free); + total_free ? s->free_slab * 100 / total_free : 0); printf("Add partial %8lu %8lu %3lu %3lu\n", s->deactivate_to_head + s->deactivate_to_tail, s->free_add_partial, (s->deactivate_to_head + s->deactivate_to_tail) * 100 / total_alloc, - s->free_add_partial * 100 / total_free); + total_free ? s->free_add_partial * 100 / total_free : 0); printf("Remove partial %8lu %8lu %3lu %3lu\n", s->alloc_from_partial, s->free_remove_partial, s->alloc_from_partial * 100 / total_alloc, - s->free_remove_partial * 100 / total_free); + total_free ? s->free_remove_partial * 100 / total_free : 0); printf("Cpu partial list %8lu %8lu %3lu %3lu\n", s->cpu_partial_alloc, s->cpu_partial_free, s->cpu_partial_alloc * 100 / total_alloc, - s->cpu_partial_free * 100 / total_free); + total_free ? s->cpu_partial_free * 100 / total_free : 0); printf("RemoteObj/SlabFrozen %8lu %8lu %3lu %3lu\n", s->deactivate_remote_frees, s->free_frozen, s->deactivate_remote_frees * 100 / total_alloc, - s->free_frozen * 100 / total_free); + total_free ? s->free_frozen * 100 / total_free : 0); printf("Total %8lu %8lu\n\n", total_alloc, total_free); |