1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
7 * Based on spi_s3c24xx.c, which is:
8 * Copyright (c) 2006 Ben Dooks
9 * Copyright (c) 2006 Simtec Electronics
10 * Ben Dooks <ben@simtec.co.uk>
13 #include <linux/interrupt.h>
14 #include <linux/errno.h>
15 #include <linux/module.h>
16 #include <linux/platform_device.h>
17 #include <linux/spi/altera.h>
18 #include <linux/spi/spi.h>
22 #define DRV_NAME "spi_altera"
24 #define ALTERA_SPI_RXDATA 0
25 #define ALTERA_SPI_TXDATA 4
26 #define ALTERA_SPI_STATUS 8
27 #define ALTERA_SPI_CONTROL 12
28 #define ALTERA_SPI_SLAVE_SEL 20
30 #define ALTERA_SPI_STATUS_ROE_MSK 0x8
31 #define ALTERA_SPI_STATUS_TOE_MSK 0x10
32 #define ALTERA_SPI_STATUS_TMT_MSK 0x20
33 #define ALTERA_SPI_STATUS_TRDY_MSK 0x40
34 #define ALTERA_SPI_STATUS_RRDY_MSK 0x80
35 #define ALTERA_SPI_STATUS_E_MSK 0x100
37 #define ALTERA_SPI_CONTROL_IROE_MSK 0x8
38 #define ALTERA_SPI_CONTROL_ITOE_MSK 0x10
39 #define ALTERA_SPI_CONTROL_ITRDY_MSK 0x40
40 #define ALTERA_SPI_CONTROL_IRRDY_MSK 0x80
41 #define ALTERA_SPI_CONTROL_IE_MSK 0x100
42 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
44 #define ALTERA_SPI_MAX_CS 32
46 enum altera_spi_type
{
47 ALTERA_SPI_TYPE_UNKNOWN
,
48 ALTERA_SPI_TYPE_SUBDEV
,
59 const unsigned char *tx
;
62 struct regmap
*regmap
;
67 static const struct regmap_config spi_altera_config
= {
74 static int altr_spi_writel(struct altera_spi
*hw
, unsigned int reg
,
79 ret
= regmap_write(hw
->regmap
, hw
->regoff
+ reg
, val
);
81 dev_err(hw
->dev
, "fail to write reg 0x%x val 0x%x: %d\n",
87 static int altr_spi_readl(struct altera_spi
*hw
, unsigned int reg
,
92 ret
= regmap_read(hw
->regmap
, hw
->regoff
+ reg
, val
);
94 dev_err(hw
->dev
, "fail to read reg 0x%x: %d\n", reg
, ret
);
99 static inline struct altera_spi
*altera_spi_to_hw(struct spi_device
*sdev
)
101 return spi_master_get_devdata(sdev
->master
);
104 static void altera_spi_set_cs(struct spi_device
*spi
, bool is_high
)
106 struct altera_spi
*hw
= altera_spi_to_hw(spi
);
109 hw
->imr
&= ~ALTERA_SPI_CONTROL_SSO_MSK
;
110 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
111 altr_spi_writel(hw
, ALTERA_SPI_SLAVE_SEL
, 0);
113 altr_spi_writel(hw
, ALTERA_SPI_SLAVE_SEL
,
114 BIT(spi
->chip_select
));
115 hw
->imr
|= ALTERA_SPI_CONTROL_SSO_MSK
;
116 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
120 static void altera_spi_tx_word(struct altera_spi
*hw
)
122 unsigned int txd
= 0;
125 switch (hw
->bytes_per_word
) {
127 txd
= hw
->tx
[hw
->count
];
130 txd
= (hw
->tx
[hw
->count
* 2]
131 | (hw
->tx
[hw
->count
* 2 + 1] << 8));
134 txd
= (hw
->tx
[hw
->count
* 4]
135 | (hw
->tx
[hw
->count
* 4 + 1] << 8)
136 | (hw
->tx
[hw
->count
* 4 + 2] << 16)
137 | (hw
->tx
[hw
->count
* 4 + 3] << 24));
143 altr_spi_writel(hw
, ALTERA_SPI_TXDATA
, txd
);
146 static void altera_spi_rx_word(struct altera_spi
*hw
)
150 altr_spi_readl(hw
, ALTERA_SPI_RXDATA
, &rxd
);
152 switch (hw
->bytes_per_word
) {
154 hw
->rx
[hw
->count
] = rxd
;
157 hw
->rx
[hw
->count
* 2] = rxd
;
158 hw
->rx
[hw
->count
* 2 + 1] = rxd
>> 8;
161 hw
->rx
[hw
->count
* 4] = rxd
;
162 hw
->rx
[hw
->count
* 4 + 1] = rxd
>> 8;
163 hw
->rx
[hw
->count
* 4 + 2] = rxd
>> 16;
164 hw
->rx
[hw
->count
* 4 + 3] = rxd
>> 24;
173 static int altera_spi_txrx(struct spi_master
*master
,
174 struct spi_device
*spi
, struct spi_transfer
*t
)
176 struct altera_spi
*hw
= spi_master_get_devdata(master
);
182 hw
->bytes_per_word
= DIV_ROUND_UP(t
->bits_per_word
, 8);
183 hw
->len
= t
->len
/ hw
->bytes_per_word
;
186 /* enable receive interrupt */
187 hw
->imr
|= ALTERA_SPI_CONTROL_IRRDY_MSK
;
188 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
190 /* send the first byte */
191 altera_spi_tx_word(hw
);
196 while (hw
->count
< hw
->len
) {
197 altera_spi_tx_word(hw
);
200 altr_spi_readl(hw
, ALTERA_SPI_STATUS
, &val
);
201 if (val
& ALTERA_SPI_STATUS_RRDY_MSK
)
207 altera_spi_rx_word(hw
);
209 spi_finalize_current_transfer(master
);
214 static irqreturn_t
altera_spi_irq(int irq
, void *dev
)
216 struct spi_master
*master
= dev
;
217 struct altera_spi
*hw
= spi_master_get_devdata(master
);
219 altera_spi_rx_word(hw
);
221 if (hw
->count
< hw
->len
) {
222 altera_spi_tx_word(hw
);
224 /* disable receive interrupt */
225 hw
->imr
&= ~ALTERA_SPI_CONTROL_IRRDY_MSK
;
226 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
228 spi_finalize_current_transfer(master
);
234 static int altera_spi_probe(struct platform_device
*pdev
)
236 const struct platform_device_id
*platid
= platform_get_device_id(pdev
);
237 struct altera_spi_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
238 enum altera_spi_type type
= ALTERA_SPI_TYPE_UNKNOWN
;
239 struct altera_spi
*hw
;
240 struct spi_master
*master
;
245 master
= spi_alloc_master(&pdev
->dev
, sizeof(struct altera_spi
));
249 /* setup the master state. */
250 master
->bus_num
= pdev
->id
;
253 if (pdata
->num_chipselect
> ALTERA_SPI_MAX_CS
) {
255 "Invalid number of chipselect: %hu\n",
256 pdata
->num_chipselect
);
260 master
->num_chipselect
= pdata
->num_chipselect
;
261 master
->mode_bits
= pdata
->mode_bits
;
262 master
->bits_per_word_mask
= pdata
->bits_per_word_mask
;
264 master
->num_chipselect
= 16;
265 master
->mode_bits
= SPI_CS_HIGH
;
266 master
->bits_per_word_mask
= SPI_BPW_RANGE_MASK(1, 16);
269 master
->dev
.of_node
= pdev
->dev
.of_node
;
270 master
->transfer_one
= altera_spi_txrx
;
271 master
->set_cs
= altera_spi_set_cs
;
273 hw
= spi_master_get_devdata(master
);
274 hw
->dev
= &pdev
->dev
;
277 type
= platid
->driver_data
;
279 /* find and map our resources */
280 if (type
== ALTERA_SPI_TYPE_SUBDEV
) {
281 struct resource
*regoff
;
283 hw
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
285 dev_err(&pdev
->dev
, "get regmap failed\n");
289 regoff
= platform_get_resource(pdev
, IORESOURCE_REG
, 0);
291 hw
->regoff
= regoff
->start
;
295 res
= devm_platform_ioremap_resource(pdev
, 0);
301 hw
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, res
,
303 if (IS_ERR(hw
->regmap
)) {
304 dev_err(&pdev
->dev
, "regmap mmio init failed\n");
305 err
= PTR_ERR(hw
->regmap
);
310 /* program defaults into the registers */
311 hw
->imr
= 0; /* disable spi interrupts */
312 altr_spi_writel(hw
, ALTERA_SPI_CONTROL
, hw
->imr
);
313 altr_spi_writel(hw
, ALTERA_SPI_STATUS
, 0); /* clear status reg */
314 altr_spi_readl(hw
, ALTERA_SPI_STATUS
, &val
);
315 if (val
& ALTERA_SPI_STATUS_RRDY_MSK
)
316 altr_spi_readl(hw
, ALTERA_SPI_RXDATA
, &val
); /* flush rxdata */
317 /* irq is optional */
318 hw
->irq
= platform_get_irq(pdev
, 0);
320 err
= devm_request_irq(&pdev
->dev
, hw
->irq
, altera_spi_irq
, 0,
326 err
= devm_spi_register_master(&pdev
->dev
, master
);
331 for (i
= 0; i
< pdata
->num_devices
; i
++) {
332 if (!spi_new_device(master
, pdata
->devices
+ i
))
334 "unable to create SPI device: %s\n",
335 pdata
->devices
[i
].modalias
);
339 dev_info(&pdev
->dev
, "regoff %u, irq %d\n", hw
->regoff
, hw
->irq
);
343 spi_master_put(master
);
348 static const struct of_device_id altera_spi_match
[] = {
349 { .compatible
= "ALTR,spi-1.0", },
350 { .compatible
= "altr,spi-1.0", },
353 MODULE_DEVICE_TABLE(of
, altera_spi_match
);
354 #endif /* CONFIG_OF */
356 static const struct platform_device_id altera_spi_ids
[] = {
357 { DRV_NAME
, ALTERA_SPI_TYPE_UNKNOWN
},
358 { "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV
},
361 MODULE_DEVICE_TABLE(platform
, altera_spi_ids
);
363 static struct platform_driver altera_spi_driver
= {
364 .probe
= altera_spi_probe
,
368 .of_match_table
= of_match_ptr(altera_spi_match
),
370 .id_table
= altera_spi_ids
,
372 module_platform_driver(altera_spi_driver
);
374 MODULE_DESCRIPTION("Altera SPI driver");
375 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
376 MODULE_LICENSE("GPL");
377 MODULE_ALIAS("platform:" DRV_NAME
);