]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/staging/media/atomisp/i2c/imx/otp_imx.c
2 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License version
6 * 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <linux/bitops.h>
20 #include <linux/device.h>
21 #include <linux/delay.h>
22 #include <linux/errno.h>
24 #include <linux/init.h>
25 #include <linux/i2c.h>
27 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/slab.h>
31 #include <linux/types.h>
32 #include <media/v4l2-device.h>
35 /* Defines for OTP Data Registers */
36 #define IMX_OTP_START_ADDR 0x3B04
37 #define IMX_OTP_PAGE_SIZE 64
38 #define IMX_OTP_READY_REG 0x3B01
39 #define IMX_OTP_PAGE_REG 0x3B02
40 #define IMX_OTP_MODE_REG 0x3B00
41 #define IMX_OTP_PAGE_MAX 20
42 #define IMX_OTP_READY_REG_DONE 1
43 #define IMX_OTP_READ_ONETIME 32
44 #define IMX_OTP_MODE_READ 1
45 #define IMX227_OTP_START_ADDR 0x0A04
46 #define IMX227_OTP_ENABLE_REG 0x0A00
47 #define IMX227_OTP_READY_REG 0x0A01
48 #define IMX227_OTP_PAGE_REG 0x0A02
49 #define IMX227_OTP_READY_REG_DONE 1
50 #define IMX227_OTP_MODE_READ 1
53 imx_read_otp_data(struct i2c_client
*client
, u16 len
, u16 reg
, void *val
)
55 struct i2c_msg msg
[2];
56 u16 data
[IMX_SHORT_MAX
] = { 0 };
59 if (len
> IMX_BYTE_MAX
) {
60 dev_err(&client
->dev
, "%s error, invalid data length\n",
65 memset(msg
, 0 , sizeof(msg
));
66 memset(data
, 0 , sizeof(data
));
68 msg
[0].addr
= client
->addr
;
70 msg
[0].len
= I2C_MSG_LENGTH
;
71 msg
[0].buf
= (u8
*)data
;
72 /* high byte goes first */
73 data
[0] = cpu_to_be16(reg
);
75 msg
[1].addr
= client
->addr
;
77 msg
[1].flags
= I2C_M_RD
;
78 msg
[1].buf
= (u8
*)data
;
80 err
= i2c_transfer(client
->adapter
, msg
, 2);
87 memcpy(val
, data
, len
);
91 dev_err(&client
->dev
, "read from offset 0x%x error %d", reg
, err
);
95 static int imx_read_otp_reg_array(struct i2c_client
*client
, u16 size
, u16 addr
,
101 for (index
= 0; index
+ IMX_OTP_READ_ONETIME
<= size
;
102 index
+= IMX_OTP_READ_ONETIME
) {
103 ret
= imx_read_otp_data(client
, IMX_OTP_READ_ONETIME
,
104 addr
+ index
, &buf
[index
]);
111 void *imx_otp_read(struct v4l2_subdev
*sd
, u8 dev_addr
,
112 u32 start_addr
, u32 size
)
114 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
119 buf
= devm_kzalloc(&client
->dev
, size
, GFP_KERNEL
);
121 return ERR_PTR(-ENOMEM
);
123 for (i
= 0; i
< IMX_OTP_PAGE_MAX
; i
++) {
126 ret
= imx_write_reg(client
, IMX_8BIT
,
127 IMX_OTP_PAGE_REG
, i
& 0xff);
132 ret
= imx_write_reg(client
, IMX_8BIT
,
133 IMX_OTP_MODE_REG
, IMX_OTP_MODE_READ
);
137 /* Reading the OTP data array */
138 ret
= imx_read_otp_reg_array(client
, IMX_OTP_PAGE_SIZE
,
139 IMX_OTP_START_ADDR
, buf
+ i
* IMX_OTP_PAGE_SIZE
);
146 /* Driver has failed to find valid data */
147 dev_err(&client
->dev
, "sensor found no valid OTP data\n");
151 void *imx227_otp_read(struct v4l2_subdev
*sd
, u8 dev_addr
,
152 u32 start_addr
, u32 size
)
154 struct i2c_client
*client
= v4l2_get_subdevdata(sd
);
159 buf
= devm_kzalloc(&client
->dev
, size
, GFP_KERNEL
);
161 return ERR_PTR(-ENOMEM
);
163 for (i
= 0; i
< IMX_OTP_PAGE_MAX
; i
++) {
166 ret
= imx_write_reg(client
, IMX_8BIT
,
167 IMX227_OTP_PAGE_REG
, i
& 0xff);
172 ret
= imx_write_reg(client
, IMX_8BIT
,
173 IMX227_OTP_ENABLE_REG
, IMX227_OTP_MODE_READ
);
177 /* Reading the OTP data array */
178 ret
= imx_read_otp_reg_array(client
, IMX_OTP_PAGE_SIZE
,
179 IMX227_OTP_START_ADDR
, buf
+ i
* IMX_OTP_PAGE_SIZE
);
186 /* Driver has failed to find valid data */
187 dev_err(&client
->dev
, "sensor found no valid OTP data\n");