aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm_atmel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/tpm/tpm_atmel.c')
-rw-r--r--drivers/char/tpm/tpm_atmel.c146
1 files changed, 80 insertions, 66 deletions
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index c0d64914595f..8cb42e84723c 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -40,7 +40,7 @@ enum tpm_atmel_read_status {
40 ATML_STATUS_READY = 0x08 40 ATML_STATUS_READY = 0x08
41}; 41};
42 42
43static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) 43static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
44{ 44{
45 u8 status, *hdr = buf; 45 u8 status, *hdr = buf;
46 u32 size; 46 u32 size;
@@ -54,7 +54,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
54 for (i = 0; i < 6; i++) { 54 for (i = 0; i < 6; i++) {
55 status = inb(chip->vendor->base + 1); 55 status = inb(chip->vendor->base + 1);
56 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 56 if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
57 dev_err(&chip->pci_dev->dev, 57 dev_err(chip->dev,
58 "error reading header\n"); 58 "error reading header\n");
59 return -EIO; 59 return -EIO;
60 } 60 }
@@ -66,12 +66,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
66 size = be32_to_cpu(*native_size); 66 size = be32_to_cpu(*native_size);
67 67
68 if (count < size) { 68 if (count < size) {
69 dev_err(&chip->pci_dev->dev, 69 dev_err(chip->dev,
70 "Recv size(%d) less than available space\n", size); 70 "Recv size(%d) less than available space\n", size);
71 for (; i < size; i++) { /* clear the waiting data anyway */ 71 for (; i < size; i++) { /* clear the waiting data anyway */
72 status = inb(chip->vendor->base + 1); 72 status = inb(chip->vendor->base + 1);
73 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 73 if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
74 dev_err(&chip->pci_dev->dev, 74 dev_err(chip->dev,
75 "error reading data\n"); 75 "error reading data\n");
76 return -EIO; 76 return -EIO;
77 } 77 }
@@ -83,7 +83,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
83 for (; i < size; i++) { 83 for (; i < size; i++) {
84 status = inb(chip->vendor->base + 1); 84 status = inb(chip->vendor->base + 1);
85 if ((status & ATML_STATUS_DATA_AVAIL) == 0) { 85 if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
86 dev_err(&chip->pci_dev->dev, 86 dev_err(chip->dev,
87 "error reading data\n"); 87 "error reading data\n");
88 return -EIO; 88 return -EIO;
89 } 89 }
@@ -93,20 +93,20 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
93 /* make sure data available is gone */ 93 /* make sure data available is gone */
94 status = inb(chip->vendor->base + 1); 94 status = inb(chip->vendor->base + 1);
95 if (status & ATML_STATUS_DATA_AVAIL) { 95 if (status & ATML_STATUS_DATA_AVAIL) {
96 dev_err(&chip->pci_dev->dev, "data available is stuck\n"); 96 dev_err(chip->dev, "data available is stuck\n");
97 return -EIO; 97 return -EIO;
98 } 98 }
99 99
100 return size; 100 return size;
101} 101}
102 102
103static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count) 103static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
104{ 104{
105 int i; 105 int i;
106 106
107 dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: "); 107 dev_dbg(chip->dev, "tpm_atml_send:\n");
108 for (i = 0; i < count; i++) { 108 for (i = 0; i < count; i++) {
109 dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]); 109 dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
110 outb(buf[i], chip->vendor->base); 110 outb(buf[i], chip->vendor->base);
111 } 111 }
112 112
@@ -118,6 +118,11 @@ static void tpm_atml_cancel(struct tpm_chip *chip)
118 outb(ATML_STATUS_ABORT, chip->vendor->base + 1); 118 outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
119} 119}
120 120
121static u8 tpm_atml_status(struct tpm_chip *chip)
122{
123 return inb(chip->vendor->base + 1);
124}
125
121static struct file_operations atmel_ops = { 126static struct file_operations atmel_ops = {
122 .owner = THIS_MODULE, 127 .owner = THIS_MODULE,
123 .llseek = no_llseek, 128 .llseek = no_llseek,
@@ -137,7 +142,7 @@ static struct attribute* atmel_attrs[] = {
137 &dev_attr_pcrs.attr, 142 &dev_attr_pcrs.attr,
138 &dev_attr_caps.attr, 143 &dev_attr_caps.attr,
139 &dev_attr_cancel.attr, 144 &dev_attr_cancel.attr,
140 0, 145 NULL,
141}; 146};
142 147
143static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; 148static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
@@ -146,6 +151,7 @@ static struct tpm_vendor_specific tpm_atmel = {
146 .recv = tpm_atml_recv, 151 .recv = tpm_atml_recv,
147 .send = tpm_atml_send, 152 .send = tpm_atml_send,
148 .cancel = tpm_atml_cancel, 153 .cancel = tpm_atml_cancel,
154 .status = tpm_atml_status,
149 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, 155 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
150 .req_complete_val = ATML_STATUS_DATA_AVAIL, 156 .req_complete_val = ATML_STATUS_DATA_AVAIL,
151 .req_canceled = ATML_STATUS_READY, 157 .req_canceled = ATML_STATUS_READY,
@@ -153,86 +159,94 @@ static struct tpm_vendor_specific tpm_atmel = {
153 .miscdev = { .fops = &atmel_ops, }, 159 .miscdev = { .fops = &atmel_ops, },
154}; 160};
155 161
156static int __devinit tpm_atml_init(struct pci_dev *pci_dev, 162static struct platform_device *pdev;
157 const struct pci_device_id *pci_id) 163
164static void __devexit tpm_atml_remove(struct device *dev)
165{
166 struct tpm_chip *chip = dev_get_drvdata(dev);
167 if (chip) {
168 release_region(chip->vendor->base, 2);
169 tpm_remove_hardware(chip->dev);
170 }
171}
172
173static struct device_driver atml_drv = {
174 .name = "tpm_atmel",
175 .bus = &platform_bus_type,
176 .owner = THIS_MODULE,
177 .suspend = tpm_pm_suspend,
178 .resume = tpm_pm_resume,
179};
180
181static int __init init_atmel(void)
158{ 182{
159 u8 version[4];
160 int rc = 0; 183 int rc = 0;
161 int lo, hi; 184 int lo, hi;
162 185
163 if (pci_enable_device(pci_dev)) 186 driver_register(&atml_drv);
164 return -EIO;
165 187
166 lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); 188 lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
167 hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); 189 hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
168 190
169 tpm_atmel.base = (hi<<8)|lo; 191 tpm_atmel.base = (hi<<8)|lo;
170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
171 192
172 /* verify that it is an Atmel part */ 193 /* verify that it is an Atmel part */
173 if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T' 194 if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
174 || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') { 195 || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
175 rc = -ENODEV; 196 return -ENODEV;
176 goto out_err;
177 } 197 }
178 198
179 /* query chip for its version number */ 199 /* verify chip version number is 1.1 */
180 if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) { 200 if ( (tpm_read_index(TPM_ADDR, 0x00) != 0x01) ||
181 version[1] = tpm_read_index(TPM_ADDR, 0x01); 201 (tpm_read_index(TPM_ADDR, 0x01) != 0x01 ))
182 version[2] = tpm_read_index(TPM_ADDR, 0x02); 202 return -ENODEV;
183 version[3] = tpm_read_index(TPM_ADDR, 0x03); 203
184 } else { 204 pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
185 dev_info(&pci_dev->dev, "version query failed\n"); 205 if ( !pdev )
186 rc = -ENODEV; 206 return -ENOMEM;
187 goto out_err; 207
208 pdev->name = "tpm_atmel0";
209 pdev->id = -1;
210 pdev->num_resources = 0;
211 pdev->dev.release = tpm_atml_remove;
212 pdev->dev.driver = &atml_drv;
213
214 if ((rc = platform_device_register(pdev)) < 0) {
215 kfree(pdev);
216 pdev = NULL;
217 return rc;
188 } 218 }
189 219
190 if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0) 220 if (request_region(tpm_atmel.base, 2, "tpm_atmel0") == NULL ) {
191 goto out_err; 221 platform_device_unregister(pdev);
222 kfree(pdev);
223 pdev = NULL;
224 return -EBUSY;
225 }
192 226
193 dev_info(&pci_dev->dev, 227 if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) {
194 "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1], 228 release_region(tpm_atmel.base, 2);
195 version[2], version[3]); 229 platform_device_unregister(pdev);
230 kfree(pdev);
231 pdev = NULL;
232 return rc;
233 }
196 234
235 dev_info(&pdev->dev, "Atmel TPM 1.1, Base Address: 0x%x\n",
236 tpm_atmel.base);
197 return 0; 237 return 0;
198out_err:
199 pci_disable_device(pci_dev);
200 return rc;
201}
202
203static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
204 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
205 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
206 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
207 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
208 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
209 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
210 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
211 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
212 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
213 {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
214 {0,}
215};
216
217MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
218
219static struct pci_driver atmel_pci_driver = {
220 .name = "tpm_atmel",
221 .id_table = tpm_pci_tbl,
222 .probe = tpm_atml_init,
223 .remove = __devexit_p(tpm_remove),
224 .suspend = tpm_pm_suspend,
225 .resume = tpm_pm_resume,
226};
227
228static int __init init_atmel(void)
229{
230 return pci_register_driver(&atmel_pci_driver);
231} 238}
232 239
233static void __exit cleanup_atmel(void) 240static void __exit cleanup_atmel(void)
234{ 241{
235 pci_unregister_driver(&atmel_pci_driver); 242 if (pdev) {
243 tpm_atml_remove(&pdev->dev);
244 platform_device_unregister(pdev);
245 kfree(pdev);
246 pdev = NULL;
247 }
248
249 driver_unregister(&atml_drv);
236} 250}
237 251
238module_init(init_atmel); 252module_init(init_atmel);