aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2014-03-20 05:20:36 -0400
committerBrian Norris <computersforpeace@gmail.com>2014-03-20 07:17:14 -0400
commit3c8b85b340c7a6b47d50c12c03661c23a5858b88 (patch)
tree3023497f1e5d493abb80d3c03428b707a2eef19c /drivers/mtd/devices
parent86f309fd8fb291039a3776593a0b2a9d86c895ab (diff)
mtd: st_spi_fsm: Supply framework for device requests
The FSM hardware works by setting a predetermined sequence of register writes. Rather than open coding them inside each functional block we're going to define them in a series of formatted 'sequence structures'. This patch provides the framework which shall be used for every action. Acked-by Angus Clark <angus.clark@st.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/st_spi_fsm.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/mtd/devices/st_spi_fsm.c b/drivers/mtd/devices/st_spi_fsm.c
index 7048ea75bf27..5e22c8688197 100644
--- a/drivers/mtd/devices/st_spi_fsm.c
+++ b/drivers/mtd/devices/st_spi_fsm.c
@@ -194,6 +194,8 @@
194 194
195#define STFSM_FLASH_SAFE_FREQ 10000000UL /* 10 MHz */ 195#define STFSM_FLASH_SAFE_FREQ 10000000UL /* 10 MHz */
196 196
197#define STFSM_MAX_WAIT_SEQ_MS 1000 /* FSM execution time */
198
197struct stfsm { 199struct stfsm {
198 struct device *dev; 200 struct device *dev;
199 void __iomem *base; 201 void __iomem *base;
@@ -204,6 +206,24 @@ struct stfsm {
204 uint32_t fifo_dir_delay; 206 uint32_t fifo_dir_delay;
205}; 207};
206 208
209struct stfsm_seq {
210 uint32_t data_size;
211 uint32_t addr1;
212 uint32_t addr2;
213 uint32_t addr_cfg;
214 uint32_t seq_opc[5];
215 uint32_t mode;
216 uint32_t dummy;
217 uint32_t status;
218 uint8_t seq[16];
219 uint32_t seq_cfg;
220} __packed __aligned(4);
221
222static inline int stfsm_is_idle(struct stfsm *fsm)
223{
224 return readl(fsm->base + SPI_FAST_SEQ_STA) & 0x10;
225}
226
207static inline uint32_t stfsm_fifo_available(struct stfsm *fsm) 227static inline uint32_t stfsm_fifo_available(struct stfsm *fsm)
208{ 228{
209 return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f; 229 return (readl(fsm->base + SPI_FAST_SEQ_STA) >> 5) & 0x7f;
@@ -225,6 +245,42 @@ static void stfsm_clear_fifo(struct stfsm *fsm)
225 } 245 }
226} 246}
227 247
248static inline void stfsm_load_seq(struct stfsm *fsm,
249 const struct stfsm_seq *seq)
250{
251 void __iomem *dst = fsm->base + SPI_FAST_SEQ_TRANSFER_SIZE;
252 const uint32_t *src = (const uint32_t *)seq;
253 int words = sizeof(*seq) / sizeof(*src);
254
255 BUG_ON(!stfsm_is_idle(fsm));
256
257 while (words--) {
258 writel(*src, dst);
259 src++;
260 dst += 4;
261 }
262}
263
264static void stfsm_wait_seq(struct stfsm *fsm)
265{
266 unsigned long deadline;
267 int timeout = 0;
268
269 deadline = jiffies + msecs_to_jiffies(STFSM_MAX_WAIT_SEQ_MS);
270
271 while (!timeout) {
272 if (time_after_eq(jiffies, deadline))
273 timeout = 1;
274
275 if (stfsm_is_idle(fsm))
276 return;
277
278 cond_resched();
279 }
280
281 dev_err(fsm->dev, "timeout on sequence completion\n");
282}
283
228static int stfsm_set_mode(struct stfsm *fsm, uint32_t mode) 284static int stfsm_set_mode(struct stfsm *fsm, uint32_t mode)
229{ 285{
230 int ret, timeout = 10; 286 int ret, timeout = 10;