xref: /OK3568_Linux_fs/kernel/drivers/bus/tegra-gmi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Driver for NVIDIA Generic Memory Interface
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2016 Host Mobility AB. All rights reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This file is licensed under the terms of the GNU General Public
7*4882a593Smuzhiyun  * License version 2. This program is licensed "as is" without any
8*4882a593Smuzhiyun  * warranty of any kind, whether express or implied.
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/clk.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/of_device.h>
16*4882a593Smuzhiyun #include <linux/reset.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define TEGRA_GMI_CONFIG		0x00
19*4882a593Smuzhiyun #define TEGRA_GMI_CONFIG_GO		BIT(31)
20*4882a593Smuzhiyun #define TEGRA_GMI_BUS_WIDTH_32BIT	BIT(30)
21*4882a593Smuzhiyun #define TEGRA_GMI_MUX_MODE		BIT(28)
22*4882a593Smuzhiyun #define TEGRA_GMI_RDY_BEFORE_DATA	BIT(24)
23*4882a593Smuzhiyun #define TEGRA_GMI_RDY_ACTIVE_HIGH	BIT(23)
24*4882a593Smuzhiyun #define TEGRA_GMI_ADV_ACTIVE_HIGH	BIT(22)
25*4882a593Smuzhiyun #define TEGRA_GMI_OE_ACTIVE_HIGH	BIT(21)
26*4882a593Smuzhiyun #define TEGRA_GMI_CS_ACTIVE_HIGH	BIT(20)
27*4882a593Smuzhiyun #define TEGRA_GMI_CS_SELECT(x)		((x & 0x7) << 4)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define TEGRA_GMI_TIMING0		0x10
30*4882a593Smuzhiyun #define TEGRA_GMI_MUXED_WIDTH(x)	((x & 0xf) << 12)
31*4882a593Smuzhiyun #define TEGRA_GMI_HOLD_WIDTH(x)		((x & 0xf) << 8)
32*4882a593Smuzhiyun #define TEGRA_GMI_ADV_WIDTH(x)		((x & 0xf) << 4)
33*4882a593Smuzhiyun #define TEGRA_GMI_CE_WIDTH(x)		(x & 0xf)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define TEGRA_GMI_TIMING1		0x14
36*4882a593Smuzhiyun #define TEGRA_GMI_WE_WIDTH(x)		((x & 0xff) << 16)
37*4882a593Smuzhiyun #define TEGRA_GMI_OE_WIDTH(x)		((x & 0xff) << 8)
38*4882a593Smuzhiyun #define TEGRA_GMI_WAIT_WIDTH(x)		(x & 0xff)
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define TEGRA_GMI_MAX_CHIP_SELECT	8
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun struct tegra_gmi {
43*4882a593Smuzhiyun 	struct device *dev;
44*4882a593Smuzhiyun 	void __iomem *base;
45*4882a593Smuzhiyun 	struct clk *clk;
46*4882a593Smuzhiyun 	struct reset_control *rst;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	u32 snor_config;
49*4882a593Smuzhiyun 	u32 snor_timing0;
50*4882a593Smuzhiyun 	u32 snor_timing1;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun 
tegra_gmi_enable(struct tegra_gmi * gmi)53*4882a593Smuzhiyun static int tegra_gmi_enable(struct tegra_gmi *gmi)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	int err;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	err = clk_prepare_enable(gmi->clk);
58*4882a593Smuzhiyun 	if (err < 0) {
59*4882a593Smuzhiyun 		dev_err(gmi->dev, "failed to enable clock: %d\n", err);
60*4882a593Smuzhiyun 		return err;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	reset_control_assert(gmi->rst);
64*4882a593Smuzhiyun 	usleep_range(2000, 4000);
65*4882a593Smuzhiyun 	reset_control_deassert(gmi->rst);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	writel(gmi->snor_timing0, gmi->base + TEGRA_GMI_TIMING0);
68*4882a593Smuzhiyun 	writel(gmi->snor_timing1, gmi->base + TEGRA_GMI_TIMING1);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	gmi->snor_config |= TEGRA_GMI_CONFIG_GO;
71*4882a593Smuzhiyun 	writel(gmi->snor_config, gmi->base + TEGRA_GMI_CONFIG);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
tegra_gmi_disable(struct tegra_gmi * gmi)76*4882a593Smuzhiyun static void tegra_gmi_disable(struct tegra_gmi *gmi)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	u32 config;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	/* stop GMI operation */
81*4882a593Smuzhiyun 	config = readl(gmi->base + TEGRA_GMI_CONFIG);
82*4882a593Smuzhiyun 	config &= ~TEGRA_GMI_CONFIG_GO;
83*4882a593Smuzhiyun 	writel(config, gmi->base + TEGRA_GMI_CONFIG);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	reset_control_assert(gmi->rst);
86*4882a593Smuzhiyun 	clk_disable_unprepare(gmi->clk);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
tegra_gmi_parse_dt(struct tegra_gmi * gmi)89*4882a593Smuzhiyun static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct device_node *child;
92*4882a593Smuzhiyun 	u32 property, ranges[4];
93*4882a593Smuzhiyun 	int err;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	child = of_get_next_available_child(gmi->dev->of_node, NULL);
96*4882a593Smuzhiyun 	if (!child) {
97*4882a593Smuzhiyun 		dev_err(gmi->dev, "no child nodes found\n");
98*4882a593Smuzhiyun 		return -ENODEV;
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/*
102*4882a593Smuzhiyun 	 * We currently only support one child device due to lack of
103*4882a593Smuzhiyun 	 * chip-select address decoding. Which means that we only have one
104*4882a593Smuzhiyun 	 * chip-select line from the GMI controller.
105*4882a593Smuzhiyun 	 */
106*4882a593Smuzhiyun 	if (of_get_child_count(gmi->dev->of_node) > 1)
107*4882a593Smuzhiyun 		dev_warn(gmi->dev, "only one child device is supported.");
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
110*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
113*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_MUX_MODE;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-rdy-active-before-data"))
116*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-rdy-active-high"))
119*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-adv-active-high"))
122*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-oe-active-high"))
125*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	if (of_property_read_bool(child, "nvidia,snor-cs-active-high"))
128*4882a593Smuzhiyun 		gmi->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	/* Decode the CS# */
131*4882a593Smuzhiyun 	err = of_property_read_u32_array(child, "ranges", ranges, 4);
132*4882a593Smuzhiyun 	if (err < 0) {
133*4882a593Smuzhiyun 		/* Invalid binding */
134*4882a593Smuzhiyun 		if (err == -EOVERFLOW) {
135*4882a593Smuzhiyun 			dev_err(gmi->dev,
136*4882a593Smuzhiyun 				"failed to decode CS: invalid ranges length\n");
137*4882a593Smuzhiyun 			goto error_cs;
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		/*
141*4882a593Smuzhiyun 		 * If we reach here it means that the child node has an empty
142*4882a593Smuzhiyun 		 * ranges or it does not exist at all. Attempt to decode the
143*4882a593Smuzhiyun 		 * CS# from the reg property instead.
144*4882a593Smuzhiyun 		 */
145*4882a593Smuzhiyun 		err = of_property_read_u32(child, "reg", &property);
146*4882a593Smuzhiyun 		if (err < 0) {
147*4882a593Smuzhiyun 			dev_err(gmi->dev,
148*4882a593Smuzhiyun 				"failed to decode CS: no reg property found\n");
149*4882a593Smuzhiyun 			goto error_cs;
150*4882a593Smuzhiyun 		}
151*4882a593Smuzhiyun 	} else {
152*4882a593Smuzhiyun 		property = ranges[1];
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	/* Valid chip selects are CS0-CS7 */
156*4882a593Smuzhiyun 	if (property >= TEGRA_GMI_MAX_CHIP_SELECT) {
157*4882a593Smuzhiyun 		dev_err(gmi->dev, "invalid chip select: %d", property);
158*4882a593Smuzhiyun 		err = -EINVAL;
159*4882a593Smuzhiyun 		goto error_cs;
160*4882a593Smuzhiyun 	}
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	gmi->snor_config |= TEGRA_GMI_CS_SELECT(property);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/* The default values that are provided below are reset values */
165*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-muxed-width", &property))
166*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(property);
167*4882a593Smuzhiyun 	else
168*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(1);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-hold-width", &property))
171*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(property);
172*4882a593Smuzhiyun 	else
173*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(1);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-adv-width", &property))
176*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(property);
177*4882a593Smuzhiyun 	else
178*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(1);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-ce-width", &property))
181*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(property);
182*4882a593Smuzhiyun 	else
183*4882a593Smuzhiyun 		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(4);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-we-width", &property))
186*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(property);
187*4882a593Smuzhiyun 	else
188*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(1);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-oe-width", &property))
191*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(property);
192*4882a593Smuzhiyun 	else
193*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(1);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	if (!of_property_read_u32(child, "nvidia,snor-wait-width", &property))
196*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(property);
197*4882a593Smuzhiyun 	else
198*4882a593Smuzhiyun 		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(3);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun error_cs:
201*4882a593Smuzhiyun 	of_node_put(child);
202*4882a593Smuzhiyun 	return err;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
tegra_gmi_probe(struct platform_device * pdev)205*4882a593Smuzhiyun static int tegra_gmi_probe(struct platform_device *pdev)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
208*4882a593Smuzhiyun 	struct tegra_gmi *gmi;
209*4882a593Smuzhiyun 	struct resource *res;
210*4882a593Smuzhiyun 	int err;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	gmi = devm_kzalloc(dev, sizeof(*gmi), GFP_KERNEL);
213*4882a593Smuzhiyun 	if (!gmi)
214*4882a593Smuzhiyun 		return -ENOMEM;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	gmi->dev = dev;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
219*4882a593Smuzhiyun 	gmi->base = devm_ioremap_resource(dev, res);
220*4882a593Smuzhiyun 	if (IS_ERR(gmi->base))
221*4882a593Smuzhiyun 		return PTR_ERR(gmi->base);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	gmi->clk = devm_clk_get(dev, "gmi");
224*4882a593Smuzhiyun 	if (IS_ERR(gmi->clk)) {
225*4882a593Smuzhiyun 		dev_err(dev, "can not get clock\n");
226*4882a593Smuzhiyun 		return PTR_ERR(gmi->clk);
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	gmi->rst = devm_reset_control_get(dev, "gmi");
230*4882a593Smuzhiyun 	if (IS_ERR(gmi->rst)) {
231*4882a593Smuzhiyun 		dev_err(dev, "can not get reset\n");
232*4882a593Smuzhiyun 		return PTR_ERR(gmi->rst);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	err = tegra_gmi_parse_dt(gmi);
236*4882a593Smuzhiyun 	if (err)
237*4882a593Smuzhiyun 		return err;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	err = tegra_gmi_enable(gmi);
240*4882a593Smuzhiyun 	if (err < 0)
241*4882a593Smuzhiyun 		return err;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	err = of_platform_default_populate(dev->of_node, NULL, dev);
244*4882a593Smuzhiyun 	if (err < 0) {
245*4882a593Smuzhiyun 		dev_err(dev, "fail to create devices.\n");
246*4882a593Smuzhiyun 		tegra_gmi_disable(gmi);
247*4882a593Smuzhiyun 		return err;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	platform_set_drvdata(pdev, gmi);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun 
tegra_gmi_remove(struct platform_device * pdev)255*4882a593Smuzhiyun static int tegra_gmi_remove(struct platform_device *pdev)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	struct tegra_gmi *gmi = platform_get_drvdata(pdev);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	of_platform_depopulate(gmi->dev);
260*4882a593Smuzhiyun 	tegra_gmi_disable(gmi);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return 0;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun static const struct of_device_id tegra_gmi_id_table[] = {
266*4882a593Smuzhiyun 	{ .compatible = "nvidia,tegra20-gmi", },
267*4882a593Smuzhiyun 	{ .compatible = "nvidia,tegra30-gmi", },
268*4882a593Smuzhiyun 	{ }
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, tegra_gmi_id_table);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun static struct platform_driver tegra_gmi_driver = {
273*4882a593Smuzhiyun 	.probe = tegra_gmi_probe,
274*4882a593Smuzhiyun 	.remove = tegra_gmi_remove,
275*4882a593Smuzhiyun 	.driver = {
276*4882a593Smuzhiyun 		.name		= "tegra-gmi",
277*4882a593Smuzhiyun 		.of_match_table	= tegra_gmi_id_table,
278*4882a593Smuzhiyun 	},
279*4882a593Smuzhiyun };
280*4882a593Smuzhiyun module_platform_driver(tegra_gmi_driver);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun MODULE_AUTHOR("Mirza Krak <mirza.krak@gmail.com");
283*4882a593Smuzhiyun MODULE_DESCRIPTION("NVIDIA Tegra GMI Bus Driver");
284*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
285