diff --git a/Documentation/arm/msm/remote_debug_drv.txt b/Documentation/arm/msm/remote_debug_drv.txt new file mode 100644 index 000000000000..13a35f43e86b --- /dev/null +++ b/Documentation/arm/msm/remote_debug_drv.txt @@ -0,0 +1,468 @@ +Introduction +============ + +The goal of this debug feature is to provide a reliable, responsive, +accurate and secure debug capability to developers interested in +debugging MSM subsystem processor images without the use of a hardware +debugger. + +The Debug Agent along with the Remote Debug Driver implements a shared +memory based transport mechanism that allows for a debugger (ex. GDB) +running on a host PC to communicate with a remote stub running on +peripheral subsystems such as the ADSP, MODEM etc. + +The diagram below depicts end to end the components involved to +support remote debugging: + + +: : +: HOST (PC) : MSM +: ,--------, : ,-------, +: | | : | Debug | ,--------, +: |Debugger|<--:-->| Agent | | Remote | +: | | : | App | +----->| Debug | +: `--------` : |-------| ,--------, | | Stub | +: : | Remote| | |<---+ `--------` +: : | Debug |<-->|--------| +: : | Driver| | |<---+ ,--------, +: : `-------` `--------` | | Remote | +: : LA Shared +----->| Debug | +: : Memory | Stub | +: : `--------` +: : Peripheral Subsystems +: : (ADSP, MODEM, ...) + + +Debugger: Debugger application running on the host PC that + communicates with the remote stub. + Examples: GDB, LLDB + +Debug Agent: Software that runs on the Linux Android platform + that provides connectivity from the MSM to the + host PC. This involves two portions: + 1) User mode Debug Agent application that discovers + processes running on the subsystems and creates + TCP/IP sockets for the host to connect to. In addition + to this, it creates an info (or meta) port that + users can connect to discover the various + processes and their corresponding debug ports. + +Remote Debug A character based driver that the Debug +Driver: Agent uses to transport the payload received from the + host to the debug stub running on the subsystem + processor over shared memory and vice versa. + +Shared Memory: Shared memory from the SMEM pool that is accessible + from the Applications Processor (AP) and the + subsystem processors. + +Remote Debug Privileged code that runs in the kernels of the +Stub: subsystem processors that receives debug commands + from the debugger running on the host and + acts on these commands. These commands include reading + and writing to registers and memory belonging to the + subsystem's address space, setting breakpoints, + single stepping etc. + +Hardware description +==================== + +The Remote Debug Driver interfaces with the Remote Debug stubs +running on the subsystem processors and does not drive or +manage any hardware resources. + +Software description +==================== + +The debugger and the remote stubs use Remote Serial Protocol (RSP) +to communicate with each other. This is widely used protocol by both +software and hardware debuggers. RSP is an ASCII based protocol +and used when it is not possible to run GDB server on the target under +debug. + +The Debug Agent application along with the Remote Debug Driver +is responsible for establishing a bi-directional connection from +the debugger application running on the host to the remote debug +stub running on a subsystem. The Debug Agent establishes connectivity +to the host PC via TCP/IP sockets. + +This feature uses ADB port forwarding to establish connectivity +between the debugger running on the host and the target under debug. + +Please note the Debug Agent does not expose HLOS memory to the +remote subsystem processors. + +Design +====== + +Here is the overall flow: + +1) When the Debug Agent application starts up, it opens up a shared memory +based transport channel to the various subsystem processor images. + +2) The Debug Agent application sends messages across to the remote stubs +to discover the various processes that are running on the subsystem and +creates debug sockets for each of them. + +3) Whenever a process running on a subsystem exits, the Debug Agent +is notified by the stub so that the debug port and other resources +can be reclaimed. + +4) The Debug Agent uses the services of the Remote Debug Driver to +transport payload from the host debugger to the remote stub and vice versa. + +5) Communication between the Remote Debug Driver and the Remote Debug stub +running on the subsystem processor is done over shared memory (see figure). +SMEM services are used to allocate the shared memory that will +be readable and writeable by the AP and the subsystem image under debug. + +A separate SMEM allocation takes place for each subsystem processor +involved in remote debugging. The remote stub running on each of the +subsystems allocates a SMEM buffer using a unique identifier so that both +the AP and subsystem get the same physical block of memory. It should be +noted that subsystem images can be restarted at any time. +However, when a subsystem comes back up, its stub uses the same unique +SMEM identifier to allocate the SMEM block. This would not result in a +new allocation rather the same block of memory in the first bootup instance +is provided back to the stub running on the subsystem. + +An 8KB chunk of shared memory is allocated and used for communication +per subsystem. For multi-process capable subsystems, 16KB chunk of shared +memory is allocated to allow for simultaneous debugging of more than one +process running on a single subsystem. + +The shared memory is used as a circular ring buffer in each direction. +Thus we have a bi-directional shared memory channel between the AP +and a subsystem. We call this SMQ. Each memory channel contains a header, +data and a control mechanism that is used to synchronize read and write +of data between the AP and the remote subsystem. + +Overall SMQ memory view: +: +: +------------------------------------------------+ +: | SMEM buffer | +: |-----------------------+------------------------| +: |Producer: LA | Producer: Remote | +: |Consumer: Remote | subsystem | +: | subsystem | Consumer: LA | +: | | | +: | Producer| Consumer| +: +-----------------------+------------------------+ +: | | +: | | +: | +--------------------------------------+ +: | | +: | | +: v v +: +--------------------------------------------------------------+ +: | Header | Data | Control | +: +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ +: | | b | b | b | | S |n |n | | S |n |n | | +: | Producer | l | l | l | | M |o |o | | M |o |o | | +: | Ver | o | o | o | | Q |d |d | | Q |d |d | | +: |-----------| c | c | c | ... | |e |e | ... | |e |e | ... | +: | | k | k | k | | O | | | | I | | | | +: | Consumer | | | | | u |0 |1 | | n |0 |1 | | +: | Ver | 0 | 1 | 2 | | t | | | | | | | | +: +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ +: | | +: + | +: | +: +------------------------+ +: | +: v +: +----+----+----+----+ +: | SMQ Nodes | +: |----|----|----|----| +: Node # | 0 | 1 | 2 | ...| +: |----|----|----|----| +: Starting Block Index # | 0 | 3 | 8 | ...| +: |----|----|----|----| +: # of blocks | 3 | 5 | 1 | ...| +: +----+----+----+----+ +: + +Header: Contains version numbers for software compatibility to ensure +that both producers and consumers on the AP and subsystems know how to +read from and write to the queue. +Both the producer and consumer versions are 1. +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 1 byte | Producer Version | +: +---------+-------------------+ +: | 1 byte | Consumer Version | +: +---------+-------------------+ + + +Data: The data portion contains multiple blocks [0..N] of a fixed size. +The block size SM_BLOCKSIZE is fixed to 128 bytes for header version #1. +Payload sent from the debug agent app is split (if necessary) and placed +in these blocks. The first data block is placed at the next 8 byte aligned +address after the header. + +The number of blocks for a given SMEM allocation is derived as follows: + Number of Blocks = ((Total Size - Alignment - Size of Header + - Size of SMQIn - Size of SMQOut)/(SM_BLOCKSIZE)) + +The producer maintains a private block map of each of these blocks to +determine which of these blocks in the queue is available and which are free. + +Control: +The control portion contains a list of nodes [0..N] where N is number +of available data blocks. Each node identifies the data +block indexes that contain a particular debug message to be transferred, +and the number of blocks it took to hold the contents of the message. + +Each node has the following structure: +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 2 bytes |Staring Block Index| +: +---------+-------------------+ +: | 2 bytes |Number of Blocks | +: +---------+-------------------+ + +The producer and the consumer update different parts of the control channel +(SMQOut / SMQIn) respectively. Each of these control data structures contains +information about the last node that was written / read, and the actual nodes +that were written/read. + +SMQOut Structure (R/W by producer, R by consumer): +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 4 bytes | Magic Init Number | +: +---------+-------------------+ +: | 4 bytes | Reset | +: +---------+-------------------+ +: | 4 bytes | Last Sent Index | +: +---------+-------------------+ +: | 4 bytes | Index Free Read | +: +---------+-------------------+ + +SMQIn Structure (R/W by consumer, R by producer): +: +---------+-------------------+ +: | Size | Field | +: +---------+-------------------+ +: | 4 bytes | Magic Init Number | +: +---------+-------------------+ +: | 4 bytes | Reset ACK | +: +---------+-------------------+ +: | 4 bytes | Last Read Index | +: +---------+-------------------+ +: | 4 bytes | Index Free Write | +: +---------+-------------------+ + +Magic Init Number: +Both SMQ Out and SMQ In initialize this field with a predefined magic +number so as to make sure that both the consumer and producer blocks +have fully initialized and have valid data in the shared memory control area. + Producer Magic #: 0xFF00FF01 + Consumer Magic #: 0xFF00FF02 + +SMQ Out's Last Sent Index and Index Free Read: + Only a producer can write to these indexes and they are updated whenever + there is new payload to be inserted into the SMQ in order to be sent to a + consumer. + + The number of blocks required for the SMQ allocation is determined as: + (payload size + SM_BLOCKSIZE - 1) / SM_BLOCKSIZE + + The private block map is searched for a large enough continuous set of blocks + and the user data is copied into the data blocks. + + The starting index of the free block(s) is updated in the SMQOut's Last Sent + Index. This update keeps track of which index was last written to and the + producer uses it to determine where the the next allocation could be done. + + Every allocation, a producer updates the Index Free Read from its + collaborating consumer's Index Free Write field (if they are unequal). + This index value indicates that the consumer has read all blocks associated + with allocation on the SMQ and that the producer can reuse these blocks for + subsquent allocations since this is a circular queue. + + At cold boot and restart, these indexes are initialized to zero and all + blocks are marked as available for allocation. + +SMQ In's Last Read Index and Index Free Write: + These indexes are written to only by a consumer and are updated whenever + there is new payload to be read from the SMQ. The Last Read Index keeps + track of which index was last read by the consumer and using this, it + determines where the next read should be done. + After completing a read, Last Read Index is incremented to the + next block index. A consumer updates Index Free Write to the starting + index of an allocation whenever it has completed processing the blocks. + This is an optimization that can be used to prevent an additional copy + of data from the queue into a client's data buffer and the data in the queue + itself can be used. + Once Index Free Write is updated, the collaborating producer (on the next + data allocation) reads the updated Index Free Write value and it then + updates its corresponding SMQ Out's Index Free Read and marks the blocks + associated with that index as available for allocation. At cold boot and + restart, these indexes are initialized to zero. + +SMQ Out Reset# and SMQ In Reset ACK #: + Since subsystems can restart at anytime, the data blocks and control channel + can be in an inconsistent state when a producer or consumer comes up. + We use Reset and Reset ACK to manage this. At cold boot, the producer + initializes the Reset# to a known number ex. 1. Every other reset that the + producer undergoes, the Reset#1 is simply incremented by 1. All the producer + indexes are reset. + When the producer notifies the consumer of data availability, the consumer + reads the producers Reset # and copies that into its SMQ In Reset ACK# + field when they differ. When that occurs, the consumer resets its + indexes to 0. + +6) Asynchronous notifications between a producer and consumer are +done using the SMP2P service which is interrupt based. + +Power Management +================ + +None + +SMP/multi-core +============== + +The driver uses completion to wake up the Debug Agent client threads. + +Security +======== + +From the perspective of the subsystem, the AP is untrusted. The remote +stubs consult the secure debug fuses to determine whether or not the +remote debugging will be enabled at the subsystem. + +If the hardware debug fuses indicate that debugging is disabled, the +remote stubs will not be functional on the subsystem. Writes to the +queue will only be done if the driver sees that the remote stub has been +initialized on the subsystem. + +Therefore even if any untrusted software running on the AP requests +the services of the Remote Debug Driver and inject RSP messages +into the shared memory buffer, these RSP messages will be discarded and +an appropriate error code will be sent up to the invoking application. + +Performance +=========== + +During operation, the Remote Debug Driver copies RSP messages +asynchronously sent from the host debugger to the remote stub and vice +versa. The debug messages are ASCII based and relatively short +(<25 bytes) and may once in a while go up to a maximum 700 bytes +depending on the command the user requested. Thus we do not +anticipate any major performance impact. Moreover, in a typical +functional debug scenario performance should not be a concern. + +Interface +========= + +The Remote Debug Driver is a character based device that manages +a piece of shared memory that is used as a bi-directional +single producer/consumer circular queue using a next fit allocator. +Every subsystem, has its own shared memory buffer that is managed +like a separate device. + +The driver distinguishes each subsystem processor's buffer by +registering a node with a different minor number. + +For each subsystem that is supported, the driver exposes a user space +interface through the following node: + - /dev/rdbg- + Ex. /dev/rdbg-adsp (for the ADSP subsystem) + +The standard open(), close(), read() and write() API set is +implemented. + +The open() syscall will fail if a subsystem is not present or supported +by the driver or a shared memory buffer cannot be allocated for the +AP - subsystem communication. It will also fail if the subsytem has +not initialized the queue on its side. Here are the error codes returned +in case a call to open() fails: +ENODEV - memory was not yet allocated for the device +EEXIST - device is already opened +ENOMEM - SMEM allocation failed +ECOMM - Subsytem queue is not yet setup +ENOMEM - Failure to initialize SMQ + +read() is a blocking call that will return with the number of bytes written +by the subsystem whenever the subsystem sends it some payload. Here are the +error codes returned in case a call to read() fails: +EINVAL - Invalid input +ENODEV - Device has not been opened yet +ERESTARTSYS - call to wait_for_completion_interruptible is interrupted +ENODATA - call to smq_receive failed + +write() attempts to send user mode payload out to the subsystem. It can fail +if the SMQ is full. The number of bytes written is returned back to the user. +Here are the error codes returned in case a call to write() fails: +EINVAL - Invalid input +ECOMM - SMQ send failed + +In the close() syscall, the control information state of the SMQ is +initialized to zero thereby preventing any further communication between +the AP and the subsystem. Here is the error code returned in case +a call to close() fails: +ENODEV - device wasn't opened/initialized + +The Remote Debug driver uses SMP2P for bi-directional AP to subsystem +notification. Notifications are sent to indicate that there are new +debug messages available for processing. Each subsystem that is +supported will need to add a device tree entry per the usage +specification of SMP2P driver. + +In case the remote stub becomes non operational or the security configuration +on the subsystem does not permit debugging, any messages put in the SMQ will +not be responded to. It is the responsibility of the Debug Agent app and the +host debugger application such as GDB to timeout and notify the user of the +non availability of remote debugging. + +Driver parameters +================= + +None + +Config options +============== + +The driver is configured with a device tree entry to map an SMP2P entry +to the device. The SMP2P entry name used is "rdbg". Please see +kernel\Documentation\arm\msm\msm_smp2p.txt for information about the +device tree entry required to configure SMP2P. + +The driver uses the SMEM allocation type SMEM_LC_DEBUGGER to allocate memory +for the queue that is used to share data with the subsystems. + +Dependencies +============ + +The Debug Agent driver requires services of SMEM to +allocate shared memory buffers. + +SMP2P is used as a bi-directional notification +mechanism between the AP and a subsystem processor. + +User space utilities +==================== + +This driver is meant to be used in conjunction with the user mode +Remote Debug Agent application. + +Other +===== + +None + +Known issues +============ +For targets with an external subsystem, we cannot use +shared memory for communication and would have to use the prevailing +transport mechanisms that exists between the AP and the external subsystem. + +This driver cannot be leveraged for such targets. + +To do +===== + +None diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index ce7bfa24490a..6e1ac697a751 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -264,6 +264,7 @@ compatible = "qcom,msmfalcon-sim" compatible = "qcom,msmfalcon-rumi" compatible = "qcom,msmfalcon-cdp" compatible = "qcom,msmfalcon-mtp" +compatible = "qcom,msmfalcon-qrd" compatible = "qcom,msmtriton-rumi" compatible = "qcom,msm8952-rumi" compatible = "qcom,msm8952-sim" diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt index 808e18b495d5..ac63b3c3bf01 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -36,6 +36,12 @@ First Level Node - FG Gen3 device Definition: For details about IIO bindings see: Documentation/devicetree/bindings/iio/iio-bindings.txt +- qcom,rradc-base + Usage: required + Value type: + Definition: Should specify the base address of RR_ADC peripheral. This + is used for reading certain peripheral registers under it. + - qcom,fg-cutoff-voltage Usage: optional Value type: @@ -260,6 +266,13 @@ First Level Node - FG Gen3 device is specified to make it fully functional. Value has no unit. Allowed range is 0 to 62200 in micro units. +- qcom,fg-rconn-mohms + Usage: optional + Value type: + Definition: Battery connector resistance (Rconn) in milliohms. If Rconn + is specified, then ESR to Rslow scaling factors will be + updated to account it for an accurate ESR. + ========================================================== Second Level Nodes - Peripherals managed by FG Gen3 driver ========================================================== @@ -290,6 +303,7 @@ pmi8998_fg: qpnp,fg { qcom,pmic-revid = <&pmi8998_revid>; io-channels = <&pmi8998_rradc 3>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,ki-coeff-soc-dischg = <30 60 90>; qcom,ki-coeff-med-dischg = <800 1000 1400>; qcom,ki-coeff-hi-dischg = <1200 1500 2100>; diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt index a6bf4147460e..dfc62b78f58d 100644 --- a/Documentation/devicetree/bindings/qseecom/qseecom.txt +++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt @@ -26,6 +26,7 @@ Optional properties: - vdd-hba-supply : handle for fixed power regulator - qcom,qsee-reentrancy-support: indicates the qsee reentrancy phase supported by the target - qcom,commonlib64-loaded-by-uefi: indicates commonlib64 is loaded by uefi already + - qcom,fde-key-size: indicates which FDE key size is used in device. Example: qcom,qseecom@fe806000 { @@ -46,6 +47,7 @@ Example: qcom,msm_bus,num_paths = <1>; qcom,no-clock-support; qcom,appsbl-qseecom-support; + qcom,fde-key-size; qcom,msm_bus,vectors = <55 512 0 0>, <55 512 3936000000 393600000>, @@ -72,6 +74,7 @@ Example: The following dts setup is the same as the example above. qcom,msm_bus,num_paths = <1>; qcom,no-clock-support; qcom,appsbl-qseecom-support; + qcom,fde-key-size; qcom,msm_bus,vectors = <55 512 0 0>, <55 512 3936000000 393600000>, diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt index 80488c802df2..66142b4cd880 100644 --- a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt @@ -9,7 +9,9 @@ contain a phandle reference to UFS PHY node. Required properties: - compatible : compatible list, contains "qcom,ufs-phy-qmp-20nm" or "qcom,ufs-phy-qmp-14nm" or "qcom,ufs-phy-qmp-v3" - or "qcom,ufs-phy-qrbtc-v2" according to the relevant phy in use. + or "qcom,ufs-phy-qrbtc-v2" or + "qcom,ufs-phy-qmp-v3-falcon" + according to the relevant phy in use. - reg : should contain PHY register address space (mandatory), - reg-names : indicates various resources passed to driver (via reg proptery) by name. Required "reg-names" is "phy_mem". diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 4d82f51be778..bc918a9a6402 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -138,7 +138,8 @@ dtb-$(CONFIG_ARCH_MSMFALCON) += msmfalcon-sim.dtb \ msmfalcon-rumi.dtb \ msmfalcon-cdp.dtb \ msmfalcon-mtp.dtb \ - msmfalcon-rcm.dtb + msmfalcon-rcm.dtb \ + msmfalcon-qrd.dtb dtb-$(CONFIG_ARCH_MSMTRITON) += msmtriton-rumi.dtb diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi index 8ec542d953e2..0f5c12856cc0 100644 --- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -34,6 +34,13 @@ ; }; + qcom,temp-alarm@2400 { + compatible = "qcom,qpnp-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>; + label = "pm2falcon_tz"; + }; + pm2falcon_gpios: gpios { compatible = "qcom,qpnp-pin"; gpio-controller; diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi index 1cc31380604b..0168cb2cddb3 100644 --- a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi @@ -51,6 +51,15 @@ }; }; + qcom,temp-alarm@2400 { + compatible = "qcom,qpnp-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>; + label = "pmfalcon_tz"; + qcom,channel-num = <6>; + qcom,temp_alarm-vadc = <&pmfalcon_vadc>; + }; + pmfalcon_gpios: gpios { compatible = "qcom,qpnp-pin"; gpio-controller; @@ -497,6 +506,7 @@ qcom,pmic-revid = <&pmfalcon_revid>; io-channels = <&pmfalcon_rradc 0>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi index 0dc9da9289e2..3fa85d918f6c 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi @@ -321,6 +321,7 @@ qcom,pmic-revid = <&pmi8998_revid>; io-channels = <&pmi8998_rradc 0>; io-channel-names = "rradc_batt_id"; + qcom,rradc-base = <0x4500>; qcom,fg-esr-timer-awake = <96>; qcom,fg-esr-timer-asleep = <256>; qcom,cycle-counter-en; diff --git a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi index 282e6bcb713b..ec07030092ca 100644 --- a/arch/arm/boot/dts/qcom/msm8996-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-camera.dtsi @@ -642,6 +642,8 @@ <106 512 0 0>, <106 512 0 0>; qcom,msm-bus-vector-dyn-vote; + qcom,src-clock-rates = <100000000 200000000 320000000 + 480000000 640000000>; qcom,cpp-fw-payload-info { qcom,stripe-base = <553>; qcom,plane-base = <481>; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi index 1a7f759f4b63..505b13aeb342 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-cdp.dtsi @@ -327,6 +327,49 @@ qcom,clock-rates = <24000000 0>; }; + qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <90>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 9 0>, + <&pm2falcon_gpios 3 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + qcom,camera@2 { cell-index = <2>; compatible = "qcom,camera"; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi index 1a7f759f4b63..505b13aeb342 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi @@ -327,6 +327,49 @@ qcom,clock-rates = <24000000 0>; }; + qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <90>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 9 0>, + <&pm2falcon_gpios 3 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + qcom,camera@2 { cell-index = <2>; compatible = "qcom,camera"; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi new file mode 100644 index 000000000000..d10c2a25b301 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + tlmm: pinctrl@03400000 { + cam_sensor_rear_active: cam_sensor_rear_active { + /* RESET, STANDBY */ + mux { + pins = "gpio9", "gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio9", "gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_suspend: cam_sensor_rear_suspend { + /* RESET, STANDBY */ + mux { + pins = "gpio9", "gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio9", "gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear2_active: cam_sensor_rear2_active { + /* RESET, STANDBY */ + mux { + pins = "gpio30", "gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio30", "gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear2_suspend: cam_sensor_rear2_suspend { + /* RESET, STANDBY */ + mux { + pins = "gpio30", "gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio30", "gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front_active: cam_sensor_front_active { + /* RESET */ + mux { + pins = "gpio28","gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio28","gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + cam_sensor_front_suspend: cam_sensor_front_suspend { + /* RESET */ + mux { + pins = "gpio28","gpio8"; + function = "gpio"; + }; + + config { + pins = "gpio28","gpio8"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + }; + + qcom,csiphy@ca34000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca35000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csiphy@ca36000 { + qcom,clock-rates = <0 0 0 0 0 0 384000000 0 0 269333333 0 + 0 384000000 0>; + }; + + qcom,csid@ca30000 { + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,cam-vreg-min-voltage = <925000 0 0>; + qcom,cam-vreg-max-voltage = <925000 0 0>; + qcom,cam-vreg-op-mode = <0 0 0>; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30400 { + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,cam-vreg-min-voltage = <925000 0 0>; + qcom,cam-vreg-max-voltage = <925000 0 0>; + qcom,cam-vreg-op-mode = <0 0 0>; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30800 { + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,cam-vreg-min-voltage = <925000 0 0>; + qcom,cam-vreg-max-voltage = <925000 0 0>; + qcom,cam-vreg-op-mode = <0 0 0>; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; + + qcom,csid@ca30c00 { + qcom,csi-vdd-voltage = <1200000>; + qcom,mipi-csi-vdd-supply = <&pmfalcon_l1>; + gdscr-supply = <&gdsc_camss_top>; + vdd_sec-supply = <&pm2falcon_l1>; + bimc_smmu-supply = <&gdsc_bimc_smmu>; + qcom,cam-vreg-name = "vdd_sec", "gdscr", "bimc_smmu"; + qcom,cam-vreg-min-voltage = <925000 0 0>; + qcom,cam-vreg-max-voltage = <925000 0 0>; + qcom,cam-vreg-op-mode = <0 0 0>; + qcom,clock-rates = <0 0 0 0 0 0 0 384000000 384000000 + 0 0 0 0 0>; + }; +}; + +&cci { + /delete-node/qcom,camera@0; + /delete-node/qcom,camera@1; + /delete-node/qcom,camera@2; + /delete-node/qcom,eeprom@0; + /delete-node/qcom,eeprom@1; + /delete-node/qcom,eeprom@2; + /delete-node/qcom,actuator@0; + /delete-node/qcom,actuator@1; + /delete-node/qcom,ois@0; +}; + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 0>; + qcom,gpio-vaf = <0>; + qcom,gpio-req-tbl-num = <0>; + qcom,gpio-req-tbl-flags = <0>; + qcom,gpio-req-tbl-label = "CAM_VAF"; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_actuator_vaf_active>; + pinctrl-1 = <&cam_actuator_vaf_suspend>; + }; + + actuator1: qcom,actuator@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 0>; + qcom,gpio-vaf = <0>; + qcom,gpio-req-tbl-num = <0>; + qcom,gpio-req-tbl-flags = <0>; + qcom,gpio-req-tbl-label = "CAM_VAF"; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_actuator_vaf_active>; + pinctrl-1 = <&cam_actuator_vaf_suspend>; + }; + + ois0: qcom,ois@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,ois"; + qcom,cci-master = <0>; + gpios = <&tlmm 27 0>; + qcom,gpio-vaf = <0>; + qcom,gpio-req-tbl-num = <0>; + qcom,gpio-req-tbl-flags = <0>; + qcom,gpio-req-tbl-label = "CAM_VAF"; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_actuator_vaf_active>; + pinctrl-1 = <&cam_actuator_vaf_suspend>; + status = "disabled"; + }; + + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + reg = <0>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1750000 3300000 1352000>; + qcom,cam-vreg-max-voltage = <1980000 3600000 1352000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 9 0>, + <&pm2falcon_gpios 4 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <1>; + reg = <0x1>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1750000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1980000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 30 0>, + <&pm2falcon_gpios 4 0>, + <&tlmm 8 0>, + <&tlmm 27 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-vaf = <4>; + qcom,gpio-req-tbl-num = <0 1 2 3 4>; + qcom,gpio-req-tbl-flags = <1 0 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_VDIG1", + "CAM_VANA1", + "CAM_VAF"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom2: qcom,eeprom@2 { + cell-index = <2>; + reg = <0x2>; + compatible = "qcom,eeprom"; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 33000000 1352000>; + qcom,cam-vreg-max-voltage = <1950000 36000000 1352000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_front_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_front_suspend>; + gpios = <&tlmm 14 0>, + <&tlmm 28 0>, + <&pm2falcon_gpios 3 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk1_clk_src>, + <&clock_mmss clk_mmss_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <90>; + qcom,actuator-src = <&actuator0>; + /*qcom,ois-src = <&ois0>;*/ + qcom,eeprom-src = <&eeprom0>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 9 0>, + <&pm2falcon_gpios 4 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET0", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_mmss_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@1 { + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <90>; + qcom,actuator-src = <&actuator1>; + qcom,eeprom-src = <&eeprom1>; + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_active + &cam_sensor_rear2_active>; + pinctrl-1 = <&cam_sensor_mclk2_suspend + &cam_sensor_rear2_suspend>; + gpios = <&tlmm 15 0>, + <&tlmm 30 0>, + <&pm2falcon_gpios 4 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1", + "CAM_VDIG1", + "CAM_VANA1"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_mmss clk_mclk2_clk_src>, + <&clock_mmss clk_mmss_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@2 { + cell-index = <2>; + compatible = "qcom,camera"; + reg = <0x02>; + qcom,csiphy-sd-index = <2>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <270>; + /*qcom,eeprom-src = <&eeprom2>;*/ + cam_vio-supply = <&pmfalcon_l11>; + cam_vana-supply = <&pm2falcon_bob>; + cam_vdig-supply = <&pmfalcon_s5>; + qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig"; + qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>; + qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>; + qcom,cam-vreg-op-mode = <105000 80000 105000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_active + &cam_sensor_front_active>; + pinctrl-1 = <&cam_sensor_mclk1_suspend + &cam_sensor_front_suspend>; + gpios = <&tlmm 14 0>, + <&tlmm 28 0>, + <&pm2falcon_gpios 3 0>, + <&tlmm 8 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vdig = <2>; + qcom,gpio-vana = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VDIG", + "CAM_VANA"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_mmss clk_mclk1_clk_src>, + <&clock_mmss clk_mmss_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; +}; + +&pm2falcon_gpios { + gpio@c300 { /* GPIO4 -CAMERA SENSOR 0 VDIG*/ + qcom,mode = <1>; /* Output */ + qcom,pull = <5>; /* No Pull */ + qcom,vin-sel = <0>; /* VIN1 GPIO_LV */ + qcom,src-sel = <0>; /* GPIO */ + qcom,invert = <0>; /* Invert */ + qcom,master-en = <1>; /* Enable GPIO */ + status = "ok"; + }; + + gpio@c200 { /* GPIO3 -CAMERA SENSOR 2 VDIG*/ + qcom,mode = <1>; /* Output */ + qcom,pull = <5>; /* No Pull */ + qcom,vin-sel = <0>; /* VIN1 GPIO_LV */ + qcom,src-sel = <0>; /* GPIO */ + qcom,invert = <0>; /* Invert */ + qcom,master-en = <1>; /* Enable GPIO */ + status = "ok"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi index 437b054a6ad0..292bc07c679a 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-cdp.dtsi @@ -12,33 +12,6 @@ #include "msm8998-pinctrl.dtsi" #include "msm8998-camera-sensor-cdp.dtsi" -/ { - bluetooth: bt_wcn3990 { - status = "disabled"; - compatible = "qca,wcn3990"; - qca,bt-vdd-io-supply = <&pm8998_s3>; - qca,bt-vdd-xtal-supply = <&pm8998_s5>; - qca,bt-vdd-core-supply = <&pm8998_l7_pin_ctrl>; - qca,bt-vdd-pa-supply = <&pm8998_l17_pin_ctrl>; - qca,bt-vdd-ldo-supply = <&pm8998_l25_pin_ctrl>; - qca,bt-chip-pwd-supply = <&pmi8998_bob_pin1>; - clocks = <&clock_gcc clk_rf_clk2>; - clock-names = "rf_clk2"; - - qca,bt-vdd-io-voltage-level = <1352000 1352000>; - qca,bt-vdd-xtal-voltage-level = <2040000 2040000>; - qca,bt-vdd-core-voltage-level = <1800000 1800000>; - qca,bt-vdd-pa-voltage-level = <1304000 1304000>; - qca,bt-vdd-ldo-voltage-level = <3312000 3312000>; - qca,bt-chip-pwd-voltage-level = <3600000 3600000>; - - qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */ - }; -}; &blsp1_uart3_hs { status = "ok"; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi index e9c64c12c419..9a1e148c46a0 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon-mtp.dtsi @@ -13,33 +13,6 @@ #include #include "msm8998-pinctrl.dtsi" #include "msm8998-camera-sensor-mtp.dtsi" -/ { - bluetooth: bt_wcn3990 { - status = "disabled"; - compatible = "qca,wcn3990"; - qca,bt-vdd-io-supply = <&pm8998_s3>; - qca,bt-vdd-xtal-supply = <&pm8998_s5>; - qca,bt-vdd-core-supply = <&pm8998_l7_pin_ctrl>; - qca,bt-vdd-pa-supply = <&pm8998_l17_pin_ctrl>; - qca,bt-vdd-ldo-supply = <&pm8998_l25_pin_ctrl>; - qca,bt-chip-pwd-supply = <&pmi8998_bob_pin1>; - clocks = <&clock_gcc clk_rf_clk2>; - clock-names = "rf_clk2"; - - qca,bt-vdd-io-voltage-level = <1352000 1352000>; - qca,bt-vdd-xtal-voltage-level = <2040000 2040000>; - qca,bt-vdd-core-voltage-level = <1800000 1800000>; - qca,bt-vdd-pa-voltage-level = <1304000 1304000>; - qca,bt-vdd-ldo-voltage-level = <3312000 3312000>; - qca,bt-chip-pwd-voltage-level = <3600000 3600000>; - - qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */ - qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */ - }; -}; &blsp1_uart3_hs { status = "ok"; diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon.dtsi index e57573166b7b..7cf02e09e785 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-msmfalcon.dtsi @@ -340,6 +340,25 @@ label = "cont_splash_mem"; }; }; + + bluetooth: bt_wcn3990 { + compatible = "qca,wcn3990"; + qca,bt-vdd-core-supply = <&pmfalcon_l9_pin_ctrl>; + qca,bt-vdd-pa-supply = <&pmfalcon_l6_pin_ctrl>; + qca,bt-vdd-ldo-supply = <&pmfalcon_l19_pin_ctrl>; + qca,bt-chip-pwd-supply = <&pm2falcon_bob_pin1>; + clocks = <&clock_gcc clk_rf_clk1>; + clock-names = "rf_clk1"; + + qca,bt-vdd-core-voltage-level = <1800000 1900000>; + qca,bt-vdd-pa-voltage-level = <1304000 1370000>; + qca,bt-vdd-ldo-voltage-level = <3312000 3400000>; + qca,bt-chip-pwd-voltage-level = <3600000 3600000>; + + qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */ + qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */ + qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */ + }; }; #include "msm8998-smp2p.dtsi" diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi index 6ecda1a9548d..fe47565fc1de 100644 --- a/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-interposer-pmfalcon.dtsi @@ -65,15 +65,6 @@ }; -&bluetooth { - /delete-property/qca,bt-vdd-io-supply; - /delete-property/qca,bt-vdd-xtal-supply; - /delete-property/qca,bt-vdd-core-supply; - /delete-property/qca,bt-vdd-pa-supply; - /delete-property/qca,bt-vdd-ldo-supply; - /delete-property/qca,bt-chip-pwd-supply; -}; - &sdhc_2 { /delete-property/vdd-supply; /delete-property/vdd-io-supply; diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dts b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dts index 013c849c4936..cf313cfea768 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dts +++ b/arch/arm/boot/dts/qcom/msm8998-v2.1-interposer-msmfalcon-qrd.dts @@ -16,7 +16,7 @@ #include "msm8998-v2.1-interposer-msmfalcon-qrd.dtsi" #include "msm8998-interposer-pmfalcon.dtsi" #include "msm8998-interposer-msmfalcon-audio.dtsi" -#include "msm8998-interposer-camera-sensor-mtp.dtsi" +#include "msm8998-interposer-camera-sensor-qrd.dtsi" / { model = diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index cc4e48ede2ad..99975877658d 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi @@ -515,37 +515,37 @@ <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, /* Speed bin 1 */ <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, /* Speed bin 2 */ <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, /* Speed bin 3 */ <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, <40000 24000 12000 30000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>, - <25000 9000 (-3000) 15000>; + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>, + <40000 24000 12000 30000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ @@ -553,37 +553,89 @@ <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, /* Speed bin 1 */ <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, /* Speed bin 2 */ <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, /* Speed bin 3 */ <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, <20000 26000 12000 30000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>, - < 5000 11000 (-3000) 15000>; + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>, + <20000 26000 12000 30000>; + + qcom,cpr-open-loop-voltage-adjustment = + /* Speed bin 0 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-12000) (-12000) (-12000) (-12000) + (-12000) (-16000) (-16000) (-20000) (-24000) + (-28000) (-28000)>, + /* Speed bin 1 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-12000) (-12000) (-12000) (-12000) + (-12000) (-16000) (-16000) (-20000) (-24000) + (-28000) (-28000)>, + /* Speed bin 2 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-12000) (-12000) (-12000) (-12000) + (-12000) (-16000) (-16000) (-20000) (-24000) + (-28000) (-28000)>, + /* Speed bin 3 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-12000) (-12000) (-12000) (-12000) + (-12000) (-16000) (-16000) (-20000) (-24000) + (-28000) (-28000)>; + + qcom,cpr-closed-loop-voltage-adjustment = + /* Speed bin 0 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-7000) (-8000) + (-10000) (-10000) (-11000) (-12000) (-13000) + (-14000) (-14000) (-15000) (-21000) (-24000) + (-26000) (-28000)>, + /* Speed bin 1 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-7000) (-8000) + (-10000) (-10000) (-11000) (-12000) (-13000) + (-14000) (-14000) (-15000) (-21000) (-24000) + (-26000) (-28000)>, + /* Speed bin 2 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-7000) (-8000) + (-10000) (-10000) (-11000) (-12000) (-13000) + (-14000) (-14000) (-15000) (-21000) (-24000) + (-26000) (-28000)>, + /* Speed bin 3 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-7000) (-8000) + (-10000) (-10000) (-11000) (-12000) (-13000) + (-14000) (-14000) (-15000) (-21000) (-24000) + (-26000) (-28000)>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; @@ -591,11 +643,7 @@ qcom,cpr-aging-ref-corner = <22>; qcom,cpr-aging-ro-scaling-factor = <1620>; - qcom,allow-aging-voltage-adjustment = - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>; + qcom,allow-aging-voltage-adjustment = <0>; }; &apc1_cpr { @@ -802,37 +850,37 @@ < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, /* Speed bin 1 */ < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, /* Speed bin 2 */ < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, /* Speed bin 3 */ < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, < 8000 0 12000 52000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>, - <(-7000) (-15000) (-3000) 37000>; + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>, + < 8000 0 12000 52000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = /* Speed bin 0 */ @@ -840,37 +888,101 @@ < 0 0 12000 50000>, < 0 0 12000 50000>, < 0 0 12000 50000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, /* Speed bin 1 */ < 0 0 12000 50000>, < 0 0 12000 50000>, < 0 0 12000 50000>, < 0 0 12000 50000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + /* Speed bin 2 */ + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + /* Speed bin 3 */ + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>, + < 0 0 12000 50000>; + + qcom,cpr-open-loop-voltage-adjustment = /* Speed bin 0 */ - < 0 0 12000 50000>, - < 0 0 12000 50000>, - < 0 0 12000 50000>, - < 0 0 12000 50000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-8000) (-12000) (-12000) (-12000) + (-12000) (-12000) (-12000) (-16000) (-16000) + (-20000) (-20000) (-24000) (-24000) (-24000) + (-28000) (-28000) (-28000) (-28000) (-28000) + (-28000) (-28000)>, /* Speed bin 1 */ - < 0 0 12000 50000>, - < 0 0 12000 50000>, - < 0 0 12000 50000>, - < 0 0 12000 50000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>, - <(-15000) (-15000) (-3000) 35000>; + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-8000) (-12000) (-12000) (-12000) + (-12000) (-12000) (-12000) (-16000) (-16000) + (-20000) (-20000) (-24000) (-24000) (-28000) + (-28000)>, + /* Speed bin 2 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-8000) (-12000) (-12000) (-12000) + (-12000) (-12000) (-12000) (-16000) (-16000) + (-20000) (-20000) (-24000) (-24000) (-24000) + (-28000) (-28000) (-28000) (-28000) (-28000)>, + /* Speed bin 3 */ + <(-4000) (-4000) (-4000) (-4000) (-4000) + (-4000) (-4000) (-4000) (-8000) (-8000) + (-8000) (-8000) (-12000) (-12000) (-12000) + (-12000) (-12000) (-12000) (-16000) (-16000) + (-20000) (-20000) (-24000) (-24000) (-24000) + (-28000) (-28000) (-28000) (-28000) (-28000) + (-28000)>; + + qcom,cpr-closed-loop-voltage-adjustment = + /* Speed bin 0 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-6000) (-7000) + (-9000) (-10000) (-10000) (-11000) (-12000) + (-12000) (-13000) (-14000) (-14000) (-15000) + (-18000) (-21000) (-24000) (-25000) (-25000) + (-26000) (-26000) (-27000) (-27000) (-28000) + (-28000) (-28000)>, + /* Speed bin 1 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-6000) (-7000) + (-9000) (-10000) (-10000) (-11000) (-12000) + (-12000) (-13000) (-14000) (-14000) (-15000) + (-18000) (-21000) (-24000) (-26000) (-27000) + (-28000)>, + /* Speed bin 2 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-6000) (-7000) + (-9000) (-10000) (-10000) (-11000) (-12000) + (-12000) (-13000) (-14000) (-14000) (-15000) + (-18000) (-21000) (-24000) (-25000) (-26000) + (-27000) (-27000) (-28000) (-28000) (-28000)>, + /* Speed bin 3 */ + <(-5000) (-5000) (-5000) (-5000) (-5000) + (-5000) (-5000) (-5000) (-6000) (-7000) + (-9000) (-10000) (-10000) (-11000) (-12000) + (-12000) (-13000) (-14000) (-14000) (-15000) + (-18000) (-21000) (-24000) (-25000) (-26000) + (-26000) (-27000) (-27000) (-28000) (-28000) + (-28000)>; qcom,allow-voltage-interpolation; qcom,allow-quotient-interpolation; @@ -878,11 +990,7 @@ qcom,cpr-aging-ref-corner = <32 26 30 31>; qcom,cpr-aging-ro-scaling-factor = <1700>; - qcom,allow-aging-voltage-adjustment = - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>, - <0 0 0 0 1 1 1 1>; + qcom,allow-aging-voltage-adjustment = <0>; }; &pm8005_s1 { @@ -964,11 +1072,11 @@ < 60000 0 0 0>, < 60000 0 0 0>, < 60000 0 0 0>, - < 45000 (-15000) (-15000) (-15000)>, - < 45000 (-15000) (-15000) (-15000)>, - < 45000 (-15000) (-15000) (-15000)>, - < 45000 (-15000) (-15000) (-15000)>, - < 45000 (-15000) (-15000) (-15000)>; + < 60000 0 0 0>, + < 60000 0 0 0>, + < 60000 0 0 0>, + < 60000 0 0 0>, + < 60000 0 0 0>; qcom,cpr-closed-loop-voltage-adjustment = < 90000 38000 28000 8000 @@ -977,19 +1085,19 @@ 0 29000 11000 0>, < 90000 38000 28000 8000 0 29000 11000 0>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>, - < 75000 23000 13000 (-7000) - (-15000) 14000 (-4000) (-15000)>; + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>, + < 90000 38000 28000 8000 + 0 29000 11000 0>; qcom,cpr-floor-to-ceiling-max-range = - <50000 50000 50000 50000 50000 50000 70000 70000>; + <40000 40000 40000 40000 40000 40000 50000 50000>; qcom,cpr-fused-closed-loop-voltage-adjustment-map = <0 0 0 0 1 2 3 4>; @@ -1000,7 +1108,7 @@ qcom,cpr-aging-max-voltage-adjustment = <15000>; qcom,cpr-aging-ref-corner = <8>; qcom,cpr-aging-ro-scaling-factor = <1620>; - qcom,allow-aging-voltage-adjustment = <0 0 0 1 1 1 1 1>; + qcom,allow-aging-voltage-adjustment = <0>; }; &qusb_phy0 { diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 8deeafccb89b..f570819fa70f 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -2248,6 +2248,7 @@ qcom,support-fde; qcom,no-clock-support; qcom,appsbl-qseecom-support; + qcom,fde-key-size; qcom,commonlib64-loaded-by-uefi; qcom,msm-bus,name = "qseecom-noc"; qcom,msm-bus,num-cases = <4>; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-cdp.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-cdp.dtsi index 3ec991b82bba..ff14003877d1 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon-cdp.dtsi @@ -20,5 +20,26 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm2falcon_l1>; + vdda-pll-supply = <&pmfalcon_l10>; + vddp-ref-clk-supply = <&pmfalcon_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm2falcon_l4>; + vccq2-supply = <&pmfalcon_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-mtp.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-mtp.dtsi index 3ec991b82bba..ff14003877d1 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon-mtp.dtsi @@ -20,5 +20,26 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm2falcon_l1>; + vdda-pll-supply = <&pmfalcon_l10>; + vddp-ref-clk-supply = <&pmfalcon_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm2falcon_l4>; + vccq2-supply = <&pmfalcon_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-qrd.dts b/arch/arm/boot/dts/qcom/msmfalcon-qrd.dts new file mode 100644 index 000000000000..229676f17456 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmfalcon-qrd.dts @@ -0,0 +1,23 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "msmfalcon.dtsi" +#include "msmfalcon-qrd.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM FALCON QRD"; + compatible = "qcom,msmfalcon-qrd", "qcom,msmfalcon", "qcom,qrd"; + qcom,board-id = <0x1000b 0>; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-qrd.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-qrd.dtsi new file mode 100644 index 000000000000..3ec991b82bba --- /dev/null +++ b/arch/arm/boot/dts/qcom/msmfalcon-qrd.dtsi @@ -0,0 +1,24 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msmfalcon-pinctrl.dtsi" +/ { +}; + +&uartblsp1dm1 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; + +&soc { +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts index d952c3b5e299..ab61ee115782 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts @@ -117,3 +117,23 @@ compatible = "qcom,dummycc"; clock-output-names = "mmss_clocks"; }; + +&ufsphy1 { + vdda-phy-supply = <&pm2falcon_l1>; + vdda-pll-supply = <&pmfalcon_l10>; + vddp-ref-clk-supply = <&pmfalcon_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm2falcon_l4>; + vccq2-supply = <&pmfalcon_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + qcom,disable-lpm; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts index fe92f40d786f..80772bab86e4 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts +++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts @@ -86,3 +86,24 @@ &pmfalcon_pdphy { status = "disabled"; }; + +&ufsphy1 { + vdda-phy-supply = <&pm2falcon_l1>; + vdda-pll-supply = <&pmfalcon_l10>; + vddp-ref-clk-supply = <&pmfalcon_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm2falcon_l4>; + vccq2-supply = <&pmfalcon_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index 9ce04f8e9ac2..ce6c5cf6c9b1 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -725,6 +725,11 @@ }; }; + qcom,lmh { + compatible = "qcom,lmh_v1"; + interrupts = ; + }; + qcom,msm-core@780000 { compatible = "qcom,apss-core-ea"; reg = <0x780000 0x1000>; @@ -1431,6 +1436,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; qcom,ghd { @@ -1583,6 +1593,85 @@ qcom,config-arr = <0x178880b8 0x178980b8 0x178a80b8 0x178b80b8>; }; + + ufsphy1: ufsphy@1da7000 { + compatible = "qcom,ufs-phy-qmp-v3-falcon"; + reg = <0x1da7000 0xdb8>; + reg-names = "phy_mem"; + #phy-cells = <0>; + clock-names = "ref_clk_src", + "ref_clk", + "ref_aux_clk"; + clocks = <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AUX_CLK>; + status = "disabled"; + }; + + ufs1: ufshc@1da4000 { + compatible = "qcom,ufshc"; + reg = <0x1da4000 0x3000>; + interrupts = <0 265 0>; + phys = <&ufsphy1>; + phy-names = "ufsphy"; + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "core_clk_ice", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk"; + clocks = + <&clock_gcc GCC_UFS_AXI_CLK>, + <&clock_gcc GCC_AGGRE2_UFS_AXI_CLK>, + <&clock_gcc GCC_UFS_AHB_CLK>, + <&clock_gcc GCC_UFS_UNIPRO_CORE_CLK>, + <&clock_gcc GCC_UFS_ICE_CORE_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_TX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_RX_SYMBOL_0_CLK>; + freq-table-hz = + <50000000 200000000>, + <0 0>, + <0 0>, + <37500000 150000000>, + <75000000 300000000>, + <0 0>, + <0 0>, + <0 0>; + + lanes-per-direction = <1>; + + qcom,msm-bus,name = "ufs1"; + qcom,msm-bus,num-cases = <12>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <95 512 0 0>, <1 650 0 0>, /* No vote */ + <95 512 922 0>, <1 650 1000 0>, /* PWM G1 */ + <95 512 1844 0>, <1 650 1000 0>, /* PWM G2 */ + <95 512 3688 0>, <1 650 1000 0>, /* PWM G3 */ + <95 512 7376 0>, <1 650 1000 0>, /* PWM G4 */ + <95 512 127796 0>, <1 650 1000 0>, /* HS G1 RA */ + <95 512 255591 0>, <1 650 1000 0>, /* HS G2 RA */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RA */ + <95 512 149422 0>, <1 650 1000 0>, /* HS G1 RB */ + <95 512 298189 0>, <1 650 1000 0>, /* HS G2 RB */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RB */ + <95 512 7643136 0>, <1 650 307200 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1", + "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1", + "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1", + "MAX"; + + resets = <&clock_gcc GCC_UFS_BCR>; + reset-names = "core_reset"; + + status = "disabled"; + }; }; #include "msmfalcon-ion.dtsi" diff --git a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi index 323024278406..2201a04cfbc1 100644 --- a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi @@ -10,351 +10,483 @@ * GNU General Public License for more details. */ +&rpm_bus { + rpm-regulator-smpa4 { + status = "okay"; + pmfalcon_s4: regulator-s4 { + regulator-min-microvolt = <1805000>; + regulator-max-microvolt = <2040000>; + status = "okay"; + }; + }; + + rpm-regulator-smpa5 { + status = "okay"; + pmfalcon_s5: regulator-s5 { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + status = "okay"; + }; + }; + + rpm-regulator-smpa6 { + status = "okay"; + pmfalcon_s6: regulator-s6 { + regulator-min-microvolt = <504000>; + regulator-max-microvolt = <992000>; + status = "okay"; + }; + }; + + rpm-regulator-smpb1 { + status = "okay"; + pm2falcon_s1: regulator-s1 { + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + status = "okay"; + }; + }; + + rpm-regulator-smpb2 { + status = "okay"; + pm2falcon_s2: regulator-s2 { + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + status = "okay"; + }; + }; + + /* PM2FALCON S3 + S4 - VDD_CX supply */ + rpm-regulator-smpb3 { + status = "okay"; + pm2falcon_s3_level: regulator-s3-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + + pm2falcon_s3_floor_level: regulator-s3-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + + pm2falcon_s3_level_ao: regulator-s3-level-ao { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s3_level_ao"; + qcom,set = <1>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + }; + + /* PM2FALCON S5 - VDD_MX supply */ + rpm-regulator-smpb5 { + status = "okay"; + pm2falcon_s5_level: regulator-s5-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + + pm2falcon_s5_floor_level: regulator-s5-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + + pm2falcon_s5_level_ao: regulator-s5-level-ao { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_s5_level_ao"; + qcom,set = <1>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + }; + + rpm-regulator-ldoa1 { + status = "okay"; + pmfalcon_l1: regulator-l1 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa2 { + status = "okay"; + pmfalcon_l2: regulator-l2 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa3 { + status = "okay"; + pmfalcon_l3: regulator-l3 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa5 { + status = "okay"; + pmfalcon_l5: regulator-l5 { + regulator-min-microvolt = <525000>; + regulator-max-microvolt = <950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa6 { + status = "okay"; + pmfalcon_l6: regulator-l6 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1370000>; + status = "okay"; + }; + + pmfalcon_l6_pin_ctrl: regulator-l6-pin-ctrl { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l6_pin_ctrl"; + qcom,set = <3>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1370000>; + /* Force NPM follows HW_EN1 */ + qcom,init-pin-ctrl-mode = <2>; + /* Enable follows HW_EN1 */ + qcom,enable-with-pin-ctrl = <0 2>; + }; + }; + + rpm-regulator-ldoa7 { + status = "okay"; + pmfalcon_l7: regulator-l7 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa8 { + status = "okay"; + pmfalcon_l8: regulator-l8 { + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa9 { + status = "okay"; + pmfalcon_l9: regulator-l9 { + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + + pmfalcon_l9_pin_ctrl: regulator-l9-pin-ctrl { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l9_pin_ctrl"; + qcom,set = <3>; + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + /* Force NPM follows HW_EN1 */ + qcom,init-pin-ctrl-mode = <2>; + /* Enable follows HW_EN1 */ + qcom,enable-with-pin-ctrl = <0 2>; + }; + }; + + rpm-regulator-ldoa10 { + status = "okay"; + pmfalcon_l10: regulator-l10 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa11 { + status = "okay"; + pmfalcon_l11: regulator-l11 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa12 { + status = "okay"; + pmfalcon_l12: regulator-l12 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa13 { + status = "okay"; + pmfalcon_l13: regulator-l13 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa14 { + status = "okay"; + pmfalcon_l14: regulator-l14 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa15 { + status = "okay"; + pmfalcon_l15: regulator-l15 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa17 { + status = "okay"; + pmfalcon_l17: regulator-l17 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldoa19 { + status = "okay"; + pmfalcon_l19: regulator-l19 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + status = "okay"; + }; + + pmfalcon_l19_pin_ctrl: regulator-l19-pin-ctrl { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pmfalcon_l19_pin_ctrl"; + qcom,set = <3>; + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + /* Force NPM follows HW_EN1 */ + qcom,init-pin-ctrl-mode = <2>; + /* Enable follows HW_EN1 */ + qcom,enable-with-pin-ctrl = <0 2>; + }; + }; + + rpm-regulator-ldob1 { + status = "okay"; + pm2falcon_l1: regulator-l1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <925000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob2 { + status = "okay"; + pm2falcon_l2: regulator-l2 { + regulator-min-microvolt = <350000>; + regulator-max-microvolt = <3100000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob3 { + status = "okay"; + pm2falcon_l3: regulator-l3 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob4 { + status = "okay"; + pm2falcon_l4: regulator-l4 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob5 { + status = "okay"; + pm2falcon_l5: regulator-l5 { + regulator-min-microvolt = <1721000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob6 { + status = "okay"; + pm2falcon_l6: regulator-l6 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3300000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob7 { + status = "okay"; + pm2falcon_l7: regulator-l7 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3125000>; + status = "okay"; + }; + }; + + rpm-regulator-ldob8 { + status = "okay"; + pm2falcon_l8: regulator-l8 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + status = "okay"; + }; + }; + + /* PM2FALCON L9 = VDD_SSC_CX supply */ + rpm-regulator-ldob9 { + status = "okay"; + pm2falcon_l9_level: regulator-l9-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l9_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + + pm2falcon_l9_floor_level: regulator-l9-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l9_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + }; + + /* PM2FALCON L10 = VDD_SSC_MX supply */ + rpm-regulator-ldob10 { + status = "okay"; + pm2falcon_l10_level: regulator-l10-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l10_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-level; + }; + + pm2falcon_l10_floor_level: regulator-l10-floor-level { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_l10_floor_level"; + qcom,set = <3>; + regulator-min-microvolt = + ; + regulator-max-microvolt = + ; + qcom,use-voltage-floor-level; + qcom,always-send-voltage; + }; + }; + + rpm-regulator-bobb { + status = "okay"; + pm2falcon_bob: regulator-bob { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; + + pm2falcon_bob_pin1: regulator-bob-pin1 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin1"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage1; + }; + + pm2falcon_bob_pin2: regulator-bob-pin2 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin2"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage2; + }; + + pm2falcon_bob_pin3: regulator-bob-pin3 { + compatible = "qcom,rpm-smd-regulator"; + regulator-name = "pm2falcon_bob_pin3"; + qcom,set = <3>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + qcom,use-pin-ctrl-voltage3; + }; + }; +}; + +&pmfalcon_charger { + smb2_vbus: qcom,smb2-vbus { + regulator-name = "smb2-vbus"; + }; + + smb2_vconn: qcom,smb2-vconn { + regulator-name = "smb2-vconn"; + }; +}; + /* Stub regulators */ - / { - /* PMFALCON S1 - VDD_APC0 supply */ - pmfalcon_s1: regulator-pmfalcon-s1 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s1"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <565000>; - regulator-max-microvolt = <1170000>; - }; - - /* PMFALCON S2 + S3 = VDD_APC1 supply */ - pmfalcon_s2: regulator-pmfalcon-s2 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s2"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <565000>; - regulator-max-microvolt = <1170000>; - }; - - pmfalcon_s4: regulator-pmfalcon-s4 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s4"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1805000>; - regulator-max-microvolt = <2040000>; - }; - - pmfalcon_s5: regulator-pmfalcon-s5 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s5"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1350000>; - regulator-max-microvolt = <1350000>; - }; - - pmfalcon_s6: regulator-pmfalcon-s6 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_s6"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <504000>; - regulator-max-microvolt = <992000>; - }; - - pm2falcon_s1: regulator-pm2falcon-s1 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s1"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1125000>; - regulator-max-microvolt = <1125000>; - }; - - pm2falcon_s2: regulator-pm2falcon-s2 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s2"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = <1050000>; - regulator-max-microvolt = <1050000>; - }; - - /* PMFALCON S3 + S4 - VDD_CX supply */ - pm2falcon_s3_level: regulator-pm2falcon-s3-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s3_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_s3_floor_level: regulator-pm2falcon-s3-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s3_floor_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_s3_level_ao: regulator-pm2falcon-s3-level-ao { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s3_level_ao"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - /* PMFALCON S5 - VDD_MX supply */ - pm2falcon_s5_level: regulator-pm2falcon-s5-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s5_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_s5_floor_level: regulator-pm2falcon-s5-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s5_floor_level"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_s5_level_ao: regulator-pm2falcon-s5-level-ao { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_s5_level_ao"; - qcom,hpm-min-load = <100000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pmfalcon_l1: regulator-pmfalcon-l1 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l1"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1150000>; - regulator-max-microvolt = <1250000>; - }; - - pmfalcon_l2: regulator-pmfalcon-l2 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l2"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1010000>; - }; - - pmfalcon_l3: regulator-pmfalcon-l3 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l3"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <950000>; - regulator-max-microvolt = <1010000>; - }; - - /* TODO: remove if ADRASTEA CX/MX not voted from APPS */ - pmfalcon_l5: regulator-pmfalcon-l5 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l5"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <525000>; - regulator-max-microvolt = <950000>; - }; - - pmfalcon_l6: regulator-pmfalcon-l6 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l6"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1370000>; - }; - - pmfalcon_l7: regulator-pmfalcon-l7 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l7"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1200000>; - }; - - pmfalcon_l8: regulator-pmfalcon-l8 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l8"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l9: regulator-pmfalcon-l9 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l9"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l10: regulator-pmfalcon-l10 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l10"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l11: regulator-pmfalcon-l11 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l11"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l12: regulator-pmfalcon-l12 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l12"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1780000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l13: regulator-pmfalcon-l13 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l13"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1750000>; - regulator-max-microvolt = <1950000>; - }; - - pmfalcon_l14: regulator-pmfalcon-l14 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l14"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1710000>; - regulator-max-microvolt = <1900000>; - }; - - pmfalcon_l15: regulator-pmfalcon-l15 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l15"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <2950000>; - }; - - pmfalcon_l17: regulator-pmfalcon-l17 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l17"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1650000>; - regulator-max-microvolt = <2950000>; - }; - - pmfalcon_l19: regulator-pmfalcon-l19 { - compatible = "qcom,stub-regulator"; - regulator-name = "pmfalcon_l19"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; - }; - - pm2falcon_l1: regulator-pm2falcon-l1 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l1"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <925000>; - }; - - pm2falcon_l2: regulator-pm2falcon-l2 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l2"; - qcom,hpm-min-load = <5000>; - regulator-min-microvolt = <350000>; - regulator-max-microvolt = <3100000>; - }; - - pm2falcon_l3: regulator-pm2falcon-l3 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l3"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1710000>; - regulator-max-microvolt = <3600000>; - }; - - pm2falcon_l4: regulator-pm2falcon-l4 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l4"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <2950000>; - }; - - pm2falcon_l5: regulator-pm2falcon-l5 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l5"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <1721000>; - regulator-max-microvolt = <3600000>; - }; - - pm2falcon_l6: regulator-pm2falcon-l6 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l6"; - qcom,hpm-min-load = <5000>; - regulator-min-microvolt = <1700000>; - regulator-max-microvolt = <3300000>; - }; - - pm2falcon_l7: regulator-pm2falcon-l7 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l7"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <2700000>; - regulator-max-microvolt = <3125000>; - }; - - pm2falcon_l8: regulator-pm2falcon-l8 { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l8"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = <3200000>; - regulator-max-microvolt = <3400000>; - }; - - /* PMFALCON L9 = VDD_SSC_CX supply */ - pm2falcon_l9_level: regulator-pm2falcon-l9-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l9_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_l9_floor_level: regulator-pm2falcon-l9-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l9_floor_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - /* PMFALCON L10 = VDD_SSC_MX supply */ - pm2falcon_l10_level: regulator-pm2falcon-l10-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l10_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_l10_floor_level: regulator-pm2falcon-l10-floor-level { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_l10_floor_level"; - qcom,hpm-min-load = <10000>; - regulator-min-microvolt = ; - regulator-max-microvolt = ; - }; - - pm2falcon_bob: regulator-pm2falcon-bob { - compatible = "qcom,stub-regulator"; - regulator-name = "pm2falcon_bob"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; - /* GFX Supply */ gfx_vreg_corner: regulator-gfx-corner { compatible = "qcom,stub-regulator"; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index 690e9e8870fd..e577a5692d90 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -960,6 +960,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; qcom,ghd { @@ -1002,9 +1007,34 @@ qcom,config-arr = <0x178880b8 0x178980b8 0x178a80b8 0x178b80b8>; }; + + spmi_bus: qcom,spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x800f000 0x1000>, + <0x8400000 0x1000000>, + <0x9400000 0x1000000>, + <0xa400000 0x220000>, + <0x800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = ; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + qcom,not-wakeup; /* Needed until Full-boot-chain enabled */ + status = "ok"; + }; }; #include "msmtriton-ion.dtsi" +#include "msm-pmfalcon.dtsi" +#include "msm-pm2falcon.dtsi" +#include "msm-pmfalcon-rpm-regulator.dtsi" +#include "msm-pm2falcon-rpm-regulator.dtsi" #include "msmtriton-regulator.dtsi" #include "msm-gdsc-falcon.dtsi" #include "msmfalcon-common.dtsi" diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig index 72c65b1cea66..b47866ae1826 100644 --- a/arch/arm/configs/msmfalcon-perf_defconfig +++ b/arch/arm/configs/msmfalcon-perf_defconfig @@ -94,6 +94,7 @@ CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y # CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y @@ -274,6 +275,7 @@ CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_CLD_LL_CORE=y @@ -529,6 +531,7 @@ CONFIG_MSM_SERVICE_NOTIFIER=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RPM_LOG=y CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_QCOM_SMCINVOKE=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_QCOM_BIMC_BWMON=y CONFIG_ARM_MEMLAT_MON=y @@ -589,7 +592,6 @@ CONFIG_PID_IN_CONTEXTIDR=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_EVENT=y -CONFIG_CORESIGHT_LINKS_AND_SINKS=y CONFIG_CORESIGHT_QCOM_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_HWEVENT=y diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index aa3ee39e616b..693588045aed 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -93,6 +93,7 @@ CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y # CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_OPTIMISTIC_DAD=y @@ -273,6 +274,7 @@ CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_CLD_LL_CORE=y @@ -518,6 +520,7 @@ CONFIG_PANIC_ON_GLADIATOR_ERROR_V2=y CONFIG_MSM_GLADIATOR_HANG_DETECT=y CONFIG_MSM_CORE_HANG_DETECT=y CONFIG_MSM_RUN_QUEUE_STATS=y +# CONFIG_MSM_JTAGV8 is not set CONFIG_MSM_BOOT_STATS=y CONFIG_QCOM_CPUSS_DUMP=y CONFIG_MSM_QDSP6_APRV2_GLINK=y @@ -537,6 +540,7 @@ CONFIG_MSM_SERVICE_NOTIFIER=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RPM_LOG=y CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_QCOM_SMCINVOKE=y CONFIG_QCOM_EARLY_RANDOM=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_QCOM_BIMC_BWMON=y @@ -627,7 +631,8 @@ CONFIG_PID_IN_CONTEXTIDR=y CONFIG_DEBUG_SET_MODULE_RONX=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_EVENT=y -CONFIG_CORESIGHT_LINKS_AND_SINKS=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_SOURCE_ETM4X=y CONFIG_CORESIGHT_REMOTE_ETM=y CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 CONFIG_CORESIGHT_QCOM_REPLICATOR=y diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 60bb033be6df..85ce3e119ebc 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -592,8 +592,6 @@ CONFIG_DEBUG_RODATA=y CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_EVENT=y -CONFIG_CORESIGHT_LINKS_AND_SINKS=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y CONFIG_CORESIGHT_QCOM_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_HWEVENT=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 1ef2d90f13de..8d5e16bbe4f9 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -261,13 +261,13 @@ CONFIG_BONDING=y CONFIG_DUMMY=y CONFIG_TUN=y CONFIG_RNDIS_IPA=y -CONFIG_PHYLIB=y CONFIG_PPP=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_DEFLATE=y CONFIG_PPP_MPPE=y CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y +CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig index 4d641012da4e..702952ceafa0 100644 --- a/arch/arm64/configs/msmfalcon_defconfig +++ b/arch/arm64/configs/msmfalcon_defconfig @@ -271,6 +271,7 @@ CONFIG_PPPOLAC=y CONFIG_PPPOPNS=y CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 1046c262b46b..8e3bff9c7fe9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -606,13 +606,20 @@ config TILE_SROM source "drivers/char/xillybus/Kconfig" config MSM_ADSPRPC - tristate "Qualcomm ADSP RPC driver" - depends on MSM_SMD - help - Provides a communication mechanism that allows for clients to - make remote method invocations across processor boundary to - applications DSP processor. Say M if you want to enable this - module. + tristate "QTI ADSP RPC driver" + depends on MSM_SMD + help + Provides a communication mechanism that allows for clients to + make remote method invocations across processor boundary to + applications DSP processor. Say M if you want to enable this + module. + +config MSM_RDBG + tristate "QTI Remote debug driver" + help + Implements a shared memory based transport mechanism that allows + for a debugger running on a host PC to communicate with a remote + stub running on peripheral subsystems such as the ADSP, MODEM etc. endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index e180562c725e..7b0bd5408324 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -65,3 +65,4 @@ obj-$(CONFIG_MSM_ADSPRPC) += adsprpc.o ifdef CONFIG_COMPAT obj-$(CONFIG_MSM_ADSPRPC) += adsprpc_compat.o endif +obj-$(CONFIG_MSM_RDBG) += rdbg.o diff --git a/drivers/char/rdbg.c b/drivers/char/rdbg.c new file mode 100644 index 000000000000..0823ed78485e --- /dev/null +++ b/drivers/char/rdbg.c @@ -0,0 +1,1165 @@ +/* + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMP2P_NUM_PROCS 8 +#define MAX_RETRIES 20 + +#define SM_VERSION 1 +#define SM_BLOCKSIZE 128 + +#define SMQ_MAGIC_INIT 0xFF00FF00 +#define SMQ_MAGIC_PRODUCER (SMQ_MAGIC_INIT | 0x1) +#define SMQ_MAGIC_CONSUMER (SMQ_MAGIC_INIT | 0x2) + +enum SMQ_STATUS { + SMQ_SUCCESS = 0, + SMQ_ENOMEMORY = -1, + SMQ_EBADPARM = -2, + SMQ_UNDERFLOW = -3, + SMQ_OVERFLOW = -4 +}; + +enum smq_type { + PRODUCER = 1, + CONSUMER = 2, + INVALID = 3 +}; + +struct smq_block_map { + uint32_t index_read; + uint32_t num_blocks; + uint8_t *map; +}; + +struct smq_node { + uint16_t index_block; + uint16_t num_blocks; +} __attribute__ ((__packed__)); + +struct smq_hdr { + uint8_t producer_version; + uint8_t consumer_version; +} __attribute__ ((__packed__)); + +struct smq_out_state { + uint32_t init; + uint32_t index_check_queue_for_reset; + uint32_t index_sent_write; + uint32_t index_free_read; +} __attribute__ ((__packed__)); + +struct smq_out { + struct smq_out_state s; + struct smq_node sent[1]; +}; + +struct smq_in_state { + uint32_t init; + uint32_t index_check_queue_for_reset_ack; + uint32_t index_sent_read; + uint32_t index_free_write; +} __attribute__ ((__packed__)); + +struct smq_in { + struct smq_in_state s; + struct smq_node free[1]; +}; + +struct smq { + struct smq_hdr *hdr; + struct smq_out *out; + struct smq_in *in; + uint8_t *blocks; + uint32_t num_blocks; + struct mutex *lock; + uint32_t initialized; + struct smq_block_map block_map; + enum smq_type type; +}; + +struct gpio_info { + int gpio_base_id; + int irq_base_id; +}; + +struct rdbg_data { + struct device *device; + struct completion work; + struct gpio_info in; + struct gpio_info out; + bool device_initialized; + int gpio_out_offset; + bool device_opened; + void *smem_addr; + size_t smem_size; + struct smq producer_smrb; + struct smq consumer_smrb; + struct mutex write_mutex; +}; + +struct rdbg_device { + struct cdev cdev; + struct class *class; + dev_t dev_no; + int num_devices; + struct rdbg_data *rdbg_data; +}; + +static struct rdbg_device g_rdbg_instance = { + { {0} }, + NULL, + 0, + SMP2P_NUM_PROCS, + NULL +}; + +struct processor_specific_info { + char *name; + unsigned int smem_buffer_addr; + size_t smem_buffer_size; +}; + +static struct processor_specific_info proc_info[SMP2P_NUM_PROCS] = { + {0}, /*APPS*/ + {"rdbg_modem", 0, 0}, /*MODEM*/ + {"rdbg_adsp", SMEM_LC_DEBUGGER, 16*1024}, /*ADSP*/ + {0}, /*SMP2P_RESERVED_PROC_1*/ + {"rdbg_wcnss", 0, 0}, /*WCNSS*/ + {0}, /*SMP2P_RESERVED_PROC_2*/ + {0}, /*SMP2P_POWER_PROC*/ + {0} /*SMP2P_REMOTE_MOCK_PROC*/ +}; + +static int smq_blockmap_get(struct smq_block_map *block_map, + uint32_t *block_index, uint32_t n) +{ + uint32_t start; + uint32_t mark = 0; + uint32_t found = 0; + uint32_t i = 0; + + start = block_map->index_read; + + if (n == 1) { + do { + if (!block_map->map[block_map->index_read]) { + *block_index = block_map->index_read; + block_map->map[block_map->index_read] = 1; + block_map->index_read++; + block_map->index_read %= block_map->num_blocks; + return SMQ_SUCCESS; + } + block_map->index_read++; + } while (start != (block_map->index_read %= + block_map->num_blocks)); + } else { + mark = block_map->num_blocks; + + do { + if (!block_map->map[block_map->index_read]) { + if (mark > block_map->index_read) { + mark = block_map->index_read; + start = block_map->index_read; + found = 0; + } + + found++; + if (found == n) { + *block_index = mark; + for (i = 0; i < n; i++) + block_map->map[mark + i] = + (uint8_t)(n - i); + block_map->index_read += block_map->map + [block_map->index_read] - 1; + return SMQ_SUCCESS; + } + } else { + found = 0; + block_map->index_read += block_map->map + [block_map->index_read] - 1; + mark = block_map->num_blocks; + } + block_map->index_read++; + } while (start != (block_map->index_read %= + block_map->num_blocks)); + } + + return SMQ_ENOMEMORY; +} + +static void smq_blockmap_put(struct smq_block_map *block_map, uint32_t i) +{ + uint32_t num_blocks = block_map->map[i]; + + while (num_blocks--) { + block_map->map[i] = 0; + i++; + } +} + +static int smq_blockmap_reset(struct smq_block_map *block_map) +{ + if (!block_map->map) + return SMQ_ENOMEMORY; + memset(block_map->map, 0, block_map->num_blocks + 1); + block_map->index_read = 0; + + return SMQ_SUCCESS; +} + +static int smq_blockmap_ctor(struct smq_block_map *block_map, + uint32_t num_blocks) +{ + if (num_blocks <= 1) + return SMQ_ENOMEMORY; + + block_map->map = kcalloc(num_blocks, sizeof(uint8_t), GFP_KERNEL); + if (!block_map->map) + return SMQ_ENOMEMORY; + + block_map->num_blocks = num_blocks - 1; + smq_blockmap_reset(block_map); + + return SMQ_SUCCESS; +} + +static void smq_blockmap_dtor(struct smq_block_map *block_map) +{ + kfree(block_map->map); + block_map->map = NULL; +} + +static int smq_free(struct smq *smq, void *data) +{ + struct smq_node node; + uint32_t index_block; + int err = SMQ_SUCCESS; + + if (smq->lock) + mutex_lock(smq->lock); + + if ((smq->hdr->producer_version != SM_VERSION) && + (smq->out->s.init != SMQ_MAGIC_PRODUCER)) { + err = SMQ_UNDERFLOW; + goto bail; + } + + index_block = ((uint8_t *)data - smq->blocks) / SM_BLOCKSIZE; + if (index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + node.index_block = (uint16_t)index_block; + node.num_blocks = 0; + *((struct smq_node *)(smq->in->free + smq->in-> + s.index_free_write)) = node; + + smq->in->s.index_free_write = (smq->in->s.index_free_write + 1) + % smq->num_blocks; + +bail: + if (smq->lock) + mutex_unlock(smq->lock); + return err; +} + +static int smq_receive(struct smq *smq, void **pp, int *pnsize, int *pbmore) +{ + struct smq_node *node; + int err = SMQ_SUCCESS; + int more = 0; + + if ((smq->hdr->producer_version != SM_VERSION) && + (smq->out->s.init != SMQ_MAGIC_PRODUCER)) + return SMQ_UNDERFLOW; + + if (smq->in->s.index_sent_read == smq->out->s.index_sent_write) { + err = SMQ_UNDERFLOW; + goto bail; + } + + node = (struct smq_node *)(smq->out->sent + smq->in->s.index_sent_read); + if (node->index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + smq->in->s.index_sent_read = (smq->in->s.index_sent_read + 1) + % smq->num_blocks; + + *pp = smq->blocks + (node->index_block * SM_BLOCKSIZE); + *pnsize = SM_BLOCKSIZE * node->num_blocks; + + /* Ensure that the reads and writes are updated in the memory + * when they are done and not cached. Also, ensure that the reads + * and writes are not reordered as they are shared between two cores. + */ + rmb(); + if (smq->in->s.index_sent_read != smq->out->s.index_sent_write) + more = 1; + +bail: + *pbmore = more; + return err; +} + +static int smq_alloc_send(struct smq *smq, const uint8_t *pcb, int nsize) +{ + void *pv = 0; + int num_blocks; + uint32_t index_block = 0; + int err = SMQ_SUCCESS; + struct smq_node *node = NULL; + + mutex_lock(smq->lock); + + if ((smq->in->s.init == SMQ_MAGIC_CONSUMER) && + (smq->hdr->consumer_version == SM_VERSION)) { + if (smq->out->s.index_check_queue_for_reset == + smq->in->s.index_check_queue_for_reset_ack) { + while (smq->out->s.index_free_read != + smq->in->s.index_free_write) { + node = (struct smq_node *)( + smq->in->free + + smq->out->s.index_free_read); + if (node->index_block >= smq->num_blocks) { + err = SMQ_EBADPARM; + goto bail; + } + + smq->out->s.index_free_read = + (smq->out->s.index_free_read + 1) + % smq->num_blocks; + + smq_blockmap_put(&smq->block_map, + node->index_block); + /* Ensure that the reads and writes are + * updated in the memory when they are done + * and not cached. Also, ensure that the reads + * and writes are not reordered as they are + * shared between two cores. + */ + rmb(); + } + } + } + + num_blocks = ALIGN(nsize, SM_BLOCKSIZE)/SM_BLOCKSIZE; + err = smq_blockmap_get(&smq->block_map, &index_block, num_blocks); + if (err != SMQ_SUCCESS) + goto bail; + + pv = smq->blocks + (SM_BLOCKSIZE * index_block); + + err = copy_from_user((void *)pv, (void *)pcb, nsize); + if (err != 0) + goto bail; + + ((struct smq_node *)(smq->out->sent + + smq->out->s.index_sent_write))->index_block + = (uint16_t)index_block; + ((struct smq_node *)(smq->out->sent + + smq->out->s.index_sent_write))->num_blocks + = (uint16_t)num_blocks; + + smq->out->s.index_sent_write = (smq->out->s.index_sent_write + 1) + % smq->num_blocks; + +bail: + if (err != SMQ_SUCCESS) { + if (pv) + smq_blockmap_put(&smq->block_map, index_block); + } + mutex_unlock(smq->lock); + return err; +} + +static int smq_reset_producer_queue_internal(struct smq *smq, + uint32_t reset_num) +{ + int retval = 0; + uint32_t i; + + if (smq->type != PRODUCER) + goto bail; + + mutex_lock(smq->lock); + if (smq->out->s.index_check_queue_for_reset != reset_num) { + smq->out->s.index_check_queue_for_reset = reset_num; + for (i = 0; i < smq->num_blocks; i++) + (smq->out->sent + i)->index_block = 0xFFFF; + + smq_blockmap_reset(&smq->block_map); + smq->out->s.index_sent_write = 0; + smq->out->s.index_free_read = 0; + retval = 1; + } + mutex_unlock(smq->lock); + +bail: + return retval; +} + +static int smq_check_queue_reset(struct smq *p_cons, struct smq *p_prod) +{ + int retval = 0; + uint32_t reset_num, i; + + if ((p_cons->type != CONSUMER) || + (p_cons->out->s.init != SMQ_MAGIC_PRODUCER) || + (p_cons->hdr->producer_version != SM_VERSION)) + goto bail; + + reset_num = p_cons->out->s.index_check_queue_for_reset; + if (p_cons->in->s.index_check_queue_for_reset_ack != reset_num) { + p_cons->in->s.index_check_queue_for_reset_ack = reset_num; + for (i = 0; i < p_cons->num_blocks; i++) + (p_cons->in->free + i)->index_block = 0xFFFF; + + p_cons->in->s.index_sent_read = 0; + p_cons->in->s.index_free_write = 0; + + retval = smq_reset_producer_queue_internal(p_prod, reset_num); + } + +bail: + return retval; +} + +static int check_subsystem_debug_enabled(void *base_addr, int size) +{ + int num_blocks; + uint8_t *pb_orig; + uint8_t *pb; + struct smq smq; + int err = 0; + + pb = pb_orig = (uint8_t *)base_addr; + pb += sizeof(struct smq_hdr); + pb = PTR_ALIGN(pb, 8); + size -= pb - (uint8_t *)pb_orig; + num_blocks = (int)((size - sizeof(struct smq_out_state) - + sizeof(struct smq_in_state))/(SM_BLOCKSIZE + + sizeof(struct smq_node) * 2)); + if (num_blocks <= 0) { + err = SMQ_EBADPARM; + goto bail; + } + + pb += num_blocks * SM_BLOCKSIZE; + smq.out = (struct smq_out *)pb; + pb += sizeof(struct smq_out_state) + (num_blocks * + sizeof(struct smq_node)); + smq.in = (struct smq_in *)pb; + + if (smq.in->s.init != SMQ_MAGIC_CONSUMER) { + pr_err("%s, smq in consumer not initialized", __func__); + err = -ECOMM; + } + +bail: + return err; +} + +static void smq_dtor(struct smq *smq) +{ + if (smq->initialized == SMQ_MAGIC_INIT) { + switch (smq->type) { + case PRODUCER: + smq->out->s.init = 0; + smq_blockmap_dtor(&smq->block_map); + break; + case CONSUMER: + smq->in->s.init = 0; + break; + default: + case INVALID: + break; + } + + smq->initialized = 0; + } +} + +/* + * The shared memory is used as a circular ring buffer in each direction. + * Thus we have a bi-directional shared memory channel between the AP + * and a subsystem. We call this SMQ. Each memory channel contains a header, + * data and a control mechanism that is used to synchronize read and write + * of data between the AP and the remote subsystem. + * + * Overall SMQ memory view: + * + * +------------------------------------------------+ + * | SMEM buffer | + * |-----------------------+------------------------| + * |Producer: LA | Producer: Remote | + * |Consumer: Remote | subsystem | + * | subsystem | Consumer: LA | + * | | | + * | Producer| Consumer| + * +-----------------------+------------------------+ + * | | + * | | + * | +--------------------------------------+ + * | | + * | | + * v v + * +--------------------------------------------------------------+ + * | Header | Data | Control | + * +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ + * | | b | b | b | | S |n |n | | S |n |n | | + * | Producer | l | l | l | | M |o |o | | M |o |o | | + * | Ver | o | o | o | | Q |d |d | | Q |d |d | | + * |-----------| c | c | c | ... | |e |e | ... | |e |e | ... | + * | | k | k | k | | O | | | | I | | | | + * | Consumer | | | | | u |0 |1 | | n |0 |1 | | + * | Ver | 0 | 1 | 2 | | t | | | | | | | | + * +-----------+---+---+---+-----+----+--+--+-----+---+--+--+-----+ + * | | + * + | + * | + * +------------------------+ + * | + * v + * +----+----+----+----+ + * | SMQ Nodes | + * |----|----|----|----| + * Node # | 0 | 1 | 2 | ...| + * |----|----|----|----| + * Starting Block Index # | 0 | 3 | 8 | ...| + * |----|----|----|----| + * # of blocks | 3 | 5 | 1 | ...| + * +----+----+----+----+ + * + * Header: Contains version numbers for software compatibility to ensure + * that both producers and consumers on the AP and subsystems know how to + * read from and write to the queue. + * Both the producer and consumer versions are 1. + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 1 byte | Producer Version | + * +---------+-------------------+ + * | 1 byte | Consumer Version | + * +---------+-------------------+ + * + * Data: The data portion contains multiple blocks [0..N] of a fixed size. + * The block size SM_BLOCKSIZE is fixed to 128 bytes for header version #1. + * Payload sent from the debug agent app is split (if necessary) and placed + * in these blocks. The first data block is placed at the next 8 byte aligned + * address after the header. + * + * The number of blocks for a given SMEM allocation is derived as follows: + * Number of Blocks = ((Total Size - Alignment - Size of Header + * - Size of SMQIn - Size of SMQOut)/(SM_BLOCKSIZE)) + * + * The producer maintains a private block map of each of these blocks to + * determine which of these blocks in the queue is available and which are free. + * + * Control: + * The control portion contains a list of nodes [0..N] where N is number + * of available data blocks. Each node identifies the data + * block indexes that contain a particular debug message to be transferred, + * and the number of blocks it took to hold the contents of the message. + * + * Each node has the following structure: + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 2 bytes |Staring Block Index| + * +---------+-------------------+ + * | 2 bytes |Number of Blocks | + * +---------+-------------------+ + * + * The producer and the consumer update different parts of the control channel + * (SMQOut / SMQIn) respectively. Each of these control data structures contains + * information about the last node that was written / read, and the actual nodes + * that were written/read. + * + * SMQOut Structure (R/W by producer, R by consumer): + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 4 bytes | Magic Init Number | + * +---------+-------------------+ + * | 4 bytes | Reset | + * +---------+-------------------+ + * | 4 bytes | Last Sent Index | + * +---------+-------------------+ + * | 4 bytes | Index Free Read | + * +---------+-------------------+ + * + * SMQIn Structure (R/W by consumer, R by producer): + * +---------+-------------------+ + * | Size | Field | + * +---------+-------------------+ + * | 4 bytes | Magic Init Number | + * +---------+-------------------+ + * | 4 bytes | Reset ACK | + * +---------+-------------------+ + * | 4 bytes | Last Read Index | + * +---------+-------------------+ + * | 4 bytes | Index Free Write | + * +---------+-------------------+ + * + * Magic Init Number: + * Both SMQ Out and SMQ In initialize this field with a predefined magic + * number so as to make sure that both the consumer and producer blocks + * have fully initialized and have valid data in the shared memory control area. + * Producer Magic #: 0xFF00FF01 + * Consumer Magic #: 0xFF00FF02 + */ +static int smq_ctor(struct smq *smq, void *base_addr, int size, + enum smq_type type, struct mutex *lock_ptr) +{ + int num_blocks; + uint8_t *pb_orig; + uint8_t *pb; + uint32_t i; + int err; + + if (smq->initialized == SMQ_MAGIC_INIT) { + err = SMQ_EBADPARM; + goto bail; + } + + if (!base_addr || !size) { + err = SMQ_EBADPARM; + goto bail; + } + + if (type == PRODUCER) + smq->lock = lock_ptr; + + pb_orig = (uint8_t *)base_addr; + smq->hdr = (struct smq_hdr *)pb_orig; + pb = pb_orig; + pb += sizeof(struct smq_hdr); + pb = PTR_ALIGN(pb, 8); + size -= pb - (uint8_t *)pb_orig; + num_blocks = (int)((size - sizeof(struct smq_out_state) - + sizeof(struct smq_in_state))/(SM_BLOCKSIZE + + sizeof(struct smq_node) * 2)); + if (num_blocks <= 0) { + err = SMQ_ENOMEMORY; + goto bail; + } + + smq->blocks = pb; + smq->num_blocks = num_blocks; + pb += num_blocks * SM_BLOCKSIZE; + smq->out = (struct smq_out *)pb; + pb += sizeof(struct smq_out_state) + (num_blocks * + sizeof(struct smq_node)); + smq->in = (struct smq_in *)pb; + smq->type = type; + if (type == PRODUCER) { + smq->hdr->producer_version = SM_VERSION; + for (i = 0; i < smq->num_blocks; i++) + (smq->out->sent + i)->index_block = 0xFFFF; + + err = smq_blockmap_ctor(&smq->block_map, smq->num_blocks); + if (err != SMQ_SUCCESS) + goto bail; + + smq->out->s.index_sent_write = 0; + smq->out->s.index_free_read = 0; + if (smq->out->s.init == SMQ_MAGIC_PRODUCER) { + smq->out->s.index_check_queue_for_reset += 1; + } else { + smq->out->s.index_check_queue_for_reset = 1; + smq->out->s.init = SMQ_MAGIC_PRODUCER; + } + } else { + smq->hdr->consumer_version = SM_VERSION; + for (i = 0; i < smq->num_blocks; i++) + (smq->in->free + i)->index_block = 0xFFFF; + + smq->in->s.index_sent_read = 0; + smq->in->s.index_free_write = 0; + if (smq->out->s.init == SMQ_MAGIC_PRODUCER) { + smq->in->s.index_check_queue_for_reset_ack = + smq->out->s.index_check_queue_for_reset; + } else { + smq->in->s.index_check_queue_for_reset_ack = 0; + } + + smq->in->s.init = SMQ_MAGIC_CONSUMER; + } + smq->initialized = SMQ_MAGIC_INIT; + err = SMQ_SUCCESS; + +bail: + return err; +} + +static void send_interrupt_to_subsystem(struct rdbg_data *rdbgdata) +{ + int offset = rdbgdata->gpio_out_offset; + int val = 1 ^ gpio_get_value(rdbgdata->out.gpio_base_id + offset); + + gpio_set_value(rdbgdata->out.gpio_base_id + offset, val); + rdbgdata->gpio_out_offset = (offset + 1) % 32; + + dev_dbg(rdbgdata->device, "%s: sent interrupt %d to subsystem", + __func__, val); +} + +static irqreturn_t on_interrupt_from(int irq, void *ptr) +{ + struct rdbg_data *rdbgdata = (struct rdbg_data *) ptr; + + dev_dbg(rdbgdata->device, "%s: Received interrupt %d from subsystem", + __func__, irq); + + complete(&(rdbgdata->work)); + return IRQ_HANDLED; +} + +static int initialize_smq(struct rdbg_data *rdbgdata) +{ + int err = 0; + unsigned char *smem_consumer_buffer = rdbgdata->smem_addr; + + smem_consumer_buffer += (rdbgdata->smem_size/2); + + if (smq_ctor(&(rdbgdata->producer_smrb), (void *)(rdbgdata->smem_addr), + ((rdbgdata->smem_size)/2), PRODUCER, &rdbgdata->write_mutex)) { + dev_err(rdbgdata->device, "%s: smq producer allocation failed", + __func__); + err = -ENOMEM; + goto bail; + } + + if (smq_ctor(&(rdbgdata->consumer_smrb), (void *)smem_consumer_buffer, + ((rdbgdata->smem_size)/2), CONSUMER, NULL)) { + dev_err(rdbgdata->device, "%s: smq conmsumer allocation failed", + __func__); + err = -ENOMEM; + } + +bail: + return err; + +} + +static int rdbg_open(struct inode *inode, struct file *filp) +{ + int device_id = -1; + struct rdbg_device *device = &g_rdbg_instance; + struct rdbg_data *rdbgdata = NULL; + int err = 0; + + if (!inode || !device->rdbg_data) { + pr_err("Memory not allocated yet"); + err = -ENODEV; + goto bail; + } + + device_id = MINOR(inode->i_rdev); + rdbgdata = &device->rdbg_data[device_id]; + + if (rdbgdata->device_opened) { + dev_err(rdbgdata->device, "%s: Device already opened", + __func__); + err = -EEXIST; + goto bail; + } + + rdbgdata->smem_size = proc_info[device_id].smem_buffer_size; + if (!rdbgdata->smem_size) { + dev_err(rdbgdata->device, "%s: smem not initialized", __func__); + err = -ENOMEM; + goto bail; + } + + rdbgdata->smem_addr = smem_find(proc_info[device_id].smem_buffer_addr, + rdbgdata->smem_size, 0, SMEM_ANY_HOST_FLAG); + if (!rdbgdata->smem_addr) { + dev_err(rdbgdata->device, "%s: Could not allocate smem memory", + __func__); + err = -ENOMEM; + goto bail; + } + dev_dbg(rdbgdata->device, "%s: SMEM address=0x%lx smem_size=%d", + __func__, (unsigned long)rdbgdata->smem_addr, + (unsigned int)rdbgdata->smem_size); + + if (check_subsystem_debug_enabled(rdbgdata->smem_addr, + rdbgdata->smem_size/2)) { + dev_err(rdbgdata->device, "%s: Subsystem %s is not debug enabled", + __func__, proc_info[device_id].name); + err = -ECOMM; + goto bail; + } + + init_completion(&rdbgdata->work); + + err = request_irq(rdbgdata->in.irq_base_id, on_interrupt_from, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + proc_info[device_id].name, + (void *)&device->rdbg_data[device_id]); + if (err) { + dev_err(rdbgdata->device, + "%s: Failed to register interrupt.Err=%d,irqid=%d.", + __func__, err, rdbgdata->in.irq_base_id); + goto irq_bail; + } + + err = enable_irq_wake(rdbgdata->in.irq_base_id); + if (err < 0) { + dev_dbg(rdbgdata->device, "enable_irq_wake() failed with err=%d", + err); + err = 0; + } + + mutex_init(&rdbgdata->write_mutex); + + err = initialize_smq(rdbgdata); + if (err) { + dev_err(rdbgdata->device, "Error initializing smq. Err=%d", + err); + goto smq_bail; + } + + rdbgdata->device_opened = 1; + + filp->private_data = (void *)rdbgdata; + + return 0; + +smq_bail: + smq_dtor(&(rdbgdata->producer_smrb)); + smq_dtor(&(rdbgdata->consumer_smrb)); + mutex_destroy(&rdbgdata->write_mutex); +irq_bail: + free_irq(rdbgdata->in.irq_base_id, (void *) + &device->rdbg_data[device_id]); +bail: + return err; +} + +static int rdbg_release(struct inode *inode, struct file *filp) +{ + int device_id = -1; + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + struct rdbg_data *rdbgdata = NULL; + int err = 0; + + if (!inode || !rdbgdevice->rdbg_data) { + pr_err("Memory not allocated yet"); + err = -ENODEV; + goto bail; + } + + device_id = MINOR(inode->i_rdev); + rdbgdata = &rdbgdevice->rdbg_data[device_id]; + + if (rdbgdata->device_opened == 1) { + dev_dbg(rdbgdata->device, "%s: Destroying %s.", __func__, + proc_info[device_id].name); + rdbgdata->device_opened = 0; + complete(&(rdbgdata->work)); + free_irq(rdbgdata->in.irq_base_id, (void *) + &rdbgdevice->rdbg_data[device_id]); + if (rdbgdevice->rdbg_data[device_id].producer_smrb.initialized) + smq_dtor(&(rdbgdevice->rdbg_data[device_id]. + producer_smrb)); + if (rdbgdevice->rdbg_data[device_id].consumer_smrb.initialized) + smq_dtor(&(rdbgdevice->rdbg_data[device_id]. + consumer_smrb)); + mutex_destroy(&rdbgdata->write_mutex); + } + + filp->private_data = NULL; + +bail: + return err; +} + +static ssize_t rdbg_read(struct file *filp, char __user *buf, size_t size, + loff_t *offset) +{ + int err = 0; + struct rdbg_data *rdbgdata = filp->private_data; + void *p_sent_buffer = NULL; + int nsize = 0; + int more = 0; + + if (!rdbgdata) { + pr_err("Invalid argument"); + err = -EINVAL; + goto bail; + } + + dev_dbg(rdbgdata->device, "%s: In receive", __func__); + err = wait_for_completion_interruptible(&(rdbgdata->work)); + if (err) { + dev_err(rdbgdata->device, "%s: Error in wait", __func__); + goto bail; + } + + smq_check_queue_reset(&(rdbgdata->consumer_smrb), + &(rdbgdata->producer_smrb)); + if (smq_receive(&(rdbgdata->consumer_smrb), &p_sent_buffer, + &nsize, &more) != SMQ_SUCCESS) { + dev_err(rdbgdata->device, "%s: Error in smq_recv(). Err code = %d", + __func__, err); + err = -ENODATA; + goto bail; + } + + size = ((size < nsize) ? size : nsize); + err = copy_to_user(buf, p_sent_buffer, size); + if (err != 0) { + dev_err(rdbgdata->device, "%s: Error in copy_to_user(). Err code = %d", + __func__, err); + err = -ENODATA; + goto bail; + } + + smq_free(&(rdbgdata->consumer_smrb), p_sent_buffer); + err = size; + dev_dbg(rdbgdata->device, "%s: Read data to buffer with address 0x%lx", + __func__, (unsigned long) buf); + +bail: + return err; +} + +static ssize_t rdbg_write(struct file *filp, const char __user *buf, + size_t size, loff_t *offset) +{ + int err = 0; + int num_retries = 0; + struct rdbg_data *rdbgdata = filp->private_data; + + if (!rdbgdata) { + pr_err("Invalid argument"); + err = -EINVAL; + goto bail; + } + + do { + err = smq_alloc_send(&(rdbgdata->producer_smrb), buf, size); + dev_dbg(rdbgdata->device, "%s, smq_alloc_send returned %d.", + __func__, err); + } while (err != 0 && num_retries++ < MAX_RETRIES); + + if (err != 0) { + err = -ECOMM; + goto bail; + } + + send_interrupt_to_subsystem(rdbgdata); + + err = size; + +bail: + return err; +} + + +static const struct file_operations rdbg_fops = { + .open = rdbg_open, + .read = rdbg_read, + .write = rdbg_write, + .release = rdbg_release, +}; + +static int register_smp2p(char *node_name, struct gpio_info *gpio_info_ptr) +{ + struct device_node *node = NULL; + int cnt = 0; + int id = 0; + + node = of_find_compatible_node(NULL, NULL, node_name); + if (node) { + cnt = of_gpio_count(node); + if (cnt && gpio_info_ptr) { + id = of_get_gpio(node, 0); + gpio_info_ptr->gpio_base_id = id; + gpio_info_ptr->irq_base_id = gpio_to_irq(id); + return 0; + } + } + return -EINVAL; +} + +static int __init rdbg_init(void) +{ + int err = 0; + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + int minor = 0; + int major = 0; + int minor_nodes_created = 0; + + char *rdbg_compatible_string = "qcom,smp2pgpio_client_rdbg_"; + int max_len = strlen(rdbg_compatible_string) + strlen("xx_out"); + + char *node_name = kcalloc(max_len, sizeof(char), GFP_KERNEL); + + if (!node_name) { + err = -ENOMEM; + goto bail; + } + + if (rdbgdevice->num_devices < 1 || + rdbgdevice->num_devices > SMP2P_NUM_PROCS) { + pr_err("rgdb: invalid num_devices"); + err = -EDOM; + goto name_bail; + } + + rdbgdevice->rdbg_data = kcalloc(rdbgdevice->num_devices, + sizeof(struct rdbg_data), GFP_KERNEL); + if (!rdbgdevice->rdbg_data) { + err = -ENOMEM; + goto name_bail; + } + + err = alloc_chrdev_region(&rdbgdevice->dev_no, 0, + rdbgdevice->num_devices, "rdbgctl"); + if (err) { + pr_err("Error in alloc_chrdev_region."); + goto data_bail; + } + major = MAJOR(rdbgdevice->dev_no); + + cdev_init(&rdbgdevice->cdev, &rdbg_fops); + rdbgdevice->cdev.owner = THIS_MODULE; + err = cdev_add(&rdbgdevice->cdev, MKDEV(major, 0), + rdbgdevice->num_devices); + if (err) { + pr_err("Error in cdev_add"); + goto chrdev_bail; + } + + rdbgdevice->class = class_create(THIS_MODULE, "rdbg"); + if (IS_ERR(rdbgdevice->class)) { + err = PTR_ERR(rdbgdevice->class); + pr_err("Error in class_create"); + goto cdev_bail; + } + + for (minor = 0; minor < rdbgdevice->num_devices; minor++) { + if (!proc_info[minor].name) + continue; + + if (snprintf(node_name, max_len, "%s%d_in", + rdbg_compatible_string, minor) <= 0) { + pr_err("Error in snprintf"); + err = -ENOMEM; + goto device_bail; + } + + if (register_smp2p(node_name, + &rdbgdevice->rdbg_data[minor].in)) { + pr_debug("No incoming device tree entry found for %s", + proc_info[minor].name); + continue; + } + + if (snprintf(node_name, max_len, "%s%d_out", + rdbg_compatible_string, minor) <= 0) { + pr_err("Error in snprintf"); + err = -ENOMEM; + goto device_bail; + } + + if (register_smp2p(node_name, + &rdbgdevice->rdbg_data[minor].out)) { + pr_err("No outgoing device tree entry found for %s", + proc_info[minor].name); + err = -EINVAL; + goto device_bail; + } + + rdbgdevice->rdbg_data[minor].device = device_create( + rdbgdevice->class, NULL, MKDEV(major, minor), + NULL, "%s", proc_info[minor].name); + if (IS_ERR(rdbgdevice->rdbg_data[minor].device)) { + err = PTR_ERR(rdbgdevice->rdbg_data[minor].device); + pr_err("Error in device_create"); + goto device_bail; + } + rdbgdevice->rdbg_data[minor].device_initialized = 1; + minor_nodes_created++; + dev_dbg(rdbgdevice->rdbg_data[minor].device, + "%s: created /dev/%s c %d %d'", __func__, + proc_info[minor].name, major, minor); + } + + if (!minor_nodes_created) { + pr_err("No device tree entries found"); + err = -EINVAL; + goto class_bail; + } + + goto name_bail; + +device_bail: + for (--minor; minor >= 0; minor--) { + if (rdbgdevice->rdbg_data[minor].device_initialized) + device_destroy(rdbgdevice->class, + MKDEV(MAJOR(rdbgdevice->dev_no), minor)); + } +class_bail: + class_destroy(rdbgdevice->class); +cdev_bail: + cdev_del(&rdbgdevice->cdev); +chrdev_bail: + unregister_chrdev_region(rdbgdevice->dev_no, rdbgdevice->num_devices); +data_bail: + kfree(rdbgdevice->rdbg_data); +name_bail: + kfree(node_name); +bail: + return err; +} + +static void __exit rdbg_exit(void) +{ + struct rdbg_device *rdbgdevice = &g_rdbg_instance; + int minor; + + for (minor = 0; minor < rdbgdevice->num_devices; minor++) { + if (rdbgdevice->rdbg_data[minor].device_initialized) { + device_destroy(rdbgdevice->class, + MKDEV(MAJOR(rdbgdevice->dev_no), minor)); + } + } + class_destroy(rdbgdevice->class); + cdev_del(&rdbgdevice->cdev); + unregister_chrdev_region(rdbgdevice->dev_no, 1); + kfree(rdbgdevice->rdbg_data); +} + +module_init(rdbg_init); +module_exit(rdbg_exit); + +MODULE_DESCRIPTION("rdbg module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index eb44cf9ddd17..c4aec62d1014 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2801,6 +2801,8 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) goto err_out; } + clk_debug_measure_add(core->hw, core->dentry); + ret = 0; goto out; @@ -2930,8 +2932,10 @@ static int __init clk_debug_init(void) return -ENOMEM; mutex_lock(&clk_debug_lock); - hlist_for_each_entry(core, &clk_debug_list, debug_node) + hlist_for_each_entry(core, &clk_debug_list, debug_node) { + clk_register_debug(core->hw, core->dentry); clk_debug_create_one(core, rootdir); + } inited = 1; mutex_unlock(&clk_debug_lock); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index 179b27c08022..c95a327a9301 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -23,6 +23,8 @@ void __clk_free_clk(struct clk *clk); /* Debugfs API to print the enabled clocks */ void clock_debug_print_enabled(void); +int clk_register_debug(struct clk_hw *hw, struct dentry *dentry); +void clk_debug_measure_add(struct clk_hw *hw, struct dentry *dentry); #else /* All these casts to avoid ifdefs in clkdev... */ diff --git a/drivers/clk/msm/clock-gpu-8998.c b/drivers/clk/msm/clock-gpu-8998.c index e4789a51b738..fce293db93f3 100644 --- a/drivers/clk/msm/clock-gpu-8998.c +++ b/drivers/clk/msm/clock-gpu-8998.c @@ -622,6 +622,7 @@ int msm_gfxcc_8998_probe(struct platform_device *pdev) struct device_node *of_node = pdev->dev.of_node; int rc; struct regulator *reg; + u32 regval; bool is_v2 = 0, is_vq = 0; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base"); @@ -697,6 +698,14 @@ int msm_gfxcc_8998_probe(struct platform_device *pdev) */ clk_set_flags(&gpucc_gfx3d_clk.c, CLKFLAG_RETAIN_PERIPH); + /* + * Program the droop detector's gfx_pdn to 1'b1 in order to reduce + * leakage between the graphics and CX rails. + */ + regval = readl_relaxed(virt_base_gfx + GPUCC_GPU_DD_WRAP_CTRL); + regval |= BIT(0); + writel_relaxed(regval, virt_base_gfx + GPUCC_GPU_DD_WRAP_CTRL); + dev_info(&pdev->dev, "Completed registering all GPU clocks\n"); return 0; diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 423e975dffee..c762a387068b 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -11,6 +11,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -286,4 +287,221 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc) } EXPORT_SYMBOL_GPL(qcom_cc_probe); +/* Debugfs Support */ +static struct clk_hw *measure; + +DEFINE_SPINLOCK(clk_reg_lock); + +/* Sample clock for 'ticks' reference clock ticks. */ +static u32 run_measurement(unsigned ticks, struct regmap *regmap, + u32 ctl_reg, u32 status_reg) +{ + u32 regval; + + /* Stop counters and set the XO4 counter start value. */ + regmap_write(regmap, ctl_reg, ticks); + + regmap_read(regmap, status_reg, ®val); + + /* Wait for timer to become ready. */ + while ((regval & BIT(25)) != 0) { + cpu_relax(); + regmap_read(regmap, status_reg, ®val); + } + + /* Run measurement and wait for completion. */ + regmap_write(regmap, ctl_reg, (BIT(20)|ticks)); + regmap_read(regmap, ctl_reg, ®val); + + regmap_read(regmap, status_reg, ®val); + + while ((regval & BIT(25)) == 0) { + cpu_relax(); + regmap_read(regmap, status_reg, ®val); + } + + /* Return measured ticks. */ + regmap_read(regmap, status_reg, ®val); + regval &= BM(24, 0); + + return regval; +} + +/* + * Perform a hardware rate measurement for a given clock. + * FOR DEBUG USE ONLY: Measurements take ~15 ms! + */ +static unsigned long clk_debug_mux_measure_rate(struct clk_hw *hw) +{ + unsigned long flags, ret = 0; + u32 gcc_xo4_reg, sample_ticks = 0x10000, multiplier = 1; + u64 raw_count_short, raw_count_full; + struct clk_debug_mux *meas = to_clk_measure(hw); + struct measure_clk_data *data = meas->priv; + + spin_lock_irqsave(&clk_reg_lock, flags); + + clk_prepare_enable(data->cxo); + + /* Enable CXO/4 and RINGOSC branch. */ + regmap_read(meas->regmap[GCC], data->xo_div4_cbcr, &gcc_xo4_reg); + gcc_xo4_reg |= BIT(0); + regmap_write(meas->regmap[GCC], data->xo_div4_cbcr, gcc_xo4_reg); + + /* + * The ring oscillator counter will not reset if the measured clock + * is not running. To detect this, run a short measurement before + * the full measurement. If the raw results of the two are the same + * then the clock must be off. + */ + + /* Run a short measurement. (~1 ms) */ + raw_count_short = run_measurement(0x1000, meas->regmap[GCC], + data->ctl_reg, data->status_reg); + + /* Run a full measurement. (~14 ms) */ + raw_count_full = run_measurement(sample_ticks, meas->regmap[GCC], + data->ctl_reg, data->status_reg); + + gcc_xo4_reg &= ~BIT(0); + regmap_write(meas->regmap[GCC], data->xo_div4_cbcr, gcc_xo4_reg); + + /* Return 0 if the clock is off. */ + if (raw_count_full == raw_count_short) + ret = 0; + else { + /* Compute rate in Hz. */ + raw_count_full = ((raw_count_full * 10) + 15) * 4800000; + do_div(raw_count_full, ((sample_ticks * 10) + 35)); + ret = (raw_count_full * multiplier); + } + + clk_disable_unprepare(data->cxo); + + spin_unlock_irqrestore(&clk_reg_lock, flags); + + return ret; +} + +static u8 clk_debug_mux_get_parent(struct clk_hw *hw) +{ + struct clk_debug_mux *meas = to_clk_measure(hw); + int i, num_parents = clk_hw_get_num_parents(hw); + + for (i = 0; i < num_parents; i++) { + if (!strcmp(meas->parent[i].parents, + hw->init->parent_names[i])) { + pr_debug("%s :Clock name %s index %d\n", __func__, + hw->init->name, i); + return i; + } + } + + return 0; +} + +static int clk_debug_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_debug_mux *meas = to_clk_measure(hw); + u32 regval = 0; + int dbg_cc = 0; + + dbg_cc = meas->parent[index].dbg_cc; + + if (dbg_cc != GCC) { + regmap_read(meas->regmap[dbg_cc], 0x0, ®val); + + if (meas->parent[index].mask) + regval &= ~meas->parent[index].mask << + meas->parent[index].shift; + else + regval &= ~meas->mask; + + regval |= (meas->parent[index].next_sel & meas->mask); + + if (meas->parent[index].en_mask == 0xFF) + /* Skip en_mask */ + regval = regval; + else if (meas->parent[index].en_mask) + regval |= meas->parent[index].en_mask; + else + regval |= meas->en_mask; + + regmap_write(meas->regmap[dbg_cc], 0x0, regval); + } + + /* update the debug sel for GCC */ + regmap_read(meas->regmap[GCC], meas->debug_offset, ®val); + + /* clear post divider bits */ + regval &= ~BM(15, 12); + regval &= ~meas->mask; + regval |= (meas->parent[index].sel & meas->mask); + regval |= meas->en_mask; + + regmap_write(meas->regmap[GCC], meas->debug_offset, regval); + + return 0; +} + +const struct clk_ops clk_debug_mux_ops = { + .get_parent = clk_debug_mux_get_parent, + .set_parent = clk_debug_mux_set_parent, +}; +EXPORT_SYMBOL_GPL(clk_debug_mux_ops); + +static int clk_debug_measure_get(void *data, u64 *val) +{ + struct clk_hw *hw = data, *par; + int ret = 0; + unsigned long meas_rate, sw_rate; + + ret = clk_set_parent(measure->clk, hw->clk); + if (!ret) { + par = measure; + while (par && par != hw) { + if (par->init->ops->enable) + par->init->ops->enable(par); + par = clk_hw_get_parent(par); + } + *val = clk_debug_mux_measure_rate(measure); + } + + meas_rate = clk_get_rate(hw->clk); + sw_rate = clk_get_rate(clk_hw_get_parent(measure)->clk); + if (sw_rate && meas_rate >= (sw_rate * 2)) + *val *= DIV_ROUND_CLOSEST(meas_rate, sw_rate); + + return ret; +} + +DEFINE_SIMPLE_ATTRIBUTE(clk_measure_fops, clk_debug_measure_get, + NULL, "%lld\n"); + +void clk_debug_measure_add(struct clk_hw *hw, struct dentry *dentry) +{ + if (IS_ERR_OR_NULL(measure)) + return; + + if (clk_set_parent(measure->clk, hw->clk)) + return; + + debugfs_create_file("measure", S_IRUGO, dentry, hw, + &clk_measure_fops); +} +EXPORT_SYMBOL_GPL(clk_debug_measure_add); + +int clk_register_debug(struct clk_hw *hw, struct dentry *dentry) +{ + if (IS_ERR_OR_NULL(measure)) { + if (hw->init->flags & CLK_IS_MEASURE) + measure = hw; + if (!IS_ERR_OR_NULL(measure)) + clk_debug_measure_add(hw, dentry); + } + + return 0; +} +EXPORT_SYMBOL_GPL(clk_register_debug); + MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index e3f450533470..841367eb21ff 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -51,4 +51,95 @@ extern int qcom_cc_really_probe(struct platform_device *pdev, extern int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc); extern struct clk_ops clk_dummy_ops; + +/* Debugfs Measure Clocks */ + +/** + * struct measure_clk_data - Structure of clk measure + * + * @cxo: XO clock. + * @xo_div4_cbcr: offset of debug XO/4 div register. + * @ctl_reg: offset of debug control register. + * @status_reg: offset of debug status register. + * + */ +struct measure_clk_data { + struct clk *cxo; + u32 xo_div4_cbcr; + u32 ctl_reg; + u32 status_reg; +}; + +/** + * List of Debug clock controllers. + */ +enum debug_cc { + GCC, + MMCC, + GPU, + CPU, +}; + +/** + * struct clk_src - Struture of clock source for debug mux + * + * @parents: clock name to be used as parent for debug mux. + * @sel: debug mux index at global clock controller. + * @dbg_cc: indicates the clock controller for recursive debug clock + * controllers. + * @next_sel: indicates the debug mux index at recursive debug mux. + * @mask: indicates the mask required at recursive debug mux. + * @shift: indicates the shift required at recursive debug mux. + * @en_mask: indicates the enable bit mask at recursive debug mux. + * Incase the recursive debug mux does not have a enable bit, + * 0xFF should be used to indicate the same, otherwise global + * enable bit would be used. + */ +struct clk_src { + const char *parents; + int sel; + enum debug_cc dbg_cc; + int next_sel; + u32 mask; + u32 shift; + u32 en_mask; +}; + +#define MUX_SRC_LIST(...) \ + .parent = (struct clk_src[]){__VA_ARGS__}, \ + .num_parents = ARRAY_SIZE(((struct clk_src[]){__VA_ARGS__})) + +/** + * struct clk_debug_mux - Struture of clock debug mux + * + * @parent: structure of clk_src + * @num_parents: number of parents + * @regmap: regmaps of debug mux + * @num_parent_regmap: number of regmap of debug mux + * @priv: private measure_clk_data to be used by debug mux + * @en_mask: indicates the enable bit mask at global clock + * controller debug mux. + * @mask: indicates the mask to be used at global clock + * controller debug mux. + * @debug_offset: Start of debug mux offset. + * @hw: handle between common and hardware-specific interfaces. + */ +struct clk_debug_mux { + struct clk_src *parent; + int num_parents; + struct regmap **regmap; + int num_parent_regmap; + void *priv; + u32 en_mask; + u32 mask; + u32 debug_offset; + struct clk_hw hw; +}; + +#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb) + +#define to_clk_measure(_hw) container_of((_hw), struct clk_debug_mux, hw) + +extern const struct clk_ops clk_debug_mux_ops; + #endif diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 8c92a564299d..ed70a980d9ac 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -79,7 +79,6 @@ config CORESIGHT_SOURCE_ETM3X config CORESIGHT_SOURCE_ETM4X bool "CoreSight Embedded Trace Macrocell 4.x driver" - depends on ARM64 select CORESIGHT_LINKS_AND_SINKS help This driver provides support for the ETM4.x tracer module, tracing the @@ -113,7 +112,7 @@ config CORESIGHT_QCOM_REPLICATOR config CORESIGHT_STM bool "CoreSight System Trace Macrocell driver" - depends on CORESIGHT_LINKS_AND_SINKS + select CORESIGHT_LINKS_AND_SINKS help This driver provides support for hardware assisted software instrumentation based tracing. This is primarily useful for diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c index 3e3143be0a13..b045d6c6e8da 100644 --- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c +++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c @@ -972,6 +972,11 @@ static int cam_smmu_map_buffer_and_add_to_list(int idx, int ion_fd, struct dma_buf_attachment *attach = NULL; struct sg_table *table = NULL; + if (!paddr_ptr) { + rc = -EINVAL; + goto err_out; + } + /* allocate memory for each buffer information */ buf = dma_buf_get(ion_fd); if (IS_ERR_OR_NULL(buf)) { diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c index a56e42dc1c6f..31568da21fee 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c @@ -266,8 +266,10 @@ static void msm_fd_stop_streaming(struct vb2_queue *q) { struct fd_ctx *ctx = vb2_get_drv_priv(q); + mutex_lock(&ctx->fd_device->recovery_lock); msm_fd_hw_remove_buffers_from_queue(ctx->fd_device, q); msm_fd_hw_put(ctx->fd_device); + mutex_unlock(&ctx->fd_device->recovery_lock); } /* Videobuf2 queue callbacks. */ @@ -328,6 +330,68 @@ static struct vb2_mem_ops msm_fd_vb2_mem_ops = { .put_userptr = msm_fd_put_userptr, }; +/* + * msm_fd_vbif_error_handler - FD VBIF Error handler + * @handle: FD Device handle + * @error: CPP-VBIF Error code + */ +static int msm_fd_vbif_error_handler(void *handle, uint32_t error) +{ + struct fd_ctx *ctx; + struct msm_fd_device *fd; + struct msm_fd_buffer *active_buf; + int ret; + + if (handle == NULL) + return 0; + + ctx = (struct fd_ctx *)handle; + fd = (struct msm_fd_device *)ctx->fd_device; + + if (error == CPP_VBIF_ERROR_HANG) { + mutex_lock(&fd->recovery_lock); + dev_err(fd->dev, "Handling FD VBIF Hang\n"); + if (fd->state != MSM_FD_DEVICE_RUNNING) { + dev_err(fd->dev, "FD is not FD_DEVICE_RUNNING, %d\n", + fd->state); + mutex_unlock(&fd->recovery_lock); + return 0; + } + fd->recovery_mode = 1; + + /* Halt and reset */ + msm_fd_hw_put(fd); + msm_fd_hw_get(fd, ctx->settings.speed); + + /* Get active buffer */ + active_buf = msm_fd_hw_get_active_buffer(fd); + + if (active_buf == NULL) { + dev_dbg(fd->dev, "no active buffer, return\n"); + fd->recovery_mode = 0; + mutex_unlock(&fd->recovery_lock); + return 0; + } + + dev_dbg(fd->dev, "Active Buffer present.. Start re-schedule\n"); + + /* Queue the buffer again */ + msm_fd_hw_add_buffer(fd, active_buf); + + /* Schedule and restart */ + ret = msm_fd_hw_schedule_next_buffer(fd); + if (ret) { + dev_err(fd->dev, "Cannot reschedule buffer, recovery failed\n"); + fd->recovery_mode = 0; + mutex_unlock(&fd->recovery_lock); + return ret; + } + dev_dbg(fd->dev, "Restarted FD after VBIF HAng\n"); + mutex_unlock(&fd->recovery_lock); + } + return 0; +} + /* * msm_fd_open - Fd device open method. * @file: Pointer to file struct. @@ -391,6 +455,10 @@ static int msm_fd_open(struct file *file) goto error_ahb_config; } + /* Register with CPP VBIF error handler */ + msm_cpp_vbif_register_error_handler((void *)ctx, + VBIF_CLIENT_FD, msm_fd_vbif_error_handler); + return 0; error_ahb_config: @@ -412,6 +480,10 @@ static int msm_fd_release(struct file *file) { struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data); + /* Un-register with CPP VBIF error handler */ + msm_cpp_vbif_register_error_handler((void *)ctx, + VBIF_CLIENT_FD, NULL); + vb2_queue_release(&ctx->vb2_q); vfree(ctx->stats); @@ -468,7 +540,7 @@ static long msm_fd_private_ioctl(struct file *file, void *fh, struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh); struct msm_fd_stats *stats; int stats_idx; - int ret; + int ret = 0; int i; switch (cmd) { @@ -1176,6 +1248,12 @@ static void msm_fd_wq_handler(struct work_struct *work) /* Stats are ready, set correct frame id */ atomic_set(&stats->frame_id, ctx->sequence); + /* If Recovery mode is on, we got IRQ after recovery, reset it */ + if (fd->recovery_mode) { + fd->recovery_mode = 0; + dev_dbg(fd->dev, "Got IRQ after Recovery\n"); + } + /* We have the data from fd hw, we can start next processing */ msm_fd_hw_schedule_next_buffer(fd); @@ -1213,6 +1291,7 @@ static int fd_probe(struct platform_device *pdev) mutex_init(&fd->lock); spin_lock_init(&fd->slock); + mutex_init(&fd->recovery_lock); init_completion(&fd->hw_halt_completion); INIT_LIST_HEAD(&fd->buf_queue); fd->pdev = pdev; diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h index b96c33b3fd07..7505f0585d42 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.h @@ -23,6 +23,8 @@ #include #include "cam_soc_api.h" #include "cam_hw_ops.h" +#include "msm_cpp.h" + /* Maximum number of result buffers */ #define MSM_FD_MAX_RESULT_BUFS 5 /* Max number of clocks defined in device tree */ @@ -214,12 +216,14 @@ enum msm_fd_mem_resources { * @work_queue: Pointer to FD device IRQ bottom half workqueue. * @work: IRQ bottom half work struct. * @hw_halt_completion: Completes when face detection hw halt completes. + * @recovery_mode: Indicates if FD is in recovery mode */ struct msm_fd_device { u32 hw_revision; struct mutex lock; spinlock_t slock; + struct mutex recovery_lock; int ref_count; int irq_num; @@ -248,6 +252,8 @@ struct msm_fd_device { struct workqueue_struct *work_queue; struct work_struct work; struct completion hw_halt_completion; + int recovery_mode; + uint32_t clk_rate_idx; }; #endif /* __MSM_FD_DEV_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c index 08268d98fc13..21d42a77accb 100644 --- a/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c +++ b/drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c @@ -38,7 +38,7 @@ /* Face detection bus client name */ #define MSM_FD_BUS_CLIENT_NAME "msm_face_detect" /* Face detection processing timeout in ms */ -#define MSM_FD_PROCESSING_TIMEOUT_MS 500 +#define MSM_FD_PROCESSING_TIMEOUT_MS 150 /* Face detection halt timeout in ms */ #define MSM_FD_HALT_TIMEOUT_MS 100 /* Smmu callback name */ @@ -822,6 +822,45 @@ static int msm_fd_hw_set_clock_rate_idx(struct msm_fd_device *fd, return 0; } + +/** + * msm_fd_hw_update_settings() - API to set clock rate and bus settings + * @fd: Pointer to fd device. + * @buf: fd buffer + */ +static int msm_fd_hw_update_settings(struct msm_fd_device *fd, + struct msm_fd_buffer *buf) +{ + int ret = 0; + uint32_t clk_rate_idx; + + if (!buf) + return 0; + + clk_rate_idx = buf->settings.speed; + if (fd->clk_rate_idx == clk_rate_idx) + return 0; + + if (fd->bus_client) { + ret = msm_fd_hw_bus_request(fd, clk_rate_idx); + if (ret < 0) { + dev_err(fd->dev, "Fail bus scale update %d\n", ret); + return -EINVAL; + } + } + + ret = msm_fd_hw_set_clock_rate_idx(fd, clk_rate_idx); + if (ret < 0) { + dev_err(fd->dev, "Fail to set clock rate idx\n"); + goto end; + } + dev_dbg(fd->dev, "set clk %d %d", fd->clk_rate_idx, clk_rate_idx); + fd->clk_rate_idx = clk_rate_idx; + +end: + return ret; +} + /* * msm_fd_hw_get - Get fd hw for performing any hw operation. * @fd: Pointer to fd device. @@ -868,6 +907,8 @@ int msm_fd_hw_get(struct msm_fd_device *fd, unsigned int clock_rate_idx) ret = msm_fd_hw_set_dt_parms(fd); if (ret < 0) goto error_set_dt; + + fd->clk_rate_idx = clock_rate_idx; } fd->ref_count++; @@ -924,7 +965,7 @@ void msm_fd_hw_put(struct msm_fd_device *fd) */ static int msm_fd_hw_attach_iommu(struct msm_fd_device *fd) { - int ret; + int ret = -EINVAL; mutex_lock(&fd->lock); @@ -1058,6 +1099,8 @@ static int msm_fd_hw_enable(struct msm_fd_device *fd, msm_fd_hw_set_direction_angle(fd, buffer->settings.direction_index, buffer->settings.angle_index); msm_fd_hw_run(fd); + if (fd->recovery_mode) + dev_err(fd->dev, "Scheduled buffer in recovery mode\n"); return 1; } @@ -1153,6 +1196,9 @@ void msm_fd_hw_remove_buffers_from_queue(struct msm_fd_device *fd, time = wait_for_completion_timeout(&active_buffer->completion, msecs_to_jiffies(MSM_FD_PROCESSING_TIMEOUT_MS)); if (!time) { + /* Do a vb2 buffer done since it timed out */ + vb2_buffer_done(&active_buffer->vb_v4l2_buf.vb2_buf, + VB2_BUF_STATE_DONE); /* Remove active buffer */ msm_fd_hw_get_active_buffer(fd); /* Schedule if other buffers are present in device */ @@ -1224,6 +1270,8 @@ int msm_fd_hw_schedule_and_start(struct msm_fd_device *fd) spin_unlock(&fd->slock); + msm_fd_hw_update_settings(fd, buf); + return 0; } @@ -1257,8 +1305,12 @@ int msm_fd_hw_schedule_next_buffer(struct msm_fd_device *fd) } } else { fd->state = MSM_FD_DEVICE_IDLE; + if (fd->recovery_mode) + dev_err(fd->dev, "No Buffer in recovery mode.Device Idle\n"); } spin_unlock(&fd->slock); + msm_fd_hw_update_settings(fd, buf); + return 0; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 56056849e140..8793745aac71 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1523,6 +1523,8 @@ void msm_vfe47_update_camif_state(struct vfe_device *vfe_dev, if ((vfe_dev->hvx_cmd > HVX_DISABLE) && (vfe_dev->hvx_cmd <= HVX_ROUND_TRIP)) msm_vfe47_configure_hvx(vfe_dev, 1); + else + msm_vfe47_configure_hvx(vfe_dev, 0); bus_en = ((vfe_dev->axi_data. diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 59b875d6e464..778df297f93c 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -450,9 +450,7 @@ static int msm_isp_cfg_pix(struct vfe_device *vfe_dev, } pix_cfg = &input_cfg->d.pix_cfg; - if ((pix_cfg->hvx_cmd > HVX_DISABLE) && - (pix_cfg->hvx_cmd <= HVX_ROUND_TRIP)) - vfe_dev->hvx_cmd = pix_cfg->hvx_cmd; + vfe_dev->hvx_cmd = pix_cfg->hvx_cmd; vfe_dev->is_split = input_cfg->d.pix_cfg.is_split; vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock = diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 7e452e9e4ee2..b7724b4bf936 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -102,6 +102,7 @@ #define IS_DEFAULT_OUTPUT_BUF_INDEX(index) \ ((index == DEFAULT_OUTPUT_BUF_INDEX) ? 1 : 0) +static struct msm_cpp_vbif_data cpp_vbif; static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev, uint32_t buff_mgr_ops, uint32_t ids, void *arg); @@ -121,6 +122,7 @@ static void msm_cpp_flush_queue_and_release_buffer(struct cpp_device *cpp_dev, static int msm_cpp_dump_frame_cmd(struct msm_cpp_frame_info_t *frame_info); static int msm_cpp_dump_addr(struct cpp_device *cpp_dev, struct msm_cpp_frame_info_t *frame_info); +static int32_t msm_cpp_reset_vbif_and_load_fw(struct cpp_device *cpp_dev); #if CONFIG_MSM_CPP_DBG #define CPP_DBG(fmt, args...) pr_err(fmt, ##args) @@ -171,6 +173,26 @@ struct msm_cpp_timer_t { struct msm_cpp_timer_t cpp_timer; static void msm_cpp_set_vbif_reg_values(struct cpp_device *cpp_dev); + +void msm_cpp_vbif_register_error_handler(void *dev, + enum cpp_vbif_client client, + int (*client_vbif_error_handler)(void *, uint32_t)) +{ + if (dev == NULL || client >= VBIF_CLIENT_MAX) { + pr_err("%s: Fail to register handler! dev = %p, client %d\n", + __func__, dev, client); + return; + } + + if (client_vbif_error_handler != NULL) { + cpp_vbif.dev[client] = dev; + cpp_vbif.err_handler[client] = client_vbif_error_handler; + } else { + /* if handler = NULL, is unregister case */ + cpp_vbif.dev[client] = NULL; + cpp_vbif.err_handler[client] = NULL; + } +} static int msm_cpp_init_bandwidth_mgr(struct cpp_device *cpp_dev) { int rc = 0; @@ -755,6 +777,7 @@ static void msm_cpp_iommu_fault_handler(struct iommu_domain *domain, struct msm_cpp_frame_info_t *processed_frame[MAX_CPP_PROCESSING_FRAME]; int32_t i = 0, queue_len = 0; struct msm_device_queue *queue = NULL; + int32_t rc = 0; if (token) { cpp_dev = token; @@ -765,7 +788,16 @@ static void msm_cpp_iommu_fault_handler(struct iommu_domain *domain, } mutex_lock(&cpp_dev->mutex); tasklet_kill(&cpp_dev->cpp_tasklet); - cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin); + rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin); + if (rc < 0) { + pr_err("load fw failure %d-retry\n", rc); + rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev); + if (rc < 0) { + msm_cpp_set_micro_irq_mask(cpp_dev, 1, 0x8); + mutex_unlock(&cpp_dev->mutex); + return; + } + } queue = &cpp_timer.data.cpp_dev->processing_q; queue_len = queue->len; if (!queue_len) { @@ -1022,11 +1054,16 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev) if (cpp_dev->fw_name_bin) { msm_camera_enable_irq(cpp_dev->irq, false); rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin); - msm_camera_enable_irq(cpp_dev->irq, true); if (rc < 0) { - pr_err("%s: load firmware failure %d\n", __func__, rc); - goto pwr_collapse_reset; + pr_err("%s: load firmware failure %d-retry\n", + __func__, rc); + rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev); + if (rc < 0) { + msm_camera_enable_irq(cpp_dev->irq, true); + goto pwr_collapse_reset; + } } + msm_camera_enable_irq(cpp_dev->irq, true); msm_camera_io_w_mb(0x7C8, cpp_dev->base + MSM_CPP_MICRO_IRQGEN_MASK); msm_camera_io_w_mb(0xFFFF, cpp_dev->base + @@ -1038,6 +1075,7 @@ static int cpp_init_hardware(struct cpp_device *cpp_dev) pwr_collapse_reset: msm_cpp_update_gdscr_status(cpp_dev, false); + msm_camera_unregister_irq(cpp_dev->pdev, cpp_dev->irq, cpp_dev); req_irq_fail: if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP, CAM_AHB_SUSPEND_VOTE) < 0) @@ -1081,7 +1119,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) { uint32_t i; uint32_t *ptr_bin = NULL; - int32_t rc = 0; + int32_t rc = 0, ret = 0; if (!fw_name_bin) { pr_err("%s:%d] invalid fw name", __func__, __LINE__); @@ -1207,14 +1245,70 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) } vote: - rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP, + ret = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP, CAM_AHB_SVS_VOTE); - if (rc < 0) + if (ret < 0) { pr_err("%s:%d: failed to vote for AHB\n", __func__, __LINE__); + rc = ret; + } end: return rc; } +int32_t msm_cpp_reset_vbif_clients(struct cpp_device *cpp_dev) +{ + uint32_t i; + + pr_warn("%s: handle vbif hang...\n", __func__); + for (i = 0; i < VBIF_CLIENT_MAX; i++) { + if (cpp_dev->vbif_data->err_handler[i] == NULL) + continue; + + cpp_dev->vbif_data->err_handler[i]( + cpp_dev->vbif_data->dev[i], CPP_VBIF_ERROR_HANG); + } + return 0; +} + +int32_t msm_cpp_reset_vbif_and_load_fw(struct cpp_device *cpp_dev) +{ + int32_t rc = 0; + + msm_cpp_reset_vbif_clients(cpp_dev); + + rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin); + if (rc < 0) + pr_err("Reset and load fw failed %d\n", rc); + + return rc; +} + +int cpp_vbif_error_handler(void *dev, uint32_t vbif_error) +{ + struct cpp_device *cpp_dev = NULL; + + if (dev == NULL || vbif_error >= CPP_VBIF_ERROR_MAX) { + pr_err("failed: dev %p, vbif error %d\n", dev, vbif_error); + return -EINVAL; + } + + cpp_dev = (struct cpp_device *) dev; + + /* MMSS_A_CPP_IRQ_STATUS_0 = 0x10 */ + pr_err("%s: before reset halt... read MMSS_A_CPP_IRQ_STATUS_0 = 0x%x", + __func__, msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10)); + + pr_err("%s: start reset bus bridge on FD + CPP!\n", __func__); + /* MMSS_A_CPP_RST_CMD_0 = 0x8, firmware reset = 0x3DF77 */ + msm_camera_io_w(0x3DF77, cpp_dev->cpp_hw_base + 0x8); + + /* MMSS_A_CPP_IRQ_STATUS_0 = 0x10 */ + pr_err("%s: after reset halt... read MMSS_A_CPP_IRQ_STATUS_0 = 0x%x", + __func__, msm_camera_io_r(cpp_dev->cpp_hw_base + 0x10)); + + return 0; +} + static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { int rc; @@ -1255,6 +1349,10 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) CPP_DBG("open %d %pK\n", i, &fh->vfh); cpp_dev->cpp_open_cnt++; + + msm_cpp_vbif_register_error_handler(cpp_dev, + VBIF_CLIENT_CPP, cpp_vbif_error_handler); + if (cpp_dev->cpp_open_cnt == 1) { rc = cpp_init_hardware(cpp_dev); if (rc < 0) { @@ -1284,6 +1382,7 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) rc = -ENOMEM; } } + mutex_unlock(&cpp_dev->mutex); return 0; } @@ -1383,6 +1482,9 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } } + /* unregister vbif error handler */ + msm_cpp_vbif_register_error_handler(cpp_dev, + VBIF_CLIENT_CPP, NULL); mutex_unlock(&cpp_dev->mutex); return 0; } @@ -1641,8 +1743,12 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) rc = cpp_load_fw(cpp_timer.data.cpp_dev, cpp_timer.data.cpp_dev->fw_name_bin); if (rc) { - pr_warn("Firmware loading failed\n"); - goto error; + pr_warn("Firmware loading failed-retry\n"); + rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev); + if (rc < 0) { + pr_err("Firmware loading failed\n"); + goto error; + } } else { pr_debug("Firmware loading done\n"); } @@ -2926,11 +3032,14 @@ long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd, msm_camera_enable_irq(cpp_dev->irq, false); rc = cpp_load_fw(cpp_dev, cpp_dev->fw_name_bin); if (rc < 0) { - pr_err("%s: load firmware failure %d\n", + pr_err("%s: load firmware failure %d-retry\n", __func__, rc); - enable_irq(cpp_dev->irq->start); - mutex_unlock(&cpp_dev->mutex); - return rc; + rc = msm_cpp_reset_vbif_and_load_fw(cpp_dev); + if (rc < 0) { + enable_irq(cpp_dev->irq->start); + mutex_unlock(&cpp_dev->mutex); + return rc; + } } rc = msm_cpp_fw_version(cpp_dev); if (rc < 0) { @@ -4195,6 +4304,8 @@ static int cpp_probe(struct platform_device *pdev) spin_lock_init(&cpp_timer.data.processed_frame_lock); cpp_dev->pdev = pdev; + memset(&cpp_vbif, 0, sizeof(struct msm_cpp_vbif_data)); + cpp_dev->vbif_data = &cpp_vbif; cpp_dev->camss_cpp_base = msm_camera_get_reg_base(pdev, "camss_cpp", true); diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h index f46cc10cef46..470c0cf1131b 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h @@ -23,6 +23,7 @@ #include "msm_sd.h" #include "cam_soc_api.h" #include "cam_hw_ops.h" +#include /* hw version info: 31:28 Major version @@ -95,6 +96,22 @@ #define MSM_CPP_TX_FIFO_LEVEL 16 #define MSM_CPP_RX_FIFO_LEVEL 512 +enum cpp_vbif_error { + CPP_VBIF_ERROR_HANG, + CPP_VBIF_ERROR_MAX, +}; + +enum cpp_vbif_client { + VBIF_CLIENT_CPP, + VBIF_CLIENT_FD, + VBIF_CLIENT_MAX, +}; + +struct msm_cpp_vbif_data { + int (*err_handler[VBIF_CLIENT_MAX])(void *, uint32_t); + void *dev[VBIF_CLIENT_MAX]; +}; + struct cpp_subscribe_info { struct v4l2_fh *vfh; uint32_t active; @@ -266,6 +283,7 @@ struct cpp_device { uint32_t bus_master_flag; uint32_t micro_reset; struct msm_cpp_payload_params payload_params; + struct msm_cpp_vbif_data *vbif_data; }; int msm_cpp_set_micro_clk(struct cpp_device *cpp_dev); @@ -274,5 +292,8 @@ int msm_cpp_get_clock_index(struct cpp_device *cpp_dev, const char *clk_name); long msm_cpp_set_core_clk(struct cpp_device *cpp_dev, long rate, int idx); void msm_cpp_fetch_dt_params(struct cpp_device *cpp_dev); int msm_cpp_read_payload_params_from_dt(struct cpp_device *cpp_dev); +void msm_cpp_vbif_register_error_handler(void *dev, + enum cpp_vbif_client client, + int (*client_vbif_error_handler)(void *, uint32_t)); #endif /* __MSM_CPP_H__ */ diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index e4cee1fa4ffc..a7cd44636d1d 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -1600,7 +1600,7 @@ static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = { static int msm_csiphy_get_clk_info(struct csiphy_device *csiphy_dev, struct platform_device *pdev) { - int i, rc; + int i, rc = 0; char *csi_3p_clk_name = "csi_phy_3p_clk"; char *csi_3p_clk_src_name = "csiphy_3p_clk_src"; uint32_t clk_cnt = 0; @@ -1616,6 +1616,7 @@ static int msm_csiphy_get_clk_info(struct csiphy_device *csiphy_dev, if (csiphy_dev->num_all_clk > CSIPHY_NUM_CLK_MAX) { pr_err("%s: invalid count=%zu, max is %d\n", __func__, csiphy_dev->num_all_clk, CSIPHY_NUM_CLK_MAX); + rc = -EINVAL; goto MAX_CLK_ERROR; } @@ -1659,13 +1660,14 @@ static int msm_csiphy_get_clk_info(struct csiphy_device *csiphy_dev, } csiphy_dev->num_clk = clk_cnt; + return rc; MAX_CLK_ERROR: msm_camera_put_clk_info(csiphy_dev->pdev, &csiphy_dev->csiphy_all_clk_info, &csiphy_dev->csiphy_all_clk, csiphy_dev->num_all_clk); - return 0; + return rc; } static int csiphy_probe(struct platform_device *pdev) diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 86e7837cc02a..c1c25b655d1f 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -381,9 +381,6 @@ static int32_t msm_sensor_fill_slave_info_init_params( if (!slave_info || !sensor_info) return -EINVAL; - if (!slave_info->is_init_params_valid) - return 0; - sensor_init_params = &slave_info->sensor_init_params; if (INVALID_CAMERA_B != sensor_init_params->position) sensor_info->position = @@ -754,8 +751,6 @@ int32_t msm_sensor_driver_probe(void *setting, slave_info->power_setting_array.power_down_setting = compat_ptr(slave_info32-> power_setting_array.power_down_setting); - slave_info->is_init_params_valid = - slave_info32->is_init_params_valid; slave_info->sensor_init_params = slave_info32->sensor_init_params; slave_info->output_format = @@ -783,13 +778,10 @@ int32_t msm_sensor_driver_probe(void *setting, CDBG("power up size %d power down size %d\n", slave_info->power_setting_array.size, slave_info->power_setting_array.size_down); - - if (slave_info->is_init_params_valid) { - CDBG("position %d", - slave_info->sensor_init_params.position); - CDBG("mount %d", - slave_info->sensor_init_params.sensor_mount_angle); - } + CDBG("position %d", + slave_info->sensor_init_params.position); + CDBG("mount %d", + slave_info->sensor_init_params.sensor_mount_angle); /* Validate camera id */ if (slave_info->camera_id >= MAX_CAMERAS) { diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c index 88a3b4b6f7ba..3835a2e45882 100644 --- a/drivers/media/platform/msm/vidc/hfi_response_handler.c +++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c @@ -1369,6 +1369,22 @@ static int hfi_process_session_flush_done(u32 device_id, cmd_done.status = hfi_map_err_status(pkt->error_type); cmd_done.size = sizeof(u32); + switch (pkt->flush_type) { + case HFI_FLUSH_OUTPUT: + cmd_done.data.flush_type = HAL_FLUSH_OUTPUT; + break; + case HFI_FLUSH_INPUT: + cmd_done.data.flush_type = HAL_FLUSH_INPUT; + break; + case HFI_FLUSH_ALL: + cmd_done.data.flush_type = HAL_FLUSH_ALL; + break; + default: + dprintk(VIDC_ERR, + "%s: invalid flush type!", __func__); + return -EINVAL; + } + *info = (struct msm_vidc_cb_info) { .response_type = HAL_SESSION_FLUSH_DONE, .response.cmd = cmd_done, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index a2edbb6a8270..c5b4872b8e23 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -1505,6 +1505,9 @@ static void handle_session_flush(enum hal_command_response cmd, void *data) { struct msm_vidc_cb_cmd_done *response = data; struct msm_vidc_inst *inst; + struct v4l2_event flush_event = {0}; + u32 *ptr = NULL; + enum hal_flush flush_type; int rc; if (!response) { @@ -1532,8 +1535,31 @@ static void handle_session_flush(enum hal_command_response cmd, void *data) } } atomic_dec(&inst->in_flush); - dprintk(VIDC_DBG, "Notify flush complete to client\n"); - msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE); + flush_event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE; + ptr = (u32 *)flush_event.u.data; + + flush_type = response->data.flush_type; + switch (flush_type) { + case HAL_FLUSH_INPUT: + ptr[0] = V4L2_QCOM_CMD_FLUSH_OUTPUT; + break; + case HAL_FLUSH_OUTPUT: + ptr[0] = V4L2_QCOM_CMD_FLUSH_CAPTURE; + break; + case HAL_FLUSH_ALL: + ptr[0] |= V4L2_QCOM_CMD_FLUSH_CAPTURE; + ptr[0] |= V4L2_QCOM_CMD_FLUSH_OUTPUT; + break; + default: + dprintk(VIDC_ERR, "Invalid flush type received!"); + goto exit; + } + + dprintk(VIDC_DBG, + "Notify flush complete, flush_type: %x\n", flush_type); + v4l2_event_queue_fh(&inst->event_handler, &flush_event); + +exit: put_inst(inst); } @@ -2455,7 +2481,6 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst) } hdev = inst->core->device; abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE); - init_completion(&inst->completions[abort_completion]); rc = call_hfi_op(hdev, session_abort, (void *)inst->session); if (rc) { @@ -2637,8 +2662,6 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst) __func__); } - init_completion(&core->completions - [SYS_MSG_INDEX(HAL_SYS_INIT_DONE)]); rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "Failed to init core, id = %d\n", @@ -2742,8 +2765,6 @@ static int msm_comm_session_init(int flipped_state, dprintk(VIDC_ERR, "Invalid session\n"); return -EINVAL; } - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_INIT_DONE)]); rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data, inst, get_hal_domain(inst->session_type), @@ -2881,8 +2902,6 @@ static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst) inst, inst->state); goto exit; } - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_START_DONE)]); rc = call_hfi_op(hdev, session_start, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -2912,8 +2931,6 @@ static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst) goto exit; } dprintk(VIDC_DBG, "Send Stop to hal\n"); - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_STOP_DONE)]); rc = call_hfi_op(hdev, session_stop, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, "Failed to send stop\n"); @@ -2943,8 +2960,6 @@ static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst) } dprintk(VIDC_DBG, "Send release res to hal\n"); - init_completion(&inst->completions[ - SESSION_MSG_INDEX(HAL_SESSION_RELEASE_RESOURCE_DONE)]); rc = call_hfi_op(hdev, session_release_res, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -2975,8 +2990,6 @@ static int msm_comm_session_close(int flipped_state, } dprintk(VIDC_DBG, "Send session close to hal\n"); - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_END_DONE)]); rc = call_hfi_op(hdev, session_end, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -4022,8 +4035,6 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, } mutex_unlock(&inst->sync_lock); - init_completion(&inst->completions[ - SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)]); switch (ptype) { case HAL_PARAM_PROFILE_LEVEL_CURRENT: case HAL_CONFIG_VDEC_ENTROPY: @@ -4253,8 +4264,6 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst, if (inst->state != MSM_VIDC_CORE_INVALID && core->state != VIDC_CORE_INVALID) { buffer_info.response_required = true; - init_completion(&inst->completions[SESSION_MSG_INDEX - (HAL_SESSION_RELEASE_BUFFER_DONE)]); rc = call_hfi_op(hdev, session_release_buffers, (void *)inst->session, &buffer_info); if (rc) { @@ -4325,9 +4334,6 @@ int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst) if (inst->state != MSM_VIDC_CORE_INVALID && core->state != VIDC_CORE_INVALID) { buffer_info.response_required = true; - init_completion( - &inst->completions[SESSION_MSG_INDEX - (HAL_SESSION_RELEASE_BUFFER_DONE)]); rc = call_hfi_op(hdev, session_release_buffers, (void *)inst->session, &buffer_info); if (rc) { diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index eceb86b01a7c..9970c4152ef9 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -934,8 +934,6 @@ err_create_pkt: return rc; } -static DECLARE_COMPLETION(release_resources_done); - static int __alloc_imem(struct venus_hfi_device *device, unsigned long size) { struct imem *imem = NULL; @@ -2172,8 +2170,6 @@ static int venus_hfi_core_init(void *device) dev = device; mutex_lock(&dev->lock); - init_completion(&release_resources_done); - rc = __load_fw(dev); if (rc) { dprintk(VIDC_ERR, "Failed to load Venus FW\n"); @@ -3460,7 +3456,6 @@ static int __response_handler(struct venus_hfi_device *device) break; case HAL_SYS_RELEASE_RESOURCE_DONE: dprintk(VIDC_DBG, "Received SYS_RELEASE_RESOURCE\n"); - complete(&release_resources_done); break; case HAL_SYS_INIT_DONE: dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n"); diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h index 116ce12c8dba..820c8685a75b 100644 --- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h +++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h @@ -1351,6 +1351,7 @@ struct msm_vidc_cb_cmd_done { struct vidc_hal_session_init_done session_init_done; struct hal_buffer_info buffer_info; union hal_get_property property; + enum hal_flush flush_type; } data; }; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 4fd845ab4086..26676a51d83c 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -95,6 +95,7 @@ #define QSEECOM_STATE_NOT_READY 0 #define QSEECOM_STATE_SUSPEND 1 #define QSEECOM_STATE_READY 2 +#define QSEECOM_ICE_FDE_KEY_SIZE_MASK 2 /* * default ce info unit to 0 for @@ -110,6 +111,15 @@ enum qseecom_clk_definitions { CLK_SFPB, }; +enum qseecom_ice_key_size_type { + QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE = + (0 << QSEECOM_ICE_FDE_KEY_SIZE_MASK), + QSEECOM_ICE_FDE_KEY_SIZE_32_BYTE = + (1 << QSEECOM_ICE_FDE_KEY_SIZE_MASK), + QSEE_ICE_FDE_KEY_SIZE_UNDEFINED = + (0xF << QSEECOM_ICE_FDE_KEY_SIZE_MASK), +}; + enum qseecom_client_handle_type { QSEECOM_CLIENT_APP = 1, QSEECOM_LISTENER_SERVICE, @@ -252,6 +262,7 @@ struct qseecom_control { bool support_bus_scaling; bool support_fde; bool support_pfe; + bool fde_key_size; uint32_t cumulative_mode; enum qseecom_bandwidth_request_mode current_mode; struct timer_list bw_scale_down_timer; @@ -5693,6 +5704,11 @@ static int qseecom_create_key(struct qseecom_dev_handle *data, goto free_buf; } + if (qseecom.fde_key_size) + flags |= QSEECOM_ICE_FDE_KEY_SIZE_32_BYTE; + else + flags |= QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE; + generate_key_ireq.flags = flags; generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY; memset((void *)generate_key_ireq.key_id, @@ -5913,6 +5929,12 @@ static int qseecom_update_key_user_info(struct qseecom_dev_handle *data, } ireq.qsee_command_id = QSEOS_UPDATE_KEY_USERINFO; + + if (qseecom.fde_key_size) + flags |= QSEECOM_ICE_FDE_KEY_SIZE_32_BYTE; + else + flags |= QSEECOM_ICE_FDE_KEY_SIZE_16_BYTE; + ireq.flags = flags; memset(ireq.key_id, 0, QSEECOM_KEY_ID_SIZE); memset((void *)ireq.current_hash32, 0, QSEECOM_HASH_SIZE); @@ -8346,6 +8368,9 @@ static int qseecom_probe(struct platform_device *pdev) "qcom,commonlib64-loaded-by-uefi"); pr_debug("qseecom.commonlib64-loaded-by-uefi = 0x%x", qseecom.commonlib64_loaded); + qseecom.fde_key_size = + of_property_read_bool((&pdev->dev)->of_node, + "qcom,fde-key-size"); qseecom.no_clock_support = of_property_read_bool((&pdev->dev)->of_node, "qcom,no-clock-support"); diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index 1e56d445c6e1..f53ed2693879 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -2472,7 +2472,7 @@ void *cnss_pci_get_virt_ramdump_mem(unsigned long *size) void cnss_pci_device_crashed(void) { if (penv && penv->subsys) { - subsys_set_crash_status(penv->subsys, true); + subsys_set_crash_status(penv->subsys, CRASH_STATUS_ERR_FATAL); subsystem_restart_dev(penv->subsys); } } @@ -2491,7 +2491,7 @@ EXPORT_SYMBOL(cnss_get_virt_ramdump_mem); void cnss_device_crashed(void) { if (penv && penv->subsys) { - subsys_set_crash_status(penv->subsys, true); + subsys_set_crash_status(penv->subsys, CRASH_STATUS_ERR_FATAL); subsystem_restart_dev(penv->subsys); } } diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c index 01b969ec627f..ce7dbc64c4c3 100644 --- a/drivers/net/wireless/cnss/cnss_sdio.c +++ b/drivers/net/wireless/cnss/cnss_sdio.c @@ -605,7 +605,8 @@ void cnss_sdio_device_crashed(void) return; ssr_info = &cnss_pdata->ssr_info; if (ssr_info->subsys) { - subsys_set_crash_status(ssr_info->subsys, true); + subsys_set_crash_status(ssr_info->subsys, + CRASH_STATUS_ERR_FATAL); subsystem_restart_dev(ssr_info->subsys); } } diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 70cabc7080b3..223339ff119d 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-v3.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qrbtc-v2.o +obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-v3-falcon.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.c b/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.c new file mode 100644 index 000000000000..e88c00e01e0b --- /dev/null +++ b/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "phy-qcom-ufs-qmp-v3-falcon.h" + +#define UFS_PHY_NAME "ufs_phy_qmp_v3_falcon" + +static +int ufs_qcom_phy_qmp_v3_falcon_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, + bool is_rate_B) +{ + int err; + int tbl_size_A, tbl_size_B; + struct ufs_qcom_phy_calibration *tbl_A, *tbl_B; + u8 major = ufs_qcom_phy->host_ctrl_rev_major; + u16 minor = ufs_qcom_phy->host_ctrl_rev_minor; + u16 step = ufs_qcom_phy->host_ctrl_rev_step; + + tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B); + tbl_B = phy_cal_table_rate_B; + + if ((major == 0x3) && (minor == 0x001) && (step == 0x001)) { + tbl_A = phy_cal_table_rate_A_3_1_1; + tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A_3_1_1); + } else { + dev_err(ufs_qcom_phy->dev, + "%s: Unknown UFS-PHY version (major 0x%x minor 0x%x step 0x%x), no calibration values\n", + __func__, major, minor, step); + err = -ENODEV; + goto out; + } + + err = ufs_qcom_phy_calibrate(ufs_qcom_phy, + tbl_A, tbl_size_A, + tbl_B, tbl_size_B, + is_rate_B); + + if (err) + dev_err(ufs_qcom_phy->dev, + "%s: ufs_qcom_phy_calibrate() failed %d\n", + __func__, err); + +out: + return err; +} + +static int ufs_qcom_phy_qmp_v3_falcon_init(struct phy *generic_phy) +{ + struct ufs_qcom_phy_qmp_v3_falcon *phy = phy_get_drvdata(generic_phy); + struct ufs_qcom_phy *phy_common = &phy->common_cfg; + int err; + + err = ufs_qcom_phy_init_clks(generic_phy, phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_clks() failed %d\n", + __func__, err); + goto out; + } + + err = ufs_qcom_phy_init_vregulators(generic_phy, phy_common); + if (err) { + dev_err(phy_common->dev, "%s: ufs_qcom_phy_init_vregulators() failed %d\n", + __func__, err); + goto out; + } + +out: + return err; +} + +static +void ufs_qcom_phy_qmp_v3_falcon_power_control(struct ufs_qcom_phy *phy, + bool power_ctrl) +{ + if (!power_ctrl) { + /* apply analog power collapse */ + writel_relaxed(0x0, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); + /* + * Make sure that PHY knows its analog rail is going to be + * powered OFF. + */ + mb(); + } else { + /* bring PHY out of analog power collapse */ + writel_relaxed(0x1, phy->mmio + UFS_PHY_POWER_DOWN_CONTROL); + + /* + * Before any transactions involving PHY, ensure PHY knows + * that it's analog rail is powered ON. + */ + mb(); + } +} + +static inline +void ufs_qcom_phy_qmp_v3_falcon_set_tx_lane_enable(struct ufs_qcom_phy *phy, + u32 val) +{ + /* + * v3 PHY does not have TX_LANE_ENABLE register. + * Implement this function so as not to propagate error to caller. + */ +} + +static +void ufs_qcom_phy_qmp_v3_falcon_ctrl_rx_linecfg(struct ufs_qcom_phy *phy, + bool ctrl) +{ + u32 temp; + + temp = readl_relaxed(phy->mmio + UFS_PHY_LINECFG_DISABLE); + + if (ctrl) /* enable RX LineCfg */ + temp &= ~UFS_PHY_RX_LINECFG_DISABLE_BIT; + else /* disable RX LineCfg */ + temp |= UFS_PHY_RX_LINECFG_DISABLE_BIT; + + writel_relaxed(temp, phy->mmio + UFS_PHY_LINECFG_DISABLE); + /* Make sure that RX LineCfg config applied before we return */ + mb(); +} + +static inline void ufs_qcom_phy_qmp_v3_falcon_start_serdes( + struct ufs_qcom_phy *phy) +{ + u32 tmp; + + tmp = readl_relaxed(phy->mmio + UFS_PHY_PHY_START); + tmp &= ~MASK_SERDES_START; + tmp |= (1 << OFFSET_SERDES_START); + writel_relaxed(tmp, phy->mmio + UFS_PHY_PHY_START); + /* Ensure register value is committed */ + mb(); +} + +static int ufs_qcom_phy_qmp_v3_falcon_is_pcs_ready( + struct ufs_qcom_phy *phy_common) +{ + int err = 0; + u32 val; + + err = readl_poll_timeout(phy_common->mmio + UFS_PHY_PCS_READY_STATUS, + val, (val & MASK_PCS_READY), 10, 1000000); + if (err) + dev_err(phy_common->dev, "%s: poll for pcs failed err = %d\n", + __func__, err); + return err; +} + +static void ufs_qcom_phy_qmp_v3_falcon_dbg_register_dump( + struct ufs_qcom_phy *phy) +{ + ufs_qcom_phy_dump_regs(phy, COM_BASE, COM_SIZE, + "PHY QSERDES COM Registers "); + ufs_qcom_phy_dump_regs(phy, PHY_BASE, PHY_SIZE, + "PHY Registers "); + ufs_qcom_phy_dump_regs(phy, RX_BASE, RX_SIZE, + "PHY RX0 Registers "); + ufs_qcom_phy_dump_regs(phy, TX_BASE, TX_SIZE, + "PHY TX0 Registers "); +} + +struct phy_ops ufs_qcom_phy_qmp_v3_falcon_phy_ops = { + .init = ufs_qcom_phy_qmp_v3_falcon_init, + .exit = ufs_qcom_phy_exit, + .power_on = ufs_qcom_phy_power_on, + .power_off = ufs_qcom_phy_power_off, + .owner = THIS_MODULE, +}; + +struct ufs_qcom_phy_specific_ops phy_v3_falcon_ops = { + .calibrate_phy = ufs_qcom_phy_qmp_v3_falcon_phy_calibrate, + .start_serdes = ufs_qcom_phy_qmp_v3_falcon_start_serdes, + .is_physical_coding_sublayer_ready = + ufs_qcom_phy_qmp_v3_falcon_is_pcs_ready, + .set_tx_lane_enable = ufs_qcom_phy_qmp_v3_falcon_set_tx_lane_enable, + .ctrl_rx_linecfg = ufs_qcom_phy_qmp_v3_falcon_ctrl_rx_linecfg, + .power_control = ufs_qcom_phy_qmp_v3_falcon_power_control, + .dbg_register_dump = ufs_qcom_phy_qmp_v3_falcon_dbg_register_dump, +}; + +static int ufs_qcom_phy_qmp_v3_falcon_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy *generic_phy; + struct ufs_qcom_phy_qmp_v3_falcon *phy; + int err = 0; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + err = -ENOMEM; + goto out; + } + + generic_phy = ufs_qcom_phy_generic_probe(pdev, &phy->common_cfg, + &ufs_qcom_phy_qmp_v3_falcon_phy_ops, + &phy_v3_falcon_ops); + + if (!generic_phy) { + dev_err(dev, "%s: ufs_qcom_phy_generic_probe() failed\n", + __func__); + err = -EIO; + goto out; + } + + phy_set_drvdata(generic_phy, phy); + + strlcpy(phy->common_cfg.name, UFS_PHY_NAME, + sizeof(phy->common_cfg.name)); + +out: + return err; +} + +static int ufs_qcom_phy_qmp_v3_falcon_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy *generic_phy = to_phy(dev); + struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy); + int err = 0; + + err = ufs_qcom_phy_remove(generic_phy, ufs_qcom_phy); + if (err) + dev_err(dev, "%s: ufs_qcom_phy_remove failed = %d\n", + __func__, err); + + return err; +} + +static const struct of_device_id ufs_qcom_phy_qmp_v3_falcon_of_match[] = { + {.compatible = "qcom,ufs-phy-qmp-v3-falcon"}, + {}, +}; +MODULE_DEVICE_TABLE(of, ufs_qcom_phy_qmp_v3_falcon_of_match); + +static struct platform_driver ufs_qcom_phy_qmp_v3_falcon_driver = { + .probe = ufs_qcom_phy_qmp_v3_falcon_probe, + .remove = ufs_qcom_phy_qmp_v3_falcon_remove, + .driver = { + .of_match_table = ufs_qcom_phy_qmp_v3_falcon_of_match, + .name = "ufs_qcom_phy_qmp_v3_falcon", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(ufs_qcom_phy_qmp_v3_falcon_driver); + +MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY QMP v3 falcon"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.h b/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.h new file mode 100644 index 000000000000..e64601cc6b22 --- /dev/null +++ b/drivers/phy/phy-qcom-ufs-qmp-v3-falcon.h @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef UFS_QCOM_PHY_QMP_V3_FALCON_H_ +#define UFS_QCOM_PHY_QMP_V3_FALCON_H_ + +#include "phy-qcom-ufs-i.h" + +/* QCOM UFS PHY control registers */ +#define COM_BASE 0x000 +#define COM_OFF(x) (COM_BASE + x) +#define COM_SIZE 0x1C0 + +#define TX_BASE 0x400 +#define TX_OFF(x) (TX_BASE + x) +#define TX_SIZE 0x128 + +#define RX_BASE 0x600 +#define RX_OFF(x) (RX_BASE + x) +#define RX_SIZE 0x1FC + +#define PHY_BASE 0xC00 +#define PHY_OFF(x) (PHY_BASE + x) +#define PHY_SIZE 0x1B4 + +/* UFS PHY QSERDES COM registers */ +#define QSERDES_COM_ATB_SEL1 COM_OFF(0x00) +#define QSERDES_COM_ATB_SEL2 COM_OFF(0x04) +#define QSERDES_COM_FREQ_UPDATE COM_OFF(0x08) +#define QSERDES_COM_BG_TIMER COM_OFF(0x0C) +#define QSERDES_COM_SSC_EN_CENTER COM_OFF(0x10) +#define QSERDES_COM_SSC_ADJ_PER1 COM_OFF(0x14) +#define QSERDES_COM_SSC_ADJ_PER2 COM_OFF(0x18) +#define QSERDES_COM_SSC_PER1 COM_OFF(0x1C) +#define QSERDES_COM_SSC_PER2 COM_OFF(0x20) +#define QSERDES_COM_SSC_STEP_SIZE1 COM_OFF(0x24) +#define QSERDES_COM_SSC_STEP_SIZE2 COM_OFF(0x28) +#define QSERDES_COM_POST_DIV COM_OFF(0x2C) +#define QSERDES_COM_POST_DIV_MUX COM_OFF(0x30) +#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN COM_OFF(0x34) +#define QSERDES_COM_CLK_ENABLE1 COM_OFF(0x38) +#define QSERDES_COM_SYS_CLK_CTRL COM_OFF(0x3C) +#define QSERDES_COM_SYSCLK_BUF_ENABLE COM_OFF(0x40) +#define QSERDES_COM_PLL_EN COM_OFF(0x44) +#define QSERDES_COM_PLL_IVCO COM_OFF(0x48) +#define QSERDES_COM_LOCK_CMP1_MODE0 COM_OFF(0X4C) +#define QSERDES_COM_LOCK_CMP2_MODE0 COM_OFF(0X50) +#define QSERDES_COM_LOCK_CMP3_MODE0 COM_OFF(0X54) +#define QSERDES_COM_LOCK_CMP1_MODE1 COM_OFF(0X58) +#define QSERDES_COM_LOCK_CMP2_MODE1 COM_OFF(0X5C) +#define QSERDES_COM_LOCK_CMP3_MODE1 COM_OFF(0X60) +#define QSERDES_COM_CMD_RSVD0 COM_OFF(0x64) +#define QSERDES_COM_EP_CLOCK_DETECT_CTRL COM_OFF(0x68) +#define QSERDES_COM_SYSCLK_DET_COMP_STATUS COM_OFF(0x6C) +#define QSERDES_COM_BG_TRIM COM_OFF(0x70) +#define QSERDES_COM_CLK_EP_DIV COM_OFF(0x74) +#define QSERDES_COM_CP_CTRL_MODE0 COM_OFF(0x78) +#define QSERDES_COM_CP_CTRL_MODE1 COM_OFF(0x7C) +#define QSERDES_COM_CMN_RSVD1 COM_OFF(0x80) +#define QSERDES_COM_PLL_RCTRL_MODE0 COM_OFF(0x84) +#define QSERDES_COM_PLL_RCTRL_MODE1 COM_OFF(0x88) +#define QSERDES_COM_CMN_RSVD2 COM_OFF(0x8C) +#define QSERDES_COM_PLL_CCTRL_MODE0 COM_OFF(0x90) +#define QSERDES_COM_PLL_CCTRL_MODE1 COM_OFF(0x94) +#define QSERDES_COM_CMN_RSVD3 COM_OFF(0x98) +#define QSERDES_COM_PLL_CNTRL COM_OFF(0x9C) +#define QSERDES_COM_PHASE_SEL_CTRL COM_OFF(0xA0) +#define QSERDES_COM_PHASE_SEL_DC COM_OFF(0xA4) +#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM COM_OFF(0xA8) +#define QSERDES_COM_SYSCLK_EN_SEL COM_OFF(0xAC) +#define QSERDES_COM_CML_SYSCLK_SEL COM_OFF(0xB0) +#define QSERDES_COM_RESETSM_CNTRL COM_OFF(0xB4) +#define QSERDES_COM_RESETSM_CNTRL2 COM_OFF(0xB8) +#define QSERDES_COM_RESTRIM_CTRL COM_OFF(0xBC) +#define QSERDES_COM_RESTRIM_CTRL2 COM_OFF(0xC0) +#define QSERDES_COM_LOCK_CMP_EN COM_OFF(0xC8) +#define QSERDES_COM_LOCK_CMP_CFG COM_OFF(0xCC) +#define QSERDES_COM_DEC_START_MODE0 COM_OFF(0xD0) +#define QSERDES_COM_DEC_START_MODE1 COM_OFF(0xD4) +#define QSERDES_COM_VCOCAL_DEADMAN_CTRL COM_OFF(0xD8) +#define QSERDES_COM_DIV_FRAC_START1_MODE0 COM_OFF(0xDC) +#define QSERDES_COM_DIV_FRAC_START2_MODE0 COM_OFF(0xE0) +#define QSERDES_COM_DIV_FRAC_START3_MODE0 COM_OFF(0xE4) +#define QSERDES_COM_DIV_FRAC_START1_MODE1 COM_OFF(0xE8) +#define QSERDES_COM_DIV_FRAC_START2_MODE1 COM_OFF(0xEC) +#define QSERDES_COM_DIV_FRAC_START3_MODE1 COM_OFF(0xF0) +#define QSERDES_COM_VCO_TUNE_MINVAL1 COM_OFF(0xF4) +#define QSERDES_COM_VCO_TUNE_MINVAL2 COM_OFF(0xF8) +#define QSERDES_COM_CMN_RSVD4 COM_OFF(0xFC) +#define QSERDES_COM_INTEGLOOP_INITVAL COM_OFF(0x100) +#define QSERDES_COM_INTEGLOOP_EN COM_OFF(0x104) +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 COM_OFF(0x108) +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 COM_OFF(0x10C) +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 COM_OFF(0x110) +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 COM_OFF(0x114) +#define QSERDES_COM_VCO_TUNE_MAXVAL1 COM_OFF(0x118) +#define QSERDES_COM_VCO_TUNE_MAXVAL2 COM_OFF(0x11C) +#define QSERDES_COM_RES_TRIM_CONTROL2 COM_OFF(0x120) +#define QSERDES_COM_VCO_TUNE_CTRL COM_OFF(0x124) +#define QSERDES_COM_VCO_TUNE_MAP COM_OFF(0x128) +#define QSERDES_COM_VCO_TUNE1_MODE0 COM_OFF(0x12C) +#define QSERDES_COM_VCO_TUNE2_MODE0 COM_OFF(0x130) +#define QSERDES_COM_VCO_TUNE1_MODE1 COM_OFF(0x134) +#define QSERDES_COM_VCO_TUNE2_MODE1 COM_OFF(0x138) +#define QSERDES_COM_VCO_TUNE_INITVAL1 COM_OFF(0x13C) +#define QSERDES_COM_VCO_TUNE_INITVAL2 COM_OFF(0x140) +#define QSERDES_COM_VCO_TUNE_TIMER1 COM_OFF(0x144) +#define QSERDES_COM_VCO_TUNE_TIMER2 COM_OFF(0x148) +#define QSERDES_COM_SAR COM_OFF(0x14C) +#define QSERDES_COM_SAR_CLK COM_OFF(0x150) +#define QSERDES_COM_SAR_CODE_OUT_STATUS COM_OFF(0x154) +#define QSERDES_COM_SAR_CODE_READY_STATUS COM_OFF(0x158) +#define QSERDES_COM_CMN_STATUS COM_OFF(0x15C) +#define QSERDES_COM_RESET_SM_STATUS COM_OFF(0x160) +#define QSERDES_COM_RESTRIM_CODE_STATUS COM_OFF(0x164) +#define QSERDES_COM_PLLCAL_CODE1_STATUS COM_OFF(0x168) +#define QSERDES_COM_PLLCAL_CODE2_STATUS COM_OFF(0x16C) +#define QSERDES_COM_BG_CTRL COM_OFF(0x170) +#define QSERDES_COM_CLK_SELECT COM_OFF(0x174) +#define QSERDES_COM_HSCLK_SEL COM_OFF(0x178) +#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS COM_OFF(0x17C) +#define QSERDES_COM_PLL_ANALOG COM_OFF(0x180) +#define QSERDES_COM_CORECLK_DIV COM_OFF(0x184) +#define QSERDES_COM_SW_RESET COM_OFF(0x188) +#define QSERDES_COM_CORE_CLK_EN COM_OFF(0x18C) +#define QSERDES_COM_C_READY_STATUS COM_OFF(0x190) +#define QSERDES_COM_CMN_CONFIG COM_OFF(0x194) +#define QSERDES_COM_CMN_RATE_OVERRIDE COM_OFF(0x198) +#define QSERDES_COM_SVS_MODE_CLK_SEL COM_OFF(0x19C) +#define QSERDES_COM_DEBUG_BUS0 COM_OFF(0x1A0) +#define QSERDES_COM_DEBUG_BUS1 COM_OFF(0x1A4) +#define QSERDES_COM_DEBUG_BUS2 COM_OFF(0x1A8) +#define QSERDES_COM_DEBUG_BUS3 COM_OFF(0x1AC) +#define QSERDES_COM_DEBUG_BUS_SEL COM_OFF(0x1B0) +#define QSERDES_COM_CMN_MISC1 COM_OFF(0x1B4) +#define QSERDES_COM_CORECLK_DIV_MODE1 COM_OFF(0x1BC) +#define QSERDES_COM_CMN_RSVD5 COM_OFF(0x1C0) + +/* UFS PHY registers */ +#define UFS_PHY_PHY_START PHY_OFF(0x00) +#define UFS_PHY_POWER_DOWN_CONTROL PHY_OFF(0x04) +#define UFS_PHY_TX_LARGE_AMP_DRV_LVL PHY_OFF(0x34) +#define UFS_PHY_TX_SMALL_AMP_DRV_LVL PHY_OFF(0x3C) +#define UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAP PHY_OFF(0xCC) +#define UFS_PHY_LINECFG_DISABLE PHY_OFF(0x138) +#define UFS_PHY_RX_SYM_RESYNC_CTRL PHY_OFF(0x13C) +#define UFS_PHY_RX_SIGDET_CTRL2 PHY_OFF(0x148) +#define UFS_PHY_RX_PWM_GEAR_BAND PHY_OFF(0x154) +#define UFS_PHY_PCS_READY_STATUS PHY_OFF(0x168) + +/* UFS PHY TX registers */ +#define QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN TX_OFF(0x68) +#define QSERDES_TX_LANE_MODE TX_OFF(0x94) + +/* UFS PHY RX registers */ +#define QSERDES_RX_UCDR_SVS_SO_GAIN_HALF RX_OFF(0x30) +#define QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER RX_OFF(0x34) +#define QSERDES_RX_UCDR_SVS_SO_GAIN_EIGHTH RX_OFF(0x38) +#define QSERDES_RX_UCDR_SVS_SO_GAIN RX_OFF(0x3C) +#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN RX_OFF(0x40) +#define QSERDES_RX_UCDR_SO_SATURATION_ENABLE RX_OFF(0x48) +#define QSERDES_RX_RX_TERM_BW RX_OFF(0x90) +#define QSERDES_RX_RX_EQ_GAIN1_LSB RX_OFF(0xC4) +#define QSERDES_RX_RX_EQ_GAIN1_MSB RX_OFF(0xC8) +#define QSERDES_RX_RX_EQ_GAIN2_LSB RX_OFF(0xCC) +#define QSERDES_RX_RX_EQ_GAIN2_MSB RX_OFF(0xD0) +#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 RX_OFF(0xD8) +#define QSERDES_RX_SIGDET_CNTRL RX_OFF(0x114) +#define QSERDES_RX_SIGDET_LVL RX_OFF(0x118) +#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL RX_OFF(0x11C) +#define QSERDES_RX_RX_INTERFACE_MODE RX_OFF(0x12C) + + +#define UFS_PHY_RX_LINECFG_DISABLE_BIT BIT(1) + +/* + * This structure represents the v3 falcon specific phy. + * common_cfg MUST remain the first field in this structure + * in case extra fields are added. This way, when calling + * get_ufs_qcom_phy() of generic phy, we can extract the + * common phy structure (struct ufs_qcom_phy) out of it + * regardless of the relevant specific phy. + */ +struct ufs_qcom_phy_qmp_v3_falcon { + struct ufs_qcom_phy common_cfg; +}; + +static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_3_1_1[] = { + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_POWER_DOWN_CONTROL, 0x01), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CMN_CONFIG, 0x0e), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYSCLK_EN_SEL, 0x14), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CLK_SELECT, 0x30), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SYS_CLK_CTRL, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TIMER, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_HSCLK_SEL, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_EN, 0x01), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_CTRL, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_RESETSM_CNTRL, 0x20), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CORE_CLK_EN, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP_CFG, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x0b), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x0b), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_HIGHZ_TRANSCEIVER_BIAS_DRVR_EN, 0x45), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX_LANE_MODE, 0x06), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_LVL, 0x24), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_CNTRL, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_INTERFACE_MODE, 0x40), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_TERM_BW, 0x5B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), + + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_IVCO, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_BG_TRIM, 0x0F), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_PWM_GEAR_BAND, 0x15), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX_UCDR_SO_SATURATION_ENABLE, 0x4B), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL1, 0xFF), + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL2, 0x6c), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_LARGE_AMP_DRV_LVL, 0x0A), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_SMALL_AMP_DRV_LVL, 0x02), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), + UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SYM_RESYNC_CTRL, 0x03), +}; + +static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = { + UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_MAP, 0x44), +}; + +#endif diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 9ddd18800f9d..d8b6754a465f 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -39,6 +39,12 @@ pr_debug(fmt, ##__VA_ARGS__); \ } while (0) +#define is_between(left, right, value) \ + (((left) >= (right) && (left) >= (value) \ + && (value) >= (right)) \ + || ((left) <= (right) && (left) <= (value) \ + && (value) <= (right))) + /* Awake votable reasons */ #define SRAM_READ "fg_sram_read" #define SRAM_WRITE "fg_sram_write" @@ -205,10 +211,10 @@ struct fg_dt_props { int recharge_soc_thr; int recharge_volt_thr_mv; int rsense_sel; - int jeita_thresholds[NUM_JEITA_LEVELS]; int esr_timer_charging; int esr_timer_awake; int esr_timer_asleep; + int rconn_mohms; int cl_start_soc; int cl_max_temp; int cl_min_temp; @@ -218,6 +224,7 @@ struct fg_dt_props { int cl_min_cap_limit; int jeita_hyst_temp; int batt_temp_delta; + int jeita_thresholds[NUM_JEITA_LEVELS]; int ki_coeff_soc[KI_COEFF_SOC_LEVELS]; int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS]; int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS]; @@ -310,8 +317,9 @@ struct fg_chip { u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; + u32 rradc_base; u32 wa_flags; - int batt_id_kohms; + int batt_id_ohms; int charge_status; int prev_charge_status; int charge_done; diff --git a/drivers/power/qcom-charger/fg-reg.h b/drivers/power/qcom-charger/fg-reg.h index ffc46f328f91..7ad26215e469 100644 --- a/drivers/power/qcom-charger/fg-reg.h +++ b/drivers/power/qcom-charger/fg-reg.h @@ -13,6 +13,10 @@ #ifndef __FG_REG_H__ #define __FG_REG_H__ +/* FG_ADC_RR register definitions used only for READ */ +#define ADC_RR_FAKE_BATT_LOW_LSB(chip) (chip->rradc_base + 0x58) +#define ADC_RR_FAKE_BATT_HIGH_LSB(chip) (chip->rradc_base + 0x5A) + /* FG_BATT_SOC register definitions */ #define BATT_SOC_FG_ALG_STS(chip) (chip->batt_soc_base + 0x06) #define BATT_SOC_FG_ALG_AUX_STS0(chip) (chip->batt_soc_base + 0x07) diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 74fa041738ff..22025ac27ffa 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -62,6 +62,10 @@ #define ESR_TIMER_CHG_INIT_OFFSET 2 #define PROFILE_LOAD_WORD 24 #define PROFILE_LOAD_OFFSET 0 +#define ESR_RSLOW_DISCHG_WORD 34 +#define ESR_RSLOW_DISCHG_OFFSET 0 +#define ESR_RSLOW_CHG_WORD 51 +#define ESR_RSLOW_CHG_OFFSET 0 #define NOM_CAP_WORD 58 #define NOM_CAP_OFFSET 0 #define ACT_BATT_CAP_BKUP_WORD 74 @@ -69,6 +73,7 @@ #define CYCLE_COUNT_WORD 75 #define CYCLE_COUNT_OFFSET 0 #define PROFILE_INTEGRITY_WORD 79 +#define SW_CONFIG_OFFSET 0 #define PROFILE_INTEGRITY_OFFSET 3 #define BATT_SOC_WORD 91 #define BATT_SOC_OFFSET 0 @@ -564,21 +569,21 @@ static int fg_get_battery_esr(struct fg_chip *chip, int *val) static int fg_get_battery_resistance(struct fg_chip *chip, int *val) { - int rc, esr, rslow; + int rc, esr_uohms, rslow_uohms; - rc = fg_get_battery_esr(chip, &esr); + rc = fg_get_battery_esr(chip, &esr_uohms); if (rc < 0) { pr_err("failed to get ESR, rc=%d\n", rc); return rc; } - rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow); + rc = fg_get_sram_prop(chip, FG_SRAM_RSLOW, &rslow_uohms); if (rc < 0) { pr_err("failed to get Rslow, rc=%d\n", rc); return rc; } - *val = esr + rslow; + *val = esr_uohms + rslow_uohms; return 0; } @@ -693,18 +698,57 @@ static bool is_batt_empty(struct fg_chip *chip) return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false); } -#define DEBUG_BATT_ID_KOHMS 7 +static int fg_get_debug_batt_id(struct fg_chip *chip, int *batt_id) +{ + int rc; + u64 temp; + u8 buf[2]; + + rc = fg_read(chip, ADC_RR_FAKE_BATT_LOW_LSB(chip), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + ADC_RR_FAKE_BATT_LOW_LSB(chip), rc); + return rc; + } + + /* + * Fake battery threshold is encoded in the following format. + * Threshold (code) = (battery_id in Ohms) * 0.00015 * 2^10 / 2.5 + */ + temp = (buf[1] << 8 | buf[0]) * 2500000; + do_div(temp, 150 * 1024); + batt_id[0] = temp; + rc = fg_read(chip, ADC_RR_FAKE_BATT_HIGH_LSB(chip), buf, 2); + if (rc < 0) { + pr_err("failed to read addr=0x%04x, rc=%d\n", + ADC_RR_FAKE_BATT_HIGH_LSB(chip), rc); + return rc; + } + + temp = (buf[1] << 8 | buf[0]) * 2500000; + do_div(temp, 150 * 1024); + batt_id[1] = temp; + pr_debug("debug batt_id range: [%d %d]\n", batt_id[0], batt_id[1]); + return 0; +} + static bool is_debug_batt_id(struct fg_chip *chip) { - int batt_id_delta = 0; + int debug_batt_id[2], rc; - if (!chip->batt_id_kohms) + if (!chip->batt_id_ohms) return false; - batt_id_delta = abs(chip->batt_id_kohms - DEBUG_BATT_ID_KOHMS); - if (batt_id_delta <= 1) { - fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dKohms\n", - chip->batt_id_kohms); + rc = fg_get_debug_batt_id(chip, debug_batt_id); + if (rc < 0) { + pr_err("Failed to get debug batt_id, rc=%d\n", rc); + return false; + } + + if (is_between(debug_batt_id[0], debug_batt_id[1], + chip->batt_id_ohms)) { + fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dohms\n", + chip->batt_id_ohms); return true; } @@ -792,8 +836,8 @@ static int fg_get_batt_profile(struct fg_chip *chip) return rc; } + chip->batt_id_ohms = batt_id; batt_id /= 1000; - chip->batt_id_kohms = batt_id; batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { pr_err("Batterydata not available\n"); @@ -1368,6 +1412,80 @@ static int fg_charge_full_update(struct fg_chip *chip) return 0; } +#define RCONN_CONFIG_BIT BIT(0) +static int fg_rconn_config(struct fg_chip *chip) +{ + int rc, esr_uohms; + u64 scaling_factor; + u32 val = 0; + + rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD, + SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading SW_CONFIG_OFFSET, rc=%d\n", rc); + return rc; + } + + if (val & RCONN_CONFIG_BIT) { + fg_dbg(chip, FG_STATUS, "Rconn already configured: %x\n", val); + return 0; + } + + rc = fg_get_battery_esr(chip, &esr_uohms); + if (rc < 0) { + pr_err("failed to get ESR, rc=%d\n", rc); + return rc; + } + + scaling_factor = div64_u64((u64)esr_uohms * 1000, + esr_uohms + (chip->dt.rconn_mohms * 1000)); + + rc = fg_sram_read(chip, ESR_RSLOW_CHG_WORD, + ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc); + return rc; + } + + val *= scaling_factor; + do_div(val, 1000); + rc = fg_sram_write(chip, ESR_RSLOW_CHG_WORD, + ESR_RSLOW_CHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc); + return rc; + } + fg_dbg(chip, FG_STATUS, "esr_rslow_chg modified to %x\n", val & 0xFF); + + rc = fg_sram_read(chip, ESR_RSLOW_DISCHG_WORD, + ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc); + return rc; + } + + val *= scaling_factor; + do_div(val, 1000); + rc = fg_sram_write(chip, ESR_RSLOW_DISCHG_WORD, + ESR_RSLOW_DISCHG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc); + return rc; + } + fg_dbg(chip, FG_STATUS, "esr_rslow_dischg modified to %x\n", + val & 0xFF); + + val = RCONN_CONFIG_BIT; + rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD, + SW_CONFIG_OFFSET, (u8 *)&val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing SW_CONFIG_OFFSET, rc=%d\n", rc); + return rc; + } + + return 0; +} + static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc) { u8 buf[4]; @@ -2330,6 +2448,9 @@ static int fg_notifier_cb(struct notifier_block *nb, if (event != PSY_EVENT_PROP_CHANGED) return NOTIFY_OK; + if (work_pending(&chip->status_change_work)) + return NOTIFY_OK; + if ((strcmp(psy->desc->name, "battery") == 0) || (strcmp(psy->desc->name, "usb") == 0)) { /* @@ -2575,6 +2696,14 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } + if (chip->dt.rconn_mohms > 0) { + rc = fg_rconn_config(chip); + if (rc < 0) { + pr_err("Error in configuring Rconn, rc=%d\n", rc); + return rc; + } + } + return 0; } @@ -3076,10 +3205,17 @@ static int fg_parse_dt(struct fg_chip *chip) } } + rc = of_property_read_u32(node, "qcom,rradc-base", &base); + if (rc < 0) { + dev_err(chip->dev, "rradc-base not specified, rc=%d\n", rc); + return rc; + } + chip->rradc_base = base; + rc = fg_get_batt_profile(chip); if (rc < 0) pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", - chip->batt_id_kohms, rc); + chip->batt_id_ohms / 1000, rc); /* Read all the optional properties below */ rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp); @@ -3236,6 +3372,12 @@ static int fg_parse_dt(struct fg_chip *chip) if (rc < 0) pr_err("Error in parsing Ki coefficients, rc=%d\n", rc); + rc = of_property_read_u32(node, "qcom,fg-rconn-mohms", &temp); + if (rc < 0) + chip->dt.rconn_mohms = -EINVAL; + else + chip->dt.rconn_mohms = temp; + return 0; } @@ -3362,7 +3504,7 @@ static int fg_gen3_probe(struct platform_device *pdev) if (!rc) pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n", - msoc, volt_uv, batt_temp, chip->batt_id_kohms); + msoc, volt_uv, batt_temp, chip->batt_id_ohms / 1000); device_init_wakeup(chip->dev, true); if (chip->profile_available) diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 507704dd469a..987e8258d301 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -2949,6 +2949,19 @@ irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data) return IRQ_HANDLED; } +irqreturn_t smblib_handle_wdog_bark(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb_charger *chg = irq_data->parent_data; + int rc; + + rc = smblib_write(chg, BARK_BITE_WDOG_PET_REG, BARK_BITE_WDOG_PET_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't pet the dog rc=%d\n", rc); + + return IRQ_HANDLED; +} + /*************** * Work Queues * ***************/ diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index b309095b04c1..001b62ad5b02 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -262,6 +262,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data); irqreturn_t smblib_handle_dc_plugin(int irq, void *data); irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data); irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data); +irqreturn_t smblib_handle_wdog_bark(int irq, void *data); int smblib_get_prop_input_suspend(struct smb_charger *chg, union power_supply_propval *val); diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index c2a2b0c86d73..ed43051adab6 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -897,7 +897,7 @@ enum { #define BITE_WDOG_INT_EN_BIT BIT(5) #define SFT_AFTER_WDOG_IRQ_MASK GENMASK(4, 3) #define WDOG_IRQ_SFT_BIT BIT(2) -#define WDOG_OPTION_BIT BIT(1) +#define WDOG_TIMER_EN_ON_PLUGIN_BIT BIT(1) #define WDOG_TIMER_EN_BIT BIT(0) #define MISC_CFG_REG (MISC_BASE + 0x52) diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c index 4255958de300..70d935e9d1df 100644 --- a/drivers/power/qcom-charger/smb138x-charger.c +++ b/drivers/power/qcom-charger/smb138x-charger.c @@ -192,11 +192,13 @@ static int smb138x_usb_get_prop(struct power_supply *psy, pr_err("get prop %d is not supported\n", prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; } static int smb138x_usb_set_prop(struct power_supply *psy, @@ -319,11 +321,13 @@ static int smb138x_batt_get_prop(struct power_supply *psy, pr_err("batt power supply get prop %d not supported\n", prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; } static int smb138x_batt_set_prop(struct power_supply *psy, @@ -457,11 +461,37 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, prop); return -EINVAL; } + if (rc < 0) { pr_debug("Couldn't get prop %d rc = %d\n", prop, rc); return -ENODATA; } - return 0; + + return rc; +} + +static int smb138x_set_parallel_suspend(struct smb138x *chip, bool suspend) +{ + struct smb_charger *chg = &chip->chg; + int rc = 0; + + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT, + suspend ? 0 : WDOG_TIMER_EN_BIT); + if (rc < 0) { + pr_err("Couldn't %s watchdog rc=%d\n", + suspend ? "disable" : "enable", rc); + suspend = true; + } + + rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, + suspend ? USBIN_SUSPEND_BIT : 0); + if (rc < 0) { + pr_err("Couldn't %s parallel charger rc=%d\n", + suspend ? "suspend" : "resume", rc); + return rc; + } + + return rc; } static int smb138x_parallel_set_prop(struct power_supply *psy, @@ -474,7 +504,7 @@ static int smb138x_parallel_set_prop(struct power_supply *psy, switch (prop) { case POWER_SUPPLY_PROP_INPUT_SUSPEND: - rc = smblib_set_usb_suspend(chg, val->intval); + rc = smb138x_set_parallel_suspend(chip, (bool)val->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_MAX: rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval); @@ -620,7 +650,7 @@ static int smb138x_init_vconn_regulator(struct smb138x *chip) static int smb138x_init_hw(struct smb138x *chip) { struct smb_charger *chg = &chip->chg; - int rc; + int rc = 0; /* votes must be cast before configuring software control */ vote(chg->usb_suspend_votable, @@ -772,6 +802,7 @@ static int smb138x_determine_initial_status(struct smb138x *chip) struct smb138x_irq_info { const char *name; const irq_handler_t handler; + const bool wake; const struct storm_watch storm_data; }; @@ -908,7 +939,8 @@ static const struct smb138x_irq_info smb138x_irqs[] = { }, { .name = "wdog-bark", - .handler = smblib_handle_debug, + .handler = smblib_handle_wdog_bark, + .wake = true, }, { .name = "aicl-fail", @@ -953,7 +985,7 @@ static int smb138x_request_interrupt(struct smb138x *chip, const char *irq_name) { struct smb_charger *chg = &chip->chg; - int rc, irq, irq_index; + int rc = 0, irq, irq_index; struct smb_irq_data *irq_data; irq = of_irq_get_byname(node, irq_name); @@ -968,6 +1000,9 @@ static int smb138x_request_interrupt(struct smb138x *chip, return irq_index; } + if (!smb138x_irqs[irq_index].handler) + return 0; + irq_data = devm_kzalloc(chg->dev, sizeof(*irq_data), GFP_KERNEL); if (!irq_data) return -ENOMEM; @@ -984,6 +1019,9 @@ static int smb138x_request_interrupt(struct smb138x *chip, return rc; } + if (smb138x_irqs[irq_index].wake) + enable_irq_wake(irq); + return rc; } @@ -1001,7 +1039,7 @@ static int smb138x_request_interrupts(struct smb138x *chip) prop, name) { rc = smb138x_request_interrupt(chip, child, name); if (rc < 0) { - pr_err("Coudn't request interrupt %s rc=%d\n", + pr_err("Couldn't request interrupt %s rc=%d\n", name, rc); return rc; } @@ -1092,7 +1130,7 @@ static int smb138x_slave_probe(struct smb138x *chip) rc = smblib_init(chg); if (rc < 0) { pr_err("Couldn't initialize smblib rc=%d\n", rc); - return rc; + goto cleanup; } if (chip->wa_flags & OOB_COMP_WA_BIT) { @@ -1102,7 +1140,7 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure the oob comp threh rc = %d\n", rc); - return rc; + goto cleanup; } rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, @@ -1110,22 +1148,41 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); - return rc; + goto cleanup; } } - /* suspend usb input */ - rc = smblib_set_usb_suspend(chg, true); + /* enable watchdog bark and bite interrupts, and disable the watchdog */ + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT + | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT + | BARK_WDOG_INT_EN_BIT, + BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); if (rc < 0) { - pr_err("Couldn't suspend USB input rc=%d\n", rc); - return rc; + pr_err("Couldn't configure the watchdog rc=%d\n", rc); + goto cleanup; + } + + /* disable charging when watchdog bites */ + rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + goto cleanup; + } + + /* suspend parallel charging */ + rc = smb138x_set_parallel_suspend(chip, true); + if (rc < 0) { + pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + goto cleanup; } /* initialize FCC to 0 */ rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); if (rc < 0) { pr_err("Couldn't set 0 FCC rc=%d\n", rc); - return rc; + goto cleanup; } /* enable the charging path */ @@ -1134,7 +1191,7 @@ static int smb138x_slave_probe(struct smb138x *chip) CHARGING_ENABLE_CMD_BIT); if (rc < 0) { dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); - return rc; + goto cleanup; } /* configure charge enable for software control; active high */ @@ -1143,7 +1200,7 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't configure charge enable source rc=%d\n", rc); - return rc; + goto cleanup; } /* enable parallel current sensing */ @@ -1152,16 +1209,27 @@ static int smb138x_slave_probe(struct smb138x *chip) if (rc < 0) { dev_err(chg->dev, "Couldn't enable parallel current sensing rc=%d\n", rc); - return rc; + goto cleanup; } - /* keep at the end of probe, ready to serve before notifying others */ rc = smb138x_init_parallel_psy(chip); if (rc < 0) { pr_err("Couldn't initialize parallel psy rc=%d\n", rc); - return rc; + goto cleanup; } + rc = smb138x_request_interrupts(chip); + if (rc < 0) { + pr_err("Couldn't request interrupts rc=%d\n", rc); + goto cleanup; + } + + return rc; + +cleanup: + smblib_deinit(chg); + if (chip->parallel_psy) + power_supply_unregister(chip->parallel_psy); return rc; } diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 21ff179b7c0b..65ce7d791a47 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -1670,6 +1670,14 @@ void ch_purge_intent_lists(struct channel_ctx *ctx) } spin_unlock_irqrestore(&ctx->tx_lists_lock_lhc3, flags); + spin_lock_irqsave(&ctx->tx_pending_rmt_done_lock_lhc4, flags); + list_for_each_entry_safe(tx_info, tx_info_temp, + &ctx->tx_pending_remote_done, list_done) { + ctx->notify_tx_abort(ctx, ctx->user_priv, tx_info->pkt_priv); + rwref_put(&tx_info->pkt_ref); + } + spin_unlock_irqrestore(&ctx->tx_pending_rmt_done_lock_lhc4, flags); + spin_lock_irqsave(&ctx->local_rx_intent_lst_lock_lhc1, flags); list_for_each_entry_safe(ptr_intent, tmp_intent, &ctx->local_rx_intent_list, list) { diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 7067c5733773..5f1064201b3a 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -2822,7 +2822,8 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, icnss_pr_dbg("Modem-Notify: event %lu\n", code); - if (code == SUBSYS_AFTER_SHUTDOWN) { + if (code == SUBSYS_AFTER_SHUTDOWN && + notif->crashed != CRASH_STATUS_WDOG_BITE) { icnss_remove_msa_permissions(priv); icnss_pr_info("Collecting msa0 segment dump\n"); icnss_msa0_ramdump(priv); diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c index dc803bdfd554..8ed98e2cbd5e 100644 --- a/drivers/soc/qcom/pil-q6v5-mss.c +++ b/drivers/soc/qcom/pil-q6v5-mss.c @@ -82,7 +82,7 @@ static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id) return IRQ_HANDLED; pr_err("Fatal error on the modem.\n"); - subsys_set_crash_status(drv->subsys, true); + subsys_set_crash_status(drv->subsys, CRASH_STATUS_ERR_FATAL); restart_modem(drv); return IRQ_HANDLED; } @@ -193,7 +193,7 @@ static irqreturn_t modem_wdog_bite_intr_handler(int irq, void *dev_id) !gpio_get_value(drv->subsys_desc.err_fatal_gpio)) panic("%s: System ramdump requested. Triggering device restart!\n", __func__); - subsys_set_crash_status(drv->subsys, true); + subsys_set_crash_status(drv->subsys, CRASH_STATUS_WDOG_BITE); restart_modem(drv); return IRQ_HANDLED; } diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c index 6bafa46a5c0b..43e3adeb0732 100644 --- a/drivers/soc/qcom/pil-q6v5.c +++ b/drivers/soc/qcom/pil-q6v5.c @@ -149,7 +149,7 @@ err_vreg_pll: err_cx_enable: regulator_set_load(drv->vreg_cx, 0); err_cx_mode: - regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE, uv); + regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE, INT_MAX); err_cx_voltage: clk_disable_unprepare(drv->qdss_clk); err_qdss_vote: @@ -179,7 +179,7 @@ void pil_q6v5_remove_proxy_votes(struct pil_desc *pil) } regulator_disable(drv->vreg_cx); regulator_set_load(drv->vreg_cx, 0); - regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE, uv); + regulator_set_voltage(drv->vreg_cx, RPM_REGULATOR_CORNER_NONE, INT_MAX); clk_disable_unprepare(drv->xo); clk_disable_unprepare(drv->pnoc_clk); clk_disable_unprepare(drv->qdss_clk); diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c index 6de73217bf86..d4be8c641ad8 100644 --- a/drivers/soc/qcom/smcinvoke.c +++ b/drivers/soc/qcom/smcinvoke.c @@ -235,7 +235,7 @@ static int marshal_out(void *buf, uint32_t buf_size, pr_err("%s: buffer overflow detected\n", __func__); goto out; } - if (copy_to_user((void __user *)(args_buf[i].b.addr), + if (copy_to_user((void __user *)(uintptr_t)(args_buf[i].b.addr), (uint8_t *)(buf) + tz_args->b.offset, tz_args->b.size)) { pr_err("Error %d copying ctxt to user\n", ret); @@ -320,7 +320,7 @@ static int marshal_in(const struct smcinvoke_cmd_req *req, tz_args++; if (copy_from_user(buf+offset, - (void __user *)(args_buf[i].b.addr), + (void __user *)(uintptr_t)(args_buf[i].b.addr), args_buf[i].b.size)) goto out; @@ -389,7 +389,7 @@ long smcinvoke_ioctl(struct file *filp, unsigned cmd, unsigned long arg) } ret = copy_from_user(args_buf, - (void __user *)(req.args), + (void __user *)(uintptr_t)(req.args), nr_args * req.argsize); if (ret) { @@ -424,8 +424,8 @@ long smcinvoke_ioctl(struct file *filp, unsigned cmd, unsigned long arg) ret = marshal_out(in_msg, inmsg_size, &req, args_buf); - ret |= copy_to_user((void __user *)(req.args), args_buf, - nr_args * req.argsize); + ret |= copy_to_user((void __user *)(uintptr_t)(req.args), + args_buf, nr_args * req.argsize); ret |= copy_to_user((void __user *)arg, &req, sizeof(req)); if (ret) goto out; diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index fcdcf0b6953e..5fee83f8ada4 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -352,11 +352,11 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info, switch (cb_info->link_state) { case GLINK_LINK_STATE_UP: - pr_debug("GLINK_LINK_STATE_UP.\n"); + pr_info("GLINK_LINK_STATE_UP.\n"); spcom_create_predefined_channels_chardev(); break; case GLINK_LINK_STATE_DOWN: - pr_debug("GLINK_LINK_STATE_DOWN.\n"); + pr_err("GLINK_LINK_STATE_DOWN.\n"); break; default: pr_err("unknown link_state [%d].\n", cb_info->link_state); @@ -466,7 +466,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event) * This is not expected on normal operation. * This may happen upon remote SSR. */ - pr_debug("GLINK_REMOTE_DISCONNECTED, ch [%s].\n", ch->name); + pr_err("GLINK_REMOTE_DISCONNECTED, ch [%s].\n", ch->name); /* * after glink_close(), * expecting notify GLINK_LOCAL_DISCONNECTED @@ -731,7 +731,9 @@ static int spcom_close(struct spcom_channel *ch) ch->glink_handle = NULL; ch->ref_count = 0; - + ch->rx_abort = false; + ch->tx_abort = false; + ch->glink_state = GLINK_LOCAL_DISCONNECTED; ch->txn_id = INITIAL_TXN_ID; /* use non-zero nonce for debug */ ch->pid = 0; diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index e70a56e7ce2e..b8d096a9c057 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -876,7 +876,7 @@ static irqreturn_t subsys_err_fatal_intr_handler (int irq, void *dev_id) d->subsys_desc.name); return IRQ_HANDLED; } - subsys_set_crash_status(d->subsys, true); + subsys_set_crash_status(d->subsys, CRASH_STATUS_ERR_FATAL); log_failure_reason(d); subsystem_restart_dev(d->subsys); @@ -895,7 +895,7 @@ static irqreturn_t subsys_wdog_bite_irq_handler(int irq, void *dev_id) !gpio_get_value(d->subsys_desc.err_fatal_gpio)) panic("%s: System ramdump requested. Triggering device restart!\n", __func__); - subsys_set_crash_status(d->subsys, true); + subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE); log_failure_reason(d); subsystem_restart_dev(d->subsys); @@ -952,7 +952,7 @@ static void clear_wdog(struct pil_tz_data *d) if (!subsys_get_crash_status(d->subsys)) { pr_err("wdog bite received from %s!\n", d->subsys_desc.name); __raw_writel(BIT(d->bits_arr[ERR_READY]), d->irq_clear); - subsys_set_crash_status(d->subsys, true); + subsys_set_crash_status(d->subsys, CRASH_STATUS_WDOG_BITE); log_failure_reason(d); subsystem_restart_dev(d->subsys); } diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c index 015e60ac622c..230a5329c8d4 100644 --- a/drivers/soc/qcom/subsystem_restart.c +++ b/drivers/soc/qcom/subsystem_restart.c @@ -178,7 +178,7 @@ struct subsys_device { struct cdev char_dev; dev_t dev_no; struct completion err_ready; - bool crashed; + enum crash_status crashed; int notif_state; struct list_head list; }; @@ -646,7 +646,7 @@ static void subsystem_powerup(struct subsys_device *dev, void *data) current, name); } subsys_set_state(dev, SUBSYS_ONLINE); - subsys_set_crash_status(dev, false); + subsys_set_crash_status(dev, CRASH_STATUS_NO_CRASH); } static int __find_subsys(struct device *dev, void *data) @@ -1126,12 +1126,13 @@ int subsystem_crashed(const char *name) } EXPORT_SYMBOL(subsystem_crashed); -void subsys_set_crash_status(struct subsys_device *dev, bool crashed) +void subsys_set_crash_status(struct subsys_device *dev, + enum crash_status crashed) { dev->crashed = crashed; } -bool subsys_get_crash_status(struct subsys_device *dev) +enum crash_status subsys_get_crash_status(struct subsys_device *dev) { return dev->crashed; } diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 176f22ba570c..c2ef091d72ce 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -157,6 +157,15 @@ int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, } EXPORT_SYMBOL(msm_ion_do_cache_op); +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd) +{ + return ion_do_cache_op(client, handle, vaddr, offset, len, cmd); +} +EXPORT_SYMBOL(msm_ion_do_cache_offset_op); + static int ion_no_pages_cache_ops(struct ion_client *client, struct ion_handle *handle, void *vaddr, @@ -305,13 +314,23 @@ static int ion_pages_cache_ops(struct ion_client *client, }; for_each_sg(table->sgl, sg, table->nents, i) { + unsigned int sg_offset, sg_left, size = 0; + len += sg->length; - if (len < offset) + if (len <= offset) continue; - __do_cache_ops(sg_page(sg), sg->offset, sg->length, op); + sg_left = len - offset; + sg_offset = sg->length - sg_left; - if (len > length + offset) + size = (length < sg_left) ? length : sg_left; + + __do_cache_ops(sg_page(sg), sg_offset, size, op); + + offset += size; + length -= size; + + if (length == 0) break; } return 0; diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h index d8677b2fb55a..098104d56fdb 100644 --- a/drivers/staging/android/ion/msm/msm_ion.h +++ b/drivers/staging/android/ion/msm/msm_ion.h @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #ifndef _MSM_MSM_ION_H #define _MSM_MSM_ION_H @@ -157,6 +170,11 @@ int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle, int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, void *vaddr, unsigned long len, unsigned int cmd); +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd); + #else static inline struct ion_client *msm_ion_client_create(const char *name) { @@ -176,6 +194,14 @@ static inline int msm_ion_do_cache_op(struct ion_client *client, return -ENODEV; } +int msm_ion_do_cache_offset_op( + struct ion_client *client, struct ion_handle *handle, + void *vaddr, unsigned int offset, unsigned long len, + unsigned int cmd) +{ + return -ENODEV; +} + #endif /* CONFIG_ION */ #endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 07867ead2413..85410a2214da 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -180,9 +180,9 @@ static int dwc3_core_reset(struct dwc3 *dwc) reg &= ~DWC3_GUSB3PIPECTL_DELAYP1TRANS; dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); - dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT, 0); - dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT, 0); return 0; } @@ -908,19 +908,19 @@ void dwc3_post_host_reset_core_init(struct dwc3 *dwc) dwc3_gadget_restart(dwc); } -static void (*notify_event) (struct dwc3 *, unsigned); -void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned)) +static void (*notify_event)(struct dwc3 *, unsigned, unsigned); +void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned, unsigned)) { notify_event = notify; } EXPORT_SYMBOL(dwc3_set_notifier); -int dwc3_notify_event(struct dwc3 *dwc, unsigned event) +int dwc3_notify_event(struct dwc3 *dwc, unsigned event, unsigned value) { int ret = 0; if (dwc->notify_event) - dwc->notify_event(dwc, event); + dwc->notify_event(dwc, event, value); else ret = -ENODEV; @@ -1317,7 +1317,7 @@ static int dwc3_suspend(struct device *dev) unsigned long flags; /* Check if platform glue driver handling PM, if not then handle here */ - if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT)) + if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT, 0)) return 0; spin_lock_irqsave(&dwc->lock, flags); @@ -1353,7 +1353,7 @@ static int dwc3_resume(struct device *dev) int ret; /* Check if platform glue driver handling PM, if not then handle here */ - if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT)) + if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0)) return 0; pinctrl_pm_select_default_state(dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 1fb5ce9caf98..c2cdfd1a823b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -731,6 +731,7 @@ struct dwc3_scratchpad_array { #define DWC3_CONTROLLER_NOTIFY_OTG_EVENT 6 #define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT 7 #define DWC3_CONTROLLER_RESTART_USB_SESSION 8 +#define DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER 9 #define MAX_INTR_STATS 10 /** @@ -952,7 +953,7 @@ struct dwc3 { const char *hsphy_interface; - void (*notify_event) (struct dwc3 *, unsigned); + void (*notify_event)(struct dwc3 *, unsigned, unsigned); struct work_struct wakeup_work; unsigned delayed_status:1; @@ -1252,7 +1253,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc); void dwc3_usb3_phy_suspend(struct dwc3 *dwc, int suspend); extern void dwc3_set_notifier( - void (*notify) (struct dwc3 *dwc3, unsigned event)); -extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned event); + void (*notify)(struct dwc3 *dwc3, unsigned event, unsigned value)); +extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned event, unsigned value); #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/dbm.c b/drivers/usb/dwc3/dbm.c index 34a1b6259d1b..0fbb1fb39f5c 100644 --- a/drivers/usb/dwc3/dbm.c +++ b/drivers/usb/dwc3/dbm.c @@ -37,6 +37,7 @@ enum dbm_reg { DBM_HW_TRB2_EP, DBM_HW_TRB3_EP, DBM_PIPE_CFG, + DBM_DISABLE_UPDXFER, DBM_SOFT_RESET, DBM_GEN_CFG, DBM_GEVNTADR_LSB, @@ -103,6 +104,7 @@ static const struct dbm_reg_data dbm_1_5_regtable[] = { [DBM_HW_TRB2_EP] = { 0x0240, 0x4 }, [DBM_HW_TRB3_EP] = { 0x0250, 0x4 }, [DBM_PIPE_CFG] = { 0x0274, 0x0 }, + [DBM_DISABLE_UPDXFER] = { 0x0298, 0x0 }, [DBM_SOFT_RESET] = { 0x020C, 0x0 }, [DBM_GEN_CFG] = { 0x0210, 0x0 }, [DBM_GEVNTADR_LSB] = { 0x0260, 0x0 }, @@ -291,6 +293,7 @@ int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe, bool producer, { int dbm_ep; u32 ep_cfg; + u32 data; if (!dbm) { pr_err("%s: dbm pointer is NULL!\n", __func__); @@ -334,6 +337,10 @@ int dbm_ep_config(struct dbm *dbm, u8 usb_ep, u8 bam_pipe, bool producer, msm_dbm_write_ep_reg_field(dbm, DBM_EP_CFG, dbm_ep, DBM_EN_EP, 1); + data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER); + data &= ~(0x1 << dbm_ep); + msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data); + return dbm_ep; } @@ -433,6 +440,35 @@ int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo, u32 addr_hi, int size) return 0; } +/** + * Disable update xfer before queueing stop xfer command to USB3 core. + * + * @usb_ep - USB physical EP number. + * + */ +int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep) +{ + u32 data; + u8 dbm_ep; + + if (!dbm) { + pr_err("%s: dbm pointer is NULL!\n", __func__); + return -EPERM; + } + + dbm_ep = find_matching_dbm_ep(dbm, usb_ep); + + if (dbm_ep < 0) { + pr_err("usb ep index %d has no corresponding dbm ep\n", usb_ep); + return -ENODEV; + } + + data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER); + data |= (0x1 << dbm_ep); + msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data); + + return 0; +} int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr, u32 size, u8 dst_pipe_idx) diff --git a/drivers/usb/dwc3/dbm.h b/drivers/usb/dwc3/dbm.h index 260afc241015..bf20d7cbd454 100644 --- a/drivers/usb/dwc3/dbm.h +++ b/drivers/usb/dwc3/dbm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -63,6 +63,7 @@ int dbm_ep_unconfig(struct dbm *dbm, u8 usb_ep); int dbm_get_num_of_eps_configured(struct dbm *dbm); int dbm_event_buffer_config(struct dbm *dbm, u32 addr_lo, u32 addr_hi, int size); +int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep); int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, phys_addr_t addr, u32 size, u8 dst_pipe_idx); void dbm_set_speed(struct dbm *dbm, bool speed); diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 15c994294c63..8a1b0d870e7a 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -367,6 +367,16 @@ static inline bool dwc3_msm_is_superspeed(struct dwc3_msm *mdwc) return dwc3_msm_is_dev_superspeed(mdwc); } +int dwc3_msm_dbm_disable_updxfer(struct dwc3 *dwc, u8 usb_ep) +{ + struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); + + dev_dbg(mdwc->dev, "%s\n", __func__); + dwc3_dbm_disable_update_xfer(mdwc->dbm, usb_ep); + + return 0; +} + #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) /** * Configure the DBM with the BAM's data fifo. @@ -1625,7 +1635,8 @@ static void dwc3_msm_vbus_draw_work(struct work_struct *w) dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw); } -static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) +static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event, + unsigned value) { struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); u32 reg; @@ -1717,6 +1728,9 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n"); schedule_work(&mdwc->restart_usb_work); break; + case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER: + dwc3_msm_dbm_disable_updxfer(dwc, value); + break; default: dev_dbg(mdwc->dev, "unknown dwc3 event\n"); break; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b6442fad550a..251ae0a7a5ee 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -384,7 +384,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, if (!(cmd & DWC3_DEPCMD_ENDTRANSFER)) { dwc->ep_cmd_timeout_cnt++; dwc3_notify_event(dwc, - DWC3_CONTROLLER_RESTART_USB_SESSION); + DWC3_CONTROLLER_RESTART_USB_SESSION, 0); } return -ETIMEDOUT; } @@ -1872,7 +1872,7 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned mA) dwc->vbus_draw = mA; dev_dbg(dwc->dev, "Notify controller from %s. mA = %d\n", __func__, mA); - dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT, 0); return 0; } @@ -1907,7 +1907,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) */ dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__); dwc->b_suspend = false; - dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); ret = dwc3_gadget_run_stop(dwc, is_on, false); spin_unlock_irqrestore(&dwc->lock, flags); @@ -2143,7 +2143,7 @@ static int dwc3_gadget_restart_usb_session(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); - return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION); + return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION, 0); } static const struct usb_gadget_ops dwc3_gadget_ops = { @@ -2659,6 +2659,10 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) if (!dep->resource_index) return; + if (dep->endpoint.endless) + dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER, + dep->number); + /* * NOTICE: We are violating what the Databook says about the * EndTransfer command. Ideally we would _always_ wait for the @@ -2743,7 +2747,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__); dwc->b_suspend = false; - dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); reg = dwc3_readl(dwc->regs, DWC3_DCTL); reg &= ~DWC3_DCTL_INITU1ENA; @@ -2799,7 +2803,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__); dwc->b_suspend = false; - dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); dwc3_usb3_phy_suspend(dwc, false); usb_gadget_vbus_draw(&dwc->gadget, 100); @@ -2960,7 +2964,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) return; } - dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT, 0); /* * Configure PHY via GUSB3PIPECTLn if required. @@ -2996,7 +3000,8 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup) */ dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__); dwc->b_suspend = false; - dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT); + dwc3_notify_event(dwc, + DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); /* * set state to U0 as function level resume is trying to queue @@ -3163,7 +3168,7 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__); dwc->b_suspend = true; - dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT); + dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0); } dwc->link_state = next; @@ -3334,7 +3339,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) evt->lpos = (evt->lpos + left) % DWC3_EVENT_BUFFERS_SIZE; dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), left); - if (dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT)) + if (dwc3_notify_event(dwc, + DWC3_CONTROLLER_ERROR_EVENT, 0)) dwc->err_evt_seen = 0; break; } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index a480b0a9a238..9360b0613154 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1670,8 +1670,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) value = min(w_length, (u16) value); break; case USB_DT_STRING: + spin_lock(&cdev->lock); value = get_string(cdev, req->buf, w_index, w_value & 0xff); + spin_unlock(&cdev->lock); if (value >= 0) value = min(w_length, (u16) value); break; diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 84b60ec771a4..8088593fad1a 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -1467,7 +1467,15 @@ static void gsi_ctrl_notify_resp_complete(struct usb_ep *ep, event->bNotificationType, req->status); /* FALLTHROUGH */ case 0: - /* + /* no need to handle multiple resp available for RNDIS */ + if (gsi->prot_id == IPA_USB_RNDIS) { + atomic_set(&gsi->c_port.notify_count, 0); + log_event_dbg("notify_count = %d", + atomic_read(&gsi->c_port.notify_count)); + break; + } + + /* * handle multiple pending resp available * notifications by queuing same until we're done, * rest of the notification require queuing new diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index 86908d2ce9d5..0f9447c986a4 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -1048,6 +1048,9 @@ static int qusb_phy_probe(struct platform_device *pdev) if (ret) usb_remove_phy(&qphy->phy); + /* de-asseert clamp dig n to reduce leakage on 1p8 upon boot up */ + writel_relaxed(0x0, qphy->tcsr_clamp_dig_n); + return ret; } diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c index fc61e3172d0b..64916f5566b5 100644 --- a/drivers/usb/phy/phy-msm-ssusb-qmp.c +++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c @@ -307,13 +307,13 @@ static int msm_ssphy_qmp_init(struct usb_phy *uphy) phy->clk_enabled = true; } - writel_relaxed(0x01, - phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]); - /* select usb3 phy mode */ if (phy->tcsr_usb3_dp_phymode) writel_relaxed(0x0, phy->tcsr_usb3_dp_phymode); + writel_relaxed(0x01, + phy->base + phy->phy_reg[USB3_PHY_POWER_DOWN_CONTROL]); + /* Make sure that above write completed to get PHY into POWER DOWN */ mb(); diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c index d3eb3db48eb7..9f1a24431de9 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.c +++ b/drivers/video/fbdev/msm/mdss_compat_utils.c @@ -846,6 +846,7 @@ static int __from_user_pcc_coeff_v17( return -EFAULT; } + memset(&pcc_cfg_payload, 0, sizeof(pcc_cfg_payload)); pcc_cfg_payload.r.b = pcc_cfg_payload32.r.b; pcc_cfg_payload.r.g = pcc_cfg_payload32.r.g; pcc_cfg_payload.r.c = pcc_cfg_payload32.r.c; @@ -1127,6 +1128,8 @@ static int __from_user_igc_lut_data_v17( pr_err("failed to copy payload from user for igc\n"); return -EFAULT; } + + memset(&igc_cfg_payload, 0, sizeof(igc_cfg_payload)); igc_cfg_payload.c0_c1_data = compat_ptr(igc_cfg_payload_32.c0_c1_data); igc_cfg_payload.c2_data = compat_ptr(igc_cfg_payload_32.c2_data); igc_cfg_payload.len = igc_cfg_payload_32.len; @@ -1261,6 +1264,7 @@ static int __from_user_pgc_lut_data_v1_7( pr_err("failed to copy from user the pgc32 payload\n"); return -EFAULT; } + memset(&pgc_cfg_payload, 0, sizeof(pgc_cfg_payload)); pgc_cfg_payload.c0_data = compat_ptr(pgc_cfg_payload_32.c0_data); pgc_cfg_payload.c1_data = compat_ptr(pgc_cfg_payload_32.c1_data); pgc_cfg_payload.c2_data = compat_ptr(pgc_cfg_payload_32.c2_data); @@ -1470,6 +1474,7 @@ static int __from_user_hist_lut_data_v1_7( return -EFAULT; } + memset(&hist_lut_cfg_payload, 0, sizeof(hist_lut_cfg_payload)); hist_lut_cfg_payload.len = hist_lut_cfg_payload32.len; hist_lut_cfg_payload.data = compat_ptr(hist_lut_cfg_payload32.data); @@ -2024,6 +2029,7 @@ static int __from_user_pa_data_v1_7( return -EFAULT; } + memset(&pa_cfg_payload, 0, sizeof(pa_cfg_payload)); pa_cfg_payload.mode = pa_cfg_payload32.mode; pa_cfg_payload.global_hue_adj = pa_cfg_payload32.global_hue_adj; pa_cfg_payload.global_sat_adj = pa_cfg_payload32.global_sat_adj; @@ -2280,6 +2286,8 @@ static int __from_user_gamut_cfg_data_v17( pr_err("failed to copy the gamut payload from userspace\n"); return -EFAULT; } + + memset(&gamut_cfg_payload, 0, sizeof(gamut_cfg_payload)); gamut_cfg_payload.mode = gamut_cfg_payload32.mode; for (i = 0; i < MDP_GAMUT_TABLE_NUM_V1_7; i++) { gamut_cfg_payload.tbl_size[i] = diff --git a/include/dt-bindings/clock/msm-clocks-hwio-8998.h b/include/dt-bindings/clock/msm-clocks-hwio-8998.h index f10afffc74b2..8dfa36362e8c 100644 --- a/include/dt-bindings/clock/msm-clocks-hwio-8998.h +++ b/include/dt-bindings/clock/msm-clocks-hwio-8998.h @@ -242,6 +242,7 @@ #define GPUCC_RBCPR_CBCR 0x01054 #define GPU_GX_BCR 0x01090 #define GPUCC_GX_DOMAIN_MISC 0x00130 +#define GPUCC_GPU_DD_WRAP_CTRL 0x00430 #define GPUCC_DEBUG_CLK_CTL 0x00120 #define MMSS_PLL_VOTE_APCS 0x001E0 diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 5cd588fa9f6a..744167a9ca8b 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -33,6 +33,7 @@ #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ #define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ #define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ +#define CLK_IS_MEASURE BIT(14) /* measure clock */ struct clk; struct clk_hw; diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h index 780666c332e2..763eaa9ad918 100644 --- a/include/soc/qcom/subsystem_restart.h +++ b/include/soc/qcom/subsystem_restart.h @@ -25,6 +25,12 @@ enum { RESET_LEVEL_MAX }; +enum crash_status { + CRASH_STATUS_NO_CRASH = 0, + CRASH_STATUS_ERR_FATAL, + CRASH_STATUS_WDOG_BITE, +}; + struct device; struct module; @@ -89,7 +95,7 @@ struct subsys_desc { /** * struct notif_data - additional notif information - * @crashed: indicates if subsystem has crashed + * @crashed: indicates if subsystem has crashed due to wdog bite or err fatal * @enable_ramdump: ramdumps disabled if set to 0 * @enable_mini_ramdumps: enable flag for minimized critical-memory-only * ramdumps @@ -97,7 +103,7 @@ struct subsys_desc { * @pdev: subsystem platform device pointer */ struct notif_data { - bool crashed; + enum crash_status crashed; int enable_ramdump; int enable_mini_ramdumps; bool no_auth; @@ -120,8 +126,9 @@ extern struct subsys_device *subsys_register(struct subsys_desc *desc); extern void subsys_unregister(struct subsys_device *dev); extern void subsys_default_online(struct subsys_device *dev); -extern void subsys_set_crash_status(struct subsys_device *dev, bool crashed); -extern bool subsys_get_crash_status(struct subsys_device *dev); +extern void subsys_set_crash_status(struct subsys_device *dev, + enum crash_status crashed); +extern enum crash_status subsys_get_crash_status(struct subsys_device *dev); void notify_proxy_vote(struct device *device); void notify_proxy_unvote(struct device *device); void complete_err_ready(struct subsys_device *subsys); @@ -174,9 +181,10 @@ struct subsys_device *subsys_register(struct subsys_desc *desc) static inline void subsys_unregister(struct subsys_device *dev) { } static inline void subsys_default_online(struct subsys_device *dev) { } +static inline void subsys_set_crash_status(struct subsys_device *dev, + enum crash_status crashed) { } static inline -void subsys_set_crash_status(struct subsys_device *dev, bool crashed) { } -static inline bool subsys_get_crash_status(struct subsys_device *dev) +enum crash_status subsys_get_crash_status(struct subsys_device *dev) { return false; } diff --git a/mm/cma.c b/mm/cma.c index 9ff71db72bc5..b55caef2454a 100644 --- a/mm/cma.c +++ b/mm/cma.c @@ -392,6 +392,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align) bitmap_maxno = cma_bitmap_maxno(cma); bitmap_count = cma_bitmap_pages_to_bits(cma, count); + if (bitmap_count > bitmap_maxno) + return NULL; + for (;;) { mutex_lock(&cma->lock); bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap, diff --git a/sound/soc/msm/msmfalcon-common.c b/sound/soc/msm/msmfalcon-common.c index c82319539f39..b4b35ee144ff 100644 --- a/sound/soc/msm/msmfalcon-common.c +++ b/sound/soc/msm/msmfalcon-common.c @@ -2746,8 +2746,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) ret); goto err; } - if (pdata->snd_card_val != INT_SND_CARD) - msm_ext_register_audio_notifier(); return 0; err: if (pdata->us_euro_gpio > 0) {