Merge 84851d12f3 on remote branch

Change-Id: Ia6060b48ba72e1f2604cfca4a2d8ca1dead6e6d1
This commit is contained in:
Linux Build Service Account
2024-01-16 04:11:32 -08:00
51 changed files with 3285 additions and 950 deletions

View File

@@ -3,5 +3,13 @@ CONFIG_TMPFS_POSIX_ACL=y
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CH341=y
CONFIG_USB_SERIAL_CP210X=y
CONFIG_I2C_MUX=y
CONFIG_PINCTRL_SX150X=y
CONFIG_GPIO_SYSFS=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_CAN=y
CONFIG_USB_XHCI_PCI_RENESAS=y
CONFIG_HWMON=y
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_THERMAL_HWMON=y

View File

@@ -203,6 +203,8 @@ CONFIG_QRTR_WAKEUP_MS=0
CONFIG_QTI_CPUFREQ_CDEV=m
CONFIG_QTI_CPU_HOTPLUG_COOLING_DEVICE=m
# CONFIG_QTI_CPU_PAUSE_COOLING_DEVICE is not set
CONFIG_QTI_CRYPTO_COMMON=m
CONFIG_QTI_CRYPTO_TZ=m
CONFIG_QTI_DEVFREQ_CDEV=m
CONFIG_QTI_PMIC_PON_LOG=m
CONFIG_QTI_QMI_COOLING_DEVICE=m
@@ -233,6 +235,7 @@ CONFIG_SA_DISPCC_LEMANS=m
CONFIG_SA_GCC_LEMANS=m
CONFIG_SA_GPUCC_LEMANS=m
CONFIG_SA_VIDEOCC_LEMANS=m
CONFIG_SCSI_UFS_CRYPTO_QTI=m
CONFIG_SCSI_UFS_QCOM=m
CONFIG_SERIAL_MSM_GENI=m
# CONFIG_SND_USB_AUDIO_QMI is not set

View File

@@ -39,6 +39,7 @@ CONFIG_CPU_IDLE_GOV_QCOM_LPM=m
CONFIG_EDAC_QCOM=m
# CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE is not set
CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
CONFIG_EP_PCIE=m
# CONFIG_EXT4_KUNIT_TESTS is not set
# CONFIG_FAT_KUNIT_TEST is not set
CONFIG_GH_ARM64_DRV=m
@@ -114,6 +115,8 @@ CONFIG_MSM_CORE_HANG_DETECT=m
CONFIG_MSM_GLOBAL_SYNX=m
CONFIG_MSM_GPI_DMA=m
# CONFIG_MSM_GPI_DMA_DEBUG is not set
CONFIG_MSM_MHI_DEV=m
CONFIG_MSM_MHI_NET_DEV=m
CONFIG_MSM_PERFORMANCE=m
CONFIG_MSM_POWER_STATE=m
CONFIG_MSM_QBT_HANDLER=m
@@ -257,6 +260,7 @@ CONFIG_QCOM_WDT_CORE=m
CONFIG_QRTR=m
CONFIG_QRTR_GUNYAH=m
CONFIG_QRTR_MHI=m
# CONFIG_QRTR_MHI_DEV is not set
CONFIG_QRTR_SMD=m
# CONFIG_QRTR_TUN is not set
CONFIG_QSEECOM_PROXY=m
@@ -368,6 +372,7 @@ CONFIG_USB_M31_MSM_EUSB2_PHY=m
CONFIG_USB_MON=m
CONFIG_USB_MSM_EUSB2_PHY=m
CONFIG_USB_MSM_SSPHY_QMP=m
CONFIG_USB_NET_AX88179_178A=m
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_USB_QCOM_EMU_PHY=m
CONFIG_USB_REDRIVER=m

View File

@@ -1,3 +1,4 @@
CONFIG_ADS7052_TDK_THERMISTOR=m
CONFIG_ARCH_KAKA=y
CONFIG_ARCH_KALAMA=y
CONFIG_ARCH_QCOM=y
@@ -7,6 +8,7 @@ CONFIG_ARM_SMMU=m
CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y
# CONFIG_ARM_SMMU_SELFTEST is not set
CONFIG_BLK_DEV_NVME=m
CONFIG_CAN_MCP25XXFD=m
CONFIG_CFG80211=m
# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
# CONFIG_CFG80211_CRDA_SUPPORT is not set
@@ -16,6 +18,8 @@ CONFIG_CFG80211=m
CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
# CONFIG_CFG80211_WEXT is not set
CONFIG_CH101=m
CONFIG_CH101_I2C=m
# CONFIG_CHARGER_QCOM_SMBB is not set
CONFIG_CHR_DEV_SG=m
CONFIG_COMMON_CLK_QCOM=m
@@ -31,10 +35,11 @@ CONFIG_CORESIGHT_TGU=m
CONFIG_CORESIGHT_TPDA=m
CONFIG_CORESIGHT_TPDM=m
CONFIG_CPU_IDLE_GOV_QCOM_LPM=m
CONFIG_DRM_LT9611UXC=m
# CONFIG_DRM_LT9611UXC is not set
CONFIG_EDAC_QCOM=m
# CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE is not set
CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
CONFIG_EP_PCIE=m
# CONFIG_EXT4_KUNIT_TESTS is not set
# CONFIG_FAT_KUNIT_TEST is not set
CONFIG_GH_ARM64_DRV=m
@@ -110,6 +115,8 @@ CONFIG_MSM_CORE_HANG_DETECT=m
CONFIG_MSM_GLOBAL_SYNX=m
CONFIG_MSM_GPI_DMA=m
# CONFIG_MSM_GPI_DMA_DEBUG is not set
CONFIG_MSM_MHI_DEV=m
CONFIG_MSM_MHI_NET_DEV=m
CONFIG_MSM_PERFORMANCE=m
CONFIG_MSM_POWER_STATE=m
CONFIG_MSM_QBT_HANDLER=m
@@ -253,6 +260,7 @@ CONFIG_QCOM_WDT_CORE=m
CONFIG_QRTR=m
CONFIG_QRTR_GUNYAH=m
CONFIG_QRTR_MHI=m
# CONFIG_QRTR_MHI_DEV is not set
CONFIG_QRTR_SMD=m
# CONFIG_QRTR_TUN is not set
CONFIG_QSEECOM_PROXY=m
@@ -364,6 +372,7 @@ CONFIG_USB_M31_MSM_EUSB2_PHY=m
CONFIG_USB_MON=m
CONFIG_USB_MSM_EUSB2_PHY=m
CONFIG_USB_MSM_SSPHY_QMP=m
CONFIG_USB_NET_AX88179_178A=m
# CONFIG_USB_NET_RNDIS_WLAN is not set
CONFIG_USB_QCOM_EMU_PHY=m
CONFIG_USB_REDRIVER=m

View File

@@ -15,12 +15,15 @@ CONFIG_MSM_GPI_DMA_DEBUG=y
# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set
CONFIG_QCOM_RTB=m
CONFIG_QCOM_RTB_SEPARATE_CPUS=y
CONFIG_QRC=m
CONFIG_QRC_DEBUG=m
CONFIG_QTI_PMIC_GLINK_CLIENT_DEBUG=y
CONFIG_RCU_TORTURE_TEST=m
CONFIG_REGMAP_QTI_DEBUGFS_ALLOW_WRITE=y
CONFIG_RPMSG_QCOM_GLINK_DEBUG=y
CONFIG_RUNTIME_TESTING_MENU=y
CONFIG_SCHED_WALT_DEBUG=m
CONFIG_SENSORS_PWM_FAN=m
CONFIG_SPI_SPIDEV=m
CONFIG_TEST_USER_COPY=m
CONFIG_UFS_DBG=y

View File

@@ -32,6 +32,9 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=m
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_IDLE_GOV_QCOM_LPM=m
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_EDAC_KRYO_ARM64=m
# CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set
CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y
CONFIG_EXTCON_USB_GPIO=m
CONFIG_HWSPINLOCK_QCOM=m
CONFIG_HW_RANDOM_MSM_LEGACY=m
@@ -111,7 +114,7 @@ CONFIG_QCOM_DMABUF_HEAPS_CMA=y
CONFIG_QCOM_DMABUF_HEAPS_PAGE_POOL_REFILL=y
CONFIG_QCOM_DMABUF_HEAPS_SYSTEM=y
CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_SECURE=y
# CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED is not set
CONFIG_QCOM_DMABUF_HEAPS_SYSTEM_UNCACHED=y
# CONFIG_QCOM_DYN_MINIDUMP_STACK is not set
CONFIG_QCOM_EUD=m
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y

View File

