From 1b67e9a46ffd7a29a800ed76b9fdd40fd3b08b8d Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Wed, 13 Apr 2016 15:27:10 -0700 Subject: [PATCH 01/58] msm: sensor: Fix to read the parameters from slave info Fix to read positions, mode and mount angle from slave info. If an invalid value is specified in the slave info, default value specified in the camera dts node will be used. Change-Id: Id37ccc891bfd2bff48e3c2e9c3242cbe6148d3f7 Signed-off-by: Sureshnaidu Laveti --- .../msm/camera_v2/sensor/msm_sensor_driver.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) 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) { From ca95ed6a5776c38861f85ff005e8347c8ea41db5 Mon Sep 17 00:00:00 2001 From: Shiraz Hashim Date: Thu, 3 Nov 2016 15:24:35 +0530 Subject: [PATCH 02/58] mm: cma: check the max limit for cma allocation CMA allocation request size is represented by size_t that gets truncated when same is passed as int to bitmap_find_next_zero_area_off. We observe that during fuzz testing when cma allocation request is too high, bitmap_find_next_zero_area_off still returns success due to the truncation. This leads to kernel crash, as subsequent code assumes that requested memory is available. Fail cma allocation in case the request breaches the corresponding cma region size. Change-Id: Ieb5fd8429726efd7686387bccb55952fb053280a Signed-off-by: Shiraz Hashim --- mm/cma.c | 3 +++ 1 file changed, 3 insertions(+) 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, From 207b7ee89cebfe4a9779014a57de2417d4d2b3f2 Mon Sep 17 00:00:00 2001 From: Sathish Ambley Date: Mon, 6 Jul 2015 14:17:40 -0700 Subject: [PATCH 03/58] msm: rdbg: Add snapshot of remote debugger driver This snapshot was taken as of msm-3.10 commit ("Merge "msm: msm_bus: Provide valid input pointer argument") Updated source and documentation to fix checkpatch warnings. Change-Id: I6e84fc016a7bea69bb4d5d1991d8b5500244307d Acked-by: Vivek Iyer Acked-by: Mahesh Rohera Acked-by: Jay Jayanna Signed-off-by: Sathish Ambley --- Documentation/arm/msm/remote_debug_drv.txt | 468 ++++++++ drivers/char/Kconfig | 21 +- drivers/char/Makefile | 1 + drivers/char/rdbg.c | 1165 ++++++++++++++++++++ 4 files changed, 1648 insertions(+), 7 deletions(-) create mode 100644 Documentation/arm/msm/remote_debug_drv.txt create mode 100644 drivers/char/rdbg.c 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/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"); From a48c2750a23684d4849dd4b80fa8e4fa39cd02ab Mon Sep 17 00:00:00 2001 From: Osvaldo Banuelos Date: Wed, 19 Oct 2016 10:04:58 -0700 Subject: [PATCH 04/58] ARM: dts: msm: Add VDD_APC CPR voltage margins for msm8998 v2 Add VDD_APC0 and VDD_APC1 CPR per corner open-loop and closed-loop adjustments. These margins account for ACD being enabled. CRs-Fixed: 1090409 Change-Id: Iafafa4bece8ea5b6afd782fede3d44af69114ba1 Signed-off-by: Osvaldo Banuelos --- arch/arm/boot/dts/qcom/msm8998-v2.dtsi | 116 +++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index cc4e48ede2ad..79d22e9d4944 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi @@ -585,6 +585,58 @@ < 5000 11000 (-3000) 15000>, < 5000 11000 (-3000) 15000>; + 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; qcom,cpr-scaled-open-loop-voltage-as-ceiling; @@ -872,6 +924,70 @@ <(-15000) (-15000) (-3000) 35000>, <(-15000) (-15000) (-3000) 35000>; + qcom,cpr-open-loop-voltage-adjustment = + /* Speed bin 0 */ + <(-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 */ + <(-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; qcom,cpr-scaled-open-loop-voltage-as-ceiling; From fbc3530d4f5f5178dea98ff8df1acb2728a0f027 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 14 Nov 2016 18:11:50 -0800 Subject: [PATCH 05/58] soc: qcom: glink: Add pending remote done packets to intent purge Glink clients are not notified of tx transactions that are waiting for remote rx done commands during SSR. This change adds a notify_tx_abort call for any pending packets during intent purge. Change-Id: I6a6ba17e2dffddc5cdc2de00da737fedf03c9476 Signed-off-by: Chris Lew --- drivers/soc/qcom/glink.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 382245eb90b6..326fdf054e19 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -1665,6 +1665,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) { From ca8e442e9f5b57215474e44bac080f5ac46d5560 Mon Sep 17 00:00:00 2001 From: Chandana Kishori Chiluveru Date: Wed, 4 May 2016 13:05:40 +0530 Subject: [PATCH 06/58] usb: gadget: composite: Add spinlock protection for usb string descriptor During composition switch, android driver stops data transfers first and removes configuration before disabling the pullup. With this sequence there is a possibility for a race where usb_remove_config is in progress during which pullup is active and sending the setup request for strings with zero configuration value. Hence fix the issue by adding spinlock protection for get_sring descriptor. Change-Id: I13c601f0e48d847b322a2761cd52268963cacf01 Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/gadget/composite.c | 2 ++ 1 file changed, 2 insertions(+) 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; From 4397141808828d3f7808c1efb3b90c9773a8fda8 Mon Sep 17 00:00:00 2001 From: Krupal Divvela Date: Thu, 10 Nov 2016 16:55:02 +0530 Subject: [PATCH 07/58] ARM: dts: msm: Add cpp src clock rates configuration for msm8996 Add cpp src clock rates to device node configuration instead of using the list rate api from clock driver. CRs-Fixed: 1093630 Change-Id: If17c4ab996be31563a260ba3c326ee5e8f58e695 Signed-off-by: Krupal Divvela --- arch/arm/boot/dts/qcom/msm8996-camera.dtsi | 2 ++ 1 file changed, 2 insertions(+) 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>; From 7abf6aa50421d91a272aad7e19cf9d143e0ce2ea Mon Sep 17 00:00:00 2001 From: Abdulla Anam Date: Tue, 15 Nov 2016 20:41:10 +0530 Subject: [PATCH 08/58] msm: vidc: Add port information to flush_done event When video driver queues the flush event, it doesn't convey the port which is flushed. Due to this userspace content has to handle the event according to the flush status variables that it maintains. This handling can go wrong when there are concurrent flush commands from client. Address this by adding port detail to flush event. Change-Id: Ie9b7e35ad396ba8eed20dcca1f655b3e23f6626c Signed-off-by: Abdulla Anam --- .../platform/msm/vidc/hfi_response_handler.c | 16 ++++++++++ .../media/platform/msm/vidc/msm_vidc_common.c | 30 +++++++++++++++++-- .../media/platform/msm/vidc/vidc_hfi_api.h | 1 + 3 files changed, 45 insertions(+), 2 deletions(-) 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..55c75e869e30 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); } 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; }; From 18abc31c7193ee2908b85a8344f12880e574963a Mon Sep 17 00:00:00 2001 From: Avaneesh Kumar Dwivedi Date: Wed, 4 May 2016 19:32:53 +0530 Subject: [PATCH 09/58] soc: qcom: pil-q6v5: Update cx_max to INT_MAX while voting for CX rail To support a higher GPU frequency on MSM8937 Pro target the CX rail expects TURBO_HIGH voltage level. So while requesting regulator voltage for CX rail request with max value set as INT_MAX. Change-Id: I47eb863c4b384bb12e2ff21c44104847b0baa7ee Signed-off-by: Avaneesh Kumar Dwivedi --- drivers/soc/qcom/pil-q6v5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/pil-q6v5.c b/drivers/soc/qcom/pil-q6v5.c index 5752aecb82bd..e32049f9496c 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); From 84335e92118d92590286cf037ae3fdc5852f9409 Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Sun, 4 Dec 2016 22:16:57 -0800 Subject: [PATCH 10/58] msm: sensor: fixing errors due to csiphy clock release csiphy clock being released during initialization even in success case due to which enabling clk returns error, so fixed to release only whene there failures in other functionality. Change-Id: I9a7618850e45bd78f74fb2833932e3f4fd776392 Signed-off-by: Sureshnaidu Laveti --- .../media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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) From fa23f759bf8eb4cf05fe30b97e80807165b3b829 Mon Sep 17 00:00:00 2001 From: Maheshwar Ajja Date: Sun, 4 Dec 2016 14:02:26 -0800 Subject: [PATCH 11/58] msm: vidc: remove redundant init_completion() calls Video driver is doing init_completion() for all completion events in msm_vidc_initialize_core() and msm_vidc_open(). So there is no need of calling init_completion() again before waiting for completion event and hence remove them. CRs-Fixed: 1095803 Change-Id: Iedd9c4c0763c29b26e91e261d9a8d0e4e24b7bb2 Signed-off-by: Maheshwar Ajja --- .../media/platform/msm/vidc/msm_vidc_common.c | 20 ------------------- drivers/media/platform/msm/vidc/venus_hfi.c | 5 ----- 2 files changed, 25 deletions(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 73c52841fd34..e0cdca80eb05 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -2453,7 +2453,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) { @@ -2635,8 +2634,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", @@ -2740,8 +2737,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), @@ -2879,8 +2874,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, @@ -2910,8 +2903,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"); @@ -2941,8 +2932,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, @@ -2973,8 +2962,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, @@ -4020,8 +4007,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: @@ -4251,8 +4236,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) { @@ -4323,9 +4306,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 0055e22b40b4..ff1e993c9fee 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; @@ -2170,8 +2168,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"); @@ -3458,7 +3454,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"); From 2cd4abda5acfd4c86d7cb5ef34f87abc77594d91 Mon Sep 17 00:00:00 2001 From: Sreesudhan Ramakrish Ramkumar Date: Mon, 8 Feb 2016 20:15:56 -0800 Subject: [PATCH 12/58] msm: camera: isp: Fix HVX streaming after crash If user space process crashed, hvx state is not updated since it is updated during stream off (which never gets called during stream off). When camera is opened after crash, HVX configuration is not reset. This leads to data routed to HVX even if its disabled. Update HVX state during stream ON and configure HVX with enable / disable to fix the issue. Change-Id: I4b9cbba1261eafd83c67275c5d7dc3defbb3d990 Signed-off-by: Sreesudhan Ramakrish Ramkumar Signed-off-by: Shubhraprakash Das --- drivers/media/platform/msm/camera_v2/isp/msm_isp47.c | 2 ++ drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) 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 98e73d48ad15..06785edd3b6d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1507,6 +1507,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 72eac5d81627..be58cbc55ded 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 = From cb6c4678e761abfc18769d0443260e620b102c09 Mon Sep 17 00:00:00 2001 From: Jayant Shekhar Date: Tue, 6 Dec 2016 17:06:26 +0530 Subject: [PATCH 13/58] msm: mdss: Clear compat structures before copying to user In the compat layer, the temporary structures used to convert data from 32bit to 64bit structures need to be set to 0 before being assigned values. CRs-Fixed: 1088206 Change-Id: I04497bc11e01c3df4beadfd6d9b06ab4321f1723 Signed-off-by: Jayant Shekhar --- drivers/video/fbdev/msm/mdss_compat_utils.c | 8 ++++++++ 1 file changed, 8 insertions(+) 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] = From c5641f4d2722505db638b03679b69c4a594d1120 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Wed, 7 Dec 2016 19:23:35 +0530 Subject: [PATCH 14/58] defconfig: msmfalcon: enable host CDC-ECM class support Enable USB host CDC-ECM class support for msmfalcon. Change-Id: I8b69e8590e3de1aa79469003633b8837451bf3ed Signed-off-by: Vijayavardhan Vennapusa --- arch/arm/configs/msmfalcon-perf_defconfig | 1 + arch/arm/configs/msmfalcon_defconfig | 1 + arch/arm64/configs/msmfalcon_defconfig | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig index 86a9ac168d0e..4a283edb6fd1 100644 --- a/arch/arm/configs/msmfalcon-perf_defconfig +++ b/arch/arm/configs/msmfalcon-perf_defconfig @@ -273,6 +273,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 diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index b53d1bfec33e..03c820a9be01 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -272,6 +272,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 diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig index 26ad84e5ecca..da861b9a0565 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 From b3ce4f602675607f616b3617e54f2dbfd9b25786 Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 7 Dec 2016 11:46:22 -0800 Subject: [PATCH 15/58] ARM: dts: msm: disable VDD_GFX CPR aging adjustments on MSM8998v2 Disable VDD_GFX CPR aging measurement and adjustments for all global CPR fusing revisions. The initial aging sensor difference fuse will not be blown on parts with revision 3 so software must not attempt to perform an aging measurement on these parts. It is unknown which future revision will end up utilizing aging so also disable aging measurements on all future revisions as well. Modify the open-loop and closed-loop voltage adjustments accordingly so that the maximum 15 mV aging margin is present for all CPR revisions. Change-Id: I4d413a2b3320d421c487aff1a97e72bd2678b19f CRs-Fixed: 1097587 Signed-off-by: David Collins --- arch/arm/boot/dts/qcom/msm8998-v2.dtsi | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index cc4e48ede2ad..b3c7d02c60b8 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi @@ -964,11 +964,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,16 +977,16 @@ 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>; @@ -1000,7 +1000,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 { From 4bf6721985f7ac9b1b03fd09d6be11cfd3d9bcce Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 7 Dec 2016 13:36:22 -0800 Subject: [PATCH 16/58] ARM: dts: msm: reduce VDD_GFX CPR max floor to ceiling range for MSM8998v2 Reduce the VDD_GFX CPR maximum floor to ceiling voltage range for each corner in order to meet the most recent hardware guidelines. Change-Id: Ie70a698fbed442e8826f0bc30c5ef6bdfd5b3e1f CRs-Fixed: 1098577 Signed-off-by: David Collins --- arch/arm/boot/dts/qcom/msm8998-v2.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index b3c7d02c60b8..74a4e349564b 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi @@ -989,7 +989,7 @@ 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>; From d804378a310ada3631ac757de459342351c6213f Mon Sep 17 00:00:00 2001 From: Nicholas Troast Date: Tue, 18 Oct 2016 15:15:21 -0700 Subject: [PATCH 17/58] smb138x-charger: enable the watchdog timer when parallel is enabled If software becomes unresponsive then the battery could be overcharged by the parallel charger. Enable the watchdog so that when the bite timer expires then charging will be disabled by hardware. Change-Id: I82febbc28c05563d052c6eed034adc817df39790 Signed-off-by: Nicholas Troast --- drivers/power/qcom-charger/smb-lib.c | 13 +++ drivers/power/qcom-charger/smb-lib.h | 1 + drivers/power/qcom-charger/smb-reg.h | 2 +- drivers/power/qcom-charger/smb138x-charger.c | 110 +++++++++++++++---- 4 files changed, 104 insertions(+), 22 deletions(-) diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index 0faf8aee8aa0..c002fb7d0179 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -2954,6 +2954,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; } From 47b27b4d0f61f4ec4b3f608683cca1074eb2d211 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 8 Dec 2016 20:30:52 -0800 Subject: [PATCH 18/58] usb: qusb2: De-assert TCSR_QUSB2PHY_CLAMP_DIG_N_1P8 upon boot up This prevents leakage on 1p8 power rail upon boot up when usb cable is not connect. Change-Id: I28a4f495293863361843eb30b2d20f1f57889f95 Signed-off-by: Hemant Kumar --- drivers/usb/phy/phy-msm-qusb-v2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c index 5a768ee4d061..6d5fa2039837 100644 --- a/drivers/usb/phy/phy-msm-qusb-v2.c +++ b/drivers/usb/phy/phy-msm-qusb-v2.c @@ -1003,6 +1003,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; } From 61f63921e527ab5d6023b67088475a079bbbda3d Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Wed, 7 Dec 2016 19:46:23 +0530 Subject: [PATCH 19/58] ARM: dts: msm: Add qcom,msm-imem-diag-dload node on msmfalcon/msmtriton The diag dload memory region is part of IMEM. USB Diag driver queries this device node for the memory address to access and update USB PID and serial number. Hence add qcom,msm-imem-diag-dload node on msmfalcon and msmtriton. Change-Id: Ib283941037469833786b793c1e31e69e1c95d45d Signed-off-by: Vijayavardhan Vennapusa --- arch/arm/boot/dts/qcom/msmfalcon.dtsi | 5 +++++ arch/arm/boot/dts/qcom/msmtriton.dtsi | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index a9b903e2f902..d37f4e2ec4d9 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -1410,6 +1410,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; qcom,ghd { diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index adef0781de72..0ee1a6209d7b 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -935,6 +935,11 @@ compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; }; + + diag_dload@c8 { + compatible = "qcom,msm-imem-diag-dload"; + reg = <0xc8 200>; + }; }; qcom,ghd { From 151d532101b589df0419c272c5e7eb99355c8a51 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 21 Nov 2016 17:50:13 +0530 Subject: [PATCH 20/58] clk: qcom: Add support for debugfs measure clock Introduce clk_debug_mux which would support clocks to be allowed to measure clock frequency from debugfs. Change-Id: I81c32a876b33f5a7773485a76897ff9cbed45a76 Signed-off-by: Taniya Das --- drivers/clk/clk.c | 6 +- drivers/clk/clk.h | 2 + drivers/clk/qcom/common.c | 218 +++++++++++++++++++++++++++++++++++ drivers/clk/qcom/common.h | 91 +++++++++++++++ include/linux/clk-provider.h | 1 + 5 files changed, 317 insertions(+), 1 deletion(-) 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/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/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; From d9db5fe079f4b5f9407dddd591ebe70b967a21fd Mon Sep 17 00:00:00 2001 From: Ashwanth Goli Date: Fri, 9 Dec 2016 17:43:27 +0530 Subject: [PATCH 21/58] defconfig: Enable config INET_DIAG_DESTROY Enable config INET_DIAG_DESTROY for msm_falcon 32-bit Change-Id: I39c5ac30070ff8555ed712a99796b9405717b072 Signed-off-by: Ashwanth Goli --- arch/arm/configs/msmfalcon-perf_defconfig | 1 + arch/arm/configs/msmfalcon_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig index 86a9ac168d0e..e25ce74db0c7 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 diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index b53d1bfec33e..66fe9f6725fc 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 From a3e98f0134dab0ae0a137c3e0bab68c46c43d028 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 9 Dec 2016 11:19:04 -0800 Subject: [PATCH 22/58] usb: phy: qmp: Select usb3 phy mode before initializing PHY Make sure the USB3/DP PHY mode selection is switched back to USB3 mode before proceeding with PHY initialization. This fixes a bug when DisplayPort previously uses the PHY and does not switch it back which causes the POWER_DOWN_CONTROL register write to not take effect and results in USB3 PHY initialization failure. Change-Id: Idad0f80eda6192ccae9e824f1f76c7071806ffec Signed-off-by: Jack Pham --- drivers/usb/phy/phy-msm-ssusb-qmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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(); From e25600294bca6da11df1a2a7551f4c5b11f7ce60 Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 7 Dec 2016 12:02:22 -0800 Subject: [PATCH 23/58] ARM: dts: msm: disable VDD_APC0/1 CPR aging adjustments on MSM8998v2 Disable VDD_APC0 and VDD_APC1 CPR aging measurement and adjustments for all local CPR fusing revisions. It is unknown which future revision will have the initial aging sensor difference fuse blown. Software must not attempt to perform an aging measurement unless this fuse is blown. Therefore, disable aging measurements on all future revisions. Modify the open-loop and closed-loop voltage adjustments accordingly so that the maximum 15 mV aging margin is present for all CPR revisions. Change-Id: I4546a7994fc0442bf82d36ca0a404a57be8c7dd3 CRs-Fixed: 1097587 Signed-off-by: David Collins --- arch/arm/boot/dts/qcom/msm8998-v2.dtsi | 144 ++++++++++++------------- 1 file changed, 68 insertions(+), 76 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index b3c7d02c60b8..3ebcf3fe8c46 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,37 @@ <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,allow-voltage-interpolation; qcom,allow-quotient-interpolation; @@ -591,11 +591,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 +798,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 +836,37 @@ < 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>, - /* 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>, - /* Speed bin 1 */ + /* Speed bin 2 */ < 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 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,allow-voltage-interpolation; qcom,allow-quotient-interpolation; @@ -878,11 +874,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 { From dc4731a1e686431f46b4a25b24f95ba96e3f2c34 Mon Sep 17 00:00:00 2001 From: Laxminath Kasam Date: Sun, 11 Dec 2016 11:36:36 +0530 Subject: [PATCH 24/58] ASoC: msm: Disable audio SSR for msmfalcon Crash observed when listen to audio SSR notifiation during modem up event. Avoid listen to SSR events as temporary fix. Change-Id: I754a43a953a311938f4e4103879bff2c2a4551a0 Signed-off-by: Laxminath Kasam --- sound/soc/msm/msmfalcon-common.c | 2 -- 1 file changed, 2 deletions(-) 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) { From c988a9870da6a04e9a7b2a4b683a83e918c14804 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Mon, 12 Dec 2016 09:10:17 +0530 Subject: [PATCH 25/58] ARM: dts: msm: Add temp alarm nodes for pm/pm2falcon The temp_alarm module monitors the PMIC die-temp. Add the device tree nodes to enable the module. CRs-Fixed: 1100015 Change-Id: I17c5d04d8492f237d75eaf433a34b3451428d537 Signed-off-by: Anirudh Ghayal --- arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi | 7 +++++++ arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi | 9 +++++++++ 2 files changed, 16 insertions(+) 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..37e39b776613 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; From 49fc48e4c231ab117c59e69456bd50422978cdfd Mon Sep 17 00:00:00 2001 From: Amey Telawane Date: Thu, 24 Nov 2016 18:55:15 +0530 Subject: [PATCH 26/58] defconfig: enable qdss nodes in msmfalcon ETM coresight nodes are not present in 32-bit defconfig file for msmfalcon. Add support to enable ETM in msmfalcon. CRs-fixed: 1089405 Change-Id: I8259722a890d8388b62294de40cb29a9005f1a3e Signed-off-by: Amey Telawane --- arch/arm/configs/msmfalcon-perf_defconfig | 1 - arch/arm/configs/msmfalcon_defconfig | 4 +++- arch/arm64/configs/msmcortex-perf_defconfig | 2 -- drivers/hwtracing/coresight/Kconfig | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig index 6f26912a318d..9c8caf5fb4a9 100644 --- a/arch/arm/configs/msmfalcon-perf_defconfig +++ b/arch/arm/configs/msmfalcon-perf_defconfig @@ -587,7 +587,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 7ff481c87614..fff9e1ba0c02 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -516,6 +516,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 @@ -625,7 +626,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/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 From 998ec9c188bf78f2ffd1c9e7bbf65c525e225db2 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Thu, 10 Nov 2016 15:55:24 +0530 Subject: [PATCH 27/58] phy: ufs: add UFS PHY support for msmfalcon Add support for new UFS PHY that is used in falcon msm. This PHY is identical to the final 8996 PHY except it has been moved to VDDMX and level shifters have been added between the controller/chip and the PHY. Change-Id: I50681c877917a58c3d70262597300b0d66b1e3a8 Signed-off-by: Asutosh Das --- .../devicetree/bindings/ufs/ufs-qcom.txt | 4 +- drivers/phy/Makefile | 1 + drivers/phy/phy-qcom-ufs-qmp-v3-falcon.c | 260 ++++++++++++++++ drivers/phy/phy-qcom-ufs-qmp-v3-falcon.h | 283 ++++++++++++++++++ 4 files changed, 547 insertions(+), 1 deletion(-) create mode 100644 drivers/phy/phy-qcom-ufs-qmp-v3-falcon.c create mode 100644 drivers/phy/phy-qcom-ufs-qmp-v3-falcon.h 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/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 From 8fb5f8480348d27fef0037b97065494f39596544 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Wed, 5 Oct 2016 17:22:24 +0530 Subject: [PATCH 28/58] ARM: dts: msm: add ufs support to msmfalcon Add ufs and ufs-phy device nodes for msmfalcon. Change-Id: I42e796ca7e1883f5c2077660dbcde87cd4b30038 Signed-off-by: Asutosh Das --- arch/arm/boot/dts/qcom/msmfalcon-cdp.dtsi | 21 ++++++ arch/arm/boot/dts/qcom/msmfalcon-mtp.dtsi | 21 ++++++ arch/arm/boot/dts/qcom/msmfalcon-rumi.dts | 20 ++++++ arch/arm/boot/dts/qcom/msmfalcon-sim.dts | 21 ++++++ arch/arm/boot/dts/qcom/msmfalcon.dtsi | 79 +++++++++++++++++++++++ 5 files changed, 162 insertions(+) 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-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 572a896ad795..c76cdcdbb9ee 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -1565,6 +1565,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" From b4b3b9b16ae3320164808faf1d98fdc8821196d4 Mon Sep 17 00:00:00 2001 From: Manaf Meethalavalappu Pallikunhi Date: Tue, 25 Oct 2016 20:23:43 +0530 Subject: [PATCH 29/58] ARM: dts: msm: Configure lmh hardware for msmfalcon Configure the limits hardware with the interrupt to listen for. Limits hardware driver will interact with the trustzone to get throttling information from the hardware. Change-Id: I295ea05892075c43d389b3b9a20ea4f68daeba3b Signed-off-by: Manaf Meethalavalappu Pallikunhi --- arch/arm/boot/dts/qcom/msmfalcon.dtsi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index 572a896ad795..86dda25a21e4 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -706,6 +706,11 @@ }; }; + qcom,lmh { + compatible = "qcom,lmh_v1"; + interrupts = ; + }; + qcom,msm-core@780000 { compatible = "qcom,apss-core-ea"; reg = <0x780000 0x1000>; From fd9f279a8a16e61f79440bb356588e0bef5beb22 Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Mon, 12 Dec 2016 13:11:22 +0800 Subject: [PATCH 30/58] ARM: dts: msm: Add device tree for msmfalcon QRD Add initial device tree support for QRD platform of msmfalcon. Change-Id: Id6787274bf5e1dce8b813835af66874f667144ff Signed-off-by: Zhenhua Huang --- .../devicetree/bindings/arm/msm/msm.txt | 1 + arch/arm/boot/dts/qcom/Makefile | 3 ++- arch/arm/boot/dts/qcom/msmfalcon-qrd.dts | 23 ++++++++++++++++++ arch/arm/boot/dts/qcom/msmfalcon-qrd.dtsi | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/qcom/msmfalcon-qrd.dts create mode 100644 arch/arm/boot/dts/qcom/msmfalcon-qrd.dtsi 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/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/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 { +}; From 884d20e96e24295a2ddd318c72b69b7ab38d18d8 Mon Sep 17 00:00:00 2001 From: Amir Samuelov Date: Mon, 12 Dec 2016 11:00:43 +0200 Subject: [PATCH 31/58] spcom: cleanup rx-abort flag when channel closed When the remote subsystem crash (SSR), glink will notify rx-abort for any pending rx buffer that was queued. The notification callback sets the channel rx-abort flag. When the channel is closed, reset the rx-abort flag. Change-Id: I6cca614327f7b8e3216e3872a36f08f33a65b23e Signed-off-by: Amir Samuelov --- drivers/soc/qcom/spcom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index 0c5f3b84162b..841fb8656387 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -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; From 60338e0dd436a9b45da7eda26d7a30419d8ca9c6 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Mon, 12 Dec 2016 10:03:50 +0530 Subject: [PATCH 32/58] ARM: dts: msm: Add SPMI and PMIC nodes for msmtriton SPMI enables communication with PMIC peripherals. Add the device tree node for it. While at it, include the supported PMIC configuration. CRs-Fixed: 1100152 Change-Id: Ib892e3c550e7486d615e9d29e701d2b0c19c45f0 Signed-off-by: Anirudh Ghayal --- .../boot/dts/qcom/msmtriton-regulator.dtsi | 10 ++++++++ arch/arm/boot/dts/qcom/msmtriton.dtsi | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi index 323024278406..89369cc3ca6d 100644 --- a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi @@ -363,3 +363,13 @@ regulator-max-microvolt = <7>; }; }; + +&pmfalcon_charger { + smb2_vbus: qcom,smb2-vbus { + regulator-name = "smb2-vbus"; + }; + + smb2_vconn: qcom,smb2-vconn { + regulator-name = "smb2-vconn"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index dfa592c16643..b5472ec9cd46 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -1003,9 +1003,32 @@ 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 "msmtriton-regulator.dtsi" #include "msm-gdsc-falcon.dtsi" #include "msmfalcon-common.dtsi" From 3e66297d1b8048764f47250983dca7335eb49318 Mon Sep 17 00:00:00 2001 From: Anirudh Ghayal Date: Mon, 12 Dec 2016 11:44:29 +0530 Subject: [PATCH 33/58] ARM: dts: msm: Move to RPM based regulators for msmtriton Move the stub regulator to RPM-control based regulators for most of the rails. Keep the GFX regulator as a stub until the MSM GFX LDO node is added. CRs-Fixed: 1100152 Change-Id: Ib2d83635af352513064a3c8b717541bc47b2f875 Signed-off-by: Anirudh Ghayal --- .../boot/dts/qcom/msmtriton-regulator.dtsi | 686 +++++++++++------- arch/arm/boot/dts/qcom/msmtriton.dtsi | 2 + 2 files changed, 406 insertions(+), 282 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi index 89369cc3ca6d..2201a04cfbc1 100644 --- a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi @@ -10,357 +10,468 @@ * GNU General Public License for more details. */ -/* 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>; +&rpm_bus { + rpm-regulator-smpa4 { + status = "okay"; + pmfalcon_s4: regulator-s4 { + regulator-min-microvolt = <1805000>; + regulator-max-microvolt = <2040000>; + status = "okay"; + }; }; - /* 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>; + rpm-regulator-smpa5 { + status = "okay"; + pmfalcon_s5: regulator-s5 { + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-smpa6 { + status = "okay"; + pmfalcon_s6: regulator-s6 { + regulator-min-microvolt = <504000>; + regulator-max-microvolt = <992000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-smpb1 { + status = "okay"; + pm2falcon_s1: regulator-s1 { + regulator-min-microvolt = <1125000>; + regulator-max-microvolt = <1125000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-smpb2 { + status = "okay"; + pm2falcon_s2: regulator-s2 { + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; + status = "okay"; + }; }; - 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 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_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>; + /* 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; + }; }; - /* 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 = ; + rpm-regulator-ldoa1 { + status = "okay"; + pmfalcon_l1: regulator-l1 { + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1250000>; + status = "okay"; + }; }; - 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 = ; + rpm-regulator-ldoa2 { + status = "okay"; + pmfalcon_l2: regulator-l2 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; }; - 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 = ; + rpm-regulator-ldoa3 { + status = "okay"; + pmfalcon_l3: regulator-l3 { + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1010000>; + status = "okay"; + }; }; - /* 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 = ; + rpm-regulator-ldoa5 { + status = "okay"; + pmfalcon_l5: regulator-l5 { + regulator-min-microvolt = <525000>; + regulator-max-microvolt = <950000>; + status = "okay"; + }; }; - 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 = ; + 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>; + }; }; - 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 = ; + rpm-regulator-ldoa7 { + status = "okay"; + pmfalcon_l7: regulator-l7 { + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa8 { + status = "okay"; + pmfalcon_l8: regulator-l8 { + regulator-min-microvolt = <1750000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; }; - 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>; + 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>; + }; }; - 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>; + rpm-regulator-ldoa10 { + status = "okay"; + pmfalcon_l10: regulator-l10 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; }; - /* 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>; + rpm-regulator-ldoa11 { + status = "okay"; + pmfalcon_l11: regulator-l11 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa12 { + status = "okay"; + pmfalcon_l12: regulator-l12 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa13 { + status = "okay"; + pmfalcon_l13: regulator-l13 { + regulator-min-microvolt = <1780000>; + regulator-max-microvolt = <1950000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa14 { + status = "okay"; + pmfalcon_l14: regulator-l14 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <1900000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa15 { + status = "okay"; + pmfalcon_l15: regulator-l15 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldoa17 { + status = "okay"; + pmfalcon_l17: regulator-l17 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; }; - 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>; + 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>; + }; }; - 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>; + rpm-regulator-ldob1 { + status = "okay"; + pm2falcon_l1: regulator-l1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <925000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob2 { + status = "okay"; + pm2falcon_l2: regulator-l2 { + regulator-min-microvolt = <350000>; + regulator-max-microvolt = <3100000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob3 { + status = "okay"; + pm2falcon_l3: regulator-l3 { + regulator-min-microvolt = <1710000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob4 { + status = "okay"; + pm2falcon_l4: regulator-l4 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2950000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob5 { + status = "okay"; + pm2falcon_l5: regulator-l5 { + regulator-min-microvolt = <1721000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob6 { + status = "okay"; + pm2falcon_l6: regulator-l6 { + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <3300000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob7 { + status = "okay"; + pm2falcon_l7: regulator-l7 { + regulator-min-microvolt = <2700000>; + regulator-max-microvolt = <3125000>; + status = "okay"; + }; }; - 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>; + rpm-regulator-ldob8 { + status = "okay"; + pm2falcon_l8: regulator-l8 { + regulator-min-microvolt = <3200000>; + regulator-max-microvolt = <3400000>; + status = "okay"; + }; }; - 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 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_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 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; + }; }; - 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>; - }; + rpm-regulator-bobb { + status = "okay"; + pm2falcon_bob: regulator-bob { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3600000>; + status = "okay"; + }; - 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_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_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_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_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"; - regulator-name = "gfx_corner"; - regulator-min-microvolt = <1>; - regulator-max-microvolt = <7>; + 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; + }; }; }; @@ -373,3 +484,14 @@ regulator-name = "smb2-vconn"; }; }; + +/* Stub regulators */ +/ { + /* GFX Supply */ + gfx_vreg_corner: regulator-gfx-corner { + compatible = "qcom,stub-regulator"; + regulator-name = "gfx_corner"; + regulator-min-microvolt = <1>; + regulator-max-microvolt = <7>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi index b5472ec9cd46..333565698c80 100644 --- a/arch/arm/boot/dts/qcom/msmtriton.dtsi +++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi @@ -1029,6 +1029,8 @@ #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" From 63cba649895a093ccfef02778f5ad12f5a2d2abe Mon Sep 17 00:00:00 2001 From: AnilKumar Chimata Date: Mon, 12 Dec 2016 18:07:25 +0530 Subject: [PATCH 34/58] msm: mink: Fix compilation issues for 32bit targets Fix compilation errors which were triggered after enabling smcinvoke driver for targets which has 32bit architecture. Change-Id: Id85cea7720343cb4101155d5f33f93a1b9946abf Signed-off-by: AnilKumar Chimata --- drivers/soc/qcom/smcinvoke.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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; From d21ac4abb938a9a2121bebed3d61f18a02e41e68 Mon Sep 17 00:00:00 2001 From: AnilKumar Chimata Date: Thu, 1 Dec 2016 14:24:21 +0530 Subject: [PATCH 35/58] defconfig: msm: Enable SMCInvoke driver for msmfalcon_32 Enable SMCInvoke driver for msmfalcon_32 to communicate securely with TZ. Change-Id: I57aa131a67242d53164a52784ebfe619d77aac15 Signed-off-by: AnilKumar Chimata --- arch/arm/configs/msmfalcon-perf_defconfig | 1 + arch/arm/configs/msmfalcon_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/msmfalcon-perf_defconfig b/arch/arm/configs/msmfalcon-perf_defconfig index 6f26912a318d..6e0185088a71 100644 --- a/arch/arm/configs/msmfalcon-perf_defconfig +++ b/arch/arm/configs/msmfalcon-perf_defconfig @@ -527,6 +527,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 diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig index 7ff481c87614..2e2ecc237202 100644 --- a/arch/arm/configs/msmfalcon_defconfig +++ b/arch/arm/configs/msmfalcon_defconfig @@ -535,6 +535,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 From d3c08a3ceda4fc47a396cd86d18400a3a929add0 Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Fri, 29 Jan 2016 21:14:24 +0530 Subject: [PATCH 36/58] USB: dwc3-msm: Disable Update xfer for DBM on ep disable or dequeue Enable update xfer for DBM while configuring dbm endpoint and also clear update xfer before queueing end xfer command as part of endpoint disable as hardware programming guide. CRs-Fixed: 965207 Change-Id: Ib5ec650884ad06394280416ccf877c1ccce1eaaf Signed-off-by: Vijayavardhan Vennapusa Signed-off-by: Chandana Kishori Chiluveru --- drivers/usb/dwc3/core.c | 16 ++++++++-------- drivers/usb/dwc3/core.h | 7 ++++--- drivers/usb/dwc3/dbm.c | 38 ++++++++++++++++++++++++++++++++++++- drivers/usb/dwc3/dbm.h | 3 ++- drivers/usb/dwc3/dwc3-msm.c | 16 +++++++++++++++- drivers/usb/dwc3/gadget.c | 26 +++++++++++++++---------- 6 files changed, 82 insertions(+), 24 deletions(-) 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 285cd5a47d82..fc91bfb8b8d5 100644 --- a/drivers/usb/dwc3/dbm.c +++ b/drivers/usb/dwc3/dbm.c @@ -1,5 +1,5 @@ /* - * 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 @@ -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__); @@ -337,6 +340,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; } @@ -449,6 +456,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 bb6afb6a7d6d..b2085af28374 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -365,6 +365,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. @@ -1616,7 +1626,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; @@ -1708,6 +1719,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 2450cc52fa24..2858388fe8d1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -383,7 +383,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; } @@ -1871,7 +1871,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; } @@ -1906,7 +1906,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); @@ -2142,7 +2142,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 = { @@ -2658,6 +2658,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 @@ -2742,7 +2746,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; @@ -2798,7 +2802,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); @@ -2959,7 +2963,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. @@ -2995,7 +2999,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 @@ -3162,7 +3167,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; @@ -3333,7 +3338,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; } From 416d9ad85b891adc031934a4c5d638bde996d178 Mon Sep 17 00:00:00 2001 From: Amir Samuelov Date: Mon, 12 Dec 2016 16:57:24 +0200 Subject: [PATCH 37/58] spcom: print error messages when remote SP subsystem crash When the remote Secure Processor (SP) subsystem crash (SSR), the communication link goes down. Print error messages for this rare event. Change-Id: Ib3f719e218d972b75936d9960e342ecfe6787301 Signed-off-by: Amir Samuelov --- drivers/soc/qcom/spcom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index 0c5f3b84162b..7d2f99a294da 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 From eba048d51838b24856588fd2b774a5d1c4de30c7 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 28 Nov 2016 18:05:20 -0800 Subject: [PATCH 38/58] qpnp-fg-gen3: add support to configure Rconn Add support to configure battery connector resistance (Rconn) so that battery resistance can take into account of that along with ESR and Rslow. Change-Id: Ib330c4f9b6d55c75aeb8e8fd5cea4dd92b0f64cf Signed-off-by: Subbaraman Narayanamurthy --- .../power/qcom-charger/qpnp-fg-gen3.txt | 7 ++ drivers/power/qcom-charger/fg-core.h | 3 +- drivers/power/qcom-charger/qpnp-fg-gen3.c | 101 +++++++++++++++++- 3 files changed, 106 insertions(+), 5 deletions(-) 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 baf534695cc1..ac63b3c3bf01 100644 --- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt @@ -266,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 ========================================================== diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index e284de8bdff1..d8b6754a465f 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -211,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; @@ -224,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]; diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index f1dc6d8ab2fb..b7b437c6313c 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; } @@ -1407,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]; @@ -2614,6 +2693,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; } @@ -3282,6 +3369,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; } From 37a8348b873cba82c8c84f1bcacbc9f9fcaedb05 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 28 Nov 2016 16:05:09 -0800 Subject: [PATCH 39/58] qpnp-fg-gen3: Read debug battery id thresholds from RR_ADC registers Currently, GEN3 FG driver uses a debug battery id threshold of 7 KOhms. However, depending on the battery id chosen by the user this threshold can be modified in the bootloader. Hence, add support to read the debug battery id thresholds directly from RR_ADC peripheral registers. This can be used to decide whether a fake battery SOC (67) can be displayed to the user. Change-Id: I22ab702e10c310e4f847c6c81a48a8f0f3188429 Signed-off-by: Subbaraman Narayanamurthy --- .../power/qcom-charger/qpnp-fg-gen3.txt | 7 ++ arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi | 1 + arch/arm/boot/dts/qcom/msm-pmi8998.dtsi | 1 + drivers/power/qcom-charger/fg-core.h | 9 ++- drivers/power/qcom-charger/fg-reg.h | 4 ++ drivers/power/qcom-charger/qpnp-fg-gen3.c | 66 ++++++++++++++++--- 6 files changed, 77 insertions(+), 11 deletions(-) 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..baf534695cc1 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: @@ -290,6 +296,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/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi index 1cc31380604b..aef01ac34826 100644 --- a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi @@ -497,6 +497,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/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index 9ddd18800f9d..e284de8bdff1 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" @@ -310,8 +316,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 84204163f076..f1dc6d8ab2fb 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -693,18 +693,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 +831,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"); @@ -3076,10 +3115,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); @@ -3362,7 +3408,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) From 658891b3b91f47fd768e99342db3b6afb05543c1 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 6 Dec 2016 14:41:29 -0800 Subject: [PATCH 40/58] qpnp-fg-gen3: fix a possible wake source count leak Currently, in the power supply notifier callback, GEN3 FG driver calls pm_stay_awake() which increases the wake source count on its device before it schedules status_change_work. In case, if status_change_work is already pending, then pm_stay_awake() will not have a balanced pm_relax() call as the work will not get scheduled again if it's pending already. Fix this by scheduling status_change_work and hence call pm_stay_awake() only if it is not pending. Change-Id: I2b8e28f6bfe1a5813410c7b1276d4e229eb67e84 Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/qcom-charger/qpnp-fg-gen3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index b7b437c6313c..fd470f62c2b0 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -2448,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)) { /* From 1fb84944f4cfbee2d34651b6e8e358f383c38b02 Mon Sep 17 00:00:00 2001 From: Susheel Khiani Date: Thu, 21 Apr 2016 12:56:57 +0530 Subject: [PATCH 41/58] msm: ion: Export msm_ion_do_cache_offset_op to do cache operations The current API exposed to clients for doing cache operations didn't provide option to specify offset within ion buffer and goes and performs operation on complete buffer. Export new function for clients which wants to perform cache operation on specific range within ion buffer. We would also need to amend the current generic ion_do_cache_op function to correctly take into account the offset within buffer. Change-Id: I5e4e7beda47cbbd43783048c64fe5adb2beb7023 Signed-off-by: Susheel Khiani Signed-off-by: Patrick Daly --- drivers/staging/android/ion/msm/msm_ion.c | 25 +++++++++++++++++++--- drivers/staging/android/ion/msm/msm_ion.h | 26 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) 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 From 78417f54789d7681d8b5336f2f244624f7a25077 Mon Sep 17 00:00:00 2001 From: Deepak Katragadda Date: Mon, 12 Dec 2016 14:48:12 -0800 Subject: [PATCH 42/58] clk: msm: clock-gpu-8998: Program the Droop Detector gfx_pdn In order to avoid leakage between the graphics and the CX rails, set the GPU_DD_WRAP_CTRL__GFX_PDN bit. Change-Id: I7b2e59606e73c467c2b862f0162a176611d7ae3d Signed-off-by: Deepak Katragadda --- drivers/clk/msm/clock-gpu-8998.c | 9 +++++++++ include/dt-bindings/clock/msm-clocks-hwio-8998.h | 1 + 2 files changed, 10 insertions(+) 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/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 From 108e051cd48d4a79439bcfb517cc5cb659d34dfd Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 8 Dec 2016 17:37:53 -0800 Subject: [PATCH 43/58] usb: gadget: Reset notify count to 0 upon completion for RNDIS When host RNDIS sends reset message it skips response available notification and directly sends get encap response. This causes notify count to become > 1. As a result when notify completion happens driver is queuing another notify response available when there is no legitimate response to send from device side. Hence reset notify count back to 0 after the completion of notify response, so that next notification will only be sent when there is a send encap command sent by host. Change-Id: I242478408f8cb60fb5af5c741dbf2e8bf3e38af8 Signed-off-by: Hemant Kumar --- drivers/usb/gadget/function/f_gsi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index af20033b621f..961af43bc9bd 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 From 6428373814f97f7cdcd9ff65b2d2b0c105cbf906 Mon Sep 17 00:00:00 2001 From: Ashwini Rao Date: Thu, 21 Jan 2016 14:16:20 -0800 Subject: [PATCH 44/58] msm: fd: Handle timeout on stream off On stream off, if there is a timeout waiting for the current buffer to complete, do a vb2_buffer_done on the active buffer before it is removed from the queue. Reduce the timeout wait time to 150ms CRs-fixed: 961394 Change-Id: I57d616e9cf89f7722483fe0d49a0b5e44f0e4782 Signed-off-by: Ashwini Rao --- drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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..17c51383682b 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 */ @@ -1153,6 +1153,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 */ From ea445a93a03fe68f643e18cfc7c87c8c1c28c225 Mon Sep 17 00:00:00 2001 From: Peter Liu Date: Thu, 21 Jan 2016 13:57:51 -0800 Subject: [PATCH 45/58] msm: camera: cpp: Add cpp bus error handler Reset and halt the bus when bus hang with cpp timeout. CRs-Fixed: 961394 Change-Id: Id3612b134e3db19f1f8e2e2b3b444f0b6284c4d1 Signed-off-by: Peter Liu Signed-off-by: Rajakumar Govindaram --- .../msm/camera_v2/pproc/cpp/msm_cpp.c | 65 +++++++++++++++++++ .../msm/camera_v2/pproc/cpp/msm_cpp.h | 21 ++++++ 2 files changed, 86 insertions(+) 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..51bf6f9df853 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); @@ -171,6 +172,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; @@ -1215,6 +1236,32 @@ end: 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; @@ -1284,6 +1331,10 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) rc = -ENOMEM; } } + + msm_cpp_vbif_register_error_handler(cpp_dev, + VBIF_CLIENT_CPP, cpp_vbif_error_handler); + mutex_unlock(&cpp_dev->mutex); return 0; } @@ -1383,6 +1434,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; } @@ -1637,6 +1691,15 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) goto end; } + pr_err("%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); + } + pr_debug("Reloading firmware %d\n", queue_len); rc = cpp_load_fw(cpp_timer.data.cpp_dev, cpp_timer.data.cpp_dev->fw_name_bin); @@ -4195,6 +4258,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__ */ From 034f436b68048a5860de3f0df3fbf73f348a8df8 Mon Sep 17 00:00:00 2001 From: Ashwini Rao Date: Thu, 21 Jan 2016 14:59:14 -0800 Subject: [PATCH 46/58] msm: camera: fd: Add CPP VBIF error handling On detecting a VBIF hang, reset the VBIF and FD core and if there is an active buffer, queue back the active buffer and start processing again. CRs-Fixed: 961394 Change-Id: I1ed035c8a8efb20d31da9556c5d5b810f81c44d2 Signed-off-by: Ashwini Rao --- .../platform/msm/camera_v2/fd/msm_fd_dev.c | 79 +++++++++++++++++++ .../platform/msm/camera_v2/fd/msm_fd_dev.h | 5 ++ .../platform/msm/camera_v2/fd/msm_fd_hw.c | 4 + 3 files changed, 88 insertions(+) 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..1cfb7a3dfa00 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); @@ -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..e7dcb383d09f 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,7 @@ struct msm_fd_device { struct workqueue_struct *work_queue; struct work_struct work; struct completion hw_halt_completion; + int recovery_mode; }; #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 17c51383682b..c5efb1153204 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 @@ -1058,6 +1058,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; } @@ -1260,6 +1262,8 @@ 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); From 95db044dafc2c65640a3e26b3a48cb632c750b8c Mon Sep 17 00:00:00 2001 From: Sunid Wilson Date: Mon, 7 Mar 2016 14:41:25 -0800 Subject: [PATCH 47/58] msm: fd: Support dynamic update of clock and bus settings Change the bus settings and clocks based on the user settings while streaming is in progress. CRs-Fixed: 985849 Change-Id: If9307ffd47854afe6101671ce911631b52a6dff9 Signed-off-by: Sunid Wilson --- .../platform/msm/camera_v2/fd/msm_fd_dev.h | 1 + .../platform/msm/camera_v2/fd/msm_fd_hw.c | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+) 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 e7dcb383d09f..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 @@ -253,6 +253,7 @@ struct msm_fd_device { 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 c5efb1153204..760a59d15a31 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 @@ -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++; @@ -1229,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; } @@ -1267,5 +1310,7 @@ int msm_fd_hw_schedule_next_buffer(struct msm_fd_device *fd) } spin_unlock(&fd->slock); + msm_fd_hw_update_settings(fd, buf); + return 0; } From 473c5b0d7e9262424d3027401ecc779e76af25a0 Mon Sep 17 00:00:00 2001 From: Kui Wang Date: Wed, 16 Nov 2016 12:17:19 +0800 Subject: [PATCH 48/58] ARM: dts: msm: Add camera dtsi for msmfalcon interposer qrd Add camera related device nodes for msmfalcon interposer qrd. That includes front/rear/aux sensor device nodes, and corresponding eeprom/actuator/ois device nodes. Change-Id: I4f8ca4182f9807d970184c85a58989b41755b163 Signed-off-by: Kui Wang --- .../msm8998-interposer-camera-sensor-qrd.dtsi | 511 ++++++++++++++++++ .../msm8998-v2.1-interposer-msmfalcon-qrd.dts | 2 +- 2 files changed, 512 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi 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-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 = From 843dac9993a481a2f0cecbf04e1de91804c3805c Mon Sep 17 00:00:00 2001 From: Rupesh Tatiya Date: Thu, 1 Dec 2016 14:11:39 +0530 Subject: [PATCH 49/58] ARM: dts: msm: Enable bluetooth for wcn3990 on msm8998 interposer Enable various voltage regulators, clocks required to enable bluetooth on msm8998 interposer. CRs-Fixed: 1097035 Change-Id: I9f70b74b7ccfb84fec721dbfa1d838d183419cb9 Signed-off-by: Rupesh Tatiya --- .../msm8998-interposer-msmfalcon-cdp.dtsi | 27 ------------------- .../msm8998-interposer-msmfalcon-mtp.dtsi | 27 ------------------- .../qcom/msm8998-interposer-msmfalcon.dtsi | 19 +++++++++++++ .../dts/qcom/msm8998-interposer-pmfalcon.dtsi | 9 ------- 4 files changed, 19 insertions(+), 63 deletions(-) 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; From faef6bbca74dcfe02e0840777c8f6b3806041227 Mon Sep 17 00:00:00 2001 From: Manish Poddar Date: Wed, 23 Mar 2016 16:57:23 +0530 Subject: [PATCH 50/58] msm: camera: Initialize variables to default Add NULL check and initialize the variables to default values in camera. CRs-fixed: 994317 Change-Id: I165f1c39c1332737a644c6650bc40f4c718a7ee8 Signed-off-by: Manish Poddar --- drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c | 5 +++++ drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c | 2 +- drivers/media/platform/msm/camera_v2/fd/msm_fd_hw.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) 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 1cfb7a3dfa00..4deda8da3871 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 @@ -540,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 = -EINVAL; int i; switch (cmd) { 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 760a59d15a31..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 @@ -965,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); From dd1c15c8028467a1122fff656e6c6cdc67a551bb Mon Sep 17 00:00:00 2001 From: Manish Poddar Date: Mon, 11 Apr 2016 11:27:42 +0530 Subject: [PATCH 51/58] msm: camera: Initialize return value to 0 Initialize return variable to 0 instead of error. CRs-fixed: 1001532 Change-Id: I81c87cac13e33e0678b3bb92f58da0699d9197c2 Signed-off-by: Manish Poddar --- drivers/media/platform/msm/camera_v2/fd/msm_fd_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4deda8da3871..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 @@ -540,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 = -EINVAL; + int ret = 0; int i; switch (cmd) { From 925920826d9bc217d9cbca212cff1eddfcbf4f83 Mon Sep 17 00:00:00 2001 From: Krishnankutty Kolathappilly Date: Mon, 12 Dec 2016 13:59:40 -0800 Subject: [PATCH 52/58] msm: cpp: Reset vbif and load firmware on poll failures CPP poll failure can happen if vbif reset is not proper. Reset vbif and load firmware on poll failures to recover from error scenario. CRs-Fixed: 1098549 Change-Id: I38ef1c9478450c98c8379d8b1c085b31209cb48e Signed-off-by: Krishnankutty Kolathappilly --- .../msm/camera_v2/pproc/cpp/msm_cpp.c | 96 ++++++++++++++----- 1 file changed, 71 insertions(+), 25 deletions(-) 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 51bf6f9df853..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 @@ -122,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) @@ -776,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; @@ -786,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) { @@ -1043,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 + @@ -1059,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) @@ -1102,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__); @@ -1228,14 +1245,44 @@ 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; @@ -1302,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) { @@ -1332,9 +1383,6 @@ static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } } - msm_cpp_vbif_register_error_handler(cpp_dev, - VBIF_CLIENT_CPP, cpp_vbif_error_handler); - mutex_unlock(&cpp_dev->mutex); return 0; } @@ -1691,21 +1739,16 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) goto end; } - pr_err("%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); - } - pr_debug("Reloading firmware %d\n", queue_len); 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"); } @@ -2989,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) { From 1056fb70ed60efc437ee0e640337913f62e6e1e4 Mon Sep 17 00:00:00 2001 From: Vijay kumar Tumati Date: Tue, 13 Dec 2016 14:18:10 +0530 Subject: [PATCH 53/58] ARM: dts: msm: Enable CAM1 on msmfalcon interposer Add DTSI configuration for camera node 1. Used by all sensor modules that are connected to this port. Change-Id: I3301d822a3664869d8531d7ff0efa20e22996763 Signed-off-by: Vijay kumar Tumati --- .../msm8998-interposer-camera-sensor-cdp.dtsi | 43 +++++++++++++++++++ .../msm8998-interposer-camera-sensor-mtp.dtsi | 43 +++++++++++++++++++ 2 files changed, 86 insertions(+) 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"; From 309430921f7ebd058cd261a589991674990b3b5b Mon Sep 17 00:00:00 2001 From: Andrey Markovytch Date: Tue, 13 Dec 2016 15:44:37 +0200 Subject: [PATCH 54/58] qseecom: add configurable encryption key size ICE crypto engine key size can now be configured using dtsi flag. This is required to facilitate usage of common TZ image with variable key sizes and also provides flexibility in handling different key sizes requirement in future. This flag is parsed in driver and depending upon the value HLOS decides on key size to be passed to TZ. Change-Id: If40f83a943e5ae8333d171c21823a16816d7ddd4 Signed-off-by: Neeraj Soni Signed-off-by: Andrey Markovytch --- .../devicetree/bindings/qseecom/qseecom.txt | 3 +++ drivers/misc/qseecom.c | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+) 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/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"); From f28a6750a843ee4ef456e097fe43a03dbd048668 Mon Sep 17 00:00:00 2001 From: Andrey Markovytch Date: Tue, 13 Dec 2016 15:49:50 +0200 Subject: [PATCH 55/58] ARM: dts: msm: specify a flag to control encryption key size on msm8998 This is required to control the FDE/FBE key size from kernel. Same TZ image can now be used for different encryption key sizes. The key size will not be fixed and will be controlled with this flag in qseecom driver. Change-Id: Iac5c25ba5dc7d22cd7a4961dd5058db0088995ca Signed-off-by: Andrey Markovytch --- arch/arm/boot/dts/qcom/msm8998.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index c265eafcdd30..777efe36f507 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -2250,6 +2250,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>; From de7e98f381fe115576dc5908801bd4e0f86d5259 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Tue, 13 Dec 2016 08:55:07 -0800 Subject: [PATCH 56/58] defconfig: arm64: Enable USBNET driver This change enables USBNET driver which allows USB ethernet class driver to register USB ethernet device as network device with Linux Network Stack and allows USB IOs with USB Host Controller driver. Change-Id: Iba036ce43656979df0b9ea228b57bc980c4c53bc Signed-off-by: Mayank Rana --- arch/arm64/configs/msmcortex_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From ef124ecde2998f08ee84f5badd3d95a0a7308977 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Thu, 15 Dec 2016 13:33:39 -0800 Subject: [PATCH 57/58] soc: qcom: ssr: add crash status to know why subsys crashed In some specific cases, clients may want to know why subsystem crashed, for example, in case of watch dog bite, subsystem may not be able to execute error handling. Which would need different code paths to be exercised on the apps processor. Change-Id: I073733b8a56b57f14906b25cba08012c2f0b414a Signed-off-by: Satya Durga Srinivasu Prabhala --- drivers/net/wireless/cnss/cnss_pci.c | 4 ++-- drivers/net/wireless/cnss/cnss_sdio.c | 3 ++- drivers/soc/qcom/pil-q6v5-mss.c | 4 ++-- drivers/soc/qcom/subsys-pil-tz.c | 6 +++--- drivers/soc/qcom/subsystem_restart.c | 9 +++++---- include/soc/qcom/subsystem_restart.h | 20 ++++++++++++++------ 6 files changed, 28 insertions(+), 18 deletions(-) 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/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/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/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; } From 58a7b9f5326470dbe8e11b749cda5fcefa68f3b3 Mon Sep 17 00:00:00 2001 From: Sameer Thalappil Date: Thu, 15 Dec 2016 18:00:06 -0800 Subject: [PATCH 58/58] icnss: Do not collect MSA0 dump during Modem WDOG bite During modem WDOG bite scenarios, error handlers are not executed in modem. So Adrastea may not be in reset when SSR notifications are received in HLOS. Remapping MSA0 during SSR could cause SMMU fault at Adrastea, as it may be still accessing it. Skip collecting MSA0 dump in WDOG bite scenarios. CRs-Fixed: 1102057 Change-Id: I9082d4d40b70d0ca8cc8fbc6aadf14b2f0aedd0c Signed-off-by: Sameer Thalappil --- drivers/soc/qcom/icnss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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);