tpm/st33zp24: Extend Copyright headers
[deliverable/linux.git] / drivers / char / tpm / st33zp24 / i2c.c
CommitLineData
bf38b871
CR
1/*
2 * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
8bb273f2 3 * Copyright (C) 2009 - 2016 STMicroelectronics
bf38b871
CR
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/module.h>
20#include <linux/i2c.h>
21#include <linux/gpio.h>
22#include <linux/of_irq.h>
23#include <linux/of_gpio.h>
24#include <linux/tpm.h>
25#include <linux/platform_data/st33zp24.h>
26
27#include "st33zp24.h"
28
29#define TPM_DUMMY_BYTE 0xAA
bf38b871
CR
30
31struct st33zp24_i2c_phy {
32 struct i2c_client *client;
33 u8 buf[TPM_BUFSIZE + 1];
34 int io_lpcpd;
35};
36
37/*
38 * write8_reg
39 * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
40 * @param: tpm_register, the tpm tis register where the data should be written
41 * @param: tpm_data, the tpm_data to write inside the tpm_register
42 * @param: tpm_size, The length of the data
43 * @return: Returns negative errno, or else the number of bytes written.
44 */
45static int write8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
46{
47 struct st33zp24_i2c_phy *phy = phy_id;
48
49 phy->buf[0] = tpm_register;
50 memcpy(phy->buf + 1, tpm_data, tpm_size);
51 return i2c_master_send(phy->client, phy->buf, tpm_size + 1);
52} /* write8_reg() */
53
54/*
55 * read8_reg
56 * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
57 * @param: tpm_register, the tpm tis register where the data should be read
58 * @param: tpm_data, the TPM response
59 * @param: tpm_size, tpm TPM response size to read.
60 * @return: number of byte read successfully: should be one if success.
61 */
62static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
63{
64 struct st33zp24_i2c_phy *phy = phy_id;
65 u8 status = 0;
66 u8 data;
67
68 data = TPM_DUMMY_BYTE;
69 status = write8_reg(phy, tpm_register, &data, 1);
70 if (status == 2)
71 status = i2c_master_recv(phy->client, tpm_data, tpm_size);
72 return status;
73} /* read8_reg() */
74
75/*
76 * st33zp24_i2c_send
77 * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
78 * @param: phy_id, the phy description
79 * @param: tpm_register, the tpm tis register where the data should be written
80 * @param: tpm_data, the tpm_data to write inside the tpm_register
81 * @param: tpm_size, the length of the data
82 * @return: number of byte written successfully: should be one if success.
83 */
84static int st33zp24_i2c_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
85 int tpm_size)
86{
87 return write8_reg(phy_id, tpm_register | TPM_WRITE_DIRECTION, tpm_data,
88 tpm_size);
89}
90
91/*
92 * st33zp24_i2c_recv
93 * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
94 * @param: phy_id, the phy description
95 * @param: tpm_register, the tpm tis register where the data should be read
96 * @param: tpm_data, the TPM response
97 * @param: tpm_size, tpm TPM response size to read.
98 * @return: number of byte read successfully: should be one if success.
99 */
100static int st33zp24_i2c_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
101 int tpm_size)
102{
103 return read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
104}
105
106static const struct st33zp24_phy_ops i2c_phy_ops = {
107 .send = st33zp24_i2c_send,
108 .recv = st33zp24_i2c_recv,
109};
110
300796cd 111static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
fec60f29 112{
bf38b871 113 struct device_node *pp;
300796cd 114 struct i2c_client *client = phy->client;
bf38b871
CR
115 int gpio;
116 int ret;
117
118 pp = client->dev.of_node;
119 if (!pp) {
120 dev_err(&client->dev, "No platform data\n");
121 return -ENODEV;
122 }
123
124 /* Get GPIO from device tree */
125 gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
126 if (gpio < 0) {
127 dev_err(&client->dev,
128 "Failed to retrieve lpcpd-gpios from dts.\n");
129 phy->io_lpcpd = -1;
130 /*
131 * lpcpd pin is not specified. This is not an issue as
132 * power management can be also managed by TPM specific
133 * commands. So leave with a success status code.
134 */
135 return 0;
136 }
137 /* GPIO request and configuration */
138 ret = devm_gpio_request_one(&client->dev, gpio,
139 GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
140 if (ret) {
141 dev_err(&client->dev, "Failed to request lpcpd pin\n");
142 return -ENODEV;
143 }
144 phy->io_lpcpd = gpio;
145
146 return 0;
147}
bf38b871 148
300796cd
CR
149static int st33zp24_i2c_request_resources(struct i2c_client *client,
150 struct st33zp24_i2c_phy *phy)
bf38b871
CR
151{
152 struct st33zp24_platform_data *pdata;
153 int ret;
154
155 pdata = client->dev.platform_data;
156 if (!pdata) {
157 dev_err(&client->dev, "No platform data\n");
158 return -ENODEV;
159 }
160
161 /* store for late use */
162 phy->io_lpcpd = pdata->io_lpcpd;
163
164 if (gpio_is_valid(pdata->io_lpcpd)) {
165 ret = devm_gpio_request_one(&client->dev,
166 pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
167 "TPM IO_LPCPD");
168 if (ret) {
169 dev_err(&client->dev, "Failed to request lpcpd pin\n");
170 return ret;
171 }
172 }
173
174 return 0;
175}
176
177/*
178 * st33zp24_i2c_probe initialize the TPM device
179 * @param: client, the i2c_client drescription (TPM I2C description).
180 * @param: id, the i2c_device_id struct.
181 * @return: 0 in case of success.
182 * -1 in other case.
183 */
184static int st33zp24_i2c_probe(struct i2c_client *client,
185 const struct i2c_device_id *id)
186{
187 int ret;
188 struct st33zp24_platform_data *pdata;
189 struct st33zp24_i2c_phy *phy;
190
191 if (!client) {
192 pr_info("%s: i2c client is NULL. Device not accessible.\n",
193 __func__);
194 return -ENODEV;
195 }
196
197 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
198 dev_info(&client->dev, "client not i2c capable\n");
199 return -ENODEV;
200 }
201
202 phy = devm_kzalloc(&client->dev, sizeof(struct st33zp24_i2c_phy),
203 GFP_KERNEL);
204 if (!phy)
205 return -ENOMEM;
206
207 phy->client = client;
208 pdata = client->dev.platform_data;
209 if (!pdata && client->dev.of_node) {
300796cd 210 ret = st33zp24_i2c_of_request_resources(phy);
bf38b871
CR
211 if (ret)
212 return ret;
213 } else if (pdata) {
300796cd 214 ret = st33zp24_i2c_request_resources(client, phy);
fec60f29
CR
215 if (ret)
216 return ret;
bf38b871
CR
217 }
218
219 return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq,
220 phy->io_lpcpd);
221}
222
223/*
224 * st33zp24_i2c_remove remove the TPM device
225 * @param: client, the i2c_client description (TPM I2C description).
226 * @return: 0 in case of success.
227 */
228static int st33zp24_i2c_remove(struct i2c_client *client)
229{
230 struct tpm_chip *chip = i2c_get_clientdata(client);
231
232 return st33zp24_remove(chip);
233}
234
235static const struct i2c_device_id st33zp24_i2c_id[] = {
236 {TPM_ST33_I2C, 0},
237 {}
238};
239MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
240
bf38b871
CR
241static const struct of_device_id of_st33zp24_i2c_match[] = {
242 { .compatible = "st,st33zp24-i2c", },
243 {}
244};
245MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
bf38b871
CR
246
247static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
248 st33zp24_pm_resume);
249
250static struct i2c_driver st33zp24_i2c_driver = {
251 .driver = {
bf38b871
CR
252 .name = TPM_ST33_I2C,
253 .pm = &st33zp24_i2c_ops,
254 .of_match_table = of_match_ptr(of_st33zp24_i2c_match),
255 },
256 .probe = st33zp24_i2c_probe,
257 .remove = st33zp24_i2c_remove,
258 .id_table = st33zp24_i2c_id
259};
260
261module_i2c_driver(st33zp24_i2c_driver);
262
263MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
264MODULE_DESCRIPTION("STM TPM 1.2 I2C ST33 Driver");
265MODULE_VERSION("1.3.0");
266MODULE_LICENSE("GPL");
This page took 0.141368 seconds and 5 git commands to generate.