diff options
Diffstat (limited to 'drivers/char/tpm/tpm_atmel.c')
-rw-r--r-- | drivers/char/tpm/tpm_atmel.c | 125 |
1 files changed, 48 insertions, 77 deletions
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 32e01450c425..ff3654964fe3 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,12 @@ 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 = ioread8(chip->vendor->iobase + 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, "error reading header\n"); |
59 | "error reading header\n"); | ||
60 | return -EIO; | 53 | return -EIO; |
61 | } | 54 | } |
62 | *buf++ = inb(chip->vendor->base); | 55 | *buf++ = ioread8(chip->vendor->iobase); |
63 | } | 56 | } |
64 | 57 | ||
65 | /* size of the data received */ | 58 | /* size of the data received */ |
@@ -70,10 +63,9 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
70 | dev_err(chip->dev, | 63 | dev_err(chip->dev, |
71 | "Recv size(%d) less than available space\n", size); | 64 | "Recv size(%d) less than available space\n", size); |
72 | for (; i < size; i++) { /* clear the waiting data anyway */ | 65 | for (; i < size; i++) { /* clear the waiting data anyway */ |
73 | status = inb(chip->vendor->base + 1); | 66 | status = ioread8(chip->vendor->iobase + 1); |
74 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 67 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
75 | dev_err(chip->dev, | 68 | dev_err(chip->dev, "error reading data\n"); |
76 | "error reading data\n"); | ||
77 | return -EIO; | 69 | return -EIO; |
78 | } | 70 | } |
79 | } | 71 | } |
@@ -82,17 +74,17 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
82 | 74 | ||
83 | /* read all the data available */ | 75 | /* read all the data available */ |
84 | for (; i < size; i++) { | 76 | for (; i < size; i++) { |
85 | status = inb(chip->vendor->base + 1); | 77 | status = ioread8(chip->vendor->iobase + 1); |
86 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { | 78 | if ((status & ATML_STATUS_DATA_AVAIL) == 0) { |
87 | dev_err(chip->dev, | 79 | dev_err(chip->dev, "error reading data\n"); |
88 | "error reading data\n"); | ||
89 | return -EIO; | 80 | return -EIO; |
90 | } | 81 | } |
91 | *buf++ = inb(chip->vendor->base); | 82 | *buf++ = ioread8(chip->vendor->iobase); |
92 | } | 83 | } |
93 | 84 | ||
94 | /* make sure data available is gone */ | 85 | /* make sure data available is gone */ |
95 | status = inb(chip->vendor->base + 1); | 86 | status = ioread8(chip->vendor->iobase + 1); |
87 | |||
96 | if (status & ATML_STATUS_DATA_AVAIL) { | 88 | if (status & ATML_STATUS_DATA_AVAIL) { |
97 | dev_err(chip->dev, "data available is stuck\n"); | 89 | dev_err(chip->dev, "data available is stuck\n"); |
98 | return -EIO; | 90 | return -EIO; |
@@ -108,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
108 | dev_dbg(chip->dev, "tpm_atml_send:\n"); | 100 | dev_dbg(chip->dev, "tpm_atml_send:\n"); |
109 | for (i = 0; i < count; i++) { | 101 | for (i = 0; i < count; i++) { |
110 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); | 102 | dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); |
111 | outb(buf[i], chip->vendor->base); | 103 | iowrite8(buf[i], chip->vendor->iobase); |
112 | } | 104 | } |
113 | 105 | ||
114 | return count; | 106 | return count; |
@@ -116,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
116 | 108 | ||
117 | static void tpm_atml_cancel(struct tpm_chip *chip) | 109 | static void tpm_atml_cancel(struct tpm_chip *chip) |
118 | { | 110 | { |
119 | outb(ATML_STATUS_ABORT, chip->vendor->base + 1); | 111 | iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); |
120 | } | 112 | } |
121 | 113 | ||
122 | static u8 tpm_atml_status(struct tpm_chip *chip) | 114 | static u8 tpm_atml_status(struct tpm_chip *chip) |
123 | { | 115 | { |
124 | return inb(chip->vendor->base + 1); | 116 | return ioread8(chip->vendor->iobase + 1); |
125 | } | 117 | } |
126 | 118 | ||
127 | static struct file_operations atmel_ops = { | 119 | static struct file_operations atmel_ops = { |
@@ -162,12 +154,17 @@ static struct tpm_vendor_specific tpm_atmel = { | |||
162 | 154 | ||
163 | static struct platform_device *pdev; | 155 | static struct platform_device *pdev; |
164 | 156 | ||
165 | static void __devexit tpm_atml_remove(struct device *dev) | 157 | static void atml_plat_remove(void) |
166 | { | 158 | { |
167 | struct tpm_chip *chip = dev_get_drvdata(dev); | 159 | struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); |
160 | |||
168 | if (chip) { | 161 | if (chip) { |
169 | release_region(chip->vendor->base, 2); | 162 | if (chip->vendor->have_region) |
163 | atmel_release_region(chip->vendor->base, | ||
164 | chip->vendor->region_size); | ||
165 | atmel_put_base_addr(chip->vendor); | ||
170 | tpm_remove_hardware(chip->dev); | 166 | tpm_remove_hardware(chip->dev); |
167 | platform_device_unregister(pdev); | ||
171 | } | 168 | } |
172 | } | 169 | } |
173 | 170 | ||
@@ -182,72 +179,46 @@ static struct device_driver atml_drv = { | |||
182 | static int __init init_atmel(void) | 179 | static int __init init_atmel(void) |
183 | { | 180 | { |
184 | int rc = 0; | 181 | int rc = 0; |
185 | int lo, hi; | ||
186 | 182 | ||
187 | driver_register(&atml_drv); | 183 | driver_register(&atml_drv); |
188 | 184 | ||
189 | lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); | 185 | if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { |
190 | hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); | 186 | rc = -ENODEV; |
191 | 187 | 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 | } | 188 | } |
199 | 189 | ||
200 | /* verify chip version number is 1.1 */ | 190 | tpm_atmel.have_region = |
201 | if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) || | 191 | (atmel_request_region |
202 | (tpm_read_index(TPM_ADDR, 0x01) != 0x01 )) | 192 | (tpm_atmel.base, tpm_atmel.region_size, |
203 | return -ENODEV; | 193 | "tpm_atmel0") == NULL) ? 0 : 1; |
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 | } | ||
220 | 194 | ||
221 | if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) { | 195 | if (IS_ERR |
222 | platform_device_unregister(pdev); | 196 | (pdev = |
223 | kfree(pdev); | 197 | platform_device_register_simple("tpm_atmel", -1, NULL, 0))) { |
224 | pdev = NULL; | 198 | rc = PTR_ERR(pdev); |
225 | return -EBUSY; | 199 | goto err_rel_reg; |
226 | } | 200 | } |
227 | 201 | ||
228 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) { | 202 | if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) |
229 | release_region(tpm_atmel.base, 2); | 203 | goto err_unreg_dev; |
230 | platform_device_unregister(pdev); | ||
231 | kfree(pdev); | ||
232 | pdev = NULL; | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n", | ||
237 | tpm_atmel.base); | ||
238 | return 0; | 204 | return 0; |
205 | |||
206 | err_unreg_dev: | ||
207 | platform_device_unregister(pdev); | ||
208 | err_rel_reg: | ||
209 | atmel_put_base_addr(&tpm_atmel); | ||
210 | if (tpm_atmel.have_region) | ||
211 | atmel_release_region(tpm_atmel.base, | ||
212 | tpm_atmel.region_size); | ||
213 | err_unreg_drv: | ||
214 | driver_unregister(&atml_drv); | ||
215 | return rc; | ||
239 | } | 216 | } |
240 | 217 | ||
241 | static void __exit cleanup_atmel(void) | 218 | static void __exit cleanup_atmel(void) |
242 | { | 219 | { |
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); | 220 | driver_unregister(&atml_drv); |
221 | atml_plat_remove(); | ||
251 | } | 222 | } |
252 | 223 | ||
253 | module_init(init_atmel); | 224 | module_init(init_atmel); |