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