]> git.sur5r.net Git - u-boot/blob - drivers/spi/altera_spi.c
Remove unnecessary instances of DECLARE_GLOBAL_DATA_PTR
[u-boot] / drivers / spi / altera_spi.c
1 /*
2  * Altera SPI driver
3  *
4  * based on bfin_spi.c
5  * Copyright (c) 2005-2008 Analog Devices Inc.
6  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10 #include <common.h>
11 #include <dm.h>
12 #include <errno.h>
13 #include <malloc.h>
14 #include <fdtdec.h>
15 #include <spi.h>
16 #include <asm/io.h>
17
18 #define ALTERA_SPI_STATUS_RRDY_MSK      BIT(7)
19 #define ALTERA_SPI_CONTROL_SSO_MSK      BIT(10)
20
21 #ifndef CONFIG_ALTERA_SPI_IDLE_VAL
22 #define CONFIG_ALTERA_SPI_IDLE_VAL      0xff
23 #endif
24
25 struct altera_spi_regs {
26         u32     rxdata;
27         u32     txdata;
28         u32     status;
29         u32     control;
30         u32     _reserved;
31         u32     slave_sel;
32 };
33
34 struct altera_spi_platdata {
35         struct altera_spi_regs *regs;
36 };
37
38 struct altera_spi_priv {
39         struct altera_spi_regs *regs;
40 };
41
42 static void spi_cs_activate(struct udevice *dev, uint cs)
43 {
44         struct udevice *bus = dev->parent;
45         struct altera_spi_priv *priv = dev_get_priv(bus);
46         struct altera_spi_regs *const regs = priv->regs;
47
48         writel(1 << cs, &regs->slave_sel);
49         writel(ALTERA_SPI_CONTROL_SSO_MSK, &regs->control);
50 }
51
52 static void spi_cs_deactivate(struct udevice *dev)
53 {
54         struct udevice *bus = dev->parent;
55         struct altera_spi_priv *priv = dev_get_priv(bus);
56         struct altera_spi_regs *const regs = priv->regs;
57
58         writel(0, &regs->control);
59         writel(0, &regs->slave_sel);
60 }
61
62 static int altera_spi_claim_bus(struct udevice *dev)
63 {
64         struct udevice *bus = dev->parent;
65         struct altera_spi_priv *priv = dev_get_priv(bus);
66         struct altera_spi_regs *const regs = priv->regs;
67
68         writel(0, &regs->control);
69         writel(0, &regs->slave_sel);
70
71         return 0;
72 }
73
74 static int altera_spi_release_bus(struct udevice *dev)
75 {
76         struct udevice *bus = dev->parent;
77         struct altera_spi_priv *priv = dev_get_priv(bus);
78         struct altera_spi_regs *const regs = priv->regs;
79
80         writel(0, &regs->slave_sel);
81
82         return 0;
83 }
84
85 static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen,
86                             const void *dout, void *din, unsigned long flags)
87 {
88         struct udevice *bus = dev->parent;
89         struct altera_spi_priv *priv = dev_get_priv(bus);
90         struct altera_spi_regs *const regs = priv->regs;
91         struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
92
93         /* assume spi core configured to do 8 bit transfers */
94         unsigned int bytes = bitlen / 8;
95         const unsigned char *txp = dout;
96         unsigned char *rxp = din;
97         uint32_t reg, data, start;
98
99         debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
100               bus->seq, slave_plat->cs, bitlen, bytes, flags);
101
102         if (bitlen == 0)
103                 goto done;
104
105         if (bitlen % 8) {
106                 flags |= SPI_XFER_END;
107                 goto done;
108         }
109
110         /* empty read buffer */
111         if (readl(&regs->status) & ALTERA_SPI_STATUS_RRDY_MSK)
112                 readl(&regs->rxdata);
113
114         if (flags & SPI_XFER_BEGIN)
115                 spi_cs_activate(dev, slave_plat->cs);
116
117         while (bytes--) {
118                 if (txp)
119                         data = *txp++;
120                 else
121                         data = CONFIG_ALTERA_SPI_IDLE_VAL;
122
123                 debug("%s: tx:%x ", __func__, data);
124                 writel(data, &regs->txdata);
125
126                 start = get_timer(0);
127                 while (1) {
128                         reg = readl(&regs->status);
129                         if (reg & ALTERA_SPI_STATUS_RRDY_MSK)
130                                 break;
131                         if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
132                                 debug("%s: Transmission timed out!\n", __func__);
133                                 return -1;
134                         }
135                 }
136
137                 data = readl(&regs->rxdata);
138                 if (rxp)
139                         *rxp++ = data & 0xff;
140
141                 debug("rx:%x\n", data);
142         }
143
144 done:
145         if (flags & SPI_XFER_END)
146                 spi_cs_deactivate(dev);
147
148         return 0;
149 }
150
151 static int altera_spi_set_speed(struct udevice *bus, uint speed)
152 {
153         return 0;
154 }
155
156 static int altera_spi_set_mode(struct udevice *bus, uint mode)
157 {
158         return 0;
159 }
160
161 static int altera_spi_probe(struct udevice *bus)
162 {
163         struct altera_spi_platdata *plat = dev_get_platdata(bus);
164         struct altera_spi_priv *priv = dev_get_priv(bus);
165
166         priv->regs = plat->regs;
167
168         return 0;
169 }
170
171 static int altera_spi_ofdata_to_platdata(struct udevice *bus)
172 {
173         struct altera_spi_platdata *plat = dev_get_platdata(bus);
174
175         plat->regs = map_physmem(devfdt_get_addr(bus),
176                                  sizeof(struct altera_spi_regs),
177                                  MAP_NOCACHE);
178
179         return 0;
180 }
181
182 static const struct dm_spi_ops altera_spi_ops = {
183         .claim_bus      = altera_spi_claim_bus,
184         .release_bus    = altera_spi_release_bus,
185         .xfer           = altera_spi_xfer,
186         .set_speed      = altera_spi_set_speed,
187         .set_mode       = altera_spi_set_mode,
188         /*
189          * cs_info is not needed, since we require all chip selects to be
190          * in the device tree explicitly
191          */
192 };
193
194 static const struct udevice_id altera_spi_ids[] = {
195         { .compatible = "altr,spi-1.0" },
196         {}
197 };
198
199 U_BOOT_DRIVER(altera_spi) = {
200         .name   = "altera_spi",
201         .id     = UCLASS_SPI,
202         .of_match = altera_spi_ids,
203         .ops    = &altera_spi_ops,
204         .ofdata_to_platdata = altera_spi_ofdata_to_platdata,
205         .platdata_auto_alloc_size = sizeof(struct altera_spi_platdata),
206         .priv_auto_alloc_size = sizeof(struct altera_spi_priv),
207         .probe  = altera_spi_probe,
208 };