diff options
author | Kylene Jo Hall <kjhall@us.ibm.com> | 2005-11-13 19:07:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-13 21:14:17 -0500 |
commit | ad5ea3cc5f745aef243ade0dafc8cf6f7f0bfea7 (patch) | |
tree | f4d2e4b39df27db5120bef6187d344d2edc05d37 /drivers/char/tpm/tpm_atmel.c | |
parent | c0131c143204ee0ba00592c016f20ce6fc67827d (diff) |
[PATCH] tpm: updates for new hardware
This is the patch to support TPMs on power ppc hardware. It has been
reworked as requested to remove the need for messing with the io page mask
by just using ioremap.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/tpm/tpm_atmel.c')
-rw-r--r-- | drivers/char/tpm/tpm_atmel.c | 108 |
1 files changed, 37 insertions, 71 deletions
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 32e01450c425..deb4b5c80914 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -19,14 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/platform_device.h> | ||
23 | #include "tpm.h" | 22 | #include "tpm.h" |
24 | 23 | #include "tpm_atmel.h" | |
25 | /* Atmel definitions */ | ||
26 | enum tpm_atmel_addr { | ||
27 | TPM_ATMEL_BASE_ADDR_LO = 0x08, | ||
28 | TPM_ATMEL_BASE_ADDR_HI = 0x09 | ||
29 | }; | ||
30 | 24 | ||
31 | /* write status bits */ | 25 | /* write status bits */ |
32 | enum tpm_atmel_write_status { | 26 | enum tpm_atmel_write_status { |
@@ -53,13 +47,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
53 | return -EIO; | 47 | return -EIO; |
54 | 48 | ||
55 | for (i = 0; i < 6; i++) { | 49 | for (i = 0; i < 6; i++) { |
56 | status = inb(chip->vendor->base + 1); | 50 | status = atmel_getb(chip, 1); |
57 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 51 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
58 | dev_err(chip->dev, | 52 | dev_err(chip->dev, |
59 | "error reading header\n"); | 53 | "error reading header\n"); |
60 | return -EIO; | 54 | return -EIO; |
61 | } | 55 | } |
62 | *buf++ = inb(chip->vendor->base); | 56 | *buf++ = atmel_getb(chip, 0); |
63 | } | 57 | } |
64 | 58 | ||
65 | /* size of the data received */ | 59 | /* size of the data received */ |
@@ -70,7 +64,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
70 | dev_err(chip->dev, | 64 | dev_err(chip->dev, |
71 | "Recv size(%d) less than available space\n", size); | 65 | "Recv size(%d) less than available space\n", size); |
72 | for (; i < size; i++) { /* clear the waiting data anyway */ | 66 | for (; i < size; i++) { /* clear the waiting data anyway */ |
73 | status = inb(chip->vendor->base + 1); | 67 | status = atmel_getb(chip, 1); |
74 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 68 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
75 | dev_err(chip->dev, | 69 | dev_err(chip->dev, |
76 | "error reading data\n"); | 70 | "error reading data\n"); |
@@ -82,17 +76,17 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
82 | 76 | ||
83 | /* read all the data available */ | 77 | /* read all the data available */ |
84 | for (; i < size; i++) { | 78 | for (; i < size; i++) { |
85 | status = inb(chip->vendor->base + 1); | 79 | status = atmel_getb(chip, 1); |
86 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 80 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
87 | dev_err(chip->dev, | 81 | dev_err(chip->dev, |
88 | "error reading data\n"); | 82 | "error reading data\n"); |
89 | return -EIO; | 83 | return -EIO; |
90 | } | 84 | } |
91 | *buf++ = inb(chip->vendor->base); | 85 | *buf++ = atmel_getb(chip, 0); |
92 | } | 86 | } |
93 | 87 | ||
94 | /* make sure data available is gone */ | 88 | /* make sure data available is gone */ |
95 | status = inb(chip->vendor->base + 1); | 89 | status = atmel_getb(chip, 1); |
96 | if (status & ATML_STATUS_DATA_AVAIL) { | 90 | if (status & ATML_STATUS_DATA_AVAIL) { |
97 | dev_err(chip->dev, "data available is stuck\n"); | 91 | dev_err(chip->dev, "data available is stuck\n"); |
98 | return -EIO; | 92 | return -EIO; |
@@ -108,7 +102,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 102 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
109 | for (i = 0; i < count; i++) { | 103 | for (i = 0; i < count; i++) { |
110 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 104 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
111 | outb(buf[i], chip->vendor->base); | 105 | atmel_putb(buf[i], chip, 0); |
112 | } | 106 | } |
113 | 107 | ||
114 | return count; | 108 | return count; |
@@ -116,12 +110,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
116 | 110 | ||
117 | static void tpm_atml_cancel(struct tpm_chip *chip) | 111 | static void tpm_atml_cancel(struct tpm_chip *chip) |
118 | { | 112 | { |
119 | outb(ATML_STATUS_ABORT, chip->vendor->base + 1); | 113 | atmel_putb(ATML_STATUS_ABORT, chip, 1); |
120 | } | 114 | } |
121 | 115 | ||
122 | static u8 tpm_atml_status(struct tpm_chip *chip) | 116 | static u8 tpm_atml_status(struct tpm_chip *chip) |
123 | { | 117 | { |
124 | return inb(chip->vendor->base + 1); | 118 | return atmel_getb(chip, 1); |
125 | } | 119 | } |
126 | 120 | ||
127 | static struct file_operations atmel_ops = { | 121 | static struct file_operations atmel_ops = { |
@@ -162,12 +156,16 @@ static struct tpm_vendor_specific tpm_atmel = { | |||
162 | 156 | ||
163 | static struct platform_device *pdev; | 157 | static struct platform_device *pdev; |
164 | 158 | ||
165 | static void __devexit tpm_atml_remove(struct device *dev) | 159 | static void atml_plat_remove(void) |
166 | { | 160 | { |
167 | struct tpm_chip *chip = dev_get_drvdata(dev); | 161 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
162 | |||
168 | if (chip) { | 163 | if (chip) { |
169 | release_region(chip->vendor->base, 2); | 164 | if (chip->vendor->have_region) |
165 | atmel_release_region(chip->vendor->base, chip->vendor->region_size); | ||
166 | atmel_put_base_addr(chip->vendor); | ||
170 | tpm_remove_hardware(chip->dev); | 167 | tpm_remove_hardware(chip->dev); |
168 | platform_device_unregister(pdev); | ||
171 | } | 169 | } |
172 | } | 170 | } |
173 | 171 | ||
@@ -182,72 +180,40 @@ static struct device_driver atml_drv = { | |||
182 | static int __init init_atmel(void) | 180 | static int __init init_atmel(void) |
183 | { | 181 | { |
184 | int rc = 0; | 182 | int rc = 0; |
185 | int lo, hi; | ||
186 | 183 | ||
187 | driver_register(&atml_drv); | 184 | driver_register(&atml_drv); |
188 | 185 | ||
189 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 186 | if (atmel_get_base_addr(&tpm_atmel) != 0) { |
190 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 187 | rc = -ENODEV; |
191 | 188 | goto err_unreg_drv; | |
192 | tpm_atmel.base = (hi<<8)|lo; | ||
193 | |||
194 | /* verify that it is an Atmel part */ | ||
195 | if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' | ||
196 | || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { | ||
197 | return -ENODEV; | ||
198 | } | ||
199 | |||
200 | /* verify chip version number is 1.1 */ | ||
201 | if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || | ||
202 | (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) | ||
203 | return -ENODEV; | ||
204 | |||
205 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | ||
206 | if ( !pdev ) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | pdev->name = "tpm_atmel0"; | ||
210 | pdev->id = -1; | ||
211 | pdev->num_resources = 0; | ||
212 | pdev->dev.release = tpm_atml_remove; | ||
213 | pdev->dev.driver = &atml_drv; | ||
214 | |||
215 | if ((rc = platform_device_register(pdev)) < 0) { | ||
216 | kfree(pdev); | ||
217 | pdev = NULL; | ||
218 | return rc; | ||
219 | } | 189 | } |
220 | 190 | ||
221 | if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { | 191 | tpm_atmel.have_region = (atmel_request_region( tpm_atmel.base, tpm_atmel.region_size, "tpm_atmel0") == NULL) ? 0 : 1; |
222 | platform_device_unregister(pdev); | ||
223 | kfree(pdev); | ||
224 | pdev = NULL; | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | 192 | ||
228 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { | 193 | if (IS_ERR(pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0 ))) { |
229 | release_region(tpm_atmel.base, 2); | 194 | rc = PTR_ERR(pdev); |
230 | platform_device_unregister(pdev); | 195 | goto err_rel_reg; |
231 | kfree(pdev); | ||
232 | pdev = NULL; | ||
233 | return rc; | ||
234 | } | 196 | } |
235 | 197 | ||
236 | dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", | 198 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) |
237 | tpm_atmel.base); | 199 | goto err_unreg_dev; |
238 | return 0; | 200 | return 0; |
201 | |||
202 | err_unreg_dev: | ||
203 | platform_device_unregister(pdev); | ||
204 | err_rel_reg: | ||
205 | if (tpm_atmel.have_region) | ||
206 | atmel_release_region(tpm_atmel.base, tpm_atmel.region_size); | ||
207 | atmel_put_base_addr(&tpm_atmel); | ||
208 | err_unreg_drv: | ||
209 | driver_unregister(&atml_drv); | ||
210 | return rc; | ||
239 | } | 211 | } |
240 | 212 | ||
241 | static void __exit cleanup_atmel(void) | 213 | static void __exit cleanup_atmel(void) |
242 | { | 214 | { |
243 | if (pdev) { | ||
244 | tpm_atml_remove(&pdev->dev); | ||
245 | platform_device_unregister(pdev); | ||
246 | kfree(pdev); | ||
247 | pdev = NULL; | ||
248 | } | ||
249 | |||
250 | driver_unregister(&atml_drv); | 215 | driver_unregister(&atml_drv); |
216 | atml_plat_remove(); | ||
251 | } | 217 | } |
252 | 218 | ||
253 | module_init(init_atmel); | 219 | module_init(init_atmel); |