xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/s5c73m3/s5c73m3-spi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Samsung LSI S5C73M3 8M pixel camera driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012, Samsung Electronics, Co., Ltd.
6*4882a593Smuzhiyun  * Sylwester Nawrocki <s.nawrocki@samsung.com>
7*4882a593Smuzhiyun  * Andrzej Hajda <a.hajda@samsung.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/sizes.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/media.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/spi/spi.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include "s5c73m3.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static const struct of_device_id s5c73m3_spi_ids[] = {
23*4882a593Smuzhiyun 	{ .compatible = "samsung,s5c73m3" },
24*4882a593Smuzhiyun 	{ }
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun enum spi_direction {
29*4882a593Smuzhiyun 	SPI_DIR_RX,
30*4882a593Smuzhiyun 	SPI_DIR_TX
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
spi_xmit(struct spi_device * spi_dev,void * addr,const int len,enum spi_direction dir)33*4882a593Smuzhiyun static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len,
34*4882a593Smuzhiyun 							enum spi_direction dir)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	struct spi_message msg;
37*4882a593Smuzhiyun 	int r;
38*4882a593Smuzhiyun 	struct spi_transfer xfer = {
39*4882a593Smuzhiyun 		.len	= len,
40*4882a593Smuzhiyun 	};
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	if (dir == SPI_DIR_TX)
43*4882a593Smuzhiyun 		xfer.tx_buf = addr;
44*4882a593Smuzhiyun 	else
45*4882a593Smuzhiyun 		xfer.rx_buf = addr;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	if (spi_dev == NULL) {
48*4882a593Smuzhiyun 		pr_err("SPI device is uninitialized\n");
49*4882a593Smuzhiyun 		return -ENODEV;
50*4882a593Smuzhiyun 	}
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	spi_message_init(&msg);
53*4882a593Smuzhiyun 	spi_message_add_tail(&xfer, &msg);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	r = spi_sync(spi_dev, &msg);
56*4882a593Smuzhiyun 	if (r < 0)
57*4882a593Smuzhiyun 		dev_err(&spi_dev->dev, "%s spi_sync failed %d\n", __func__, r);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	return r;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
s5c73m3_spi_write(struct s5c73m3 * state,const void * addr,const unsigned int len,const unsigned int tx_size)62*4882a593Smuzhiyun int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
63*4882a593Smuzhiyun 		      const unsigned int len, const unsigned int tx_size)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	struct spi_device *spi_dev = state->spi_dev;
66*4882a593Smuzhiyun 	u32 count = len / tx_size;
67*4882a593Smuzhiyun 	u32 extra = len % tx_size;
68*4882a593Smuzhiyun 	unsigned int i, j = 0;
69*4882a593Smuzhiyun 	u8 padding[32];
70*4882a593Smuzhiyun 	int r = 0;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	memset(padding, 0, sizeof(padding));
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
75*4882a593Smuzhiyun 		r = spi_xmit(spi_dev, (void *)addr + j, tx_size, SPI_DIR_TX);
76*4882a593Smuzhiyun 		if (r < 0)
77*4882a593Smuzhiyun 			return r;
78*4882a593Smuzhiyun 		j += tx_size;
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (extra > 0) {
82*4882a593Smuzhiyun 		r = spi_xmit(spi_dev, (void *)addr + j, extra, SPI_DIR_TX);
83*4882a593Smuzhiyun 		if (r < 0)
84*4882a593Smuzhiyun 			return r;
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return spi_xmit(spi_dev, padding, sizeof(padding), SPI_DIR_TX);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
s5c73m3_spi_read(struct s5c73m3 * state,void * addr,const unsigned int len,const unsigned int tx_size)90*4882a593Smuzhiyun int s5c73m3_spi_read(struct s5c73m3 *state, void *addr,
91*4882a593Smuzhiyun 		     const unsigned int len, const unsigned int tx_size)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	struct spi_device *spi_dev = state->spi_dev;
94*4882a593Smuzhiyun 	u32 count = len / tx_size;
95*4882a593Smuzhiyun 	u32 extra = len % tx_size;
96*4882a593Smuzhiyun 	unsigned int i, j = 0;
97*4882a593Smuzhiyun 	int r = 0;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
100*4882a593Smuzhiyun 		r = spi_xmit(spi_dev, addr + j, tx_size, SPI_DIR_RX);
101*4882a593Smuzhiyun 		if (r < 0)
102*4882a593Smuzhiyun 			return r;
103*4882a593Smuzhiyun 		j += tx_size;
104*4882a593Smuzhiyun 	}
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	if (extra > 0)
107*4882a593Smuzhiyun 		return spi_xmit(spi_dev, addr + j, extra, SPI_DIR_RX);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	return 0;
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
s5c73m3_spi_probe(struct spi_device * spi)112*4882a593Smuzhiyun static int s5c73m3_spi_probe(struct spi_device *spi)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	int r;
115*4882a593Smuzhiyun 	struct s5c73m3 *state = container_of(spi->dev.driver, struct s5c73m3,
116*4882a593Smuzhiyun 					     spidrv.driver);
117*4882a593Smuzhiyun 	spi->bits_per_word = 32;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	r = spi_setup(spi);
120*4882a593Smuzhiyun 	if (r < 0) {
121*4882a593Smuzhiyun 		dev_err(&spi->dev, "spi_setup() failed\n");
122*4882a593Smuzhiyun 		return r;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	mutex_lock(&state->lock);
126*4882a593Smuzhiyun 	state->spi_dev = spi;
127*4882a593Smuzhiyun 	mutex_unlock(&state->lock);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	v4l2_info(&state->sensor_sd, "S5C73M3 SPI probed successfully\n");
130*4882a593Smuzhiyun 	return 0;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
s5c73m3_spi_remove(struct spi_device * spi)133*4882a593Smuzhiyun static int s5c73m3_spi_remove(struct spi_device *spi)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	return 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
s5c73m3_register_spi_driver(struct s5c73m3 * state)138*4882a593Smuzhiyun int s5c73m3_register_spi_driver(struct s5c73m3 *state)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	struct spi_driver *spidrv = &state->spidrv;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	spidrv->remove = s5c73m3_spi_remove;
143*4882a593Smuzhiyun 	spidrv->probe = s5c73m3_spi_probe;
144*4882a593Smuzhiyun 	spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
145*4882a593Smuzhiyun 	spidrv->driver.of_match_table = s5c73m3_spi_ids;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	return spi_register_driver(spidrv);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
s5c73m3_unregister_spi_driver(struct s5c73m3 * state)150*4882a593Smuzhiyun void s5c73m3_unregister_spi_driver(struct s5c73m3 *state)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	spi_unregister_driver(&state->spidrv);
153*4882a593Smuzhiyun }
154