Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2012 - 2013 Michal Simek <monstr@monstr.eu> |
Michal Simek | 98d0f1f | 2018-01-17 07:37:47 +0100 | [diff] [blame] | 4 | * Copyright (C) 2012 - 2017 Xilinx, Inc. All rights reserved. |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 5 | */ |
| 6 | |
Tom Rini | dec7ea0 | 2024-05-20 13:35:03 -0600 | [diff] [blame^] | 7 | #include <linux/string.h> |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 8 | #include <asm/io.h> |
| 9 | #include <asm/arch/sys_proto.h> |
| 10 | #include <asm/arch/hardware.h> |
| 11 | |
Siva Durga Prasad Paladugu | d8e4e1c | 2017-05-12 15:04:11 +0530 | [diff] [blame] | 12 | #ifndef CONFIG_ZYNQ_DDRC_INIT |
| 13 | void zynq_ddrc_init(void) {} |
| 14 | #else |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 15 | /* Control regsiter bitfield definitions */ |
| 16 | #define ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK 0xC |
| 17 | #define ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT 2 |
| 18 | #define ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT 1 |
| 19 | |
| 20 | /* ECC scrub regsiter definitions */ |
| 21 | #define ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK 0x7 |
| 22 | #define ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED 0x4 |
| 23 | |
| 24 | void zynq_ddrc_init(void) |
| 25 | { |
| 26 | u32 width, ecctype; |
| 27 | |
| 28 | width = readl(&ddrc_base->ddrc_ctrl); |
| 29 | width = (width & ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK) >> |
| 30 | ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT; |
| 31 | ecctype = (readl(&ddrc_base->ecc_scrub) & |
| 32 | ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK); |
| 33 | |
| 34 | /* ECC is enabled when memory is in 16bit mode and it is enabled */ |
| 35 | if ((ecctype == ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED) && |
| 36 | (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)) { |
Michal Simek | 79e6794 | 2014-05-15 09:40:14 +0200 | [diff] [blame] | 37 | puts("ECC enabled "); |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 38 | /* |
| 39 | * Clear the first 1MB because it is not initialized from |
| 40 | * first stage bootloader. To get ECC to work all memory has |
| 41 | * been initialized by writing any value. |
| 42 | */ |
Wolfgang Denk | 6ae8083 | 2014-11-06 14:02:57 +0100 | [diff] [blame] | 43 | /* cppcheck-suppress nullPointer */ |
Michal Simek | 5d688f2 | 2014-04-25 14:19:00 +0200 | [diff] [blame] | 44 | memset((void *)0, 0, 1 * 1024 * 1024); |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 45 | } else { |
Michal Simek | 79e6794 | 2014-05-15 09:40:14 +0200 | [diff] [blame] | 46 | puts("ECC disabled "); |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 47 | } |
Michal Simek | f5ff7bc | 2013-06-17 14:37:01 +0200 | [diff] [blame] | 48 | } |
Siva Durga Prasad Paladugu | d8e4e1c | 2017-05-12 15:04:11 +0530 | [diff] [blame] | 49 | #endif |