Blame view

drivers/char/tpm/tpm_atmel.c 5.43 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   * Copyright (C) 2004 IBM Corporation
   *
   * Authors:
   * Leendert van Doorn <leendert@watson.ibm.com>
   * Dave Safford <safford@watson.ibm.com>
   * Reiner Sailer <sailer@watson.ibm.com>
   * Kylene Hall <kjhall@us.ibm.com>
   *
8e81cc13a   Kent Yoder   tpmdd maintainers
10
   * Maintained by: <tpmdd-devel@lists.sourceforge.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
18
19
20
21
22
   *
   * Device driver for TCG/TCPA TPM (trusted platform module).
   * Specifications at www.trustedcomputinggroup.org	 
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation, version 2 of the
   * License.
   * 
   */
  
  #include "tpm.h"
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
23
  #include "tpm_atmel.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  
  /* write status bits */
3122a88a2   Kylene Hall   [PATCH] tpm: Fix ...
26
27
28
29
  enum tpm_atmel_write_status {
  	ATML_STATUS_ABORT = 0x01,
  	ATML_STATUS_LASTBYTE = 0x04
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  /* read status bits */
3122a88a2   Kylene Hall   [PATCH] tpm: Fix ...
31
32
33
34
35
36
  enum tpm_atmel_read_status {
  	ATML_STATUS_BUSY = 0x01,
  	ATML_STATUS_DATA_AVAIL = 0x02,
  	ATML_STATUS_REWRITE = 0x04,
  	ATML_STATUS_READY = 0x08
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

b888c87b7   Andrew Morton   [PATCH] tpm-tidies
38
  static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  {
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
40
  	struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
  	u8 status, *hdr = buf;
  	u32 size;
  	int i;
  	__be32 *native_size;
  
  	/* start reading header */
  	if (count < 6)
  		return -EIO;
  
  	for (i = 0; i < 6; i++) {
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
51
  		status = ioread8(priv->iobase + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
53
54
  			dev_err(&chip->dev, "error reading header
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
  			return -EIO;
  		}
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
57
  		*buf++ = ioread8(priv->iobase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
  	}
  
  	/* size of the data received */
  	native_size = (__force __be32 *) (hdr + 2);
  	size = be32_to_cpu(*native_size);
  
  	if (count < size) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
65
  		dev_err(&chip->dev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  			"Recv size(%d) less than available space
  ", size);
  		for (; i < size; i++) {	/* clear the waiting data anyway */
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
69
  			status = ioread8(priv->iobase + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
71
72
  				dev_err(&chip->dev, "error reading data
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
78
79
80
  				return -EIO;
  			}
  		}
  		return -EIO;
  	}
  
  	/* read all the data available */
  	for (; i < size; i++) {
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
81
  		status = ioread8(priv->iobase + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
83
84
  			dev_err(&chip->dev, "error reading data
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  			return -EIO;
  		}
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
87
  		*buf++ = ioread8(priv->iobase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  	}
  
  	/* make sure data available is gone */
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
91
  	status = ioread8(priv->iobase + 1);
90612b308   Kylene Jo Hall   [PATCH] tpm: use ...
92

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  	if (status & ATML_STATUS_DATA_AVAIL) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
94
95
  		dev_err(&chip->dev, "data available is stuck
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
  		return -EIO;
  	}
  
  	return size;
  }
b888c87b7   Andrew Morton   [PATCH] tpm-tidies
101
  static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  {
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
103
  	struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  	int i;
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
105
106
  	dev_dbg(&chip->dev, "tpm_atml_send:
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  	for (i = 0; i < count; i++) {
8cfffc9d4   Jason Gunthorpe   tpm: Get rid of c...
108
109
  		dev_dbg(&chip->dev, "%d 0x%x(%d)
  ",  i, buf[i], buf[i]);
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
110
  		iowrite8(buf[i], priv->iobase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
114
115
116
117
  	}
  
  	return count;
  }
  
  static void tpm_atml_cancel(struct tpm_chip *chip)
  {
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
118
  	struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
119
120
  
  	iowrite8(ATML_STATUS_ABORT, priv->iobase + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  }
b4ed3e3cb   Kylene Jo Hall   [PATCH] tpm: add ...
122
123
  static u8 tpm_atml_status(struct tpm_chip *chip)
  {
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
124
  	struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
125
126
  
  	return ioread8(priv->iobase + 1);
b4ed3e3cb   Kylene Jo Hall   [PATCH] tpm: add ...
127
  }
1f8660572   Stefan Berger   tpm: Fix cancella...
128
129
130
131
  static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status)
  {
  	return (status == ATML_STATUS_READY);
  }
01ad1fa75   Jason Gunthorpe   tpm: Create a tpm...
132
  static const struct tpm_class_ops tpm_atmel = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  	.recv = tpm_atml_recv,
  	.send = tpm_atml_send,
  	.cancel = tpm_atml_cancel,
b4ed3e3cb   Kylene Jo Hall   [PATCH] tpm: add ...
136
  	.status = tpm_atml_status,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
  	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
  	.req_complete_val = ATML_STATUS_DATA_AVAIL,
1f8660572   Stefan Berger   tpm: Fix cancella...
139
  	.req_canceled = tpm_atml_req_canceled,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  };
b888c87b7   Andrew Morton   [PATCH] tpm-tidies
141
  static struct platform_device *pdev;
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
142

ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
143
  static void atml_plat_remove(void)
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
144
  {
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
145
  	struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
146
  	struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
147

b888c87b7   Andrew Morton   [PATCH] tpm-tidies
148
  	if (chip) {
afb5abc26   Jarkko Sakkinen   tpm: two-phase ch...
149
  		tpm_chip_unregister(chip);
23d06ff70   Jarkko Sakkinen   tpm: drop tpm_atm...
150
  		if (priv->have_region)
ee1779840   Jarkko Sakkinen   tpm: drop 'base' ...
151
  			atmel_release_region(priv->base, priv->region_size);
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
152
  		atmel_put_base_addr(priv->iobase);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
153
  		platform_device_unregister(pdev);
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
154
155
  	}
  }
8324be053   Rafael J. Wysocki   tpm_atmel: Use st...
156
  static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume);
7a192ec33   Ming Lei   platform driver: ...
157

7a192ec33   Ming Lei   platform driver: ...
158
159
160
  static struct platform_driver atml_drv = {
  	.driver = {
  		.name = "tpm_atmel",
8324be053   Rafael J. Wysocki   tpm_atmel: Use st...
161
  		.pm		= &tpm_atml_pm,
7a192ec33   Ming Lei   platform driver: ...
162
  	},
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
163
164
165
  };
  
  static int __init init_atmel(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  	int rc = 0;
e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
168
169
170
171
  	void __iomem *iobase = NULL;
  	int have_region, region_size;
  	unsigned long base;
  	struct  tpm_chip *chip;
23d06ff70   Jarkko Sakkinen   tpm: drop tpm_atm...
172
  	struct tpm_atmel_priv *priv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

7a192ec33   Ming Lei   platform driver: ...
174
  	rc = platform_driver_register(&atml_drv);
f33d9bd50   Jeff Garzik   [PATCH] tpm: fix ...
175
176
  	if (rc)
  		return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
178
  	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
179
180
  		rc = -ENODEV;
  		goto err_unreg_drv;
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
181
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182

e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
183
  	have_region =
90612b308   Kylene Jo Hall   [PATCH] tpm: use ...
184
  	    (atmel_request_region
1e6e0974b   Jason Gunthorpe   tpm atmel: Call r...
185
  	     (base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
186

f33d9bd50   Jeff Garzik   [PATCH] tpm: fix ...
187
188
  	pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0);
  	if (IS_ERR(pdev)) {
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
189
190
  		rc = PTR_ERR(pdev);
  		goto err_rel_reg;
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
191
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192

23d06ff70   Jarkko Sakkinen   tpm: drop tpm_atm...
193
194
195
196
197
  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  	if (!priv) {
  		rc = -ENOMEM;
  		goto err_unreg_dev;
  	}
4eea703ca   Christophe Ricard   tpm: drop 'iobase...
198
  	priv->iobase = iobase;
ee1779840   Jarkko Sakkinen   tpm: drop 'base' ...
199
  	priv->base = base;
23d06ff70   Jarkko Sakkinen   tpm: drop tpm_atm...
200
201
  	priv->have_region = have_region;
  	priv->region_size = region_size;
afb5abc26   Jarkko Sakkinen   tpm: two-phase ch...
202
203
204
  	chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel);
  	if (IS_ERR(chip)) {
  		rc = PTR_ERR(chip);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
205
  		goto err_unreg_dev;
e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
206
  	}
9e0d39d8a   Christophe Ricard   tpm: Remove usele...
207
  	dev_set_drvdata(&chip->dev, priv);
e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
208

afb5abc26   Jarkko Sakkinen   tpm: two-phase ch...
209
210
211
  	rc = tpm_chip_register(chip);
  	if (rc)
  		goto err_unreg_dev;
682e97ace   Kylene Jo Hall   [PATCH] tpm: move...
212
  	return 0;
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
213
214
215
216
  
  err_unreg_dev:
  	platform_device_unregister(pdev);
  err_rel_reg:
e0dd03caf   Kylene Jo Hall   [PATCH] tpm: retu...
217
218
219
220
  	atmel_put_base_addr(iobase);
  	if (have_region)
  		atmel_release_region(base,
  				     region_size);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
221
  err_unreg_drv:
7a192ec33   Ming Lei   platform driver: ...
222
  	platform_driver_unregister(&atml_drv);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
223
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
  }
  
  static void __exit cleanup_atmel(void)
  {
7a192ec33   Ming Lei   platform driver: ...
228
  	platform_driver_unregister(&atml_drv);
ad5ea3cc5   Kylene Jo Hall   [PATCH] tpm: upda...
229
  	atml_plat_remove();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
237
238
  }
  
  module_init(init_atmel);
  module_exit(cleanup_atmel);
  
  MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
  MODULE_DESCRIPTION("TPM Driver");
  MODULE_VERSION("2.0");
  MODULE_LICENSE("GPL");