| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * JZ4780 NAND/external memory controller (NEMC) |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2015 Imagination Technologies |
|---|
| 5 | 6 | * Author: Alex Smith <alex@alex-smith.me.uk> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 8 | | - * under the terms of the GNU General Public License version 2 as published |
|---|
| 9 | | - * by the Free Software Foundation. |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | |
|---|
| 12 | 9 | #include <linux/clk.h> |
|---|
| 13 | 10 | #include <linux/init.h> |
|---|
| 11 | +#include <linux/io.h> |
|---|
| 14 | 12 | #include <linux/math64.h> |
|---|
| 15 | 13 | #include <linux/of.h> |
|---|
| 16 | 14 | #include <linux/of_address.h> |
|---|
| .. | .. |
|---|
| 24 | 22 | |
|---|
| 25 | 23 | #define NEMC_SMCRn(n) (0x14 + (((n) - 1) * 4)) |
|---|
| 26 | 24 | #define NEMC_NFCSR 0x50 |
|---|
| 25 | + |
|---|
| 26 | +#define NEMC_REG_LEN 0x54 |
|---|
| 27 | 27 | |
|---|
| 28 | 28 | #define NEMC_SMCR_SMT BIT(0) |
|---|
| 29 | 29 | #define NEMC_SMCR_BW_SHIFT 6 |
|---|
| .. | .. |
|---|
| 44 | 44 | #define NEMC_NFCSR_NFCEn(n) BIT((((n) - 1) << 1) + 1) |
|---|
| 45 | 45 | #define NEMC_NFCSR_TNFEn(n) BIT(16 + (n) - 1) |
|---|
| 46 | 46 | |
|---|
| 47 | +struct jz_soc_info { |
|---|
| 48 | + u8 tas_tah_cycles_max; |
|---|
| 49 | +}; |
|---|
| 50 | + |
|---|
| 47 | 51 | struct jz4780_nemc { |
|---|
| 48 | 52 | spinlock_t lock; |
|---|
| 49 | 53 | struct device *dev; |
|---|
| 54 | + const struct jz_soc_info *soc_info; |
|---|
| 50 | 55 | void __iomem *base; |
|---|
| 51 | 56 | struct clk *clk; |
|---|
| 52 | 57 | uint32_t clk_period; |
|---|
| .. | .. |
|---|
| 59 | 64 | * |
|---|
| 60 | 65 | * Return: The number of unique NEMC banks referred to by the specified NEMC |
|---|
| 61 | 66 | * child device. Unique here means that a device that references the same bank |
|---|
| 62 | | - * multiple times in the its "reg" property will only count once. |
|---|
| 67 | + * multiple times in its "reg" property will only count once. |
|---|
| 63 | 68 | */ |
|---|
| 64 | 69 | unsigned int jz4780_nemc_num_banks(struct device *dev) |
|---|
| 65 | 70 | { |
|---|
| .. | .. |
|---|
| 161 | 166 | * Conversion of tBP and tAW cycle counts to values supported by the |
|---|
| 162 | 167 | * hardware (round up to the next supported value). |
|---|
| 163 | 168 | */ |
|---|
| 164 | | - static const uint32_t convert_tBP_tAW[] = { |
|---|
| 169 | + static const u8 convert_tBP_tAW[] = { |
|---|
| 165 | 170 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, |
|---|
| 166 | 171 | |
|---|
| 167 | 172 | /* 11 - 12 -> 12 cycles */ |
|---|
| .. | .. |
|---|
| 202 | 207 | if (of_property_read_u32(node, "ingenic,nemc-tAS", &val) == 0) { |
|---|
| 203 | 208 | smcr &= ~NEMC_SMCR_TAS_MASK; |
|---|
| 204 | 209 | cycles = jz4780_nemc_ns_to_cycles(nemc, val); |
|---|
| 205 | | - if (cycles > 15) { |
|---|
| 210 | + if (cycles > nemc->soc_info->tas_tah_cycles_max) { |
|---|
| 206 | 211 | dev_err(nemc->dev, "tAS %u is too high (%u cycles)\n", |
|---|
| 207 | 212 | val, cycles); |
|---|
| 208 | 213 | return false; |
|---|
| .. | .. |
|---|
| 214 | 219 | if (of_property_read_u32(node, "ingenic,nemc-tAH", &val) == 0) { |
|---|
| 215 | 220 | smcr &= ~NEMC_SMCR_TAH_MASK; |
|---|
| 216 | 221 | cycles = jz4780_nemc_ns_to_cycles(nemc, val); |
|---|
| 217 | | - if (cycles > 15) { |
|---|
| 222 | + if (cycles > nemc->soc_info->tas_tah_cycles_max) { |
|---|
| 218 | 223 | dev_err(nemc->dev, "tAH %u is too high (%u cycles)\n", |
|---|
| 219 | 224 | val, cycles); |
|---|
| 220 | 225 | return false; |
|---|
| .. | .. |
|---|
| 278 | 283 | if (!nemc) |
|---|
| 279 | 284 | return -ENOMEM; |
|---|
| 280 | 285 | |
|---|
| 286 | + nemc->soc_info = device_get_match_data(dev); |
|---|
| 287 | + if (!nemc->soc_info) |
|---|
| 288 | + return -EINVAL; |
|---|
| 289 | + |
|---|
| 281 | 290 | spin_lock_init(&nemc->lock); |
|---|
| 282 | 291 | nemc->dev = dev; |
|---|
| 283 | 292 | |
|---|
| 284 | 293 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 285 | | - nemc->base = devm_ioremap_resource(dev, res); |
|---|
| 286 | | - if (IS_ERR(nemc->base)) { |
|---|
| 294 | + if (!res) |
|---|
| 295 | + return -EINVAL; |
|---|
| 296 | + |
|---|
| 297 | + /* |
|---|
| 298 | + * The driver currently only uses the registers up to offset |
|---|
| 299 | + * NEMC_REG_LEN. Since the EFUSE registers are in the middle of the |
|---|
| 300 | + * NEMC registers, we only request the registers we will use for now; |
|---|
| 301 | + * that way the EFUSE driver can probe too. |
|---|
| 302 | + */ |
|---|
| 303 | + if (!devm_request_mem_region(dev, res->start, NEMC_REG_LEN, dev_name(dev))) { |
|---|
| 304 | + dev_err(dev, "unable to request I/O memory region\n"); |
|---|
| 305 | + return -EBUSY; |
|---|
| 306 | + } |
|---|
| 307 | + |
|---|
| 308 | + nemc->base = devm_ioremap(dev, res->start, NEMC_REG_LEN); |
|---|
| 309 | + if (!nemc->base) { |
|---|
| 287 | 310 | dev_err(dev, "failed to get I/O memory\n"); |
|---|
| 288 | | - return PTR_ERR(nemc->base); |
|---|
| 311 | + return -ENOMEM; |
|---|
| 289 | 312 | } |
|---|
| 290 | 313 | |
|---|
| 291 | 314 | writel(0, nemc->base + NEMC_NFCSR); |
|---|
| .. | .. |
|---|
| 370 | 393 | return 0; |
|---|
| 371 | 394 | } |
|---|
| 372 | 395 | |
|---|
| 396 | +static const struct jz_soc_info jz4740_soc_info = { |
|---|
| 397 | + .tas_tah_cycles_max = 7, |
|---|
| 398 | +}; |
|---|
| 399 | + |
|---|
| 400 | +static const struct jz_soc_info jz4780_soc_info = { |
|---|
| 401 | + .tas_tah_cycles_max = 15, |
|---|
| 402 | +}; |
|---|
| 403 | + |
|---|
| 373 | 404 | static const struct of_device_id jz4780_nemc_dt_match[] = { |
|---|
| 374 | | - { .compatible = "ingenic,jz4780-nemc" }, |
|---|
| 405 | + { .compatible = "ingenic,jz4740-nemc", .data = &jz4740_soc_info, }, |
|---|
| 406 | + { .compatible = "ingenic,jz4780-nemc", .data = &jz4780_soc_info, }, |
|---|
| 375 | 407 | {}, |
|---|
| 376 | 408 | }; |
|---|
| 377 | 409 | |
|---|