diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2018-12-20 01:19:29 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-12-20 10:26:59 -0500 |
commit | 4ce193fdba48516717a4840043abb83f71109ee2 (patch) | |
tree | 498a3f96c989494255b5bc79165b47074ab987af /drivers/tty/serial/sccnxp.c | |
parent | 663abb1a7a7ff8fea9ab0145463de7fcff823755 (diff) |
serial: sccnxp: Adds a delay between sequential read/write cycles
This patch adds a delay between sequential read/write cycles,
to ensure the required minimum inactive time (tRWD). A time value
from the datasheet has been added for each type of supported chips.
The “inline” compiler attribute has been removed from the
read/write functions, simply allow the compiler to control this.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/sccnxp.c')
-rw-r--r-- | drivers/tty/serial/sccnxp.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 339befdd2f4d..c0a68eee4479 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/mod_devicetable.h> | 18 | #include <linux/mod_devicetable.h> |
@@ -103,6 +104,8 @@ struct sccnxp_chip { | |||
103 | unsigned long freq_max; | 104 | unsigned long freq_max; |
104 | unsigned int flags; | 105 | unsigned int flags; |
105 | unsigned int fifosize; | 106 | unsigned int fifosize; |
107 | /* Time between read/write cycles */ | ||
108 | unsigned int trwd; | ||
106 | }; | 109 | }; |
107 | 110 | ||
108 | struct sccnxp_port { | 111 | struct sccnxp_port { |
@@ -137,6 +140,7 @@ static const struct sccnxp_chip sc2681 = { | |||
137 | .freq_max = 4000000, | 140 | .freq_max = 4000000, |
138 | .flags = SCCNXP_HAVE_IO, | 141 | .flags = SCCNXP_HAVE_IO, |
139 | .fifosize = 3, | 142 | .fifosize = 3, |
143 | .trwd = 200, | ||
140 | }; | 144 | }; |
141 | 145 | ||
142 | static const struct sccnxp_chip sc2691 = { | 146 | static const struct sccnxp_chip sc2691 = { |
@@ -147,6 +151,7 @@ static const struct sccnxp_chip sc2691 = { | |||
147 | .freq_max = 4000000, | 151 | .freq_max = 4000000, |
148 | .flags = 0, | 152 | .flags = 0, |
149 | .fifosize = 3, | 153 | .fifosize = 3, |
154 | .trwd = 150, | ||
150 | }; | 155 | }; |
151 | 156 | ||
152 | static const struct sccnxp_chip sc2692 = { | 157 | static const struct sccnxp_chip sc2692 = { |
@@ -157,6 +162,7 @@ static const struct sccnxp_chip sc2692 = { | |||
157 | .freq_max = 4000000, | 162 | .freq_max = 4000000, |
158 | .flags = SCCNXP_HAVE_IO, | 163 | .flags = SCCNXP_HAVE_IO, |
159 | .fifosize = 3, | 164 | .fifosize = 3, |
165 | .trwd = 30, | ||
160 | }; | 166 | }; |
161 | 167 | ||
162 | static const struct sccnxp_chip sc2891 = { | 168 | static const struct sccnxp_chip sc2891 = { |
@@ -167,6 +173,7 @@ static const struct sccnxp_chip sc2891 = { | |||
167 | .freq_max = 8000000, | 173 | .freq_max = 8000000, |
168 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, | 174 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, |
169 | .fifosize = 16, | 175 | .fifosize = 16, |
176 | .trwd = 27, | ||
170 | }; | 177 | }; |
171 | 178 | ||
172 | static const struct sccnxp_chip sc2892 = { | 179 | static const struct sccnxp_chip sc2892 = { |
@@ -177,6 +184,7 @@ static const struct sccnxp_chip sc2892 = { | |||
177 | .freq_max = 8000000, | 184 | .freq_max = 8000000, |
178 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, | 185 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, |
179 | .fifosize = 16, | 186 | .fifosize = 16, |
187 | .trwd = 17, | ||
180 | }; | 188 | }; |
181 | 189 | ||
182 | static const struct sccnxp_chip sc28202 = { | 190 | static const struct sccnxp_chip sc28202 = { |
@@ -187,6 +195,7 @@ static const struct sccnxp_chip sc28202 = { | |||
187 | .freq_max = 50000000, | 195 | .freq_max = 50000000, |
188 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, | 196 | .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, |
189 | .fifosize = 256, | 197 | .fifosize = 256, |
198 | .trwd = 10, | ||
190 | }; | 199 | }; |
191 | 200 | ||
192 | static const struct sccnxp_chip sc68681 = { | 201 | static const struct sccnxp_chip sc68681 = { |
@@ -197,6 +206,7 @@ static const struct sccnxp_chip sc68681 = { | |||
197 | .freq_max = 4000000, | 206 | .freq_max = 4000000, |
198 | .flags = SCCNXP_HAVE_IO, | 207 | .flags = SCCNXP_HAVE_IO, |
199 | .fifosize = 3, | 208 | .fifosize = 3, |
209 | .trwd = 200, | ||
200 | }; | 210 | }; |
201 | 211 | ||
202 | static const struct sccnxp_chip sc68692 = { | 212 | static const struct sccnxp_chip sc68692 = { |
@@ -207,24 +217,36 @@ static const struct sccnxp_chip sc68692 = { | |||
207 | .freq_max = 4000000, | 217 | .freq_max = 4000000, |
208 | .flags = SCCNXP_HAVE_IO, | 218 | .flags = SCCNXP_HAVE_IO, |
209 | .fifosize = 3, | 219 | .fifosize = 3, |
220 | .trwd = 200, | ||
210 | }; | 221 | }; |
211 | 222 | ||
212 | static inline u8 sccnxp_read(struct uart_port *port, u8 reg) | 223 | static u8 sccnxp_read(struct uart_port *port, u8 reg) |
213 | { | 224 | { |
214 | return readb(port->membase + (reg << port->regshift)); | 225 | struct sccnxp_port *s = dev_get_drvdata(port->dev); |
226 | u8 ret; | ||
227 | |||
228 | ret = readb(port->membase + (reg << port->regshift)); | ||
229 | |||
230 | ndelay(s->chip->trwd); | ||
231 | |||
232 | return ret; | ||
215 | } | 233 | } |
216 | 234 | ||
217 | static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v) | 235 | static void sccnxp_write(struct uart_port *port, u8 reg, u8 v) |
218 | { | 236 | { |
237 | struct sccnxp_port *s = dev_get_drvdata(port->dev); | ||
238 | |||
219 | writeb(v, port->membase + (reg << port->regshift)); | 239 | writeb(v, port->membase + (reg << port->regshift)); |
240 | |||
241 | ndelay(s->chip->trwd); | ||
220 | } | 242 | } |
221 | 243 | ||
222 | static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg) | 244 | static u8 sccnxp_port_read(struct uart_port *port, u8 reg) |
223 | { | 245 | { |
224 | return sccnxp_read(port, (port->line << 3) + reg); | 246 | return sccnxp_read(port, (port->line << 3) + reg); |
225 | } | 247 | } |
226 | 248 | ||
227 | static inline void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v) | 249 | static void sccnxp_port_write(struct uart_port *port, u8 reg, u8 v) |
228 | { | 250 | { |
229 | sccnxp_write(port, (port->line << 3) + reg, v); | 251 | sccnxp_write(port, (port->line << 3) + reg, v); |
230 | } | 252 | } |