Re: [PATCH V3 3/4] firmware: tegra: add bpmp driver for Tegra210

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 24/01/2019 17:03, Timo Alho wrote:
> This patch adds driver for Tegra210 BPMP firmware.
> 
> The BPMP is a specific processor in Tegra210 chip, which runs firmware
> for assisting in entering deep low power states (suspend to ram), and
> offloading DRAM memory clock scaling on some platforms.
> 
> Based on work by Sivaram Nair <sivaramn@xxxxxxxxxx>
> 
> Signed-off-by: Timo Alho <talho@xxxxxxxxxx>
> ---
>  drivers/firmware/tegra/Makefile       |   1 +
>  drivers/firmware/tegra/bpmp-private.h |   1 +
>  drivers/firmware/tegra/bpmp-t210.c    | 245 ++++++++++++++++++++++++++++++++++
>  drivers/firmware/tegra/bpmp.c         |  46 +++++--
>  include/soc/tegra/bpmp.h              |   1 +
>  5 files changed, 285 insertions(+), 9 deletions(-)
>  create mode 100644 drivers/firmware/tegra/bpmp-t210.c
> 
> diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
> index 367d482..dc41d6f 100644
> --- a/drivers/firmware/tegra/Makefile
> +++ b/drivers/firmware/tegra/Makefile
> @@ -1,5 +1,6 @@
>  tegra-bpmp-y			= bpmp.o
>  tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC)	+= bpmp-t186.o
> +tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC)	+= bpmp-t210.o
>  tegra-bpmp-$(CONFIG_DEBUG_FS)	+= bpmp-debugfs.o
>  obj-$(CONFIG_TEGRA_BPMP)	+= tegra-bpmp.o
>  obj-$(CONFIG_TEGRA_IVC)		+= ivc.o
> diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h
> index 2354337..5132234 100644
> --- a/drivers/firmware/tegra/bpmp-private.h
> +++ b/drivers/firmware/tegra/bpmp-private.h
> @@ -24,5 +24,6 @@ struct tegra_bpmp_ops {
>  };
>  
>  extern struct tegra_bpmp_ops tegra186_bpmp_ops;
> +extern struct tegra_bpmp_ops tegra210_bpmp_ops;
>  
>  #endif
> diff --git a/drivers/firmware/tegra/bpmp-t210.c b/drivers/firmware/tegra/bpmp-t210.c
> new file mode 100644
> index 0000000..cc56682
> --- /dev/null
> +++ b/drivers/firmware/tegra/bpmp-t210.c
> @@ -0,0 +1,245 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018, NVIDIA CORPORATION.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#include <soc/tegra/bpmp.h>
> +
> +#include "bpmp-private.h"
> +
> +#define TRIGGER_OFFSET		0x000
> +#define RESULT_OFFSET(id)	(0xc00 + id * 4)
> +#define TRIGGER_ID_SHIFT	16
> +#define TRIGGER_CMD_GET		4
> +
> +#define STA_OFFSET		0
> +#define SET_OFFSET		4
> +#define CLR_OFFSET		8
> +
> +#define CH_MASK(ch)	(0x3 << ((ch) * 2))
> +#define SL_SIGL(ch)	(0x0 << ((ch) * 2))
> +#define SL_QUED(ch)	(0x1 << ((ch) * 2))
> +#define MA_FREE(ch)	(0x2 << ((ch) * 2))
> +#define MA_ACKD(ch)	(0x3 << ((ch) * 2))
> +
> +struct tegra210_bpmp {
> +	void __iomem *atomics;
> +	void __iomem *arb_sema;
> +	struct irq_data *tx_irq_data;
> +};
> +
> +static uint32_t bpmp_ch_sta(struct tegra_bpmp *bpmp, int ch)
> +{
> +	struct tegra210_bpmp *priv = bpmp->priv;
> +
> +	return __raw_readl(priv->arb_sema + STA_OFFSET) & CH_MASK(ch);
> +}
> +
> +static bool tegra210_bpmp_is_resp_ready(struct tegra_bpmp_channel *channel)
> +{
> +	int nr = channel->nr;
> +
> +	return bpmp_ch_sta(channel->bpmp, nr) == MA_ACKD(nr);
> +}
> +
> +static bool tegra210_bpmp_is_req_ready(struct tegra_bpmp_channel *channel)
> +{
> +	int nr = channel->nr;
> +
> +	return bpmp_ch_sta(channel->bpmp, nr) == SL_SIGL(nr);
> +}
> +
> +static bool tegra210_bpmp_is_req_channel_free(
> +	struct tegra_bpmp_channel *channel)
> +{
> +	int nr = channel->nr;
> +
> +	return bpmp_ch_sta(channel->bpmp, nr) == MA_FREE(nr);
> +}
> +
> +static bool tegra210_bpmp_is_resp_channel_free(
> +	struct tegra_bpmp_channel *channel)
> +{
> +	int nr = channel->nr;
> +
> +	return bpmp_ch_sta(channel->bpmp, nr) == SL_QUED(nr);
> +}
> +
> +static int tegra210_bpmp_post_req(struct tegra_bpmp_channel *channel)
> +{
> +	struct tegra210_bpmp *priv = channel->bpmp->priv;
> +	int nr = channel->nr;
> +
> +	__raw_writel(CH_MASK(nr), priv->arb_sema + CLR_OFFSET);
> +
> +	return 0;
> +}
> +
> +static int tegra210_bpmp_post_resp(struct tegra_bpmp_channel *channel)
> +{
> +	struct tegra210_bpmp *priv = channel->bpmp->priv;
> +	int nr = channel->nr;
> +
> +	__raw_writel(MA_ACKD(nr), priv->arb_sema + SET_OFFSET);
> +
> +	return 0;
> +}
> +
> +static int tegra210_bpmp_ack_resp(struct tegra_bpmp_channel *channel)
> +{
> +	struct tegra210_bpmp *priv = channel->bpmp->priv;
> +	int nr = channel->nr;
> +
> +	__raw_writel(MA_ACKD(nr) ^ MA_FREE(nr),
> +		     priv->arb_sema + CLR_OFFSET);
> +
> +	return 0;
> +}
> +
> +static int tegra210_bpmp_ack_req(struct tegra_bpmp_channel *channel)
> +{
> +	struct tegra210_bpmp *priv = channel->bpmp->priv;
> +	int nr = channel->nr;
> +
> +	__raw_writel(SL_QUED(nr), priv->arb_sema + SET_OFFSET);
> +
> +	return 0;
> +}
> +
> +static int tegra210_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
> +{
> +	struct tegra210_bpmp *priv = bpmp->priv;
> +	struct irq_data *irq_data = priv->tx_irq_data;
> +
> +	/* Tegra Legacy Interrupt Controller (LIC) is used to notify
> +	 * BPMP of available messages
> +	 */
> +	if (!irq_data->chip->irq_retrigger)
> +		return -EINVAL;
> +	else
> +		return irq_data->chip->irq_retrigger(irq_data);
> +}

This check could also be handled in probe as there does not seem to be
much pointer registering the device if this irq_retrigger is not supported.

Otherwise ...

Acked-by: Jon Hunter <jonathanh@xxxxxxxxxx>

Cheers
Jon

-- 
nvpublic



[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux