1 /*
2  * NXP GPMI NAND flash driver (DT initialization)
3  *
4  * Copyright (C) 2018 Toradex
5  * Copyright 2019 NXP
6  *
7  * Authors:
8  * Stefan Agner <stefan.agner@toradex.com>
9  *
10  * Based on denali_dt.c
11  *
12  * SPDX-License-Identifier:	GPL-2.0+
13  */
14 
15 #include <dm.h>
16 #include <linux/io.h>
17 #include <linux/ioport.h>
18 #include <linux/printk.h>
19 #include <clk.h>
20 
21 #include <mxs_nand.h>
22 
23 struct mxs_nand_dt_data {
24 	unsigned int max_ecc_strength_supported;
25 };
26 
27 static const struct mxs_nand_dt_data mxs_nand_imx6q_data = {
28 	.max_ecc_strength_supported = 40,
29 };
30 
31 static const struct mxs_nand_dt_data mxs_nand_imx6sx_data = {
32 	.max_ecc_strength_supported = 62,
33 };
34 
35 static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
36 	.max_ecc_strength_supported = 62,
37 };
38 
39 static const struct mxs_nand_dt_data mxs_nand_imx8qxp_data = {
40 	.max_ecc_strength_supported = 62,
41 };
42 
43 static const struct udevice_id mxs_nand_dt_ids[] = {
44 	{
45 		.compatible = "fsl,imx6q-gpmi-nand",
46 		.data = (unsigned long)&mxs_nand_imx6q_data,
47 	},
48 	{
49 		.compatible = "fsl,imx6qp-gpmi-nand",
50 		.data = (unsigned long)&mxs_nand_imx6q_data,
51 	},
52 	{
53 		.compatible = "fsl,imx6sx-gpmi-nand",
54 		.data = (unsigned long)&mxs_nand_imx6sx_data,
55 	},
56 	{
57 		.compatible = "fsl,imx7d-gpmi-nand",
58 		.data = (unsigned long)&mxs_nand_imx7d_data,
59 	},
60 	{
61 		.compatible = "fsl,imx8qxp-gpmi-nand",
62 		.data = (unsigned long)&mxs_nand_imx8qxp_data,
63 	},
64 	{ /* sentinel */ }
65 };
66 
mxs_nand_dt_probe(struct udevice * dev)67 static int mxs_nand_dt_probe(struct udevice *dev)
68 {
69 	struct mxs_nand_info *info = dev_get_priv(dev);
70 	const struct mxs_nand_dt_data *data;
71 	struct resource res;
72 	int ret;
73 
74 	data = (void *)dev_get_driver_data(dev);
75 	if (data)
76 		info->max_ecc_strength_supported = data->max_ecc_strength_supported;
77 
78 	info->dev = dev;
79 
80 	ret = dev_read_resource_byname(dev, "gpmi-nand", &res);
81 	if (ret)
82 		return ret;
83 
84 	info->gpmi_regs = devm_ioremap(dev, res.start, resource_size(&res));
85 
86 
87 	ret = dev_read_resource_byname(dev, "bch", &res);
88 	if (ret)
89 		return ret;
90 
91 	info->bch_regs = devm_ioremap(dev, res.start, resource_size(&res));
92 
93 	info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
94 
95 	info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry");
96 
97 	if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) {
98 		/* Assigned clock already set clock */
99 		struct clk gpmi_clk;
100 
101 		ret = clk_get_by_name(dev, "gpmi_io", &gpmi_clk);
102 		if (ret < 0) {
103 			debug("Can't get gpmi io clk: %d\n", ret);
104 			return ret;
105 		}
106 
107 		ret = clk_enable(&gpmi_clk);
108 		if (ret < 0) {
109 			debug("Can't enable gpmi io clk: %d\n", ret);
110 			return ret;
111 		}
112 
113 		ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
114 		if (ret < 0) {
115 			debug("Can't get gpmi_apb clk: %d\n", ret);
116 			return ret;
117 		}
118 
119 		ret = clk_enable(&gpmi_clk);
120 		if (ret < 0) {
121 			debug("Can't enable gpmi_apb clk: %d\n", ret);
122 			return ret;
123 		}
124 
125 		ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
126 		if (ret < 0) {
127 			debug("Can't get gpmi_bch clk: %d\n", ret);
128 			return ret;
129 		}
130 
131 		ret = clk_enable(&gpmi_clk);
132 		if (ret < 0) {
133 			debug("Can't enable gpmi_bch clk: %d\n", ret);
134 			return ret;
135 		}
136 
137 		ret = clk_get_by_name(dev, "gpmi_apb_bch", &gpmi_clk);
138 		if (ret < 0) {
139 			debug("Can't get gpmi_apb_bch clk: %d\n", ret);
140 			return ret;
141 		}
142 
143 		ret = clk_enable(&gpmi_clk);
144 		if (ret < 0) {
145 			debug("Can't enable gpmi_apb_bch clk: %d\n", ret);
146 			return ret;
147 		}
148 
149 		/* this clock is used for apbh_dma, since the apbh dma does not support DM,
150 		  * we optionally enable it here
151 		  */
152 		ret = clk_get_by_name(dev, "gpmi_apbh_dma", &gpmi_clk);
153 		if (ret < 0) {
154 			debug("Can't get gpmi_apbh_dma clk: %d\n", ret);
155 		} else {
156 			ret = clk_enable(&gpmi_clk);
157 			if (ret < 0) {
158 				debug("Can't enable gpmi_apbh_dma clk: %d\n", ret);
159 			}
160 		}
161 	}
162 
163 	return mxs_nand_init_ctrl(info);
164 }
165 
166 U_BOOT_DRIVER(mxs_nand_dt) = {
167 	.name = "mxs-nand-dt",
168 	.id = UCLASS_MTD,
169 	.of_match = mxs_nand_dt_ids,
170 	.probe = mxs_nand_dt_probe,
171 	.priv_auto	= sizeof(struct mxs_nand_info),
172 };
173 
board_nand_init(void)174 void board_nand_init(void)
175 {
176 	struct udevice *dev;
177 	int ret;
178 
179 	ret = uclass_get_device_by_driver(UCLASS_MTD,
180 					  DM_DRIVER_GET(mxs_nand_dt),
181 					  &dev);
182 	if (ret && ret != -ENODEV)
183 		pr_err("Failed to initialize MXS NAND controller. (error %d)\n",
184 		       ret);
185 }
186