1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Technologic Systems TS72xx NAND controller driver
4 *
5 * Copyright (C) 2023 Nikita Shubin <nikita.shubin@maquefel.me>
6 *
7 * Derived from: plat_nand.c
8 * Author: Vitaly Wool <vitalywool@gmail.com>
9 */
10
11 #include <linux/bits.h>
12 #include <linux/err.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/platnand.h>
21
22 #define TS72XX_NAND_CONTROL_ADDR_LINE BIT(22) /* 0xN0400000 */
23 #define TS72XX_NAND_BUSY_ADDR_LINE BIT(23) /* 0xN0800000 */
24
25 #define TS72XX_NAND_ALE BIT(0)
26 #define TS72XX_NAND_CLE BIT(1)
27 #define TS72XX_NAND_NCE BIT(2)
28
29 #define TS72XX_NAND_CTRL_CLE (TS72XX_NAND_NCE | TS72XX_NAND_CLE)
30 #define TS72XX_NAND_CTRL_ALE (TS72XX_NAND_NCE | TS72XX_NAND_ALE)
31
32 struct ts72xx_nand_data {
33 struct nand_controller controller;
34 struct nand_chip chip;
35 void __iomem *base;
36 void __iomem *ctrl;
37 void __iomem *busy;
38 };
39
chip_to_ts72xx(struct nand_chip * chip)40 static inline struct ts72xx_nand_data *chip_to_ts72xx(struct nand_chip *chip)
41 {
42 return container_of(chip, struct ts72xx_nand_data, chip);
43 }
44
ts72xx_nand_attach_chip(struct nand_chip * chip)45 static int ts72xx_nand_attach_chip(struct nand_chip *chip)
46 {
47 switch (chip->ecc.engine_type) {
48 case NAND_ECC_ENGINE_TYPE_ON_HOST:
49 return -EINVAL;
50 case NAND_ECC_ENGINE_TYPE_SOFT:
51 if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
52 chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
53 chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
54 fallthrough;
55 default:
56 return 0;
57 }
58 }
59
ts72xx_nand_ctrl(struct nand_chip * chip,u8 value)60 static void ts72xx_nand_ctrl(struct nand_chip *chip, u8 value)
61 {
62 struct ts72xx_nand_data *data = chip_to_ts72xx(chip);
63 unsigned char bits = ioread8(data->ctrl) & ~GENMASK(2, 0);
64
65 iowrite8(bits | value, data->ctrl);
66 }
67
ts72xx_nand_exec_instr(struct nand_chip * chip,const struct nand_op_instr * instr)68 static int ts72xx_nand_exec_instr(struct nand_chip *chip,
69 const struct nand_op_instr *instr)
70 {
71 struct ts72xx_nand_data *data = chip_to_ts72xx(chip);
72 unsigned int timeout_us;
73 u32 status;
74 int ret;
75
76 switch (instr->type) {
77 case NAND_OP_CMD_INSTR:
78 ts72xx_nand_ctrl(chip, TS72XX_NAND_CTRL_CLE);
79 iowrite8(instr->ctx.cmd.opcode, data->base);
80 ts72xx_nand_ctrl(chip, TS72XX_NAND_NCE);
81 break;
82
83 case NAND_OP_ADDR_INSTR:
84 ts72xx_nand_ctrl(chip, TS72XX_NAND_CTRL_ALE);
85 iowrite8_rep(data->base, instr->ctx.addr.addrs, instr->ctx.addr.naddrs);
86 ts72xx_nand_ctrl(chip, TS72XX_NAND_NCE);
87 break;
88
89 case NAND_OP_DATA_IN_INSTR:
90 ioread8_rep(data->base, instr->ctx.data.buf.in, instr->ctx.data.len);
91 break;
92
93 case NAND_OP_DATA_OUT_INSTR:
94 iowrite8_rep(data->base, instr->ctx.data.buf.in, instr->ctx.data.len);
95 break;
96
97 case NAND_OP_WAITRDY_INSTR:
98 timeout_us = instr->ctx.waitrdy.timeout_ms * 1000;
99 ret = readb_poll_timeout(data->busy, status, status & BIT(5), 0, timeout_us);
100 if (ret)
101 return ret;
102
103 break;
104 }
105
106 if (instr->delay_ns)
107 ndelay(instr->delay_ns);
108
109 return 0;
110 }
111
ts72xx_nand_exec_op(struct nand_chip * chip,const struct nand_operation * op,bool check_only)112 static int ts72xx_nand_exec_op(struct nand_chip *chip,
113 const struct nand_operation *op, bool check_only)
114 {
115 unsigned int i;
116 int ret;
117
118 if (check_only)
119 return 0;
120
121 for (i = 0; i < op->ninstrs; i++) {
122 ret = ts72xx_nand_exec_instr(chip, &op->instrs[i]);
123 if (ret)
124 return ret;
125 }
126
127 return 0;
128 }
129
130 static const struct nand_controller_ops ts72xx_nand_ops = {
131 .attach_chip = ts72xx_nand_attach_chip,
132 .exec_op = ts72xx_nand_exec_op,
133 };
134
ts72xx_nand_probe(struct platform_device * pdev)135 static int ts72xx_nand_probe(struct platform_device *pdev)
136 {
137 struct ts72xx_nand_data *data;
138 struct fwnode_handle *child;
139 struct mtd_info *mtd;
140 int err;
141
142 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
143 if (!data)
144 return -ENOMEM;
145
146 nand_controller_init(&data->controller);
147 data->controller.ops = &ts72xx_nand_ops;
148 data->chip.controller = &data->controller;
149
150 data->base = devm_platform_ioremap_resource(pdev, 0);
151 if (IS_ERR(data->base))
152 return PTR_ERR(data->base);
153 data->ctrl = data->base + TS72XX_NAND_CONTROL_ADDR_LINE;
154 data->busy = data->base + TS72XX_NAND_BUSY_ADDR_LINE;
155
156 child = fwnode_get_next_child_node(dev_fwnode(&pdev->dev), NULL);
157 if (!child)
158 return dev_err_probe(&pdev->dev, -ENXIO,
159 "ts72xx controller node should have exactly one child\n");
160
161 nand_set_flash_node(&data->chip, to_of_node(child));
162 mtd = nand_to_mtd(&data->chip);
163 mtd->dev.parent = &pdev->dev;
164 platform_set_drvdata(pdev, data);
165
166 /*
167 * This driver assumes that the default ECC engine should be TYPE_SOFT.
168 * Set ->engine_type before registering the NAND devices in order to
169 * provide a driver specific default value.
170 */
171 data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
172
173 /* Scan to find existence of the device */
174 err = nand_scan(&data->chip, 1);
175 if (err)
176 goto err_handle_put;
177
178 err = mtd_device_parse_register(mtd, NULL, NULL, NULL, 0);
179 if (err)
180 goto err_clean_nand;
181
182 return 0;
183
184 err_clean_nand:
185 nand_cleanup(&data->chip);
186 err_handle_put:
187 fwnode_handle_put(child);
188 return err;
189 }
190
ts72xx_nand_remove(struct platform_device * pdev)191 static void ts72xx_nand_remove(struct platform_device *pdev)
192 {
193 struct ts72xx_nand_data *data = platform_get_drvdata(pdev);
194 struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
195 struct nand_chip *chip = &data->chip;
196 int ret;
197
198 ret = mtd_device_unregister(nand_to_mtd(chip));
199 WARN_ON(ret);
200 nand_cleanup(chip);
201 fwnode_handle_put(fwnode);
202 }
203
204 static const struct of_device_id ts72xx_id_table[] = {
205 { .compatible = "technologic,ts7200-nand" },
206 { /* sentinel */ }
207 };
208 MODULE_DEVICE_TABLE(of, ts72xx_id_table);
209
210 static struct platform_driver ts72xx_nand_driver = {
211 .driver = {
212 .name = "ts72xx-nand",
213 .of_match_table = ts72xx_id_table,
214 },
215 .probe = ts72xx_nand_probe,
216 .remove_new = ts72xx_nand_remove,
217 };
218 module_platform_driver(ts72xx_nand_driver);
219
220 MODULE_AUTHOR("Nikita Shubin <nikita.shubin@maquefel.me>");
221 MODULE_DESCRIPTION("Technologic Systems TS72xx NAND controller driver");
222 MODULE_LICENSE("GPL");
223