blob: 41b93e660a0ac6e9e2bc116ba963af2c85e45260 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +09002/*
3 * Copyright (C) 2017 Socionext Inc.
4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +09005 */
6
Masahiro Yamadab1c72732017-10-14 02:21:18 +09007#include <clk.h>
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +09008#include <dm.h>
Simon Glass9bc15642020-02-03 07:36:16 -07009#include <dm/device_compat.h>
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090010#include <linux/io.h>
11#include <linux/ioport.h>
Masahiro Yamada2cf4eba2017-11-30 13:45:26 +090012#include <linux/printk.h>
Marek Vasut54f81072020-01-21 20:03:11 +010013#include <reset.h>
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090014
15#include "denali.h"
16
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090017struct denali_dt_data {
18 unsigned int revision;
19 unsigned int caps;
Masahiro Yamada6be38732020-01-30 00:55:55 +090020 unsigned int oob_skip_bytes;
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090021 const struct nand_ecc_caps *ecc_caps;
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090022};
23
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090024NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,
25 512, 8, 15);
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090026static const struct denali_dt_data denali_socfpga_data = {
27 .caps = DENALI_CAP_HW_ECC_FIXUP,
Masahiro Yamada6be38732020-01-30 00:55:55 +090028 .oob_skip_bytes = 2,
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090029 .ecc_caps = &denali_socfpga_ecc_caps,
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090030};
31
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090032NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,
33 1024, 8, 16, 24);
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090034static const struct denali_dt_data denali_uniphier_v5a_data = {
35 .caps = DENALI_CAP_HW_ECC_FIXUP |
36 DENALI_CAP_DMA_64BIT,
Masahiro Yamada6be38732020-01-30 00:55:55 +090037 .oob_skip_bytes = 8,
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090038 .ecc_caps = &denali_uniphier_v5a_ecc_caps,
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090039};
40
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090041NAND_ECC_CAPS_SINGLE(denali_uniphier_v5b_ecc_caps, denali_calc_ecc_bytes,
42 1024, 8, 16);
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090043static const struct denali_dt_data denali_uniphier_v5b_data = {
44 .revision = 0x0501,
45 .caps = DENALI_CAP_HW_ECC_FIXUP |
46 DENALI_CAP_DMA_64BIT,
Masahiro Yamada6be38732020-01-30 00:55:55 +090047 .oob_skip_bytes = 8,
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090048 .ecc_caps = &denali_uniphier_v5b_ecc_caps,
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090049};
50
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090051static const struct udevice_id denali_nand_dt_ids[] = {
52 {
53 .compatible = "altr,socfpga-denali-nand",
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090054 .data = (unsigned long)&denali_socfpga_data,
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090055 },
56 {
57 .compatible = "socionext,uniphier-denali-nand-v5a",
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090058 .data = (unsigned long)&denali_uniphier_v5a_data,
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090059 },
60 {
61 .compatible = "socionext,uniphier-denali-nand-v5b",
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090062 .data = (unsigned long)&denali_uniphier_v5b_data,
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090063 },
64 { /* sentinel */ }
65};
66
67static int denali_dt_probe(struct udevice *dev)
68{
69 struct denali_nand_info *denali = dev_get_priv(dev);
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090070 const struct denali_dt_data *data;
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +090071 struct clk clk, clk_x, clk_ecc;
Marek Vasut54f81072020-01-21 20:03:11 +010072 struct reset_ctl_bulk resets;
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090073 struct resource res;
74 int ret;
75
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090076 data = (void *)dev_get_driver_data(dev);
Masahiro Yamada6be38732020-01-30 00:55:55 +090077 if (WARN_ON(!data))
78 return -EINVAL;
79
80 denali->revision = data->revision;
81 denali->caps = data->caps;
82 denali->oob_skip_bytes = data->oob_skip_bytes;
83 denali->ecc_caps = data->ecc_caps;
Masahiro Yamada54fde8e2017-09-15 21:43:19 +090084
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090085 denali->dev = dev;
86
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090087 ret = dev_read_resource_byname(dev, "denali_reg", &res);
88 if (ret)
89 return ret;
90
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090091 denali->reg = devm_ioremap(dev, res.start, resource_size(&res));
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090092
93 ret = dev_read_resource_byname(dev, "nand_data", &res);
94 if (ret)
95 return ret;
96
Masahiro Yamada8b0c16f2017-11-22 02:38:32 +090097 denali->host = devm_ioremap(dev, res.start, resource_size(&res));
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +090098
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +090099 ret = clk_get_by_name(dev, "nand", &clk);
100 if (ret)
101 ret = clk_get_by_index(dev, 0, &clk);
Masahiro Yamadab1c72732017-10-14 02:21:18 +0900102 if (ret)
Masahiro Yamadabfee37c2020-01-21 20:03:10 +0100103 clk.dev = NULL;
Masahiro Yamadab1c72732017-10-14 02:21:18 +0900104
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +0900105 ret = clk_get_by_name(dev, "nand_x", &clk_x);
106 if (ret)
107 clk_x.dev = NULL;
108
109 ret = clk_get_by_name(dev, "ecc", &clk_ecc);
110 if (ret)
111 clk_ecc.dev = NULL;
112
Masahiro Yamadabfee37c2020-01-21 20:03:10 +0100113 if (clk.dev) {
114 ret = clk_enable(&clk);
115 if (ret)
116 return ret;
117 }
Masahiro Yamadab1c72732017-10-14 02:21:18 +0900118
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +0900119 if (clk_x.dev) {
120 ret = clk_enable(&clk_x);
121 if (ret)
122 return ret;
123 }
124
125 if (clk_ecc.dev) {
126 ret = clk_enable(&clk_ecc);
127 if (ret)
128 return ret;
129 }
130
131 if (clk_x.dev) {
Masahiro Yamada2d1fbc82018-12-19 20:03:18 +0900132 denali->clk_rate = clk_get_rate(&clk);
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +0900133 denali->clk_x_rate = clk_get_rate(&clk_x);
134 } else {
135 /*
136 * Hardcode the clock rates for the backward compatibility.
137 * This works for both SOCFPGA and UniPhier.
138 */
139 dev_notice(dev,
140 "necessary clock is missing. default clock rates are used.\n");
Masahiro Yamada2d1fbc82018-12-19 20:03:18 +0900141 denali->clk_rate = 50000000;
Masahiro Yamada8b86f5e2018-12-19 20:03:17 +0900142 denali->clk_x_rate = 200000000;
143 }
Masahiro Yamadab1c72732017-10-14 02:21:18 +0900144
Marek Vasut54f81072020-01-21 20:03:11 +0100145 ret = reset_get_bulk(dev, &resets);
Masahiro Yamada6b982ad2020-01-30 00:55:54 +0900146 if (ret) {
Simon Goldschmidtcedfa4e2019-03-01 20:12:34 +0100147 dev_warn(dev, "Can't get reset: %d\n", ret);
Masahiro Yamada6b982ad2020-01-30 00:55:54 +0900148 } else {
Marek Vasut54f81072020-01-21 20:03:11 +0100149 reset_deassert_bulk(&resets);
Simon Goldschmidtcedfa4e2019-03-01 20:12:34 +0100150
Masahiro Yamada6b982ad2020-01-30 00:55:54 +0900151 /*
152 * When the reset is deasserted, the initialization sequence is
153 * kicked (bootstrap process). The driver must wait until it is
154 * finished. Otherwise, it will result in unpredictable behavior.
155 */
156 udelay(200);
157 }
158
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +0900159 return denali_init(denali);
160}
161
162U_BOOT_DRIVER(denali_nand_dt) = {
163 .name = "denali-nand-dt",
Masahiro Yamada8fc53822020-01-30 22:07:59 +0900164 .id = UCLASS_MTD,
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +0900165 .of_match = denali_nand_dt_ids,
166 .probe = denali_dt_probe,
167 .priv_auto_alloc_size = sizeof(struct denali_nand_info),
168};
169
170void board_nand_init(void)
171{
172 struct udevice *dev;
173 int ret;
174
Masahiro Yamada8fc53822020-01-30 22:07:59 +0900175 ret = uclass_get_device_by_driver(UCLASS_MTD,
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +0900176 DM_GET_DRIVER(denali_nand_dt),
177 &dev);
178 if (ret && ret != -ENODEV)
Masahiro Yamada2cf4eba2017-11-30 13:45:26 +0900179 pr_err("Failed to initialize Denali NAND controller. (error %d)\n",
Masahiro Yamada9c5a5dd2017-08-26 01:12:31 +0900180 ret);
181}