Skip to content

Commit bf38b87

Browse files
cricard13PeterHuewe
authored andcommitted
tpm/tpm_i2c_stm_st33: Split tpm_i2c_tpm_st33 in 2 layers (core + phy)
tpm_i2c_stm_st33 is a TIS 1.2 TPM with a core interface which can be used by different phy such as i2c or spi. The core part is called st33zp24 which is also the main part reference. include/linux/platform_data/tpm_stm_st33.h is renamed consequently. The driver is also split into an i2c phy in charge of sending/receiving data as well as managing platform data or dts configuration. Acked-by: Jarkko Sakkinen <jarkko.sakknen@linux.intel.com> Reviewed-by: Jason Gunthorpe <jason.gunthorpe@obsidianresearch.com> Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
1 parent fe7d368 commit bf38b87

File tree

9 files changed

+1036
-942
lines changed

9 files changed

+1036
-942
lines changed

drivers/char/tpm/Kconfig

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,6 @@ config TCG_IBMVTPM
100100
will be accessible from within Linux. To compile this driver
101101
as a module, choose M here; the module will be called tpm_ibmvtpm.
102102

103-
config TCG_TIS_I2C_ST33
104-
tristate "TPM Interface Specification 1.2 Interface (I2C - STMicroelectronics)"
105-
depends on I2C
106-
depends on GPIOLIB
107-
---help---
108-
If you have a TPM security chip from STMicroelectronics working with
109-
an I2C bus say Yes and it will be accessible from within Linux.
110-
To compile this driver as a module, choose M here; the module will be
111-
called tpm_i2c_stm_st33.
112-
113103
config TCG_XEN
114104
tristate "XEN TPM Interface"
115105
depends on TCG_TPM && XEN
@@ -131,4 +121,5 @@ config TCG_CRB
131121
from within Linux. To compile this driver as a module, choose
132122
M here; the module will be called tpm_crb.
133123

124+
source "drivers/char/tpm/st33zp24/Kconfig"
134125
endif # TCG_TPM

drivers/char/tpm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
2020
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
2121
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
2222
obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
23-
obj-$(CONFIG_TCG_TIS_I2C_ST33) += tpm_i2c_stm_st33.o
23+
obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
2424
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
2525
obj-$(CONFIG_TCG_CRB) += tpm_crb.o

drivers/char/tpm/st33zp24/Kconfig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
config TCG_TIS_ST33ZP24
2+
tristate "STMicroelectronics TPM Interface Specification 1.2 Interface"
3+
depends on GPIOLIB
4+
---help---
5+
STMicroelectronics ST33ZP24 core driver. It implements the core
6+
TPM1.2 logic and hooks into the TPM kernel APIs. Physical layers will
7+
register against it.
8+
9+
To compile this driver as a module, choose m here. The module will be called
10+
tpm_st33zp24.
11+
12+
config TCG_TIS_ST33ZP24_I2C
13+
tristate "TPM 1.2 ST33ZP24 I2C support"
14+
depends on TCG_TIS_ST33ZP24
15+
depends on I2C
16+
---help---
17+
This module adds support for the STMicroelectronics TPM security chip
18+
ST33ZP24 with i2c interface.
19+
To compile this driver as a module, choose M here; the module will be
20+
called tpm_st33zp24_i2c.

drivers/char/tpm/st33zp24/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# Makefile for ST33ZP24 TPM 1.2 driver
3+
#
4+
5+
tpm_st33zp24-objs = st33zp24.o
6+
obj-$(CONFIG_TCG_TIS_ST33ZP24) += tpm_st33zp24.o
7+
8+
tpm_st33zp24_i2c-objs = i2c.o
9+
obj-$(CONFIG_TCG_TIS_ST33ZP24_I2C) += tpm_st33zp24_i2c.o

