]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/media/atomisp/i2c/imx/otp_imx.c
media: staging: atomisp: Remove unneeded intel-mid.h inclusion
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / media / atomisp / i2c / imx / otp_imx.c
CommitLineData
a49d2536
AC
1/*
2 * Copyright (c) 2013 Intel Corporation. All Rights Reserved.
3 *
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.
7 *
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.
12 *
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
16 * 02110-1301, USA.
17 *
18 */
19#include <linux/bitops.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/errno.h>
23#include <linux/fs.h>
24#include <linux/init.h>
25#include <linux/i2c.h>
26#include <linux/io.h>
27#include <linux/kernel.h>
28#include <linux/mm.h>
29#include <linux/string.h>
30#include <linux/slab.h>
31#include <linux/types.h>
32#include <media/v4l2-device.h>
a49d2536
AC
33#include "common.h"
34
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
51
52static int
53imx_read_otp_data(struct i2c_client *client, u16 len, u16 reg, void *val)
54{
55 struct i2c_msg msg[2];
56 u16 data[IMX_SHORT_MAX] = { 0 };
57 int err;
58
59 if (len > IMX_BYTE_MAX) {
60 dev_err(&client->dev, "%s error, invalid data length\n",
61 __func__);
62 return -EINVAL;
63 }
64
65 memset(msg, 0 , sizeof(msg));
66 memset(data, 0 , sizeof(data));
67
68 msg[0].addr = client->addr;
69 msg[0].flags = 0;
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);
74
75 msg[1].addr = client->addr;
76 msg[1].len = len;
77 msg[1].flags = I2C_M_RD;
78 msg[1].buf = (u8 *)data;
79
80 err = i2c_transfer(client->adapter, msg, 2);
81 if (err != 2) {
82 if (err >= 0)
83 err = -EIO;
84 goto error;
85 }
86
87 memcpy(val, data, len);
88 return 0;
89
90error:
91 dev_err(&client->dev, "read from offset 0x%x error %d", reg, err);
92 return err;
93}
94
95static int imx_read_otp_reg_array(struct i2c_client *client, u16 size, u16 addr,
96 u8 *buf)
97{
98 u16 index;
99 int ret;
100
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]);
105 if (ret)
106 return ret;
107 }
108 return 0;
109}
110
111void *imx_otp_read(struct v4l2_subdev *sd, u8 dev_addr,
112 u32 start_addr, u32 size)
113{
114 struct i2c_client *client = v4l2_get_subdevdata(sd);
115 u8 *buf;
116 int ret;
117 int i;
118
119 buf = devm_kzalloc(&client->dev, size, GFP_KERNEL);
120 if (!buf)
121 return ERR_PTR(-ENOMEM);
122
123 for (i = 0; i < IMX_OTP_PAGE_MAX; i++) {
124
125 /*set page NO.*/
126 ret = imx_write_reg(client, IMX_8BIT,
127 IMX_OTP_PAGE_REG, i & 0xff);
128 if (ret)
129 goto fail;
130
131 /*set read mode*/
132 ret = imx_write_reg(client, IMX_8BIT,
133 IMX_OTP_MODE_REG, IMX_OTP_MODE_READ);
134 if (ret)
135 goto fail;
136
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);
140 if (ret)
141 goto fail;
142 }
143
144 return buf;
145fail:
146 /* Driver has failed to find valid data */
147 dev_err(&client->dev, "sensor found no valid OTP data\n");
148 return ERR_PTR(ret);
149}
150
151void *imx227_otp_read(struct v4l2_subdev *sd, u8 dev_addr,
152 u32 start_addr, u32 size)
153{
154 struct i2c_client *client = v4l2_get_subdevdata(sd);
155 u8 *buf;
156 int ret;
157 int i;
158
159 buf = devm_kzalloc(&client->dev, size, GFP_KERNEL);
160 if (!buf)
161 return ERR_PTR(-ENOMEM);
162
163 for (i = 0; i < IMX_OTP_PAGE_MAX; i++) {
164
165 /*set page NO.*/
166 ret = imx_write_reg(client, IMX_8BIT,
167 IMX227_OTP_PAGE_REG, i & 0xff);
168 if (ret)
169 goto fail;
170
171 /*set read mode*/
172 ret = imx_write_reg(client, IMX_8BIT,
173 IMX227_OTP_ENABLE_REG, IMX227_OTP_MODE_READ);
174 if (ret)
175 goto fail;
176
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);
180 if (ret)
181 goto fail;
182 }
183
184 return buf;
185fail:
186 /* Driver has failed to find valid data */
187 dev_err(&client->dev, "sensor found no valid OTP data\n");
188 return ERR_PTR(ret);
189}
190