xref: /rk3399_rockchip-uboot/drivers/mailbox/tegra-hsp.c (revision 5e1ff6480fbe7cf1b2be1f8a13086b217b2f8578)
10f67e239SStephen Warren /*
20f67e239SStephen Warren  * Copyright (c) 2016, NVIDIA CORPORATION.
30f67e239SStephen Warren  *
40f67e239SStephen Warren  * SPDX-License-Identifier: GPL-2.0
50f67e239SStephen Warren  */
60f67e239SStephen Warren 
70f67e239SStephen Warren #include <common.h>
80f67e239SStephen Warren #include <asm/io.h>
90f67e239SStephen Warren #include <dm.h>
100f67e239SStephen Warren #include <mailbox-uclass.h>
11729c2db7SStephen Warren #include <dt-bindings/mailbox/tegra186-hsp.h>
12729c2db7SStephen Warren 
13729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING		0x380
14729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSI_SHIFT	16
15729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSI_MASK	0xf
16729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NDB_SHIFT	12
17729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NDB_MASK	0xf
18729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT	8
19729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NAS_MASK	0xf
20729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT	4
21729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSS_MASK	0xf
22729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT	0
23729c2db7SStephen Warren #define TEGRA_HSP_INT_DIMENSIONING_NSM_MASK	0xf
240f67e239SStephen Warren 
250f67e239SStephen Warren #define TEGRA_HSP_DB_REG_TRIGGER	0x0
260f67e239SStephen Warren #define TEGRA_HSP_DB_REG_ENABLE		0x4
270f67e239SStephen Warren #define TEGRA_HSP_DB_REG_RAW		0x8
280f67e239SStephen Warren #define TEGRA_HSP_DB_REG_PENDING	0xc
290f67e239SStephen Warren 
300f67e239SStephen Warren #define TEGRA_HSP_DB_ID_CCPLEX		1
310f67e239SStephen Warren #define TEGRA_HSP_DB_ID_BPMP		3
320f67e239SStephen Warren #define TEGRA_HSP_DB_ID_NUM		7
330f67e239SStephen Warren 
340f67e239SStephen Warren struct tegra_hsp {
350f67e239SStephen Warren 	fdt_addr_t regs;
360f67e239SStephen Warren 	uint32_t db_base;
370f67e239SStephen Warren };
380f67e239SStephen Warren 
390f67e239SStephen Warren DECLARE_GLOBAL_DATA_PTR;
400f67e239SStephen Warren 
tegra_hsp_reg(struct tegra_hsp * thsp,uint32_t db_id,uint32_t reg)410f67e239SStephen Warren static uint32_t *tegra_hsp_reg(struct tegra_hsp *thsp, uint32_t db_id,
420f67e239SStephen Warren 			       uint32_t reg)
430f67e239SStephen Warren {
440f67e239SStephen Warren 	return (uint32_t *)(thsp->regs + thsp->db_base + (db_id * 0x100) + reg);
450f67e239SStephen Warren }
460f67e239SStephen Warren 
tegra_hsp_readl(struct tegra_hsp * thsp,uint32_t db_id,uint32_t reg)470f67e239SStephen Warren static uint32_t tegra_hsp_readl(struct tegra_hsp *thsp, uint32_t db_id,
480f67e239SStephen Warren 				uint32_t reg)
490f67e239SStephen Warren {
500f67e239SStephen Warren 	uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
510f67e239SStephen Warren 	return readl(r);
520f67e239SStephen Warren }
530f67e239SStephen Warren 
tegra_hsp_writel(struct tegra_hsp * thsp,uint32_t val,uint32_t db_id,uint32_t reg)540f67e239SStephen Warren static void tegra_hsp_writel(struct tegra_hsp *thsp, uint32_t val,
550f67e239SStephen Warren 			     uint32_t db_id, uint32_t reg)
560f67e239SStephen Warren {
570f67e239SStephen Warren 	uint32_t *r = tegra_hsp_reg(thsp, db_id, reg);
580f67e239SStephen Warren 
590f67e239SStephen Warren 	writel(val, r);
600f67e239SStephen Warren 	readl(r);
610f67e239SStephen Warren }
620f67e239SStephen Warren 
tegra_hsp_db_id(ulong chan_id)630f67e239SStephen Warren static int tegra_hsp_db_id(ulong chan_id)
640f67e239SStephen Warren {
650f67e239SStephen Warren 	switch (chan_id) {
66729c2db7SStephen Warren 	case (HSP_MBOX_TYPE_DB << 16) | HSP_DB_MASTER_BPMP:
670f67e239SStephen Warren 		return TEGRA_HSP_DB_ID_BPMP;
680f67e239SStephen Warren 	default:
690f67e239SStephen Warren 		debug("Invalid channel ID\n");
700f67e239SStephen Warren 		return -EINVAL;
710f67e239SStephen Warren 	}
720f67e239SStephen Warren }
730f67e239SStephen Warren 
tegra_hsp_of_xlate(struct mbox_chan * chan,struct ofnode_phandle_args * args)74729c2db7SStephen Warren static int tegra_hsp_of_xlate(struct mbox_chan *chan,
75*5e1ff648SSimon Glass 			      struct ofnode_phandle_args *args)
76729c2db7SStephen Warren {
77729c2db7SStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
78729c2db7SStephen Warren 
79729c2db7SStephen Warren 	if (args->args_count != 2) {
80729c2db7SStephen Warren 		debug("Invaild args_count: %d\n", args->args_count);
81729c2db7SStephen Warren 		return -EINVAL;
82729c2db7SStephen Warren 	}
83729c2db7SStephen Warren 
84729c2db7SStephen Warren 	chan->id = (args->args[0] << 16) | args->args[1];
85729c2db7SStephen Warren 
86729c2db7SStephen Warren 	return 0;
87729c2db7SStephen Warren }
88729c2db7SStephen Warren 
tegra_hsp_request(struct mbox_chan * chan)890f67e239SStephen Warren static int tegra_hsp_request(struct mbox_chan *chan)
900f67e239SStephen Warren {
910f67e239SStephen Warren 	int db_id;
920f67e239SStephen Warren 
930f67e239SStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
940f67e239SStephen Warren 
950f67e239SStephen Warren 	db_id = tegra_hsp_db_id(chan->id);
960f67e239SStephen Warren 	if (db_id < 0) {
970f67e239SStephen Warren 		debug("tegra_hsp_db_id() failed: %d\n", db_id);
980f67e239SStephen Warren 		return -EINVAL;
990f67e239SStephen Warren 	}
1000f67e239SStephen Warren 
1010f67e239SStephen Warren 	return 0;
1020f67e239SStephen Warren }
1030f67e239SStephen Warren 
tegra_hsp_free(struct mbox_chan * chan)1040f67e239SStephen Warren static int tegra_hsp_free(struct mbox_chan *chan)
1050f67e239SStephen Warren {
1060f67e239SStephen Warren 	debug("%s(chan=%p)\n", __func__, chan);
1070f67e239SStephen Warren 
1080f67e239SStephen Warren 	return 0;
1090f67e239SStephen Warren }
1100f67e239SStephen Warren 
tegra_hsp_send(struct mbox_chan * chan,const void * data)1110f67e239SStephen Warren static int tegra_hsp_send(struct mbox_chan *chan, const void *data)
1120f67e239SStephen Warren {
1130f67e239SStephen Warren 	struct tegra_hsp *thsp = dev_get_priv(chan->dev);
1140f67e239SStephen Warren 	int db_id;
1150f67e239SStephen Warren 
1160f67e239SStephen Warren 	debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
1170f67e239SStephen Warren 
1180f67e239SStephen Warren 	db_id = tegra_hsp_db_id(chan->id);
1190f67e239SStephen Warren 	tegra_hsp_writel(thsp, 1, db_id, TEGRA_HSP_DB_REG_TRIGGER);
1200f67e239SStephen Warren 
1210f67e239SStephen Warren 	return 0;
1220f67e239SStephen Warren }
1230f67e239SStephen Warren 
tegra_hsp_recv(struct mbox_chan * chan,void * data)1240f67e239SStephen Warren static int tegra_hsp_recv(struct mbox_chan *chan, void *data)
1250f67e239SStephen Warren {
1260f67e239SStephen Warren 	struct tegra_hsp *thsp = dev_get_priv(chan->dev);
1270f67e239SStephen Warren 	uint32_t db_id = TEGRA_HSP_DB_ID_CCPLEX;
1280f67e239SStephen Warren 	uint32_t val;
1290f67e239SStephen Warren 
1300f67e239SStephen Warren 	debug("%s(chan=%p, data=%p)\n", __func__, chan, data);
1310f67e239SStephen Warren 
1320f67e239SStephen Warren 	val = tegra_hsp_readl(thsp, db_id, TEGRA_HSP_DB_REG_RAW);
1330f67e239SStephen Warren 	if (!(val & BIT(chan->id)))
1340f67e239SStephen Warren 		return -ENODATA;
1350f67e239SStephen Warren 
1360f67e239SStephen Warren 	tegra_hsp_writel(thsp, BIT(chan->id), db_id, TEGRA_HSP_DB_REG_RAW);
1370f67e239SStephen Warren 
1380f67e239SStephen Warren 	return 0;
1390f67e239SStephen Warren }
1400f67e239SStephen Warren 
tegra_hsp_bind(struct udevice * dev)1410f67e239SStephen Warren static int tegra_hsp_bind(struct udevice *dev)
1420f67e239SStephen Warren {
1430f67e239SStephen Warren 	debug("%s(dev=%p)\n", __func__, dev);
1440f67e239SStephen Warren 
1450f67e239SStephen Warren 	return 0;
1460f67e239SStephen Warren }
1470f67e239SStephen Warren 
tegra_hsp_probe(struct udevice * dev)1480f67e239SStephen Warren static int tegra_hsp_probe(struct udevice *dev)
1490f67e239SStephen Warren {
1500f67e239SStephen Warren 	struct tegra_hsp *thsp = dev_get_priv(dev);
151729c2db7SStephen Warren 	u32 val;
1520f67e239SStephen Warren 	int nr_sm, nr_ss, nr_as;
1530f67e239SStephen Warren 
1540f67e239SStephen Warren 	debug("%s(dev=%p)\n", __func__, dev);
1550f67e239SStephen Warren 
156a821c4afSSimon Glass 	thsp->regs = devfdt_get_addr(dev);
1570f67e239SStephen Warren 	if (thsp->regs == FDT_ADDR_T_NONE)
1580f67e239SStephen Warren 		return -ENODEV;
1590f67e239SStephen Warren 
160729c2db7SStephen Warren 	val = readl(thsp->regs + TEGRA_HSP_INT_DIMENSIONING);
161729c2db7SStephen Warren 	nr_sm = (val >> TEGRA_HSP_INT_DIMENSIONING_NSM_SHIFT) &
162729c2db7SStephen Warren 		TEGRA_HSP_INT_DIMENSIONING_NSM_MASK;
163729c2db7SStephen Warren 	nr_ss = (val >> TEGRA_HSP_INT_DIMENSIONING_NSS_SHIFT) &
164729c2db7SStephen Warren 		TEGRA_HSP_INT_DIMENSIONING_NSS_MASK;
165729c2db7SStephen Warren 	nr_as = (val >> TEGRA_HSP_INT_DIMENSIONING_NAS_SHIFT) &
166729c2db7SStephen Warren 		TEGRA_HSP_INT_DIMENSIONING_NAS_MASK;
167729c2db7SStephen Warren 
1680f67e239SStephen Warren 	thsp->db_base = (1 + (nr_sm >> 1) + nr_ss + nr_as) << 16;
1690f67e239SStephen Warren 
1700f67e239SStephen Warren 	return 0;
1710f67e239SStephen Warren }
1720f67e239SStephen Warren 
1730f67e239SStephen Warren static const struct udevice_id tegra_hsp_ids[] = {
1740f67e239SStephen Warren 	{ .compatible = "nvidia,tegra186-hsp" },
1750f67e239SStephen Warren 	{ }
1760f67e239SStephen Warren };
1770f67e239SStephen Warren 
1780f67e239SStephen Warren struct mbox_ops tegra_hsp_mbox_ops = {
179729c2db7SStephen Warren 	.of_xlate = tegra_hsp_of_xlate,
1800f67e239SStephen Warren 	.request = tegra_hsp_request,
1810f67e239SStephen Warren 	.free = tegra_hsp_free,
1820f67e239SStephen Warren 	.send = tegra_hsp_send,
1830f67e239SStephen Warren 	.recv = tegra_hsp_recv,
1840f67e239SStephen Warren };
1850f67e239SStephen Warren 
1860f67e239SStephen Warren U_BOOT_DRIVER(tegra_hsp) = {
1870f67e239SStephen Warren 	.name = "tegra-hsp",
1880f67e239SStephen Warren 	.id = UCLASS_MAILBOX,
1890f67e239SStephen Warren 	.of_match = tegra_hsp_ids,
1900f67e239SStephen Warren 	.bind = tegra_hsp_bind,
1910f67e239SStephen Warren 	.probe = tegra_hsp_probe,
1920f67e239SStephen Warren 	.priv_auto_alloc_size = sizeof(struct tegra_hsp),
1930f67e239SStephen Warren 	.ops = &tegra_hsp_mbox_ops,
1940f67e239SStephen Warren };
195