@@ -103,9 +103,6 @@
#define M_KERNEL_PERF_LIST (PERF_KEY_MAX)
#define M_DSP_PERF_LIST (12)
#define SESSION_ID_INDEX (30)
#define SESSION_ID_MASK (1 << SESSION_ID_INDEX)
#define PROCESS_ID_MASK ((2^SESSION_ID_INDEX) - 1)
#define FASTRPC_CTX_MAGIC (0xbeeddeed)
/* Process status notifications from DSP will be sent with this unique context */
@@ -198,6 +195,9 @@
/* Max no. of persistent headers pre-allocated per process */
#define MAX_PERSISTENT_HEADERS (25)
/* Max value of the unique fastrpc tgid */
#define MAX_FRPC_TGID 256
#define PERF_CAPABILITY_SUPPORT (1 << 1)
#define KERNEL_ERROR_CODE_V1_SUPPORT 1
#define USERSPACE_ALLOCATION_SUPPORT 1
@@ -215,9 +215,18 @@
#define FASTRPC_USER_PD_FORCE_KILL 2
/*
* No of pages shared with DSP during process init with
* First page for init-mem and second page for proc-attrs
*/
#define PAGESLEN_WITH_SHAREDBUF 2
/* Unique index flag used for mini dump */
static int md_unique_index_flag[MAX_UNIQUE_ID] = { 0, 0, 0, 0, 0 };
/* Array to keep track unique tgid_frpc usage */
static bool frpc_tgid_usage_array[MAX_FRPC_TGID] = {0};
/* Fastrpc remote process attributes */
enum fastrpc_proc_attr {
/* Macro for Debug attr */
@@ -1102,8 +1111,8 @@ bail:
kfree(map);
}
static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure,
int sharedcb, struct fastrpc_session_ctx **session);
static int fastrpc_session_alloc_secure_memory(struct fastrpc_channel_ctx *chan, int secure,
int sharedcb, int pd_type, struct fastrpc_session_ctx **session);
static inline bool fastrpc_get_persistent_map(size_t len, struct fastrpc_mmap **pers_map)
{
@@ -1293,11 +1302,11 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, struct dma_buf *
map->secure = (mem_buf_dma_buf_exclusive_owner(map->buf)) ? 0 : 1;
if (map->secure) {
if (!fl->secsctx)
err = fastrpc_session_alloc(chan, 1, 0,
&fl->secsctx);
err = fastrpc_session_alloc_secure_memory(chan, 1, 0,
fl->pd_type, &fl->secsctx);
if (err) {
ADSPRPC_ERR(
"fastrpc_session_alloc failed for fd %d ret %d\n",
"fastrpc_session_alloc_secure_memory failed for fd %d ret %d\n",
fd, err);
err = -ENOSR;
goto bail;
@@ -1866,6 +1875,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
}
ctx->retval = -1;
ctx->pid = current->pid;
/* Store HLOS PID in context, it is not being sent to DSP */
ctx->tgid = fl->tgid;
init_completion(&ctx->work);
ctx->magic = FASTRPC_CTX_MAGIC;
@@ -1883,6 +1893,10 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel,
goto bail;
}
memset(ctx->perf, 0, sizeof(*(ctx->perf)));
/*
* Use HLOS PID, as perf tid is not being sent
* to DSP and is used to log in traces.
*/
ctx->perf->tid = fl->tgid;
}
if (invokefd->job) {
@@ -2060,13 +2074,11 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
struct fastrpc_file *fl = NULL;
struct hlist_node *n;
bool is_process_found = false;
int sessionid = 0;
unsigned long irq_flags = 0;
spin_lock_irqsave(&me->hlock, irq_flags);
hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
if (fl->tgid == notif->pid ||
(fl->tgid == (notif->pid & PROCESS_ID_MASK))) {
if (fl->tgid_frpc == notif->pid) {
is_process_found = true;
break;
}
@@ -2075,9 +2087,7 @@ static void fastrpc_notif_find_process(int domain, struct smq_notif_rspv3 *notif
if (!is_process_found)
return;
if (notif->pid & SESSION_ID_MASK)
sessionid = 1;
fastrpc_queue_pd_status(fl, domain, notif->status, sessionid);
fastrpc_queue_pd_status(fl, domain, notif->status, fl->sessionid);
}
static void context_notify_user(struct smq_invoke_ctx *ctx,
@@ -2909,10 +2919,9 @@ static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
channel_ctx = &fl->apps->channel[cid];
mutex_lock(&channel_ctx->smd_mutex);
msg->pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
msg->pid = fl->tgid_frpc;
msg->tid = current->pid;
if (fl->sessionid)
msg->tid |= SESSION_ID_MASK;
if (kernel == KERNEL_MSG_WITH_ZERO_PID)
msg->pid = 0;
msg->invoke.header.ctx = ctx->ctxid | fl->pd;
@@ -2996,6 +3005,7 @@ static void fastrpc_init(struct fastrpc_apps *me)
spin_lock_init(&me->hlock);
me->channel = &gcinfo[0];
mutex_init(&me->mut_uid);
me->max_sess_per_proc = DEFAULT_MAX_SESS_PER_PROC;
for (i = 0; i < NUM_CHANNELS; i++) {
init_completion(&me->channel[i].work);
init_completion(&me->channel[i].workport);
@@ -3555,6 +3565,70 @@ bail:
return err;
}
static int fastrpc_set_session_info(
struct fastrpc_proc_sess_info *sess_info,
void *param, struct fastrpc_file *fl)
{
int err = 0;
struct fastrpc_apps *me = &gfa;
if (fl->set_session_info) {
ADSPRPC_ERR("Set session info invoked multiple times\n");
err = -EBADR;
goto bail;
}
/*
* Third-party apps don't have permission to open the fastrpc device, so
* it is opened on their behalf by DSP HAL. This is detected by
* comparing current PID with the one stored during device open.
*/
if (current->tgid != fl->tgid_open)
fl->untrusted_process = true;
VERIFY(err, sess_info->pd_type > DEFAULT_UNUSED &&
sess_info->pd_type < MAX_PD_TYPE);
if (err) {
ADSPRPC_ERR(
"Session PD type %u is invalid for the process\n",
sess_info->pd_type);
err = -EBADR;
goto bail;
}
if (fl->untrusted_process && sess_info->pd_type != USERPD) {
ADSPRPC_ERR(
"Session PD type %u not allowed for untrusted process\n",
sess_info->pd_type);
err = -EBADR;
goto bail;
}
/*
* If PD type is not configured for context banks,
* ignore PD type passed by the user, leave pd_type set to DEFAULT_UNUSED(0)
*/
if (me->cb_pd_type)
fl->pd_type = sess_info->pd_type;
// Processes attaching to Sensor Static PD, share context bank.
if (sess_info->pd_type == SENSORS_STATICPD)
fl->sharedcb = 1;
if (sess_info->session_id >= me->max_sess_per_proc) {
ADSPRPC_ERR(
"Session ID %u cannot be beyond %u\n",
sess_info->session_id, me->max_sess_per_proc);
err = -EBADR;
goto bail;
}
fl->sessionid = sess_info->session_id;
// Set multi_session_support, to disable old way of setting session_id
fl->multi_session_support = true;
VERIFY(err, 0 == (err = fastrpc_get_info(fl, &(sess_info->domain_id))));
if (err)
goto bail;
K_COPY_TO_USER(err, 0, param, sess_info,
sizeof(struct fastrpc_proc_sess_info));
bail:
return err;
}
static int fastrpc_create_persistent_headers(struct fastrpc_file *fl,
uint32_t user_concurrency)
{
@@ -3636,6 +3710,8 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
struct fastrpc_ioctl_async_response async_res;
uint32_t user_concurrency;
struct fastrpc_ioctl_notif_rsp notif;
struct fastrpc_proc_sharedbuf_info buff_info;
struct fastrpc_proc_sess_info sess_info;
} p;
struct fastrpc_dsp_capabilities *dsp_cap_ptr = NULL;
uint32_t size = 0;
@@ -3714,6 +3790,35 @@ int fastrpc_internal_invoke2(struct fastrpc_file *fl,
err = fastrpc_get_notif_response(&p.notif,
(void *)inv2->invparam, fl);
break;
case FASTRPC_INVOKE2_PROC_SHAREDBUF_INFO:
VERIFY(err,
sizeof(struct fastrpc_proc_sharedbuf_info) >= inv2->size);
if (err) {
err = -EBADE;
goto bail;
}
K_COPY_FROM_USER(err, fl->is_compat, &p.buff_info,
(void *)inv2->invparam, inv2->size);
if (err)
goto bail;
fl->sharedbuf_info.buf_fd = p.buff_info.buf_fd;
fl->sharedbuf_info.buf_size = p.buff_info.buf_size;
break;
case FASTRPC_INVOKE2_SESS_INFO:
VERIFY(err,
sizeof(struct fastrpc_proc_sess_info) >= inv2->size);
if (err) {
err = -EBADE;
goto bail;
}
K_COPY_FROM_USER(err, fl->is_compat, &p.sess_info,
(void *)inv2->invparam, inv2->size);
if (err)
goto bail;
err = fastrpc_set_session_info(&p.sess_info,
(void *)inv2->invparam, fl);
break;
default:
err = -ENOTTY;
break;
@@ -3764,7 +3869,7 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl, int locked);
static int fastrpc_init_attach_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init *init)
{
int err = 0, tgid = fl->tgid;
int err = 0, tgid = fl->tgid_frpc;
remote_arg_t ra[1];
struct fastrpc_ioctl_invoke_async ioctl;
@@ -3777,6 +3882,7 @@ static int fastrpc_init_attach_process(struct fastrpc_file *fl,
/*
* Prepare remote arguments for creating thread group
* in guestOS/staticPD on the remote subsystem.
* Send unique fastrpc id to dsp
*/
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
@@ -3814,7 +3920,8 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
int err = 0, memlen = 0, mflags = 0, locked = 0;
struct fastrpc_ioctl_invoke_async ioctl;
struct fastrpc_ioctl_init *init = &uproc->init;
struct smq_phy_page pages[1];
/* First page for init-mem and second page for proc-attrs */
struct smq_phy_page pages[PAGESLEN_WITH_SHAREDBUF];
struct fastrpc_mmap *file = NULL;
struct fastrpc_buf *imem = NULL;
unsigned long imem_dma_attr = 0;
@@ -3823,6 +3930,7 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
unsigned int gid = 0, one_mb = 1024*1024;
unsigned int dsp_userpd_memlen = 3 * one_mb;
struct fastrpc_buf *init_mem;
struct fastrpc_mmap *sharedbuf_map = NULL;
struct {
int pgid;
@@ -3843,7 +3951,7 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
fl->dsp_process_state = PROCESS_CREATE_IS_INPROGRESS;
spin_unlock(&fl->hlock);
inbuf.pgid = fl->tgid;
inbuf.pgid = fl->tgid_frpc;
inbuf.namelen = strlen(current->comm) + 1;
inbuf.filelen = init->filelen;
fl->pd = 1;
@@ -3934,11 +4042,23 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
goto bail;
fl->init_mem = imem;
inbuf.pageslen = 1;
if ((fl->sharedbuf_info.buf_fd != -1) && fl->sharedbuf_info.buf_size) {
mutex_lock(&fl->map_mutex);
err = fastrpc_mmap_create(fl, fl->sharedbuf_info.buf_fd, NULL, 0,
0, fl->sharedbuf_info.buf_size, mflags, &sharedbuf_map);
mutex_unlock(&fl->map_mutex);
if (err)
goto bail;
/* if shared buff is available send this as the second page and set pageslen as 2 */
inbuf.pageslen = PAGESLEN_WITH_SHAREDBUF;
}
/*
* Prepare remote arguments for dynamic process create
* call to remote subsystem.
*/
inbuf.pageslen = 1;
ra[0].buf.pv = (void *)&inbuf;
ra[0].buf.len = sizeof(inbuf);
fds[0] = -1;
@@ -3953,8 +4073,14 @@ static int fastrpc_init_create_dynamic_process(struct fastrpc_file *fl,
pages[0].addr = imem->phys;
pages[0].size = imem->size;
/* Update IOVA of second page shared with DSP */
if (inbuf.pageslen > 1) {
pages[1].addr = sharedbuf_map->phys;
pages[1].size = sharedbuf_map->size;
}
ra[3].buf.pv = (void *)pages;
ra[3].buf.len = 1 * sizeof(*pages);
ra[3].buf.len = (inbuf.pageslen) * sizeof(*pages);
fds[3] = -1;
inbuf.attrs = uproc->attrs;
@@ -4069,7 +4195,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_file *fl,
}
fl->pd = 1;
inbuf.pgid = fl->tgid;
inbuf.pgid = fl->tgid_frpc;
inbuf.namelen = init->filelen;
inbuf.pageslen = 0;
@@ -4222,38 +4348,6 @@ bail:
kfree(proc_name);
}
/*
* Function to restrict duplicate session creation with same tgid, cid.
* check introduced after extended session creation
* to avoid breaking in case of extended sessions.
*/
static bool fastrpc_session_exists(struct fastrpc_apps *me, uint32_t cid, int tgid)
{
struct fastrpc_file *fl;
struct hlist_node *n;
bool session_found = false;
unsigned long irq_flags = 0;
int total_session_count = 0;
spin_lock_irqsave(&me->hlock, irq_flags);
hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
if (fl->tgid == tgid && fl->cid == cid) {
++total_session_count;
if (total_session_count > 1) {
session_found = true;
break;
}
}
}
spin_unlock_irqrestore(&me->hlock, irq_flags);
if (session_found)
ADSPRPC_ERR(
"trying to open a session that already exists for tgid %d, channel ID %u\n",
tgid, cid);
return session_found;
}
int fastrpc_init_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init_attrs *uproc)
@@ -4279,11 +4373,6 @@ int fastrpc_init_process(struct fastrpc_file *fl,
err = -ECHRNG;
goto bail;
}
VERIFY(err, !fastrpc_session_exists(me, fl->cid, fl->tgid));
if (err) {
err = -EEXIST;
goto bail;
}
chan = &me->channel[cid];
if (chan->unsigned_support && fl->dev_minor == MINOR_NUM_DEV) {
/* Make sure third party applications */
@@ -4523,7 +4612,8 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl)
err = -ECONNRESET;
goto bail;
}
tgid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
tgid = fl->tgid_frpc;
ra[0].buf.pv = (void *)&tgid;
ra[0].buf.len = sizeof(tgid);
ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP;
@@ -4582,7 +4672,8 @@ static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset,
uint64_t vaddrout;
} routargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.fd = fd;
inargs.offset = offset;
inargs.vaddrin = (uintptr_t)va;
@@ -4633,7 +4724,8 @@ static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd,
uint64_t len;
} inargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.fd = fd;
inargs.vaddrin = (uint64_t)va;
inargs.len = (uint64_t)size;
@@ -4669,7 +4761,8 @@ static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl,
size_t size;
} inargs;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.size = size;
inargs.vaddrout = raddr;
ra[0].buf.pv = (void *)&inargs;
@@ -4721,7 +4814,8 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags,
goto bail;
}
cid = fl->cid;
inargs.pid = fl->tgid;
/* Send unique fastrpc process ID to dsp */
inargs.pid = fl->tgid_frpc;
inargs.vaddrin = (uintptr_t)va;
inargs.flags = flags;
inargs.num = fl->apps->compat ? num * sizeof(page) : num;
@@ -5431,17 +5525,23 @@ int fastrpc_internal_mmap(struct fastrpc_file *fl,
static void fastrpc_context_list_dtor(struct fastrpc_file *fl);
static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
int secure, int sharedcb, struct fastrpc_session_ctx **session)
int secure, int sharedcb, int pd_type, struct fastrpc_session_ctx **session)
{
struct fastrpc_apps *me = &gfa;
uint64_t idx = 0;
int err = 0;
/*
* PD type can be either unused(DEFAULT_UNUSED) (or) if PD type
* is used, choose the context bank with matching PD type.
*/
if (chan->sesscount) {
for (idx = 0; idx < chan->sesscount; ++idx) {
if (!chan->session[idx].used &&
chan->session[idx].smmu.secure == secure &&
chan->session[idx].smmu.sharedcb == sharedcb) {
chan->session[idx].smmu.sharedcb == sharedcb &&
(pd_type == DEFAULT_UNUSED ||
chan->session[idx].smmu.pd_type == pd_type)) {
chan->session[idx].used = 1;
break;
}
@@ -5493,7 +5593,11 @@ static void handle_remote_signal(uint64_t msg, int cid)
spin_lock_irqsave(&me->hlock, irq_flags);
hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
if ((fl->tgid == pid) && (fl->cid == cid)) {
/*
* Response from DSP contains unique fastrpc process id,
* use unique fastrpc process ID to compare.
*/
if ((fl->tgid_frpc == pid) && (fl->cid == cid)) {
unsigned long fflags = 0;
spin_lock_irqsave(&fl->dspsignals_lock, fflags);
@@ -5632,14 +5736,22 @@ bail:
return err;
}
static int fastrpc_session_alloc(struct fastrpc_channel_ctx *chan, int secure,
int sharedcb, struct fastrpc_session_ctx **session)
static int fastrpc_session_alloc_secure_memory(struct fastrpc_channel_ctx *chan, int secure,
int sharedcb, int pd_type, struct fastrpc_session_ctx **session)
{
int err = 0;
struct fastrpc_apps *me = &gfa;
/*
* If PD type is configured for context banks,
* Use CPZ_USERPD, to allocate secure context bank type.
*/
if (pd_type != DEFAULT_UNUSED && me->cb_pd_type)
pd_type = CPZ_USERPD;
mutex_lock(&chan->smd_mutex);
if (!*session)
err = fastrpc_session_alloc_locked(chan, secure, sharedcb, session);
err = fastrpc_session_alloc_locked(chan, secure, sharedcb, pd_type, session);
mutex_unlock(&chan->smd_mutex);
if (err == -EUSERS) {
ADSPRPC_WARN(
@@ -5706,6 +5818,9 @@ skip_dump_wait:
fl->is_ramdump_pend = false;
fl->is_dma_invoke_pend = false;
fl->dsp_process_state = PROCESS_CREATE_DEFAULT;
/* Reset the tgid usage to false */
if (fl->tgid_frpc != -1)
frpc_tgid_usage_array[fl->tgid_frpc] = false;
is_locked = false;
spin_unlock_irqrestore(&fl->apps->hlock, irq_flags);
@@ -6150,9 +6265,12 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
INIT_HLIST_NODE(&fl->hn);
fl->sessionid = 0;
fl->tgid_open = current->tgid;
/* PD type is not known, when device is opened */
fl->pd_type = DEFAULT_UNUSED;
fl->apps = me;
fl->mode = FASTRPC_MODE_SERIAL;
fl->cid = -1;
fl->tgid_frpc = -1;
fl->dev_minor = dev_minor;
fl->init_mem = NULL;
fl->qos_request = 0;
@@ -6163,10 +6281,13 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
fl->is_compat = false;
fl->exit_notif = false;
fl->exit_async = false;
fl->multi_session_support = false;
fl->set_session_info = false;
init_completion(&fl->work);
init_completion(&fl->dma_invoke);
fl->file_close = FASTRPC_PROCESS_DEFAULT_STATE;
filp->private_data = fl;
fl->sharedbuf_info.buf_fd = -1;
mutex_init(&fl->internal_map_mutex);
mutex_init(&fl->map_mutex);
spin_lock_irqsave(&me->hlock, irq_flags);
@@ -6210,6 +6331,25 @@ bail:
return err;
}
// Generate a unique process ID to DSP process
static int get_unique_hlos_process_id(void)
{
int tgid_frpc = -1, tgid_index = 1;
struct fastrpc_apps *me = &gfa;
spin_lock(&me->hlock);
for (tgid_index = 1; tgid_index < MAX_FRPC_TGID; tgid_index++) {
if (!frpc_tgid_usage_array[tgid_index]) {
tgid_frpc = tgid_index;
/* Set the tgid usage to false */
frpc_tgid_usage_array[tgid_index] = true;
break;
}
}
spin_unlock(&me->hlock);
return tgid_frpc;
}
static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
{
int err = 0, buf_size = 0;
@@ -6219,6 +6359,13 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
memcpy(cur_comm, current->comm, TASK_COMM_LEN);
cur_comm[TASK_COMM_LEN-1] = '\0';
fl->tgid = current->tgid;
fl->tgid_frpc = get_unique_hlos_process_id();
VERIFY(err, fl->tgid_frpc != -1);
if (err) {
ADSPRPC_ERR("too many fastrpc clients, max %u allowed\n", MAX_FRPC_TGID);
err = -EUSERS;
goto bail;
}
/*
* Third-party apps don't have permission to open the fastrpc device, so
@@ -6251,8 +6398,12 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl, uint32_t cid)
err = -ENOMEM;
return err;
}
snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d",
cur_comm, "_", current->pid, "_", cid);
/*
* Use HLOS PID, unique fastrpc PID, CID in debugfs filename,
* for better ability to debug.
*/
snprintf(fl->debug_buf, buf_size, "%.10s%s%d%s%d%s%d",
cur_comm, "_", current->pid, "_", fl->tgid_frpc, "_", cid);
fl->debugfs_file = debugfs_create_file(fl->debug_buf, 0644,
debugfs_root, fl, &debugfs_fops);
if (IS_ERR_OR_NULL(fl->debugfs_file)) {
@@ -6278,6 +6429,21 @@ int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
err = -EBADF;
goto bail;
}
spin_lock(&fl->hlock);
if (fl->set_session_info) {
spin_unlock(&fl->hlock);
ADSPRPC_ERR("Set session info invoked multiple times\n");
err = -EBADR;
goto bail;
}
// Set set_session_info to true
fl->set_session_info = true;
spin_unlock(&fl->hlock);
VERIFY(err, VALID_FASTRPC_CID(cid));
if (err) {
err = -ECHRNG;
goto bail;
}
fastrpc_get_process_gids(&fl->gidlist);
err = fastrpc_set_process_info(fl, cid);
@@ -6315,7 +6481,7 @@ int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
fl->ssrcount = fl->apps->channel[cid].ssrcount;
mutex_lock(&fl->apps->channel[cid].smd_mutex);
err = fastrpc_session_alloc_locked(&fl->apps->channel[cid],
0, fl->sharedcb, &fl->sctx);
0, fl->sharedcb, fl->pd_type, &fl->sctx);
mutex_unlock(&fl->apps->channel[cid].smd_mutex);
if (err == -EUSERS) {
ADSPRPC_WARN(
@@ -6372,7 +6538,6 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
int err = 0;
unsigned int latency;
struct fastrpc_apps *me = &gfa;
int sessionid = 0;
unsigned int cpu;
unsigned long flags = 0;
@@ -6468,9 +6633,7 @@ int fastrpc_internal_control(struct fastrpc_file *fl,
break;
case FASTRPC_CONTROL_DSPPROCESS_CLEAN:
(void)fastrpc_release_current_dsp_process(fl);
if (fl->tgid & SESSION_ID_MASK)
sessionid = 1;
fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, sessionid);
fastrpc_queue_pd_status(fl, fl->cid, FASTRPC_USER_PD_FORCE_KILL, fl->sessionid);
break;
case FASTRPC_CONTROL_RPC_POLL:
err = fastrpc_manage_poll_mode(fl, cp->lp.enable, cp->lp.latency);
@@ -6547,8 +6710,8 @@ int fastrpc_setmode(unsigned long ioctl_param,
"multiple sessions not allowed for untrusted apps\n");
goto bail;
}
fl->sessionid = 1;
fl->tgid |= SESSION_ID_MASK;
if (!fl->multi_session_support)
fl->sessionid = 1;
break;
default:
err = -ENOTTY;
@@ -6619,8 +6782,9 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
// track outgoing signals in the driver. The userspace library does a
// basic sanity check and any security validation needs to be done by
// the recipient.
DSPSIGNAL_VERBOSE("Send signal PID %u, signal %u\n",
(unsigned int)fl->tgid, (unsigned int)sig->signal_id);
DSPSIGNAL_VERBOSE("Send signal PID %u, unique fastrpc pid %u signal %u\n",
(unsigned int)fl->tgid, (unsigned int)fl->tgid_frpc,
(unsigned int)sig->signal_id);
VERIFY(err, sig->signal_id < DSPSIGNAL_NUM_SIGNALS);
if (err) {
ADSPRPC_ERR("Sending bad signal %u for PID %u",
@@ -6644,7 +6808,8 @@ int fastrpc_dspsignal_signal(struct fastrpc_file *fl,
goto bail;
}
msg = (((uint64_t)fl->tgid) << 32) | ((uint64_t)sig->signal_id);
/* Use unique fastrpc pid, to signal DSP process */
msg = (((uint64_t)fl->tgid_frpc) << 32) | ((uint64_t)sig->signal_id);
err = fastrpc_transport_send(cid, (void *)&msg, sizeof(msg), fl->trusted_vm);
mutex_unlock(&channel_ctx->smd_mutex);
@@ -7724,6 +7889,14 @@ static int fastrpc_cb_probe(struct device *dev)
me->max_size_limit = (dma_addr_pool[1] == 0 ? 0x78000000 :
dma_addr_pool[1]);
if (of_get_property(dev->of_node, "pd-type", NULL) != NULL) {
err = of_property_read_u32(dev->of_node, "pd-type",
&(sess->smmu.pd_type));
/* Set cb_pd_type, if the process type is set for context banks */
me->cb_pd_type = true;
if (err)
goto bail;
}
if (of_get_property(dev->of_node, "shared-cb", NULL) != NULL) {
sess->smmu.sharedcb = 1;
err = of_property_read_u32(dev->of_node, "shared-cb",
@@ -8056,6 +8229,8 @@ static int fastrpc_probe(struct platform_device *pdev)
me->lowest_capacity_core_count = 1;
of_property_read_u32(dev->of_node, "qcom,rpc-latency-us",
&me->latency);
of_property_read_u32(dev->of_node, "qcom,max-sessions",
&me->max_sess_per_proc);
if (of_get_property(dev->of_node,
"qcom,secure-domains", NULL) != NULL) {
VERIFY(err, !of_property_read_u32(dev->of_node,
@@ -8472,17 +8647,24 @@ static int fastrpc_device_create(struct fastrpc_file *fl)
frpc_dev->dev.parent = &fastrpc_bus;
frpc_dev->dev.bus = &fastrpc_bus_type;
dev_set_name(&frpc_dev->dev, "%s-%d-%d",
dev_name(frpc_dev->dev.parent), fl->tgid, fl->cid);
/*
* Use HLOS PID, unique fastrpc process ID and CID to create device file,
* Else names would conflict for multiple sessions
* And also for better ability to debug
*/
dev_set_name(&frpc_dev->dev, "%s-%d-%d-%d",
dev_name(frpc_dev->dev.parent), fl->tgid, fl->tgid_frpc, fl->cid);
frpc_dev->dev.release = fastrpc_dev_release;
frpc_dev->fl = fl;
frpc_dev->handle = fl->tgid;
/* Use unique fastrpc tgid as handle */
frpc_dev->handle = fl->tgid_frpc;
err = device_register(&frpc_dev->dev);
if (err) {
put_device(&frpc_dev->dev);
ADSPRPC_ERR("fastrpc device register failed for process %d with error %d\n",
fl->tgid, err);
ADSPRPC_ERR(
"fastrpc device register failed for process %d unique fastrpc tgid %d session %d with error %d\n",
fl->tgid, fl->tgid_frpc, fl->sessionid, err);
goto bail;
}
fl->device = frpc_dev;

View File

@@ -120,6 +120,9 @@
#define NUM_CHANNELS (MAX_DOMAIN_ID + 1) /* adsp, mdsp, slpi, cdsp, cdsp1, gpdsp, gpdsp1*/
#define NUM_SESSIONS 13 /* max 12 compute, 1 cpz */
/* Default maximum sessions allowed per process */
#define DEFAULT_MAX_SESS_PER_PROC 4
#define RH_CID ADSP_DOMAIN_ID
#define VALID_FASTRPC_CID(cid) \
@@ -213,6 +216,15 @@ struct remote_buf {
size_t len; /* length of buffer */
};
/* structure to hold fd and size of buffer shared with DSP,
* which contains initial debug parameters that needs to be passed
* during process initialization.
*/
struct fastrpc_proc_sharedbuf_info {
int buf_fd;
int buf_size;
};
struct remote_dma_handle {
int fd;
uint32_t offset;
@@ -296,6 +308,14 @@ struct fastrpc_ioctl_notif_rsp {
uint32_t status; /* Status of the process */
};
/* FastRPC ioctl structure to set session related info */
struct fastrpc_proc_sess_info {
uint32_t domain_id; /* Set the remote subsystem, Domain ID of the session */
uint32_t session_id; /* Unused, Set the Session ID on remote subsystem */
uint32_t pd_type; /* Set the process type on remote subsystem */
uint32_t sharedcb; /* Unused, Session can share context bank with other sessions */
};
/* INIT a new process or attach to guestos */
enum fastrpc_init_flags {
FASTRPC_INIT_NO_CREATE = -1,
@@ -310,6 +330,9 @@ enum fastrpc_invoke2_type {
FASTRPC_INVOKE2_ASYNC_RESPONSE = 2,
FASTRPC_INVOKE2_KERNEL_OPTIMIZATIONS,
FASTRPC_INVOKE2_STATUS_NOTIF,
FASTRPC_INVOKE2_PROC_SHAREDBUF_INFO,
/* Set session info of remote sub system */
FASTRPC_INVOKE2_SESS_INFO,
};
struct fastrpc_ioctl_invoke2 {
@@ -710,6 +733,21 @@ struct gid_list {
unsigned int gidcount;
};
/*
* Process types on remote subsystem
* Always add new PD types at the end, before MAX_PD_TYPE
*/
#define DEFAULT_UNUSED 0 /* pd type not configured for context banks */
#define ROOT_PD 1 /* Root PD */
#define AUDIO_STATICPD 2 /* ADSP Audio Static PD */
#define SENSORS_STATICPD 3 /* ADSP Sensors Static PD */
#define SECURE_STATICPD 4 /* CDSP Secure Static PD */
#define OIS_STATICPD 5 /* ADSP OIS Static PD */
#define CPZ_USERPD 6 /* CDSP CPZ USER PD */
#define USERPD 7 /* DSP User Dynamic PD */
#define GUEST_OS_SHARED 8 /* Legacy Guest OS Shared */
#define MAX_PD_TYPE 9 /* Max PD type */
struct fastrpc_file;
struct fastrpc_buf {
@@ -850,6 +888,8 @@ struct fastrpc_smmu {
int secure;
int coherent;
int sharedcb;
/* Process type on remote sub system */
int pd_type;
/* gen pool for QRTR */
struct gen_pool *frpc_genpool;
/* fastrpc gen pool buffer */
@@ -956,6 +996,10 @@ struct fastrpc_apps {
unsigned int lowest_capacity_core_count;
/* Flag to check if PM QoS vote needs to be done for only one core */
bool single_core_latency_vote;
/* Indicates process type is configured for SMMU context bank */
bool cb_pd_type;
/* Maximum sessions allowed to be created per process */
uint32_t max_sess_per_proc;
};
struct fastrpc_mmap {
@@ -1056,6 +1100,8 @@ struct fastrpc_file {
int sessionid;
int tgid_open; /* Process ID during device open */
int tgid; /* Process ID that uses device for RPC calls */
/* Unique HLOS process ID created by fastrpc for each client */
int tgid_frpc;
int cid;
bool trusted_vm;
uint64_t ssrcount;
@@ -1064,6 +1110,8 @@ struct fastrpc_file {
int file_close;
int dsp_proc_init;
int sharedcb;
/* Process type on remote sub system */
int pd_type;
struct fastrpc_apps *apps;
struct dentry *debugfs_file;
struct dev_pm_qos_request *dev_pm_qos_req;
@@ -1119,6 +1167,16 @@ struct fastrpc_file {
bool exit_notif;
/* Flag to indicate async thread exit requested*/
bool exit_async;
/*
* structure to hold fd and size of buffer shared with DSP,
* which contains initial debug configurations and other initial
* config parameters.
*/
struct fastrpc_proc_sharedbuf_info sharedbuf_info;
/* Flag to indicate 4 session support available */
bool multi_session_support;
/* Flag to indicate session info is set */
bool set_session_info;
};
union fastrpc_ioctl_param {

View File

@@ -460,13 +460,6 @@ config SC_VIDEOCC_7280
Say Y if you want to support video devices and functionality such as
video encode and decode.
config SDM_CAMCC_845
tristate "SDM845 Camera Clock Controller"
select SDM_GCC_845
help
Support for the camera clock controller on SDM845 devices.
Say Y if you want to support camera devices and camera functionality.
config SDM_GCC_660
tristate "SDM660 Global Clock Controller"
select QCOM_GDSC
@@ -507,9 +500,18 @@ config QCS_Q6SSTOP_404
Say Y if you want to use the Q6SSTOP branch clocks of the WCSS clock
controller to reset the Q6SSTOP subsystem.
config SDM_CAMCC_845
tristate "SDM845 Camera Clock Controller"
select SDM_GCC_845
help
Support for the camera clock controller on Qualcomm Technologies, Inc
SDM845 devices.
Say Y if you want to support camera devices and functionality such as
capturing pictures.
config SDM_GCC_845
tristate "SDM845 Global Clock Controller"
select QCOM_GDSC
depends on COMMON_CLK_QCOM
help
Support for the global clock controller on SDM845 devices.
Say Y if you want to use peripheral devices such as UART, SPI,

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,42 @@ static struct measure_clk_data debug_mux_priv = {
.xo_div4_cbcr = 0x28008,
};
static const char *const cpu_cc_debug_mux_parent_names[] = {
"pwrcl_clk",
"perfcl_clk",
};
static int apss_cc_debug_mux_pre_divs[] = {
0x8, /* pwrcl_clk */
0x8, /* perfcl_clk */
};
static int cpu_cc_debug_mux_sels[] = {
0x0, /* pwrcl_clk */
0x1, /* perfcl_clk */
};
static struct clk_debug_mux cpu_cc_debug_mux = {
.priv = &debug_mux_priv,
.debug_offset = 0x0,
.post_div_offset = 0x0,
.cbcr_offset = U32_MAX,
.src_sel_mask = 0x3FF,
.src_sel_shift = 8,
.post_div_mask = 0xF,
.post_div_shift = 28,
.post_div_val = 1,
.pre_div_vals = apss_cc_debug_mux_pre_divs,
.mux_sels = cpu_cc_debug_mux_sels,
.num_mux_sels = ARRAY_SIZE(cpu_cc_debug_mux_sels),
.hw.init = &(const struct clk_init_data){
.name = "cpu_cc_debug_mux",
.ops = &clk_debug_mux_ops,
.parent_names = cpu_cc_debug_mux_parent_names,
.num_parents = ARRAY_SIZE(cpu_cc_debug_mux_parent_names),
},
};
static const char *const disp_cc_debug_mux_parent_names[] = {
"disp_cc_mdss_ahb_clk",
"disp_cc_mdss_byte0_clk",
@@ -235,6 +271,7 @@ static const char *const gcc_debug_mux_parent_names[] = {
"measure_only_ipa_2x_clk",
"measure_only_snoc_clk",
"video_cc_debug_mux",
"cpu_cc_debug_mux",
};
static int gcc_debug_mux_sels[] = {
@@ -389,6 +426,7 @@ static int gcc_debug_mux_sels[] = {
0xC2, /* measure_only_ipa_2x_clk */
0x7, /* measure_only_snoc_clk */
0x42, /* video_cc_debug_mux */
0xAB, /* cpu_cc_debug_mux */
};
static struct clk_debug_mux gcc_debug_mux = {
@@ -520,11 +558,28 @@ static struct clk_debug_mux mc_cc_debug_mux = {
static struct mux_regmap_names mux_list[] = {
{ .mux = &mc_cc_debug_mux, .regmap_name = "qcom,mccc" },
{ .mux = &video_cc_debug_mux, .regmap_name = "qcom,videocc" },
{ .mux = &cpu_cc_debug_mux, .regmap_name = "qcom,cpucc" },
{ .mux = &gpu_cc_debug_mux, .regmap_name = "qcom,gpucc" },
{ .mux = &disp_cc_debug_mux, .regmap_name = "qcom,dispcc" },
{ .mux = &gcc_debug_mux, .regmap_name = "qcom,gcc" },
};
static struct clk_dummy perfcl_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "perfcl_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy pwrcl_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
.name = "pwrcl_clk",
.ops = &clk_dummy_ops,
},
};
static struct clk_dummy measure_only_mccc_clk = {
.rrate = 1000,
.hw.init = &(struct clk_init_data){
@@ -562,6 +617,8 @@ static struct clk_hw *debugcc_trinket_hws[] = {
&measure_only_ipa_2x_clk.hw,
&measure_only_mccc_clk.hw,
&measure_only_snoc_clk.hw,
&perfcl_clk.hw,
&pwrcl_clk.hw,
};
static const struct of_device_id clk_debug_match_table[] = {
@@ -581,6 +638,8 @@ static int clk_debug_trinket_probe(struct platform_device *pdev)
ARRAY_SIZE(gpu_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(video_cc_debug_mux_parent_names) !=
ARRAY_SIZE(video_cc_debug_mux_sels));
BUILD_BUG_ON(ARRAY_SIZE(cpu_cc_debug_mux_parent_names) !=
ARRAY_SIZE(cpu_cc_debug_mux_sels));
clk = devm_clk_get(&pdev->dev, "xo_clk_src");
if (IS_ERR(clk)) {

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk.h>
@@ -19,6 +20,13 @@
#include "common.h"
#include "gdsc.h"
#include "reset.h"
#include "vdd-level-sdm845.h"
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner);
static struct clk_vdd_class *disp_cc_sdm845_regulators[] = {
&vdd_cx,
};
enum {
P_BI_TCXO,
@@ -33,18 +41,34 @@ enum {
P_DP_PHY_PLL_VCO_DIV_CLK,
};
static struct pll_vco fabia_vco[] = {
{ 249600000, 2000000000, 0 },
{ 125000000, 1000000000, 1 },
};
static struct clk_alpha_pll disp_cc_pll0 = {
.offset = 0x0,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
.vco_table = fabia_vco,
.num_vco = ARRAY_SIZE(fabia_vco),
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "disp_cc_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo", .name = "bi_tcxo",
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fabia_ops,
},
.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000 },
},
},
};
@@ -55,7 +79,7 @@ static const struct parent_map disp_cc_parent_map_0[] = {
};
static const struct clk_parent_data disp_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .fw_name = "dsi0_phy_pll_out_byteclk", .name = "dsi0_phy_pll_out_byteclk" },
{ .fw_name = "dsi1_phy_pll_out_byteclk", .name = "dsi1_phy_pll_out_byteclk" },
};
@@ -67,7 +91,7 @@ static const struct parent_map disp_cc_parent_map_1[] = {
};
static const struct clk_parent_data disp_cc_parent_data_1[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .fw_name = "dp_link_clk_divsel_ten", .name = "dp_link_clk_divsel_ten" },
{ .fw_name = "dp_vco_divided_clk_src_mux", .name = "dp_vco_divided_clk_src_mux" },
};
@@ -77,7 +101,7 @@ static const struct parent_map disp_cc_parent_map_2[] = {
};
static const struct clk_parent_data disp_cc_parent_data_2[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
};
static const struct parent_map disp_cc_parent_map_3[] = {
@@ -88,7 +112,7 @@ static const struct parent_map disp_cc_parent_map_3[] = {
};
static const struct clk_parent_data disp_cc_parent_data_3[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .hw = &disp_cc_pll0.clkr.hw },
{ .fw_name = "gcc_disp_gpll0_clk_src", .name = "gcc_disp_gpll0_clk_src" },
{ .fw_name = "gcc_disp_gpll0_div_clk_src", .name = "gcc_disp_gpll0_div_clk_src" },
@@ -101,7 +125,7 @@ static const struct parent_map disp_cc_parent_map_4[] = {
};
static const struct clk_parent_data disp_cc_parent_data_4[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .fw_name = "dsi0_phy_pll_out_dsiclk", .name = "dsi0_phy_pll_out_dsiclk" },
{ .fw_name = "dsi1_phy_pll_out_dsiclk", .name = "dsi1_phy_pll_out_dsiclk" },
};
@@ -119,6 +143,16 @@ static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 150000000,
[VDD_LOW] = 240000000,
[VDD_LOW_L1] = 262500000,
[VDD_NOMINAL] = 358000000 },
},
};
/* Return the HW recalc rate for idle use case */
@@ -134,6 +168,16 @@ static struct clk_rcg2 disp_cc_mdss_byte1_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 150000000,
[VDD_LOW] = 240000000,
[VDD_LOW_L1] = 262500000,
[VDD_NOMINAL] = 358000000 },
},
};
static const struct freq_tbl ftbl_disp_cc_mdss_dp_aux_clk_src[] = {
@@ -154,6 +198,12 @@ static struct clk_rcg2 disp_cc_mdss_dp_aux_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000 },
},
};
static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
@@ -165,8 +215,19 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
.name = "disp_cc_mdss_dp_crypto_clk_src",
.parent_data = disp_cc_parent_data_1,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 12800000,
[VDD_LOWER] = 108000000,
[VDD_LOW] = 180000000,
[VDD_LOW_L1] = 360000000,
[VDD_NOMINAL] = 540000000 },
},
};
static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
@@ -181,6 +242,16 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 162000000,
[VDD_LOW] = 270000000,
[VDD_LOW_L1] = 540000000,
[VDD_NOMINAL] = 810000000 },
},
};
static struct clk_rcg2 disp_cc_mdss_dp_pixel1_clk_src = {
@@ -195,6 +266,15 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel1_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_dp_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 202500000,
[VDD_LOW] = 296735000,
[VDD_LOW_L1] = 675000000 },
},
};
static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = {
@@ -209,6 +289,15 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_dp_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 202500000,
[VDD_LOW] = 296735000,
[VDD_LOW_L1] = 675000000 },
},
};
static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {
@@ -226,8 +315,15 @@ static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
.name = "disp_cc_mdss_esc0_clk_src",
.parent_data = disp_cc_parent_data_0,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000 },
},
};
static struct clk_rcg2 disp_cc_mdss_esc1_clk_src = {
@@ -242,15 +338,35 @@ static struct clk_rcg2 disp_cc_mdss_esc1_clk_src = {
.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000 },
},
};
static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(85714286, P_GPLL0_OUT_MAIN, 7, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
F(165000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
F(275000000, P_DISP_CC_PLL0_OUT_MAIN, 1.5, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(412500000, P_DISP_CC_PLL0_OUT_MAIN, 1, 0, 0),
{ }
};
static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src_sdm670[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(85714286, P_GPLL0_OUT_MAIN, 7, 0, 0),
F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
F(171428571, P_GPLL0_OUT_MAIN, 3.5, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
F(286666667, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(344000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
F(430000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
@@ -267,8 +383,18 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
.name = "disp_cc_mdss_mdp_clk_src",
.parent_data = disp_cc_parent_data_3,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 165000000,
[VDD_LOW] = 300000000,
[VDD_NOMINAL] = 412500000 },
},
};
/* Return the HW recalc rate for idle use case */
@@ -284,6 +410,16 @@ static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_pixel_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 184000000,
[VDD_LOW] = 295000000,
[VDD_LOW_L1] = 350000000,
[VDD_NOMINAL] = 571428571 },
},
};
/* Return the HW recalc rate for idle use case */
@@ -299,9 +435,27 @@ static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src = {
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_pixel_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 184000000,
[VDD_LOW] = 295000000,
[VDD_LOW_L1] = 350000000,
[VDD_NOMINAL] = 571428571 },
},
};
static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(165000000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
F(412500000, P_DISP_CC_PLL0_OUT_MAIN, 1, 0, 0),
{ }
};
static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src_sdm670[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(171428571, P_GPLL0_OUT_MAIN, 3.5, 0, 0),
F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0),
@@ -320,8 +474,18 @@ static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
.name = "disp_cc_mdss_rot_clk_src",
.parent_data = disp_cc_parent_data_3,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000,
[VDD_LOWER] = 165000000,
[VDD_LOW] = 300000000,
[VDD_NOMINAL] = 412500000 },
},
};
static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
@@ -334,8 +498,15 @@ static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
.name = "disp_cc_mdss_vsync_clk_src",
.parent_data = disp_cc_parent_data_2,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 19200000 },
},
};
static struct clk_branch disp_cc_mdss_ahb_clk = {
@@ -829,7 +1000,7 @@ static const struct regmap_config disp_cc_sdm845_regmap_config = {
.fast_io = true,
};
static const struct qcom_cc_desc disp_cc_sdm845_desc = {
static struct qcom_cc_desc disp_cc_sdm845_desc = {
.config = &disp_cc_sdm845_regmap_config,
.clks = disp_cc_sdm845_clocks,
.num_clks = ARRAY_SIZE(disp_cc_sdm845_clocks),
@@ -837,23 +1008,86 @@ static const struct qcom_cc_desc disp_cc_sdm845_desc = {
.num_resets = ARRAY_SIZE(disp_cc_sdm845_resets),
.gdscs = disp_cc_sdm845_gdscs,
.num_gdscs = ARRAY_SIZE(disp_cc_sdm845_gdscs),
.clk_regulators = disp_cc_sdm845_regulators,
.num_clk_regulators = ARRAY_SIZE(disp_cc_sdm845_regulators),
};
static const struct of_device_id disp_cc_sdm845_match_table[] = {
{ .compatible = "qcom,sdm845-dispcc" },
{ .compatible = "qcom,sdm670-dispcc" },
{ }
};
MODULE_DEVICE_TABLE(of, disp_cc_sdm845_match_table);
static void disp_cc_sdm845_fixup_sdm670(void)
{
disp_cc_mdss_byte0_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
180000000;
disp_cc_mdss_byte0_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
275000000;
disp_cc_mdss_byte0_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
358000000;
disp_cc_mdss_byte1_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
180000000;
disp_cc_mdss_byte1_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
275000000;
disp_cc_mdss_byte1_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
358000000;
disp_cc_mdss_dp_pixel1_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
337500000;
disp_cc_mdss_dp_pixel_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
337500000;
disp_cc_mdss_mdp_clk_src.freq_tbl =
ftbl_disp_cc_mdss_mdp_clk_src_sdm670;
disp_cc_mdss_mdp_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
171428571;
disp_cc_mdss_mdp_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
344000000;
disp_cc_mdss_mdp_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] =
430000000;
disp_cc_mdss_pclk0_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
280000000;
disp_cc_mdss_pclk0_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
430000000;
disp_cc_mdss_pclk0_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
430000000;
disp_cc_mdss_pclk1_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
280000000;
disp_cc_mdss_pclk1_clk_src.clkr.vdd_data.rate_max[VDD_LOW] =
430000000;
disp_cc_mdss_pclk1_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
430000000;
disp_cc_mdss_rot_clk_src.freq_tbl =
ftbl_disp_cc_mdss_rot_clk_src_sdm670;
disp_cc_mdss_rot_clk_src.clkr.vdd_data.rate_max[VDD_LOWER] =
171428571;
disp_cc_mdss_rot_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
344000000;
disp_cc_mdss_rot_clk_src.clkr.vdd_data.rate_max[VDD_NOMINAL] =
430000000;
}
static int disp_cc_sdm845_probe(struct platform_device *pdev)
{
struct regmap *regmap;
struct alpha_pll_config disp_cc_pll0_config = {};
int ret;
bool sdm670;
sdm670 = of_device_is_compatible(pdev->dev.of_node,
"qcom,sdm670-dispcc");
regmap = qcom_cc_map(pdev, &disp_cc_sdm845_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
if (sdm670)
disp_cc_sdm845_fixup_sdm670();
disp_cc_sdm845_desc.gdscs = NULL;
disp_cc_sdm845_desc.num_gdscs = 0;
/* 960 MHz Configuration*/
disp_cc_pll0_config.l = 0x2c;
disp_cc_pll0_config.alpha = 0xcaaa;
@@ -862,7 +1096,19 @@ static int disp_cc_sdm845_probe(struct platform_device *pdev)
/* Enable hardware clock gating for DSI and MDP clocks */
regmap_update_bits(regmap, 0x8000, 0x7f0, 0x7f0);
return qcom_cc_really_probe(pdev, &disp_cc_sdm845_desc, regmap);
ret = qcom_cc_really_probe(pdev, &disp_cc_sdm845_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register Display CC clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered Display CC clocks\n");
return ret;
}
static void disp_cc_sdm845_sync_state(struct device *dev)
{
qcom_cc_sync_state(dev, &disp_cc_sdm845_desc);
}
static struct platform_driver disp_cc_sdm845_driver = {
@@ -870,7 +1116,7 @@ static struct platform_driver disp_cc_sdm845_driver = {
.driver = {
.name = "disp_cc-sdm845",
.of_match_table = disp_cc_sdm845_match_table,
.sync_state = clk_sync_state,
.sync_state = disp_cc_sdm845_sync_state,
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -567,6 +567,7 @@ static const struct qcom_reset_map gpu_cc_crow_resets[] = {
[GPUCC_GPU_CC_GX_BCR] = { 0x9058 },
[GPUCC_GPU_CC_RBCPR_BCR] = { 0x91e0 },
[GPUCC_GPU_CC_XO_BCR] = { 0x9000 },
[GPUCC_GPU_CC_FREQUENCY_LIMITER_IRQ_CLEAR] = { 0x9538 },
};
static const struct regmap_config gpu_cc_crow_regmap_config = {
@@ -605,6 +606,9 @@ static int gpu_cc_crow_probe(struct platform_device *pdev)
clk_lucid_ole_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
clk_lucid_ole_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
/* Enable frequency limiter irq */
regmap_write(regmap, 0x9534, 0x0);
/*
* Keep clocks always enabled:
* gpu_cc_cxo_aon_clk

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk-provider.h>
@@ -17,6 +18,8 @@
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "gdsc.h"
#include "reset.h"
#include "vdd-level-sdm845.h"
#define CX_GMU_CBCR_SLEEP_MASK 0xf
#define CX_GMU_CBCR_SLEEP_SHIFT 4
@@ -25,51 +28,188 @@
#define CLK_DIS_WAIT_SHIFT 12
#define CLK_DIS_WAIT_MASK (0xf << CLK_DIS_WAIT_SHIFT)
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner);
static DEFINE_VDD_REGULATORS(vdd_mx, VDD_NUM, 1, vdd_corner);
static DEFINE_VDD_REGULATORS(vdd_gfx, VDD_GX_NUM, 1, vdd_gx_corner);
static struct clk_vdd_class *gpu_cc_sdm845_regulators[] = {
&vdd_cx,
&vdd_mx,
&vdd_gfx,
};
enum {
P_BI_TCXO,
P_GPLL0_OUT_MAIN,
P_GPLL0_OUT_MAIN_DIV,
P_GPU_CC_PLL0_OUT_EVEN,
P_GPU_CC_PLL0_OUT_MAIN,
P_GPU_CC_PLL0_OUT_ODD,
P_GPU_CC_PLL1_OUT_EVEN,
P_GPU_CC_PLL1_OUT_MAIN,
P_GPU_CC_PLL1_OUT_ODD,
P_CRC_DIV,
};
static const struct alpha_pll_config gpu_cc_pll1_config = {
.l = 0x1a,
.alpha = 0xaab,
static struct pll_vco fabia_vco[] = {
{ 249600000, 2000000000, 0 },
{ 125000000, 1000000000, 1 },
};
static struct clk_alpha_pll gpu_cc_pll0 = {
.offset = 0x0,
.vco_table = fabia_vco,
.num_vco = ARRAY_SIZE(fabia_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fabia_ops,
},
.vdd_data = {
.vdd_class = &vdd_mx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000 },
},
},
};
static const struct clk_div_table post_div_table_fabia_even[] = {
{ 0x0, 1 },
{ 0x1, 2 },
{ 0x3, 4 },
{ 0x7, 8 },
{},
};
static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_even = {
.offset = 0x0,
.post_div_shift = 8,
.post_div_table = post_div_table_fabia_even,
.num_post_div = ARRAY_SIZE(post_div_table_fabia_even),
.width = 4,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
.clkr.hw.init = &(struct clk_init_data){
.name = "gpu_cc_pll0_out_even",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_pll0.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_alpha_pll_postdiv_fabia_ops,
},
};
static struct clk_alpha_pll gpu_cc_pll1 = {
.offset = 0x100,
.vco_table = fabia_vco,
.num_vco = ARRAY_SIZE(fabia_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_pll1",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo", .name = "bi_tcxo",
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fabia_ops,
},
.vdd_data = {
.vdd_class = &vdd_mx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000 },
},
},
};
static struct clk_fixed_factor crc_div = {
.mult = 1,
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "crc_div",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_pll0_out_even.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_fixed_factor_ops,
},
};
static const struct parent_map gpu_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_GPU_CC_PLL0_OUT_MAIN, 1 },
{ P_GPU_CC_PLL1_OUT_MAIN, 3 },
{ P_GPLL0_OUT_MAIN, 5 },
{ P_GPLL0_OUT_MAIN_DIV, 6 },
};
static const struct clk_parent_data gpu_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .hw = &gpu_cc_pll0.clkr.hw },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .fw_name = "gcc_gpu_gpll0_clk_src", .name = "gcc_gpu_gpll0_clk_src" },
{ .fw_name = "gcc_gpu_gpll0_div_clk_src", .name = "gcc_gpu_gpll0_div_clk_src" },
{ .fw_name = "gcc_gpu_gpll0_clk_src" },
{ .fw_name = "gcc_gpu_gpll0_div_clk_src" },
};
static const struct parent_map gpu_cc_parent_map_1[] = {
{ P_BI_TCXO, 0 },
{ P_GPU_CC_PLL0_OUT_EVEN, 1 },
{ P_GPU_CC_PLL0_OUT_ODD, 2 },
{ P_GPU_CC_PLL1_OUT_EVEN, 3 },
{ P_GPU_CC_PLL1_OUT_ODD, 4 },
{ P_GPLL0_OUT_MAIN, 5 },
};
static const struct clk_parent_data gpu_cc_parent_data_1[] = {
{ .fw_name = "bi_tcxo" },
{ .hw = &gpu_cc_pll0_out_even.clkr.hw },
{ .hw = &gpu_cc_pll0.clkr.hw },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .fw_name = "gcc_gpu_gpll0_clk_src" },
};
static const struct parent_map gpu_cc_parent_map_2[] = {
{ P_BI_TCXO, 0 },
{ P_CRC_DIV, 1 },
{ P_GPU_CC_PLL0_OUT_ODD, 2 },
{ P_GPU_CC_PLL1_OUT_EVEN, 3 },
{ P_GPU_CC_PLL1_OUT_ODD, 4 },
{ P_GPLL0_OUT_MAIN, 5 },
};
static const struct clk_parent_data gpu_cc_parent_data_2[] = {
{ .fw_name = "bi_tcxo" },
{ .hw = &crc_div.hw },
{ .hw = &gpu_cc_pll0.clkr.hw },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .hw = &gpu_cc_pll1.clkr.hw },
{ .fw_name = "gcc_gpu_gpll0_clk_src" },
};
static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0),
F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0),
{ }
};
static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src_sdm670[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0),
{ }
};
@@ -83,8 +223,160 @@ static struct clk_rcg2 gpu_cc_gmu_clk_src = {
.name = "gpu_cc_gmu_clk_src",
.parent_data = gpu_cc_parent_data_0,
.num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 200000000,
[VDD_LOW] = 400000000 },
},
};
static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src[] = {
F(147000000, P_CRC_DIV, 1, 0, 0),
F(210000000, P_CRC_DIV, 1, 0, 0),
F(280000000, P_CRC_DIV, 1, 0, 0),
F(338000000, P_CRC_DIV, 1, 0, 0),
F(425000000, P_CRC_DIV, 1, 0, 0),
F(487000000, P_CRC_DIV, 1, 0, 0),
F(548000000, P_CRC_DIV, 1, 0, 0),
F(600000000, P_CRC_DIV, 1, 0, 0),
{ }
};
static const struct freq_tbl ftbl_gpu_cc_gx_gfx3d_clk_src_sdm670[] = {
F(180000000, P_CRC_DIV, 1, 0, 0),
F(267000000, P_CRC_DIV, 1, 0, 0),
F(355000000, P_CRC_DIV, 1, 0, 0),
F(430000000, P_CRC_DIV, 1, 0, 0),
F(504000000, P_CRC_DIV, 1, 0, 0),
F(565000000, P_CRC_DIV, 1, 0, 0),
F(610000000, P_CRC_DIV, 1, 0, 0),
F(650000000, P_CRC_DIV, 1, 0, 0),
F(700000000, P_CRC_DIV, 1, 0, 0),
F(750000000, P_CRC_DIV, 1, 0, 0),
F(780000000, P_CRC_DIV, 1, 0, 0),
{ }
};
static struct clk_rcg2 gpu_cc_gx_gfx3d_clk_src = {
.cmd_rcgr = 0x101c,
.mnd_width = 0,
.hid_width = 5,
.parent_map = gpu_cc_parent_map_2,
.freq_tbl = ftbl_gpu_cc_gx_gfx3d_clk_src,
.flags = FORCE_ENABLE_RCG,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gx_gfx3d_clk_src",
.parent_data = gpu_cc_parent_data_2,
.num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_gfx,
.num_rate_max = VDD_GX_NUM,
.rate_max = (unsigned long[VDD_GX_NUM]) {
[VDD_GX_MIN] = 147000000,
[VDD_GX_LOWER] = 210000000,
[VDD_GX_LOW] = 280000000,
[VDD_GX_LOW_L1] = 338000000,
[VDD_GX_NOMINAL] = 425000000,
[VDD_GX_NOMINAL_L1] = 487000000,
[VDD_GX_HIGH] = 548000000,
[VDD_GX_HIGH_L1] = 600000000 },
},
};
static struct clk_branch gpu_cc_acd_ahb_clk = {
.halt_reg = 0x1168,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1168,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_acd_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_acd_cxo_clk = {
.halt_reg = 0x1164,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1164,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_acd_cxo_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_crc_ahb_clk = {
.halt_reg = 0x107c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x107c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_crc_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_apb_clk = {
.halt_reg = 0x1088,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1088,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_apb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_gfx3d_clk = {
.halt_reg = 0x10a4,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x10a4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_gfx3d_clk",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_gfx3d_slv_clk = {
.halt_reg = 0x10a8,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x10a8,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_gfx3d_slv_clk",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cx_gmu_clk = {
@@ -105,6 +397,32 @@ static struct clk_branch gpu_cc_cx_gmu_clk = {
},
};
static struct clk_branch gpu_cc_cx_snoc_dvm_clk = {
.halt_reg = 0x108c,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x108c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cx_snoc_dvm_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cxo_aon_clk = {
.halt_reg = 0x1004,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1004,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_cxo_aon_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_cxo_clk = {
.halt_reg = 0x109c,
.halt_check = BRANCH_HALT,
@@ -118,6 +436,55 @@ static struct clk_branch gpu_cc_cxo_clk = {
},
};
static struct clk_branch gpu_cc_gx_gfx3d_clk = {
.halt_reg = 0x1054,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1054,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gx_gfx3d_clk",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_gx_gfx3d_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_gx_gmu_clk = {
.halt_reg = 0x1064,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1064,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gx_gmu_clk",
.parent_hws = (const struct clk_hw*[]){
&gpu_cc_gmu_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gpu_cc_gx_vsense_clk = {
.halt_reg = 0x1058,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0x1058,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpu_cc_gx_vsense_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc gpu_cx_gdsc = {
.gdscr = 0x106c,
.gds_hw_ctrl = 0x1540,
@@ -140,15 +507,34 @@ static struct gdsc gpu_gx_gdsc = {
};
static struct clk_regmap *gpu_cc_sdm845_clocks[] = {
[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
[GPU_CC_ACD_AHB_CLK] = &gpu_cc_acd_ahb_clk.clkr,
[GPU_CC_ACD_CXO_CLK] = &gpu_cc_acd_cxo_clk.clkr,
[GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
[GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr,
[GPU_CC_CX_GFX3D_CLK] = &gpu_cc_cx_gfx3d_clk.clkr,
[GPU_CC_CX_GFX3D_SLV_CLK] = &gpu_cc_cx_gfx3d_slv_clk.clkr,
[GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
[GPU_CC_GX_VSENSE_CLK] = &gpu_cc_gx_vsense_clk.clkr,
[GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr,
[GPU_CC_GX_GFX3D_CLK_SRC] = &gpu_cc_gx_gfx3d_clk_src.clkr,
[GPU_CC_GX_GFX3D_CLK] = &gpu_cc_gx_gfx3d_clk.clkr,
[GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
[GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
};
static struct gdsc *gpu_cc_sdm845_gdscs[] = {
[GPU_CX_GDSC] = &gpu_cx_gdsc,
[GPU_GX_GDSC] = &gpu_gx_gdsc,
static const struct qcom_reset_map gpu_cc_sdm845_resets[] = {
[GPUCC_GPU_CC_ACD_BCR] = { 0x1160 },
[GPUCC_GPU_CC_CX_BCR] = { 0x1068 },
[GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 },
[GPUCC_GPU_CC_GMU_BCR] = { 0x111c },
[GPUCC_GPU_CC_GX_BCR] = { 0x1008 },
[GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 },
[GPUCC_GPU_CC_XO_BCR] = { 0x1000 },
};
static const struct regmap_config gpu_cc_sdm845_regmap_config = {
@@ -159,30 +545,90 @@ static const struct regmap_config gpu_cc_sdm845_regmap_config = {
.fast_io = true,
};
static const struct qcom_cc_desc gpu_cc_sdm845_desc = {
static struct gdsc *gpu_cc_sdm845_gdscs[] = {
[GPU_CX_GDSC] = &gpu_cx_gdsc,
[GPU_GX_GDSC] = &gpu_gx_gdsc,
};
static struct qcom_cc_desc gpu_cc_sdm845_desc = {
.config = &gpu_cc_sdm845_regmap_config,
.clks = gpu_cc_sdm845_clocks,
.num_clks = ARRAY_SIZE(gpu_cc_sdm845_clocks),
.resets = gpu_cc_sdm845_resets,
.num_resets = ARRAY_SIZE(gpu_cc_sdm845_resets),
.gdscs = gpu_cc_sdm845_gdscs,
.num_gdscs = ARRAY_SIZE(gpu_cc_sdm845_gdscs),
.clk_regulators = gpu_cc_sdm845_regulators,
.num_clk_regulators = ARRAY_SIZE(gpu_cc_sdm845_regulators),
};
static const struct of_device_id gpu_cc_sdm845_match_table[] = {
{ .compatible = "qcom,sdm845-gpucc" },
{ .compatible = "qcom,sdm670-gpucc" },
{ }
};
MODULE_DEVICE_TABLE(of, gpu_cc_sdm845_match_table);
static void gpu_cc_sdm845_fixup_sdm670(void)
{
gpu_cc_gmu_clk_src.freq_tbl = ftbl_gpu_cc_gmu_clk_src_sdm670;
gpu_cc_gmu_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 200000000;
/* GFX clocks */
gpu_cc_gx_gfx3d_clk_src.freq_tbl =
ftbl_gpu_cc_gx_gfx3d_clk_src_sdm670;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_MIN] = 180000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_LOWER] =
267000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_LOW] = 355000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_LOW_L1] =
430000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_NOMINAL] =
565000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_NOMINAL_L1] =
650000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_HIGH] = 750000000;
gpu_cc_gx_gfx3d_clk_src.clkr.vdd_data.rate_max[VDD_GX_HIGH_L1] =
780000000;
}
static int gpu_cc_sdm845_probe(struct platform_device *pdev)
{
struct regmap *regmap;
unsigned int value, mask;
struct alpha_pll_config gpu_cc_pll0_config = {};
int ret;
bool sdm670;
sdm670 = of_device_is_compatible(pdev->dev.of_node,
"qcom,sdm670-gpucc");
regmap = qcom_cc_map(pdev, &gpu_cc_sdm845_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config);
/* Register clock fixed factor for CRC divide. */
ret = devm_clk_hw_register(&pdev->dev, &crc_div.hw);
if (ret) {
dev_err(&pdev->dev, "Failed to register hardware clock\n");
return ret;
}
if (sdm670)
gpu_cc_sdm845_fixup_sdm670();
gpu_cc_sdm845_desc.gdscs = NULL;
gpu_cc_sdm845_desc.num_gdscs = 0;
/* 560 MHz configuration */
gpu_cc_pll0_config.l = 0x1d,
gpu_cc_pll0_config.alpha = 0x2aaa,
clk_fabia_pll_configure(&gpu_cc_pll0, regmap, &gpu_cc_pll0_config);
/* 512 Mhz configuration */
gpu_cc_pll0_config.l = 0x1a,
gpu_cc_pll0_config.alpha = 0xaaaa,
clk_fabia_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll0_config);
/*
* Configure gpu_cc_cx_gmu_clk with recommended
@@ -197,7 +643,19 @@ static int gpu_cc_sdm845_probe(struct platform_device *pdev)
regmap_update_bits(regmap, 0x106c, CLK_DIS_WAIT_MASK,
8 << CLK_DIS_WAIT_SHIFT);
return qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap);
ret = qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register GPU CC clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered GPU CC clocks\n");
return ret;
}
static void gpu_cc_sdm845_sync_state(struct device *dev)
{
qcom_cc_sync_state(dev, &gpu_cc_sdm845_desc);
}
static struct platform_driver gpu_cc_sdm845_driver = {
@@ -205,7 +663,7 @@ static struct platform_driver gpu_cc_sdm845_driver = {
.driver = {
.name = "sdm845-gpucc",
.of_match_table = gpu_cc_sdm845_match_table,
.sync_state = clk_sync_state,
.sync_state = gpu_cc_sdm845_sync_state,
},
};

View File

@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __DRIVERS_CLK_QCOM_VDD_LEVEL_SDM845_H
#define __DRIVERS_CLK_QCOM_VDD_LEVEL_SDM845_H
#include <linux/regulator/consumer.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator-levels.h>
enum vdd_levels {
VDD_NONE,
VDD_MIN, /* MIN SVS */
VDD_LOWER, /* SVS2 */
VDD_LOW, /* SVS */
VDD_LOW_L1, /* SVSL1 */
VDD_NOMINAL, /* NOM */
VDD_HIGH, /* TURBO */
VDD_NUM,
};
static int vdd_corner[] = {
[VDD_NONE] = 0,
[VDD_MIN] = RPMH_REGULATOR_LEVEL_MIN_SVS,
[VDD_LOWER] = RPMH_REGULATOR_LEVEL_LOW_SVS,
[VDD_LOW] = RPMH_REGULATOR_LEVEL_SVS,
[VDD_LOW_L1] = RPMH_REGULATOR_LEVEL_SVS_L1,
[VDD_NOMINAL] = RPMH_REGULATOR_LEVEL_NOM,
[VDD_HIGH] = RPMH_REGULATOR_LEVEL_TURBO,
};
enum vdd_gx_levels {
VDD_GX_NONE,
VDD_GX_MIN, /* MIN SVS */
VDD_GX_LOWER, /* SVS2 */
VDD_GX_LOW, /* SVS */
VDD_GX_LOW_L1, /* SVSL1 */
VDD_GX_NOMINAL, /* NOM */
VDD_GX_NOMINAL_L1, /* NOM1 */
VDD_GX_HIGH, /* TURBO */
VDD_GX_HIGH_L1, /* TURBO1 */
VDD_GX_NUM,
};
static int vdd_gx_corner[] = {
[VDD_GX_NONE] = 0, /* VDD_GX_NONE */
[VDD_GX_MIN] = RPMH_REGULATOR_LEVEL_MIN_SVS, /* VDD_GX_MIN */
[VDD_GX_LOWER] = RPMH_REGULATOR_LEVEL_LOW_SVS, /* VDD_GX_LOWER */
[VDD_GX_LOW] = RPMH_REGULATOR_LEVEL_SVS, /* VDD_GX_LOW */
[VDD_GX_LOW_L1] = RPMH_REGULATOR_LEVEL_SVS_L1, /* VDD_GX_LOW_L1 */
[VDD_GX_NOMINAL] = RPMH_REGULATOR_LEVEL_NOM, /* VDD_GX_NOMINAL */
[VDD_GX_NOMINAL_L1] = RPMH_REGULATOR_LEVEL_NOM_L1, /* VDD_GX_NOMINAL_L1 */
[VDD_GX_HIGH] = RPMH_REGULATOR_LEVEL_TURBO, /* VDD_GX_HIGH */
[VDD_GX_HIGH_L1] = RPMH_REGULATOR_LEVEL_TURBO_L1, /* VDD_GX_HIGH_L1 */
};
#endif

