Qualcomm driver updates for v5.10
Replace the busy wait for free tcs slots in the RPMh driver with a sleeping wait and use memory barriers when writing the command registers. Add a bunch of SoC ids to the socinfo driver, fix an erro printin the apr driver and migrate llcc to devm_platform_ioremap_resource_byname(). -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAl9sEdIbHGJqb3JuLmFu ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3F4x8P/3EW9en9/ZGeNMAi6c9X 3/OcCtLBQlq6e9xvxyEEV5j0809u0/gTxOr09oupFw8cjKH76hU0Yc6Ag0tYN1tZ xoDDonCKvxpCuGlMzzG27G9EljbLpia4Nth+U0YaEAswNgYUwarqmFTjTdB4bd7d bOMrrjU34/uNas8PLKo5MOI3iywtE79XdjYsOLoDOPLib8r7MH2zK/Ux/UJN4I+v mQheg08LFOvsucFSy+r+haEwikUMvVgVCIGOApKK2+kIFsK31kqUc8udTrvuEi67 SD8hyJaeWR+HfVj/kkudLR+FzX49AauaFaCVxZ9ODO0iWpntSnWRP6q211oOWgwd eMKmZ7WH6RyaTN8PTKs78yuJ9+MYQUletnGbKt3npOUjfan9WsEnQrsh0JWT9rDb +d2IZ6USYdnzxOG0qsP5sbbpnVsGFYl+eABQ8/cvRr/W1lmHo+sdArcjAXcI65yc i6IHBnXmZJh6c5d/fUGyazBHpsmGIcL568PzmQ0EQCnHJcaH4SEgE8CPUnYFQtKG 5qzi/cLonXefQNZgbmb4fc60tqjUAQTjtS7IqsYFHV2rmueCPWFjj5fyuaB6CWQj e7lmTcHRHJl9EQYzZfEShMMwF5B6CnfNEkCBTZLE72ypodCyU8UNO6aF5FybtVhn 9hVWlAqnJCJfhIutuuKs6WYI =GI6C -----END PGP SIGNATURE----- Merge tag 'qcom-drivers-for-5.10' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers Qualcomm driver updates for v5.10 Replace the busy wait for free tcs slots in the RPMh driver with a sleeping wait and use memory barriers when writing the command registers. Add a bunch of SoC ids to the socinfo driver, fix an erro printin the apr driver and migrate llcc to devm_platform_ioremap_resource_byname(). * tag 'qcom-drivers-for-5.10' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: soc: qcom: llcc: use devm_platform_ioremap_resource_byname() soc: qcom: apr: Fixup the error displayed on lookup failure soc: qcom: socinfo: Add msm8992/4 and apq8094 SoC IDs soc: qcom: rpmh-rsc: Sleep waiting for tcs slots to be free soc: qcom-geni-se: Don't use relaxed writes when writing commands soc: qcom: socinfo: add SC7180 entry to soc_id array soc: qcom: socinfo: add soc id for IPQ6018 Link: https://lore.kernel.org/r/20200924040504.179708-1-bjorn.andersson@linaro.org Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
f8e87554b1
|
@ -328,7 +328,7 @@ static int of_apr_add_pd_lookups(struct device *dev)
|
||||||
|
|
||||||
pds = pdr_add_lookup(apr->pdr, service_name, service_path);
|
pds = pdr_add_lookup(apr->pdr, service_name, service_path);
|
||||||
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
|
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
|
||||||
dev_err(dev, "pdr add lookup failed: %d\n", ret);
|
dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
|
||||||
return PTR_ERR(pds);
|
return PTR_ERR(pds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,7 +387,6 @@ static int qcom_llcc_remove(struct platform_device *pdev)
|
||||||
static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
|
static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct regmap_config llcc_regmap_config = {
|
struct regmap_config llcc_regmap_config = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
|
@ -396,11 +395,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
|
||||||
.fast_io = true,
|
.fast_io = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
|
base = devm_platform_ioremap_resource_byname(pdev, name);
|
||||||
if (!res)
|
|
||||||
return ERR_PTR(-ENODEV);
|
|
||||||
|
|
||||||
base = devm_ioremap_resource(&pdev->dev, res);
|
|
||||||
if (IS_ERR(base))
|
if (IS_ERR(base))
|
||||||
return ERR_CAST(base);
|
return ERR_CAST(base);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define __RPM_INTERNAL_H__
|
#define __RPM_INTERNAL_H__
|
||||||
|
|
||||||
#include <linux/bitmap.h>
|
#include <linux/bitmap.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
#include <soc/qcom/tcs.h>
|
#include <soc/qcom/tcs.h>
|
||||||
|
|
||||||
#define TCS_TYPE_NR 4
|
#define TCS_TYPE_NR 4
|
||||||
|
@ -106,6 +107,8 @@ struct rpmh_ctrlr {
|
||||||
* @lock: Synchronize state of the controller. If RPMH's cache
|
* @lock: Synchronize state of the controller. If RPMH's cache
|
||||||
* lock will also be held, the order is: drv->lock then
|
* lock will also be held, the order is: drv->lock then
|
||||||
* cache_lock.
|
* cache_lock.
|
||||||
|
* @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a
|
||||||
|
* slot
|
||||||
* @client: Handle to the DRV's client.
|
* @client: Handle to the DRV's client.
|
||||||
*/
|
*/
|
||||||
struct rsc_drv {
|
struct rsc_drv {
|
||||||
|
@ -118,6 +121,7 @@ struct rsc_drv {
|
||||||
struct tcs_group tcs[TCS_TYPE_NR];
|
struct tcs_group tcs[TCS_TYPE_NR];
|
||||||
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
|
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
wait_queue_head_t tcs_wait;
|
||||||
struct rpmh_ctrlr client;
|
struct rpmh_ctrlr client;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
|
||||||
#include <soc/qcom/cmd-db.h>
|
#include <soc/qcom/cmd-db.h>
|
||||||
#include <soc/qcom/tcs.h>
|
#include <soc/qcom/tcs.h>
|
||||||
|
@ -453,6 +454,7 @@ skip:
|
||||||
if (!drv->tcs[ACTIVE_TCS].num_tcs)
|
if (!drv->tcs[ACTIVE_TCS].num_tcs)
|
||||||
enable_tcs_irq(drv, i, false);
|
enable_tcs_irq(drv, i, false);
|
||||||
spin_unlock(&drv->lock);
|
spin_unlock(&drv->lock);
|
||||||
|
wake_up(&drv->tcs_wait);
|
||||||
if (req)
|
if (req)
|
||||||
rpmh_tx_done(req, err);
|
rpmh_tx_done(req, err);
|
||||||
}
|
}
|
||||||
|
@ -571,43 +573,74 @@ static int find_free_tcs(struct tcs_group *tcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tcs_write() - Store messages into a TCS right now, or return -EBUSY.
|
* claim_tcs_for_req() - Claim a tcs in the given tcs_group; only for active.
|
||||||
* @drv: The controller.
|
* @drv: The controller.
|
||||||
|
* @tcs: The tcs_group used for ACTIVE_ONLY transfers.
|
||||||
* @msg: The data to be sent.
|
* @msg: The data to be sent.
|
||||||
*
|
*
|
||||||
* Grabs a TCS for ACTIVE_ONLY transfers and writes the messages to it.
|
* Claims a tcs in the given tcs_group while making sure that no existing cmd
|
||||||
|
* is in flight that would conflict with the one in @msg.
|
||||||
*
|
*
|
||||||
* If there are no free TCSes for ACTIVE_ONLY transfers or if a command for
|
* Context: Must be called with the drv->lock held since that protects
|
||||||
* the same address is already transferring returns -EBUSY which means the
|
* tcs_in_use.
|
||||||
* client should retry shortly.
|
|
||||||
*
|
*
|
||||||
* Return: 0 on success, -EBUSY if client should retry, or an error.
|
* Return: The id of the claimed tcs or -EBUSY if a matching msg is in flight
|
||||||
* Client should have interrupts enabled for a bit before retrying.
|
* or the tcs_group is full.
|
||||||
*/
|
*/
|
||||||
static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
|
static int claim_tcs_for_req(struct rsc_drv *drv, struct tcs_group *tcs,
|
||||||
|
const struct tcs_request *msg)
|
||||||
{
|
{
|
||||||
struct tcs_group *tcs;
|
|
||||||
int tcs_id;
|
|
||||||
unsigned long flags;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
tcs = get_tcs_for_msg(drv, msg);
|
|
||||||
if (IS_ERR(tcs))
|
|
||||||
return PTR_ERR(tcs);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&drv->lock, flags);
|
|
||||||
/*
|
/*
|
||||||
* The h/w does not like if we send a request to the same address,
|
* The h/w does not like if we send a request to the same address,
|
||||||
* when one is already in-flight or being processed.
|
* when one is already in-flight or being processed.
|
||||||
*/
|
*/
|
||||||
ret = check_for_req_inflight(drv, tcs, msg);
|
ret = check_for_req_inflight(drv, tcs, msg);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock;
|
return ret;
|
||||||
|
|
||||||
ret = find_free_tcs(tcs);
|
return find_free_tcs(tcs);
|
||||||
if (ret < 0)
|
}
|
||||||
goto unlock;
|
|
||||||
tcs_id = ret;
|
/**
|
||||||
|
* rpmh_rsc_send_data() - Write / trigger active-only message.
|
||||||
|
* @drv: The controller.
|
||||||
|
* @msg: The data to be sent.
|
||||||
|
*
|
||||||
|
* NOTES:
|
||||||
|
* - This is only used for "ACTIVE_ONLY" since the limitations of this
|
||||||
|
* function don't make sense for sleep/wake cases.
|
||||||
|
* - To do the transfer, we will grab a whole TCS for ourselves--we don't
|
||||||
|
* try to share. If there are none available we'll wait indefinitely
|
||||||
|
* for a free one.
|
||||||
|
* - This function will not wait for the commands to be finished, only for
|
||||||
|
* data to be programmed into the RPMh. See rpmh_tx_done() which will
|
||||||
|
* be called when the transfer is fully complete.
|
||||||
|
* - This function must be called with interrupts enabled. If the hardware
|
||||||
|
* is busy doing someone else's transfer we need that transfer to fully
|
||||||
|
* finish so that we can have the hardware, and to fully finish it needs
|
||||||
|
* the interrupt handler to run. If the interrupts is set to run on the
|
||||||
|
* active CPU this can never happen if interrupts are disabled.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -EINVAL on error.
|
||||||
|
*/
|
||||||
|
int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
|
||||||
|
{
|
||||||
|
struct tcs_group *tcs;
|
||||||
|
int tcs_id;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
tcs = get_tcs_for_msg(drv, msg);
|
||||||
|
if (IS_ERR(tcs))
|
||||||
|
return PTR_ERR(tcs);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&drv->lock, flags);
|
||||||
|
|
||||||
|
/* Wait forever for a free tcs. It better be there eventually! */
|
||||||
|
wait_event_lock_irq(drv->tcs_wait,
|
||||||
|
(tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
|
||||||
|
drv->lock);
|
||||||
|
|
||||||
tcs->req[tcs_id - tcs->offset] = msg;
|
tcs->req[tcs_id - tcs->offset] = msg;
|
||||||
set_bit(tcs_id, drv->tcs_in_use);
|
set_bit(tcs_id, drv->tcs_in_use);
|
||||||
|
@ -635,47 +668,6 @@ static int tcs_write(struct rsc_drv *drv, const struct tcs_request *msg)
|
||||||
__tcs_set_trigger(drv, tcs_id, true);
|
__tcs_set_trigger(drv, tcs_id, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
unlock:
|
|
||||||
spin_unlock_irqrestore(&drv->lock, flags);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rpmh_rsc_send_data() - Write / trigger active-only message.
|
|
||||||
* @drv: The controller.
|
|
||||||
* @msg: The data to be sent.
|
|
||||||
*
|
|
||||||
* NOTES:
|
|
||||||
* - This is only used for "ACTIVE_ONLY" since the limitations of this
|
|
||||||
* function don't make sense for sleep/wake cases.
|
|
||||||
* - To do the transfer, we will grab a whole TCS for ourselves--we don't
|
|
||||||
* try to share. If there are none available we'll wait indefinitely
|
|
||||||
* for a free one.
|
|
||||||
* - This function will not wait for the commands to be finished, only for
|
|
||||||
* data to be programmed into the RPMh. See rpmh_tx_done() which will
|
|
||||||
* be called when the transfer is fully complete.
|
|
||||||
* - This function must be called with interrupts enabled. If the hardware
|
|
||||||
* is busy doing someone else's transfer we need that transfer to fully
|
|
||||||
* finish so that we can have the hardware, and to fully finish it needs
|
|
||||||
* the interrupt handler to run. If the interrupts is set to run on the
|
|
||||||
* active CPU this can never happen if interrupts are disabled.
|
|
||||||
*
|
|
||||||
* Return: 0 on success, -EINVAL on error.
|
|
||||||
*/
|
|
||||||
int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = tcs_write(drv, msg);
|
|
||||||
if (ret == -EBUSY) {
|
|
||||||
pr_info_ratelimited("TCS Busy, retrying RPMH message send: addr=%#x\n",
|
|
||||||
msg->cmds[0].addr);
|
|
||||||
udelay(10);
|
|
||||||
}
|
|
||||||
} while (ret == -EBUSY);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -983,6 +975,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
spin_lock_init(&drv->lock);
|
spin_lock_init(&drv->lock);
|
||||||
|
init_waitqueue_head(&drv->tcs_wait);
|
||||||
bitmap_zero(drv->tcs_in_use, MAX_TCS_NR);
|
bitmap_zero(drv->tcs_in_use, MAX_TCS_NR);
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, drv->id);
|
irq = platform_get_irq(pdev, drv->id);
|
||||||
|
|
|
@ -194,6 +194,7 @@ static const struct soc_id soc_id[] = {
|
||||||
{ 186, "MSM8674" },
|
{ 186, "MSM8674" },
|
||||||
{ 194, "MSM8974PRO" },
|
{ 194, "MSM8974PRO" },
|
||||||
{ 206, "MSM8916" },
|
{ 206, "MSM8916" },
|
||||||
|
{ 207, "MSM8994" },
|
||||||
{ 208, "APQ8074-AA" },
|
{ 208, "APQ8074-AA" },
|
||||||
{ 209, "APQ8074-AB" },
|
{ 209, "APQ8074-AB" },
|
||||||
{ 210, "APQ8074PRO" },
|
{ 210, "APQ8074PRO" },
|
||||||
|
@ -214,6 +215,8 @@ static const struct soc_id soc_id[] = {
|
||||||
{ 248, "MSM8216" },
|
{ 248, "MSM8216" },
|
||||||
{ 249, "MSM8116" },
|
{ 249, "MSM8116" },
|
||||||
{ 250, "MSM8616" },
|
{ 250, "MSM8616" },
|
||||||
|
{ 251, "MSM8992" },
|
||||||
|
{ 253, "APQ8094" },
|
||||||
{ 291, "APQ8096" },
|
{ 291, "APQ8096" },
|
||||||
{ 305, "MSM8996SG" },
|
{ 305, "MSM8996SG" },
|
||||||
{ 310, "MSM8996AU" },
|
{ 310, "MSM8996AU" },
|
||||||
|
@ -223,6 +226,8 @@ static const struct soc_id soc_id[] = {
|
||||||
{ 321, "SDM845" },
|
{ 321, "SDM845" },
|
||||||
{ 341, "SDA845" },
|
{ 341, "SDA845" },
|
||||||
{ 356, "SM8250" },
|
{ 356, "SM8250" },
|
||||||
|
{ 402, "IPQ6018" },
|
||||||
|
{ 425, "SC7180" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
||||||
|
|
|
@ -296,7 +296,7 @@ static inline void geni_se_setup_m_cmd(struct geni_se *se, u32 cmd, u32 params)
|
||||||
u32 m_cmd;
|
u32 m_cmd;
|
||||||
|
|
||||||
m_cmd = (cmd << M_OPCODE_SHFT) | (params & M_PARAMS_MSK);
|
m_cmd = (cmd << M_OPCODE_SHFT) | (params & M_PARAMS_MSK);
|
||||||
writel_relaxed(m_cmd, se->base + SE_GENI_M_CMD0);
|
writel(m_cmd, se->base + SE_GENI_M_CMD0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -316,7 +316,7 @@ static inline void geni_se_setup_s_cmd(struct geni_se *se, u32 cmd, u32 params)
|
||||||
s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
|
s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
|
||||||
s_cmd |= (cmd << S_OPCODE_SHFT);
|
s_cmd |= (cmd << S_OPCODE_SHFT);
|
||||||
s_cmd |= (params & S_PARAMS_MSK);
|
s_cmd |= (params & S_PARAMS_MSK);
|
||||||
writel_relaxed(s_cmd, se->base + SE_GENI_S_CMD0);
|
writel(s_cmd, se->base + SE_GENI_S_CMD0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue