blob: 8bc45e50be7015c2da32b412e2676a74a9cf87e9 [file] [log] [blame]
Angel Ponsbbc99cf2020-04-04 18:51:23 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Julius Werner4783db22018-03-27 16:28:52 -07002
3/* Compile this driver in place of common/spi.c for bitbang testing.
4 NOTE: Also need to adjust board-specific code for GPIO pinmux! */
5
6#include <assert.h>
7#include <gpio.h>
8#include <soc/spi.h>
9#include <spi_bitbang.h>
10#include <spi_flash.h>
Elyes HAOUASc379d462020-07-27 08:16:24 +020011#include <stddef.h>
Julius Werner4783db22018-03-27 16:28:52 -070012
13struct rockchip_bitbang_slave {
14 struct spi_bitbang_ops ops;
15 gpio_t miso;
16 gpio_t mosi;
17 gpio_t clk;
18 gpio_t cs;
19};
20
21static int get_miso(const struct spi_bitbang_ops *ops)
22{
23 const struct rockchip_bitbang_slave *slave =
24 container_of(ops, const struct rockchip_bitbang_slave, ops);
25 return gpio_get(slave->miso);
26}
27
28static void set_mosi(const struct spi_bitbang_ops *ops, int value)
29{
30 const struct rockchip_bitbang_slave *slave =
31 container_of(ops, const struct rockchip_bitbang_slave, ops);
32 gpio_set(slave->mosi, value);
33}
34
35static void set_clk(const struct spi_bitbang_ops *ops, int value)
36{
37 const struct rockchip_bitbang_slave *slave =
38 container_of(ops, const struct rockchip_bitbang_slave, ops);
39 gpio_set(slave->clk, value);
40}
41
42static void set_cs(const struct spi_bitbang_ops *ops, int value)
43{
44 const struct rockchip_bitbang_slave *slave =
45 container_of(ops, const struct rockchip_bitbang_slave, ops);
46 gpio_set(slave->cs, value);
47}
48
Jon Murphyc4e90452022-06-28 10:36:23 -060049/* Can't use GPIO() here because of bug in GCC version used by ChromiumOS. */
Julius Werner4783db22018-03-27 16:28:52 -070050static const struct rockchip_bitbang_slave slaves[] = {
51 [0] = {
52 .ops = { get_miso, set_mosi, set_clk, set_cs },
53 .miso = { .port = 3, .bank = GPIO_A, .idx = 4 },
54 .mosi = { .port = 3, .bank = GPIO_A, .idx = 5 },
55 .clk = { .port = 3, .bank = GPIO_A, .idx = 6 },
56 .cs = { .port = 3, .bank = GPIO_A, .idx = 7 },
57 },
58 [1] = {
59 .ops = { get_miso, set_mosi, set_clk, set_cs },
60 .miso = { .port = 1, .bank = GPIO_A, .idx = 7 },
61 .mosi = { .port = 1, .bank = GPIO_B, .idx = 0 },
62 .clk = { .port = 1, .bank = GPIO_B, .idx = 1 },
63 .cs = { .port = 1, .bank = GPIO_B, .idx = 2 },
64 },
65 [2] = {
66 .ops = { get_miso, set_mosi, set_clk, set_cs },
67 .miso = { .port = 2, .bank = GPIO_B, .idx = 1 },
68 .mosi = { .port = 2, .bank = GPIO_B, .idx = 2 },
69 .clk = { .port = 2, .bank = GPIO_B, .idx = 3 },
70 .cs = { .port = 2, .bank = GPIO_B, .idx = 4 },
71 },
72 [3] = {
73 .ops = { get_miso, set_mosi, set_clk, set_cs },
74 .miso = { .port = 1, .bank = GPIO_B, .idx = 7 },
75 .mosi = { .port = 1, .bank = GPIO_C, .idx = 0 },
76 .clk = { .port = 1, .bank = GPIO_C, .idx = 1 },
77 .cs = { .port = 1, .bank = GPIO_C, .idx = 2 },
78 },
79 [4] = {
80 .ops = { get_miso, set_mosi, set_clk, set_cs },
81 .miso = { .port = 3, .bank = GPIO_A, .idx = 0 },
82 .mosi = { .port = 3, .bank = GPIO_A, .idx = 1 },
83 .clk = { .port = 3, .bank = GPIO_A, .idx = 2 },
84 .cs = { .port = 3, .bank = GPIO_A, .idx = 3 },
85 },
86 [5] = {
87 .ops = { get_miso, set_mosi, set_clk, set_cs },
88 .miso = { .port = 2, .bank = GPIO_C, .idx = 4 },
89 .mosi = { .port = 2, .bank = GPIO_C, .idx = 5 },
90 .clk = { .port = 2, .bank = GPIO_C, .idx = 6 },
91 .cs = { .port = 2, .bank = GPIO_C, .idx = 7 },
92 },
93};
94
95void rockchip_spi_init(unsigned int bus, unsigned int ignored_speed_hz)
96{
97 assert(bus >= 0 && bus < ARRAY_SIZE(slaves));
98
99 gpio_output(slaves[bus].cs, 1);
100 gpio_output(slaves[bus].clk, 0);
101 gpio_input(slaves[bus].miso);
102 gpio_output(slaves[bus].mosi, 0);
103}
104
105void rockchip_spi_set_sample_delay(unsigned int bus, unsigned int delay_ns)
106{
107 /* not supported, and not necessary for slow bitbang speeds */
108}
109
110static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
111{
112 assert(slave->bus >= 0 && slave->bus < ARRAY_SIZE(slaves));
113 return spi_bitbang_claim_bus(&slaves[slave->bus].ops);
114}
115
116static void spi_ctrlr_release_bus(const struct spi_slave *slave)
117{
118 assert(slave->bus >= 0 && slave->bus < ARRAY_SIZE(slaves));
119 spi_bitbang_release_bus(&slaves[slave->bus].ops);
120}
121
122static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
123 size_t bytes_out, void *din, size_t bytes_in)
124{
125 assert(slave->bus >= 0 && slave->bus < ARRAY_SIZE(slaves));
126 return spi_bitbang_xfer(&slaves[slave->bus].ops,
127 dout, bytes_out, din, bytes_in);
128}
129
130static const struct spi_ctrlr spi_ctrlr = {
131 .claim_bus = spi_ctrlr_claim_bus,
132 .release_bus = spi_ctrlr_release_bus,
133 .xfer = spi_ctrlr_xfer,
134 .max_xfer_size = 65535,
135};
136
137const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
138 {
139 .ctrlr = &spi_ctrlr,
140 .bus_start = 0,
141 .bus_end = ARRAY_SIZE(slaves) - 1,
142 },
143};
144
145const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);