tpm_tis.c
来自「linux 内核源代码」· C语言 代码 · 共 711 行 · 第 1/2 页
C
711 行
&dev_attr_enabled.attr, &dev_attr_active.attr, &dev_attr_owned.attr, &dev_attr_temp_deactivated.attr, &dev_attr_caps.attr, &dev_attr_cancel.attr, NULL,};static struct attribute_group tis_attr_grp = { .attrs = tis_attrs};static struct tpm_vendor_specific tpm_tis = { .status = tpm_tis_status, .recv = tpm_tis_recv, .send = tpm_tis_send, .cancel = tpm_tis_ready, .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, .req_canceled = TPM_STS_COMMAND_READY, .attr_group = &tis_attr_grp, .miscdev = { .fops = &tis_ops,},};static irqreturn_t tis_int_probe(int irq, void *dev_id){ struct tpm_chip *chip = dev_id; u32 interrupt; interrupt = ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); if (interrupt == 0) return IRQ_NONE; chip->vendor.irq = irq; /* Clear interrupts handled with TPM_EOI */ iowrite32(interrupt, chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); return IRQ_HANDLED;}static irqreturn_t tis_int_handler(int irq, void *dev_id){ struct tpm_chip *chip = dev_id; u32 interrupt; int i; interrupt = ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); if (interrupt == 0) return IRQ_NONE; if (interrupt & TPM_INTF_DATA_AVAIL_INT) wake_up_interruptible(&chip->vendor.read_queue); if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) for (i = 0; i < 5; i++) if (check_locality(chip, i) >= 0) break; if (interrupt & (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | TPM_INTF_CMD_READY_INT)) wake_up_interruptible(&chip->vendor.int_queue); /* Clear interrupts handled with TPM_EOI */ iowrite32(interrupt, chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); return IRQ_HANDLED;}static int interrupts = 1;module_param(interrupts, bool, 0444);MODULE_PARM_DESC(interrupts, "Enable interrupts");static int tpm_tis_init(struct device *dev, resource_size_t start, resource_size_t len, unsigned int irq){ u32 vendor, intfcaps, intmask; int rc, i; struct tpm_chip *chip; if (!(chip = tpm_register_hardware(dev, &tpm_tis))) return -ENODEV; chip->vendor.iobase = ioremap(start, len); if (!chip->vendor.iobase) { rc = -EIO; goto out_err; } if (request_locality(chip, 0) != 0) { rc = -ENODEV; goto out_err; } vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); /* Default timeouts */ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); dev_info(dev, "1.2 TPM (device-id 0x%X, rev-id %d)\n", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); /* Figure out the capabilities */ intfcaps = ioread32(chip->vendor.iobase + TPM_INTF_CAPS(chip->vendor.locality)); dev_dbg(dev, "TPM interface capabilities (0x%x):\n", intfcaps); if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) dev_dbg(dev, "\tBurst Count Static\n"); if (intfcaps & TPM_INTF_CMD_READY_INT) dev_dbg(dev, "\tCommand Ready Int Support\n"); if (intfcaps & TPM_INTF_INT_EDGE_FALLING) dev_dbg(dev, "\tInterrupt Edge Falling\n"); if (intfcaps & TPM_INTF_INT_EDGE_RISING) dev_dbg(dev, "\tInterrupt Edge Rising\n"); if (intfcaps & TPM_INTF_INT_LEVEL_LOW) dev_dbg(dev, "\tInterrupt Level Low\n"); if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) dev_dbg(dev, "\tInterrupt Level High\n"); if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) dev_dbg(dev, "\tLocality Change Int Support\n"); if (intfcaps & TPM_INTF_STS_VALID_INT) dev_dbg(dev, "\tSts Valid Int Support\n"); if (intfcaps & TPM_INTF_DATA_AVAIL_INT) dev_dbg(dev, "\tData Avail Int Support\n"); /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); intmask = ioread32(chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; iowrite32(intmask, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); if (interrupts) chip->vendor.irq = irq; if (interrupts && !chip->vendor.irq) { chip->vendor.irq = ioread8(chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { iowrite8(i, chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); if (request_irq (i, tis_int_probe, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { dev_info(chip->dev, "Unable to request irq: %d for probe\n", i); continue; } /* Clear all existing */ iowrite32(ioread32 (chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)), chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); /* Turn on */ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); /* Generate Interrupts */ tpm_gen_interrupt(chip); /* Turn off */ iowrite32(intmask, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); free_irq(i, chip); } } if (chip->vendor.irq) { iowrite8(chip->vendor.irq, chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); if (request_irq (chip->vendor.irq, tis_int_handler, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { dev_info(chip->dev, "Unable to request irq: %d for use\n", chip->vendor.irq); chip->vendor.irq = 0; } else { /* Clear all existing */ iowrite32(ioread32 (chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)), chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality)); /* Turn on */ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); } } INIT_LIST_HEAD(&chip->vendor.list); spin_lock(&tis_lock); list_add(&chip->vendor.list, &tis_chips); spin_unlock(&tis_lock); tpm_get_timeouts(chip); tpm_continue_selftest(chip); return 0;out_err: if (chip->vendor.iobase) iounmap(chip->vendor.iobase); tpm_remove_hardware(chip->dev); return rc;}static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, const struct pnp_device_id *pnp_id){ resource_size_t start, len; unsigned int irq = 0; start = pnp_mem_start(pnp_dev, 0); len = pnp_mem_len(pnp_dev, 0); if (pnp_irq_valid(pnp_dev, 0)) irq = pnp_irq(pnp_dev, 0); else interrupts = 0; return tpm_tis_init(&pnp_dev->dev, start, len, irq);}static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg){ return tpm_pm_suspend(&dev->dev, msg);}static int tpm_tis_pnp_resume(struct pnp_dev *dev){ return tpm_pm_resume(&dev->dev);}static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"PNP0C31", 0}, /* TPM */ {"ATM1200", 0}, /* Atmel */ {"IFX0102", 0}, /* Infineon */ {"BCM0101", 0}, /* Broadcom */ {"NSC1200", 0}, /* National */ /* Add new here */ {"", 0}, /* User Specified */ {"", 0} /* Terminator */};static struct pnp_driver tis_pnp_driver = { .name = "tpm_tis", .id_table = tpm_pnp_tbl, .probe = tpm_tis_pnp_init, .suspend = tpm_tis_pnp_suspend, .resume = tpm_tis_pnp_resume,};#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");static struct device_driver tis_drv = { .name = "tpm_tis", .bus = &platform_bus_type, .owner = THIS_MODULE, .suspend = tpm_pm_suspend, .resume = tpm_pm_resume,};static struct platform_device *pdev;static int force;module_param(force, bool, 0444);MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");static int __init init_tis(void){ int rc; if (force) { rc = driver_register(&tis_drv); if (rc < 0) return rc; if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) return PTR_ERR(pdev); if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { platform_device_unregister(pdev); driver_unregister(&tis_drv); } return rc; } return pnp_register_driver(&tis_pnp_driver);}static void __exit cleanup_tis(void){ struct tpm_vendor_specific *i, *j; struct tpm_chip *chip; spin_lock(&tis_lock); list_for_each_entry_safe(i, j, &tis_chips, list) { chip = to_tpm_chip(i); iowrite32(~TPM_GLOBAL_INT_ENABLE & ioread32(chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor. locality)), chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); release_locality(chip, chip->vendor.locality, 1); if (chip->vendor.irq) free_irq(chip->vendor.irq, chip); iounmap(i->iobase); list_del(&i->list); tpm_remove_hardware(chip->dev); } spin_unlock(&tis_lock); if (force) { platform_device_unregister(pdev); driver_unregister(&tis_drv); } else pnp_unregister_driver(&tis_pnp_driver);}module_init(init_tis);module_exit(cleanup_tis);MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");MODULE_DESCRIPTION("TPM Driver");MODULE_VERSION("2.0");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?