xref: /openbmc/linux/drivers/bus/tegra-gmi.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
13bb16560SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
240eb4776SMirza Krak /*
340eb4776SMirza Krak  * Driver for NVIDIA Generic Memory Interface
440eb4776SMirza Krak  *
540eb4776SMirza Krak  * Copyright (C) 2016 Host Mobility AB. All rights reserved.
640eb4776SMirza Krak  */
740eb4776SMirza Krak 
840eb4776SMirza Krak #include <linux/clk.h>
940eb4776SMirza Krak #include <linux/delay.h>
1040eb4776SMirza Krak #include <linux/io.h>
1140eb4776SMirza Krak #include <linux/module.h>
121c5e9170SRob Herring #include <linux/of.h>
131c5e9170SRob Herring #include <linux/of_platform.h>
141c5e9170SRob Herring #include <linux/platform_device.h>
1559caf732SDmitry Osipenko #include <linux/pm_runtime.h>
1640eb4776SMirza Krak #include <linux/reset.h>
1740eb4776SMirza Krak 
1859caf732SDmitry Osipenko #include <soc/tegra/common.h>
1959caf732SDmitry Osipenko 
2040eb4776SMirza Krak #define TEGRA_GMI_CONFIG		0x00
2140eb4776SMirza Krak #define TEGRA_GMI_CONFIG_GO		BIT(31)
2240eb4776SMirza Krak #define TEGRA_GMI_BUS_WIDTH_32BIT	BIT(30)
2340eb4776SMirza Krak #define TEGRA_GMI_MUX_MODE		BIT(28)
2440eb4776SMirza Krak #define TEGRA_GMI_RDY_BEFORE_DATA	BIT(24)
2540eb4776SMirza Krak #define TEGRA_GMI_RDY_ACTIVE_HIGH	BIT(23)
2640eb4776SMirza Krak #define TEGRA_GMI_ADV_ACTIVE_HIGH	BIT(22)
2740eb4776SMirza Krak #define TEGRA_GMI_OE_ACTIVE_HIGH	BIT(21)
2840eb4776SMirza Krak #define TEGRA_GMI_CS_ACTIVE_HIGH	BIT(20)
2940eb4776SMirza Krak #define TEGRA_GMI_CS_SELECT(x)		((x & 0x7) << 4)
3040eb4776SMirza Krak 
3140eb4776SMirza Krak #define TEGRA_GMI_TIMING0		0x10
3240eb4776SMirza Krak #define TEGRA_GMI_MUXED_WIDTH(x)	((x & 0xf) << 12)
3340eb4776SMirza Krak #define TEGRA_GMI_HOLD_WIDTH(x)		((x & 0xf) << 8)
3440eb4776SMirza Krak #define TEGRA_GMI_ADV_WIDTH(x)		((x & 0xf) << 4)
3540eb4776SMirza Krak #define TEGRA_GMI_CE_WIDTH(x)		(x & 0xf)
3640eb4776SMirza Krak 
3740eb4776SMirza Krak #define TEGRA_GMI_TIMING1		0x14
3840eb4776SMirza Krak #define TEGRA_GMI_WE_WIDTH(x)		((x & 0xff) << 16)
3940eb4776SMirza Krak #define TEGRA_GMI_OE_WIDTH(x)		((x & 0xff) << 8)
4040eb4776SMirza Krak #define TEGRA_GMI_WAIT_WIDTH(x)		(x & 0xff)
4140eb4776SMirza Krak 
4240eb4776SMirza Krak #define TEGRA_GMI_MAX_CHIP_SELECT	8
4340eb4776SMirza Krak 
4440eb4776SMirza Krak struct tegra_gmi {
4540eb4776SMirza Krak 	struct device *dev;
4640eb4776SMirza Krak 	void __iomem *base;
4740eb4776SMirza Krak 	struct clk *clk;
4840eb4776SMirza Krak 	struct reset_control *rst;
4940eb4776SMirza Krak 
5040eb4776SMirza Krak 	u32 snor_config;
5140eb4776SMirza Krak 	u32 snor_timing0;
5240eb4776SMirza Krak 	u32 snor_timing1;
5340eb4776SMirza Krak };
5440eb4776SMirza Krak 
tegra_gmi_enable(struct tegra_gmi * gmi)5540eb4776SMirza Krak static int tegra_gmi_enable(struct tegra_gmi *gmi)
5640eb4776SMirza Krak {
5740eb4776SMirza Krak 	int err;
5840eb4776SMirza Krak 
5959caf732SDmitry Osipenko 	pm_runtime_enable(gmi->dev);
6059caf732SDmitry Osipenko 	err = pm_runtime_resume_and_get(gmi->dev);
6159caf732SDmitry Osipenko 	if (err) {
6259caf732SDmitry Osipenko 		pm_runtime_disable(gmi->dev);
6340eb4776SMirza Krak 		return err;
6440eb4776SMirza Krak 	}
6540eb4776SMirza Krak 
6640eb4776SMirza Krak 	reset_control_assert(gmi->rst);
6740eb4776SMirza Krak 	usleep_range(2000, 4000);
6840eb4776SMirza Krak 	reset_control_deassert(gmi->rst);
6940eb4776SMirza Krak 
7040eb4776SMirza Krak 	writel(gmi->snor_timing0, gmi->base + TEGRA_GMI_TIMING0);
7140eb4776SMirza Krak 	writel(gmi->snor_timing1, gmi->base + TEGRA_GMI_TIMING1);
7240eb4776SMirza Krak 
7340eb4776SMirza Krak 	gmi->snor_config |= TEGRA_GMI_CONFIG_GO;
7440eb4776SMirza Krak 	writel(gmi->snor_config, gmi->base + TEGRA_GMI_CONFIG);
7540eb4776SMirza Krak 
7640eb4776SMirza Krak 	return 0;
7740eb4776SMirza Krak }
7840eb4776SMirza Krak 
tegra_gmi_disable(struct tegra_gmi * gmi)7940eb4776SMirza Krak static void tegra_gmi_disable(struct tegra_gmi *gmi)
8040eb4776SMirza Krak {
8140eb4776SMirza Krak 	u32 config;
8240eb4776SMirza Krak 
8340eb4776SMirza Krak 	/* stop GMI operation */
8440eb4776SMirza Krak 	config = readl(gmi->base + TEGRA_GMI_CONFIG);
8540eb4776SMirza Krak 	config &= ~TEGRA_GMI_CONFIG_GO;
8640eb4776SMirza Krak 	writel(config, gmi->base + TEGRA_GMI_CONFIG);
8740eb4776SMirza Krak 
8840eb4776SMirza Krak 	reset_control_assert(gmi->rst);
8959caf732SDmitry Osipenko 
9059caf732SDmitry Osipenko 	pm_runtime_put_sync_suspend(gmi->dev);
9159caf732SDmitry Osipenko 	pm_runtime_force_suspend(gmi->dev);
9240eb4776SMirza Krak }
9340eb4776SMirza Krak 
tegra_gmi_parse_dt(struct tegra_gmi * gmi)9440eb4776SMirza Krak static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
9540eb4776SMirza Krak {
9640eb4776SMirza Krak 	struct device_node *child;
9740eb4776SMirza Krak 	u32 property, ranges[4];
9840eb4776SMirza Krak 	int err;
9940eb4776SMirza Krak 
10040eb4776SMirza Krak 	child = of_get_next_available_child(gmi->dev->of_node, NULL);
10140eb4776SMirza Krak 	if (!child) {
10240eb4776SMirza Krak 		dev_err(gmi->dev, "no child nodes found\n");
10340eb4776SMirza Krak 		return -ENODEV;
10440eb4776SMirza Krak 	}
10540eb4776SMirza Krak 
10640eb4776SMirza Krak 	/*
10740eb4776SMirza Krak 	 * We currently only support one child device due to lack of
10840eb4776SMirza Krak 	 * chip-select address decoding. Which means that we only have one
10940eb4776SMirza Krak 	 * chip-select line from the GMI controller.
11040eb4776SMirza Krak 	 */
11140eb4776SMirza Krak 	if (of_get_child_count(gmi->dev->of_node) > 1)
11240eb4776SMirza Krak 		dev_warn(gmi->dev, "only one child device is supported.");
11340eb4776SMirza Krak 
11440eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
11540eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;
11640eb4776SMirza Krak 
11740eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
11840eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_MUX_MODE;
11940eb4776SMirza Krak 
12040eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-rdy-active-before-data"))
12140eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;
12240eb4776SMirza Krak 
12340eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-rdy-active-high"))
12440eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;
12540eb4776SMirza Krak 
12640eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-adv-active-high"))
12740eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;
12840eb4776SMirza Krak 
12940eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-oe-active-high"))
13040eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;
13140eb4776SMirza Krak 
13240eb4776SMirza Krak 	if (of_property_read_bool(child, "nvidia,snor-cs-active-high"))
13340eb4776SMirza Krak 		gmi->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;
13440eb4776SMirza Krak 
13540eb4776SMirza Krak 	/* Decode the CS# */
13640eb4776SMirza Krak 	err = of_property_read_u32_array(child, "ranges", ranges, 4);
13740eb4776SMirza Krak 	if (err < 0) {
13840eb4776SMirza Krak 		/* Invalid binding */
13940eb4776SMirza Krak 		if (err == -EOVERFLOW) {
14040eb4776SMirza Krak 			dev_err(gmi->dev,
14140eb4776SMirza Krak 				"failed to decode CS: invalid ranges length\n");
14240eb4776SMirza Krak 			goto error_cs;
14340eb4776SMirza Krak 		}
14440eb4776SMirza Krak 
14540eb4776SMirza Krak 		/*
14640eb4776SMirza Krak 		 * If we reach here it means that the child node has an empty
14740eb4776SMirza Krak 		 * ranges or it does not exist at all. Attempt to decode the
14840eb4776SMirza Krak 		 * CS# from the reg property instead.
14940eb4776SMirza Krak 		 */
15040eb4776SMirza Krak 		err = of_property_read_u32(child, "reg", &property);
15140eb4776SMirza Krak 		if (err < 0) {
15240eb4776SMirza Krak 			dev_err(gmi->dev,
15340eb4776SMirza Krak 				"failed to decode CS: no reg property found\n");
15440eb4776SMirza Krak 			goto error_cs;
15540eb4776SMirza Krak 		}
15640eb4776SMirza Krak 	} else {
15740eb4776SMirza Krak 		property = ranges[1];
15840eb4776SMirza Krak 	}
15940eb4776SMirza Krak 
16040eb4776SMirza Krak 	/* Valid chip selects are CS0-CS7 */
16140eb4776SMirza Krak 	if (property >= TEGRA_GMI_MAX_CHIP_SELECT) {
16240eb4776SMirza Krak 		dev_err(gmi->dev, "invalid chip select: %d", property);
16340eb4776SMirza Krak 		err = -EINVAL;
16440eb4776SMirza Krak 		goto error_cs;
16540eb4776SMirza Krak 	}
16640eb4776SMirza Krak 
16740eb4776SMirza Krak 	gmi->snor_config |= TEGRA_GMI_CS_SELECT(property);
16840eb4776SMirza Krak 
16940eb4776SMirza Krak 	/* The default values that are provided below are reset values */
17040eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-muxed-width", &property))
17140eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(property);
17240eb4776SMirza Krak 	else
17340eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(1);
17440eb4776SMirza Krak 
17540eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-hold-width", &property))
17640eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(property);
17740eb4776SMirza Krak 	else
17840eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(1);
17940eb4776SMirza Krak 
18040eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-adv-width", &property))
18140eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(property);
18240eb4776SMirza Krak 	else
18340eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(1);
18440eb4776SMirza Krak 
18540eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-ce-width", &property))
18640eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(property);
18740eb4776SMirza Krak 	else
18840eb4776SMirza Krak 		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(4);
18940eb4776SMirza Krak 
19040eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-we-width", &property))
19140eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(property);
19240eb4776SMirza Krak 	else
19340eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(1);
19440eb4776SMirza Krak 
19540eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-oe-width", &property))
19640eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(property);
19740eb4776SMirza Krak 	else
19840eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(1);
19940eb4776SMirza Krak 
20040eb4776SMirza Krak 	if (!of_property_read_u32(child, "nvidia,snor-wait-width", &property))
20140eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(property);
20240eb4776SMirza Krak 	else
20340eb4776SMirza Krak 		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(3);
20440eb4776SMirza Krak 
20540eb4776SMirza Krak error_cs:
20640eb4776SMirza Krak 	of_node_put(child);
20740eb4776SMirza Krak 	return err;
20840eb4776SMirza Krak }
20940eb4776SMirza Krak 
tegra_gmi_probe(struct platform_device * pdev)21040eb4776SMirza Krak static int tegra_gmi_probe(struct platform_device *pdev)
21140eb4776SMirza Krak {
21240eb4776SMirza Krak 	struct device *dev = &pdev->dev;
21340eb4776SMirza Krak 	struct tegra_gmi *gmi;
21440eb4776SMirza Krak 	int err;
21540eb4776SMirza Krak 
21640eb4776SMirza Krak 	gmi = devm_kzalloc(dev, sizeof(*gmi), GFP_KERNEL);
21740eb4776SMirza Krak 	if (!gmi)
21840eb4776SMirza Krak 		return -ENOMEM;
21940eb4776SMirza Krak 
22059caf732SDmitry Osipenko 	platform_set_drvdata(pdev, gmi);
22140eb4776SMirza Krak 	gmi->dev = dev;
22240eb4776SMirza Krak 
223*df823d21SYangtao Li 	gmi->base = devm_platform_ioremap_resource(pdev, 0);
22440eb4776SMirza Krak 	if (IS_ERR(gmi->base))
22540eb4776SMirza Krak 		return PTR_ERR(gmi->base);
22640eb4776SMirza Krak 
22740eb4776SMirza Krak 	gmi->clk = devm_clk_get(dev, "gmi");
22840eb4776SMirza Krak 	if (IS_ERR(gmi->clk)) {
22940eb4776SMirza Krak 		dev_err(dev, "can not get clock\n");
23040eb4776SMirza Krak 		return PTR_ERR(gmi->clk);
23140eb4776SMirza Krak 	}
23240eb4776SMirza Krak 
23340eb4776SMirza Krak 	gmi->rst = devm_reset_control_get(dev, "gmi");
23440eb4776SMirza Krak 	if (IS_ERR(gmi->rst)) {
23540eb4776SMirza Krak 		dev_err(dev, "can not get reset\n");
23640eb4776SMirza Krak 		return PTR_ERR(gmi->rst);
23740eb4776SMirza Krak 	}
23840eb4776SMirza Krak 
23959caf732SDmitry Osipenko 	err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
24059caf732SDmitry Osipenko 	if (err)
24159caf732SDmitry Osipenko 		return err;
24259caf732SDmitry Osipenko 
24340eb4776SMirza Krak 	err = tegra_gmi_parse_dt(gmi);
24440eb4776SMirza Krak 	if (err)
24540eb4776SMirza Krak 		return err;
24640eb4776SMirza Krak 
24740eb4776SMirza Krak 	err = tegra_gmi_enable(gmi);
24840eb4776SMirza Krak 	if (err < 0)
24940eb4776SMirza Krak 		return err;
25040eb4776SMirza Krak 
25140eb4776SMirza Krak 	err = of_platform_default_populate(dev->of_node, NULL, dev);
25240eb4776SMirza Krak 	if (err < 0) {
25340eb4776SMirza Krak 		dev_err(dev, "fail to create devices.\n");
25440eb4776SMirza Krak 		tegra_gmi_disable(gmi);
25540eb4776SMirza Krak 		return err;
25640eb4776SMirza Krak 	}
25740eb4776SMirza Krak 
25840eb4776SMirza Krak 	return 0;
25940eb4776SMirza Krak }
26040eb4776SMirza Krak 
tegra_gmi_remove(struct platform_device * pdev)26140eb4776SMirza Krak static int tegra_gmi_remove(struct platform_device *pdev)
26240eb4776SMirza Krak {
26340eb4776SMirza Krak 	struct tegra_gmi *gmi = platform_get_drvdata(pdev);
26440eb4776SMirza Krak 
26540eb4776SMirza Krak 	of_platform_depopulate(gmi->dev);
26640eb4776SMirza Krak 	tegra_gmi_disable(gmi);
26740eb4776SMirza Krak 
26840eb4776SMirza Krak 	return 0;
26940eb4776SMirza Krak }
27040eb4776SMirza Krak 
tegra_gmi_runtime_resume(struct device * dev)27159caf732SDmitry Osipenko static int __maybe_unused tegra_gmi_runtime_resume(struct device *dev)
27259caf732SDmitry Osipenko {
27359caf732SDmitry Osipenko 	struct tegra_gmi *gmi = dev_get_drvdata(dev);
27459caf732SDmitry Osipenko 	int err;
27559caf732SDmitry Osipenko 
27659caf732SDmitry Osipenko 	err = clk_prepare_enable(gmi->clk);
27759caf732SDmitry Osipenko 	if (err < 0) {
27859caf732SDmitry Osipenko 		dev_err(gmi->dev, "failed to enable clock: %d\n", err);
27959caf732SDmitry Osipenko 		return err;
28059caf732SDmitry Osipenko 	}
28159caf732SDmitry Osipenko 
28259caf732SDmitry Osipenko 	return 0;
28359caf732SDmitry Osipenko }
28459caf732SDmitry Osipenko 
tegra_gmi_runtime_suspend(struct device * dev)28559caf732SDmitry Osipenko static int __maybe_unused tegra_gmi_runtime_suspend(struct device *dev)
28659caf732SDmitry Osipenko {
28759caf732SDmitry Osipenko 	struct tegra_gmi *gmi = dev_get_drvdata(dev);
28859caf732SDmitry Osipenko 
28959caf732SDmitry Osipenko 	clk_disable_unprepare(gmi->clk);
29059caf732SDmitry Osipenko 
29159caf732SDmitry Osipenko 	return 0;
29259caf732SDmitry Osipenko }
29359caf732SDmitry Osipenko 
29459caf732SDmitry Osipenko static const struct dev_pm_ops tegra_gmi_pm = {
29559caf732SDmitry Osipenko 	SET_RUNTIME_PM_OPS(tegra_gmi_runtime_suspend, tegra_gmi_runtime_resume,
29659caf732SDmitry Osipenko 			   NULL)
29759caf732SDmitry Osipenko };
29859caf732SDmitry Osipenko 
29940eb4776SMirza Krak static const struct of_device_id tegra_gmi_id_table[] = {
30040eb4776SMirza Krak 	{ .compatible = "nvidia,tegra20-gmi", },
30140eb4776SMirza Krak 	{ .compatible = "nvidia,tegra30-gmi", },
30240eb4776SMirza Krak 	{ }
30340eb4776SMirza Krak };
30440eb4776SMirza Krak MODULE_DEVICE_TABLE(of, tegra_gmi_id_table);
30540eb4776SMirza Krak 
30640eb4776SMirza Krak static struct platform_driver tegra_gmi_driver = {
30740eb4776SMirza Krak 	.probe = tegra_gmi_probe,
30840eb4776SMirza Krak 	.remove = tegra_gmi_remove,
30940eb4776SMirza Krak 	.driver = {
31040eb4776SMirza Krak 		.name		= "tegra-gmi",
31140eb4776SMirza Krak 		.of_match_table	= tegra_gmi_id_table,
31259caf732SDmitry Osipenko 		.pm = &tegra_gmi_pm,
31340eb4776SMirza Krak 	},
31440eb4776SMirza Krak };
31540eb4776SMirza Krak module_platform_driver(tegra_gmi_driver);
31640eb4776SMirza Krak 
31740eb4776SMirza Krak MODULE_AUTHOR("Mirza Krak <mirza.krak@gmail.com");
31840eb4776SMirza Krak MODULE_DESCRIPTION("NVIDIA Tegra GMI Bus Driver");
31940eb4776SMirza Krak MODULE_LICENSE("GPL v2");
320