1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd.
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/delay.h>
5*4882a593Smuzhiyun #include <linux/i2c.h>
6*4882a593Smuzhiyun #include <linux/module.h>
7*4882a593Smuzhiyun #include <linux/pm_runtime.h>
8*4882a593Smuzhiyun #include <linux/rk-camera-module.h>
9*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
10*4882a593Smuzhiyun #include <media/v4l2-device.h>
11*4882a593Smuzhiyun #include "imx258_eeprom_head.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #define DEVICE_NAME "imx258_eeprom"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun static inline struct imx258_eeprom_device
sd_to_imx258_eeprom(struct v4l2_subdev * subdev)16*4882a593Smuzhiyun *sd_to_imx258_eeprom(struct v4l2_subdev *subdev)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun return container_of(subdev, struct imx258_eeprom_device, sd);
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /* Read registers up to 4 at a time */
imx258_read_reg_otp(struct i2c_client * client,u16 reg,unsigned int len,u32 * val)22*4882a593Smuzhiyun static int imx258_read_reg_otp(struct i2c_client *client, u16 reg,
23*4882a593Smuzhiyun unsigned int len, u32 *val)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun struct i2c_msg msgs[2];
26*4882a593Smuzhiyun u8 *data_be_p;
27*4882a593Smuzhiyun __be32 data_be = 0;
28*4882a593Smuzhiyun __be16 reg_addr_be = cpu_to_be16(reg);
29*4882a593Smuzhiyun int ret;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (len > 4 || !len)
32*4882a593Smuzhiyun return -EINVAL;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun data_be_p = (u8 *)&data_be;
35*4882a593Smuzhiyun /* Write register address */
36*4882a593Smuzhiyun msgs[0].addr = client->addr;
37*4882a593Smuzhiyun msgs[0].flags = 0;
38*4882a593Smuzhiyun msgs[0].len = 2;
39*4882a593Smuzhiyun msgs[0].buf = (u8 *)®_addr_be;
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* Read data from register */
42*4882a593Smuzhiyun msgs[1].addr = client->addr;
43*4882a593Smuzhiyun msgs[1].flags = I2C_M_RD;
44*4882a593Smuzhiyun msgs[1].len = len;
45*4882a593Smuzhiyun msgs[1].buf = &data_be_p[4 - len];
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
48*4882a593Smuzhiyun if (ret != ARRAY_SIZE(msgs))
49*4882a593Smuzhiyun return -EIO;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun *val = be32_to_cpu(data_be);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun return 0;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
get_vendor_flag(struct i2c_client * client)56*4882a593Smuzhiyun static u8 get_vendor_flag(struct i2c_client *client)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun u8 vendor_flag = 0;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (client->addr == SLAVE_ADDRESS_GZ)
61*4882a593Smuzhiyun vendor_flag |= 0x80;
62*4882a593Smuzhiyun return vendor_flag;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
imx258_otp_read_gz(struct imx258_eeprom_device * imx258_eeprom_dev)65*4882a593Smuzhiyun static int imx258_otp_read_gz(struct imx258_eeprom_device *imx258_eeprom_dev)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun struct i2c_client *client = imx258_eeprom_dev->client;
68*4882a593Smuzhiyun int otp_flag, i;
69*4882a593Smuzhiyun struct imx258_otp_info *otp_ptr;
70*4882a593Smuzhiyun struct device *dev = &imx258_eeprom_dev->client->dev;
71*4882a593Smuzhiyun int ret = 0;
72*4882a593Smuzhiyun u32 r_value, gr_value, gb_value, b_value;
73*4882a593Smuzhiyun u32 temp = 0;
74*4882a593Smuzhiyun u32 checksum = 0;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun otp_ptr = kzalloc(sizeof(*otp_ptr), GFP_KERNEL);
77*4882a593Smuzhiyun if (!otp_ptr)
78*4882a593Smuzhiyun return -ENOMEM;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun otp_flag = 0;
81*4882a593Smuzhiyun /* OTP base information*/
82*4882a593Smuzhiyun ret = imx258_read_reg_otp(client, GZ_INFO_FLAG_REG,
83*4882a593Smuzhiyun 1, &otp_flag);
84*4882a593Smuzhiyun if (otp_flag == 0x01) {
85*4882a593Smuzhiyun otp_ptr->flag = 0x80; /* valid INFO in OTP */
86*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_ID_REG,
87*4882a593Smuzhiyun 1, &otp_ptr->module_id);
88*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_LENS_ID_REG,
89*4882a593Smuzhiyun 1, &otp_ptr->lens_id);
90*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_PRODUCT_YEAR_REG,
91*4882a593Smuzhiyun 1, &otp_ptr->year);
92*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_PRODUCT_MONTH_REG,
93*4882a593Smuzhiyun 1, &otp_ptr->month);
94*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_PRODUCT_DAY_REG,
95*4882a593Smuzhiyun 1, &otp_ptr->day);
96*4882a593Smuzhiyun dev_dbg(dev, "fac info: module(0x%x) lens(0x%x) time(%d_%d_%d)!\n",
97*4882a593Smuzhiyun otp_ptr->module_id,
98*4882a593Smuzhiyun otp_ptr->lens_id,
99*4882a593Smuzhiyun otp_ptr->year,
100*4882a593Smuzhiyun otp_ptr->month,
101*4882a593Smuzhiyun otp_ptr->day);
102*4882a593Smuzhiyun if (ret)
103*4882a593Smuzhiyun goto err;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* OTP WB calibration data */
107*4882a593Smuzhiyun ret = imx258_read_reg_otp(client, GZ_AWB_FLAG_REG,
108*4882a593Smuzhiyun 1, &otp_flag);
109*4882a593Smuzhiyun if (otp_flag == 0x01) {
110*4882a593Smuzhiyun otp_ptr->flag |= 0x40; /* valid AWB in OTP */
111*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_CUR_R_REG,
112*4882a593Smuzhiyun 1, &r_value);
113*4882a593Smuzhiyun checksum += r_value;
114*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_CUR_GR_REG,
115*4882a593Smuzhiyun 1, &gr_value);
116*4882a593Smuzhiyun checksum += gr_value;
117*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_CUR_GB_REG,
118*4882a593Smuzhiyun 1, &gb_value);
119*4882a593Smuzhiyun checksum += gb_value;
120*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_CUR_B_REG,
121*4882a593Smuzhiyun 1, &b_value);
122*4882a593Smuzhiyun checksum += b_value;
123*4882a593Smuzhiyun otp_ptr->rg_ratio =
124*4882a593Smuzhiyun r_value * 1024 / ((gr_value + gb_value) / 2);
125*4882a593Smuzhiyun otp_ptr->bg_ratio =
126*4882a593Smuzhiyun b_value * 1024 / ((gr_value + gb_value) / 2);
127*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_GOLDEN_R_REG,
128*4882a593Smuzhiyun 1, &r_value);
129*4882a593Smuzhiyun checksum += r_value;
130*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_GOLDEN_GR_REG,
131*4882a593Smuzhiyun 1, &gr_value);
132*4882a593Smuzhiyun checksum += gr_value;
133*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_GOLDEN_GB_REG,
134*4882a593Smuzhiyun 1, &gb_value);
135*4882a593Smuzhiyun checksum += gb_value;
136*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_GOLDEN_B_REG,
137*4882a593Smuzhiyun 1, &b_value);
138*4882a593Smuzhiyun checksum += b_value;
139*4882a593Smuzhiyun otp_ptr->rg_golden =
140*4882a593Smuzhiyun r_value * 1024 / ((gr_value + gb_value) / 2);
141*4882a593Smuzhiyun otp_ptr->bg_golden =
142*4882a593Smuzhiyun b_value * 1024 / ((gr_value + gb_value) / 2);
143*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_AWB_CHECKSUM_REG,
144*4882a593Smuzhiyun 1, &temp);
145*4882a593Smuzhiyun if (ret != 0 || (checksum % 0xff) != temp) {
146*4882a593Smuzhiyun dev_err(dev, "otp awb info: check sum (%d,%d),ret = %d !\n",
147*4882a593Smuzhiyun checksum,
148*4882a593Smuzhiyun temp,
149*4882a593Smuzhiyun ret);
150*4882a593Smuzhiyun goto err;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun dev_dbg(dev, "awb cur:(rg 0x%x, bg 0x%x,)\n",
153*4882a593Smuzhiyun otp_ptr->rg_ratio, otp_ptr->bg_ratio);
154*4882a593Smuzhiyun dev_dbg(dev, "awb gol:(rg 0x%x, bg 0x%x)\n",
155*4882a593Smuzhiyun otp_ptr->rg_golden, otp_ptr->bg_golden);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun checksum = 0;
159*4882a593Smuzhiyun /* OTP LSC calibration data */
160*4882a593Smuzhiyun ret = imx258_read_reg_otp(client, GZ_LSC_FLAG_REG,
161*4882a593Smuzhiyun 1, &otp_flag);
162*4882a593Smuzhiyun if (otp_flag == 0x01) {
163*4882a593Smuzhiyun otp_ptr->flag |= 0x10; /* valid LSC in OTP */
164*4882a593Smuzhiyun for (i = 0; i < 504; i++) {
165*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client,
166*4882a593Smuzhiyun GZ_LSC_DATA_START_REG + i,
167*4882a593Smuzhiyun 1, &temp);
168*4882a593Smuzhiyun otp_ptr->lenc[i] = temp;
169*4882a593Smuzhiyun checksum += temp;
170*4882a593Smuzhiyun dev_dbg(dev,
171*4882a593Smuzhiyun "otp read lsc addr = 0x%04x, lenc[%d] = %d\n",
172*4882a593Smuzhiyun GZ_LSC_DATA_START_REG + i, i, temp);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_LSC_CHECKSUM_REG,
175*4882a593Smuzhiyun 1, &temp);
176*4882a593Smuzhiyun if (ret != 0 || (checksum % 0xff) != temp) {
177*4882a593Smuzhiyun dev_err(dev,
178*4882a593Smuzhiyun "otp lsc info: check sum (%d,%d),ret = %d !\n",
179*4882a593Smuzhiyun checksum, temp, ret);
180*4882a593Smuzhiyun goto err;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun checksum = 0;
185*4882a593Smuzhiyun /* OTP VCM calibration data */
186*4882a593Smuzhiyun ret = imx258_read_reg_otp(client, GZ_VCM_FLAG_REG,
187*4882a593Smuzhiyun 1, &otp_flag);
188*4882a593Smuzhiyun if (otp_flag == 0x01) {
189*4882a593Smuzhiyun otp_ptr->flag |= 0x20; /* valid VCM in OTP */
190*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_DIR_REG,
191*4882a593Smuzhiyun 1, &otp_ptr->vcm_dir);
192*4882a593Smuzhiyun checksum += otp_ptr->vcm_dir;
193*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_START_REG,
194*4882a593Smuzhiyun 1, &temp);
195*4882a593Smuzhiyun checksum += temp;
196*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_START_REG + 1,
197*4882a593Smuzhiyun 1, &otp_ptr->vcm_start);
198*4882a593Smuzhiyun checksum += otp_ptr->vcm_start;
199*4882a593Smuzhiyun otp_ptr->vcm_start |= (temp << 8);
200*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_END_REG,
201*4882a593Smuzhiyun 1, &temp);
202*4882a593Smuzhiyun checksum += temp;
203*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_END_REG + 1,
204*4882a593Smuzhiyun 1, &otp_ptr->vcm_end);
205*4882a593Smuzhiyun checksum += otp_ptr->vcm_end;
206*4882a593Smuzhiyun otp_ptr->vcm_end |= (temp << 8);
207*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_VCM_CHECKSUM_REG,
208*4882a593Smuzhiyun 1, &temp);
209*4882a593Smuzhiyun if (ret != 0 || (checksum % 0xff) != temp) {
210*4882a593Smuzhiyun dev_err(dev,
211*4882a593Smuzhiyun "otp VCM info: check sum (%d,%d),ret = %d !\n",
212*4882a593Smuzhiyun checksum, temp, ret);
213*4882a593Smuzhiyun goto err;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun dev_dbg(dev, "vcm_info: 0x%x, 0x%x, 0x%x!\n",
216*4882a593Smuzhiyun otp_ptr->vcm_start,
217*4882a593Smuzhiyun otp_ptr->vcm_end,
218*4882a593Smuzhiyun otp_ptr->vcm_dir);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun checksum = 0;
222*4882a593Smuzhiyun /* OTP SPC calibration data */
223*4882a593Smuzhiyun ret = imx258_read_reg_otp(client, GZ_SPC_FLAG_REG,
224*4882a593Smuzhiyun 1, &otp_flag);
225*4882a593Smuzhiyun if (otp_flag == 0x01) {
226*4882a593Smuzhiyun otp_ptr->flag |= 0x08; /* valid LSC in OTP */
227*4882a593Smuzhiyun for (i = 0; i < 126; i++) {
228*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client,
229*4882a593Smuzhiyun GZ_SPC_DATA_START_REG + i,
230*4882a593Smuzhiyun 1, &temp);
231*4882a593Smuzhiyun otp_ptr->spc[i] = (uint8_t)temp;
232*4882a593Smuzhiyun checksum += temp;
233*4882a593Smuzhiyun dev_dbg(dev,
234*4882a593Smuzhiyun "otp read spc addr = 0x%04x, spc[%d] = %d\n",
235*4882a593Smuzhiyun GZ_SPC_DATA_START_REG + i, i, temp);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun ret |= imx258_read_reg_otp(client, GZ_SPC_CHECKSUM_REG,
238*4882a593Smuzhiyun 1, &temp);
239*4882a593Smuzhiyun if (ret != 0 || (checksum % 0xff) != temp) {
240*4882a593Smuzhiyun dev_err(dev,
241*4882a593Smuzhiyun "otp spc info: check sum (%d,%d),ret = %d !\n",
242*4882a593Smuzhiyun checksum, temp, ret);
243*4882a593Smuzhiyun goto err;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (otp_ptr->flag) {
248*4882a593Smuzhiyun imx258_eeprom_dev->otp = otp_ptr;
249*4882a593Smuzhiyun } else {
250*4882a593Smuzhiyun imx258_eeprom_dev->otp = NULL;
251*4882a593Smuzhiyun kfree(otp_ptr);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return 0;
255*4882a593Smuzhiyun err:
256*4882a593Smuzhiyun imx258_eeprom_dev->otp = NULL;
257*4882a593Smuzhiyun kfree(otp_ptr);
258*4882a593Smuzhiyun return -EINVAL;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
imx258_otp_read(struct imx258_eeprom_device * imx258_eeprom_dev)261*4882a593Smuzhiyun static int imx258_otp_read(struct imx258_eeprom_device *imx258_eeprom_dev)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun u8 vendor_flag = 0;
264*4882a593Smuzhiyun struct i2c_client *client = imx258_eeprom_dev->client;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun vendor_flag = get_vendor_flag(client);
267*4882a593Smuzhiyun if (vendor_flag == 0x80)
268*4882a593Smuzhiyun imx258_otp_read_gz(imx258_eeprom_dev);
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
imx258_eeprom_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)272*4882a593Smuzhiyun static long imx258_eeprom_ioctl(struct v4l2_subdev *sd,
273*4882a593Smuzhiyun unsigned int cmd, void *arg)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun struct imx258_eeprom_device *imx258_eeprom_dev =
276*4882a593Smuzhiyun sd_to_imx258_eeprom(sd);
277*4882a593Smuzhiyun imx258_otp_read(imx258_eeprom_dev);
278*4882a593Smuzhiyun if (arg && imx258_eeprom_dev->otp)
279*4882a593Smuzhiyun memcpy(arg, imx258_eeprom_dev->otp,
280*4882a593Smuzhiyun sizeof(struct imx258_otp_info));
281*4882a593Smuzhiyun return 0;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops imx258_eeprom_core_ops = {
285*4882a593Smuzhiyun .ioctl = imx258_eeprom_ioctl,
286*4882a593Smuzhiyun };
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static const struct v4l2_subdev_ops imx258_eeprom_ops = {
289*4882a593Smuzhiyun .core = &imx258_eeprom_core_ops,
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
imx258_eeprom_subdev_cleanup(struct imx258_eeprom_device * dev)292*4882a593Smuzhiyun static void imx258_eeprom_subdev_cleanup(struct imx258_eeprom_device *dev)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun v4l2_device_unregister_subdev(&dev->sd);
295*4882a593Smuzhiyun media_entity_cleanup(&dev->sd.entity);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
imx258_eeprom_probe(struct i2c_client * client,const struct i2c_device_id * id)298*4882a593Smuzhiyun static int imx258_eeprom_probe(struct i2c_client *client,
299*4882a593Smuzhiyun const struct i2c_device_id *id)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun struct imx258_eeprom_device *imx258_eeprom_dev;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun dev_info(&client->dev, "probing...\n");
304*4882a593Smuzhiyun imx258_eeprom_dev = devm_kzalloc(&client->dev,
305*4882a593Smuzhiyun sizeof(*imx258_eeprom_dev),
306*4882a593Smuzhiyun GFP_KERNEL);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (imx258_eeprom_dev == NULL) {
309*4882a593Smuzhiyun dev_err(&client->dev, "Probe failed\n");
310*4882a593Smuzhiyun return -ENOMEM;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun v4l2_i2c_subdev_init(&imx258_eeprom_dev->sd,
313*4882a593Smuzhiyun client, &imx258_eeprom_ops);
314*4882a593Smuzhiyun imx258_eeprom_dev->client = client;
315*4882a593Smuzhiyun pm_runtime_set_active(&client->dev);
316*4882a593Smuzhiyun pm_runtime_enable(&client->dev);
317*4882a593Smuzhiyun pm_runtime_idle(&client->dev);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun dev_info(&client->dev, "probing successful\n");
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun return 0;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
imx258_eeprom_remove(struct i2c_client * client)324*4882a593Smuzhiyun static int imx258_eeprom_remove(struct i2c_client *client)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun struct v4l2_subdev *sd = i2c_get_clientdata(client);
327*4882a593Smuzhiyun struct imx258_eeprom_device *imx258_eeprom_dev =
328*4882a593Smuzhiyun sd_to_imx258_eeprom(sd);
329*4882a593Smuzhiyun kfree(imx258_eeprom_dev->otp);
330*4882a593Smuzhiyun pm_runtime_disable(&client->dev);
331*4882a593Smuzhiyun imx258_eeprom_subdev_cleanup(imx258_eeprom_dev);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun return 0;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
imx258_eeprom_suspend(struct device * dev)336*4882a593Smuzhiyun static int __maybe_unused imx258_eeprom_suspend(struct device *dev)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun return 0;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
imx258_eeprom_resume(struct device * dev)341*4882a593Smuzhiyun static int __maybe_unused imx258_eeprom_resume(struct device *dev)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun return 0;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun static const struct i2c_device_id imx258_eeprom_id_table[] = {
347*4882a593Smuzhiyun { DEVICE_NAME, 0 },
348*4882a593Smuzhiyun { { 0 } }
349*4882a593Smuzhiyun };
350*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, imx258_eeprom_id_table);
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun static const struct of_device_id imx258_eeprom_of_table[] = {
353*4882a593Smuzhiyun { .compatible = "sony,imx258_eeprom" },
354*4882a593Smuzhiyun { { 0 } }
355*4882a593Smuzhiyun };
356*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, imx258_eeprom_of_table);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun static const struct dev_pm_ops imx258_eeprom_pm_ops = {
359*4882a593Smuzhiyun SET_SYSTEM_SLEEP_PM_OPS(imx258_eeprom_suspend, imx258_eeprom_resume)
360*4882a593Smuzhiyun SET_RUNTIME_PM_OPS(imx258_eeprom_suspend, imx258_eeprom_resume, NULL)
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun static struct i2c_driver imx258_eeprom_i2c_driver = {
364*4882a593Smuzhiyun .driver = {
365*4882a593Smuzhiyun .name = DEVICE_NAME,
366*4882a593Smuzhiyun .pm = &imx258_eeprom_pm_ops,
367*4882a593Smuzhiyun .of_match_table = imx258_eeprom_of_table,
368*4882a593Smuzhiyun },
369*4882a593Smuzhiyun .probe = &imx258_eeprom_probe,
370*4882a593Smuzhiyun .remove = &imx258_eeprom_remove,
371*4882a593Smuzhiyun .id_table = imx258_eeprom_id_table,
372*4882a593Smuzhiyun };
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun module_i2c_driver(imx258_eeprom_i2c_driver);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun MODULE_DESCRIPTION("IMX258 OTP driver");
377*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
378