Lines Matching +full:spi +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0+
2 // Loongson SPI Support
14 #include <linux/spi/spi.h>
16 #include "spi-loongson.h"
18 static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg, in loongson_spi_write_reg() argument
21 writeb(data, spi->base + reg); in loongson_spi_write_reg()
24 static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg) in loongson_spi_read_reg() argument
26 return readb(spi->base + reg); in loongson_spi_read_reg()
29 static void loongson_spi_set_cs(struct spi_device *spi, bool en) in loongson_spi_set_cs() argument
32 unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0); in loongson_spi_set_cs()
33 unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0)); in loongson_spi_set_cs()
34 struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); in loongson_spi_set_cs()
46 div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096); in loongson_spi_set_clk()
47 div_tmp = rdiv[fls(div - 1)]; in loongson_spi_set_clk()
48 loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0; in loongson_spi_set_clk()
49 loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2; in loongson_spi_set_clk()
53 loongson_spi->spcr); in loongson_spi_set_clk()
57 loongson_spi->sper); in loongson_spi_set_clk()
58 loongson_spi->hz = hz; in loongson_spi_set_clk()
62 struct spi_device *spi) in loongson_spi_set_mode() argument
68 if (spi->mode & SPI_CPOL) in loongson_spi_set_mode()
70 if (spi->mode & SPI_CPHA) in loongson_spi_set_mode()
74 loongson_spi->mode |= spi->mode; in loongson_spi_set_mode()
78 struct spi_device *spi, struct spi_transfer *t) in loongson_spi_update_state() argument
80 if (t && loongson_spi->hz != t->speed_hz) in loongson_spi_update_state()
81 loongson_spi_set_clk(loongson_spi, t->speed_hz); in loongson_spi_update_state()
83 if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK) in loongson_spi_update_state()
84 loongson_spi_set_mode(loongson_spi, spi); in loongson_spi_update_state()
89 static int loongson_spi_setup(struct spi_device *spi) in loongson_spi_setup() argument
93 loongson_spi = spi_controller_get_devdata(spi->controller); in loongson_spi_setup()
94 if (spi->bits_per_word % 8) in loongson_spi_setup()
95 return -EINVAL; in loongson_spi_setup()
97 if (spi_get_chipselect(spi, 0) >= spi->controller->num_chipselect) in loongson_spi_setup()
98 return -EINVAL; in loongson_spi_setup()
100 loongson_spi->hz = 0; in loongson_spi_setup()
101 loongson_spi_set_cs(spi, true); in loongson_spi_setup()
106 static int loongson_spi_write_read_8bit(struct spi_device *spi, const u8 **tx_buf, in loongson_spi_write_read_8bit() argument
110 struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); in loongson_spi_write_read_8bit()
117 ret = readb_poll_timeout(loongson_spi->base + LOONGSON_SPI_SPSR_REG, in loongson_spi_write_read_8bit()
118 loongson_spi->spsr, (loongson_spi->spsr & in loongson_spi_write_read_8bit()
130 static int loongson_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) in loongson_spi_write_read() argument
134 const u8 *tx = xfer->tx_buf; in loongson_spi_write_read()
135 u8 *rx = xfer->rx_buf; in loongson_spi_write_read()
137 count = xfer->len; in loongson_spi_write_read()
139 ret = loongson_spi_write_read_8bit(spi, &tx, &rx, count); in loongson_spi_write_read()
142 } while (--count); in loongson_spi_write_read()
151 loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG); in loongson_spi_prepare_message()
152 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para & in loongson_spi_prepare_message()
158 static int loongson_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi, in loongson_spi_transfer_one() argument
161 struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); in loongson_spi_transfer_one()
163 loongson_spi_update_state(loongson_spi, spi, xfer); in loongson_spi_transfer_one()
164 if (xfer->len) in loongson_spi_transfer_one()
165 return loongson_spi_write_read(spi, xfer); in loongson_spi_transfer_one()
174 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para); in loongson_spi_unprepare_message()
198 struct loongson_spi *spi; in loongson_spi_init_controller() local
203 return -ENOMEM; in loongson_spi_init_controller()
205 controller->mode_bits = SPI_MODE_X_MASK | SPI_CS_HIGH; in loongson_spi_init_controller()
206 controller->setup = loongson_spi_setup; in loongson_spi_init_controller()
207 controller->prepare_message = loongson_spi_prepare_message; in loongson_spi_init_controller()
208 controller->transfer_one = loongson_spi_transfer_one; in loongson_spi_init_controller()
209 controller->unprepare_message = loongson_spi_unprepare_message; in loongson_spi_init_controller()
210 controller->set_cs = loongson_spi_set_cs; in loongson_spi_init_controller()
211 controller->num_chipselect = 4; in loongson_spi_init_controller()
212 device_set_node(&controller->dev, dev_fwnode(dev)); in loongson_spi_init_controller()
215 spi = spi_controller_get_devdata(controller); in loongson_spi_init_controller()
216 spi->base = regs; in loongson_spi_init_controller()
217 spi->controller = controller; in loongson_spi_init_controller()
223 spi->clk_rate = clk_get_rate(clk); in loongson_spi_init_controller()
224 loongson_spi_reginit(spi); in loongson_spi_init_controller()
226 spi->mode = 0; in loongson_spi_init_controller()
242 loongson_spi->spcr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG); in loongson_spi_suspend()
243 loongson_spi->sper = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG); in loongson_spi_suspend()
244 loongson_spi->spsr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG); in loongson_spi_suspend()
245 loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG); in loongson_spi_suspend()
246 loongson_spi->sfcs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG); in loongson_spi_suspend()
247 loongson_spi->timi = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_TIMI_REG); in loongson_spi_suspend()
260 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, loongson_spi->spcr); in loongson_spi_resume()
261 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, loongson_spi->sper); in loongson_spi_resume()
262 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPSR_REG, loongson_spi->spsr); in loongson_spi_resume()
263 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para); in loongson_spi_resume()
264 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, loongson_spi->sfcs); in loongson_spi_resume()
265 loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_TIMI_REG, loongson_spi->timi); in loongson_spi_resume()
278 MODULE_DESCRIPTION("Loongson SPI core driver");