1 // SPDX-License-Identifier: GPL-2.0+
3 * Microchip PIC32 SPI controller driver.
5 * Copyright (c) 2015, Microchip Technology Inc.
6 * Purna Chandra Mandal <purna.mandal@microchip.com>
12 #include <linux/compat.h>
16 #include <asm/types.h>
19 #include <dt-bindings/clock/microchip,clock.h>
20 #include <mach/pic32.h>
22 DECLARE_GLOBAL_DATA_PTR
;
24 /* PIC32 SPI controller registers */
25 struct pic32_reg_spi
{
26 struct pic32_reg_atomic ctrl
;
27 struct pic32_reg_atomic status
;
28 struct pic32_reg_atomic buf
;
29 struct pic32_reg_atomic baud
;
30 struct pic32_reg_atomic ctrl2
;
33 /* Bit fields in SPI Control Register */
34 #define PIC32_SPI_CTRL_MSTEN BIT(5) /* Enable SPI Master */
35 #define PIC32_SPI_CTRL_CKP BIT(6) /* active low */
36 #define PIC32_SPI_CTRL_CKE BIT(8) /* Tx on falling edge */
37 #define PIC32_SPI_CTRL_SMP BIT(9) /* Rx at middle or end of tx */
38 #define PIC32_SPI_CTRL_BPW_MASK 0x03 /* Bits per word */
39 #define PIC32_SPI_CTRL_BPW_8 0x0
40 #define PIC32_SPI_CTRL_BPW_16 0x1
41 #define PIC32_SPI_CTRL_BPW_32 0x2
42 #define PIC32_SPI_CTRL_BPW_SHIFT 10
43 #define PIC32_SPI_CTRL_ON BIT(15) /* Macro enable */
44 #define PIC32_SPI_CTRL_ENHBUF BIT(16) /* Enable enhanced buffering */
45 #define PIC32_SPI_CTRL_MCLKSEL BIT(23) /* Select SPI Clock src */
46 #define PIC32_SPI_CTRL_MSSEN BIT(28) /* SPI macro will drive SS */
47 #define PIC32_SPI_CTRL_FRMEN BIT(31) /* Enable framing mode */
49 /* Bit fields in SPI Status Register */
50 #define PIC32_SPI_STAT_RX_OV BIT(6) /* err, s/w needs to clear */
51 #define PIC32_SPI_STAT_TF_LVL_MASK 0x1f
52 #define PIC32_SPI_STAT_TF_LVL_SHIFT 16
53 #define PIC32_SPI_STAT_RF_LVL_MASK 0x1f
54 #define PIC32_SPI_STAT_RF_LVL_SHIFT 24
56 /* Bit fields in SPI Baud Register */
57 #define PIC32_SPI_BAUD_MASK 0x1ff
59 struct pic32_spi_priv
{
60 struct pic32_reg_spi
*regs
;
61 u32 fifo_depth
; /* FIFO depth in bytes */
62 u32 fifo_n_word
; /* FIFO depth in words */
63 struct gpio_desc cs_gpio
;
65 /* Current SPI slave specific */
67 u32 speed_hz
; /* spi-clk rate */
70 /* Current message/transfer state */
77 /* SPI FiFo accessor */
78 void (*rx_fifo
)(struct pic32_spi_priv
*);
79 void (*tx_fifo
)(struct pic32_spi_priv
*);
82 static inline void pic32_spi_enable(struct pic32_spi_priv
*priv
)
84 writel(PIC32_SPI_CTRL_ON
, &priv
->regs
->ctrl
.set
);
87 static inline void pic32_spi_disable(struct pic32_spi_priv
*priv
)
89 writel(PIC32_SPI_CTRL_ON
, &priv
->regs
->ctrl
.clr
);
92 static inline u32
pic32_spi_rx_fifo_level(struct pic32_spi_priv
*priv
)
94 u32 sr
= readl(&priv
->regs
->status
.raw
);
96 return (sr
>> PIC32_SPI_STAT_RF_LVL_SHIFT
) & PIC32_SPI_STAT_RF_LVL_MASK
;
99 static inline u32
pic32_spi_tx_fifo_level(struct pic32_spi_priv
*priv
)
101 u32 sr
= readl(&priv
->regs
->status
.raw
);
103 return (sr
>> PIC32_SPI_STAT_TF_LVL_SHIFT
) & PIC32_SPI_STAT_TF_LVL_MASK
;
106 /* Return the max entries we can fill into tx fifo */
107 static u32
pic32_tx_max(struct pic32_spi_priv
*priv
, int n_bytes
)
109 u32 tx_left
, tx_room
, rxtx_gap
;
111 tx_left
= (priv
->tx_end
- priv
->tx
) / n_bytes
;
112 tx_room
= priv
->fifo_n_word
- pic32_spi_tx_fifo_level(priv
);
114 rxtx_gap
= (priv
->rx_end
- priv
->rx
) - (priv
->tx_end
- priv
->tx
);
116 return min3(tx_left
, tx_room
, (u32
)(priv
->fifo_n_word
- rxtx_gap
));
119 /* Return the max entries we should read out of rx fifo */
120 static u32
pic32_rx_max(struct pic32_spi_priv
*priv
, int n_bytes
)
122 u32 rx_left
= (priv
->rx_end
- priv
->rx
) / n_bytes
;
124 return min_t(u32
, rx_left
, pic32_spi_rx_fifo_level(priv
));
127 #define BUILD_SPI_FIFO_RW(__name, __type, __bwl) \
128 static void pic32_spi_rx_##__name(struct pic32_spi_priv *priv) \
131 u32 mx = pic32_rx_max(priv, sizeof(__type)); \
134 val = read##__bwl(&priv->regs->buf.raw); \
135 if (priv->rx_end - priv->len) \
136 *(__type *)(priv->rx) = val; \
137 priv->rx += sizeof(__type); \
141 static void pic32_spi_tx_##__name(struct pic32_spi_priv *priv) \
144 u32 mx = pic32_tx_max(priv, sizeof(__type)); \
146 for (; mx ; mx--) { \
147 val = (__type) ~0U; \
148 if (priv->tx_end - priv->len) \
149 val = *(__type *)(priv->tx); \
150 write##__bwl(val, &priv->regs->buf.raw); \
151 priv->tx += sizeof(__type); \
154 BUILD_SPI_FIFO_RW(byte
, u8
, b
);
155 BUILD_SPI_FIFO_RW(word
, u16
, w
);
156 BUILD_SPI_FIFO_RW(dword
, u32
, l
);
158 static int pic32_spi_set_word_size(struct pic32_spi_priv
*priv
,
159 unsigned int wordlen
)
166 priv
->rx_fifo
= pic32_spi_rx_byte
;
167 priv
->tx_fifo
= pic32_spi_tx_byte
;
168 bits_per_word
= PIC32_SPI_CTRL_BPW_8
;
171 priv
->rx_fifo
= pic32_spi_rx_word
;
172 priv
->tx_fifo
= pic32_spi_tx_word
;
173 bits_per_word
= PIC32_SPI_CTRL_BPW_16
;
176 priv
->rx_fifo
= pic32_spi_rx_dword
;
177 priv
->tx_fifo
= pic32_spi_tx_dword
;
178 bits_per_word
= PIC32_SPI_CTRL_BPW_32
;
181 printf("pic32-spi: unsupported wordlen\n");
185 /* set bits-per-word */
186 val
= readl(&priv
->regs
->ctrl
.raw
);
187 val
&= ~(PIC32_SPI_CTRL_BPW_MASK
<< PIC32_SPI_CTRL_BPW_SHIFT
);
188 val
|= bits_per_word
<< PIC32_SPI_CTRL_BPW_SHIFT
;
189 writel(val
, &priv
->regs
->ctrl
.raw
);
191 /* calculate maximum number of words fifo can hold */
192 priv
->fifo_n_word
= DIV_ROUND_UP(priv
->fifo_depth
, wordlen
/ 8);
197 static int pic32_spi_claim_bus(struct udevice
*slave
)
199 struct pic32_spi_priv
*priv
= dev_get_priv(slave
->parent
);
202 pic32_spi_enable(priv
);
207 static int pic32_spi_release_bus(struct udevice
*slave
)
209 struct pic32_spi_priv
*priv
= dev_get_priv(slave
->parent
);
212 pic32_spi_disable(priv
);
217 static void spi_cs_activate(struct pic32_spi_priv
*priv
)
219 if (!dm_gpio_is_valid(&priv
->cs_gpio
))
222 dm_gpio_set_value(&priv
->cs_gpio
, 1);
225 static void spi_cs_deactivate(struct pic32_spi_priv
*priv
)
227 if (!dm_gpio_is_valid(&priv
->cs_gpio
))
230 dm_gpio_set_value(&priv
->cs_gpio
, 0);
233 static int pic32_spi_xfer(struct udevice
*slave
, unsigned int bitlen
,
234 const void *tx_buf
, void *rx_buf
,
237 struct dm_spi_slave_platdata
*slave_plat
;
238 struct udevice
*bus
= slave
->parent
;
239 struct pic32_spi_priv
*priv
;
240 int len
= bitlen
/ 8;
244 priv
= dev_get_priv(bus
);
245 slave_plat
= dev_get_parent_platdata(slave
);
247 debug("spi_xfer: bus:%i cs:%i flags:%lx\n",
248 bus
->seq
, slave_plat
->cs
, flags
);
249 debug("msg tx %p, rx %p submitted of %d byte(s)\n",
250 tx_buf
, rx_buf
, len
);
253 if (flags
& SPI_XFER_BEGIN
)
254 spi_cs_activate(priv
);
256 /* set current transfer information */
259 priv
->tx_end
= priv
->tx
+ len
;
260 priv
->rx_end
= priv
->rx
+ len
;
263 /* transact by polling */
264 tbase
= get_timer(0);
269 /* received sufficient data */
270 if (priv
->rx
>= priv
->rx_end
) {
275 if (get_timer(tbase
) > 5 * CONFIG_SYS_HZ
) {
276 printf("pic32_spi: error, xfer timedout.\n");
277 flags
|= SPI_XFER_END
;
284 if (flags
& SPI_XFER_END
)
285 spi_cs_deactivate(priv
);
290 static int pic32_spi_set_speed(struct udevice
*bus
, uint speed
)
292 struct pic32_spi_priv
*priv
= dev_get_priv(bus
);
295 debug("%s: %s, speed %u\n", __func__
, bus
->name
, speed
);
297 /* div = [clk_in / (2 * spi_clk)] - 1 */
298 div
= (priv
->clk_rate
/ 2 / speed
) - 1;
299 div
&= PIC32_SPI_BAUD_MASK
;
300 writel(div
, &priv
->regs
->baud
.raw
);
302 priv
->speed_hz
= speed
;
307 static int pic32_spi_set_mode(struct udevice
*bus
, uint mode
)
309 struct pic32_spi_priv
*priv
= dev_get_priv(bus
);
312 debug("%s: %s, mode %d\n", __func__
, bus
->name
, mode
);
314 /* set spi-clk mode */
315 val
= readl(&priv
->regs
->ctrl
.raw
);
318 val
|= PIC32_SPI_CTRL_CKP
;
320 val
&= ~PIC32_SPI_CTRL_CKP
;
322 /* TX at idle-to-active clk transition */
324 val
&= ~PIC32_SPI_CTRL_CKE
;
326 val
|= PIC32_SPI_CTRL_CKE
;
328 /* RX at end of tx */
329 val
|= PIC32_SPI_CTRL_SMP
;
330 writel(val
, &priv
->regs
->ctrl
.raw
);
337 static int pic32_spi_set_wordlen(struct udevice
*slave
, unsigned int wordlen
)
339 struct pic32_spi_priv
*priv
= dev_get_priv(slave
->parent
);
341 return pic32_spi_set_word_size(priv
, wordlen
);
344 static void pic32_spi_hw_init(struct pic32_spi_priv
*priv
)
349 pic32_spi_disable(priv
);
351 val
= readl(&priv
->regs
->ctrl
);
353 /* enable enhanced fifo of 128bit deep */
354 val
|= PIC32_SPI_CTRL_ENHBUF
;
355 priv
->fifo_depth
= 16;
357 /* disable framing mode */
358 val
&= ~PIC32_SPI_CTRL_FRMEN
;
360 /* enable master mode */
361 val
|= PIC32_SPI_CTRL_MSTEN
;
363 /* select clk source */
364 val
&= ~PIC32_SPI_CTRL_MCLKSEL
;
366 /* set manual /CS mode */
367 val
&= ~PIC32_SPI_CTRL_MSSEN
;
369 writel(val
, &priv
->regs
->ctrl
);
371 /* clear rx overflow indicator */
372 writel(PIC32_SPI_STAT_RX_OV
, &priv
->regs
->status
.clr
);
375 static int pic32_spi_probe(struct udevice
*bus
)
377 struct pic32_spi_priv
*priv
= dev_get_priv(bus
);
378 struct dm_spi_bus
*dm_spi
= dev_get_uclass_priv(bus
);
379 int node
= dev_of_offset(bus
);
380 struct udevice
*clkdev
;
385 debug("%s: %d, bus: %i\n", __func__
, __LINE__
, bus
->seq
);
386 addr
= fdtdec_get_addr_size(gd
->fdt_blob
, node
, "reg", &size
);
387 if (addr
== FDT_ADDR_T_NONE
)
390 priv
->regs
= ioremap(addr
, size
);
394 dm_spi
->max_hz
= fdtdec_get_int(gd
->fdt_blob
, node
, "spi-max-frequency",
397 ret
= clk_get_by_index(bus
, 0, &clkdev
);
399 printf("pic32-spi: error, clk not found\n");
402 priv
->clk_rate
= clk_get_periph_rate(clkdev
, ret
);
405 pic32_spi_hw_init(priv
);
408 pic32_spi_set_word_size(priv
, SPI_DEFAULT_WORDLEN
);
410 /* PIC32 SPI controller can automatically drive /CS during transfer
411 * depending on fifo fill-level. /CS will stay asserted as long as
412 * TX fifo is non-empty, else will be deasserted confirming completion
413 * of the ongoing transfer. To avoid this sort of error we will drive
414 * /CS manually by toggling cs-gpio pins.
416 ret
= gpio_request_by_name_nodev(offset_to_ofnode(node
), "cs-gpios", 0,
417 &priv
->cs_gpio
, GPIOD_IS_OUT
);
419 printf("pic32-spi: error, cs-gpios not found\n");
426 static const struct dm_spi_ops pic32_spi_ops
= {
427 .claim_bus
= pic32_spi_claim_bus
,
428 .release_bus
= pic32_spi_release_bus
,
429 .xfer
= pic32_spi_xfer
,
430 .set_speed
= pic32_spi_set_speed
,
431 .set_mode
= pic32_spi_set_mode
,
432 .set_wordlen
= pic32_spi_set_wordlen
,
435 static const struct udevice_id pic32_spi_ids
[] = {
436 { .compatible
= "microchip,pic32mzda-spi" },
440 U_BOOT_DRIVER(pic32_spi
) = {
443 .of_match
= pic32_spi_ids
,
444 .ops
= &pic32_spi_ops
,
445 .priv_auto_alloc_size
= sizeof(struct pic32_spi_priv
),
446 .probe
= pic32_spi_probe
,