xref: /OK3568_Linux_fs/kernel/drivers/spi/spidev-rkmst.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include <linux/delay.h>
7 #include <linux/gpio.h>
8 #include <linux/interrupt.h>
9 #include <linux/iopoll.h>
10 #include <linux/miscdevice.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_gpio.h>
14 #include <linux/platform_device.h>
15 #include <linux/random.h>
16 #include <linux/slab.h>
17 #include <linux/spi/spi.h>
18 
19 #include <linux/platform_data/spi-rockchip.h>
20 
21 #define SPI_OBJ_MAX_XFER_SIZE	0x1040
22 #define SPI_OBJ_APP_RAM_SIZE	0x10000
23 
24 #define SPI_OBJ_CTRL_MSG_SIZE	0x8
25 #define SPI_OBJ_CTRL_CMD_INIT	0x99
26 #define SPI_OBJ_CTRL_CMD_READ	0x3A
27 #define SPI_OBJ_CTRL_CMD_WRITE	0x4B
28 #define SPI_OBJ_CTRL_CMD_DUPLEX	0x5C
29 
30 #define SPI_OBJ_DEFAULT_TIMEOUT_US	100000
31 
32 struct spi_obj_ctrl {
33 	u16 cmd;
34 	u16 addr;
35 	u32 data;
36 };
37 
38 struct spidev_rkmst_data {
39 	struct device	*dev;
40 	struct spi_device *spi;
41 	char *ctrlbuf;
42 	char *rxbuf;
43 	char *txbuf;
44 	struct gpio_desc *ready;
45 	int ready_irqnum;
46 	bool ready_status;
47 	bool verbose;
48 	struct miscdevice misc_dev;
49 };
50 
51 static u32 bit_per_word = 8;
52 
spidev_mst_slave_ready_status(struct spidev_rkmst_data * spidev,bool status)53 static inline void spidev_mst_slave_ready_status(struct spidev_rkmst_data *spidev, bool status)
54 {
55 	spidev->ready_status = status;
56 }
57 
spidev_mst_slave_ready_interrupt(int irq,void * arg)58 static irqreturn_t spidev_mst_slave_ready_interrupt(int irq, void *arg)
59 {
60 	struct spidev_rkmst_data *spidev = (struct spidev_rkmst_data *)arg;
61 
62 	spidev_mst_slave_ready_status(spidev, true);
63 
64 	return IRQ_HANDLED;
65 }
66 
spidev_mst_check_slave_ready(struct spidev_rkmst_data * spidev)67 static bool spidev_mst_check_slave_ready(struct spidev_rkmst_data *spidev)
68 {
69 	return spidev->ready_status;
70 }
71 
spidev_mst_wait_for_slave_ready(struct spidev_rkmst_data * spidev,u32 timeout_us)72 static int spidev_mst_wait_for_slave_ready(struct spidev_rkmst_data *spidev,
73 					   u32 timeout_us)
74 {
75 	bool ready;
76 	int ret;
77 
78 	ret = read_poll_timeout(spidev_mst_check_slave_ready, ready,
79 				ready, 100, timeout_us + 100, false, spidev);
80 	if (ret) {
81 		dev_err(&spidev->spi->dev, "timeout and reset slave\n");
82 
83 		return -ETIMEDOUT;
84 	}
85 
86 	return true;
87 }
88 
spidev_mst_write(struct spidev_rkmst_data * spidev,const void * txbuf,size_t n)89 static int spidev_mst_write(struct spidev_rkmst_data *spidev, const void *txbuf, size_t n)
90 {
91 	struct spi_device *spi = spidev->spi;
92 	struct spi_transfer t = {
93 			.tx_buf = txbuf,
94 			.len = n,
95 			.bits_per_word = bit_per_word,
96 		};
97 	struct spi_message m;
98 	int ret;
99 
100 	spi_message_init(&m);
101 	spi_message_add_tail(&t, &m);
102 
103 	ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_DEFAULT_TIMEOUT_US);
104 	if (ret < 0)
105 		return ret;
106 
107 	spidev_mst_slave_ready_status(spidev, false);
108 	ret = spi_sync(spi, &m);
109 
110 	return ret;
111 }
112 
spidev_mst_write_bypass(struct spidev_rkmst_data * spidev,const void * txbuf,size_t n)113 static int spidev_mst_write_bypass(struct spidev_rkmst_data *spidev, const void *txbuf, size_t n)
114 {
115 	struct spi_device *spi = spidev->spi;
116 	struct spi_transfer t = {
117 			.tx_buf = txbuf,
118 			.len = n,
119 			.bits_per_word = bit_per_word,
120 		};
121 	struct spi_message m;
122 	int ret;
123 
124 	spi_message_init(&m);
125 	spi_message_add_tail(&t, &m);
126 
127 	ret = spi_sync(spi, &m);
128 
129 	return ret;
130 }
131 
spidev_mst_read(struct spidev_rkmst_data * spidev,void * rxbuf,size_t n)132 static int spidev_mst_read(struct spidev_rkmst_data *spidev, void *rxbuf, size_t n)
133 {
134 	struct spi_device *spi = spidev->spi;
135 	struct spi_transfer t = {
136 			.rx_buf = rxbuf,
137 			.len = n,
138 			.bits_per_word = bit_per_word,
139 		};
140 	struct spi_message m;
141 	int ret;
142 
143 	spi_message_init(&m);
144 	spi_message_add_tail(&t, &m);
145 
146 	ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_MAX_XFER_SIZE);
147 	if (ret < 0)
148 		return ret;
149 
150 	spidev_mst_slave_ready_status(spidev, false);
151 	ret = spi_sync(spi, &m);
152 
153 	return ret;
154 }
155 
spidev_slv_write_and_read(struct spidev_rkmst_data * spidev,const void * tx_buf,void * rx_buf,size_t len)156 static int spidev_slv_write_and_read(struct spidev_rkmst_data *spidev,
157 				     const void *tx_buf, void *rx_buf,
158 				     size_t len)
159 {
160 	struct spi_device *spi = spidev->spi;
161 	struct spi_transfer t = {
162 			.tx_buf = tx_buf,
163 			.rx_buf = rx_buf,
164 			.len = len,
165 		};
166 	struct spi_message m;
167 	int ret;
168 
169 	spi_message_init(&m);
170 	spi_message_add_tail(&t, &m);
171 
172 	ret = spidev_mst_wait_for_slave_ready(spidev, SPI_OBJ_MAX_XFER_SIZE);
173 	if (ret < 0)
174 		return ret;
175 
176 	spidev_mst_slave_ready_status(spidev, false);
177 	ret = spi_sync(spi, &m);
178 
179 	return ret;
180 }
181 
spidev_rkmst_reset_slave(struct spidev_rkmst_data * spidev)182 static void spidev_rkmst_reset_slave(struct spidev_rkmst_data *spidev)
183 {
184 	struct spi_obj_ctrl *ctrl = (struct spi_obj_ctrl *)spidev->ctrlbuf;
185 
186 	ctrl->cmd = SPI_OBJ_CTRL_CMD_INIT;
187 
188 	spidev_mst_write_bypass(spidev, ctrl, SPI_OBJ_MAX_XFER_SIZE);
189 	msleep(100);
190 	spidev_mst_write_bypass(spidev, ctrl, SPI_OBJ_MAX_XFER_SIZE);
191 }
192 
193 
spidev_rkmst_ctrl(struct spidev_rkmst_data * spidev,u32 cmd,u16 addr,u32 data)194 static int spidev_rkmst_ctrl(struct spidev_rkmst_data *spidev, u32 cmd, u16 addr, u32 data)
195 {
196 	struct spi_obj_ctrl *ctrl = (struct spi_obj_ctrl *)spidev->ctrlbuf;
197 	struct spi_device *spi = spidev->spi;
198 	int ret;
199 
200 	if (spidev->verbose)
201 		dev_err(&spi->dev, "ctrl cmd=%x addr=0x%x data=0x%x\n", cmd, addr, data);
202 
203 	/* ctrl_xfer */
204 	ctrl->cmd = cmd;
205 	ctrl->addr = addr;
206 	ctrl->data = data;
207 	ret = spidev_mst_write(spidev, ctrl, SPI_OBJ_CTRL_MSG_SIZE);
208 	if (ret) {
209 		dev_err(&spi->dev, "ctrl cmd=%x addr=0x%x data=0x%x, ret=%d\n", cmd, addr, data, ret);
210 		return -EIO;
211 	}
212 
213 	return 0;
214 }
215 
spidev_rkmst_xfer(struct spidev_rkmst_data * spidev,void * tx,void * rx,u16 addr,u32 len)216 static int spidev_rkmst_xfer(struct spidev_rkmst_data *spidev, void *tx,
217 			     void *rx, u16 addr, u32 len)
218 {
219 	struct spi_device *spi = spidev->spi;
220 	int ret;
221 	u32 cmd;
222 
223 	if (tx && rx)
224 		cmd = SPI_OBJ_CTRL_CMD_DUPLEX;
225 	else if (rx)
226 		cmd = SPI_OBJ_CTRL_CMD_READ;
227 	else if (tx)
228 		cmd = SPI_OBJ_CTRL_CMD_WRITE;
229 	else
230 		return -EINVAL;
231 
232 	/* ctrl_xfer */
233 	ret = spidev_rkmst_ctrl(spidev, cmd, addr, len);
234 	if (ret) {
235 		spidev_rkmst_reset_slave(spidev);
236 		return -EIO;
237 	}
238 
239 	if (spidev->verbose)
240 		dev_err(&spi->dev, "xfer len=0x%x\n", len);
241 	/* data_xfer */
242 	switch (cmd) {
243 	case SPI_OBJ_CTRL_CMD_READ:
244 		ret = spidev_mst_read(spidev, rx, len);
245 		if (ret)
246 			goto err_out;
247 		break;
248 	case SPI_OBJ_CTRL_CMD_WRITE:
249 		ret = spidev_mst_write(spidev, tx, len);
250 		if (ret)
251 			goto err_out;
252 		break;
253 	case SPI_OBJ_CTRL_CMD_DUPLEX:
254 		ret = spidev_slv_write_and_read(spidev, tx, rx, len);
255 		if (ret)
256 			goto err_out;
257 		break;
258 	default:
259 		dev_err(&spi->dev, "%s unknown\n", __func__);
260 	}
261 
262 	return 0;
263 err_out:
264 	dev_err(&spi->dev, "xfer cmd=%x addr=0x%x len=0x%x, ret=%d\n",
265 		cmd, addr, len, ret);
266 
267 	return ret;
268 }
269 
spidev_rkmst_misc_write(struct file * filp,const char __user * buf,size_t n,loff_t * offset)270 static ssize_t spidev_rkmst_misc_write(struct file *filp, const char __user *buf,
271 				       size_t n, loff_t *offset)
272 {
273 	struct spidev_rkmst_data *spidev;
274 	struct spi_device *spi;
275 	int argc = 0, i;
276 	char tmp[64];
277 	char *argv[16];
278 	char *cmd, *data;
279 
280 	if (n >= 64)
281 		return -EINVAL;
282 
283 	spidev = filp->private_data;
284 
285 	if (!spidev)
286 		return -ESHUTDOWN;
287 
288 	spi = spidev->spi;
289 	memset(tmp, 0, sizeof(tmp));
290 	if (copy_from_user(tmp, buf, n))
291 		return -EFAULT;
292 	cmd = tmp;
293 	data = tmp;
294 
295 	while (data < (tmp + n)) {
296 		data = strstr(data, " ");
297 		if (!data)
298 			break;
299 		*data = 0;
300 		argv[argc] = ++data;
301 		argc++;
302 		if (argc >= 16)
303 			break;
304 	}
305 
306 	tmp[n - 1] = 0;
307 
308 	if (!strcmp(cmd, "verbose")) {
309 		int val;
310 
311 		if (argc < 1)
312 			return -EINVAL;
313 
314 		if (kstrtoint(argv[0], 0, &val))
315 			return -EINVAL;
316 
317 		if (val == 1)
318 			spidev->verbose = true;
319 		else
320 			spidev->verbose = false;
321 	} else if (!strcmp(cmd, "init")) {
322 		spidev_rkmst_ctrl(spidev, SPI_OBJ_CTRL_CMD_INIT, 0x55AA, 0x1234567);
323 	} else if (!strcmp(cmd, "read")) {
324 		int addr, len;
325 
326 		if (argc < 2)
327 			return -EINVAL;
328 
329 		if (kstrtoint(argv[0], 0, &addr))
330 			return -EINVAL;
331 		if (kstrtoint(argv[1], 0, &len))
332 			return -EINVAL;
333 
334 		if (!len) {
335 			dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]);
336 			return -EINVAL;
337 		}
338 
339 		if (addr + len > SPI_OBJ_APP_RAM_SIZE) {
340 			dev_err(&spi->dev, "rxbuf print out of size\n");
341 			return -EINVAL;
342 		}
343 
344 		spidev_rkmst_xfer(spidev, NULL, spidev->rxbuf, addr, len);
345 
346 		print_hex_dump(KERN_ERR, "m-r: ",
347 			       DUMP_PREFIX_OFFSET,
348 			       16,
349 			       1,
350 			       spidev->rxbuf,
351 			       len,
352 			       1);
353 	} else if (!strcmp(cmd, "write")) {
354 		int addr, len;
355 
356 		if (argc < 2)
357 			return -EINVAL;
358 
359 		if (kstrtoint(argv[0], 0, &addr))
360 			return -EINVAL;
361 		if (kstrtoint(argv[1], 0, &len))
362 			return -EINVAL;
363 
364 		if (!len) {
365 			dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]);
366 			return -EINVAL;
367 		}
368 
369 		if (addr + len > SPI_OBJ_APP_RAM_SIZE) {
370 			dev_err(&spi->dev, "rxbuf print out of size\n");
371 			return -EINVAL;
372 		}
373 
374 		for (i = 0; i < len; i++)
375 			spidev->txbuf[i] = i & 0xFF;
376 		((u32 *)spidev->txbuf)[0] = addr;
377 
378 		spidev_rkmst_xfer(spidev, spidev->txbuf, NULL, addr, len);
379 	} else if (!strcmp(cmd, "duplex")) {
380 		int addr, len;
381 
382 		if (argc < 2)
383 			return -EINVAL;
384 
385 		if (kstrtoint(argv[0], 0, &addr))
386 			return -EINVAL;
387 		if (kstrtoint(argv[1], 0, &len))
388 			return -EINVAL;
389 
390 		if (!len) {
391 			dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]);
392 			return -EINVAL;
393 		}
394 
395 		if (addr + len > SPI_OBJ_APP_RAM_SIZE) {
396 			dev_err(&spi->dev, "rxbuf print out of size\n");
397 			return -EINVAL;
398 		}
399 
400 		for (i = 0; i < len; i++)
401 			spidev->txbuf[i] = i & 0xFF;
402 		((u32 *)spidev->txbuf)[0] = addr;
403 
404 		spidev_rkmst_xfer(spidev, spidev->txbuf, spidev->rxbuf, addr, len);
405 
406 		print_hex_dump(KERN_ERR, "m-d: ",
407 			       DUMP_PREFIX_OFFSET,
408 			       16,
409 			       1,
410 			       spidev->rxbuf,
411 			       len,
412 			       1);
413 	} else if (!strcmp(cmd, "autotest")) {
414 		int addr = 0, len, loops, i;
415 		unsigned long long bytes = 0;
416 		unsigned long us = 0;
417 		ktime_t start_time;
418 		ktime_t end_time;
419 		ktime_t cost_time;
420 		char *tempbuf;
421 
422 		if (argc < 2)
423 			return -EINVAL;
424 
425 		if (kstrtoint(argv[0], 0, &len))
426 			return -EINVAL;
427 
428 		if (kstrtoint(argv[1], 0, &loops))
429 			return -EINVAL;
430 
431 		if (!len) {
432 			dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]);
433 			return -EINVAL;
434 		}
435 
436 		if (len > SPI_OBJ_APP_RAM_SIZE) {
437 			dev_err(&spi->dev, "rxbuf print out of size\n");
438 			return -EINVAL;
439 		}
440 
441 		tempbuf = kzalloc(len, GFP_KERNEL);
442 		if (!tempbuf)
443 			return -ENOMEM;
444 
445 		prandom_bytes(tempbuf, len);
446 		spidev_rkmst_xfer(spidev, tempbuf, NULL, addr, len);
447 		start_time = ktime_get();
448 		for (i = 0; i < loops; i++) {
449 			prandom_bytes(spidev->txbuf, len);
450 			spidev_rkmst_xfer(spidev, spidev->txbuf, spidev->rxbuf, addr, len);
451 			if (memcmp(spidev->rxbuf, tempbuf, len)) {
452 				dev_err(&spi->dev, "dulplex autotest failed, loops=%d\n", i);
453 				print_hex_dump(KERN_ERR, "m-d-t: ",
454 					       DUMP_PREFIX_OFFSET,
455 					       16,
456 					       1,
457 					       spidev->txbuf,
458 					       len,
459 					       1);
460 				print_hex_dump(KERN_ERR, "m-d-r: ",
461 					       DUMP_PREFIX_OFFSET,
462 					       16,
463 					       1,
464 					       spidev->rxbuf,
465 					       len,
466 					       1);
467 				print_hex_dump(KERN_ERR, "m-d-c: ",
468 					       DUMP_PREFIX_OFFSET,
469 					       16,
470 					       1,
471 					       tempbuf,
472 					       len,
473 					       1);
474 				break;
475 			}
476 			memcpy(tempbuf, spidev->txbuf, len);
477 		}
478 		end_time = ktime_get();
479 		cost_time = ktime_sub(end_time, start_time);
480 		us = ktime_to_us(cost_time);
481 
482 		bytes = (u64)len * (u64)loops * 1000;
483 		do_div(bytes, us);
484 		if (i >= loops)
485 			dev_err(&spi->dev, "dulplex test pass, cost=%ldus, speed=%lldKB/S, %ldus/loops\n",
486 				us, bytes, us / loops);
487 
488 		start_time = ktime_get();
489 		for (i = 0; i < loops; i++) {
490 			prandom_bytes(spidev->txbuf, len);
491 			spidev_rkmst_xfer(spidev, spidev->txbuf, NULL, addr, len);
492 			spidev_rkmst_xfer(spidev, NULL, spidev->rxbuf, addr, len);
493 			if (memcmp(spidev->rxbuf, spidev->txbuf, len)) {
494 				dev_err(&spi->dev, "read/write autotest failed, loops=%d\n", i);
495 				print_hex_dump(KERN_ERR, "m-d-t: ",
496 					       DUMP_PREFIX_OFFSET,
497 					       16,
498 					       1,
499 					       spidev->txbuf,
500 					       len,
501 					       1);
502 				print_hex_dump(KERN_ERR, "m-d-r: ",
503 					       DUMP_PREFIX_OFFSET,
504 					       16,
505 					       1,
506 					       spidev->rxbuf,
507 					       len,
508 					       1);
509 				break;
510 			}
511 		}
512 		end_time = ktime_get();
513 		cost_time = ktime_sub(end_time, start_time);
514 		us = ktime_to_us(cost_time);
515 
516 		bytes = (u64)len * (u64)loops * 2 * 1000; /* multi 2 for both write and read */
517 		do_div(bytes, us);
518 		if (i >= loops)
519 			dev_err(&spi->dev, "read/write test pass, cost=%ldus, speed=%lldKB/S, %ldus/loops\n",
520 				us, bytes, us / loops);
521 		kfree(tempbuf);
522 	} else {
523 		dev_err(&spi->dev, "unknown command\n");
524 	}
525 
526 	return n;
527 }
528 
spidev_rkmst_misc_open(struct inode * inode,struct file * filp)529 static int spidev_rkmst_misc_open(struct inode *inode, struct file *filp)
530 {
531 	struct miscdevice *miscdev = filp->private_data;
532 	struct spidev_rkmst_data *spidev;
533 
534 	spidev = container_of(miscdev, struct spidev_rkmst_data, misc_dev);
535 	filp->private_data = spidev;
536 
537 	return 0;
538 }
539 
540 static const struct file_operations spidev_rkmst_misc_fops = {
541 	.write = spidev_rkmst_misc_write,
542 	.open = spidev_rkmst_misc_open,
543 };
544 
spidev_rkmst_probe(struct spi_device * spi)545 static int spidev_rkmst_probe(struct spi_device *spi)
546 {
547 	struct spidev_rkmst_data *spidev = NULL;
548 	int ret;
549 
550 	if (!spi)
551 		return -ENOMEM;
552 
553 	spidev = devm_kzalloc(&spi->dev, sizeof(struct spidev_rkmst_data), GFP_KERNEL);
554 	if (!spidev)
555 		return -ENOMEM;
556 
557 	spidev->ctrlbuf = devm_kzalloc(&spi->dev, SPI_OBJ_MAX_XFER_SIZE, GFP_KERNEL);
558 	if (!spidev->ctrlbuf)
559 		return -ENOMEM;
560 
561 	spidev->rxbuf = devm_kzalloc(&spi->dev, SPI_OBJ_APP_RAM_SIZE, GFP_KERNEL | GFP_DMA);
562 	if (!spidev->rxbuf)
563 		return -ENOMEM;
564 
565 	spidev->txbuf = devm_kzalloc(&spi->dev, SPI_OBJ_MAX_XFER_SIZE, GFP_KERNEL);
566 	if (!spidev->txbuf)
567 		return -ENOMEM;
568 
569 	spidev->spi = spi;
570 	spidev->dev = &spi->dev;
571 
572 	spidev_mst_slave_ready_status(spidev, false);
573 	spidev->ready = devm_gpiod_get_optional(&spi->dev, "ready", GPIOD_IN);
574 	if (IS_ERR(spidev->ready))
575 		return dev_err_probe(&spi->dev, PTR_ERR(spidev->ready),
576 				     "invalid ready-gpios property in node\n");
577 
578 	spidev->ready_irqnum = gpiod_to_irq(spidev->ready);
579 	ret = devm_request_irq(&spi->dev, spidev->ready_irqnum, spidev_mst_slave_ready_interrupt,
580 		IRQF_TRIGGER_FALLING, "spidev-mst-ready-in", spidev);
581 	if (ret < 0) {
582 		dev_err(&spi->dev, "request ready irq failed\n");
583 		return ret;
584 	}
585 	dev_set_drvdata(&spi->dev, spidev);
586 
587 	dev_err(&spi->dev, "mode=%d, max_speed_hz=%d\n", spi->mode, spi->max_speed_hz);
588 
589 	spidev->misc_dev.minor = MISC_DYNAMIC_MINOR;
590 	spidev->misc_dev.name = "spidev_rkmst_misc";
591 	spidev->misc_dev.fops = &spidev_rkmst_misc_fops;
592 	spidev->misc_dev.parent = &spi->dev;
593 	ret = misc_register(&spidev->misc_dev);
594 	if (ret) {
595 		dev_err(&spi->dev, "fail to register misc device\n");
596 		return ret;
597 	}
598 
599 	spidev_rkmst_reset_slave(spidev);
600 
601 	return 0;
602 }
603 
spidev_rkmst_remove(struct spi_device * spi)604 static int spidev_rkmst_remove(struct spi_device *spi)
605 {
606 	struct spidev_rkmst_data *spidev = dev_get_drvdata(&spi->dev);
607 
608 	misc_deregister(&spidev->misc_dev);
609 
610 	return 0;
611 }
612 
613 #ifdef CONFIG_OF
614 static const struct of_device_id spidev_rkmst_dt_match[] = {
615 	{ .compatible = "rockchip,spi-obj-master", },
616 	{},
617 };
618 MODULE_DEVICE_TABLE(of, spidev_rkmst_dt_match);
619 
620 #endif /* CONFIG_OF */
621 
622 static struct spi_driver spidev_rkmst_driver = {
623 	.driver = {
624 		.name	= "spidev_rkmst",
625 		.owner = THIS_MODULE,
626 		.of_match_table = of_match_ptr(spidev_rkmst_dt_match),
627 	},
628 	.probe		= spidev_rkmst_probe,
629 	.remove		= spidev_rkmst_remove,
630 };
631 module_spi_driver(spidev_rkmst_driver);
632 
633 MODULE_AUTHOR("Jon Lin <jon.lin@rock-chips.com>");
634 MODULE_DESCRIPTION("ROCKCHIP SPI Object Master Driver");
635 MODULE_LICENSE("GPL");
636 MODULE_ALIAS("spi:spidev_rkmst");
637