View File

@@ -493,32 +493,16 @@ static struct clk_branch video_cc_mvs1c_clk = {
},
};
static struct clk_branch video_cc_sleep_clk = {
.halt_reg = 0x8140,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x8140,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_sleep_clk",
.parent_hws = (const struct clk_hw*[]){
&video_cc_sleep_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
/*
* video_cc_ahb_clk
* video_cc_xo_clk
* video_cc_sleep_clk
*/
static struct critical_clk_offset critical_clk_list[] = {
{ .offset = 0x80f4, .mask = BIT(0) },
{ .offset = 0x8124, .mask = BIT(0) },
{ .offset = 0x8140, .mask = BIT(0) },
};
static struct clk_regmap *video_cc_kalama_clocks[] = {
@@ -535,7 +519,6 @@ static struct clk_regmap *video_cc_kalama_clocks[] = {
[VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
[VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
[VIDEO_CC_PLL1] = &video_cc_pll1.clkr,
[VIDEO_CC_SLEEP_CLK] = &video_cc_sleep_clk.clkr,
[VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
[VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
};

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/clk-provider.h>
@@ -17,58 +18,102 @@
#include "clk-regmap.h"
#include "clk-pll.h"
#include "gdsc.h"
#include "reset.h"
#include "vdd-level-sdm845.h"
static DEFINE_VDD_REGULATORS(vdd_cx, VDD_NUM, 1, vdd_corner);
static struct clk_vdd_class *video_cc_sdm845_regulators[] = {
&vdd_cx,
};
enum {
P_BI_TCXO,
P_VIDEO_PLL0_OUT_EVEN,
P_VIDEO_PLL0_OUT_MAIN,
/* P_VIDEO_PLL0_OUT_EVEN, */
/* P_VIDEO_PLL0_OUT_ODD, */
P_VIDEO_PLL0_OUT_ODD,
};
static const struct alpha_pll_config video_pll0_config = {
static struct pll_vco fabia_vco[] = {
{ 249600000, 2000000000, 0 },
{ 125000000, 1000000000, 1 },
};
/*320 MHz configuration */
static struct alpha_pll_config video_pll0_config = {
.l = 0x10,
.alpha = 0xaaab,
.cal_l = 0x32,
.alpha = 0xaaaa,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002067,
.test_ctl_val = 0x40000000,
.test_ctl_hi_val = 0x00000002,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00004805,
};
static struct clk_alpha_pll video_pll0 = {
.offset = 0x42c,
.vco_table = fabia_vco,
.num_vco = ARRAY_SIZE(fabia_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "video_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo", .name = "bi_tcxo",
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_fabia_ops,
},
.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 615000000,
[VDD_LOW] = 1066000000,
[VDD_LOW_L1] = 1600000000,
[VDD_NOMINAL] = 2000000000 },
},
},
};
static const struct parent_map video_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_VIDEO_PLL0_OUT_MAIN, 1 },
/* { P_VIDEO_PLL0_OUT_EVEN, 2 }, */
/* { P_VIDEO_PLL0_OUT_ODD, 3 }, */
{ P_VIDEO_PLL0_OUT_EVEN, 2 },
{ P_VIDEO_PLL0_OUT_ODD, 3 },
};
static const struct clk_parent_data video_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
{ .fw_name = "bi_tcxo" },
{ .hw = &video_pll0.clkr.hw },
{ .hw = &video_pll0.clkr.hw },
{ .hw = &video_pll0.clkr.hw },
/* { .name = "video_pll0_out_even" }, */
/* { .name = "video_pll0_out_odd" }, */
};
static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = {
F(100000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0),
F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(330000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(320000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(380000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(444000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(533000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
{ }
};
static const struct freq_tbl ftbl_video_cc_venus_clk_src_sdm670[] = {
F(100000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0),
F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(330000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(364700000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(404000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(444000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(533000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
{ }
};
static struct clk_rcg2 video_cc_venus_clk_src = {
.cmd_rcgr = 0x7f0,
.mnd_width = 0,
@@ -81,6 +126,17 @@ static struct clk_rcg2 video_cc_venus_clk_src = {
.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
.clkr.vdd_data = {
.vdd_class = &vdd_cx,
.num_rate_max = VDD_NUM,
.rate_max = (unsigned long[VDD_NUM]) {
[VDD_MIN] = 100000000,
[VDD_LOWER] = 200000000,
[VDD_LOW] = 320000000,
[VDD_LOW_L1] = 380000000,
[VDD_NOMINAL] = 444000000,
[VDD_HIGH] = 533000000 },
},
};
@@ -305,31 +361,65 @@ static const struct regmap_config video_cc_sdm845_regmap_config = {
.fast_io = true,
};
static const struct qcom_cc_desc video_cc_sdm845_desc = {
static struct qcom_cc_desc video_cc_sdm845_desc = {
.config = &video_cc_sdm845_regmap_config,
.clks = video_cc_sdm845_clocks,
.num_clks = ARRAY_SIZE(video_cc_sdm845_clocks),
.gdscs = video_cc_sdm845_gdscs,
.num_gdscs = ARRAY_SIZE(video_cc_sdm845_gdscs),
.clk_regulators = video_cc_sdm845_regulators,
.num_clk_regulators = ARRAY_SIZE(video_cc_sdm845_regulators),
};
static const struct of_device_id video_cc_sdm845_match_table[] = {
{ .compatible = "qcom,sdm845-videocc" },
{ .compatible = "qcom,sdm670-videocc" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sdm845_match_table);
static void video_cc_sdm845_fixup_sdm670(void)
{
video_cc_venus_clk_src.freq_tbl = ftbl_video_cc_venus_clk_src_sdm670;
video_cc_venus_clk_src.clkr.vdd_data.rate_max[VDD_LOW] = 330000000;
video_cc_venus_clk_src.clkr.vdd_data.rate_max[VDD_LOW_L1] =
404000000;
}
static int video_cc_sdm845_probe(struct platform_device *pdev)
{
struct regmap *regmap;
int ret;
bool sdm670;
sdm670 = of_device_is_compatible(pdev->dev.of_node,
"qcom,sdm670-videocc");
regmap = qcom_cc_map(pdev, &video_cc_sdm845_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
if (sdm670)
video_cc_sdm845_fixup_sdm670();
video_cc_sdm845_desc.gdscs = NULL;
video_cc_sdm845_desc.num_gdscs = 0;
clk_fabia_pll_configure(&video_pll0, regmap, &video_pll0_config);
return qcom_cc_really_probe(pdev, &video_cc_sdm845_desc, regmap);
ret = qcom_cc_really_probe(pdev, &video_cc_sdm845_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register Video CC clocks\n");
return ret;
}
dev_info(&pdev->dev, "Registered Video CC clocks\n");
return ret;
}
static void video_cc_sdm845_sync_state(struct device *dev)
{
qcom_cc_sync_state(dev, &video_cc_sdm845_desc);
}
static struct platform_driver video_cc_sdm845_driver = {
@@ -337,7 +427,7 @@ static struct platform_driver video_cc_sdm845_driver = {
.driver = {
.name = "sdm845-videocc",
.of_match_table = video_cc_sdm845_match_table,
.sync_state = clk_sync_state,
.sync_state = video_cc_sdm845_sync_state,
},
};

View File

@@ -775,10 +775,12 @@ int tmc_etr_usb_init(struct amba_device *adev,
mapping_config = qcom_iommu_get_mappings_configuration(domain);
if (mapping_config < 0)
return -ENOMEM;
if (!(mapping_config & QCOM_IOMMU_MAPPING_CONF_S1_BYPASS))
if (!(mapping_config & QCOM_IOMMU_MAPPING_CONF_S1_BYPASS)) {
pr_debug("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
__func__, dev_name(dev));
bamdata->props.options |= SPS_BAM_SMMU_EN;
bamdata->props.options |= SPS_BAM_SMMU_EN;
}
}
return sps_register_bam_device(&bamdata->props, &bamdata->handle);

View File

@@ -679,6 +679,12 @@ static void geni_i2c_irq_handle_watermark(struct geni_i2c_dev *gi2c, u32 m_stat)
int i, j;
u32 rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
if (!cur) {
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, "%s: Spurious irq\n", __func__);
geni_i2c_err(gi2c, GENI_SPURIOUS_IRQ);
return;
}
if (((m_stat & M_RX_FIFO_WATERMARK_EN) ||
(m_stat & M_RX_FIFO_LAST_EN)) && (cur->flags & I2C_M_RD)) {
u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
@@ -737,7 +743,7 @@ static irqreturn_t geni_i2c_irq(int irq, void *dev)
"%s: m_irq_status:0x%x\n", __func__, m_stat);
if (!cur) {
I2C_LOG_ERR(gi2c->ipcl, false, gi2c->dev, "Spurious irq\n");
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, "Spurious irq\n");
geni_i2c_err(gi2c, GENI_SPURIOUS_IRQ);
gi2c->cmd_done = true;
is_clear_watermark = true;
@@ -2420,7 +2426,7 @@ static int geni_i2c_suspend_late(struct device *device)
pm_runtime_enable(device);
}
i2c_unlock_bus(&gi2c->adap, I2C_LOCK_SEGMENT);
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, "%s ret=%d\n", __func__);
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, "%s ret=%d\n", __func__, ret);
return 0;
}
#else

View File

@@ -453,11 +453,14 @@ static int __arm_smmu_alloc_cb(unsigned long *map, int start, int end,
{
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);
struct arm_smmu_device *smmu = cfg->smmu;
struct arm_smmu_device *smmu;
int idx;
int i;
int cb = -EINVAL;
if (!fwspec || !cfg)
return cb;
smmu = cfg->smmu;
for_each_cfg_sme(cfg, fwspec, i, idx) {
if (smmu->s2crs[idx].pinned)
cb = smmu->s2crs[idx].cbndx;
@@ -1113,7 +1116,7 @@ static bool arm_smmu_master_attached(struct arm_smmu_device *smmu,
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master_cfg *cfg = dev_iommu_priv_get(dev);
if (!cfg || !fwspec)
if (!fwspec || !cfg)
return false;
for_each_cfg_sme(cfg, fwspec, i, idx) {
@@ -1959,6 +1962,9 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
bool config_smrs = !dev_defer_smr_configuration(dev);
int i, idx, ret;
if (!fwspec || !cfg)
return -EINVAL;
mutex_lock(&smmu->stream_map_mutex);
/* Figure out a viable stream map entry allocation */
for_each_cfg_sme(cfg, fwspec, i, idx) {
@@ -2771,6 +2777,9 @@ static struct iommu_group *arm_smmu_device_group(struct device *dev)
struct iommu_group *group = NULL;
int i, idx;
if (!cfg || !fwspec)
return ERR_PTR(-EINVAL);
mutex_lock(&smmu->stream_map_mutex);
group = of_get_device_group(dev);
if (group)

View File

@@ -3031,6 +3031,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
/* Read en_wol from device tree */
priv->en_wol = of_property_read_bool(np, "enable-wol");
if (of_property_read_bool(np, "disable-frame-preem"))
priv->dma_cap.fpesel = 0;
/* enable safety feature from device tree */
if (of_property_read_bool(np, "safety-feat") && priv->dma_cap.asp)

View File

@@ -205,6 +205,7 @@ struct stmmac_priv {
int tx_coalesce;
int hwts_tx_en;
int irq_number;
bool tx_path_in_lpi_mode;
bool tso;
int sph;

View File

@@ -3956,6 +3956,8 @@ static int stmmac_open(struct net_device *dev)
if (ret)
goto irq_error;
priv->irq_number = dev->irq;
stmmac_enable_all_queues(priv);
netif_tx_start_all_queues(priv->dev);
stmmac_enable_all_dma_irq(priv);
@@ -7659,6 +7661,12 @@ int stmmac_suspend(struct device *dev)
hrtimer_cancel(&priv->tx_queue[chan].txtimer);
}
/* Free the IRQ lines */
if (priv->irq_number != 0) {
free_irq(ndev->irq, ndev);
priv->irq_number = 0;
}
if (priv->eee_enabled) {
priv->tx_path_in_lpi_mode = false;
del_timer_sync(&priv->eee_ctrl_timer);
@@ -7813,6 +7821,16 @@ int stmmac_resume(struct device *dev)
stmmac_restore_hw_vlan_rx_fltr(priv, ndev, priv->hw);
if (priv->irq_number == 0) {
ret = request_irq(ndev->irq, stmmac_interrupt,
IRQF_SHARED, ndev->name, ndev);
if (unlikely(ret < 0))
netdev_err(priv->dev,
"%s: ERROR: allocating the IRQ %d (error: %d)\n",
__func__, ndev->irq, ret);
priv->irq_number = ndev->irq;
}
stmmac_enable_all_queues(priv);
stmmac_enable_all_dma_irq(priv);

View File

@@ -8005,11 +8005,15 @@ static int msm_pcie_set_link_width(struct msm_pcie_dev_t *pcie_dev,
LINK_WIDTH_MASK << LINK_WIDTH_SHIFT,
link_width);
/* Set NUM_OF_LANES in GEN2_CTRL_OFF */
/*
* It's advisable to set NUM_OF_LANES[8:0] field to 0x1. It allows
* establishing connection on one line even if there is a termination
* on the second line. Otherwise the link will go to compliance.
*/
msm_pcie_write_reg_field(pcie_dev->dm_core,
PCIE_GEN3_GEN2_CTRL,
NUM_OF_LANES_MASK << NUM_OF_LANES_SHIFT,
link_width);
LINK_WIDTH_X1);
/* enable write access to RO register */
msm_pcie_write_mask(pcie_dev->dm_core + PCIE_GEN3_MISC_CONTROL, 0,
@@ -8017,7 +8021,8 @@ static int msm_pcie_set_link_width(struct msm_pcie_dev_t *pcie_dev,
/* Set Maximum link width as current width */
msm_pcie_write_reg_field(pcie_dev->dm_core, PCIE20_CAP + PCI_EXP_LNKCAP,
PCI_EXP_LNKCAP_MLW, link_width);
PCI_EXP_LNKCAP_MLW,
target_link_width >> PCI_EXP_LNKSTA_NLW_SHIFT);
/* disable write access to RO register */
msm_pcie_write_mask(pcie_dev->dm_core + PCIE_GEN3_MISC_CONTROL, BIT(0),

View File

@@ -478,7 +478,6 @@ struct ep_pcie_dev_t {
bool enumerated;
enum ep_pcie_link_status link_status;
bool power_on;
bool suspending;
bool l23_ready;
bool l1ss_enabled;
bool no_notify;

View File

@@ -2434,7 +2434,6 @@ checkbme:
dev->link_status = EP_PCIE_LINK_UP;
}
dev->suspending = false;
goto out;
link_fail_pipe_clk_deinit:
@@ -2631,13 +2630,13 @@ static irqreturn_t ep_pcie_handle_linkdown_irq(int irq, void *data)
EP_PCIE_DBG(dev,
"PCIe V%d:Linkdown IRQ happened when the link is disabled\n",
dev->rev);
} else if (dev->suspending) {
} else if (!atomic_read(&dev->perst_deast)) {
EP_PCIE_DBG(dev,
"PCIe V%d:Linkdown IRQ happened when the link is suspending\n",
"PCIe V%d:Linkdown IRQ happened when PERST asserted\n",
dev->rev);
} else {
dev->link_status = EP_PCIE_LINK_DISABLED;
EP_PCIE_ERR(dev, "PCIe V%d:PCIe link is down for %ld times\n",
EP_PCIE_DBG(dev, "PCIe V%d:PCIe link is down for %ld times\n",
dev->rev, dev->linkdown_counter);
ep_pcie_reg_dump(dev, BIT(EP_PCIE_RES_PHY) |
BIT(EP_PCIE_RES_PARF), true);

View File

@@ -309,8 +309,6 @@ static void ep_pcie_show_status(struct ep_pcie_dev_t *dev)
EP_PCIE_DBG_FS("PCIe: link is %s\n",
(dev->link_status == EP_PCIE_LINK_ENABLED)
? "enabled" : "disabled");
EP_PCIE_DBG_FS("the link is %s suspending\n",
dev->suspending ? "" : "not");
EP_PCIE_DBG_FS("the power is %s on\n",
dev->power_on ? "" : "not");
EP_PCIE_DBG_FS("linkdown_counter: %lu\n",

View File

@@ -93,6 +93,7 @@ void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon);
bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon);
uint32_t qcom_sysmon_get_txn_id(struct qcom_sysmon *sysmon);
int qcom_sysmon_get_reason(struct qcom_sysmon *sysmon, char *buf, size_t len);
void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon, bool suspend);
#else
static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
const char *name,
@@ -120,6 +121,9 @@ static inline int qcom_sysmon_get_reason(struct qcom_sysmon *sysmon,
{
return -ENODEV;
}
static inline void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon,
bool suspend) { }
#endif
#endif

View File

@@ -32,6 +32,7 @@
#include <soc/qcom/secure_buffer.h>
#include <trace/events/rproc_qcom.h>
#include <soc/qcom/qcom_ramdump.h>
#include <linux/remoteproc/qcom_rproc.h>
#include "qcom_common.h"
#include "qcom_pil_info.h"
@@ -635,6 +636,52 @@ static int adsp_stop(struct rproc *rproc)
return ret;
}
static int adsp_shutdown(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
int handover;
trace_rproc_qcom_event(dev_name(adsp->dev), "adsp_shutdown", "enter");
scm_pas_enable_bw();
/*
* ADSP teardown is not possible in LPM. Ignore the SCM call return
* status for the teardown sequence.
*/
if (adsp->retry_shutdown)
qcom_scm_pas_shutdown_retry(adsp->pas_id);
else
qcom_scm_pas_shutdown(adsp->pas_id);
if (adsp->dtb_pas_id)
qcom_scm_pas_shutdown(adsp->dtb_pas_id);
scm_pas_disable_bw();
adsp_pds_disable(adsp, adsp->active_pds, adsp->active_pd_count);
if (adsp->qmp)
qcom_rproc_toggle_load_state(adsp->qmp, adsp->qmp_name, false);
handover = qcom_q6v5_unprepare(&adsp->q6v5);
if (handover)
qcom_pas_handover(&adsp->q6v5);
trace_rproc_qcom_event(dev_name(adsp->dev), "adsp_shutdown", "exit");
return 0;
}
void adsp_set_ops_stop(struct rproc *rproc, bool suspend)
{
struct qcom_adsp *adsp;
adsp = (struct qcom_adsp *)rproc->priv;
qcom_sysmon_set_ops_stop(adsp->sysmon, suspend);
if (suspend)
rproc->ops->stop = adsp_shutdown;
else
rproc->ops->stop = adsp_stop;
}
EXPORT_SYMBOL_GPL(adsp_set_ops_stop);
static int adsp_attach(struct rproc *rproc)
{
struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;

View File

@@ -757,7 +757,7 @@ static void slate_coredump(struct rproc *rproc)
slate_tz_req.address_fw = start_addr;
slate_tz_req.size_fw = size;
ret = slate_tzapp_comm(slate_data, &slate_tz_req);
if (ret != 0) {
if (ret != 0 || slate_data->cmd_status) {
dev_dbg(slate_data->dev,
"%s: SLATE RPROC ramdmp collection failed\n",
__func__);

View File

@@ -40,10 +40,6 @@
#define SP_SCSR_MB1_SP2CL_GP0_ADDR 0x1888020
#define SP_SCSR_MB3_SP2CL_GP0_ADDR 0x188C020
#define MAX_ROT_DATA_SIZE_IN_BYTES 4096
static bool ssr_already_occurred_since_boot;
#define NUM_OF_DEBUG_REGISTERS_READ 0x3
struct spss_data {
const char *firmware_name;
@@ -302,74 +298,13 @@ static bool check_status(struct qcom_spss *spss, int *ret_error)
return false;
}
static int manage_unused_pil_region_memory(struct qcom_spss *spss)
{
unsigned int src_vmid_list;
struct qcom_scm_vmperm newvm[2];
u8 *spss_rot_data;
int res;
spss_rot_data = kcalloc(MAX_ROT_DATA_SIZE_IN_BYTES, sizeof(*spss_rot_data), GFP_KERNEL);
if (!spss_rot_data)
return -ENOMEM;
/*
* When assigning memory to different ownership, previous data is erased,
* ROT data needs to remain in SPSS region as written by SPSS before.
*/
memcpy(spss_rot_data,
(uint8_t *)(uintptr_t)(spss->mem_region+spss->mem_size-MAX_ROT_DATA_SIZE_IN_BYTES),
MAX_ROT_DATA_SIZE_IN_BYTES);
src_vmid_list = BIT(QCOM_SCM_VMID_HLOS);
newvm[0].vmid = QCOM_SCM_VMID_HLOS;
newvm[0].perm = QCOM_SCM_PERM_RW;
newvm[1].vmid = QCOM_SCM_VMID_CP_SPSS_SP;
newvm[1].perm = QCOM_SCM_PERM_RW;
res = qcom_scm_assign_mem(spss->mem_phys + spss->mem_size - MAX_ROT_DATA_SIZE_IN_BYTES,
MAX_ROT_DATA_SIZE_IN_BYTES, &src_vmid_list, newvm, 2);
if (res) {
dev_err(spss->dev, "qcom_scm_assign_mem failed %d\n", res);
kfree(spss_rot_data);
return res;
}
memcpy((uint8_t *)(uintptr_t)(spss->mem_region+spss->mem_size-MAX_ROT_DATA_SIZE_IN_BYTES),
spss_rot_data, MAX_ROT_DATA_SIZE_IN_BYTES);
kfree(spss_rot_data);
return res;
}
static int spss_load(struct rproc *rproc, const struct firmware *fw)
{
struct qcom_spss *spss = (struct qcom_spss *)rproc->priv;
int res;
res = qcom_mdt_load(spss->dev, fw, rproc->firmware, spss->pas_id,
return qcom_mdt_load(spss->dev, fw, rproc->firmware, spss->pas_id,
spss->mem_region, spss->mem_phys, spss->mem_size,
&spss->mem_reloc);
if (res) {
dev_err(spss->dev, "qcom_mdt_load of SPSS image failed, error value %d\n", res);
return res;
}
/*
* During SSR only PIL memory is released.
* If an SSR already occurred, the memory beyond image_size
* remains assigned since PIL didn't own it.
*/
if (!ssr_already_occurred_since_boot) {
res = manage_unused_pil_region_memory(spss);
/* Set to true only if memory was successfully assigned*/
if (!res)
ssr_already_occurred_since_boot = true;
}
return res;
}
static int spss_stop(struct rproc *rproc)

View File

@@ -775,6 +775,51 @@ static void sysmon_stop(struct rproc_subdev *subdev, bool crashed)
del_timer_sync(&sysmon->timeout_data.timer);
}
static void sysmon_shutdown(struct rproc_subdev *subdev, bool crashed)
{
unsigned long timeout;
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon, subdev);
trace_rproc_qcom_event(dev_name(sysmon->rproc->dev.parent), SYSMON_SUBDEV_NAME,
crashed ? "crash stop" : "stop");
sysmon->shutdown_acked = false;
mutex_lock(&sysmon->state_lock);
sysmon->state = QCOM_SSR_BEFORE_SHUTDOWN;
sysmon->transaction_id++;
dev_info(sysmon->dev, "Incrementing tid for %s to %d\n", sysmon->name,
sysmon->transaction_id);
blocking_notifier_call_chain(&sysmon_notifiers, 0, (void *)sysmon);
mutex_unlock(&sysmon->state_lock);
/* Don't request graceful shutdown if we've crashed */
if (crashed)
return;
sysmon->timeout_data.timer.function = sysmon_shutdown_notif_timeout_handler;
timeout = jiffies + msecs_to_jiffies(SYSMON_NOTIF_TIMEOUT);
mod_timer(&sysmon->timeout_data.timer, timeout);
if (sysmon->ssctl_instance) {
if (!wait_for_completion_timeout(&sysmon->ssctl_comp, HZ / 2))
dev_err(sysmon->dev, "timeout waiting for ssctl service\n");
}
del_timer_sync(&sysmon->timeout_data.timer);
}
void qcom_sysmon_set_ops_stop(struct qcom_sysmon *sysmon, bool suspend)
{
if (suspend)
sysmon->subdev.stop = sysmon_shutdown;
else
sysmon->subdev.stop = sysmon_stop;
}
EXPORT_SYMBOL_GPL(qcom_sysmon_set_ops_stop);
static void sysmon_unprepare(struct rproc_subdev *subdev)
{
struct qcom_sysmon *sysmon = container_of(subdev, struct qcom_sysmon,

View File

@@ -5402,14 +5402,20 @@ static void ufs_qcom_hook_prepare_command(void *param, struct ufs_hba *hba,
#if IS_ENABLED(CONFIG_QTI_CRYPTO_FDE)
struct ice_data_setting setting;
if (!crypto_qti_ice_config_start(rq, &setting)) {
if ((rq_data_dir(rq) == WRITE) ? setting.encr_bypass : setting.decr_bypass) {
lrbp->crypto_key_slot = -1;
} else {
lrbp->crypto_key_slot = setting.crypto_data.key_index;
lrbp->data_unit_num = rq->bio->bi_iter.bi_sector >>
ICE_CRYPTO_DATA_UNIT_4_KB;
if (!rq->crypt_keyslot) {
if (!crypto_qti_ice_config_start(rq, &setting)) {
if ((rq_data_dir(rq) == WRITE) ? setting.encr_bypass :
setting.decr_bypass) {
lrbp->crypto_key_slot = -1;
} else {
lrbp->crypto_key_slot = setting.crypto_data.key_index;
lrbp->data_unit_num = rq->bio->bi_iter.bi_sector >>
ICE_CRYPTO_DATA_UNIT_4_KB;
}
}
} else {
lrbp->crypto_key_slot = blk_ksm_get_slot_idx(rq->crypt_keyslot);
lrbp->data_unit_num = rq->crypt_ctx->bc_dun[0];
}
#endif
}

View File

@@ -186,6 +186,7 @@ int ufshcd_qti_hba_init_crypto_capabilities(struct ufs_hba *hba)
{
int cap_idx;
int err = 0;
unsigned int max_slots = 0;
enum blk_crypto_mode_num blk_mode_num;
/*
@@ -212,9 +213,27 @@ int ufshcd_qti_hba_init_crypto_capabilities(struct ufs_hba *hba)
goto out;
}
max_slots = hba->crypto_capabilities.config_count + 1;
#if IS_ENABLED(CONFIG_QTI_CRYPTO_FDE)
if (max_slots > crypto_qti_ice_get_num_fde_slots()) {
/*
* Reduce the total number of slots available to FBE
* (by the number reserved for the FDE)
* Check at least one slot for backward compatibility,
* otherwise return failure
*/
if (max_slots - crypto_qti_ice_get_num_fde_slots() < 1) {
pr_err("%s: Too much slots allocated to fde\n", __func__);
err = -EINVAL;
goto out;
} else {
max_slots = max_slots - crypto_qti_ice_get_num_fde_slots();
}
}
#endif
/* The actual number of configurations supported is (CFGC+1) */
err = devm_blk_ksm_init(hba->dev, &hba->ksm,
hba->crypto_capabilities.config_count + 1);
err = devm_blk_ksm_init(hba->dev, &hba->ksm, max_slots);
if (err)
goto out;

View File

@@ -614,7 +614,8 @@ static void hab_recv_unimport_msg(struct physical_channel *pchan, int vchan_exis
static int hab_try_get_vchan(struct physical_channel *pchan,
struct hab_header *header,
struct virtual_channel **vchan_out)
struct virtual_channel **vchan_out,
int *need_ret)
{
struct virtual_channel *vchan = NULL;
size_t sizebytes = HAB_HEADER_GET_SIZE(*header);
@@ -644,6 +645,7 @@ static int hab_try_get_vchan(struct physical_channel *pchan,
*/
vchan = hab_vchan_get(pchan, header);
if (!vchan) {
*need_ret = 1;
pr_debug("vchan not found type %d vcid %x sz %zx sesn %d\n",
payload_type, vchan_id, sizebytes, session_id);
@@ -661,6 +663,7 @@ static int hab_try_get_vchan(struct physical_channel *pchan,
}
return -EINVAL;
} else if (vchan->otherend_closed) {
*need_ret = 1;
hab_vchan_put(vchan);
pr_info("vchan remote closed type %d, vchan id %x, sizebytes %zx, session %d\n",
payload_type, vchan_id,
@@ -675,6 +678,7 @@ static int hab_try_get_vchan(struct physical_channel *pchan,
}
} else {
if (sizebytes != sizeof(struct hab_open_send_data)) {
*need_ret = 1;
pr_err("%s Invalid open req type %d vcid %x bytes %zx session %d\n",
pchan->name, payload_type, vchan_id,
sizebytes, session_id);
@@ -712,9 +716,10 @@ int hab_msg_recv(struct physical_channel *pchan,
int found = 0;
struct hab_import_data imp_data = {0};
int irqs_disabled = irqs_disabled();
int need_ret = 0;
ret = hab_try_get_vchan(pchan, header, &vchan);
if (ret != 0 || ((vchan == NULL) && (payload_type == HAB_PAYLOAD_TYPE_UNIMPORT)))
ret = hab_try_get_vchan(pchan, header, &vchan, &need_ret);
if (need_ret)
return ret;
switch (payload_type) {

View File

@@ -511,10 +511,9 @@ static int hgsl_alloc_pages(struct device *dev, uint32_t requested_pcount,
for (i = 0; i < pcount; i++)
pages[i] = nth_page(page, i);
_dma_cache_op(dev, page, pcount, GSL_CACHEFLAGS_FLUSH);
}
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
mod_node_page_state(page_pgdat(page), NR_KERNEL_MISC_RECLAIMABLE,
(1 << order));
}
return pcount;
}

View File

@@ -968,7 +968,6 @@ static void md_dump_data(unsigned long addr, int nbytes, const char *name)
static void md_reg_context_data(struct pt_regs *regs)
{
unsigned int i;
int nbytes = 128;
if (user_mode(regs) || !regs->pc)
@@ -977,12 +976,6 @@ static void md_reg_context_data(struct pt_regs *regs)
md_dump_data(regs->pc - nbytes, nbytes * 2, "PC");
md_dump_data(regs->regs[30] - nbytes, nbytes * 2, "LR");
md_dump_data(regs->sp - nbytes, nbytes * 2, "SP");
for (i = 0; i < 30; i++) {
char name[4];
snprintf(name, sizeof(name), "X%u", i);
md_dump_data(regs->regs[i] - nbytes, nbytes * 2, name);
}
}
static inline void md_dump_panic_regs(void)

View File

@@ -1318,7 +1318,7 @@ static int init_lplh_notif(const char *buf)
return -EINVAL;
cp = buf;
if (sscanf(cp, INIT ":%hu", &nClusters)) {
if (!nClusters)
if (!nClusters || nClusters > LPLH_CLUSTER_MAX_CNT)
return -EINVAL;
*ptmp++ = nClusters;
@@ -1358,7 +1358,7 @@ static int init_lplh_notif(const char *buf)
while ((cp1 = strpbrk(cp1 + 1, ",")))
nValues++;
if (nValues % 2 != 0)
if (nValues % 2 != 0 || LPLH_IPC_FREQ_VTBL_MAX_CNT < nValues/2)
return -EINVAL;
*ptmp++ = nValues/2;

View File

@@ -124,6 +124,7 @@ static int subsys_suspend(struct subsystem_data *ss_data, struct rproc *rproc, u
case SUBSYS_DEEPSLEEP:
case SUBSYS_HIBERNATE:
ss_data->ignore_ssr = true;
adsp_set_ops_stop(rproc, true);
rproc_shutdown(rproc);
ss_data->ignore_ssr = false;
break;
@@ -144,6 +145,7 @@ static int subsys_resume(struct subsystem_data *ss_data, struct rproc *rproc, u3
case SUBSYS_DEEPSLEEP:
case SUBSYS_HIBERNATE:
ss_data->ignore_ssr = true;
adsp_set_ops_stop(rproc, false);
ret = rproc_boot(rproc);
ss_data->ignore_ssr = false;
break;
@@ -571,6 +573,12 @@ static int power_state_probe(struct platform_device *pdev)
if (!drv)
return -ENOMEM;
if (IS_ENABLED(CONFIG_NOTIFY_AOP)) {
drv->qmp = qmp_get(&pdev->dev);
if (IS_ERR(drv->qmp))
return -EPROBE_DEFER;
}
drv->ps_pm_nb.notifier_call = ps_pm_cb;
drv->ps_pm_nb.priority = PS_PM_NOTIFIER_PRIORITY;
ret = register_pm_notifier(&drv->ps_pm_nb);
@@ -599,7 +607,7 @@ static int power_state_probe(struct platform_device *pdev)
goto remove_ss;
}
ss_data->name = name;
ss_data->name = kstrdup_const(name, GFP_KERNEL);
ss_data->rproc_handle = rproc_handle;
ss_data->ps_ssr_nb.notifier_call = ps_ssr_cb;
@@ -625,14 +633,6 @@ static int power_state_probe(struct platform_device *pdev)
list_add_tail(&ss_data->list, &drv->sub_sys_list);
}
if (IS_ENABLED(CONFIG_NOTIFY_AOP)) {
drv->qmp = qmp_get(&pdev->dev);
if (IS_ERR(drv->qmp)) {
ret = PTR_ERR(drv->qmp);
goto remove_ss;
}
}
ret = power_state_dev_init(drv);
if (ret)
goto remove_ss;

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2016-2018, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
@@ -28,8 +28,25 @@
#define SOLVER_PRESENT 1
#define HW_CHANNEL_PRESENT 2
#define CMD_DB_MAX_RESOURCES 250
struct rsc_drv;
/**
* struct cache_req: the request object for caching
*
* @addr: the address of the resource
* @sleep_val: the sleep vote
* @wake_val: the wake vote
* @list: linked list obj
*/
struct cache_req {
u32 addr;
u32 sleep_val;
u32 wake_val;
struct list_head list;
};
/**
* struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
* to the controller
@@ -70,20 +87,17 @@ struct tcs_group {
* @cmd: the payload that will be part of the @msg
* @completion: triggered when request is done
* @dev: the device making the request
* @needs_free: check to free dynamically allocated request object
*/
struct rpmh_request {
struct tcs_request msg;
struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
struct completion *completion;
const struct device *dev;
bool needs_free;
};
/**
* struct rpmh_ctrlr: our representation of the controller
*
* @cache: the list of cached requests
* @cache_lock: synchronize access to the cache data
* @dirty: was the cache updated since flush
* @in_solver_mode: Controller is busy in solver mode
@@ -91,12 +105,13 @@ struct rpmh_request {
* @batch_cache: Cache sleep and wake requests sent as batch
*/
struct rpmh_ctrlr {
struct list_head cache;
spinlock_t cache_lock;
bool dirty;
bool in_solver_mode;
u32 flags;
struct list_head batch_cache;
struct rpmh_request batch_cache[RPMH_ACTIVE_ONLY_STATE];
u32 non_batch_cache_idx;
struct cache_req *non_batch_cache;
};
/**

View File

@@ -704,11 +704,22 @@ static int find_free_tcs(struct tcs_group *tcs)
const struct rsc_drv *drv = tcs->drv;
unsigned long i;
unsigned long max = tcs->offset + tcs->num_tcs;
int timeout = 100;
i = find_next_zero_bit(drv->tcs_in_use, max, tcs->offset);
if (i >= max)
return -EBUSY;
while (timeout) {
if (read_tcs_reg(drv, drv->regs[RSC_DRV_STATUS], i))
break;
timeout--;
udelay(1);
}
if (!timeout)
return -EBUSY;
return i;
}
@@ -791,17 +802,20 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg, int c
tcs->req[tcs_id - tcs->offset] = msg;
set_bit(tcs_id, drv->tcs_in_use);
if (msg->state == RPMH_ACTIVE_ONLY_STATE && tcs->type != ACTIVE_TCS) {
/*
* Clear previously programmed WAKE commands in selected
* repurposed TCS to avoid triggering them. tcs->slots will be
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
*/
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0);
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_WAIT_FOR_CMPL], tcs_id, 0);
/*
* Clear previously programmed ACTIVE/WAKE commands in selected
* repurposed TCS to avoid triggering them. tcs->slots will be
* cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate()
*/
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0);
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_WAIT_FOR_CMPL], tcs_id, 0);
if (msg->wait_for_compl || (msg->state == RPMH_ACTIVE_ONLY_STATE &&
tcs->type != ACTIVE_TCS))
enable_tcs_irq(drv, tcs_id, true);
}
spin_unlock_irqrestore(&drv->lock, flags);
else
enable_tcs_irq(drv, tcs_id, false);
/*
* These two can be done after the lock is released because:
@@ -813,7 +827,16 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg, int c
*/
__tcs_buffer_write(drv, tcs_id, 0, msg);
__tcs_set_trigger(drv, tcs_id, true);
ipc_log_string(drv->ipc_log_ctx, "TCS trigger: m=%d", tcs_id);
ipc_log_string(drv->ipc_log_ctx, "TCS trigger: m=%d wait_for_compl=%u",
tcs_id, msg->wait_for_compl);
if (!msg->wait_for_compl)
clear_bit(tcs_id, drv->tcs_in_use);
spin_unlock_irqrestore(&drv->lock, flags);
if (!msg->wait_for_compl)
wake_up(&drv->tcs_wait);
return 0;
}
@@ -1195,6 +1218,13 @@ int rpmh_rsc_is_tcs_completed(struct rsc_drv *drv, int ch)
sts &= CH1_WAKE_TCS_STATUS;
retry--;
/*
* Wait till all the WAKE votes of the new channel are
* applied during channel switch.
* Maximum delay of 100 usec.
*/
if (!sts)
udelay(10);
} while (!sts && retry);
if (!retry) {
@@ -1586,7 +1616,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
struct rsc_drv_top *rsc_top;
int ret, irq;
u32 rsc_id, major_ver, minor_ver, solver_config;
int i, drv_count;
int i, j, drv_count;
const char *name;
/*
@@ -1717,6 +1747,13 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
spin_lock_init(&drv[i].lock);
init_waitqueue_head(&drv[i].tcs_wait);
bitmap_zero(drv[i].tcs_in_use, MAX_TCS_NR);
drv[i].client.non_batch_cache = devm_kcalloc(&pdev->dev, CMD_DB_MAX_RESOURCES,
sizeof(struct cache_req), GFP_KERNEL);
if (!drv[i].client.non_batch_cache)
return -ENOMEM;
for (j = 0; j < CMD_DB_MAX_RESOURCES; j++)
INIT_LIST_HEAD(&drv[i].client.non_batch_cache[j].list);
irq = platform_get_irq(pdev, drv[i].id);
if (irq < 0)
@@ -1731,8 +1768,6 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
return ret;
spin_lock_init(&drv[i].client.cache_lock);
INIT_LIST_HEAD(&drv[i].client.cache);
INIT_LIST_HEAD(&drv[i].client.batch_cache);
drv[i].ipc_log_ctx = ipc_log_context_create(
RSC_DRV_IPC_LOG_SIZE,

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2018, 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/atomic.h>
@@ -36,40 +36,10 @@
.cmd = { { 0 } }, \
.completion = q, \
.dev = device, \
.needs_free = false, \
}
#define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
/**
* struct cache_req: the request object for caching
*
* @addr: the address of the resource
* @sleep_val: the sleep vote
* @wake_val: the wake vote
* @list: linked list obj
*/
struct cache_req {
u32 addr;
u32 sleep_val;
u32 wake_val;
struct list_head list;
};
/**
* struct batch_cache_req - An entry in our batch catch
*
* @list: linked list obj
* @count: number of messages
* @rpm_msgs: the messages
*/
struct batch_cache_req {
struct list_head list;
int count;
struct rpmh_request *rpm_msgs;
};
static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
{
struct rsc_drv *drv = dev_get_drvdata(dev->parent);
@@ -108,30 +78,32 @@ void rpmh_tx_done(const struct tcs_request *msg)
struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
msg);
struct completion *compl = rpm_msg->completion;
bool free = rpm_msg->needs_free;
if (!compl)
goto exit;
return;
/* Signal the blocking thread we are done */
complete(compl);
exit:
if (free)
kfree(rpm_msg);
}
static struct cache_req *__find_req(struct rpmh_ctrlr *ctrlr, u32 addr)
static struct cache_req *get_non_batch_cache_req(struct rpmh_ctrlr *ctrlr, u32 addr)
{
struct cache_req *p, *req = NULL;
struct cache_req *req = ctrlr->non_batch_cache;
int i;
list_for_each_entry(p, &ctrlr->cache, list) {
if (p->addr == addr) {
req = p;
break;
}
if (ctrlr->non_batch_cache_idx >= CMD_DB_MAX_RESOURCES)
return NULL;
for (i = 0; i < ctrlr->non_batch_cache_idx; i++) {
req = &ctrlr->non_batch_cache[i];
if (req->addr == addr)
return req;
}
req = &ctrlr->non_batch_cache[ctrlr->non_batch_cache_idx];
req->sleep_val = req->wake_val = UINT_MAX;
ctrlr->non_batch_cache_idx++;
return req;
}
@@ -144,21 +116,14 @@ static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
u32 old_sleep_val, old_wake_val;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
req = __find_req(ctrlr, cmd->addr);
if (req)
goto existing;
req = kzalloc(sizeof(*req), GFP_ATOMIC);
req = get_non_batch_cache_req(ctrlr, cmd->addr);
if (!req) {
req = ERR_PTR(-ENOMEM);
goto unlock;
}
req->addr = cmd->addr;
req->sleep_val = req->wake_val = UINT_MAX;
list_add_tail(&req->list, &ctrlr->cache);
existing:
old_sleep_val = req->sleep_val;
old_wake_val = req->wake_val;
@@ -255,29 +220,23 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
int rpmh_write_async(const struct device *dev, enum rpmh_state state,
const struct tcs_cmd *cmd, u32 n)
{
DEFINE_RPMH_MSG_ONSTACK(dev, state, NULL, rpm_msg);
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
struct rpmh_request *rpm_msg;
int ret;
if (rpmh_standalone)
return 0;
rpm_msg.msg.wait_for_compl = false;
ret = check_ctrlr_state(ctrlr, state);
if (ret)
return ret;
rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC);
if (!rpm_msg)
return -ENOMEM;
rpm_msg->needs_free = true;
ret = __fill_rpmh_msg(rpm_msg, state, cmd, n);
if (ret) {
kfree(rpm_msg);
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, n);
if (ret)
return ret;
}
return __rpmh_write(dev, state, rpm_msg);
return __rpmh_write(dev, state, &rpm_msg);
}
EXPORT_SYMBOL(rpmh_write_async);
@@ -324,35 +283,18 @@ int rpmh_write(const struct device *dev, enum rpmh_state state,
}
EXPORT_SYMBOL(rpmh_write);
static void cache_batch(struct rpmh_ctrlr *ctrlr, struct batch_cache_req *req)
{
unsigned long flags;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
list_add_tail(&req->list, &ctrlr->batch_cache);
ctrlr->dirty = true;
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
}
static int flush_batch(struct rpmh_ctrlr *ctrlr, int ch)
{
struct batch_cache_req *req;
const struct rpmh_request *rpm_msg;
int ret = 0;
int i;
int ret;
/* Send Sleep/Wake requests to the controller, expect no response */
list_for_each_entry(req, &ctrlr->batch_cache, list) {
for (i = 0; i < req->count; i++) {
rpm_msg = req->rpm_msgs + i;
ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
&rpm_msg->msg, ch);
if (ret)
break;
}
}
/* Send Sleep/Wake requests to the controller, expect no response IRQ */
ret = rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
&ctrlr->batch_cache[RPMH_SLEEP_STATE].msg, ch);
if (ret)
return ret;
return ret;
return rpmh_rsc_write_ctrl_data(ctrlr_to_drv(ctrlr),
&ctrlr->batch_cache[RPMH_WAKE_ONLY_STATE].msg, ch);
}
/**
@@ -375,14 +317,10 @@ static int flush_batch(struct rpmh_ctrlr *ctrlr, int ch)
int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
const struct tcs_cmd *cmd, u32 *n)
{
struct batch_cache_req *req;
struct rpmh_request *rpm_msgs;
struct completion *compls;
DECLARE_COMPLETION_ONSTACK(compl);
DEFINE_RPMH_MSG_ONSTACK(dev, state, &compl, rpm_msg);
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
unsigned long time_left;
int count = 0;
int ret, i, ch;
void *ptr;
int ret, ch;
if (rpmh_standalone)
return 0;
@@ -391,73 +329,46 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
if (ret)
return ret;
if (!cmd || !n)
return -EINVAL;
if (state == RPMH_ACTIVE_ONLY_STATE) {
ret = __fill_rpmh_msg(&rpm_msg, state, cmd, *n);
if (ret)
return ret;
} else {
memset(&ctrlr->batch_cache[state], 0, sizeof(struct rpmh_request));
ret = __fill_rpmh_msg(&ctrlr->batch_cache[state], state, cmd, *n);
if (ret)
return ret;
while (n[count] > 0)
count++;
if (!count)
return -EINVAL;
spin_lock(&ctrlr->cache_lock);
ctrlr->dirty = true;
spin_unlock(&ctrlr->cache_lock);
ptr = kzalloc(sizeof(*req) +
count * (sizeof(req->rpm_msgs[0]) + sizeof(*compls)),
GFP_ATOMIC);
if (!ptr)
return -ENOMEM;
req = ptr;
rpm_msgs = ptr + sizeof(*req);
compls = ptr + sizeof(*req) + count * sizeof(*rpm_msgs);
req->count = count;
req->rpm_msgs = rpm_msgs;
for (i = 0; i < count; i++) {
__fill_rpmh_msg(rpm_msgs + i, state, cmd, n[i]);
cmd += n[i];
}
if (state != RPMH_ACTIVE_ONLY_STATE) {
cache_batch(ctrlr, req);
return 0;
}
ch = rpmh_rsc_get_channel(ctrlr_to_drv(ctrlr));
if (ch < 0) {
kfree(ptr);
if (ch < 0)
return ch;
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg.msg, ch);
if (ret) {
pr_err("Error(%d) sending RPMH message addr=%#x\n",
ret, rpm_msg.msg.cmds[0].addr);
return ret;
}
for (i = 0; i < count; i++) {
struct completion *compl = &compls[i];
init_completion(compl);
rpm_msgs[i].completion = compl;
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg, ch);
if (ret) {
pr_err("Error(%d) sending RPMH message addr=%#x\n",
ret, rpm_msgs[i].msg.cmds[0].addr);
break;
}
ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS);
if (!ret) {
/*
* Better hope they never finish because they'll signal
* the completion that we're going to free once
* we've returned from this function.
*/
rpmh_rsc_debug(ctrlr_to_drv(ctrlr), &compl);
BUG_ON(1);
}
time_left = RPMH_TIMEOUT_MS;
while (i--) {
time_left = wait_for_completion_timeout(&compls[i], time_left);
if (!time_left) {
/*
* Better hope they never finish because they'll signal
* the completion that we're going to free once
* we've returned from this function.
*/
rpmh_rsc_debug(ctrlr_to_drv(ctrlr), &compls[i]);
BUG_ON(1);
}
}
kfree(ptr);
return ret;
return 0;
}
EXPORT_SYMBOL(rpmh_write_batch);
@@ -485,7 +396,7 @@ static int send_single(struct rpmh_ctrlr *ctrlr, enum rpmh_state state,
int _rpmh_flush(struct rpmh_ctrlr *ctrlr, int ch)
{
struct cache_req *p;
int ret = 0;
int ret = 0, i;
if (!ctrlr->dirty) {
pr_debug("Skipping flush, TCS has latest data.\n");
@@ -500,7 +411,8 @@ int _rpmh_flush(struct rpmh_ctrlr *ctrlr, int ch)
if (ret)
return ret;
list_for_each_entry(p, &ctrlr->cache, list) {
for (i = 0; i < ctrlr->non_batch_cache_idx; i++) {
p = &ctrlr->non_batch_cache[i];
if (!is_req_valid(p)) {
pr_debug("%s: skipping RPMH req: a:%#x s:%#x w:%#x\n",
__func__, p->addr, p->sleep_val, p->wake_val);
@@ -533,6 +445,7 @@ int _rpmh_flush(struct rpmh_ctrlr *ctrlr, int ch)
*/
int rpmh_flush(struct rpmh_ctrlr *ctrlr, int ch)
{
unsigned long flags;
int ret;
if (rpmh_standalone)
@@ -552,14 +465,9 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr, int ch)
if (!(ctrlr->flags & SOLVER_PRESENT))
lockdep_assert_irqs_disabled();
/*
* If the lock is busy it means another transaction is on going,
* in such case it's better to abort than spin.
*/
if (!spin_trylock(&ctrlr->cache_lock))
return -EBUSY;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
ret = _rpmh_flush(ctrlr, ch);
spin_unlock(&ctrlr->cache_lock);
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
return ret;
}
@@ -628,19 +536,14 @@ EXPORT_SYMBOL(rpmh_write_sleep_and_wake_no_child);
void rpmh_invalidate(const struct device *dev)
{
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
struct batch_cache_req *req, *tmp;
unsigned long flags;
if (rpmh_standalone)
return;
spin_lock_irqsave(&ctrlr->cache_lock, flags);
list_for_each_entry_safe(req, tmp, &ctrlr->batch_cache, list) {
list_del(&req->list);
kfree(req);
}
INIT_LIST_HEAD(&ctrlr->batch_cache);
memset(&ctrlr->batch_cache[RPMH_SLEEP_STATE], 0, sizeof(struct rpmh_request));
memset(&ctrlr->batch_cache[RPMH_WAKE_ONLY_STATE], 0, sizeof(struct rpmh_request));
ctrlr->dirty = true;
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
}

View File

@@ -1051,10 +1051,15 @@ static ssize_t slatecom_char_write(struct file *f, const char __user *buf,
unsigned char qcli_cmnd;
uint32_t opcode;
int ret = 0;
struct slatedaemon_priv *dev = container_of(slatecom_intf_drv,
struct slatedaemon_priv *dev = NULL;
if (!slatecom_intf_drv) {
pr_err("Invalid use-case, slatecom driver is not ready\n");
return -EINVAL;
}
dev = container_of(slatecom_intf_drv,
struct slatedaemon_priv,
lhndl);
if (copy_from_user(&qcli_cmnd, buf, sizeof(unsigned char)))
return -EFAULT;

View File

@@ -352,7 +352,7 @@ static int slatecom_transfer(void *handle, uint8_t *tx_buf,
struct spi_transfer *tx_xfer;
struct slate_spi_priv *slate_spi;
struct slate_context *cntx;
struct spi_device *spi;
struct spi_device *spi = NULL;
int ret = 0;
if (!handle || !tx_buf)
@@ -428,8 +428,11 @@ void send_event(enum slatecom_event_type event,
void slatecom_slatedown_handler(void)
{
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!is_slatecom_ready())
return;
spi = get_spi_device();
g_slav_status_reg = 0;
atomic_set(&ok_to_sleep, 0);
pm_runtime_get_sync(&spi->dev);
@@ -863,7 +866,7 @@ int slatecom_ahb_read(void *handle, uint32_t ahb_start_addr,
int ret = 0;
uint8_t cmnd = 0;
uint32_t ahb_addr = 0;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!handle || !read_buf || num_words == 0
|| num_words > SLATE_SPI_MAX_WORDS) {
@@ -877,7 +880,7 @@ int slatecom_ahb_read(void *handle, uint32_t ahb_start_addr,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -928,7 +931,7 @@ int slatecom_ahb_write_bytes(void *handle, uint32_t ahb_start_addr,
uint8_t cmnd = 0;
uint32_t ahb_addr = 0;
uint32_t curr_num_bytes;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!handle || !write_buf || num_bytes == 0
|| num_bytes > (SLATE_SPI_MAX_WORDS * sizeof(int))) {
@@ -943,7 +946,7 @@ int slatecom_ahb_write_bytes(void *handle, uint32_t ahb_start_addr,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -998,7 +1001,7 @@ int slatecom_ahb_write(void *handle, uint32_t ahb_start_addr,
uint32_t ahb_addr = 0;
uint32_t curr_num_words;
uint32_t curr_num_bytes;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!handle || !write_buf || num_words == 0
|| num_words > SLATE_SPI_MAX_WORDS) {
@@ -1013,7 +1016,7 @@ int slatecom_ahb_write(void *handle, uint32_t ahb_start_addr,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -1062,13 +1065,11 @@ int slatecom_fifo_write(void *handle, uint32_t num_words,
uint32_t size;
int ret = 0;
uint8_t cmnd = 0;
struct spi_device *spi;
struct spi_device *spi = NULL;
if (!is_slatecom_ready())
return -ENODEV;
spi = get_spi_device();
if (!handle || !write_buf || num_words == 0
|| num_words > SLATE_SPI_MAX_WORDS) {
SLATECOM_ERR("Invalid param\n");
@@ -1079,7 +1080,7 @@ int slatecom_fifo_write(void *handle, uint32_t num_words,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -1116,7 +1117,7 @@ int slatecom_fifo_read(void *handle, uint32_t num_words,
uint32_t size;
uint8_t cmnd = 0;
int ret = 0;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!handle || !read_buf || num_words == 0
|| num_words > SLATE_SPI_MAX_WORDS) {
@@ -1131,7 +1132,7 @@ int slatecom_fifo_read(void *handle, uint32_t num_words,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -1216,8 +1217,9 @@ int slatecom_reg_write(void *handle, uint8_t reg_start_addr,
uint8_t num_regs, void *write_buf)
{
int ret = 0;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);
@@ -1294,7 +1296,7 @@ int slatecom_reg_read(void *handle, uint8_t reg_start_addr,
uint32_t size;
int ret = 0;
uint8_t cmnd = 0;
struct spi_device *spi = get_spi_device();
struct spi_device *spi = NULL;
if (!handle || !read_buf || num_regs == 0
|| num_regs > SLATE_SPI_MAX_REGS) {
@@ -1309,7 +1311,7 @@ int slatecom_reg_read(void *handle, uint8_t reg_start_addr,
SLATECOM_ERR("Device busy\n");
return -EBUSY;
}
spi = get_spi_device();
pm_runtime_get_sync(&spi->dev);
mutex_lock(&slate_task_mutex);

View File

@@ -2,7 +2,7 @@
/*
* Copyright (c) 2009-2017, 2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, Linaro Ltd.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/debugfs.h>
@@ -371,10 +371,14 @@ struct smem_image_version {
int num_parts = 0; \
int str_pos = 0, i = 0, ret = 0; \
num_parts = socinfo_get_part_count(part_enum); \
if (num_parts <= 0) \
return -EINVAL; \
part_info = kmalloc_array(num_parts, sizeof(*part_info), GFP_KERNEL); \
ret = socinfo_get_subpart_info(part_enum, part_info, num_parts); \
if (ret < 0) \
if (ret < 0) { \
kfree(part_info); \
return -EINVAL; \
} \
for (i = 0; i < num_parts; i++) { \
str_pos += scnprintf(buf+str_pos, PAGE_SIZE-str_pos, "0x%x", \
part_info[i]); \
@@ -886,8 +890,9 @@ bool
socinfo_get_part_info(enum subset_part_type part)
{
uint32_t partinfo;
uint32_t num_parts = socinfo_get_num_subset_parts();
if (part >= NUM_PARTS_MAX) {
if ((part <= PART_UNKNOWN) || (part >= NUM_PARTS_MAX) || (part >= num_parts)) {
pr_err("Bad part number\n");
return false;
}
@@ -925,10 +930,11 @@ int
socinfo_get_part_count(enum subset_part_type part)
{
int part_count = 1;
uint32_t num_parts = socinfo_get_num_subset_parts();
/* TODO: part_count to be read from SMEM after firmware adds support */
if ((part <= PART_UNKNOWN) || (part >= NUM_PARTS_MAX)) {
if ((part <= PART_UNKNOWN) || (part >= NUM_PARTS_MAX) || (part >= num_parts)) {
pr_err("Bad part number\n");
return -EINVAL;
}
@@ -1249,6 +1255,7 @@ static const struct soc_id soc_id[] = {
{ 606, "MONACOAU_IVI"},
{ 607, "MONACOAU_SRV1L"},
{ 608, "CROW" },
{ 644, "CROW_LTE" },
};
static struct qcom_socinfo *qsocinfo;

View File

@@ -3876,13 +3876,65 @@ disable_sleep_clk:
return ret;
}
static void dwc3_msm_suspend_phy(struct dwc3_msm *mdwc)
{
bool can_suspend_ssphy, no_active_ss;
/*
* Synopsys Superspeed PHY does not support ss_phy_irq, so to detect
* any wakeup events in host mode PHY cannot be suspended.
* This Superspeed PHY can be suspended only in the following cases:
* 1. The core is not in host mode
* 2. A Highspeed device is connected but not a Superspeed device
*
*/
no_active_ss = (!mdwc->in_host_mode) || (mdwc->in_host_mode &&
((mdwc->hs_phy->flags & (PHY_HSFS_MODE | PHY_LS_MODE)) &&
!dwc3_msm_is_superspeed(mdwc)));
can_suspend_ssphy = dwc3_msm_get_max_speed(mdwc) >= USB_SPEED_SUPER &&
(!(mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) || no_active_ss);
/* Suspend SS PHY */
if (can_suspend_ssphy) {
if (mdwc->in_host_mode) {
u32 reg = dwc3_msm_read_reg(mdwc->base,
DWC3_GUSB3PIPECTL(0));
reg |= DWC3_GUSB3PIPECTL_DISRXDETU3;
dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0),
reg);
}
/* indicate phy about SS mode */
if (dwc3_msm_is_superspeed(mdwc))
mdwc->ss_phy->flags |= DEVICE_IN_SS_MODE;
usb_phy_set_suspend(mdwc->ss_phy, 1);
mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND;
} else if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) {
mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP;
}
/*
* When operating in HS host mode, check if pwr event IRQ is
* required for wakeup.
*/
if (mdwc->in_host_mode && (mdwc->use_pwr_event_for_wakeup
& PWR_EVENT_HS_WAKEUP))
mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP;
if (mdwc->lpm_flags & MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP) {
dwc3_msm_set_pwr_events(mdwc, true);
enable_irq(mdwc->wakeup_irq[PWR_EVNT_IRQ].irq);
}
}
static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse)
{
int ret;
struct dwc3 *dwc = NULL;
struct dwc3_event_buffer *evt;
struct usb_irq *uirq;
bool can_suspend_ssphy, no_active_ss;
if (mdwc->dwc3)
dwc = platform_get_drvdata(mdwc->dwc3);
@@ -3959,49 +4011,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool force_power_collapse)
/* Suspend HS PHY */
usb_phy_set_suspend(mdwc->hs_phy, 1);
/*
* Synopsys Superspeed PHY does not support ss_phy_irq, so to detect
* any wakeup events in host mode PHY cannot be suspended.
* This Superspeed PHY can be suspended only in the following cases:
* 1. The core is not in host mode
* 2. A Highspeed device is connected but not a Superspeed device
*/
no_active_ss = (!mdwc->in_host_mode) || (mdwc->in_host_mode &&
((mdwc->hs_phy->flags & (PHY_HSFS_MODE | PHY_LS_MODE)) &&
!dwc3_msm_is_superspeed(mdwc)));
can_suspend_ssphy = dwc3_msm_get_max_speed(mdwc) >= USB_SPEED_SUPER &&
(!(mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) || no_active_ss);
/* Suspend SS PHY */
if (can_suspend_ssphy) {
if (mdwc->in_host_mode) {
u32 reg = dwc3_msm_read_reg(mdwc->base,
DWC3_GUSB3PIPECTL(0));
reg |= DWC3_GUSB3PIPECTL_DISRXDETU3;
dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0),
reg);
}
/* indicate phy about SS mode */
if (dwc3_msm_is_superspeed(mdwc))
mdwc->ss_phy->flags |= DEVICE_IN_SS_MODE;
usb_phy_set_suspend(mdwc->ss_phy, 1);
mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND;
} else if (mdwc->use_pwr_event_for_wakeup & PWR_EVENT_SS_WAKEUP) {
mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP;
}
/*
* When operating in HS host mode, check if pwr event IRQ is
* required for wakeup.
*/
if (mdwc->in_host_mode && (mdwc->use_pwr_event_for_wakeup
& PWR_EVENT_HS_WAKEUP))
mdwc->lpm_flags |= MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP;
if (mdwc->lpm_flags & MDWC3_USE_PWR_EVENT_IRQ_FOR_WAKEUP) {
dwc3_msm_set_pwr_events(mdwc, true);
enable_irq(mdwc->wakeup_irq[PWR_EVNT_IRQ].irq);
}
dwc3_msm_suspend_phy(mdwc);
/* make sure above writes are completed before turning off clocks */
wmb();

View File

@@ -91,7 +91,6 @@ extern enum qcom_scm_custom_reset_type qcom_scm_custom_reset_type;
#define QCOM_SCM_VMID_MSS_MSA 0xF
#define QCOM_SCM_VMID_WLAN 0x18
#define QCOM_SCM_VMID_WLAN_CE 0x19
#define QCOM_SCM_VMID_CP_SPSS_SP 0x1A
#define QCOM_SCM_PERM_READ 0x4
#define QCOM_SCM_PERM_WRITE 0x2
#define QCOM_SCM_PERM_EXEC 0x1

View File

@@ -61,6 +61,14 @@ static inline int qcom_rproc_set_dtb_firmware(struct rproc *rproc, const char *d
{
return -EINVAL;
}
#endif
#if IS_ENABLED(CONFIG_QCOM_Q6V5_PAS)
void adsp_set_ops_stop(struct rproc *rproc, bool suspend);
#else
static inline void adsp_set_ops_stop(struct rproc *rproc, bool suspend) { }
#endif
#endif

View File

@@ -2,6 +2,7 @@
/*
* Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
/*
@@ -2585,6 +2586,8 @@ enum ipa_ep_desc_type_enum_v01 {
DATA_EP_DESC_TYPE_TETH_RMNET_PROD_V01 = 0x09,
DATA_EP_DESC_TYPE_EMB_FLOW_CTL_CONS_V01 = 0x0A,
DATA_EP_DESC_TYPE_EMB_FLOW_CTL_PROD_V01 = 0x0B,
DATA_EP_DESC_TYPE_TETH_LL_CONS_V01 = 0x0C,
DATA_EP_DESC_TYPE_TETH_LL_PROD_V01 = 0x0D,
IPA_EP_DESC_TYPE_ENUM_MAX_VAL_V01 = IPA_INT_MAX,
};

View File

@@ -1,17 +1,19 @@
qcom_wdt_core.ko
qcom_cpu_vendor_hooks.ko
clk-rpmh.ko
gcc-sdm845.ko
icc-rpmh.ko
qcom_ipcc.ko
qcom_ipc_logging.ko
qcom-pdc.ko
rpmh-regulator.ko
bwmon.ko
qcom_rpmh.ko
qcom-cpufreq-hw.ko
sched-walt.ko
clk-dummy.ko
clk-rpmh.ko
clk-qcom.ko
clk-dummy.ko
gdsc-regulator.ko
gcc-sdm845.ko
dispcc-sdm845.ko
cmd-db.ko
cqhci.ko
crypto-qti-common.ko
@@ -19,7 +21,6 @@ crypto-qti-hwkm.ko
dcc_v2.ko
dcvs_fp.ko
debug-regulator.ko
gdsc-regulator.ko
smp2p.ko
rproc_qcom_common.ko
qcom_pil_info.ko
@@ -31,6 +32,9 @@ qcom_smd.ko
mdt_loader.ko
hwkm.ko
icc-bcm-voter.ko
icc-rpmh.ko
qnoc-qos.ko
qnoc-sdm670.ko
icc-debug.ko
iommu-logger.ko
llcc-qcom.ko
@@ -54,9 +58,7 @@ qcom_llcc_pmu.ko
qcom-pmu-lib.ko
qcom-spmi-pmic.ko
spmi-pmic-arb.ko
qcom_rpmh.ko
qcom-scm.ko
qnoc-qos.ko
qrtr.ko
qti-regmap-debugfs.ko
regmap-spmi.ko