drivers/char/tpm/st33zp24/i2c.c

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
3+
* Copyright (C) 2009 - 2015 STMicroelectronics
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
30+
#define TPM_WRITE_DIRECTION 0x80
31+
#define TPM_BUFSIZE 2048
32+
33+
struct st33zp24_i2c_phy {
34+
struct i2c_client *client;
35+
u8 buf[TPM_BUFSIZE + 1];
36+
int io_lpcpd;
37+
};
38+
39+
/*
40+
* write8_reg
41+
* Send byte to the TIS register according to the ST33ZP24 I2C protocol.
42+
* @param: tpm_register, the tpm tis register where the data should be written
43+
* @param: tpm_data, the tpm_data to write inside the tpm_register
44+
* @param: tpm_size, The length of the data
45+
* @return: Returns negative errno, or else the number of bytes written.
46+
*/
47+
static int write8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
48+
{
49+
struct st33zp24_i2c_phy *phy = phy_id;
50+
51+
phy->buf[0] = tpm_register;
52+
memcpy(phy->buf + 1, tpm_data, tpm_size);
53+
return i2c_master_send(phy->client, phy->buf, tpm_size + 1);
54+
} /* write8_reg() */
55+
56+
/*
57+
* read8_reg
58+
* Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
59+
* @param: tpm_register, the tpm tis register where the data should be read
60+
* @param: tpm_data, the TPM response
61+
* @param: tpm_size, tpm TPM response size to read.
62+
* @return: number of byte read successfully: should be one if success.
63+
*/
64+
static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
65+
{
66+
struct st33zp24_i2c_phy *phy = phy_id;
67+
u8 status = 0;
68+
u8 data;
69+
70+
data = TPM_DUMMY_BYTE;
71+
status = write8_reg(phy, tpm_register, &data, 1);
72+
if (status == 2)
73+
status = i2c_master_recv(phy->client, tpm_data, tpm_size);
74+
return status;
75+
} /* read8_reg() */
76+
77+
/*
78+
* st33zp24_i2c_send
79+
* Send byte to the TIS register according to the ST33ZP24 I2C protocol.
80+
* @param: phy_id, the phy description
81+
* @param: tpm_register, the tpm tis register where the data should be written
82+
* @param: tpm_data, the tpm_data to write inside the tpm_register
83+
* @param: tpm_size, the length of the data
84+
* @return: number of byte written successfully: should be one if success.
85+
*/
86+
static int st33zp24_i2c_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
87+
int tpm_size)
88+
{
89+
return write8_reg(phy_id, tpm_register | TPM_WRITE_DIRECTION, tpm_data,
90+
tpm_size);
91+
}
92+
93+
/*
94+
* st33zp24_i2c_recv
95+
* Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
96+
* @param: phy_id, the phy description
97+
* @param: tpm_register, the tpm tis register where the data should be read
98+
* @param: tpm_data, the TPM response
99+
* @param: tpm_size, tpm TPM response size to read.
100+
* @return: number of byte read successfully: should be one if success.
101+
*/
102+
static int st33zp24_i2c_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
103+
int tpm_size)
104+
{
105+
return read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
106+
}
107+
108+
static const struct st33zp24_phy_ops i2c_phy_ops = {
109+
.send = st33zp24_i2c_send,
110+
.recv = st33zp24_i2c_recv,
111+
};
112+
113+
#ifdef CONFIG_OF
114+
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
115+
{
116+
struct device_node *pp;
117+
struct i2c_client *client = phy->client;
118+
int gpio;
119+
int ret;
120+
121+
pp = client->dev.of_node;
122+
if (!pp) {
123+
dev_err(&client->dev, "No platform data\n");
124+
return -ENODEV;
125+
}
126+
127+
/* Get GPIO from device tree */
128+
gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
129+
if (gpio < 0) {
130+
dev_err(&client->dev,
131+
"Failed to retrieve lpcpd-gpios from dts.\n");
132+
phy->io_lpcpd = -1;
133+
/*
134+
* lpcpd pin is not specified. This is not an issue as
135+
* power management can be also managed by TPM specific
136+
* commands. So leave with a success status code.
137+
*/
138+
return 0;
139+
}
140+
/* GPIO request and configuration */
141+
ret = devm_gpio_request_one(&client->dev, gpio,
142+
GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
143+
if (ret) {
144+
dev_err(&client->dev, "Failed to request lpcpd pin\n");
145+
return -ENODEV;
146+
}
147+
phy->io_lpcpd = gpio;
148+
149+
return 0;
150+
}
151+
#else
152+
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
153+
{
154+
return -ENODEV;
155+
}
156+
#endif
157+
158+
static int st33zp24_i2c_request_resources(struct i2c_client *client,
159+
struct st33zp24_i2c_phy *phy)
160+
{
161+
struct st33zp24_platform_data *pdata;
162+
int ret;
163+
164+
pdata = client->dev.platform_data;
165+
if (!pdata) {
166+
dev_err(&client->dev, "No platform data\n");
167+
return -ENODEV;
168+
}
169+
170+
/* store for late use */
171+
phy->io_lpcpd = pdata->io_lpcpd;
172+
173+
if (gpio_is_valid(pdata->io_lpcpd)) {
174+
ret = devm_gpio_request_one(&client->dev,
175+
pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
176+
"TPM IO_LPCPD");
177+
if (ret) {
178+
dev_err(&client->dev, "Failed to request lpcpd pin\n");
179+
return ret;
180+
}
181+
}
182+
183+
return 0;
184+
}
185+
186+
/*
187+
* st33zp24_i2c_probe initialize the TPM device
188+
* @param: client, the i2c_client drescription (TPM I2C description).
189+
* @param: id, the i2c_device_id struct.
190+
* @return: 0 in case of success.
191+
* -1 in other case.
192+
*/
193+
static int st33zp24_i2c_probe(struct i2c_client *client,
194+
const struct i2c_device_id *id)
195+
{
196+
int ret;
197+
struct st33zp24_platform_data *pdata;
198+
struct st33zp24_i2c_phy *phy;
199+
200+
if (!client) {
201+
pr_info("%s: i2c client is NULL. Device not accessible.\n",
202+
__func__);
203+
return -ENODEV;
204+
}
205+
206+
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
207+
dev_info(&client->dev, "client not i2c capable\n");
208+
return -ENODEV;
209+
}
210+
211+
phy = devm_kzalloc(&client->dev, sizeof(struct st33zp24_i2c_phy),
212+
GFP_KERNEL);
213+
if (!phy)
214+
return -ENOMEM;
215+
216+
phy->client = client;
217+
pdata = client->dev.platform_data;
218+
if (!pdata && client->dev.of_node) {
219+
ret = st33zp24_i2c_of_request_resources(phy);
220+
if (ret)
221+
return ret;
222+
} else if (pdata) {
223+
ret = st33zp24_i2c_request_resources(client, phy);
224+
if (ret)
225+
return ret;
226+
}
227+
228+
return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq,
229+
phy->io_lpcpd);
230+
}
231+
232+
/*
233+
* st33zp24_i2c_remove remove the TPM device
234+
* @param: client, the i2c_client description (TPM I2C description).
235+
* @return: 0 in case of success.
236+
*/
237+
static int st33zp24_i2c_remove(struct i2c_client *client)
238+
{
239+
struct tpm_chip *chip = i2c_get_clientdata(client);
240+
241+
return st33zp24_remove(chip);
242+
}
243+
244+
static const struct i2c_device_id st33zp24_i2c_id[] = {
245+
{TPM_ST33_I2C, 0},
246+
{}
247+
};
248+
MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
249+
250+
#ifdef CONFIG_OF
251+
static const struct of_device_id of_st33zp24_i2c_match[] = {
252+
{ .compatible = "st,st33zp24-i2c", },
253+
{}
254+
};
255+
MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
256+
#endif
257+
258+
static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
259+
st33zp24_pm_resume);
260+
261+
static struct i2c_driver st33zp24_i2c_driver = {
262+
.driver = {
263+
.owner = THIS_MODULE,
264+
.name = TPM_ST33_I2C,
265+
.pm = &st33zp24_i2c_ops,
266+
.of_match_table = of_match_ptr(of_st33zp24_i2c_match),
267+
},
268+
.probe = st33zp24_i2c_probe,
269+
.remove = st33zp24_i2c_remove,
270+
.id_table = st33zp24_i2c_id
271+
};
272+
273+
module_i2c_driver(st33zp24_i2c_driver);
274+
275+
MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
276+
MODULE_DESCRIPTION("STM TPM 1.2 I2C ST33 Driver");
277+
MODULE_VERSION("1.3.0");
278+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)