~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/spi/sandbox_spi.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Simulate a SPI port
 
3
 *
 
4
 * Copyright (c) 2011-2013 The Chromium OS Authors.
 
5
 * See file CREDITS for list of people who contributed to this
 
6
 * project.
 
7
 *
 
8
 * Licensed under the GPL-2 or later.
 
9
 */
 
10
 
 
11
#include <common.h>
 
12
#include <malloc.h>
 
13
#include <spi.h>
 
14
#include <os.h>
 
15
 
 
16
#include <asm/errno.h>
 
17
#include <asm/spi.h>
 
18
#include <asm/state.h>
 
19
 
 
20
#ifndef CONFIG_SPI_IDLE_VAL
 
21
# define CONFIG_SPI_IDLE_VAL 0xFF
 
22
#endif
 
23
 
 
24
struct sandbox_spi_slave {
 
25
        struct spi_slave slave;
 
26
        const struct sandbox_spi_emu_ops *ops;
 
27
        void *priv;
 
28
};
 
29
 
 
30
#define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave)
 
31
 
 
32
const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
 
33
                                   unsigned long *cs)
 
34
{
 
35
        char *endp;
 
36
 
 
37
        *bus = simple_strtoul(arg, &endp, 0);
 
38
        if (*endp != ':' || *bus >= CONFIG_SANDBOX_SPI_MAX_BUS)
 
39
                return NULL;
 
40
 
 
41
        *cs = simple_strtoul(endp + 1, &endp, 0);
 
42
        if (*endp != ':' || *cs >= CONFIG_SANDBOX_SPI_MAX_CS)
 
43
                return NULL;
 
44
 
 
45
        return endp + 1;
 
46
}
 
47
 
 
48
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 
49
{
 
50
        return bus < CONFIG_SANDBOX_SPI_MAX_BUS &&
 
51
                cs < CONFIG_SANDBOX_SPI_MAX_CS;
 
52
}
 
53
 
 
54
void spi_cs_activate(struct spi_slave *slave)
 
55
{
 
56
        struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
 
57
 
 
58
        debug("sandbox_spi: activating CS\n");
 
59
        if (sss->ops->cs_activate)
 
60
                sss->ops->cs_activate(sss->priv);
 
61
}
 
62
 
 
63
void spi_cs_deactivate(struct spi_slave *slave)
 
64
{
 
65
        struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
 
66
 
 
67
        debug("sandbox_spi: deactivating CS\n");
 
68
        if (sss->ops->cs_deactivate)
 
69
                sss->ops->cs_deactivate(sss->priv);
 
70
}
 
71
 
 
72
void spi_init(void)
 
73
{
 
74
}
 
75
 
 
76
void spi_set_speed(struct spi_slave *slave, uint hz)
 
77
{
 
78
}
 
79
 
 
80
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
81
                unsigned int max_hz, unsigned int mode)
 
82
{
 
83
        struct sandbox_spi_slave *sss;
 
84
        struct sandbox_state *state = state_get_current();
 
85
        const char *spec;
 
86
 
 
87
        if (!spi_cs_is_valid(bus, cs)) {
 
88
                debug("sandbox_spi: Invalid SPI bus/cs\n");
 
89
                return NULL;
 
90
        }
 
91
 
 
92
        sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs);
 
93
        if (!sss) {
 
94
                debug("sandbox_spi: Out of memory\n");
 
95
                return NULL;
 
96
        }
 
97
 
 
98
        spec = state->spi[bus][cs].spec;
 
99
        sss->ops = state->spi[bus][cs].ops;
 
100
        if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) {
 
101
                free(sss);
 
102
                printf("sandbox_spi: unable to locate a slave client\n");
 
103
                return NULL;
 
104
        }
 
105
 
 
106
        return &sss->slave;
 
107
}
 
108
 
 
109
void spi_free_slave(struct spi_slave *slave)
 
110
{
 
111
        struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
 
112
 
 
113
        debug("sandbox_spi: releasing slave\n");
 
114
 
 
115
        if (sss->ops->free)
 
116
                sss->ops->free(sss->priv);
 
117
 
 
118
        free(sss);
 
119
}
 
120
 
 
121
static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS];
 
122
 
 
123
int spi_claim_bus(struct spi_slave *slave)
 
124
{
 
125
        if (spi_bus_claim_cnt[slave->bus]++) {
 
126
                printf("sandbox_spi: error: bus already claimed: %d!\n",
 
127
                       spi_bus_claim_cnt[slave->bus]);
 
128
        }
 
129
 
 
130
        return 0;
 
131
}
 
132
 
 
133
void spi_release_bus(struct spi_slave *slave)
 
134
{
 
135
        if (--spi_bus_claim_cnt[slave->bus]) {
 
136
                printf("sandbox_spi: error: bus freed too often: %d!\n",
 
137
                       spi_bus_claim_cnt[slave->bus]);
 
138
        }
 
139
}
 
140
 
 
141
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 
142
                void *din, unsigned long flags)
 
143
{
 
144
        struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
 
145
        uint bytes = bitlen / 8, i;
 
146
        int ret = 0;
 
147
        u8 *tx = (void *)dout, *rx = din;
 
148
 
 
149
        if (bitlen == 0)
 
150
                goto done;
 
151
 
 
152
        /* we can only do 8 bit transfers */
 
153
        if (bitlen % 8) {
 
154
                printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
 
155
                       bitlen);
 
156
                flags |= SPI_XFER_END;
 
157
                goto done;
 
158
        }
 
159
 
 
160
        if (flags & SPI_XFER_BEGIN)
 
161
                spi_cs_activate(slave);
 
162
 
 
163
        /* make sure rx/tx buffers are full so clients can assume */
 
164
        if (!tx) {
 
165
                debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n");
 
166
                tx = malloc(bytes);
 
167
                if (!tx) {
 
168
                        debug("sandbox_spi: Out of memory\n");
 
169
                        return -ENOMEM;
 
170
                }
 
171
        }
 
172
        if (!rx) {
 
173
                debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n");
 
174
                rx = malloc(bytes);
 
175
                if (!rx) {
 
176
                        debug("sandbox_spi: Out of memory\n");
 
177
                        return -ENOMEM;
 
178
                }
 
179
        }
 
180
 
 
181
        debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes);
 
182
        for (i = 0; i < bytes; ++i)
 
183
                debug(" %u:%02x", i, tx[i]);
 
184
        debug("\n");
 
185
 
 
186
        ret = sss->ops->xfer(sss->priv, tx, rx, bytes);
 
187
 
 
188
        debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
 
189
              ret, ret ? "bad" : "good");
 
190
        for (i = 0; i < bytes; ++i)
 
191
                debug(" %u:%02x", i, rx[i]);
 
192
        debug("\n");
 
193
 
 
194
        if (tx != dout)
 
195
                free(tx);
 
196
        if (rx != din)
 
197
                free(rx);
 
198
 
 
199
 done:
 
200
        if (flags & SPI_XFER_END)
 
201
                spi_cs_deactivate(slave);
 
202
 
 
203
        return ret;
 
204
}
 
205
 
 
206
/**
 
207
 * Set up a new SPI slave for an fdt node
 
208
 *
 
209
 * @param blob          Device tree blob
 
210
 * @param node          SPI peripheral node to use
 
211
 * @return 0 if ok, -1 on error
 
212
 */
 
213
struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
 
214
                                      int spi_node)
 
215
{
 
216
        return NULL;
 
217
}