diff options
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); |