1/*
2 * Broadcom chipcommon NAND flash interface
3 *
4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id:$
19 */
20
21#include <typedefs.h>
22#include <osl.h>
23#include <bcmutils.h>
24#include <siutils.h>
25#include <hndsoc.h>
26#include <sbhndcpu.h>
27#include <sbchipc.h>
28#include <bcmdevs.h>
29#include <hndsflash.h>
30
31/* Private global state */
32static hndsflash_t *hndsflash;
33
34hndsflash_t *ccsflash_init(si_t *sih);
35hndsflash_t *spiflash_init(si_t *sih);
36
37/* Initialize nand flash access */
38hndsflash_t *
39hndsflash_init(si_t *sih)
40{
41	uint32 origidx;
42
43	ASSERT(sih);
44
45	/* Already initialized ? */
46	if (hndsflash)
47		return hndsflash;
48
49	/* spin lock here */
50	origidx = si_coreidx(sih);
51
52#ifdef	__mips__
53	if (!hndsflash)
54		hndsflash = ccsflash_init(sih);
55#endif	/* __mips__ */
56#ifdef __ARM_ARCH_7A__
57	if (!hndsflash)
58		hndsflash = spiflash_init(sih);
59#endif	/* __ARM_ARCH_7A__ */
60
61	si_setcoreidx(sih, origidx);
62	return hndsflash;
63}
64
65/* Read len bytes starting at offset into buf. Returns number of bytes read. */
66int
67hndsflash_read(hndsflash_t *sfl, uint offset, uint len, const uchar *buf)
68{
69	ASSERT(sfl);
70	ASSERT(sfl->read);
71
72	return (sfl->read)(sfl, offset, len, buf);
73}
74
75/* Write len bytes starting at offset into buf. Returns number of bytes
76 * written.
77 */
78int
79hndsflash_write(hndsflash_t *sfl, uint offset, uint len, const uchar *buf)
80{
81	ASSERT(sfl);
82	ASSERT(sfl->write);
83
84	return (sfl->write)(sfl, offset, len, (const uchar *)buf);
85}
86
87/* Erase a region. Returns number of bytes scheduled for erasure.
88 * Caller should poll for completion.
89 */
90int
91hndsflash_erase(hndsflash_t *sfl, uint offset)
92{
93	ASSERT(sfl);
94	ASSERT(sfl->erase);
95
96	return (sfl->erase)(sfl, offset);
97}
98
99/*
100 * writes the appropriate range of flash, a NULL buf simply erases
101 * the region of flash
102 */
103int hndsflash_commit(hndsflash_t *sfl, uint offset, uint len, const uchar *buf)
104{
105	ASSERT(sfl);
106	ASSERT(sfl->commit);
107
108	return (sfl->commit)(sfl, offset, len, (const uchar *)buf);
109}
110
111/* Poll for command completion. Returns zero when complete. */
112int hndsflash_poll(hndsflash_t *sfl, uint offset)
113{
114	ASSERT(sfl);
115
116	if (!sfl->poll)
117		return 0;
118
119	return (sfl->poll)(sfl, offset);
120}
121