]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/mtd/nand/raw/oxnas_nand.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 500
[mirror_ubuntu-jammy-kernel.git] / drivers / mtd / nand / raw / oxnas_nand.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
66859249
NA
2/*
3 * Oxford Semiconductor OXNAS NAND driver
4
5 * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
6 * Heavily based on plat_nand.c :
7 * Author: Vitaly Wool <vitalywool@gmail.com>
8 * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
9 * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
66859249
NA
10 */
11
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/clk.h>
18#include <linux/reset.h>
19#include <linux/mtd/mtd.h>
d4092d76 20#include <linux/mtd/rawnand.h>
66859249
NA
21#include <linux/mtd/partitions.h>
22#include <linux/of.h>
23
24/* Nand commands */
25#define OXNAS_NAND_CMD_ALE BIT(18)
26#define OXNAS_NAND_CMD_CLE BIT(19)
27
28#define OXNAS_NAND_MAX_CHIPS 1
29
30struct oxnas_nand_ctrl {
7da45139 31 struct nand_controller base;
66859249
NA
32 void __iomem *io_base;
33 struct clk *clk;
34 struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS];
35};
36
7e534323 37static uint8_t oxnas_nand_read_byte(struct nand_chip *chip)
66859249 38{
66859249
NA
39 struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
40
41 return readb(oxnas->io_base);
42}
43
7e534323 44static void oxnas_nand_read_buf(struct nand_chip *chip, u8 *buf, int len)
66859249 45{
66859249
NA
46 struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
47
48 ioread8_rep(oxnas->io_base, buf, len);
49}
50
c0739d85
BB
51static void oxnas_nand_write_buf(struct nand_chip *chip, const u8 *buf,
52 int len)
66859249 53{
66859249
NA
54 struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
55
56 iowrite8_rep(oxnas->io_base, buf, len);
57}
58
59/* Single CS command control */
0f808c16 60static void oxnas_nand_cmd_ctrl(struct nand_chip *chip, int cmd,
66859249
NA
61 unsigned int ctrl)
62{
66859249
NA
63 struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
64
65 if (ctrl & NAND_CLE)
66 writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_CLE);
67 else if (ctrl & NAND_ALE)
68 writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_ALE);
69}
70
71/*
72 * Probe for the NAND device.
73 */
74static int oxnas_nand_probe(struct platform_device *pdev)
75{
76 struct device_node *np = pdev->dev.of_node;
77 struct device_node *nand_np;
78 struct oxnas_nand_ctrl *oxnas;
79 struct nand_chip *chip;
80 struct mtd_info *mtd;
81 struct resource *res;
82 int nchips = 0;
83 int count = 0;
84 int err = 0;
85
86 /* Allocate memory for the device structure (and zero it) */
b98e1995 87 oxnas = devm_kzalloc(&pdev->dev, sizeof(*oxnas),
66859249
NA
88 GFP_KERNEL);
89 if (!oxnas)
90 return -ENOMEM;
91
7da45139 92 nand_controller_init(&oxnas->base);
66859249
NA
93
94 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
95 oxnas->io_base = devm_ioremap_resource(&pdev->dev, res);
96 if (IS_ERR(oxnas->io_base))
97 return PTR_ERR(oxnas->io_base);
98
99 oxnas->clk = devm_clk_get(&pdev->dev, NULL);
100 if (IS_ERR(oxnas->clk))
101 oxnas->clk = NULL;
102
103 /* Only a single chip node is supported */
104 count = of_get_child_count(np);
105 if (count > 1)
106 return -EINVAL;
107
24c9cd8f
AY
108 err = clk_prepare_enable(oxnas->clk);
109 if (err)
110 return err;
111
66859249
NA
112 device_reset_optional(&pdev->dev);
113
114 for_each_child_of_node(np, nand_np) {
115 chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
116 GFP_KERNEL);
24c9cd8f
AY
117 if (!chip) {
118 err = -ENOMEM;
119 goto err_clk_unprepare;
120 }
66859249
NA
121
122 chip->controller = &oxnas->base;
123
124 nand_set_flash_node(chip, nand_np);
125 nand_set_controller_data(chip, oxnas);
126
127 mtd = nand_to_mtd(chip);
128 mtd->dev.parent = &pdev->dev;
129 mtd->priv = chip;
130
bf6065c6 131 chip->legacy.cmd_ctrl = oxnas_nand_cmd_ctrl;
716bbbab
BB
132 chip->legacy.read_buf = oxnas_nand_read_buf;
133 chip->legacy.read_byte = oxnas_nand_read_byte;
134 chip->legacy.write_buf = oxnas_nand_write_buf;
3cece3ab 135 chip->legacy.chip_delay = 30;
66859249
NA
136
137 /* Scan to find existence of the device */
00ad378f 138 err = nand_scan(chip, 1);
66859249 139 if (err)
24c9cd8f 140 goto err_clk_unprepare;
66859249
NA
141
142 err = mtd_device_register(mtd, NULL, 0);
143 if (err) {
59ac276f 144 nand_release(chip);
24c9cd8f 145 goto err_clk_unprepare;
66859249
NA
146 }
147
148 oxnas->chips[nchips] = chip;
149 ++nchips;
150 }
151
152 /* Exit if no chips found */
24c9cd8f
AY
153 if (!nchips) {
154 err = -ENODEV;
155 goto err_clk_unprepare;
156 }
66859249
NA
157
158 platform_set_drvdata(pdev, oxnas);
159
160 return 0;
24c9cd8f
AY
161
162err_clk_unprepare:
163 clk_disable_unprepare(oxnas->clk);
164 return err;
66859249
NA
165}
166
167static int oxnas_nand_remove(struct platform_device *pdev)
168{
169 struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
170
171 if (oxnas->chips[0])
59ac276f 172 nand_release(oxnas->chips[0]);
66859249
NA
173
174 clk_disable_unprepare(oxnas->clk);
175
176 return 0;
177}
178
179static const struct of_device_id oxnas_nand_match[] = {
180 { .compatible = "oxsemi,ox820-nand" },
181 {},
182};
183MODULE_DEVICE_TABLE(of, oxnas_nand_match);
184
185static struct platform_driver oxnas_nand_driver = {
186 .probe = oxnas_nand_probe,
187 .remove = oxnas_nand_remove,
188 .driver = {
189 .name = "oxnas_nand",
190 .of_match_table = oxnas_nand_match,
191 },
192};
193
194module_platform_driver(oxnas_nand_driver);
195
196MODULE_LICENSE("GPL");
197MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
198MODULE_DESCRIPTION("Oxnas NAND driver");
199MODULE_ALIAS("platform:oxnas_nand");