openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nand / orion.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2009 by Marvell Semiconductors, Inc.                    *
5  *   Written by Nicolas Pitre <nico at marvell.com>                        *
6  ***************************************************************************/
7
8 /*
9  * NAND controller interface for Marvell Orion/Kirkwood SoCs.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include "imp.h"
17 #include "arm_io.h"
18 #include <target/arm.h>
19
20 struct orion_nand_controller {
21         struct arm_nand_data    io;
22
23         uint32_t                cmd;
24         uint32_t                addr;
25         uint32_t                data;
26 };
27
28 #define CHECK_HALTED \
29         do { \
30                 if (target->state != TARGET_HALTED) { \
31                         LOG_ERROR("NAND flash access requires halted target"); \
32                         return ERROR_NAND_OPERATION_FAILED; \
33                 } \
34         } while (0)
35
36 static int orion_nand_command(struct nand_device *nand, uint8_t command)
37 {
38         struct orion_nand_controller *hw = nand->controller_priv;
39         struct target *target = nand->target;
40
41         CHECK_HALTED;
42         target_write_u8(target, hw->cmd, command);
43         return ERROR_OK;
44 }
45
46 static int orion_nand_address(struct nand_device *nand, uint8_t address)
47 {
48         struct orion_nand_controller *hw = nand->controller_priv;
49         struct target *target = nand->target;
50
51         CHECK_HALTED;
52         target_write_u8(target, hw->addr, address);
53         return ERROR_OK;
54 }
55
56 static int orion_nand_read(struct nand_device *nand, void *data)
57 {
58         struct orion_nand_controller *hw = nand->controller_priv;
59         struct target *target = nand->target;
60
61         CHECK_HALTED;
62         target_read_u8(target, hw->data, data);
63         return ERROR_OK;
64 }
65
66 static int orion_nand_write(struct nand_device *nand, uint16_t data)
67 {
68         struct orion_nand_controller *hw = nand->controller_priv;
69         struct target *target = nand->target;
70
71         CHECK_HALTED;
72         target_write_u8(target, hw->data, data);
73         return ERROR_OK;
74 }
75
76 static int orion_nand_slow_block_write(struct nand_device *nand, uint8_t *data, int size)
77 {
78         while (size--)
79                 orion_nand_write(nand, *data++);
80         return ERROR_OK;
81 }
82
83 static int orion_nand_fast_block_write(struct nand_device *nand, uint8_t *data, int size)
84 {
85         struct orion_nand_controller *hw = nand->controller_priv;
86         int retval;
87
88         hw->io.chunk_size = nand->page_size;
89
90         retval = arm_nandwrite(&hw->io, data, size);
91         if (retval == ERROR_NAND_NO_BUFFER)
92                 retval = orion_nand_slow_block_write(nand, data, size);
93
94         return retval;
95 }
96
97 static int orion_nand_reset(struct nand_device *nand)
98 {
99         return orion_nand_command(nand, NAND_CMD_RESET);
100 }
101
102 NAND_DEVICE_COMMAND_HANDLER(orion_nand_device_command)
103 {
104         struct orion_nand_controller *hw;
105         uint32_t base;
106         uint8_t ale, cle;
107
108         if (CMD_ARGC != 3)
109                 return ERROR_COMMAND_SYNTAX_ERROR;
110
111         hw = calloc(1, sizeof(*hw));
112         if (!hw) {
113                 LOG_ERROR("no memory for nand controller");
114                 return ERROR_NAND_DEVICE_INVALID;
115         }
116
117         nand->controller_priv = hw;
118
119         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], base);
120         cle = 0;
121         ale = 1;
122
123         hw->data = base;
124         hw->cmd = base + (1 << cle);
125         hw->addr = base + (1 << ale);
126
127         hw->io.target = nand->target;
128         hw->io.data = hw->data;
129         hw->io.op = ARM_NAND_NONE;
130
131         return ERROR_OK;
132 }
133
134 static int orion_nand_init(struct nand_device *nand)
135 {
136         return ERROR_OK;
137 }
138
139 struct nand_flash_controller orion_nand_controller = {
140         .name = "orion",
141         .usage = "<target_id> <NAND_address>",
142         .command = orion_nand_command,
143         .address = orion_nand_address,
144         .read_data = orion_nand_read,
145         .write_data = orion_nand_write,
146         .write_block_data = orion_nand_fast_block_write,
147         .reset = orion_nand_reset,
148         .nand_device_command = orion_nand_device_command,
149         .init = orion_nand_init,
150 };