2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2011, 2012 Cavium, Inc.
9 #include <linux/platform_device.h>
10 #include <linux/interrupt.h>
11 #include <linux/spi/spi.h>
12 #include <linux/module.h>
13 #include <linux/delay.h>
17 #include <asm/octeon/octeon.h>
18 #include <asm/octeon/cvmx-mpi-defs.h>
20 #define OCTEON_SPI_CFG 0
21 #define OCTEON_SPI_STS 0x08
22 #define OCTEON_SPI_TX 0x10
23 #define OCTEON_SPI_DAT0 0x80
25 #define OCTEON_SPI_MAX_BYTES 9
27 #define OCTEON_SPI_MAX_CLOCK_HZ 16000000
30 void __iomem
*register_base
;
36 static void octeon_spi_wait_ready(struct octeon_spi
*p
)
38 union cvmx_mpi_sts mpi_sts
;
39 unsigned int loops
= 0;
44 mpi_sts
.u64
= readq(p
->register_base
+ OCTEON_SPI_STS
);
45 } while (mpi_sts
.s
.busy
);
48 static int octeon_spi_do_transfer(struct octeon_spi
*p
,
49 struct spi_message
*msg
,
50 struct spi_transfer
*xfer
,
53 struct spi_device
*spi
= msg
->spi
;
54 union cvmx_mpi_cfg mpi_cfg
;
55 union cvmx_mpi_tx mpi_tx
;
65 cpha
= mode
& SPI_CPHA
;
66 cpol
= mode
& SPI_CPOL
;
68 clkdiv
= p
->sys_freq
/ (2 * xfer
->speed_hz
);
72 mpi_cfg
.s
.clkdiv
= clkdiv
;
73 mpi_cfg
.s
.cshi
= (mode
& SPI_CS_HIGH
) ? 1 : 0;
74 mpi_cfg
.s
.lsbfirst
= (mode
& SPI_LSB_FIRST
) ? 1 : 0;
75 mpi_cfg
.s
.wireor
= (mode
& SPI_3WIRE
) ? 1 : 0;
76 mpi_cfg
.s
.idlelo
= cpha
!= cpol
;
77 mpi_cfg
.s
.cslate
= cpha
? 1 : 0;
80 if (spi
->chip_select
< 4)
81 p
->cs_enax
|= 1ull << (12 + spi
->chip_select
);
82 mpi_cfg
.u64
|= p
->cs_enax
;
84 if (mpi_cfg
.u64
!= p
->last_cfg
) {
85 p
->last_cfg
= mpi_cfg
.u64
;
86 writeq(mpi_cfg
.u64
, p
->register_base
+ OCTEON_SPI_CFG
);
88 tx_buf
= xfer
->tx_buf
;
89 rx_buf
= xfer
->rx_buf
;
91 while (len
> OCTEON_SPI_MAX_BYTES
) {
92 for (i
= 0; i
< OCTEON_SPI_MAX_BYTES
; i
++) {
98 writeq(d
, p
->register_base
+ OCTEON_SPI_DAT0
+ (8 * i
));
101 mpi_tx
.s
.csid
= spi
->chip_select
;
102 mpi_tx
.s
.leavecs
= 1;
103 mpi_tx
.s
.txnum
= tx_buf
? OCTEON_SPI_MAX_BYTES
: 0;
104 mpi_tx
.s
.totnum
= OCTEON_SPI_MAX_BYTES
;
105 writeq(mpi_tx
.u64
, p
->register_base
+ OCTEON_SPI_TX
);
107 octeon_spi_wait_ready(p
);
109 for (i
= 0; i
< OCTEON_SPI_MAX_BYTES
; i
++) {
110 u64 v
= readq(p
->register_base
+ OCTEON_SPI_DAT0
+ (8 * i
));
113 len
-= OCTEON_SPI_MAX_BYTES
;
116 for (i
= 0; i
< len
; i
++) {
122 writeq(d
, p
->register_base
+ OCTEON_SPI_DAT0
+ (8 * i
));
126 mpi_tx
.s
.csid
= spi
->chip_select
;
128 mpi_tx
.s
.leavecs
= xfer
->cs_change
;
130 mpi_tx
.s
.leavecs
= !xfer
->cs_change
;
131 mpi_tx
.s
.txnum
= tx_buf
? len
: 0;
132 mpi_tx
.s
.totnum
= len
;
133 writeq(mpi_tx
.u64
, p
->register_base
+ OCTEON_SPI_TX
);
135 octeon_spi_wait_ready(p
);
137 for (i
= 0; i
< len
; i
++) {
138 u64 v
= readq(p
->register_base
+ OCTEON_SPI_DAT0
+ (8 * i
));
142 if (xfer
->delay_usecs
)
143 udelay(xfer
->delay_usecs
);
148 static int octeon_spi_transfer_one_message(struct spi_master
*master
,
149 struct spi_message
*msg
)
151 struct octeon_spi
*p
= spi_master_get_devdata(master
);
152 unsigned int total_len
= 0;
154 struct spi_transfer
*xfer
;
156 list_for_each_entry(xfer
, &msg
->transfers
, transfer_list
) {
157 bool last_xfer
= list_is_last(&xfer
->transfer_list
,
159 int r
= octeon_spi_do_transfer(p
, msg
, xfer
, last_xfer
);
167 msg
->status
= status
;
168 msg
->actual_length
= total_len
;
169 spi_finalize_current_message(master
);
173 static int octeon_spi_probe(struct platform_device
*pdev
)
175 struct resource
*res_mem
;
176 void __iomem
*reg_base
;
177 struct spi_master
*master
;
178 struct octeon_spi
*p
;
181 master
= spi_alloc_master(&pdev
->dev
, sizeof(struct octeon_spi
));
184 p
= spi_master_get_devdata(master
);
185 platform_set_drvdata(pdev
, master
);
187 res_mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
188 reg_base
= devm_ioremap_resource(&pdev
->dev
, res_mem
);
189 if (IS_ERR(reg_base
)) {
190 err
= PTR_ERR(reg_base
);
194 p
->register_base
= reg_base
;
195 p
->sys_freq
= octeon_get_io_clock_rate();
197 master
->num_chipselect
= 4;
198 master
->mode_bits
= SPI_CPHA
|
204 master
->transfer_one_message
= octeon_spi_transfer_one_message
;
205 master
->bits_per_word_mask
= SPI_BPW_MASK(8);
206 master
->max_speed_hz
= OCTEON_SPI_MAX_CLOCK_HZ
;
208 master
->dev
.of_node
= pdev
->dev
.of_node
;
209 err
= devm_spi_register_master(&pdev
->dev
, master
);
211 dev_err(&pdev
->dev
, "register master failed: %d\n", err
);
215 dev_info(&pdev
->dev
, "OCTEON SPI bus driver\n");
219 spi_master_put(master
);
223 static int octeon_spi_remove(struct platform_device
*pdev
)
225 struct spi_master
*master
= platform_get_drvdata(pdev
);
226 struct octeon_spi
*p
= spi_master_get_devdata(master
);
228 /* Clear the CSENA* and put everything in a known state. */
229 writeq(0, p
->register_base
+ OCTEON_SPI_CFG
);
234 static const struct of_device_id octeon_spi_match
[] = {
235 { .compatible
= "cavium,octeon-3010-spi", },
238 MODULE_DEVICE_TABLE(of
, octeon_spi_match
);
240 static struct platform_driver octeon_spi_driver
= {
242 .name
= "spi-octeon",
243 .of_match_table
= octeon_spi_match
,
245 .probe
= octeon_spi_probe
,
246 .remove
= octeon_spi_remove
,
249 module_platform_driver(octeon_spi_driver
);
251 MODULE_DESCRIPTION("Cavium, Inc. OCTEON SPI bus driver");
252 MODULE_AUTHOR("David Daney");
253 MODULE_LICENSE("GPL");